1.1
BIN
gfx/button-table-114-32.png
Normal file
After Width: | Height: | Size: 888 B |
BIN
gfx/cart.png
Normal file
After Width: | Height: | Size: 232 B |
BIN
gfx/comic.png
Normal file
After Width: | Height: | Size: 5.3 KiB |
BIN
gfx/enemy-table-30-48.png
Normal file
After Width: | Height: | Size: 526 B |
BIN
gfx/floor.png
Normal file
After Width: | Height: | Size: 152 B |
21
gfx/font.fnt
Normal file
|
@ -0,0 +1,21 @@
|
|||
--metrics={"baseline":-2,"xHeight":8,"capHeight":2,"pairs":{},"left":[],"right":[]}
|
||||
datalen=1552
|
||||
data=iVBORw0KGgoAAAANSUhEUgAAAGAAAABICAYAAAAJZ/BjAAAEUklEQVR4Xu1d23LrMAg8+f+PPu24sUciQssiUJwMeWkT2UhiYbnIaR//nq//v6/z99nPx+/Lcp12jTZPlly5DnYeq17OeVj5lzKtE7ETSAUUAL1GHlIhmoFLB2GB0OY55bLyNM+NXv+5buT4Xv0UAIBPtwFwIjxAslsia7HIw1h5GqVp62+4+fiVnY+gZpf8ywMKgLErfA0AEuDBe1d2hYK6pBDWA1DGtyp/mwcUAGMotwEwyMddnIks0hojvFlXtPwCgEVUXJ9GQdmUERUDkP5WFWTtFHj3o3pAAdBDi7KhAkChhtU6QHpAdKX9tR4Q3fpAFfFyK0Iiq1XEq3l0FCdbu62TApOqO7ZRUONy3R69HBedtlmDrkY9zecFgKc3s9vyrYB7DfQlBnyqByDO91r+xwMw6dV0lfCgUjZRhFXxUfI1QG7rAQXA3IfSD2RQ+jYI0sdH1l7NXeQvp6Eya9AUw3LpXRQkY1s0wG4ArL0OVvGs3GyO3iXfCuylT1ZR7ASogJkENVcQRlkLa0js+ln9vMQAtAF2AnYDrIJYA2LlZ6+/AAAWtw0AdCjv7QHtCsIoicgOwl755hOxAsAUkujHXrYDINO1qCCMngvKzoLCKuHoNrTWfo4K9rvkG9Z7XMIyxds8gM2mNAVkny+w87JZVgGATFsZR55nNbC3AbDK/TL/t8YAq2KQ5cusi6We634Dki5u26UgtH5v8L0tACzHTTi626O3mWWtM7zyJRAIcNbDaAoqAP6+yhV12K8eSU5c8BiyIq1ZaFS6iywyiqtlS8Kb979QotWFG04vAAYeYDVIFYBJVtIFYS8FoWzPa1GoDkDjaF3WZKIAeH57VqaDtwcApVtey5SWo6WDqwpC96Nx5AFZ3H8xSQEwh+BrAECVqtfTsrMgJN/L/ds9oAAYe5p6yrDKnVoMiH6+XqOIQQXbfWS13Cg9qFnm7hhQAPQahx6gZS8oexhYYOpfY5GeMKlrbGeLTwGaXKsHIT0VAEBD2wDIsiBUD0R5GLK0rPFVgLb9vaBsgLMUjOQuA7Ari2h6SMM9RfXrkcKixlGB1ux3GnO2PZ5eACh1AKr0pOJkswtZVLZ8NH/0eDRjwBOxAqCHcBsAZ567Wgmi+9F4tAV75Vk5XzNYLSbMvil/BI9VBaH70bhXYdH3FQDRGjXKQ5TTxMRDonzf1EHdjCfDlAcAIN4GgFzXXfv1RkN2XyYpEgnSPEB6AvSAAuBPA9sAkNFbAuCtVJELa/NEdRuRxaJx6/qtli+zodtUwpqLIgVlj28DIOvIsFHs9DzAG2OyAdDWrx0sscyRXgkXAL3dSWpNT0ORhX5KIYY8QasHJOe/JDdIAWgcKRiNZ8tH87PjqCJmn5pOpyC5YG3Dd48BA27vuIVV/OUZ2e3iAmD+L1+2paEoa/DWGSyFRF+vGZi1jikAFhFZBsCaJqJoru3DSkFe+Yv6e/vt6U9FFABzjH8AeebksrVI2isAAAAASUVORK5CYII=
|
||||
width=24
|
||||
height=24
|
||||
|
||||
tracking=1
|
||||
|
||||
0 22
|
||||
1 12
|
||||
2 12
|
||||
3 12
|
||||
4 12
|
||||
5 12
|
||||
6 12
|
||||
7 12
|
||||
8 12
|
||||
9 12
|
||||
space 22
|
||||
<EFBFBD> 20
|
||||
|
BIN
gfx/logo.png
Normal file
After Width: | Height: | Size: 3.4 KiB |
BIN
gfx/player-table-34-42.png
Normal file
After Width: | Height: | Size: 559 B |
BIN
gfx/security.png
Normal file
After Width: | Height: | Size: 533 B |
BIN
gfx/square-table-22-22.png
Normal file
After Width: | Height: | Size: 585 B |
BIN
launcher/card.png
Normal file
After Width: | Height: | Size: 3.3 KiB |
346
main.lua
Normal file
|
@ -0,0 +1,346 @@
|
|||
-- PossiblyAxolotl
|
||||
-- June 24th, 2022 to June 27th, 2022
|
||||
-- Shopping spree
|
||||
|
||||
-- I am well aware that if you are touching an enemy and item at the same time no collision is counted
|
||||
-- I am simply lazy and there's not enough jam time left to fix it
|
||||
|
||||
-- IMPORTS
|
||||
import "CoreLibs/ui"
|
||||
import "CoreLibs/animation"
|
||||
import "CoreLibs/sprites"
|
||||
import "CoreLibs/math"
|
||||
import "CoreLibs/graphics"
|
||||
|
||||
local gfx <const> = playdate.graphics
|
||||
|
||||
-- sprites
|
||||
local tSquare = gfx.imagetable.new("gfx/square")
|
||||
local tPlayer = gfx.imagetable.new("gfx/player")
|
||||
local tEnemy = gfx.imagetable.new("gfx/enemy")
|
||||
local tButton = gfx.imagetable.new("gfx/button")
|
||||
local imgCart = gfx.image.new("gfx/cart")
|
||||
local imgLogo = gfx.image.new("gfx/logo")
|
||||
local imgTile = gfx.image.new("gfx/floor")
|
||||
local imgSecurity = gfx.image.new("gfx/security")
|
||||
local imgComic = gfx.image.new("gfx/comic")
|
||||
assert(tSquare)
|
||||
assert(tPlayer)
|
||||
assert(tEnemy)
|
||||
assert(tButton)
|
||||
assert(imgCart)
|
||||
assert(imgLogo)
|
||||
assert(imgTile)
|
||||
assert(imgSecurity)
|
||||
assert(imgComic)
|
||||
|
||||
local animPlayer = gfx.animation.loop.new(150,tPlayer)
|
||||
local animEnemy = gfx.animation.loop.new(200,tEnemy)
|
||||
local animButton = gfx.animation.loop.new(300,tButton)
|
||||
|
||||
local sprSquare = gfx.sprite.new(tSquare[1])
|
||||
local sprPlayer = gfx.sprite.new()
|
||||
local sprEnemies = gfx.sprite.new()
|
||||
sprSquare:setCollideRect(0,0,18,18)
|
||||
sprPlayer:setCollideRect(6,2,22,34)
|
||||
sprPlayer:setZIndex(2)
|
||||
sprEnemies:setCollideRect(11,18,10,10)
|
||||
sprSquare:add()
|
||||
sprSquare:moveTo(50,50)
|
||||
sprPlayer:add()
|
||||
sprEnemies:add()
|
||||
|
||||
-- sfx
|
||||
local sfxCollect = playdate.sound.sampleplayer.new("sfx/collect")
|
||||
local sfxLose = playdate.sound.sampleplayer.new("sfx/lose")
|
||||
local sfxPlay = playdate.sound.sampleplayer.new("sfx/play")
|
||||
|
||||
local mus = playdate.sound.fileplayer.new("sfx/tree")
|
||||
|
||||
mus:play(0)
|
||||
|
||||
-- enemy vars
|
||||
local enemies = {}
|
||||
local rechargeTime = 80
|
||||
local recharge = 80
|
||||
local enemySpeed = 1
|
||||
local enemyAmount = 1
|
||||
|
||||
-- title vars
|
||||
local titleY = 400 -- -100
|
||||
local titleLerpY = 0
|
||||
|
||||
-- other vars
|
||||
local mode = "comic"
|
||||
|
||||
local yOffset = 240
|
||||
|
||||
local score = 0
|
||||
|
||||
local particles = {}
|
||||
local shake = 0
|
||||
|
||||
local font = gfx.font.new("gfx/font")
|
||||
|
||||
-- OTHER STUFF
|
||||
gfx.setLineWidth(2)
|
||||
gfx.setFont(font)
|
||||
|
||||
|
||||
playdate.graphics.sprite.setBackgroundDrawingCallback(function()
|
||||
gfx.setDrawOffset(0,yOffset)
|
||||
imgTile:drawTiled(0,0,400,240)
|
||||
end)
|
||||
|
||||
local menu = playdate.getSystemMenu()
|
||||
menu:addMenuItem("restart", function() die() end)
|
||||
menu:addCheckmarkMenuItem("night mode", function(value) playdate.display.setInverted(value) end)
|
||||
|
||||
math.randomseed(playdate.getSecondsSinceEpoch())
|
||||
|
||||
playdate.ui.crankIndicator:start()
|
||||
|
||||
--local cubePos = math.rad(math.random(1,359))
|
||||
local cubePos = math.pi
|
||||
local cubeCirc = 0
|
||||
|
||||
function playdate.update()
|
||||
gfx.setDrawOffset(0,0)
|
||||
if mode == "game" then
|
||||
updateGame()
|
||||
elseif mode == "comic" then -- too lazy to move to a different function. screw you.
|
||||
titleY = playdate.math.lerp(titleY,titleLerpY,0.1)
|
||||
imgComic:draw(0,titleY)
|
||||
|
||||
local change = playdate.getCrankChange()
|
||||
titleLerpY -= change
|
||||
if titleLerpY > 0 then titleLerpY = 0 end
|
||||
if titleLerpY < -453 then titleLerpY = -453 end
|
||||
|
||||
if playdate.buttonJustPressed(playdate.kButtonA) then
|
||||
titleLerpY = 0
|
||||
titleY = -100
|
||||
mode = "title"
|
||||
sfxCollect:play()
|
||||
end
|
||||
elseif mode == "title" then
|
||||
updateTitle()
|
||||
end
|
||||
|
||||
processParticles()
|
||||
|
||||
if playdate.isCrankDocked() then
|
||||
playdate.ui.crankIndicator:update()
|
||||
end
|
||||
end
|
||||
|
||||
function collectCube(pos)
|
||||
shake = 5
|
||||
sfxCollect:play()
|
||||
|
||||
sprSquare:setImage(tSquare[math.random(1,#tSquare)])
|
||||
|
||||
spawnParts(sprSquare.x,sprSquare.y)
|
||||
|
||||
score += 1
|
||||
|
||||
local option = score % 3
|
||||
if option == 0 and rechargeTime > 20 then
|
||||
rechargeTime -= .5
|
||||
elseif option == 1 and enemySpeed < 10 then
|
||||
enemySpeed += .3
|
||||
elseif option == 2 and enemyAmount < 6 then
|
||||
enemyAmount += .3
|
||||
end
|
||||
|
||||
cubeCirc = 0
|
||||
cubePos = pos + math.rad(math.random(-45,45) + 180)
|
||||
end
|
||||
|
||||
function updateTitle()
|
||||
gfx.clear()
|
||||
imgLogo:draw(31,imgLogo.height/2+titleY - 40)
|
||||
titleY = playdate.math.lerp(titleY,titleLerpY,0.1)
|
||||
|
||||
if titleLerpY+1 >= titleY then
|
||||
if titleLerpY == -170 then
|
||||
mode = "game"
|
||||
else
|
||||
animButton:draw(143, 200)
|
||||
|
||||
if playdate.buttonJustPressed(playdate.kButtonA) then
|
||||
titleLerpY = -170
|
||||
rechargeTime = 80
|
||||
recharge = 80
|
||||
enemySpeed = 1
|
||||
enemyAmount = 1
|
||||
|
||||
sfxPlay:play()
|
||||
|
||||
cubePos = math.rad(playdate.getCrankPosition() + 180)
|
||||
|
||||
spawnParts(143 + 57,210)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function updateGame()
|
||||
-- UPDATE
|
||||
|
||||
-- set important vars
|
||||
local pos = playdate.getCrankPosition()
|
||||
local change = playdate.getCrankChange()
|
||||
pos = math.rad(pos)
|
||||
|
||||
-- if player is overlapping a square, move it
|
||||
if #sprSquare:overlappingSprites() > 0 then
|
||||
local spr = sprSquare:overlappingSprites()[1]
|
||||
if spr.width == 34 and spr.height == 42 then
|
||||
collectCube(pos)
|
||||
end
|
||||
end
|
||||
|
||||
-- set shake var. yeah
|
||||
if shake > 0 then shake -= .2 elseif shake < 0 then shake = 0 end
|
||||
|
||||
-- spawn enemies
|
||||
recharge -= 1
|
||||
|
||||
if recharge <= 0 then
|
||||
for amnt = 1, math.floor(enemyAmount), 1 do
|
||||
local enemy = {
|
||||
x=180,
|
||||
y=100,
|
||||
dir = math.random(0,359),
|
||||
speed = enemySpeed
|
||||
}
|
||||
enemies[#enemies+1] = enemy
|
||||
end
|
||||
|
||||
recharge = rechargeTime
|
||||
end
|
||||
|
||||
-- DRAW
|
||||
gfx.clear()
|
||||
|
||||
-- smooth transition in + drawing with shake
|
||||
yOffset = playdate.math.lerp(yOffset,0,0.1)
|
||||
|
||||
gfx.setDrawOffset(math.random(-1,1) * shake, math.random(-1,1) * shake + yOffset)
|
||||
|
||||
-- animate
|
||||
if change == 0 then
|
||||
animPlayer.frame = 0
|
||||
end
|
||||
|
||||
sprPlayer:setImage(animPlayer:image())
|
||||
|
||||
-- move sprites
|
||||
local nX, nY = 200 + (math.sin(pos) * 120), 120 - (math.cos(pos) * 70)
|
||||
sprPlayer:moveTo(nX, nY)
|
||||
|
||||
sprSquare:moveTo(200 + (math.sin(cubePos) * 120), 120 - (math.cos(cubePos) * 70))
|
||||
|
||||
-- yeah
|
||||
gfx.sprite.update()
|
||||
|
||||
-- enemy processing and drawing
|
||||
for enemyNo = 1, #enemies, 1 do
|
||||
local enemy = enemies[enemyNo]
|
||||
enemy.x += math.sin(enemy.dir) * enemy.speed
|
||||
enemy.y -= math.cos(enemy.dir) * enemy.speed
|
||||
|
||||
local flipped = playdate.graphics.kImageUnflipped
|
||||
--print(math.sin(enemy.dir))
|
||||
if math.sin(enemy.dir)< -0.01 then
|
||||
flipped = playdate.graphics.kImageFlippedX
|
||||
end
|
||||
|
||||
animEnemy:draw(enemy.x-2,enemy.y, flipped)
|
||||
sprEnemies:moveTo(enemy.x-2,enemy.y)
|
||||
|
||||
-- death
|
||||
if #sprEnemies:overlappingSprites() > 0 and #sprSquare:overlappingSprites() == 0 then
|
||||
die()
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
-- despawn enemies out of camera
|
||||
for enemyNo = 1, #enemies do
|
||||
local enemy = enemies[enemyNo]
|
||||
if enemy.x > 400 or enemy.x < -34 or enemy.y > 240 or enemy.y < -44 then
|
||||
table.remove(enemies,enemyNo)
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
-- draw the circle around items when they spawn
|
||||
if cubeCirc < 32 then
|
||||
cubeCirc += 1
|
||||
gfx.setColor(gfx.kColorXOR)
|
||||
gfx.fillCircleAtPoint(sprSquare.x,sprSquare.y,math.sin(cubeCirc/10) * 19)
|
||||
end
|
||||
|
||||
imgSecurity:draw(200-44,120-40)
|
||||
|
||||
-- overlay
|
||||
gfx.setDrawOffset(0,0)
|
||||
imgCart:draw(2,2)
|
||||
gfx.drawText(score,30,5)
|
||||
end
|
||||
|
||||
function die()
|
||||
-- vars
|
||||
titleLerpY = 0
|
||||
mode = "title"
|
||||
yOffset = 240
|
||||
score = 0
|
||||
|
||||
sfxLose:play()
|
||||
|
||||
-- spawn particles on each enemy + other objects
|
||||
for enemy = 1, #enemies do
|
||||
spawnParts(enemies[enemy].x,enemies[enemy].y)
|
||||
end
|
||||
enemies = {}
|
||||
|
||||
spawnParts(sprPlayer.x,sprPlayer.y)
|
||||
spawnParts(sprSquare.x,sprSquare.y)
|
||||
end
|
||||
|
||||
-- particle functions
|
||||
function spawnParts(_x,_y)
|
||||
for i = 1, 10, 1 do
|
||||
local part = {
|
||||
x = _x,
|
||||
y = _y,
|
||||
dir = math.random(0,359),
|
||||
size = math.random(10,15),
|
||||
speed = math.random(1,3)
|
||||
}
|
||||
particles[#particles+1] = part
|
||||
end
|
||||
end
|
||||
|
||||
function processParticles()
|
||||
gfx.setColor(gfx.kColorBlack)
|
||||
for part = 1, #particles do
|
||||
local particle = particles[part]
|
||||
|
||||
particle.x += math.sin(particle.dir) * particle.speed
|
||||
particle.y -= math.cos(particle.dir) * particle.speed
|
||||
gfx.fillCircleAtPoint(particle.x,particle.y,particle.size)
|
||||
particles[part].size -= .3
|
||||
|
||||
if particles[part].size < 0 then particles[part].size = 0 end
|
||||
end
|
||||
|
||||
for part = 1, #particles do
|
||||
if particles[part].size <= 0.1 then
|
||||
table.remove(particles, part)
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
8
pdxinfo
Normal file
|
@ -0,0 +1,8 @@
|
|||
name=Shopping Spree
|
||||
author=PossiblyAxolotl
|
||||
description=I can't remember exactly what I was looking for, I'm sure if I grab everything one of them will be it!
|
||||
bundleID=com.PossiblyAxolotl.shoppingspree
|
||||
version=1.1
|
||||
buildNumber=1
|
||||
imagePath=launcher
|
||||
contentWarning=This game contains mild amounts of screen shaking and particle effects.
|