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 init( cavemen_nbr
: Int )
46 nbr_wanted_cavemen
= cavemen_nbr
48 for n
in [0..nbr_wanted_cavemen
[ do
53 var radius
= (random_radius_min
+ random_radius_diff
.rand
).to_f
54 var angle
= (2.0*pi
).rand
55 man
.pos
.x
= ( angle
.cos
* radius
).to_i
56 man
.pos
.y
= ( angle
.sin
* radius
).to_i
63 var turn
= new Turn( self )
68 if not man
.is_alive
then
73 for j
in javelins_in_air
do
76 javelins_in_air
.remove
( j
)
78 else if j
.hit_ground
then
79 javelins_in_air
.remove
( j
)
80 javelins_on_ground
.add
( j
)
84 if over
and over_since
== 0 then
88 # sort for blitting, firsts and in the back
89 # FIXME: remove closure
90 entities
.sort
!cmp
( a
, b
) = b
.pos
.y
<=> a
.pos
.y
95 fun add_javelin
( j
: Javelin )
97 javelins_in_air
.add
( j
)
101 fun over
: Bool do return dino
.life
<= 0 or cavemen
.is_empty
102 fun won
: Bool do return cavemen
.is_empty
and dino
.is_alive
103 fun lost
: Bool do return not won
105 fun ready_to_start_over
: Bool do return over_since
+ 80 < turn_nbr
129 init copy
( src
: GamePos )
135 fun squared_dist_with
( other
: GamePos ) : Int
143 redef fun to_s
do return "<{x}|{y}>"
149 var pos
= new GamePos( 0, 0 )
151 fun squared_dist_with_dino
( game
: Game ) : Int
153 return pos
.squared_dist_with
( game
.dino
.pos
)
160 var going_to
: nullable GamePos writable = null
162 fun speed
: Int is abstract
164 var going_left
= false
165 var going_right
= false
167 redef fun do_turn
( t
)
169 if going_to
!= null then
170 var ds
= pos
.squared_dist_with
( going_to
.as(not null) )
171 if ds
< speed
*speed
then
172 going_to
= null # is there
174 var dx
= going_to
.x
- pos
.x
175 var dy
= going_to
.y
- pos
.y
176 var a
= atan2
( dy
.to_f
, dx
.to_f
)
177 var mx
= a
.cos
*speed
.to_f
178 var my
= a
.sin
*speed
.to_f
183 going_left
= mx
< 0.0
184 going_right
= mx
> 0.0
193 fun is_alive
: Bool is abstract
200 #var running_until = 0
202 var life
: Int = total_life
204 redef fun speed
do return 8
206 redef fun is_alive
do return life
> 0
208 fun hit
( hitter
: Entity, damage
: Int )
215 redef fun do_turn
( t
)
228 var cannot_throw_until
= 0
230 var throw_distance
: Int = 400*40+10.rand
231 var fear_distance
: Int = 300*20+8.rand
232 var flee_distance
: Int = 600*60+16.rand
233 var run_over_distance
= 500
235 var fear_duration
: Int = 80+40.rand
236 var throw_period
: Int = 40+8.rand
238 redef var is_alive
: Bool = true
240 redef fun speed
do return 4
242 fun is_afraid
( turn
: Turn ) : Bool do return turn
.nbr
< afraid_until
243 fun can_throw
( turn
: Turn ) : Bool do return cannot_throw_until
< turn
.nbr
245 redef fun do_turn
( t
)
248 var dwd
= squared_dist_with_dino
( t
.game
)
250 if dwd
< run_over_distance
then
253 else if is_afraid
( t
) then
254 # going to destination
255 else if t
.game
.dino
.life
<= 0 then
256 # dino is dead, chill
258 if dwd
< fear_distance
then
259 afraid_until
= t
.nbr
+ fear_duration
261 var dino_pos
= t
.game
.dino
.pos
262 var dx
= dino_pos
.x
- pos
.x
263 var dy
= dino_pos
.y
- pos
.y
264 var a
= atan2
( dy
.to_f
, dx
.to_f
)
265 a
+= pi
# get opposite
266 var x
= a
.cos
*flee_distance
.to_f
267 var y
= a
.sin
*flee_distance
.to_f
268 going_to
= new GamePos( x
.to_i
, y
.to_i
)
269 else if dwd
< throw_distance
then
270 if can_throw
( t
) then
271 cannot_throw_until
= t
.nbr
+ throw_period
272 var javelin
= new Javelin( pos
, t
.game
.dino
.pos
)
273 t
.game
.add_javelin
( javelin
)
278 going_to
= t
.game
.dino
.pos
291 var angle
: Float = pi
/2.0
293 var thrown_angle_xy
: Float
297 var hit_ground
= false
300 var speed
: Int = 10+2.rand
301 var hit_dino_distance
= 128
303 var gravity
: Int = -3
305 init ( from
: GamePos, to
: GamePos )
309 thrown_angle_xy
= atan2
( dy
.to_f
, dx
.to_f
)
310 pos
= new GamePos.copy
( from
)
313 redef fun do_turn
( t
)
315 var dwd
= squared_dist_with_dino
( t
.game
)
316 if dwd
< hit_dino_distance
and t
.game
.dino
.is_alive
then
317 t
.game
.dino
.hit
( self, hit_damage
)
327 var mx
= (thrown_angle_xy
.cos
* speed
.to_f
).to_i
329 pos
.y
+= (thrown_angle_xy
.sin
* speed
.to_f
).to_i
332 angle
= atan2
( (speed_z
/10).to_f
, -1.0*speed
.to_f
)-pi
/2.0
334 angle
= atan2
( (speed_z
/10).to_f
, speed
.to_f
)-pi
/2.0