[SOLVED] Simple Physics help.

Questions about the LÖVE API, installing LÖVE and other support related questions go here.
Forum rules
Before you make a thread asking for help, read this.
Post Reply
FlashFire
Prole
Posts: 20
Joined: Thu Sep 11, 2014 12:44 am

[SOLVED] Simple Physics help.

Post by FlashFire »

I'm trying to make basic physics for a game I'm making. I just can't get the math right. The game physics are as advanced as the old Mario 2d games, so not that good at all, I'm just an idiot when it comes to this stuff.

Main issues:
walls don't stop the player(I only made left-side physics of the blocks though

After I detected the collision, I convert the player's position and velocity into slope-intercept form, Then I try to see if that line goes through any surface of the block, and i get the side this way. Don't know if this is one of the issues or not.

This is my old attempt, it's more readable, but has minor differences
pastebin.com/ATAknuT4

My current version is at:
pastebin.com/6EPKwTaj

The main difference being that the left side of the physics are only allowed to happen if the top left vertice of the player is in the collision.

Sorry, this is my first post on this forum, please tell me if I didn't provide enough information.
Last edited by FlashFire on Sun Sep 14, 2014 9:38 pm, edited 1 time in total.
Snackrilege
Prole
Posts: 19
Joined: Sat Sep 06, 2014 8:50 pm

Re: Simple Physics help.

Post by Snackrilege »

Hey there, welcome! I'm pretty new here myself. I've gotten pretty proficient with love's physics system by now, and I've done some homebrewed physics in FlashPunk before, so I'll try to help you out.

My first thought is, for your own sanity, you should separate the collision detection code from the collision resolution code.

ie

Code: Select all

if --code to detect collisions-- then
for i,object in ipairs(collidedObjects) do
  object.resolveCollision(collidedObjects) -- passing in the list of things collided with, so he can get data about them
end
That being said, I don't understand why you are representing your velocity vector with a slope. Are you trying to determine the angle of their movement? If so, just dividing y/x isn't going to work.

you'll need to use math.atan2(y,x) to get the result you're looking for. It will return an angle, in radians, of the direction traveled.
User avatar
ivan
Party member
Posts: 1911
Joined: Fri Mar 07, 2008 1:39 pm
Contact:

Re: Simple Physics help.

Post by ivan »

Hey I have a few suggestions.
First, when get a lot of nesting like this:

Code: Select all

									end
								end
							end
						end
					end
				end
			end
		end
	end
is a sign that you may want to break your code into several functions.
For example, "if localCamera.X < position.X+100 and localCamera.Y < position.Y+100 then --print('Inside Block')" becomes the function: "isInsideBlock(x, y)" or the statement "for i,v in pairs({Vector2.new(0,0),Vector2.new(50,0),Vector2.new(0,75),Vector2.new(50,75)}) do" becomes the function "testRect(list)".
FlashFire wrote:After I detected the collision, I convert the player's position and velocity into slope-intercept form, Then I try to see if that line goes through any surface of the block, and i get the side this way. Don't know if this is one of the issues or not.
I think your case is ideal for the "separating axis theorem":
http://gamedevelopment.tutsplus.com/tut ... amedev-169
More specifically, take a look at AABB vs AABB intersection:
http://www.opentk.com/node/869
FlashFire
Prole
Posts: 20
Joined: Thu Sep 11, 2014 12:44 am

Re: Simple Physics help.

Post by FlashFire »

Thanks for the nesting tip ivan. I re-did 95% of the coding, and fixed any errors. It works great now. There still are a lot of ends, especially for the getCollisions functions, but it's better.

Code: Select all

----------------
---physics
----------------
--notes
--uses map as hitboxes
--only tests 4 points of player(using localCamera)
--points are (50,0),(0,75),(0,0),(50,75)
----------------

physics = {}
physics.objects = {}

physics.objects.player = {}
physics.objects.player.velocity = Vector2.new(0,0)
physics.objects.player.staticVelocity = Vector2.new(0,0)
physics.objects.player.position = Vector2.new(0,0)

