Basically trying to have the .love file linked below as is but with the squares that make up the "map" all being able to be "jumped" on, rather than merely the last/ most recently created. I'm certain that this will already have been asked about and solved somewhere but I can't find anything after an hour of searching.
Also there seems to be a collision thing while walking along the squares that decides to detect a collision sometimes at the border between two, is there a simple fix for this or is this a consequence of how it's built? Most controls are in the window title but holding space pauses the game until released also.
And if I'm just being a dope noob as usual about all this feel free to ignore.
True Object Instantiation
Forum rules
Before you make a thread asking for help, read this.
Before you make a thread asking for help, read this.
-
- Prole
- Posts: 17
- Joined: Mon Jul 30, 2012 9:15 pm
True Object Instantiation
- Attachments
-
- Swing Game.love
- (3.86 KiB) Downloaded 54 times
Re: True Object Instantiation
Here's how I've made it. I've set the jumpable bodies' user data to "jumpable", to indicate which bodies can be jumped on. On second thought, maybe I could have used the fixtures, but it's OK like this if you have just one fixture per body.
I also got rid of objects.square which isn't very helpful. The loop for the platform shapes now looks like this:
Note the body:setUserData("jumpable").
And this is how the jump key handler ended up looking like:
Basically, go through all the contacts to see if one of the contacts is with a fixture whose body is marked as jumpable, and has a normal that makes sense for a ground jump. Note that this check disables the ability to jump on walls; if you want that, you'll have to change the normal check.
The getting stuck on borders is a common problem, even more with Box2D. I've tried making a capsule-shaped player, but then you get small bounces:
Code: Select all
objects.ground.body:setUserData("jumpable")
Code: Select all
for y=1, #map do
for x=1, #map[y] do
if map[y][x] == 1 then
local body = love.physics.newBody(world,(x * 64) - 32 , (y * 64) - 32) --Creates the square body objects to create the map
body:setUserData("jumpable")
local shape = love.physics.newRectangleShape(64, 64) --Creates the square shape of size X=64, Y=64
love.physics.newFixture(body, shape, 1) --Fixes the square body and shape together
end
end
end
And this is how the jump key handler ended up looking like:
Code: Select all
if love.keyboard.isDown("w") then
local canJump = false
if objects.rectangle.body:isTouching(objects.ground.body) then
-- TODO: check normal
canJump = true
else
local contacts = objects.rectangle.body:getContacts()
for k,v in pairs(contacts) do
if v:isTouching() then
local f1, f2 = v:getFixtures()
local nx, ny = v:getNormal()
local groundCheck = ny < 0
local b = f1:getBody()
if b == objects.rectangle.body then
b = f2:getBody()
groundCheck = ny > 0
end
if b:getUserData() == "jumpable" then
if groundCheck and nx == 0 then
canJump = true
break
end
end
end
end
end
if canJump then
objects.rectangle.body:applyForce(0, -800)
end
end
The getting stuck on borders is a common problem, even more with Box2D. I've tried making a capsule-shaped player, but then you get small bounces:
Code: Select all
objects.rectangle.shape1 = love.physics.newRectangleShape(14, 16) --Creates the rectangle shape of size X=20, Y=50
objects.rectangle.shape2 = love.physics.newCircleShape(0, -8, 8) --Creates the circle shape of radius 8
objects.rectangle.shape3 = love.physics.newCircleShape(0, 8, 8) --Creates the circle shape of radius 8
objects.rectangle.fixt1 = love.physics.newFixture(objects.rectangle.body, objects.rectangle.shape1, 1) --Fixes the rectangle body and shape together
objects.rectangle.fixt2 = love.physics.newFixture(objects.rectangle.body, objects.rectangle.shape2, 1) --Fixes the circle shape and body together
objects.rectangle.fixt3 = love.physics.newFixture(objects.rectangle.body, objects.rectangle.shape3, 1) --Fixes the circle shape and body together
-
- Prole
- Posts: 17
- Joined: Mon Jul 30, 2012 9:15 pm
Re: True Object Instantiation
This is all wicked, and solves more problems than I had even asked for help with! I had thought to just cap the sides of anything I didn't want walljumpable, but this solves that without any caveat, and wouldn't leave some horrible jump blocking zone at the side of any platform.
I'm just going over everything now since obviously draw functions won't work if this was all just Ctrl+C, Ctrl+V'd in, and I'm intent on understanding how it all works to write better code in future.
The assist is super appreciated, really can't thank you enough.
I'm just going over everything now since obviously draw functions won't work if this was all just Ctrl+C, Ctrl+V'd in, and I'm intent on understanding how it all works to write better code in future.
The assist is super appreciated, really can't thank you enough.
Re: True Object Instantiation
Sorry, I wasn't too careful. The first check (the check for the platform) is unnecessary. I started with that but then decided to go with UserData to detect jumpable fixtures, and didn't remove that part.
This is how it looks like after fixing that:
And yes, by all means, try to understand the code. I outlined the intent already, but since there aren't any comments, you might have a bit more difficulty following it. Hopefully it will be straightforward.
One problem that is taken care of, and that may be obfuscating the code a bit, is that you don't know which of the two returned fixtures belongs to the player. You want to check the fixture that isn't the player, to see if it's jumpable.
Then there's the normal, which always points from the first fixture to the second one, therefore if we get the player as the first fixture, the normal must point down (y > 0) in order to be able to jump, and if the player is the second, the first fixture will be the ground and it needs to point up (y < 0), towards the player, to allow jumping.
This is how it looks like after fixing that:
Code: Select all
if love.keyboard.isDown("w") then
local canJump = false
local contacts = objects.rectangle.body:getContacts()
for k,v in pairs(contacts) do
if v:isTouching() then
local f1, f2 = v:getFixtures()
local nx, ny = v:getNormal()
local groundCheck = ny < 0
local b = f1:getBody()
if b == objects.rectangle.body then
b = f2:getBody()
groundCheck = ny > 0
end
if b:getUserData() == "jumpable" then
if groundCheck and nx == 0 then
canJump = true
break
end
end
end
end
if canJump then
objects.rectangle.body:applyForce(0, -800)
end
end
One problem that is taken care of, and that may be obfuscating the code a bit, is that you don't know which of the two returned fixtures belongs to the player. You want to check the fixture that isn't the player, to see if it's jumpable.
Then there's the normal, which always points from the first fixture to the second one, therefore if we get the player as the first fixture, the normal must point down (y > 0) in order to be able to jump, and if the player is the second, the first fixture will be the ground and it needs to point up (y < 0), towards the player, to allow jumping.
Who is online
Users browsing this forum: slime and 6 guests