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, obst_obstacles = nil, obst_ramps = 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, obst_obstacles, obst_ramps) ⇒ 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.
190 191 192 |
# File 'lib/minigl/movement.rb', line 190 def bottom @bottom end |
#h ⇒ Object (readonly)
Height of the bounding box.
178 179 180 |
# File 'lib/minigl/movement.rb', line 178 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.
194 195 196 |
# File 'lib/minigl/movement.rb', line 194 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.
164 165 166 |
# File 'lib/minigl/movement.rb', line 164 def mass @mass end |
#max_speed ⇒ Object (readonly)
A Vector with the speed limits for the object (x: horizontal component, y: vertical component).
172 173 174 |
# File 'lib/minigl/movement.rb', line 172 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.
182 183 184 |
# File 'lib/minigl/movement.rb', line 182 def passable @passable end |
#prev_speed ⇒ Object (readonly)
:nodoc:
210 211 212 |
# File 'lib/minigl/movement.rb', line 210 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.
198 199 200 |
# File 'lib/minigl/movement.rb', line 198 def right @right end |
#speed ⇒ Object (readonly)
A Vector with the current speed of the object (x: horizontal component, y: vertical component).
168 169 170 |
# File 'lib/minigl/movement.rb', line 168 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.
208 209 210 |
# File 'lib/minigl/movement.rb', line 208 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.
186 187 188 |
# File 'lib/minigl/movement.rb', line 186 def top @top end |
#w ⇒ Object (readonly)
Width of the bounding box.
175 176 177 |
# File 'lib/minigl/movement.rb', line 175 def w @w end |
#x ⇒ Object
The x-coordinate of the top left corner of the bounding box.
201 202 203 |
# File 'lib/minigl/movement.rb', line 201 def x @x end |
#y ⇒ Object
The y-coordinate of the top left corner of the bounding box.
204 205 206 |
# File 'lib/minigl/movement.rb', line 204 def y @y end |
Instance Method Details
#bounds ⇒ Object
Returns the bounding box as a Rectangle.
213 214 215 |
# File 'lib/minigl/movement.rb', line 213 def bounds Rectangle.new @x, @y, @w, @h end |
#cycle(points, speed, obstacles = nil, obst_obstacles = nil, obst_ramps = 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. - obst_obstacles
-
Obstacles that should be considered when moving objects from the
obstaclesarray, i.e., these obstacles won’t interfere in the elevator’s movement, but in the movement of the objects being carried. - obst_ramps
-
Ramps to consider when moving objects from the
obstaclesarray, as described forobst_obstacles.
471 472 473 474 475 476 477 478 479 480 481 482 |
# File 'lib/minigl/movement.rb', line 471 def cycle(points, speed, obstacles = nil, obst_obstacles = nil, obst_ramps = nil) @cur_point = 0 if @cur_point.nil? if obstacles points[@cur_point], speed, obstacles, obst_obstacles, obst_ramps 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).
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 338 339 340 341 342 |
# File 'lib/minigl/movement.rb', line 228 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 if @bottom.ratio >= G.ramp_slip_threshold forces.x += (@bottom.left ? -1 : 1) * G.ramp_slip_force elsif forces.x > 0 && @bottom.left || forces.x < 0 && !@bottom.left forces.x *= @bottom.factor end 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, obst_obstacles, obst_ramps) ⇒ 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. - obst_obstacles
-
Obstacles that should be considered when moving objects from the
obstaclesarray, i.e., these obstacles won’t interfere in the elevator’s movement, but in the movement of the objects being carried. - obst_ramps
-
Ramps to consider when moving objects from the
obstaclesarray, as described forobst_obstacles.
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 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 |
# File 'lib/minigl/movement.rb', line 361 def (aim, speed, obstacles, obst_obstacles, obst_ramps) 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 prev_x = @x; prev_y = @y if @speed.x > 0 && x_aim >= aim.x || @speed.x < 0 && x_aim <= aim.x @x = aim.x; @speed.x = 0 else @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 forces = Vector.new @x - prev_x, @y - prev_y prev_g = G.gravity.clone G.gravity.x = G.gravity.y = 0 passengers.each do |p| prev_speed = p.speed.clone prev_forces = p.stored_forces.clone prev_bottom = p.bottom p.speed.x = p.speed.y = 0 p.stored_forces.x = p.stored_forces.y = 0 p.instance_exec { @bottom = nil } p.move forces * p.mass, obst_obstacles, obst_ramps p.speed.x = prev_speed.x p.speed.y = prev_speed.y p.stored_forces.x = prev_forces.x p.stored_forces.y = prev_forces.y p.instance_exec(prev_bottom) { |b| @bottom = b } end G.gravity = prev_g 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.
423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 |
# File 'lib/minigl/movement.rb', line 423 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 |