Basic animations

This commit is contained in:
Pyrex 2024-02-04 22:55:13 -08:00
parent a5c76557d2
commit bdc8c91078
7 changed files with 152 additions and 23 deletions

26
animator.lua Normal file
View File

@ -0,0 +1,26 @@
animator=klass()
function animator:init()
self.operations={}
end
function animator:update()
while true do
if (#self.operations==0) return
local op=self.operations[1]
if op:update() then
return true
else
deli(self.operations,1)
end
end
end
function animator:idle()
return #self.operations==0
end
function animator:add(op)
add(self.operations,op)
end
function animator:draw()
for i=#self.operations,1,-1 do
self.operations[i]:draw()
end
end

View File

@ -3,6 +3,7 @@ board=klass()
function board:init(ruleset)
self.ruleset=ruleset
self.cursor=cursor:new(self)
self.animator=animator:new()
self.slots={}
self.wells={}
@ -52,7 +53,8 @@ function board:deal()
for i=1,#self.ruleset.deck.aces do
local well=self.wells[i]
local ace=self.ruleset.deck.aces[i]
well:add(ace)
well:add(ace) -- temporarily, so would_accept will work
self:animate_move_ace_to_well(ace,i)
available[ace]=false
end
@ -69,6 +71,11 @@ function board:deal()
if (not skip) add(eligible_bottom_row,card)
end
-- let the animation install the aces for real
for w in all(self.wells) do
w:clear()
end
function i_to_slot(i)
if (i<n_usable_slots\2) return i+1
return i+2
@ -93,18 +100,20 @@ function board:deal()
for i=1,#eligible do
local ix=i_to_slot((i-1)%n_usable_slots)
local slot=self.slots[ix]
slot:add(eligible[i])
self:animate_move_new_card_to_slot(eligible[i],ix)
end
end
function board:on_idle()
self:find_automove()
end
function board:on_move()
-- TODO: Make checkpoint
while true do
if (not self:_on_move_1()) break
end
self:find_automove()
end
function board:_on_move_1()
function board:find_automove()
for s=1,#self.slots do
local top=self.slots[s]:peek()
if top then
@ -112,7 +121,8 @@ function board:_on_move_1()
if w<=self.ruleset.n_suits and self.slots[self.ruleset.n_slots+1]:peek()!=nil then
-- the top wells are blocked
elseif self.wells[w]:would_accept(top) then
self.wells[w]:add(self.slots[s]:pop())
self:animate_and_move_to_well(s,w)
return true
end
end
@ -120,6 +130,19 @@ function board:_on_move_1()
end
end
function board:can_take_input()
return self.animator:idle()
end
function board:update()
local was_idle=self.animator:idle()
self.animator:update()
local is_idle=self.animator:idle()
if (not was_idle and is_idle) then
self:on_idle()
end
end
function board:draw()
for w_ix=1,#self.wells do
local w=self.wells[w_ix]
@ -131,7 +154,6 @@ function board:draw()
end
end
local function forall_slots(cb)
for s_ix=1,#self.slots do
local s=self.slots[s_ix]
@ -151,6 +173,9 @@ function board:draw()
end
end)
self.animator:draw()
if self.animator:idle() then
local hover_slot=self.cursor:hover_slot()
forall_slots(function(x,y,s_ix,s,l,n)
if hover_slot==s_ix then
@ -159,6 +184,7 @@ function board:draw()
end
end)
end
end
slot=klass()
function slot:init(ruleset,max_n)
@ -203,3 +229,6 @@ end
function well:add(card)
add(self.contents,card)
end
function well:clear()
self.contents={}
end

68
board_animations.lua Normal file
View File

@ -0,0 +1,68 @@
function board:animate_move_ace_to_well(card, well)
local slot_layout=self.ruleset.layouts:slot(
self.ruleset.n_slots\2+1
)
local well_layout=self.ruleset.layouts:well(well)
local start_x,start_y=slot_layout:place_card(1)
local end_x,end_y=well_layout:place_card(1) -- index shouldn't matter
local _self=self
self:_animate_move_card(
card,function() _self.wells[well]:add(card) end,
start_x,start_y,function() return end_x,end_y end
)
end
function board:animate_move_new_card_to_slot(card, slot)
local src_layout=self.ruleset.layouts:slot(self.ruleset.n_slots\2+1)
local dst_layout=self.ruleset.layouts:slot(slot)
local start_x,start_y=src_layout:place_card(1)
local _self=self
self:_animate_move_card(
card,function() _self.slots[slot]:add(card) end,
start_x,start_y,function()
return dst_layout:place_card(#_self.slots[slot].contents+1)
end
)
end
function board:animate_and_move_to_well(slot, well)
local slot_layout=self.ruleset.layouts:slot(slot)
local well_layout=self.ruleset.layouts:well(well)
local start_x,start_y=slot_layout:place_card(#self.slots[slot].contents)
local end_x,end_y=well_layout:place_card(1) -- index shouldn't matter
local card=self.slots[slot]:pop()
local _self=self
self:_animate_move_card(
card,function() _self.wells[well]:add(card) end,
start_x,start_y,function() return end_x,end_y end
)
end
function board:_animate_move_card(card,on_end,start_x,start_y,compute_end)
local frame=0
local progress=0.0
local anim_obj={}
local end_x,end_y=start_x,start_y
local _self=self
function anim_obj:update()
if (frame==0) end_x,end_y=compute_end()
frame+=1
progress=frame/7
if (progress>=1.0) on_end() return false
return true
end
function anim_obj:draw()
local x=start_x+(end_x-start_x)*progress
local y=start_y+(end_y-start_y)*progress
_self.ruleset.deck:draw_card(x,y,card,false)
end
self.animator:add(anim_obj)
end

View File

@ -2,16 +2,20 @@ main={}
add(modules,main)
function main:init()
extcmd("rec")
self.board=board:new(progression[1])
end
function main:update()
self.board:update()
if self.board:can_take_input() then
if (btnp(0)) self.board.cursor:move_x(-1)
if (btnp(1)) self.board.cursor:move_x(1)
if (btnp(2)) self.board.cursor:move_y(-1)
if (btnp(3)) self.board.cursor:move_y(1)
if (btnp(4)) self.board.cursor:toggle_grab()
end
end
function main:draw()
cls(13)

View File

@ -2,7 +2,9 @@ pico-8 cartridge // http://www.pico-8.com
version 41
__lua__
#include engine.lua
#include animator.lua
#include board.lua
#include board_animations.lua
#include cursor.lua
#include layout.lua
#include ruleset.lua

View File

@ -1,6 +1,6 @@
progression={
-- level 1
ruleset:new(5,1,9,0),
--ruleset:new(5,1,9,0),
-- level 2
-- ruleset:new(5,2,9,0),
-- level 3
@ -10,7 +10,7 @@ progression={
-- level 5
-- ruleset:new(9,3,11,18),
-- fortune's foundation
-- ruleset:new(11,4,13,22)
ruleset:new(11,4,13,22)
-- harder than fortune's foundation
-- ruleset:new(11,5,10,25)
}

View File

@ -84,7 +84,7 @@ function ruleset:generate_deck()
local bg,shadowbg
if meta.suit=='a' then
bg,shadowbg=1,1
if (shadow) bg,shadowbg=1,0
if (shadow) bg,shadowbg=1,1
if (is_extreme) bg,shadowbg=8,8
else
bg,shadowbg=7,7