How to tell if certain objects are colliding/hitboxes?

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
Bya
Prole
Posts: 20
Joined: Sat Sep 06, 2014 4:24 am

How to tell if certain objects are colliding/hitboxes?

Post 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
Bya
Prole
Posts: 20
Joined: Sat Sep 06, 2014 4:24 am

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

Post 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.
User avatar
Plu
Inner party member
Posts: 722
Joined: Fri Mar 15, 2013 9:36 pm

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

Post 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.
Bya
Prole
Posts: 20
Joined: Sat Sep 06, 2014 4:24 am

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

Post 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?
User avatar
Plu
Inner party member
Posts: 722
Joined: Fri Mar 15, 2013 9:36 pm

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

Post 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.
Bya
Prole
Posts: 20
Joined: Sat Sep 06, 2014 4:24 am

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

Post by Bya »

That worked perfectly, thank you!
Post Reply

Who is online

Users browsing this forum: Bing [Bot] and 2 guests