Module: MiniGL::Movement
- Included in:
- GameObject
- Defined in:
- lib/minigl/movement.rb
Overview
This module provides objects with physical properties and methods for moving. It allows moving with or without collision checking (based on rectangular bounding boxes), including a method to behave as an elevator, affecting other objects’ positions as it moves.
Instance Attribute Summary collapse
-
#bottom ⇒ Object
readonly
The object that is making contact with this from below.
-
#h ⇒ Object
readonly
Height of the bounding box.
-
#left ⇒ Object
readonly
The object that is making contact with this from the left.
-
#mass ⇒ Object
readonly
The mass of the object, in arbitrary units.
-
#max_speed ⇒ Object
readonly
A Vector with the speed limits for the object (x: horizontal component, y: vertical component).
-
#passable ⇒ Object
readonly
Whether a moving object can pass through this block when coming from below.
-
#prev_speed ⇒ Object
readonly
:nodoc:.
-
#right ⇒ Object
readonly
The object that is making contact with this from the right.
-
#speed ⇒ Object
readonly
A Vector with the current speed of the object (x: horizontal component, y: vertical component).
-
#stored_forces ⇒ Object
A Vector with the horizontal and vertical components of a force that be applied in the next time
moveis called. -
#top ⇒ Object
readonly
The object that is making contact with this from above.
-
#w ⇒ Object
readonly
Width of the bounding box.
-
#x ⇒ Object
The x-coordinate of the top left corner of the bounding box.
-
#y ⇒ Object
The y-coordinate of the top left corner of the bounding box.
Instance Method Summary collapse
-
#bounds ⇒ Object
Returns the bounding box as a Rectangle.
-
#cycle(points, speed, obstacles = nil) ⇒ Object
Causes the object to move in cycles across multiple given points (the first point in the array is the first point the object will move towards, so it doesn’t need to be equal to the current/initial position).
-
#move(forces, obst, ramps) ⇒ Object
Moves this object, based on the forces being applied to it, and performing collision checking.
-
#move_carrying(aim, speed, obstacles) ⇒ Object
Moves this object as an elevator (i.e., potentially carrying other objects) towards a given point.
-
#move_free(aim, speed) ⇒ Object
Moves this object, without performing any collision checking, towards the specified point.
Instance Attribute Details
#bottom ⇒ Object (readonly)
The object that is making contact with this from below. If there’s no contact, returns nil.
189 190 191 |
# File 'lib/minigl/movement.rb', line 189 def bottom @bottom end |
#h ⇒ Object (readonly)
Height of the bounding box.
177 178 179 |
# File 'lib/minigl/movement.rb', line 177 def h @h end |
#left ⇒ Object (readonly)
The object that is making contact with this from the left. If there’s no contact, returns nil.
193 194 195 |
# File 'lib/minigl/movement.rb', line 193 def left @left end |
#mass ⇒ Object (readonly)
The mass of the object, in arbitrary units. The default value for GameObject instances, for example, is 1. The larger the mass (i.e., the heavier the object), the more intense the forces applied to the object have to be in order to move it.
163 164 165 |
# File 'lib/minigl/movement.rb', line 163 def mass @mass end |
#max_speed ⇒ Object (readonly)
A Vector with the speed limits for the object (x: horizontal component, y: vertical component).
171 172 173 |
# File 'lib/minigl/movement.rb', line 171 def max_speed @max_speed end |
#passable ⇒ Object (readonly)
Whether a moving object can pass through this block when coming from below. This is a common feature of platforms in platform games.
181 182 183 |
# File 'lib/minigl/movement.rb', line 181 def passable @passable end |
#prev_speed ⇒ Object (readonly)
:nodoc:
209 210 211 |
# File 'lib/minigl/movement.rb', line 209 def prev_speed @prev_speed end |
#right ⇒ Object (readonly)
The object that is making contact with this from the right. If there’s no contact, returns nil.
197 198 199 |
# File 'lib/minigl/movement.rb', line 197 def right @right end |
#speed ⇒ Object (readonly)
A Vector with the current speed of the object (x: horizontal component, y: vertical component).
167 168 169 |
# File 'lib/minigl/movement.rb', line 167 def speed @speed end |
#stored_forces ⇒ Object
A Vector with the horizontal and vertical components of a force that be applied in the next time move is called.
207 208 209 |
# File 'lib/minigl/movement.rb', line 207 def stored_forces @stored_forces end |
#top ⇒ Object (readonly)
The object that is making contact with this from above. If there’s no contact, returns nil.
185 186 187 |
# File 'lib/minigl/movement.rb', line 185 def top @top end |
#w ⇒ Object (readonly)
Width of the bounding box.
174 175 176 |
# File 'lib/minigl/movement.rb', line 174 def w @w end |
#x ⇒ Object
The x-coordinate of the top left corner of the bounding box.
200 201 202 |
# File 'lib/minigl/movement.rb', line 200 def x @x end |
#y ⇒ Object
The y-coordinate of the top left corner of the bounding box.
203 204 205 |
# File 'lib/minigl/movement.rb', line 203 def y @y end |
Instance Method Details
#bounds ⇒ Object
Returns the bounding box as a Rectangle.
212 213 214 |
# File 'lib/minigl/movement.rb', line 212 def bounds Rectangle.new @x, @y, @w, @h end |
#cycle(points, speed, obstacles = nil) ⇒ Object
Causes the object to move in cycles across multiple given points (the first point in the array is the first point the object will move towards, so it doesn’t need to be equal to the current/initial position). If obstacles are provided, it will behave as an elevator (as in move_carrying).
Parameters:
- points
-
An array of Vectors representing the path that the object will perform.
- speed
-
The constant speed at which the object will move. This must be provided as a scalar, not a vector.
- obstacles
-
An array of obstacles to be considered in the collision checking, and carried along when colliding from above. Obstacles must be instances of Block (or derived classes), or objects that
include Movement.
438 439 440 441 442 443 444 445 446 447 448 449 |
# File 'lib/minigl/movement.rb', line 438 def cycle(points, speed, obstacles = nil) @cur_point = 0 if @cur_point.nil? if obstacles points[@cur_point], speed, obstacles else move_free points[@cur_point], speed end if @speed.x == 0 and @speed.y == 0 if @cur_point == points.length - 1; @cur_point = 0 else; @cur_point += 1; end end end |
#move(forces, obst, ramps) ⇒ Object
Moves this object, based on the forces being applied to it, and performing collision checking.
Parameters:
- forces
-
A Vector where x is the horizontal component of the resulting force and y is the vertical component.
- obst
-
An array of obstacles to be considered in the collision checking. Obstacles must be instances of Block (or derived classes), or objects that
include Movement. - ramps
-
An array of ramps to be considered in the collision checking. Ramps must be instances of Ramp (or derived classes).
227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 |
# File 'lib/minigl/movement.rb', line 227 def move(forces, obst, ramps) forces.x += G.gravity.x; forces.y += G.gravity.y forces.x += @stored_forces.x; forces.y += @stored_forces.y @stored_forces.x = @stored_forces.y = 0 forces.x = 0 if (forces.x < 0 and @left) or (forces.x > 0 and @right) forces.y = 0 if (forces.y < 0 and @top) or (forces.y > 0 and @bottom) if @bottom.is_a? Ramp and @bottom.ratio >= G.ramp_slip_threshold forces.x = (@bottom.left ? -1 : 1) * 0.1 end @speed.x += forces.x / @mass; @speed.y += forces.y / @mass @speed.x = 0 if @speed.x.abs < G.min_speed.x @speed.y = 0 if @speed.y.abs < G.min_speed.y @speed.x = (@speed.x <=> 0) * @max_speed.x if @speed.x.abs > @max_speed.x @speed.y = (@speed.y <=> 0) * @max_speed.y if @speed.y.abs > @max_speed.y @prev_speed = @speed.clone x = @speed.x < 0 ? @x + @speed.x : @x y = @speed.y < 0 ? @y + @speed.y : @y w = @w + (@speed.x < 0 ? -@speed.x : @speed.x) h = @h + (@speed.y < 0 ? -@speed.y : @speed.y) move_bounds = Rectangle.new x, y, w, h coll_list = [] obst.each do |o| coll_list << o if move_bounds.intersect? o.bounds end ramps.each do |r| r.check_can_collide move_bounds end if coll_list.length > 0 up = @speed.y < 0; rt = @speed.x > 0; dn = @speed.y > 0; lf = @speed.x < 0 if @speed.x == 0 || @speed.y == 0 # Ortogonal if rt; x_lim = find_right_limit coll_list elsif lf; x_lim = find_left_limit coll_list elsif dn; y_lim = find_down_limit coll_list elsif up; y_lim = find_up_limit coll_list end if rt && @x + @w + @speed.x > x_lim @x = x_lim - @w @speed.x = 0 elsif lf && @x + @speed.x < x_lim @x = x_lim @speed.x = 0 elsif dn && @y + @h + @speed.y > y_lim; @y = y_lim - @h; @speed.y = 0 elsif up && @y + @speed.y < y_lim; @y = y_lim; @speed.y = 0 end else # Diagonal x_aim = @x + @speed.x + (rt ? @w : 0); x_lim_def = x_aim y_aim = @y + @speed.y + (dn ? @h : 0); y_lim_def = y_aim coll_list.each do |c| if c.passable; x_lim = x_aim elsif rt; x_lim = c.x else; x_lim = c.x + c.w end if dn; y_lim = c.y elsif c.passable; y_lim = y_aim else; y_lim = c.y + c.h end if c.passable y_lim_def = y_lim if dn && @y + @h <= y_lim && y_lim < y_lim_def elsif (rt && @x + @w > x_lim) || (lf && @x < x_lim) # Can't limit by x, will limit by y y_lim_def = y_lim if (dn && y_lim < y_lim_def) || (up && y_lim > y_lim_def) elsif (dn && @y + @h > y_lim) || (up && @y < y_lim) # Can't limit by y, will limit by x x_lim_def = x_lim if (rt && x_lim < x_lim_def) || (lf && x_lim > x_lim_def) else x_time = 1.0 * (x_lim - @x - (@speed.x < 0 ? 0 : @w)) / @speed.x y_time = 1.0 * (y_lim - @y - (@speed.y < 0 ? 0 : @h)) / @speed.y if x_time > y_time # Will limit by x x_lim_def = x_lim if (rt && x_lim < x_lim_def) || (lf && x_lim > x_lim_def) elsif (dn && y_lim < y_lim_def) || (up && y_lim > y_lim_def) y_lim_def = y_lim end end end if x_lim_def != x_aim @speed.x = 0 if lf; @x = x_lim_def else; @x = x_lim_def - @w end end if y_lim_def != y_aim @speed.y = 0 if up; @y = y_lim_def else; @y = y_lim_def - @h end end end end @x += @speed.x @y += @speed.y # Keeping contact with ramp # if @speed.y == 0 and @speed.x.abs <= G.ramp_contact_threshold and @bottom.is_a? Ramp # @y = @bottom.get_y(self) # puts 'aqui' # end ramps.each do |r| r.check_intersection self end check_contact obst, ramps end |
#move_carrying(aim, speed, obstacles) ⇒ Object
Moves this object as an elevator (i.e., potentially carrying other objects) towards a given point.
Parameters:
- aim
-
A Vector specifying where the object will move to.
- speed
-
The constant speed at which the object will move. This must be provided as a scalar, not a vector.
- obstacles
-
An array of obstacles to be considered in the collision checking, and carried along when colliding from above. Obstacles must be instances of Block (or derived classes), or objects that
include Movement.
350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 |
# File 'lib/minigl/movement.rb', line 350 def (aim, speed, obstacles) x_d = aim.x - @x; y_d = aim.y - @y distance = Math.sqrt(x_d**2 + y_d**2) if distance == 0 @speed.x = @speed.y = 0 return end @speed.x = 1.0 * x_d * speed / distance @speed.y = 1.0 * y_d * speed / distance x_aim = @x + @speed.x; y_aim = @y + @speed.y passengers = [] obstacles.each do |o| if @x + @w > o.x && o.x + o.w > @x foot = o.y + o.h if foot.round(6) == @y.round(6) || @speed.y < 0 && foot < @y && foot > y_aim passengers << o end end end if @speed.x > 0 && x_aim >= aim.x || @speed.x < 0 && x_aim <= aim.x passengers.each do |p| p.x += aim.x - @x end @x = aim.x; @speed.x = 0 else passengers.each do |p| p.x += @speed.x end @x = x_aim end if @speed.y > 0 && y_aim >= aim.y || @speed.y < 0 && y_aim <= aim.y @y = aim.y; @speed.y = 0 else @y = y_aim end passengers.each do |p| p.y = @y - p.h end end |
#move_free(aim, speed) ⇒ Object
Moves this object, without performing any collision checking, towards the specified point.
Parameters:
- aim
-
A Vector specifying where the object will move to.
- speed
-
The constant speed at which the object will move. This must be provided as a scalar, not a vector.
396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 |
# File 'lib/minigl/movement.rb', line 396 def move_free(aim, speed) x_d = aim.x - @x; y_d = aim.y - @y distance = Math.sqrt(x_d**2 + y_d**2) if distance == 0 @speed.x = @speed.y = 0 return end @speed.x = 1.0 * x_d * speed / distance @speed.y = 1.0 * y_d * speed / distance if (@speed.x < 0 and @x + @speed.x <= aim.x) or (@speed.x >= 0 and @x + @speed.x >= aim.x) @x = aim.x @speed.x = 0 else @x += @speed.x end if (@speed.y < 0 and @y + @speed.y <= aim.y) or (@speed.y >= 0 and @y + @speed.y >= aim.y) @y = aim.y @speed.y = 0 else @y += @speed.y end end |