Split crank and button input states.
Add crank-powered cart-launch 😎
This commit is contained in:
parent
03e5ce69cf
commit
edeed9f4d0
28
src/cart.lua
28
src/cart.lua
|
@ -2,19 +2,35 @@ Cart = {}
|
||||||
|
|
||||||
local sizeX, sizeY = CartSprite:getSize()
|
local sizeX, sizeY = CartSprite:getSize()
|
||||||
local size = { x = sizeX, y = sizeY * 0.75 }
|
local size = { x = sizeX, y = sizeY * 0.75 }
|
||||||
|
local secOver90 = 0
|
||||||
|
|
||||||
|
filteredSystem("launchedByCrank", { launchedByCrank = T.marker, crankState = T.CrankState, baseVelocity = T.XyPair }, function(e, dt, system)
|
||||||
|
local change = math.abs(e.crankState.changeInLastHalfSecond)
|
||||||
|
if change > 90 then
|
||||||
|
secOver90 = secOver90 + dt
|
||||||
|
end
|
||||||
|
|
||||||
|
if secOver90 > 0.05 then
|
||||||
|
secOver90 = 0
|
||||||
|
local launchPower = change - 40
|
||||||
|
print("Launch power: " .. launchPower)
|
||||||
|
e.launchedByCrank = nil
|
||||||
|
e.crankState = nil
|
||||||
|
e.velocity = { x = launchPower * e.baseVelocity.x, y = launchPower * e.baseVelocity.y }
|
||||||
|
system.world:addEntity(e)
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
cartSystem = filteredSystem("cart", { isCart = T.marker })
|
cartSystem = filteredSystem("cart", { isCart = T.marker })
|
||||||
|
|
||||||
function Cart.reset(o)
|
function Cart.reset(o)
|
||||||
|
o.launchedByCrank = T.marker
|
||||||
o.isCart = T.marker
|
o.isCart = T.marker
|
||||||
o.position = {
|
o.position = {
|
||||||
x = 20,
|
x = 20,
|
||||||
y = 50,
|
y = 50,
|
||||||
}
|
}
|
||||||
o.velocity = {
|
o.velocity = nil
|
||||||
x = o.baseVelocity.x + (100 * math.random()),
|
|
||||||
y = o.baseVelocity.y * math.random(),
|
|
||||||
}
|
|
||||||
o.size = size
|
o.size = size
|
||||||
o.canBeBounced = {
|
o.canBeBounced = {
|
||||||
flat = { x = 0, y = 0 },
|
flat = { x = 0, y = 0 },
|
||||||
|
@ -52,8 +68,8 @@ function Cart.new()
|
||||||
return setmetatable(
|
return setmetatable(
|
||||||
Cart.reset({
|
Cart.reset({
|
||||||
baseVelocity = {
|
baseVelocity = {
|
||||||
x = 300,
|
x = 2,
|
||||||
y = -170,
|
y = -1,
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
{ __index = Cart }
|
{ __index = Cart }
|
||||||
|
|
28
src/main.lua
28
src/main.lua
|
@ -70,7 +70,8 @@ world:addEntity(floor)
|
||||||
|
|
||||||
local scenarios = {
|
local scenarios = {
|
||||||
default = function()
|
default = function()
|
||||||
world:addEntity(Cart.new())
|
local cart = Cart.new()
|
||||||
|
world:addEntity(cart)
|
||||||
end,
|
end,
|
||||||
manyCollectables = function()
|
manyCollectables = function()
|
||||||
local cart = Cart.new()
|
local cart = Cart.new()
|
||||||
|
@ -86,7 +87,7 @@ local scenarios = {
|
||||||
end,
|
end,
|
||||||
}
|
}
|
||||||
|
|
||||||
scenarios.manyCollectables()
|
scenarios.default()
|
||||||
|
|
||||||
addAllSpawners(world)
|
addAllSpawners(world)
|
||||||
|
|
||||||
|
@ -97,29 +98,6 @@ playdate.setAutoLockDisabled(true)
|
||||||
|
|
||||||
local startMsOffset = -playdate.getCurrentTimeMilliseconds()
|
local startMsOffset = -playdate.getCurrentTimeMilliseconds()
|
||||||
|
|
||||||
-- local maxBatcherLength = 10
|
|
||||||
-- local root = {}
|
|
||||||
-- local physicsGroup = root
|
|
||||||
--
|
|
||||||
-- function append(element)
|
|
||||||
-- if #physicsGroup < maxBatcherLength then
|
|
||||||
-- physicsGroup[#physicsGroup + 1] = element
|
|
||||||
-- else
|
|
||||||
-- physicsGroup = { element }
|
|
||||||
-- root[#root + 1] = physicsGroup
|
|
||||||
-- end
|
|
||||||
-- end
|
|
||||||
--
|
|
||||||
-- for i = 1, 25 do
|
|
||||||
-- append(i)
|
|
||||||
-- end
|
|
||||||
--
|
|
||||||
-- for i = 1, 10 do
|
|
||||||
--
|
|
||||||
-- end
|
|
||||||
--
|
|
||||||
-- printTable(root)
|
|
||||||
|
|
||||||
function playdate.update()
|
function playdate.update()
|
||||||
local deltaSeconds = playdate.getElapsedTime()
|
local deltaSeconds = playdate.getElapsedTime()
|
||||||
playdate.resetElapsedTime()
|
playdate.resetElapsedTime()
|
||||||
|
|
|
@ -7,12 +7,13 @@ local SOME_TABLE <const> = {}
|
||||||
|
|
||||||
---@alias AnyComponent any
|
---@alias AnyComponent any
|
||||||
---@alias BitMask number
|
---@alias BitMask number
|
||||||
|
---@alias ButtonState { receivedInputThisFrame: boolean, aJustPressed: boolean, bJustPressed: boolean, upJustPressed: boolean, downJustPressed: boolean, leftJustPressed: boolean, rightJustPressed: boolean }
|
||||||
---@alias CanBeBounced { flat: XyPair, mult = XyPair }
|
---@alias CanBeBounced { flat: XyPair, mult = XyPair }
|
||||||
---@alias CanSpawn { entityToSpawn: Entity }
|
---@alias CanSpawn { entityToSpawn: Entity }
|
||||||
---@alias Collision { collisionBetween: Entity[] }
|
---@alias Collision { collisionBetween: Entity[] }
|
||||||
|
---@alias CrankState { crankChange: number, changeInLastHalfSecond: number }
|
||||||
---@alias Entity table
|
---@alias Entity table
|
||||||
---@alias InRelations Entity[]
|
---@alias InRelations Entity[]
|
||||||
---@alias InputState { receivedInputThisFrame: boolean, aJustPressed: boolean, bJustPressed: boolean, upJustPressed: boolean, downJustPressed: boolean, leftJustPressed: boolean, rightJustPressed: boolean }
|
|
||||||
---@alias ReplaceRelation { entityToModify: Entity, replacement: table }
|
---@alias ReplaceRelation { entityToModify: Entity, replacement: table }
|
||||||
---@alias RoundStateAction "end" | "start"
|
---@alias RoundStateAction "end" | "start"
|
||||||
---@alias Selectable { additions: Entity[] | nil, replacements: ReplaceRelation[] | nil, highlighted: boolean, navigateDown: Selectable | nil, navigateUp: Selectable | nil }
|
---@alias Selectable { additions: Entity[] | nil, replacements: ReplaceRelation[] | nil, highlighted: boolean, navigateDown: Selectable | nil, navigateUp: Selectable | nil }
|
||||||
|
@ -45,6 +46,9 @@ T = {
|
||||||
---@type BitMask
|
---@type BitMask
|
||||||
BitMask = 0,
|
BitMask = 0,
|
||||||
|
|
||||||
|
---@type ButtonState
|
||||||
|
ButtonState = SOME_TABLE,
|
||||||
|
|
||||||
---@type CanBeBounced
|
---@type CanBeBounced
|
||||||
CanBeBounced = SOME_TABLE,
|
CanBeBounced = SOME_TABLE,
|
||||||
|
|
||||||
|
@ -54,15 +58,15 @@ T = {
|
||||||
---@type Collision
|
---@type Collision
|
||||||
Collision = SOME_TABLE,
|
Collision = SOME_TABLE,
|
||||||
|
|
||||||
|
---@type CrankState
|
||||||
|
CrankState = SOME_TABLE,
|
||||||
|
|
||||||
---@type Entity
|
---@type Entity
|
||||||
Entity = SOME_TABLE,
|
Entity = SOME_TABLE,
|
||||||
|
|
||||||
---@type InRelations
|
---@type InRelations
|
||||||
InRelations = SOME_TABLE,
|
InRelations = SOME_TABLE,
|
||||||
|
|
||||||
---@type InputState
|
|
||||||
InputState = SOME_TABLE,
|
|
||||||
|
|
||||||
---@type ReplaceRelation
|
---@type ReplaceRelation
|
||||||
ReplaceRelation = SOME_TABLE,
|
ReplaceRelation = SOME_TABLE,
|
||||||
|
|
||||||
|
|
|
@ -64,7 +64,8 @@ local SOME_TABLE <const> = {}
|
||||||
CanSpawn = "{ entityToSpawn: Entity }",
|
CanSpawn = "{ entityToSpawn: Entity }",
|
||||||
InRelations = "Entity[]",
|
InRelations = "Entity[]",
|
||||||
CanBeBounced = "{ flat: XyPair, mult = XyPair }",
|
CanBeBounced = "{ flat: XyPair, mult = XyPair }",
|
||||||
InputState = "{ receivedInputThisFrame: boolean, aJustPressed: boolean, bJustPressed: boolean, upJustPressed: boolean, downJustPressed: boolean, leftJustPressed: boolean, rightJustPressed: boolean }",
|
ButtonState = "{ receivedInputThisFrame: boolean, aJustPressed: boolean, bJustPressed: boolean, upJustPressed: boolean, downJustPressed: boolean, leftJustPressed: boolean, rightJustPressed: boolean }",
|
||||||
|
CrankState = "{ crankChange: number, changeInLastHalfSecond: number }",
|
||||||
|
|
||||||
ReplaceRelation = "{ entityToModify: Entity, replacement: table }",
|
ReplaceRelation = "{ entityToModify: Entity, replacement: table }",
|
||||||
Selectable = "{ additions: Entity[] | nil, replacements: ReplaceRelation[] | nil, highlighted: boolean, navigateDown: Selectable | nil, navigateUp: Selectable | nil }",
|
Selectable = "{ additions: Entity[] | nil, replacements: ReplaceRelation[] | nil, highlighted: boolean, navigateDown: Selectable | nil, navigateUp: Selectable | nil }",
|
||||||
|
|
|
@ -1,25 +1,66 @@
|
||||||
local buttonJustPressed = playdate.buttonJustPressed
|
local buttonJustPressed = playdate.buttonJustPressed
|
||||||
|
|
||||||
---@type InputState
|
---@type ButtonState
|
||||||
local inputState = {}
|
local buttonState = {}
|
||||||
|
|
||||||
inputSystem = filteredSystem("input", { canReceiveInput = T.marker }, function(e, _, system)
|
buttonInputSystem = filteredSystem("buttonInput", { canReceiveButtons = T.marker }, function(e, _, system)
|
||||||
e.inputState = inputState
|
e.buttonState = buttonState
|
||||||
system.world:addEntity(e)
|
system.world:addEntity(e)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
function inputSystem:preProcess()
|
function buttonInputSystem:preProcess()
|
||||||
inputState.upJustPressed = buttonJustPressed(playdate.kButtonUp)
|
if #self.entities == 0 then
|
||||||
inputState.downJustPressed = buttonJustPressed(playdate.kButtonDown)
|
return
|
||||||
inputState.rightJustPressed = buttonJustPressed(playdate.kButtonRight)
|
end
|
||||||
inputState.leftJustPressed = buttonJustPressed(playdate.kButtonLeft)
|
buttonState.upJustPressed = buttonJustPressed(playdate.kButtonUp)
|
||||||
inputState.aJustPressed = buttonJustPressed(playdate.kButtonA)
|
buttonState.downJustPressed = buttonJustPressed(playdate.kButtonDown)
|
||||||
inputState.bJustPressed = buttonJustPressed(playdate.kButtonB)
|
buttonState.rightJustPressed = buttonJustPressed(playdate.kButtonRight)
|
||||||
|
buttonState.leftJustPressed = buttonJustPressed(playdate.kButtonLeft)
|
||||||
|
buttonState.aJustPressed = buttonJustPressed(playdate.kButtonA)
|
||||||
|
buttonState.bJustPressed = buttonJustPressed(playdate.kButtonB)
|
||||||
|
|
||||||
inputState.receivedInputThisFrame = inputState.upJustPressed
|
buttonState.receivedInputThisFrame = buttonState.upJustPressed
|
||||||
or inputState.downJustPressed
|
or buttonState.downJustPressed
|
||||||
or inputState.rightJustPressed
|
or buttonState.rightJustPressed
|
||||||
or inputState.leftJustPressed
|
or buttonState.leftJustPressed
|
||||||
or inputState.aJustPressed
|
or buttonState.aJustPressed
|
||||||
or inputState.bJustPressed
|
or buttonState.bJustPressed
|
||||||
|
end
|
||||||
|
|
||||||
|
local crankState = {}
|
||||||
|
|
||||||
|
crankInputSystem = filteredSystem(
|
||||||
|
"crankInput",
|
||||||
|
tiny.requireAny("canReceiveCrank", "launchedByCrank"),
|
||||||
|
function(e, _, system)
|
||||||
|
e.crankState = crankState
|
||||||
|
system.world:addEntity(e)
|
||||||
|
end
|
||||||
|
)
|
||||||
|
|
||||||
|
crankHistory = filteredSystem("crankHistory", { crankChange = T.number, msOccurred = T.number })
|
||||||
|
|
||||||
|
function crankInputSystem:preProcess()
|
||||||
|
if #self.entities == 0 then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
local currentMs = playdate.getCurrentTimeMilliseconds()
|
||||||
|
local crankChange = playdate.getCrankChange()
|
||||||
|
|
||||||
|
self.world:addEntity({
|
||||||
|
crankChange = crankChange,
|
||||||
|
msOccurred = currentMs,
|
||||||
|
})
|
||||||
|
|
||||||
|
local changeInLastHalfSecond = 0
|
||||||
|
for _, v in pairs(crankHistory.entities) do
|
||||||
|
if currentMs - v.msOccurred > 500 then
|
||||||
|
self.world:removeEntity(v)
|
||||||
|
else
|
||||||
|
changeInLastHalfSecond = changeInLastHalfSecond + v.crankChange
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
crankState.crankChange = crankChange
|
||||||
|
crankState.changeInLastHalfSecond = changeInLastHalfSecond
|
||||||
end
|
end
|
||||||
|
|
|
@ -9,11 +9,11 @@ end
|
||||||
|
|
||||||
menuController = filteredSystem(
|
menuController = filteredSystem(
|
||||||
"menuController",
|
"menuController",
|
||||||
{ menuItems = Arr(T.Selectable), inputState = T.InputState },
|
{ menuItems = Arr(T.Selectable), buttonState = T.ButtonState },
|
||||||
function(e, _, system)
|
function(e, _, system)
|
||||||
for _, menuItem in pairs(e.menuItems) do
|
for _, menuItem in pairs(e.menuItems) do
|
||||||
if menuItem.highlighted then
|
if menuItem.highlighted then
|
||||||
if e.inputState.aJustPressed then
|
if e.buttonState.aJustPressed then
|
||||||
-- Prepare to remove the menu and all menu items
|
-- Prepare to remove the menu and all menu items
|
||||||
system.world:removeEntity(e)
|
system.world:removeEntity(e)
|
||||||
for _, item in pairs(e.menuItems) do
|
for _, item in pairs(e.menuItems) do
|
||||||
|
@ -35,13 +35,13 @@ menuController = filteredSystem(
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if e.inputState.downJustPressed and menuItem.navigateDown then
|
if e.buttonState.downJustPressed and menuItem.navigateDown then
|
||||||
menuItem.highlighted = false
|
menuItem.highlighted = false
|
||||||
menuItem.navigateDown.highlighted = true
|
menuItem.navigateDown.highlighted = true
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
if e.inputState.upJustPressed and menuItem.navigateUp then
|
if e.buttonState.upJustPressed and menuItem.navigateUp then
|
||||||
menuItem.highlighted = false
|
menuItem.highlighted = false
|
||||||
menuItem.navigateUp.highlighted = true
|
menuItem.navigateUp.highlighted = true
|
||||||
return
|
return
|
||||||
|
|
|
@ -96,7 +96,7 @@ roundSystem = filteredSystem(
|
||||||
y = y - 50
|
y = y - 50
|
||||||
local menuEntity = {
|
local menuEntity = {
|
||||||
menuItems = {},
|
menuItems = {},
|
||||||
canReceiveInput = T.marker,
|
canReceiveButtons = T.marker,
|
||||||
}
|
}
|
||||||
local upgradeBelow
|
local upgradeBelow
|
||||||
local i = #collectedEntities.entities
|
local i = #collectedEntities.entities
|
||||||
|
|
|
@ -1,25 +1,29 @@
|
||||||
---@generic T
|
---@generic T
|
||||||
---@param shape T
|
---@param shape T | fun()
|
||||||
---@param process fun(entity: T, dt: number, system: System)
|
---@param process fun(entity: T, dt: number, system: System)
|
||||||
---@return System | { entities: T[] }
|
---@return System | { entities: T[] }
|
||||||
function filteredSystem(name, shape, process)
|
function filteredSystem(name, shape, process)
|
||||||
assert(type(name) == "string")
|
assert(type(name) == "string")
|
||||||
assert(type(shape) == "table")
|
assert(type(shape) == "table" or type(shape) == "function")
|
||||||
assert(process == nil or type(process) == "function")
|
assert(process == nil or type(process) == "function")
|
||||||
|
|
||||||
local system = tiny.processingSystem()
|
local system = tiny.processingSystem()
|
||||||
system.name = name
|
system.name = name
|
||||||
local keys = {}
|
if type(shape) == "table" then
|
||||||
for key, value in pairs(shape) do
|
local keys = {}
|
||||||
local isTable = type(value) == "table"
|
for key, value in pairs(shape) do
|
||||||
local isMaybe = isTable and value.maybe ~= nil
|
local isTable = type(value) == "table"
|
||||||
|
local isMaybe = isTable and value.maybe ~= nil
|
||||||
|
|
||||||
if not isMaybe then
|
if not isMaybe then
|
||||||
-- ^ Don't require any Maybe types
|
-- ^ Don't require any Maybe types
|
||||||
keys[#keys + 1] = key
|
keys[#keys + 1] = key
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
system.filter = tiny.requireAll(table.unpack(keys))
|
||||||
|
elseif type(shape) == "function" then
|
||||||
|
system.filter = shape
|
||||||
end
|
end
|
||||||
system.filter = tiny.requireAll(table.unpack(keys))
|
|
||||||
if not process then
|
if not process then
|
||||||
return world:addSystem(system)
|
return world:addSystem(system)
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in New Issue