Hello there,
In a 2d top down game im working on, a player picks up items off the ground, they animate moving to the player before disappearing via remove(). I noticed a bug recently where sometimes parts of the sprite of the item on the ground still render in the place it dropped after the item is picked up. It will disappear upon the player moving, which triggers the whole scene to update due to camera implementation.
One thing i thought it might be is the "miss" text as that was a recent change, but after removing that feature the bug still occurs.
The sprite itself is relatively simple:
class('ItemDrop').extends(gfx.sprite)
local pickupVelocity = 4
function ItemDrop:init(item)
self:setTag(ITEM_DROP_TAG)
local frame = item.animation:image()
self.item = item
self:setSize(frame.width, frame.height)
self:setCollideRect(0, 0, self:getSize())
self:setCollidesWithGroups({ITEM_DROP_GROUP})
self:setGroups(ITEM_DROP_GROUP)
self.isPickedUp = false
end
function ItemDrop:update()
self:setImage(self.item.animation:image())
if self.isPickedUp then
local dirX = self.pickupTarget.x - self.x
local dirY = self.pickupTarget.y - self.y
local x = pickupVelocity
local y = pickupVelocity
if math.abs(dirX) < x then
x = dirX
elseif dirX < 0 then
x = x * -1
end
if math.abs(dirY) < y then
y = dirY
elseif dirY < 0 then
y = y * -1
end
self:moveBy(x, y)
if self.x == self.pickupTarget.x and self.y == self.pickupTarget.y then
self:remove()
inventory_addItem(self.item)
end
else
local overlappingSprites = self:overlappingSprites()
for _, sprite in pairs(overlappingSprites) do
if sprite:getTag() == ITEM_DROP_TAG then
local r1 = self:getCollideRect()
r1.x = r1.x + self.x
r1.y = r1.y + self.y
local r2 = sprite:getCollideRect()
r2.x = r2.x + sprite.x
r2.y = r2.y + sprite.y
local intersection = r1:intersection(r2)
local x1 = math.random(2, 4)
local x2 = math.random(2, 4)
local y1 = math.random(2, 4)
local y2 = math.random(2, 4)
self:moveBy(intersection.width / 2 + x1, intersection.height / 2 + y1)
sprite:moveBy(-(intersection.width / 2 + x2), -(intersection.height / 2 + y2))
end
end
end
end
function ItemDrop:print()
local type = ''
if self.item.type == WEAPON_ITEM then
type = 'Weapon'
elseif self.item.type == ARMOR_ITEM then
type = 'Armor'
elseif self.item.type == SHIELD_ITEM then
type = 'Shield'
elseif self.item.type == POTION_ITEM then
type = 'Potion'
end
print('Dropped', type, self.x, self.y)
end
function ItemDrop:getRect()
local rect = self:getCollideRect()
rect.x = rect.x + self.x
rect.y = rect.y + self.y
return rect
end
function ItemDrop:pickedUpBy(x, y)
self.isPickedUp = true
self.pickupTarget = playdate.geometry.vector2D.new(x, y)
self:clearCollideRect()
end
Here's a screenshot where you can see the full sword close the player, and the bits of the hilt below them:
Likewise here's the full video: Playdate update bug - YouTube