Hitbox

Hey everyone
I am currently doing a game, everything is going well so far, but I’ve found myself in a problem, i am trying to make a rectangular hitbox for a boat, and it works fine when it is at 90 degrees, but when it turns i am having problems with the hitbox, i kinda solved this issue with "vec2(bullet.x,bullet.y):dist(Enemy.pos) < 45"but this creates a circular hitbox and not a rectangular one :(, here i put a failed approach i tried, maybe i am doing something wrong, if anyone could help me i would thank you a lot :slight_smile:

--[[
        local px= Enemy.pos.x
        local py= Enemy.pos.y
        pushMatrix()
        translate(Enemy.pos.x,Enemy.pos.y)
        rotate(Enemy.Angle)
        pushStyle()
        fill(255, 0, 0, 255)
        ellipse(bullet.x-px,bullet.y-py,10) --this is to see the bullets hitbox
        fill(28, 0, 255, 255)
        rectMode(CORNER)
        rect(-22,-54,44,108) --this is to see the boat hitbox
        popStyle()
        if (bullet.x-px) > -22 and (bullet.x-px) < 22 and (bullet.y-py) > -54 and (bullet.y-py) < 54 then
            sound("A Hero's Quest:Drop")
            table.remove(self.shots,i)
            if InfiniteLife == false then
            self.life=self.life-1
            end
        end
        popMatrix()]]

@CarlosSando What you need to do is convert your bullet position to the rotated box position. I haven’t tried doing that so I don’t have an example to share. I’ll look into it but maybe someone else has tried that and will share what they have.

@CarlosSando Here’s an example I put together that allows you to rotate a rectangle using the parameter slider and a bulle coming from the bottom. When the bullet hits the rectangle, it turns the rectangle red and then back to green once the bullet leaves the rectangle. This demonstrates the bullet hitting the rectangle with the rectangle bring in different degrees of rotation. I think this is what you’re after, if not let me know.

function setup()
    rectMode(CENTER)    -- draw rectangle using center position
    cx,cy=WIDTH/2,HEIGHT/2  -- center point of rectangle
    w=100   -- width of rect
    h=50    -- height of rect
    parameter.integer("ang",-180,180,0,calc)    -- change angle of rectangle
    startBullet() -- start bullet position
end

function startBullet()
    mx=math.random((WIDTH//2-50),(WIDTH//2+50))
    my=HEIGHT/2-200
end

function calc() -- calculate rotated corner points of rectangle
    x1,y1=rot(cx-w/2,cy-h/2,ang)
    x2,y2=rot(cx+w/2,cy-h/2,ang)
    x3,y3=rot(cx+w/2,cy+h/2,ang)
    x4,y4=rot(cx-w/2,cy+h/2,ang)
    verts1={vec2(x1,y1),vec2(x2,y2),vec2(x3,y3),vec2(x4,y4)}
end

function rot(x,y,ang)
    theta=math.rad(ang)
    tempX=x-cx
    tempY=y-cy
    rotatedX=tempX*math.cos(theta)-tempY*math.sin(theta)
    rotatedY=tempX*math.sin(theta)+tempY*math.cos(theta)
    return rotatedX+cx,rotatedY+cy
end

function draw()
    background(40, 40, 50)
    
    -- draw rotated rectangle
    pushMatrix()
    fill(255)
    if hit then
        fill(255,0,0)
    end
    translate(cx,cy)
    rotate(ang)
    rect(0,0,w,h)
    popMatrix()
    
    -- draw bullet
    fill(0,255,0)
    ellipse(mx,my,10)     
    checkRect(mx,my)    -- check if bullet is within rectangle
    my=my+2             -- move bullet
    if my>HEIGHT/2+200 then -- draw another bullet
        startBullet()
    end
end

function checkRect(px,py)    -- check if point px,py is within rectangle
    j=#verts1
    hit=false
    for i=1,#verts1 do
        a1=false
        if verts1[i].y>py then
            a1=true
        end
        a2=false
        if verts1[j].y>py then
            a2=true
        end
        b1=verts1[j].x-verts1[i].x
        b2=py-verts1[i].y
        b3=(verts1[j].y-verts1[i].y)
        if a1~=a2 and px<(b1*b2/b3+verts1[i].x) then
            hit=not hit
        end
        j=i
    end 
end

Here’s a rewrite of @dave1707 's code using more vec2s and native functions to shorten it a bit. I also removed a few globals by packaging things into tables.

-- HitBox

function setup()
    rectMode(CENTER)    -- draw rectangle using center position
    box = {
        centre = vec2(WIDTH/2,HEIGHT/2),
        size = vec2(100,50),
        angle = 0
    }
    parameter.integer("ang",-180,180,0,function(a) box.angle = a end)    -- change angle of rectangle
    bullet = startBullet()
end

function startBullet()
    return vec2(math.random((WIDTH//2-50),(WIDTH//2+50)),HEIGHT/2-200)
end

function draw()
    background(40, 40, 50)

    -- draw rotated rectangle
    pushMatrix()
    fill(255)
    if checkRect(box,bullet) then
        fill(255,0,0)
    end
    translate(box.centre.x,box.centre.y)
    rotate(box.angle)
    rect(0,0,box.size.x,box.size.y)
    popMatrix()

    -- draw bullet
    fill(0,255,0)
    ellipse(bullet.x,bullet.y,10)     
    bullet.y = bullet.y + 2           -- move bullet
    if bullet.y>HEIGHT/2+200 then -- draw another bullet
        bullet = startBullet()
    end
end

function checkRect(r,p)    -- check if point p is within rectangle r
    p = (p - r.centre):rotate(-math.rad(r.angle))
    if math.abs(p.x) < r.size.x/2 and math.abs(p.y) < r.size.y/2 then
        return true
    end
    return false
end
1 Like

@LoopSpace I like your checkRect function. I tried something like that to start, but mine didn’t work right all the time. So I took my point inside a polygon routine instead and used that for the rectangle. I’ll have to dig into your function and see why it works.

@LoopSpace I see why your routine worked and mine didn’t. It’s hard to explain what’s happening, but I drew everything that you were doing and I saw what I was doing wrong as I rotated the rectangle. It all makes sense now.