1 # This file is part of NIT ( http://www.nitlanguage.org ).
3 # Copyright 2012-2013 Alexis Laferrière <alexis.laf@xymus.net>
5 # Licensed under the Apache License, Version 2.0 (the "License");
6 # you may not use this file except in compliance with the License.
7 # You may obtain a copy of the License at
9 # http://www.apache.org/licenses/LICENSE-2.0
11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
17 # Entire game logic for the Dino game
18 # Depends only on Nit `core` library
22 fun do_turn
( turn
: Turn ) is abstract
26 var nbr_wanted_cavemen
: Int
29 var cavemen
= new Array[Caveman]
30 var javelins_in_air
= new Array[Javelin]
31 var items_on_ground
= new Array[Entity]
32 var entities
= new Array[Entity].with_items
(dino
)
39 var random_radius_min
= 200
40 var random_radius_max
= 400
41 protected var random_radius_diff
: Int =
42 random_radius_max
- random_radius_min
44 var entities_sorter
= new EntitiesSorter
46 init( cavemen_nbr
: Int, score
: Ref[Int] )
48 srand_from
(cavemen_nbr
)
52 nbr_wanted_cavemen
= cavemen_nbr
54 for n
in [0..nbr_wanted_cavemen
[ do
59 var radius
= (random_radius_min
+ random_radius_diff
.rand
).to_f
60 var angle
= (2.0*pi
).rand
61 man
.pos
.x
= ( angle
.cos
* radius
).to_i
62 man
.pos
.y
= ( angle
.sin
* radius
).to_i
67 bush
.pos
= new GamePos([-300..300[.rand
, [-400..400[.rand
)
68 items_on_ground
.add bush
76 var turn
= new Turn( self )
81 if not man
.is_alive
then
87 for j
in javelins_in_air
do
90 javelins_in_air
.remove
( j
)
92 else if j
.hit_ground
then
93 javelins_in_air
.remove
( j
)
94 items_on_ground
.add
( j
)
98 if over
and over_since
== 0 then
102 # sort for blitting, firsts and in the back
103 entities_sorter
.sort entities
108 fun add_javelin
( j
: Javelin )
110 javelins_in_air
.add
( j
)
114 fun over
: Bool do return dino
.life
<= 0 or cavemen
.is_empty
115 fun won
: Bool do return cavemen
.is_empty
and dino
.is_alive
116 fun lost
: Bool do return not won
118 fun ready_to_start_over
: Bool do return over_since
+ 80 < turn_nbr
136 init copy
( src
: GamePos )
141 fun squared_dist_with
( other
: GamePos ) : Int
149 redef fun to_s
do return "<{x}|{y}>"
155 fun run_over_distance_x
: Int do return 50
156 fun run_over_distance_y
: Int do return 16
158 var pos
= new GamePos( 0, 0 )
160 fun squared_dist_with_dino
( game
: Game ) : Int
162 return pos
.squared_dist_with
( game
.dino
.pos
)
165 fun under_dino
(game
: Game): Bool
167 var dy
= pos
.y
- game
.dino
.pos
.y
168 if dy
.abs
> run_over_distance_y
then return false
170 var dx
= pos
.x
- game
.dino
.pos
.x
171 return dx
.abs
<= run_over_distance_x
178 var going_to
: nullable GamePos = null is writable
180 fun speed
: Int is abstract
182 var going_left
= false
183 var going_right
= false
185 redef fun do_turn
( t
)
187 if going_to
!= null then
188 var ds
= pos
.squared_dist_with
( going_to
.as(not null) )
189 if ds
< speed
*speed
then
190 going_to
= null # is there
192 var dx
= going_to
.x
- pos
.x
193 var dy
= going_to
.y
- pos
.y
194 var a
= atan2
( dy
.to_f
, dx
.to_f
)
195 var mx
= a
.cos
*speed
.to_f
196 var my
= a
.sin
*speed
.to_f
201 going_left
= mx
< 0.0
202 going_right
= mx
> 0.0
211 fun is_alive
: Bool is abstract
218 #var running_until = 0
220 var life
: Int = total_life
222 redef fun speed
do return 8
224 redef fun is_alive
do return life
> 0
226 fun hit
( hitter
: Entity, damage
: Int )
233 redef fun do_turn
( t
)
239 for i
in t
.game
.items_on_ground
do
240 if i
.under_dino
(t
.game
) then
241 t
.game
.items_on_ground
.remove i
242 t
.game
.entities
.remove i
253 var cannot_throw_until
= 0
255 var throw_distance
: Int = 400*40+10.rand
256 var fear_distance
: Int = 300*20+8.rand
257 var flee_distance
: Int = 600*60+16.rand
259 var fear_duration
: Int = 80+40.rand
260 var throw_period
: Int = 40+8.rand
262 var variance_angle
: Float = 2.0*pi
.rand
263 var variance_dist
: Int = throw_distance
.to_f
.sqrt
.to_i-4
264 var variance_x
: Int = (variance_angle
.cos
*variance_dist
.to_f
).to_i
265 var variance_y
: Int = (variance_angle
.sin
*variance_dist
.to_f
).to_i
267 redef var is_alive
: Bool = true
269 redef var speed
: Int = 3+3.rand
271 fun is_afraid
( turn
: Turn ) : Bool do return turn
.nbr
< afraid_until
272 fun can_throw
( turn
: Turn ) : Bool do return cannot_throw_until
< turn
.nbr
273 fun die
(turn
: Turn) do is_alive
= false
275 redef fun do_turn
( t
)
278 if under_dino
(t
.game
) then
279 if t
.game
.dino
.is_alive
then die
(t
)
281 else if is_afraid
( t
) then
282 # going to destination
283 else if t
.game
.dino
.life
<= 0 then
284 # dino is dead, chill
286 var dwd
= squared_dist_with_dino
( t
.game
)
287 if dwd
< fear_distance
then
288 afraid_until
= t
.nbr
+ fear_duration
290 var dino_pos
= t
.game
.dino
.pos
291 var dx
= dino_pos
.x
- pos
.x
292 var dy
= dino_pos
.y
- pos
.y
293 var a
= atan2
( dy
.to_f
, dx
.to_f
)
294 a
+= pi
# get opposite
295 a
+= [-100..100[.rand
.to_f
*pi
/3.0/100.0
296 var x
= a
.cos
*flee_distance
.to_f
297 var y
= a
.sin
*flee_distance
.to_f
298 going_to
= new GamePos( x
.to_i
, y
.to_i
)
299 else if dwd
< throw_distance
then
300 if can_throw
( t
) then
301 cannot_throw_until
= t
.nbr
+ throw_period
302 var javelin
= new Javelin( pos
, t
.game
.dino
.pos
)
303 t
.game
.add_javelin
( javelin
)
308 var dino_pos
= t
.game
.dino
.pos
309 going_to
= new GamePos(dino_pos
.x
+variance_x
, dino_pos
.y
+variance_y
)
322 var angle
: Float = pi
/2.0
324 var thrown_angle_xy
: Float
328 var hit_ground
= false
331 var speed
: Int = 10+2.rand
332 var hit_dino_distance
= 128
334 var gravity
: Int = -3
336 init ( from
: GamePos, to
: GamePos )
340 thrown_angle_xy
= atan2
( dy
.to_f
, dx
.to_f
)
341 pos
= new GamePos.copy
( from
)
344 redef fun do_turn
( t
)
346 var dwd
= squared_dist_with_dino
( t
.game
)
347 if dwd
< hit_dino_distance
and t
.game
.dino
.is_alive
then
348 t
.game
.dino
.hit
( self, hit_damage
)
353 if thrown_angle_xy
.cos
> 0.0 then
354 angle
= pi
*5.0/8.0+(pi
/4.0).rand
357 angle
= pi
*9.0/8.0+(pi
/4.0).rand
364 var mx
= (thrown_angle_xy
.cos
* speed
.to_f
).to_i
366 pos
.y
+= (thrown_angle_xy
.sin
* speed
.to_f
).to_i
369 angle
= atan2
( (speed_z
/10).to_f
, -1.0*speed
.to_f
)-pi
/2.0
371 angle
= atan2
( (speed_z
/10).to_f
, speed
.to_f
)-pi
/2.0
378 class Bush super Entity end
380 # Sort entities on screen in order of Y, entities in the back are drawn first
383 redef type COMPARED: Entity
385 redef fun compare
(a
, b
) do return b
.pos
.y
<=> a
.pos
.y