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.
[SOLVED] Simple Physics help.
Forum rules
Before you make a thread asking for help, read this.
Before you make a thread asking for help, read this.
[SOLVED] Simple Physics help.
Last edited by FlashFire on Sun Sep 14, 2014 9:38 pm, edited 1 time in total.
-
- Prole
- Posts: 19
- Joined: Sat Sep 06, 2014 8:50 pm
Re: Simple Physics help.
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
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.
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
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.
Re: Simple Physics help.
Hey I have a few suggestions.
First, when get a lot of nesting like this:
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)".
http://gamedevelopment.tutsplus.com/tut ... amedev-169
More specifically, take a look at AABB vs AABB intersection:
http://www.opentk.com/node/869
First, when get a lot of nesting like this:
Code: Select all
end
end
end
end
end
end
end
end
end
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)".
I think your case is ideal for the "separating axis theorem":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.
http://gamedevelopment.tutsplus.com/tut ... amedev-169
More specifically, take a look at AABB vs AABB intersection:
http://www.opentk.com/node/869
Re: Simple Physics help.
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
Who is online
Users browsing this forum: Bing [Bot], Google [Bot] and 2 guests