lib/minigl/movement.rb
def move(forces, obst, ramps, set_speed = false)
      if set_speed
        @speed.x = forces.x
        @speed.y = forces.y
      else
        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) * (@bottom.ratio - G.ramp_slip_threshold) * G.ramp_slip_force / G.ramp_slip_threshold
          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
      end

      @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 o != self && 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
def move(forces, obst, ramps, set_speed = false)
      if set_speed
        @speed.x = forces.x
        @speed.y = forces.y
      else
        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) * (@bottom.ratio - G.ramp_slip_threshold) * G.ramp_slip_force / G.ramp_slip_threshold
          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
      end

      @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 o != self && 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
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 <code>include Movement</code>.
 [ramps] An array of ramps to be considered in the collision checking.
         Ramps must be instances of Ramp (or derived classes).
 [set_speed] Set this flag to +true+ to cause the +forces+ vector to be
             treated as a speed vector, i.e., the object's speed will be
             directly set to the given values. The force of gravity will
             also be ignored in this case.