-- NAME: Pong -- DESC: Classic two-player Pong game -- Game states local STATE_MENU = 0 local STATE_PLAYING = 1 local STATE_GAME_OVER = 2 -- Game constants local PADDLE_WIDTH = 8 local PADDLE_HEIGHT = 40 local BALL_RADIUS = 5 local MAX_SCORE = 5 -- Initialize game function init() game.vars.state = STATE_MENU game.vars.frame_count = 0 -- Left paddle (player 1) game.vars.paddle_left_y = (game.height() / 2) - (PADDLE_HEIGHT / 2) game.vars.paddle_left_score = 0 -- Right paddle (player 2) game.vars.paddle_right_y = (game.height() / 2) - (PADDLE_HEIGHT / 2) game.vars.paddle_right_score = 0 -- Ball game.vars.ball_x = game.width() / 2 game.vars.ball_y = game.height() / 2 game.vars.ball_vel_x = 3 game.vars.ball_vel_y = 2 -- Enable continuous frame updates for smooth animation game.set_frame_updates(true) print("Pong initialized") end -- Update game logic function update(event) local state = game.vars.state -- State: MENU 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 -- State: PLAYING elseif state == STATE_PLAYING then -- Handle paddle input via touch if event.type == INPUT.TOUCH_DOWN or event.type == INPUT.TOUCH_MOVE then -- Left side touch moves left paddle, right side touch moves right paddle if event.x < game.width() / 2 then -- Move left paddle (constrain within bounds) game.vars.paddle_left_y = math.max(0, math.min(game.height() - PADDLE_HEIGHT, event.y - PADDLE_HEIGHT / 2)) else -- Move right paddle (constrain within bounds) game.vars.paddle_right_y = math.max(0, math.min(game.height() - PADDLE_HEIGHT, event.y - PADDLE_HEIGHT / 2)) end end -- Update physics on frame tick if event.type == INPUT.FRAME_TICK then update_ball() -- Check win condition if game.vars.paddle_left_score >= MAX_SCORE or game.vars.paddle_right_score >= MAX_SCORE then game.vars.state = STATE_GAME_OVER end return true -- Always redraw when playing end -- State: GAME_OVER 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 -- Draw game function draw() renderer.clear(false) -- Black background local state = game.vars.state -- Draw: MENU if state == STATE_MENU then renderer.text(game.width() / 2 - 15, game.height() / 2 - 30, "PONG", true) renderer.text(game.width() / 2 - 50, game.height() / 2, "Tap to Start", true) renderer.text(game.width() / 2 - 70, game.height() / 2 + 20, "First to " .. tostring(MAX_SCORE), true) -- Draw: PLAYING elseif state == STATE_PLAYING then -- Draw center line for y = 0, game.height(), 5 do renderer.pixel(game.width() / 2, y, true) end -- Draw paddles renderer.rect(10, game.vars.paddle_left_y, PADDLE_WIDTH, PADDLE_HEIGHT, true, true) renderer.rect(game.width() - 10 - PADDLE_WIDTH, game.vars.paddle_right_y, PADDLE_WIDTH, PADDLE_HEIGHT, true, true) -- Draw ball (convert to integers) renderer.circle(math.floor(game.vars.ball_x + 0.5), math.floor(game.vars.ball_y + 0.5), BALL_RADIUS, true, true) -- Draw scores local left_score_text = tostring(game.vars.paddle_left_score) local right_score_text = tostring(game.vars.paddle_right_score) renderer.text(game.width() / 2 - 30, 5, left_score_text, true) renderer.text(game.width() / 2 + 20, 5, right_score_text, true) -- Draw: GAME_OVER elseif state == STATE_GAME_OVER then renderer.text(game.width() / 2 - 40, game.height() / 2 - 30, "GAME OVER", true) local winner = "Player 1 Wins!" if game.vars.paddle_right_score > game.vars.paddle_left_score then winner = "Player 2 Wins!" end renderer.text(game.width() / 2 - 50, game.height() / 2, winner, true) local final_text = game.vars.paddle_left_score .. " - " .. game.vars.paddle_right_score renderer.text(game.width() / 2 - 25, game.height() / 2 + 20, final_text, true) renderer.text(game.width() / 2 - 60, game.height() / 2 + 40, "Tap to Menu", true) end end -- Helper: Update ball physics function update_ball() -- Move ball game.vars.ball_x = game.vars.ball_x + game.vars.ball_vel_x game.vars.ball_y = game.vars.ball_y + game.vars.ball_vel_y -- Bounce off top/bottom if game.vars.ball_y - BALL_RADIUS < 0 or game.vars.ball_y + BALL_RADIUS > game.height() then game.vars.ball_vel_y = -game.vars.ball_vel_y game.vars.ball_y = math.max(BALL_RADIUS, math.min(game.height() - BALL_RADIUS, game.vars.ball_y)) end -- Check left paddle collision if game.vars.ball_x - BALL_RADIUS < 10 + PADDLE_WIDTH then if game.vars.ball_y > game.vars.paddle_left_y and game.vars.ball_y < game.vars.paddle_left_y + PADDLE_HEIGHT then if game.vars.ball_vel_x < 0 then game.vars.ball_vel_x = -game.vars.ball_vel_x -- Add spin based on where ball hits paddle local hit_pos = (game.vars.ball_y - game.vars.paddle_left_y) / PADDLE_HEIGHT game.vars.ball_vel_y = (hit_pos - 0.5) * 6 end end end -- Check right paddle collision if game.vars.ball_x + BALL_RADIUS > game.width() - 10 - PADDLE_WIDTH then if game.vars.ball_y > game.vars.paddle_right_y and game.vars.ball_y < game.vars.paddle_right_y + PADDLE_HEIGHT then if game.vars.ball_vel_x > 0 then game.vars.ball_vel_x = -game.vars.ball_vel_x -- Add spin based on where ball hits paddle local hit_pos = (game.vars.ball_y - game.vars.paddle_right_y) / PADDLE_HEIGHT game.vars.ball_vel_y = (hit_pos - 0.5) * 6 end end end -- Score on left side miss if game.vars.ball_x < 0 then game.vars.paddle_right_score = game.vars.paddle_right_score + 1 reset_ball() end -- Score on right side miss if game.vars.ball_x > game.width() then game.vars.paddle_left_score = game.vars.paddle_left_score + 1 reset_ball() end end -- Helper: Reset ball to center function reset_ball() game.vars.ball_x = game.width() / 2 game.vars.ball_y = game.height() / 2 game.vars.ball_vel_x = 3 * (math.random() > 0.5 and 1 or -1) game.vars.ball_vel_y = 2 * (math.random() > 0.5 and 1 or -1) end -- Helper: Reset game function reset_game() game.vars.paddle_left_y = (game.height() / 2) - (PADDLE_HEIGHT / 2) game.vars.paddle_left_score = 0 game.vars.paddle_right_y = (game.height() / 2) - (PADDLE_HEIGHT / 2) game.vars.paddle_right_score = 0 reset_ball() end