Page 1 of 1

How to tell if certain objects are colliding/hitboxes?

Posted: Tue Sep 09, 2014 10:21 am
by Bya
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.
Image

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.

Image

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

Re: How to tell if certain objects are colliding/hitboxes?

Posted: Tue Sep 09, 2014 12:08 pm
by Bya
I've actually been able to determine whether or not the two objects are colliding by the following code:

Code: Select all

function beginContact(a, b, coll)
    if a == player.f then
		--text = text.."?????"
		if b == enemy.f then
			text = text.."CONTACT"
			end
			end
			
	x,y = coll:getNormal() 
    text = text.."\n"..a:getUserData().." colliding with "..b:getUserData().." with a vector normal of: "..x..", "..y
end
The hitbox question, however, is still a mystery to me.

Re: How to tell if certain objects are colliding/hitboxes?

Posted: Tue Sep 09, 2014 12:21 pm
by Plu
I can't really do a detailed debug right now, but you are aware that images are by default drawn with their X,Y in the top-left corner, while physics bodies by default are calculated with X,Y as the center of the hitbox?

This is something that will cause the sort of things that you're seeing right now if you're not taking it into account.

Re: How to tell if certain objects are colliding/hitboxes?

Posted: Tue Sep 09, 2014 12:35 pm
by Bya
Plu wrote:I can't really do a detailed debug right now, but you are aware that images are by default drawn with their X,Y in the top-left corner, while physics bodies by default are calculated with X,Y as the center of the hitbox?

This is something that will cause the sort of things that you're seeing right now if you're not taking it into account.
I was not aware of that. Is there a way to readjust where the center is?

Re: How to tell if certain objects are colliding/hitboxes?

Posted: Tue Sep 09, 2014 1:11 pm
by Plu
For images, you can use the offset variable:

Code: Select all

love.graphics.draw( image, x, y, 0, 1, 1, image:getWidth()/2, image:getHeight()/2 )
It's best to encapsulate that in your entities somewhere.

For physics-objects, I'm not sure if it's possible.

Re: How to tell if certain objects are colliding/hitboxes?

Posted: Tue Sep 09, 2014 1:50 pm
by Bya
That worked perfectly, thank you!