How to tell if certain objects are colliding/hitboxes?
Posted: Tue Sep 09, 2014 10:21 am
Hey there, I have two problems that I've been trying to figure out so far. I've got a player character who is input controlled, and an "enemy" character who is "built" the same way as the player character. I used the CollisionCallback Physics tutorial on the main page, and while the engine does tell me when anything collides, I want to be able to write a function that executes code when two specific entities collide. For instance, if the player and the enemy collide, I want to either decrease the player's health, or the enemy's health. I don't know the syntax to do that, however.
My second problem is that the "hitboxes", for lack of a better term, seem to be off with my player character (and on a lesser extent, the enemy character.) I have a premade sprite, shown below.
As you can see, the collisions seem to be off. I'm thinking that maybe the game interprets the character's center as being right at the top of its head, as it can phase through the top of the rectangle but not the bottom, and the sides seem to be off as well, as the player knocks the little guy (the enemy) off without actually touching him. I'd like for the hitbox of the player character to just be the center section, as in, from their feet to the top of their head, so a slim rectangle, but I don't know how I would go about doing that. My code is below: thank you for your help.
My second problem is that the "hitboxes", for lack of a better term, seem to be off with my player character (and on a lesser extent, the enemy character.) I have a premade sprite, shown below.
As you can see, the collisions seem to be off. I'm thinking that maybe the game interprets the character's center as being right at the top of its head, as it can phase through the top of the rectangle but not the bottom, and the sides seem to be off as well, as the player knocks the little guy (the enemy) off without actually touching him. I'd like for the hitbox of the player character to just be the center section, as in, from their feet to the top of their head, so a slim rectangle, but I don't know how I would go about doing that. My code is below: thank you for your help.
Code: Select all
function love.load()
playerimage = love.graphics.newImage("KnightIdle.gif")
playerrun = love.graphics.newImage("KnightRunRight.gif")
playerattack = love.graphics.newImage("KnightStab.gif")
playerjump = love.graphics.newImage("KnightJump.gif")
brick = love.graphics.newImage("Brick.png")
--playerrun1 = love.graphics.newImage("KnightRunRight1.png")
--playerrun2 = love.graphics.newImage("KnightRunRight2.png")
--playeridle1 = love.graphics.newImage("KnightIdle1.png")
--playeridle2 = love.graphics.newImage("KnightIdle2.png")
tempenemyimage = love.graphics.newImage("fighter.gif")
--x = 50
--y = 50
speed = 300
health = 10
--physics engine below
love.physics.setMeter(64)
world = love.physics.newWorld(0, 200, true)
world:setCallbacks(beginContact, endContact, preSolve, postSolve)
text = ""
persisting = 0
player = {}
player.b = love.physics.newBody(world, 400, 200, "dynamic")
player.b:setMass(10)
player.s = love.physics.newRectangleShape(32,54)
player.f = love.physics.newFixture(player.b, player.s)
player.f:setRestitution(0.4)
player.f:setUserData("Knight")
player.x = 50;
player.y = 50;
enemy = {}
enemy.b = love.physics.newBody(world, 300, 200, "dynamic")
enemy.b:setMass(10)
enemy.s = love.physics.newCircleShape(20)
enemy.f = love.physics.newFixture(enemy.b, enemy.s)
enemy.f:setRestitution(0.4)
enemy.f:setUserData("Enemy")
static = {}
static.b = love.physics.newBody(world, 325, 650, "static")
static.s = love.physics.newRectangleShape(650,5)
static.f = love.physics.newFixture(static.b, static.s)
static.f:setUserData("Floor")
leftwall = {}
leftwall.b = love.physics.newBody(world, 0, 325, "static")
leftwall.s = love.physics.newRectangleShape(5, 650)
leftwall.f = love.physics.newFixture(leftwall.b, leftwall.s)
leftwall.f:setUserData("LeftWall")
rightwall = {650, 325}
rightwall.b = love.physics.newBody(world, 650, 325, "static")
rightwall.s = love.physics.newRectangleShape(5, 650)
rightwall.f = love.physics.newFixture(rightwall.b, rightwall.s)
rightwall.f:setUserData("RightWall")
ceiling = {}
ceiling.b = love.physics.newBody(world, 325, 0, "static")
ceiling.s = love.physics.newRectangleShape(650, 5)
ceiling.f = love.physics.newFixture(ceiling.b, ceiling.s)
ceiling.f:setUserData("Ceiling")
love.graphics.setBackgroundColor(104, 136, 248)
love.window.setMode(650,650)
end
function beginContact(a, b, coll)
x,y = coll:getNormal()
text = text.."\n"..a:getUserData().." colliding with "..b:getUserData().." with a vector normal of: "..x..", "..y
end
function beginPlayerEnemyContact(player, enemy, coll)
x,y = coll:getNormal()
text = "!!!!!!!"
text = text.."\n"..a:getUserData().." uncolliding with "..b:getUserData()
end
function endPlayerEnemyContact(player, enemy, coll)
persisting = 0
text = text.."\n"..a:getUserData().." uncolliding with "..b:getUserData()
end
function endContact(a, b, coll)
persisting = 0
text = text.."\n"..a:getUserData().." uncolliding with "..b:getUserData()
end
function preSolve(a, b, coll)
if persisting == 0 then -- only say when they first start touching
text = text.."\n"..a:getUserData().." touching "..b:getUserData()
elseif persisting < 20 then -- then just start counting
text = text.." "..persisting
end
persisting = persisting + 1 -- keep track of how many updates they've been touching for
end
function postSolve(a, b, coll, normalimpulse1, tangentimpulse1, normalimpulse2, tangentimpulse2)
end
function love.update(dt)
world:update(dt)
if
if love.keyboard.isDown("right") then
player.b:applyForce(500, 0)
playerimage = love.graphics.newImage("KnightRunRight.gif")
elseif love.keyboard.isDown("left") then
player.b:applyForce(-500, 0)
playerimage = love.graphics.newImage("KnightRunRight.gif")
end
if love.keyboard.isDown("up") then
player.b:applyForce(0, -100)
enemy.b:applyForce(0, -100)
playerimage = love.graphics.newImage("KnightJump.gif")
elseif love.keyboard.isDown("down") then
player.b:applyForce(0, 50)
playerimage = love.graphics.newImage("KnightIdle.gif")
end
if love.keyboard.isDown("x") then
playerimage = love.graphics.newImage("KnightStab.gif")
end
if string.len(text) > 768 then
text = ""
end
end
function love.draw()
love.graphics.print(text, 10, 10)
love.graphics.draw(playerimage, player.b:getX(),player.b:getY())
love.graphics.draw(tempenemyimage, enemy.b:getX(),enemy.b:getY())
love.graphics.polygon("line", static.b:getWorldPoints(static.s:getPoints()))
love.graphics.polygon("line", leftwall.b:getWorldPoints(leftwall.s:getPoints()))
love.graphics.polygon("line", rightwall.b:getWorldPoints(rightwall.s:getPoints()))
love.graphics.polygon("line", ceiling.b:getWorldPoints(ceiling.s:getPoints()))
--love.graphics.draw(brick, static.b:getWorldPoints(static.s:getPoints()))
end