diff --git a/vacation.p8 b/vacation.p8 index 873f512..46d7066 100644 --- a/vacation.p8 +++ b/vacation.p8 @@ -113,6 +113,8 @@ function outer_or_each_opt(t, mname) end) end +function nop() end + -- puke emits a verbose string -- describing item, indented to -- the specified depth (0 by @@ -547,7 +549,7 @@ end -- hitbox for current state function toyphin:box() local st = self.state - return self.x + st.xo, self.y + st.yo, st.ws * 8, st.hs * 8 + return {self.x + st.xo, self.y + st.yo, st.ws * 8, st.hs * 8} end function toyphin:draw() @@ -556,6 +558,43 @@ function toyphin:draw() spr(st.s[1+(((t()<<1)&0x0.FFFF*#st.s)&0x7FFF)], self.x + st.xo, y + st.yo, self.state.ws, self.state.hs) end +-->8 word target + +wordtarget = { + x = 129, + y = 60, + str = "DRIFT", + on_hit = nop, +} +mknew(wordtarget, function(x) + poke(0x5f58, 0x81) + x.w = print(x.str or wordtarget.str, 0, -9999)-1 +end) + +function collides(b1, b2) + if (b1[1] > b2[1] + b2[3]) return false + if (b1[1] + b1[3] < b2[1]) return false + if (b1[2] > b2[2] + b2[4]) return false + return not (b1[2] + b1[4] < b2[2]) +end + +function wordtarget:update() + if collides({self.x, self.y, self.w, 7}, self.phin:box()) then + self:on_hit() + return true + end + self.x -= 1 + return self.x < -self.w +end + +function wordtarget:draw() + poke(0x5f58, 0x81) + -- debug: show hitbox + --rect(self.x-1, self.y-1, self.x+self.w+1, self.y + 8, 0x10F1.5a5a) + print(self.str, self.x+1, self.y+1, 0x100b) + print(self.str, self.x, self.y, 0x100a) +end + -->8 -- arcade mode @@ -634,7 +673,8 @@ end arcade_level = { score=0, - maxscore=15, + wordcount=15, + wordwait = 90, } mknew(arcade_level, function(x) x.phin = toyphin.new{splasher=x} @@ -643,8 +683,11 @@ mknew(arcade_level, function(x) x.sea = sea.new() x.bg = event_list.new() x.fg = event_list.new() + x.words = event_list.new() -- TODO: score renderer x.t0 = t() + x.wordremain = x.wordcount or arcade_level.wordcount + x.wordtimer = x.wordwait or arcade_level.wordwait x.v = view.of{ x.sky, @@ -653,6 +696,7 @@ mknew(arcade_level, function(x) x.bg, x.phin, x.fg, + x.words, } x.s = scootbox.new() @@ -662,12 +706,46 @@ mknew(arcade_level, function(x) end) function arcade_level:update() + if self.phin.entered then + if self.wordtimer <= 0 and self.wordremain > 0 then + self:spawn_word() + self.wordtimer = self.wordwait + self.wordremain -= 1 + end + self.wordtimer -= 1 + end + if self.wordremain <= 0 and self.words.next == nil then + self.phin.exiting = true + end + if self.phin.x > 90 then + -- TODO: done callback + self:on_level_done() + end -- TODO: timers, word loop, -- level state tracking and -- progression, etc. self.s:update() end +function arcade_level:spawn_word() + -- TODO: basically everything. + -- word lists + -- pattern generator + self.words:push_back(wordtarget.new{ + y=32+rnd(64), -- real game uses pattern generator! + phin=self.phin, + on_hit = function(word) + self:word_hit(word) + end, + }) +end + +function arcade_level:word_hit(word) + self.score += 1 + -- TODO: sfx + -- TODO: sparkle +end + function arcade_level:draw() setup_arcade_pal() self.s:draw()