contrib: remove crazy_moles
[nit.git] / examples / mnit_dino / src / game_logic.nit
index 4958fde..63b6d53 100644 (file)
@@ -15,7 +15,7 @@
 # limitations under the License.
 
 # Entire game logic for the Dino game
-# Depends only on Nit standard library
+# Depends only on Nit `core` library
 module game_logic
 
 interface Turnable
@@ -28,12 +28,14 @@ class Game
        var dino = new Dino
        var cavemen = new Array[Caveman]
        var javelins_in_air = new Array[Javelin]
-       var javelins_on_ground = new Array[Javelin]
+       var items_on_ground = new Array[Entity]
        var entities = new Array[Entity].with_items(dino)
        var turn_nbr = 0
 
        var over_since = 0
 
+       var score: Ref[Int]
+
        var random_radius_min = 200
        var random_radius_max = 400
        protected var random_radius_diff : Int =
@@ -41,9 +43,11 @@ class Game
 
        var entities_sorter = new EntitiesSorter
 
-       init( cavemen_nbr : Int )
+       init( cavemen_nbr : Int, score: Ref[Int] )
        do
-               srand
+               srand_from(cavemen_nbr)
+
+               self.score = score
 
                nbr_wanted_cavemen = cavemen_nbr
 
@@ -57,6 +61,13 @@ class Game
                        man.pos.x = ( angle.cos * radius ).to_i
                        man.pos.y = ( angle.sin * radius ).to_i
                end
+
+               for b in 24.times do
+                       var bush = new Bush
+                       bush.pos = new GamePos([-300..300[.rand, [-400..400[.rand)
+                       items_on_ground.add bush
+                       entities.add bush
+               end
        end
 
        fun do_turn : Turn
@@ -69,6 +80,7 @@ class Game
                        man.do_turn( turn )
                        if not man.is_alive then
                                cavemen.remove( man )
+                               score.item += 1
                        end
                end
 
@@ -79,7 +91,7 @@ class Game
                                entities.remove( j )
                        else if j.hit_ground then
                                javelins_in_air.remove( j )
-                               javelins_on_ground.add( j )
+                               items_on_ground.add( j )
                        end
                end
 
@@ -121,16 +133,9 @@ class GamePos
        var x : Int
        var y : Int
 
-       init ( x, y : Int )
-       do
-               self.x = x
-               self.y = y
-       end
-
        init copy( src : GamePos )
        do
-               x = src.x
-               y = src.y
+               init(src.x, src.y)
        end
 
        fun squared_dist_with( other : GamePos ) : Int
@@ -147,18 +152,30 @@ end
 class Entity
        super Turnable
 
+       fun run_over_distance_x: Int do return 50
+       fun run_over_distance_y: Int do return 16
+
        var pos = new GamePos( 0, 0 )
 
        fun squared_dist_with_dino( game : Game ) : Int
        do
                return pos.squared_dist_with( game.dino.pos )
        end
+
+       fun under_dino(game: Game): Bool
+       do
+               var dy = pos.y - game.dino.pos.y
+               if dy.abs > run_over_distance_y then return false
+
+               var dx = pos.x - game.dino.pos.x
+               return dx.abs <= run_over_distance_x
+       end
 end
 
 class MovingEntity
        super Entity
 
-       var going_to : nullable GamePos writable = null
+       var going_to : nullable GamePos = null is writable
 
        fun speed : Int is abstract
 
@@ -218,6 +235,13 @@ class Dino
                if is_alive then
                        super
                end
+
+               for i in t.game.items_on_ground do
+                       if i.under_dino(t.game) then
+                               t.game.items_on_ground.remove i
+                               t.game.entities.remove i
+                       end
+               end
        end
 end
 
@@ -231,7 +255,6 @@ class Caveman
        var throw_distance : Int = 400*40+10.rand
        var fear_distance : Int = 300*20+8.rand
        var flee_distance : Int = 600*60+16.rand
-       var run_over_distance = 500
 
        var fear_duration : Int = 80+40.rand
        var throw_period : Int = 40+8.rand
@@ -243,24 +266,24 @@ class Caveman
 
        redef var is_alive : Bool = true
 
-       redef fun speed do return 4
+       redef var speed: Int = 3+3.rand
 
        fun is_afraid( turn : Turn ) : Bool do return turn.nbr < afraid_until
        fun can_throw( turn : Turn ) : Bool do return cannot_throw_until < turn.nbr
+       fun die(turn: Turn) do is_alive = false
 
        redef fun do_turn( t )
        do
                if is_alive then
-                       var dwd = squared_dist_with_dino( t.game )
-
-                       if dwd < run_over_distance then
-                               if t.game.dino.is_alive then is_alive = false
+                       if under_dino(t.game) then
+                               if t.game.dino.is_alive then die(t)
                                return
                        else if is_afraid( t ) then
                                # going to destination
                        else if t.game.dino.life <= 0 then
                                # dino is dead, chill
                        else
+                               var dwd = squared_dist_with_dino( t.game )
                                if dwd < fear_distance then
                                        afraid_until = t.nbr + fear_duration
 
@@ -269,6 +292,7 @@ class Caveman
                                        var dy = dino_pos.y - pos.y
                                        var a = atan2( dy.to_f, dx.to_f )
                                        a += pi # get opposite
+                                       a += [-100..100[.rand.to_f*pi/3.0/100.0
                                        var x = a.cos*flee_distance.to_f
                                        var y = a.sin*flee_distance.to_f
                                        going_to = new GamePos( x.to_i, y.to_i )
@@ -326,6 +350,12 @@ class Javelin
                else
                        if z <= 0 then
                                hit_ground = true
+                               if thrown_angle_xy.cos > 0.0 then
+                                       angle = pi*5.0/8.0+(pi/4.0).rand
+                               else
+                                       # left of the screen
+                                       angle = pi*9.0/8.0+(pi/4.0).rand
+                               end
                        else
                                # in the air
                                speed_z += gravity
@@ -345,9 +375,12 @@ class Javelin
        end
 end
 
+class Bush super Entity end
+
 # Sort entities on screen in order of Y, entities in the back are drawn first
 class EntitiesSorter
-       super AbstractSorter[Entity]
+       super Comparator
+       redef type COMPARED: Entity
 
        redef fun compare(a, b) do return b.pos.y <=> a.pos.y
 end