feat: add 6 lua games for basic1 console
- Pong: 2-player paddle and ball game with spin mechanics - Flappy Bird: gravity physics, obstacle avoidance - Breakout: paddle control, brick grid, collision detection - Simon Says: sequence memory, animation timing - Memory Match: pair matching, flip animations, grid layout - Tetris: falling blocks, grid system, line clearing - Asteroids: vector math, rotation, projectiles, enemy spawning All games follow API conventions with state machines, touch input, frame-based animation, and persistent game.vars state management.
This commit is contained in:
193
games/lua_examples/simon_says.lua
Normal file
193
games/lua_examples/simon_says.lua
Normal file
@@ -0,0 +1,193 @@
|
||||
-- NAME: Simon Says
|
||||
-- DESC: Repeat the color sequence
|
||||
|
||||
-- Game states
|
||||
local STATE_MENU = 0
|
||||
local STATE_PLAYING = 1
|
||||
local STATE_SHOWING = 2
|
||||
local STATE_GAME_OVER = 3
|
||||
|
||||
-- Game constants
|
||||
local BUTTON_SIZE = 40
|
||||
local BUTTON_SPACING = 10
|
||||
local SHOW_DURATION = 30 -- Frames to show each button
|
||||
local WAIT_DURATION = 20 -- Frames between shows
|
||||
|
||||
-- Button positions (4 buttons in grid)
|
||||
local BUTTONS = {
|
||||
{x = 20, y = 20, color = 1}, -- Top-left
|
||||
{x = 80, y = 20, color = 2}, -- Top-right
|
||||
{x = 20, y = 80, color = 3}, -- Bottom-left
|
||||
{x = 80, y = 80, color = 4} -- Bottom-right
|
||||
}
|
||||
|
||||
function init()
|
||||
game.vars.state = STATE_MENU
|
||||
game.vars.score = 0
|
||||
|
||||
-- Sequence of button presses
|
||||
game.vars.sequence = {}
|
||||
game.vars.player_seq = {}
|
||||
|
||||
-- Animation state
|
||||
game.vars.showing_idx = 0
|
||||
game.vars.show_frame = 0
|
||||
game.vars.show_button = nil
|
||||
|
||||
-- Input state
|
||||
game.vars.waiting_for_input = false
|
||||
game.vars.input_idx = 0
|
||||
|
||||
-- Enable continuous updates
|
||||
game.set_frame_updates(true)
|
||||
|
||||
print("Simon Says initialized")
|
||||
end
|
||||
|
||||
function update(event)
|
||||
local state = game.vars.state
|
||||
|
||||
if state == STATE_MENU then
|
||||
if event.type == INPUT.TOUCH_DOWN or event.type == INPUT.BUTTON_0 or event.type == INPUT.BUTTON_1 then
|
||||
reset_game()
|
||||
game.vars.state = STATE_PLAYING
|
||||
return true
|
||||
end
|
||||
|
||||
elseif state == STATE_PLAYING then
|
||||
-- Start showing sequence
|
||||
if event.type == INPUT.FRAME_TICK then
|
||||
game.vars.show_frame = game.vars.show_frame + 1
|
||||
return true
|
||||
end
|
||||
|
||||
return false
|
||||
|
||||
elseif state == STATE_SHOWING then
|
||||
-- Animate sequence
|
||||
if event.type == INPUT.FRAME_TICK then
|
||||
game.vars.show_frame = game.vars.show_frame + 1
|
||||
|
||||
-- Move to next button in sequence
|
||||
if game.vars.show_frame > SHOW_DURATION + WAIT_DURATION then
|
||||
game.vars.showing_idx = game.vars.showing_idx + 1
|
||||
game.vars.show_frame = 0
|
||||
game.vars.show_button = nil
|
||||
|
||||
-- Done showing sequence, wait for player input
|
||||
if game.vars.showing_idx > #game.vars.sequence then
|
||||
game.vars.state = STATE_PLAYING
|
||||
game.vars.waiting_for_input = true
|
||||
game.vars.input_idx = 0
|
||||
end
|
||||
else
|
||||
-- Highlight button during show duration
|
||||
if game.vars.show_frame <= SHOW_DURATION then
|
||||
game.vars.show_button = game.vars.sequence[game.vars.showing_idx]
|
||||
else
|
||||
game.vars.show_button = nil
|
||||
end
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
return false
|
||||
|
||||
elseif state == STATE_GAME_OVER then
|
||||
if event.type == INPUT.TOUCH_DOWN or event.type == INPUT.BUTTON_0 or event.type == INPUT.BUTTON_1 then
|
||||
game.vars.state = STATE_MENU
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
-- Handle player input
|
||||
if game.vars.waiting_for_input and event.type == INPUT.TOUCH_DOWN then
|
||||
local button = get_button_at(event.x, event.y)
|
||||
if button then
|
||||
game.vars.player_seq[#game.vars.player_seq + 1] = button
|
||||
game.vars.input_idx = game.vars.input_idx + 1
|
||||
|
||||
-- Check if correct
|
||||
if game.vars.sequence[game.vars.input_idx] ~= button then
|
||||
-- Wrong! Game over
|
||||
game.vars.state = STATE_GAME_OVER
|
||||
return true
|
||||
end
|
||||
|
||||
-- Check if completed sequence
|
||||
if game.vars.input_idx == #game.vars.sequence then
|
||||
-- Advance to next round
|
||||
game.vars.sequence[#game.vars.sequence + 1] = math.random(1, 4)
|
||||
game.vars.player_seq = {}
|
||||
game.vars.waiting_for_input = false
|
||||
game.vars.showing_idx = 0
|
||||
game.vars.show_frame = 0
|
||||
game.vars.show_button = nil
|
||||
game.vars.state = STATE_SHOWING
|
||||
game.vars.score = game.vars.score + 1
|
||||
return true
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
function draw()
|
||||
renderer.clear(false) -- Black background
|
||||
|
||||
local state = game.vars.state
|
||||
|
||||
if state == STATE_MENU then
|
||||
renderer.text(game.width() / 2 - 40, game.height() / 2 - 40, "SIMON SAYS", true)
|
||||
renderer.text(game.width() / 2 - 50, game.height() / 2 - 10, "Repeat the sequence", true)
|
||||
renderer.text(game.width() / 2 - 50, game.height() / 2 + 20, "Tap to Start", true)
|
||||
|
||||
else
|
||||
-- Draw buttons with highlight
|
||||
for i = 1, 4 do
|
||||
local btn = BUTTONS[i]
|
||||
local filled = (game.vars.show_button == i)
|
||||
renderer.rect(btn.x, btn.y, BUTTON_SIZE, BUTTON_SIZE, true, filled)
|
||||
end
|
||||
|
||||
-- Draw score
|
||||
renderer.text(10, 10, "Level: " .. tostring(game.vars.score + 1), true)
|
||||
|
||||
if state == STATE_PLAYING and game.vars.waiting_for_input then
|
||||
renderer.text(game.width() / 2 - 40, game.height() - 20, "Your turn!", true)
|
||||
end
|
||||
|
||||
if state == STATE_GAME_OVER then
|
||||
renderer.text(game.width() / 2 - 40, game.height() / 2 - 20, "GAME OVER", true)
|
||||
renderer.text(game.width() / 2 - 30, game.height() / 2, "Level: " .. tostring(game.vars.score + 1), true)
|
||||
renderer.text(game.width() / 2 - 60, game.height() / 2 + 20, "Tap to Restart", true)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function get_button_at(x, y)
|
||||
for i = 1, 4 do
|
||||
local btn = BUTTONS[i]
|
||||
if x >= btn.x and x < btn.x + BUTTON_SIZE and
|
||||
y >= btn.y and y < btn.y + BUTTON_SIZE then
|
||||
return i
|
||||
end
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
function reset_game()
|
||||
game.vars.score = 0
|
||||
game.vars.sequence = {math.random(1, 4)}
|
||||
game.vars.player_seq = {}
|
||||
game.vars.showing_idx = 0
|
||||
game.vars.show_frame = 0
|
||||
game.vars.show_button = nil
|
||||
game.vars.waiting_for_input = false
|
||||
game.vars.input_idx = 0
|
||||
game.vars.state = STATE_SHOWING
|
||||
end
|
||||
Reference in New Issue
Block a user