Files
basic1/games/lua_examples/memory_match.lua
Adolfo Reyna fa7d2fd32f Scale games on both axes and 2x text size
All 4 games (simon_says, tic_tac_toe, memory_match, 2048):
- Changed sizing to use min(width, height) instead of just width
- Grids now scale proportionally on both axes
- All UI text now uses text_scale=2 for better visibility
- Games fill more of the screen properly on portrait mode

Fixes:
- Simon Says buttons now square grid on any orientation
- Tic-Tac-Toe grid centered vertically using full screen height
- Memory Match cards use smallest dimension for square sizing
- 2048 tiles scale and center on both axes
- All text (scores, menus, game over) now 2x larger
2026-02-12 21:23:34 -05:00

224 lines
7.4 KiB
Lua

-- NAME: Memory Match
-- DESC: Find matching pairs
-- Game states
local STATE_MENU = 0
local STATE_PLAYING = 1
local STATE_GAME_OVER = 2
-- Game constants
local GRID_COLS = 4
local GRID_ROWS = 4
local FLIP_DURATION = 15 -- Frames to show flip animation
-- Calculate card size based on screen size
local function get_card_size()
-- Use available space with padding, based on smallest dimension
local min_dim = math.min(game.width(), game.height())
local padding = math.floor(min_dim / 8)
local available_w = game.width() - (padding * 2)
local available_h = game.height() - 80 -- Leave room for text
-- Calculate based on grid
local card_width = math.floor(available_w / GRID_COLS)
local card_height = math.floor(available_h / GRID_ROWS)
-- Use the smaller dimension for square cards
return math.min(card_width, card_height)
end
local function get_grid_start_x()
local card_size = get_card_size()
local grid_width = card_size * GRID_COLS
return math.floor((game.width() - grid_width) / 2)
end
local function get_grid_start_y()
return 60
end
function init()
game.vars.state = STATE_MENU
game.vars.score = 0
game.vars.moves = 0
-- Card grid
game.vars.cards = {} -- {id, face_up, matched}
game.vars.selected = {} -- Indices of selected cards
game.vars.flip_frame = 0
game.vars.waiting = false -- Waiting to flip back incorrect pair
-- Enable continuous updates
game.set_frame_updates(true)
print("Memory Match 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
-- Handle card selection
if event.type == INPUT.TOUCH_DOWN and not game.vars.waiting then
local card_idx = get_card_at(event.x, event.y)
if card_idx and not game.vars.cards[card_idx].matched and not game.vars.cards[card_idx].face_up then
-- Select card
game.vars.cards[card_idx].face_up = true
table.insert(game.vars.selected, card_idx)
if #game.vars.selected == 2 then
game.vars.moves = game.vars.moves + 1
-- Check for match
if game.vars.cards[game.vars.selected[1]].id == game.vars.cards[game.vars.selected[2]].id then
-- Match!
game.vars.cards[game.vars.selected[1]].matched = true
game.vars.cards[game.vars.selected[2]].matched = true
game.vars.score = game.vars.score + 1
game.vars.selected = {}
-- Check win
if game.vars.score == (GRID_COLS * GRID_ROWS) / 2 then
game.vars.state = STATE_GAME_OVER
end
else
-- No match, wait then flip back
game.vars.waiting = true
game.vars.flip_frame = 0
end
end
return true
end
end
-- Handle flip-back animation
if game.vars.waiting and event.type == INPUT.FRAME_TICK then
game.vars.flip_frame = game.vars.flip_frame + 1
if game.vars.flip_frame >= FLIP_DURATION then
-- Flip cards back
game.vars.cards[game.vars.selected[1]].face_up = false
game.vars.cards[game.vars.selected[2]].face_up = false
game.vars.selected = {}
game.vars.waiting = false
game.vars.flip_frame = 0
end
return true
end
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
return false
end
function draw()
renderer.clear(false) -- Black background
local state = game.vars.state
local card_size = get_card_size()
local start_x = get_grid_start_x()
local start_y = get_grid_start_y()
if state == STATE_MENU then
renderer.text(game.width() / 2 - 40, game.height() / 2 - 40, "MEMORY MATCH", true, 2)
renderer.text(game.width() / 2 - 50, game.height() / 2 - 10, "Find all pairs", true, 2)
renderer.text(game.width() / 2 - 50, game.height() / 2 + 20, "Tap to Start", true, 2)
elseif state == STATE_PLAYING or state == STATE_GAME_OVER then
-- Draw grid
for row = 0, GRID_ROWS - 1 do
for col = 0, GRID_COLS - 1 do
local idx = row * GRID_COLS + col + 1
local card = game.vars.cards[idx]
local x = start_x + col * card_size
local y = start_y + row * card_size
if card.face_up or card.matched then
-- Show card value
renderer.rect(x, y, card_size, card_size, true, true)
local text = tostring(card.id)
renderer.text(x + math.floor(card_size / 2 - 2), y + math.floor(card_size / 2 - 2), text, false, 2)
else
-- Face down (outline)
renderer.rect(x, y, card_size, card_size, true, false)
end
end
end
-- Draw stats
renderer.text(10, 10, "Pairs: " .. tostring(game.vars.score) .. "/" .. tostring((GRID_COLS * GRID_ROWS) / 2), true, 2)
renderer.text(10, 25, "Moves: " .. tostring(game.vars.moves), true, 2)
if state == STATE_GAME_OVER then
renderer.text(game.width() / 2 - 40, 5, "YOU WIN!", true, 2)
renderer.text(game.width() / 2 - 50, game.height() - 20, "Tap to Menu", true, 2)
end
end
end
function get_card_at(x, y)
local card_size = get_card_size()
local start_x = get_grid_start_x()
local start_y = get_grid_start_y()
for row = 0, GRID_ROWS - 1 do
for col = 0, GRID_COLS - 1 do
local card_x = start_x + col * card_size
local card_y = start_y + row * card_size
if x >= card_x and x < card_x + card_size and
y >= card_y and y < card_y + card_size then
return row * GRID_COLS + col + 1
end
end
end
return nil
end
function reset_game()
game.vars.score = 0
game.vars.moves = 0
game.vars.selected = {}
game.vars.flip_frame = 0
game.vars.waiting = false
-- Create shuffled card pairs
local card_ids = {}
local num_pairs = (GRID_COLS * GRID_ROWS) / 2
for i = 1, num_pairs do
table.insert(card_ids, i)
table.insert(card_ids, i)
end
-- Shuffle
for i = #card_ids, 2, -1 do
local j = math.random(1, i)
card_ids[i], card_ids[j] = card_ids[j], card_ids[i]
end
-- Create card objects
game.vars.cards = {}
for i = 1, #card_ids do
game.vars.cards[i] = {
id = card_ids[i],
face_up = false,
matched = false
}
end
end