physics.getCollisions = function(position,size)
	local collisions = {}
	for xIndex,xValue in pairs(map) do
		for yIndex,value in pairs(xValue) do
			if value ~= 'air' then
				local blockPosition = Vector2.new(xIndex,yIndex)*100+Vector2.new(0,450)
				for i,v in pairs({Vector2.new(0,size.Y),Vector2.new(size.X,0),Vector2.new(0,0),Vector2.new(size.X,size.Y)}) do
					local position = position+v
					if position.X >= blockPosition.X and position.Y >= blockPosition.Y then
						if position.X <= blockPosition.X+100 and position.Y <= blockPosition.Y+100 then
							collisions[#collisions+1] = {position = blockPosition,vertex = v}
						end
					end
				end
			end
		end
	end
	return collisions
end
 
 
physics.reactToCollision = function(collision,object,lastPosition,size)
	local slope = object.velocity.Y/object.velocity.X
	local offset = lastPosition.Y-(slope*lastPosition.X)
	------Top side
  if collision.vertex.Y == size.Y then
    if tostring(slope) == '-inf' then
      object.velocity = Vector2.new(object.velocity.X,0)
      object.position = Vector2.new(object.position.X,collision.position.Y-75)
      return true,'top'
    else
      local x = (-offset+lastPosition.Y)/slope
      if x >= collision.position.X and x <= collision.position.X+100 then
        object.velocity = Vector2.new(object.velocity.X,0)
        object.position = Vector2.new(object.position.X,collision.position.Y-75)
        return true,'top'
      end
    end
  end
	------Left side
	if collision.vertex.X == size.X and collision.vertex.Y == 0 then
		if slope == 0 then
			object.velocity = Vector2.new(0,object.velocity.Y)
			object.position = Vector2.new(collision.position.X-size.X,object.position.Y)
			return true,'left'
		else
			local y = slope*object.position.X+offset
			if y >= collision.position.Y and y <= collision.position.Y+100 then
				object.velocity = Vector2.new(0,object.velocity.Y)
				object.position = Vector2.new(collision.position.X-size.X,object.position.Y)
				return true,'left'
			end
		end
	end
	------Right side
	if collision.vertex.X == 0 and collision.vertex.Y == 0 then
		if slope == 0 then
			object.velocity = Vector2.new(0,object.velocity.Y)
			object.position = Vector2.new(collision.position.X,object.position.Y)
			return true,'right'
		else
			local y = slope*object.position.X+offset
			if y >= collision.position.Y and y <= collision.position.Y+100 then
				object.velocity = Vector2.new(0,object.velocity.Y)
				object.position = Vector2.new(collision.position.X+100,object.position.Y)
				return true,'right'
			end
		end
	end
	return false
end
 
 
physics.run = function()
	--player variables
	physics.objects.player.velocity = physics.objects.player.velocity-Vector2.new(0,1)
	physics.objects.player.velocity = physics.objects.player.velocity+physics.objects.player.staticVelocity
	Camera = Camera+physics.objects.player.velocity
	local globalPlayerPosition = Vector2.new(Camera.X*-1,Camera.Y*-1)+Vector2.new(screenSize.X/2,375)
	physics.objects.player.position = globalPlayerPosition
	local collisions = physics.getCollisions(globalPlayerPosition,Vector2.new(50,75))
	for i,v in pairs(collisions) do
		local rep = false
    local side
    repeat
      rep,side = physics.reactToCollision(v,physics.objects.player,physics.objects.player.position-physics.objects.player.velocity,Vector2.new(50,75))
      if side ~= 'top' and rep then
        print(rep,side)
      end
    until not rep
  end
  Camera = (physics.objects.player.position-Vector2.new(screenSize.X/2,375))*-1
  if physics.objects.player.velocity.X ~= 0 then
    physics.objects.player.velocity = physics.objects.player.velocity-physics.objects.player.staticVelocity
  end
end
Post Reply

Who is online

Users browsing this forum: Roland Chastain, slime and 194 guests