I am using Playdate SDK Version 2.5.0 on a Mac.
Alpha collisions are not recognized between a circle and the bottom and right lines of a sprite consisting of four lines that form a square. Alpha collisions are recognized between the circle and the top and left lines. I expect alpha collisions to be recognized between the circle and all lines.
This seems like a bug. Maybe it's caused by an off-by-one error or a mishandled floating point number? Or am I doing something wrong?
Here is a gif showing failed alpha collisions with the bottom and right lines.
Here is a gif showing successful alpha collisions with all lines where the bottom and right lines are brought in by 1 pixel.
Here is the code to reproduce the issue. Replace the line drawing with the commented out line drawing to see alpha collisions with all lines work.
import "CoreLibs/graphics"
local CELL_SIZE <const> = 39
local HALF_CELL_SIZE <const> = CELL_SIZE / 2
local LAST_CELL_PIXEL_INDEX <const> = CELL_SIZE - 1
local COLUMNS <const> = 10
local ROWS <const> = 6
local BOARD_PIXEL_WIDTH <const> = CELL_SIZE * COLUMNS
local BOARD_PIXEL_HEIGHT <const> = CELL_SIZE * ROWS
local BOARD_X <const> = (400 - BOARD_PIXEL_WIDTH) / 2
local BOARD_Y <const> = (240 - BOARD_PIXEL_HEIGHT) / 2
local CELL_X <const> = CELL_SIZE * (COLUMNS - 1)
local CELL_Y <const> = CELL_SIZE * (ROWS - 1)
local CELL_RIGHT <const> = CELL_X + LAST_CELL_PIXEL_INDEX
local CELL_ALMOST_RIGHT <const> = CELL_RIGHT - 1
local CELL_BOTTOM <const> = CELL_Y + LAST_CELL_PIXEL_INDEX
local CELL_ALMOST_BOTTOM <const> = CELL_BOTTOM - 1
local PLAYER_SIZE <const> = 14
local PLAYER_X <const> = CELL_X + BOARD_X + HALF_CELL_SIZE
local PLAYER_Y <const> = CELL_Y + BOARD_Y + HALF_CELL_SIZE
local MOVE_SPEED <const> = 1
local REPORT_X <const> = 400 - CELL_SIZE
local REPORT_Y <const> = 200 - CELL_SIZE - PLAYER_SIZE
local playerImage <const> = playdate.graphics.image.new(PLAYER_SIZE, PLAYER_SIZE)
local playerSprite <const> = playdate.graphics.sprite.new(playerImage)
local boardImage <const> = playdate.graphics.image.new(BOARD_PIXEL_WIDTH, BOARD_PIXEL_HEIGHT, playdate.graphics.kColorClear)
local boardSprite <const> = playdate.graphics.sprite.new(boardImage)
playdate.graphics.pushContext(playerImage)
playdate.graphics.fillCircleInRect(0, 0, PLAYER_SIZE, PLAYER_SIZE)
playdate.graphics.popContext()
playdate.graphics.pushContext(boardImage)
playdate.graphics.drawLine(CELL_X, CELL_Y, CELL_RIGHT, CELL_Y)
playdate.graphics.drawLine(CELL_RIGHT, CELL_Y, CELL_RIGHT, CELL_BOTTOM)
playdate.graphics.drawLine(CELL_RIGHT, CELL_BOTTOM, CELL_X, CELL_BOTTOM)
playdate.graphics.drawLine(CELL_X, CELL_BOTTOM, CELL_X, CELL_Y)
-- playdate.graphics.drawLine(CELL_X, CELL_Y, CELL_ALMOST_RIGHT, CELL_Y)
-- playdate.graphics.drawLine(CELL_ALMOST_RIGHT, CELL_Y, CELL_ALMOST_RIGHT, CELL_ALMOST_BOTTOM)
-- playdate.graphics.drawLine(CELL_ALMOST_RIGHT, CELL_ALMOST_BOTTOM, CELL_X, CELL_ALMOST_BOTTOM)
-- playdate.graphics.drawLine(CELL_X, CELL_ALMOST_BOTTOM, CELL_X, CELL_Y)
playdate.graphics.popContext()
boardSprite:setCenter(0, 0)
boardSprite:setCollideRect(0, 0, BOARD_PIXEL_WIDTH, BOARD_PIXEL_HEIGHT)
boardSprite:moveTo(BOARD_X, BOARD_Y)
boardSprite:add()
playerSprite:setCollideRect(0, 0, PLAYER_SIZE, PLAYER_SIZE)
playerSprite:moveTo(PLAYER_X, PLAYER_Y)
playerSprite:add()
playdate.graphics.setColor(playdate.graphics.kColorClear)
function playdate.update()
local dx = 0
local dy = 0
if playdate.buttonIsPressed(playdate.kButtonLeft) then
dx -= MOVE_SPEED
end
if playdate.buttonIsPressed(playdate.kButtonRight) then
dx += MOVE_SPEED
end
if playdate.buttonIsPressed(playdate.kButtonUp) then
dy -= MOVE_SPEED
end
if playdate.buttonIsPressed(playdate.kButtonDown) then
dy += MOVE_SPEED
end
playerSprite:moveBy(dx, dy)
playdate.graphics.sprite.update()
local overlappingSprites <const> = playerSprite:overlappingSprites()
local alpha = false
for i = 1, #overlappingSprites do
if playerSprite:alphaCollision(overlappingSprites[i]) then
alpha = true
end
end
playdate.graphics.drawText(tostring(alpha), REPORT_X, REPORT_Y)
end