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 items_on_ground
= new Array[Entity]
32 var entities
= new Array[Entity].with_items
(dino
)
37 var score
: Container[Int]
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
: Container[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
142 init copy
( src
: GamePos )
148 fun squared_dist_with
( other
: GamePos ) : Int
156 redef fun to_s
do return "<{x}|{y}>"
162 fun run_over_distance
: Int do return 500
163 var pos
= new GamePos( 0, 0 )
165 fun squared_dist_with_dino
( game
: Game ) : Int
167 return pos
.squared_dist_with
( game
.dino
.pos
)
174 var going_to
: nullable GamePos writable = null
176 fun speed
: Int is abstract
178 var going_left
= false
179 var going_right
= false
181 redef fun do_turn
( t
)
183 if going_to
!= null then
184 var ds
= pos
.squared_dist_with
( going_to
.as(not null) )
185 if ds
< speed
*speed
then
186 going_to
= null # is there
188 var dx
= going_to
.x
- pos
.x
189 var dy
= going_to
.y
- pos
.y
190 var a
= atan2
( dy
.to_f
, dx
.to_f
)
191 var mx
= a
.cos
*speed
.to_f
192 var my
= a
.sin
*speed
.to_f
197 going_left
= mx
< 0.0
198 going_right
= mx
> 0.0
207 fun is_alive
: Bool is abstract
214 #var running_until = 0
216 var life
: Int = total_life
218 redef fun speed
do return 8
220 redef fun is_alive
do return life
> 0
222 fun hit
( hitter
: Entity, damage
: Int )
229 redef fun do_turn
( t
)
235 for i
in t
.game
.items_on_ground
do
236 var dwd
= i
.squared_dist_with_dino
(t
.game
)
237 if dwd
< i
.run_over_distance
then
238 t
.game
.items_on_ground
.remove i
239 t
.game
.entities
.remove i
250 var cannot_throw_until
= 0
252 var throw_distance
: Int = 400*40+10.rand
253 var fear_distance
: Int = 300*20+8.rand
254 var flee_distance
: Int = 600*60+16.rand
256 var fear_duration
: Int = 80+40.rand
257 var throw_period
: Int = 40+8.rand
259 var variance_angle
: Float = 2.0*pi
.rand
260 var variance_dist
: Int = throw_distance
.to_f
.sqrt
.to_i-4
261 var variance_x
: Int = (variance_angle
.cos
*variance_dist
.to_f
).to_i
262 var variance_y
: Int = (variance_angle
.sin
*variance_dist
.to_f
).to_i
264 redef var is_alive
: Bool = true
266 redef var speed
: Int = 3+3.rand
268 fun is_afraid
( turn
: Turn ) : Bool do return turn
.nbr
< afraid_until
269 fun can_throw
( turn
: Turn ) : Bool do return cannot_throw_until
< turn
.nbr
271 redef fun do_turn
( t
)
274 var dwd
= squared_dist_with_dino
( t
.game
)
276 if dwd
< run_over_distance
then
277 if t
.game
.dino
.is_alive
then is_alive
= false
279 else if is_afraid
( t
) then
280 # going to destination
281 else if t
.game
.dino
.life
<= 0 then
282 # dino is dead, chill
284 if dwd
< fear_distance
then
285 afraid_until
= t
.nbr
+ fear_duration
287 var dino_pos
= t
.game
.dino
.pos
288 var dx
= dino_pos
.x
- pos
.x
289 var dy
= dino_pos
.y
- pos
.y
290 var a
= atan2
( dy
.to_f
, dx
.to_f
)
291 a
+= pi
# get opposite
292 a
+= [-100..100[.rand
.to_f
*pi
/3.0/100.0
293 var x
= a
.cos
*flee_distance
.to_f
294 var y
= a
.sin
*flee_distance
.to_f
295 going_to
= new GamePos( x
.to_i
, y
.to_i
)
296 else if dwd
< throw_distance
then
297 if can_throw
( t
) then
298 cannot_throw_until
= t
.nbr
+ throw_period
299 var javelin
= new Javelin( pos
, t
.game
.dino
.pos
)
300 t
.game
.add_javelin
( javelin
)
305 var dino_pos
= t
.game
.dino
.pos
306 going_to
= new GamePos(dino_pos
.x
+variance_x
, dino_pos
.y
+variance_y
)
319 var angle
: Float = pi
/2.0
321 var thrown_angle_xy
: Float
325 var hit_ground
= false
328 var speed
: Int = 10+2.rand
329 var hit_dino_distance
= 128
331 var gravity
: Int = -3
333 init ( from
: GamePos, to
: GamePos )
337 thrown_angle_xy
= atan2
( dy
.to_f
, dx
.to_f
)
338 pos
= new GamePos.copy
( from
)
341 redef fun do_turn
( t
)
343 var dwd
= squared_dist_with_dino
( t
.game
)
344 if dwd
< hit_dino_distance
and t
.game
.dino
.is_alive
then
345 t
.game
.dino
.hit
( self, hit_damage
)
350 if thrown_angle_xy
.cos
> 0.0 then
351 angle
= pi
*5.0/8.0+(pi
/4.0).rand
354 angle
= pi
*9.0/8.0+(pi
/4.0).rand
361 var mx
= (thrown_angle_xy
.cos
* speed
.to_f
).to_i
363 pos
.y
+= (thrown_angle_xy
.sin
* speed
.to_f
).to_i
366 angle
= atan2
( (speed_z
/10).to_f
, -1.0*speed
.to_f
)-pi
/2.0
368 angle
= atan2
( (speed_z
/10).to_f
, speed
.to_f
)-pi
/2.0
375 class Bush super Entity end
377 # Sort entities on screen in order of Y, entities in the back are drawn first
379 super AbstractSorter[Entity]
381 redef fun compare
(a
, b
) do return b
.pos
.y
<=> a
.pos
.y