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 standard 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 javelins_on_ground
= new Array[Javelin]
32 var entities
= new Array[Entity].with_items
(dino
)
37 var random_radius_min
= 200
38 var random_radius_max
= 400
39 protected var random_radius_diff
: Int =
40 random_radius_max
- random_radius_min
42 var entities_sorter
= new EntitiesSorter
44 init( cavemen_nbr
: Int )
48 nbr_wanted_cavemen
= cavemen_nbr
50 for n
in [0..nbr_wanted_cavemen
[ do
55 var radius
= (random_radius_min
+ random_radius_diff
.rand
).to_f
56 var angle
= (2.0*pi
).rand
57 man
.pos
.x
= ( angle
.cos
* radius
).to_i
58 man
.pos
.y
= ( angle
.sin
* radius
).to_i
65 var turn
= new Turn( self )
70 if not man
.is_alive
then
75 for j
in javelins_in_air
do
78 javelins_in_air
.remove
( j
)
80 else if j
.hit_ground
then
81 javelins_in_air
.remove
( j
)
82 javelins_on_ground
.add
( j
)
86 if over
and over_since
== 0 then
90 # sort for blitting, firsts and in the back
91 entities_sorter
.sort entities
96 fun add_javelin
( j
: Javelin )
98 javelins_in_air
.add
( j
)
102 fun over
: Bool do return dino
.life
<= 0 or cavemen
.is_empty
103 fun won
: Bool do return cavemen
.is_empty
and dino
.is_alive
104 fun lost
: Bool do return not won
106 fun ready_to_start_over
: Bool do return over_since
+ 80 < turn_nbr
130 init copy
( src
: GamePos )
136 fun squared_dist_with
( other
: GamePos ) : Int
144 redef fun to_s
do return "<{x}|{y}>"
150 var pos
= new GamePos( 0, 0 )
152 fun squared_dist_with_dino
( game
: Game ) : Int
154 return pos
.squared_dist_with
( game
.dino
.pos
)
161 var going_to
: nullable GamePos writable = null
163 fun speed
: Int is abstract
165 var going_left
= false
166 var going_right
= false
168 redef fun do_turn
( t
)
170 if going_to
!= null then
171 var ds
= pos
.squared_dist_with
( going_to
.as(not null) )
172 if ds
< speed
*speed
then
173 going_to
= null # is there
175 var dx
= going_to
.x
- pos
.x
176 var dy
= going_to
.y
- pos
.y
177 var a
= atan2
( dy
.to_f
, dx
.to_f
)
178 var mx
= a
.cos
*speed
.to_f
179 var my
= a
.sin
*speed
.to_f
184 going_left
= mx
< 0.0
185 going_right
= mx
> 0.0
194 fun is_alive
: Bool is abstract
201 #var running_until = 0
203 var life
: Int = total_life
205 redef fun speed
do return 8
207 redef fun is_alive
do return life
> 0
209 fun hit
( hitter
: Entity, damage
: Int )
216 redef fun do_turn
( t
)
229 var cannot_throw_until
= 0
231 var throw_distance
: Int = 400*40+10.rand
232 var fear_distance
: Int = 300*20+8.rand
233 var flee_distance
: Int = 600*60+16.rand
234 var run_over_distance
= 500
236 var fear_duration
: Int = 80+40.rand
237 var throw_period
: Int = 40+8.rand
239 var variance_angle
: Float = 2.0*pi
.rand
240 var variance_dist
: Int = throw_distance
.to_f
.sqrt
.to_i-4
241 var variance_x
: Int = (variance_angle
.cos
*variance_dist
.to_f
).to_i
242 var variance_y
: Int = (variance_angle
.sin
*variance_dist
.to_f
).to_i
244 redef var is_alive
: Bool = true
246 redef var speed
: Int = 3+3.rand
248 fun is_afraid
( turn
: Turn ) : Bool do return turn
.nbr
< afraid_until
249 fun can_throw
( turn
: Turn ) : Bool do return cannot_throw_until
< turn
.nbr
251 redef fun do_turn
( t
)
254 var dwd
= squared_dist_with_dino
( t
.game
)
256 if dwd
< run_over_distance
then
257 if t
.game
.dino
.is_alive
then is_alive
= false
259 else if is_afraid
( t
) then
260 # going to destination
261 else if t
.game
.dino
.life
<= 0 then
262 # dino is dead, chill
264 if dwd
< fear_distance
then
265 afraid_until
= t
.nbr
+ fear_duration
267 var dino_pos
= t
.game
.dino
.pos
268 var dx
= dino_pos
.x
- pos
.x
269 var dy
= dino_pos
.y
- pos
.y
270 var a
= atan2
( dy
.to_f
, dx
.to_f
)
271 a
+= pi
# get opposite
272 a
+= [-100..100[.rand
.to_f
*pi
/3.0/100.0
273 var x
= a
.cos
*flee_distance
.to_f
274 var y
= a
.sin
*flee_distance
.to_f
275 going_to
= new GamePos( x
.to_i
, y
.to_i
)
276 else if dwd
< throw_distance
then
277 if can_throw
( t
) then
278 cannot_throw_until
= t
.nbr
+ throw_period
279 var javelin
= new Javelin( pos
, t
.game
.dino
.pos
)
280 t
.game
.add_javelin
( javelin
)
285 var dino_pos
= t
.game
.dino
.pos
286 going_to
= new GamePos(dino_pos
.x
+variance_x
, dino_pos
.y
+variance_y
)
299 var angle
: Float = pi
/2.0
301 var thrown_angle_xy
: Float
305 var hit_ground
= false
308 var speed
: Int = 10+2.rand
309 var hit_dino_distance
= 128
311 var gravity
: Int = -3
313 init ( from
: GamePos, to
: GamePos )
317 thrown_angle_xy
= atan2
( dy
.to_f
, dx
.to_f
)
318 pos
= new GamePos.copy
( from
)
321 redef fun do_turn
( t
)
323 var dwd
= squared_dist_with_dino
( t
.game
)
324 if dwd
< hit_dino_distance
and t
.game
.dino
.is_alive
then
325 t
.game
.dino
.hit
( self, hit_damage
)
335 var mx
= (thrown_angle_xy
.cos
* speed
.to_f
).to_i
337 pos
.y
+= (thrown_angle_xy
.sin
* speed
.to_f
).to_i
340 angle
= atan2
( (speed_z
/10).to_f
, -1.0*speed
.to_f
)-pi
/2.0
342 angle
= atan2
( (speed_z
/10).to_f
, speed
.to_f
)-pi
/2.0
349 # Sort entities on screen in order of Y, entities in the back are drawn first
351 super AbstractSorter[Entity]
353 redef fun compare
(a
, b
) do return b
.pos
.y
<=> a
.pos
.y