Method: MiniGL::Movement#move_carrying

Defined in:
lib/minigl/movement.rb

#move_carrying(arg, speed, carried_objs, obstacles, ramps, ignore_collision = false) ⇒ Object

Moves this object as an elevator (i.e., potentially carrying other objects) with the specified forces or towards a given point.

Parameters:

arg

A Vector specifying either the forces acting on this object or a point towards the object should move.

speed

If the first argument is a forces vector, then this should be nil. If it is a point, then this is the constant speed at which the object will move (provided as a scalar, not a vector).

carried_objs

An array of objects that can potentially be carried by this object while it moves. The objects must respond to x, y, w and h.

obstacles

Obstacles that should be considered for collision checking with the carried objects, if they include the Movement module, and with this object too, if moving with forces and the ignore_collision flag is false.

ramps

Ramps that should be considered for the carried objects, if they include the Movement module, and for this object too, if moving with forces and ignore_collision is false.

ignore_collision

Set to true to make this object ignore collision even when moving with forces.



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
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
# File 'lib/minigl/movement.rb', line 363

def move_carrying(arg, speed, carried_objs, obstacles, ramps, ignore_collision = false)
  if speed
    x_d = arg.x - @x; y_d = arg.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
  else
    x_aim = @x + @speed.x + G.gravity.x + arg.x
    y_aim = @y + @speed.y + G.gravity.y + arg.y
  end

  passengers = []
  carried_objs.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
    if @speed.x > 0 && x_aim >= arg.x || @speed.x < 0 && x_aim <= arg.x
      @x = arg.x; @speed.x = 0
    else
      @x = x_aim
    end
    if @speed.y > 0 && y_aim >= arg.y || @speed.y < 0 && y_aim <= arg.y
      @y = arg.y; @speed.y = 0
    else
      @y = y_aim
    end
  else
    move(arg, ignore_collision ? [] : obstacles, ignore_collision ? [] : ramps)
  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|
    if p.class.included_modules.include?(Movement)
      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, obstacles, 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 }
    else
      p.x += forces.x
      p.y += forces.y
    end
  end
  G.gravity = prev_g
end