mnit_ballz: game_logic module
[nit.git] / examples / mnit_ballz / src / game_logic.nit
1 #this file is part of NIT ( http://www.nitlanguage.org ).
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
6 #
7 # http://www.apache.org/licenses/LICENSE-2.0
8 #
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
14
15 # All the logic of the game
16 module game_logic
17
18 import assets
19 import objects
20 import geometry::quadtree
21 import collision
22
23 redef class Ball
24
25 # Scale for drawing the image of `self`
26 var scale = 1.0
27
28 # ASensorProximity value for modifying `scale`
29 # Not used yet
30 var scale_proximity_modifier = 6.0
31
32 # Radius of `self`
33 var radius = 32.0
34
35 # Movement vector of `self`
36 var offset = new Point[Float](0.0, 0.0)
37
38 # Calculates the acceleration of `self`
39 fun acceleration(x,y: Float)
40 do
41 var max_offset = 10.0
42 var max_value = 9.80
43 var offset_x = offset.x - x/max_value
44 var offset_y = offset.y + y/max_value
45 if offset_x > max_offset then offset_x = max_offset
46 if offset_x < -max_offset then offset_x = -max_offset
47 if offset_y > max_offset then offset_y = max_offset
48 if offset_y < -max_offset then offset_y = -max_offset
49 offset = new Point[Float](offset_x, offset_y)
50 end
51
52 # Do the collision detection, then move `self`consequently
53 fun do_turn(game: Game)
54 do
55 offset = new Point[Float](offset.x * 0.98, offset.y * 0.98)
56 var np = collision(game.quadtree)
57 if np != null then
58 offset = np
59 center = new Point[Float](center.x + offset.x, center.y + offset.y)
60 else
61 center = new Point[Float](center.x + offset.x, center.y + offset.y)
62 end
63 end
64
65 # Collision detection
66 fun collision(quadtree: SQuadTree[OrientedLine]): nullable Point[Float]
67 do
68
69 var nx = self.center.x + offset.x
70 var ny = self.center.y + offset.y
71 var new_center = new Point[Float](nx, ny)
72 var effective_radius = radius*scale
73 # Lines intersecting with the ball
74 var intersecting_lines = new Array[OrientedLine]
75
76 # Line intersecting closest to the ball
77 var intersecting_line: nullable OrientedLine = null
78
79 # closest point of the intersecting line
80 var closest_point: nullable Point[Float] = null
81
82 # get the intersecting lines with help of the quadtree
83 var lines = quadtree.items_overlapping(new_center.padded(effective_radius))
84 for l in lines do
85 if is_intersecting(new_center, l.point_left, l.point_right, effective_radius) then
86 intersecting_lines.add(l)
87 end
88 end
89
90 # get the line closest to the ball from the intersecting lines, setting the closest point
91 var min_dist = 100.0
92 if intersecting_lines.length >= 2 then
93 for l in intersecting_lines do
94 var closest = point_closest_to_line(new_center, l.point_left, l.point_right)
95 var distance = distance(closest, new_center)
96 if distance < min_dist then
97 min_dist = distance
98 intersecting_line = l
99 closest_point = closest
100 end
101 end
102 else if intersecting_lines.length == 1 then
103 intersecting_line = intersecting_lines[0]
104 closest_point = point_closest_to_line(new_center, intersecting_line.point_left, intersecting_line.point_right)
105 end
106
107 if intersecting_line != null and closest_point != null then
108 return bounce(center, intersecting_line.point_left, intersecting_line.point_right, offset)
109 end
110 return null
111 end
112
113 # Event interception
114 fun intercepts(event: InputEvent): Bool is abstract
115 end
116
117 # The core of the game
118 class Game
119
120 # The Ball!
121 var ball: Ball is noinit
122
123 # List of walls in the level
124 var walls: Array[Wall] is noinit
125
126 # Width of the display
127 var width: Float
128
129 # Heightof the display
130 var height: Float
131
132 # Quadtree used for collision detection
133 var quadtree: SQuadTree[OrientedLine] is noinit
134
135 init
136 do
137 ball = new Ball(new Point[Float](width/2.0, height/2.0))
138 # Walls initialisation
139 var walla = new Wall(new Point[Float](width/4.0, height/4.0), pi/3.0, 1.0)
140 var wallb = new Wall(new Point[Float](width*0.75, height/4.0), 0.0, 1.0)
141 var wallc = new Wall(new Point[Float](width/4.0, height*0.75), 0.0, 1.0)
142 var walld = new Wall(new Point[Float](width*0.75, height*0.75), pi/3.0, 1.0)
143 walls = new Array[Wall].with_items(walla, wallb, wallc, walld)
144
145 # adding screen bordures
146 var i = new Point[Float](0.0,0.0)
147 var a = new Point[Float](0.0, height/2.0)
148 var b = new Point[Float](width/2.0, 0.0)
149 var c = new Point[Float](width, height/2.0)
150 var d = new Point[Float](width/2.0, height)
151
152 var l1 = new OrientedLine(i, i, pi/2.0, height, a)
153 var l2 = new OrientedLine(i, i, 0.0, width, b)
154 var l3 = new OrientedLine(i, i, pi/2.0, height, c)
155 var l4 = new OrientedLine(i, i, 0.0, width, d)
156
157 quadtree = new SQuadTree[OrientedLine](5, width, height)
158 for w in walls do for l in w.lines do
159 quadtree.add(l)
160 end
161 quadtree.add(l1)
162 quadtree.add(l2)
163 quadtree.add(l3)
164 quadtree.add(l4)
165 end
166
167 # Only calls `do_turn` of the ball for the moment
168 fun do_turn do ball.do_turn(self)
169
170 # Input gestion
171 fun input(ie: InputEvent): Bool do return false
172 end
173
174 redef class App
175
176 # Assets used in all the app
177 var assets = new Assets
178
179 redef fun on_create do
180 super
181 assets.load
182 end
183 end