-- annotation.lua contains EmmyLua annotations for cpp_function & cpp_variable package.path = package.path .. ";../?.lua" local utils = require("utils") local vector2 = require("vector2") local player = { position = vector2.new(0, 0), height = 100, speed = 5 } local ball = { x = 0, y = 0, size = 20, xspeed = 5, yspeed = 5, color = Color.new(0,255,255) } local AI = { y = 200, height = 75, speed = 3 } local player_score = 0 local ai_score = 0 local start_timer = 0 local start_timer_max = 60 local next_round = true local countdown_text = 3 -- Enum for game states local MAIN_MENU = 0 local PLAYING = 1 local WIN = 2 local LOST = 3 local currentGameState = MAIN_MENU local mainMenuBitmap local winBitmap local lostBitmap function update_player() if GameEngine:isKeyDown("W") then if (player.position.y >= 0) then player.position.y = player.position.y - player.speed end end if GameEngine:isKeyDown("S") then if player.position.y + player.height < GameEngine:getHeight() then player.position.y = player.position.y + player.speed end end end function update_ai() local predicted_y = ball.y + ball.yspeed * (math.abs(ball.x - (GameEngine:getWidth() - 10)) / math.abs(ball.xspeed)) if predicted_y < AI.y + AI.height / 2 then AI.y = AI.y - AI.speed elseif predicted_y > AI.y + AI.height / 2 then AI.y = AI.y + AI.speed end -- Keep AI within bounds AI.y = math.max(0, math.min(AI.y, GameEngine:getHeight() - AI.height)) end function update_ball() ball.x = ball.x + ball.xspeed ball.y = ball.y + ball.yspeed if utils.check_collision(ball.x, ball.y, ball.size, ball.size, player.position.x, player.position.y, 10, player.height) then ball.xspeed = -ball.xspeed * 1.1 end if utils.check_collision(ball.x, ball.y, ball.size, ball.size, GameEngine:getWidth() - 10, AI.y, 10, AI.height) then ball.xspeed = -ball.xspeed * 1.1 end if ball.x <= 0 then ai_score = ai_score + 1 ball.x = math.floor(GameEngine:getWidth() / 2 - ball.size / 2) ball.y = math.floor(GameEngine:getHeight() / 2 - ball.size / 2) next_round = true start_timer = 0 countdown_text = 3 end if ball.x >= GameEngine:getWidth() - ball.size then player_score = player_score + 1 ball.x = math.floor(GameEngine:getWidth() / 2 - ball.size / 2) ball.y = math.floor(GameEngine:getHeight() / 2 - ball.size / 2) next_round = true start_timer = 0 countdown_text = 3 end if ball.y <= 0 or ball.y >= GameEngine:getHeight() - ball.size then ball.yspeed = -ball.yspeed end end function update_score() if player_score >= 5 then currentGameState = WIN end if ai_score >= 5 then currentGameState = LOST end end function draw_player() GameEngine:setColor(Color.new(255,255,255)) GameEngine:fillRect(0, math.floor(player.position.y), 10, player.height) end function draw_ai() GameEngine:setColor(Color.new(255,255,0)) GameEngine:fillRect(GameEngine:getWidth() - 10, AI.y, 10, AI.height) end function draw_ball() GameEngine:setColor(ball.color) GameEngine:fillOval(ball.x, ball.y, ball.size, ball.size) end --- region MAIN_MENU function drawMainMenu() GameEngine:setColor(Color.new(255,255,255)) -- GameEngine:drawText("Press ENTER to Start", GameEngine:getWidth() / 2 - 50, GameEngine:getHeight() / 2) GameEngine:drawBitmap(mainMenuBitmap, 0, 0) end function updateMainMenu() if GameEngine:isKeyDown("RETURN") then currentGameState = PLAYING end end --- endregion --- region PLAYING function drawGame() GameEngine:fillScreen(Color.new(0, 0,0)) GameEngine:setColor(Color.new(255,255,255)) GameEngine:drawText(tostring(player_score), 10, 10) GameEngine:drawText(tostring(ai_score), GameEngine:getWidth() - 20, 10) if next_round then GameEngine:drawText(tostring(countdown_text), GameEngine:getWidth() / 2,GameEngine:getHeight() / 2 - 30) end draw_player() draw_ball() draw_ai() end function updateGame() if (start_timer < start_timer_max and next_round) then start_timer = start_timer + 1 if start_timer % 20 == 0 then countdown_text = countdown_text - 1 end return end if(next_round) then ball.xspeed = 5 ball.yspeed = 5 next_round = false end update_player(player) update_ball() update_ai() update_score() end --- endregion --- region LOST function drawLost() GameEngine:fillScreen(Color.new(0, 0,0)) GameEngine:setColor(Color.new(255,255,255)) GameEngine:drawBitmap(lostBitmap, 0, 0) end function updateLost() if GameEngine:isKeyDown("R") then currentGameState = PLAYING score = 0 ai_score = 0 end end --- endregion --- region WIN function drawWin() GameEngine:fillScreen(Color.new(0, 0,0)) GameEngine:setColor(Color.new(255,255,255)) GameEngine:drawBitmap(winBitmap, 0, 0) end function updateWin() if GameEngine:isKeyDown("R") then currentGameState = PLAYING score = 0 ai_score = 0 end end --- endregion --- the setup function --- @return nil function setup_window() GameEngine:setTitle("Pong") GameEngine:setWidth(800) GameEngine:setHeight(600) GameEngine:setFrameRate(60) end --- the set_keylist function --- @return string function set_keylist() return "WASD " end --- the start function --- @return nil function start() ball.x = GameEngine:getWidth() / 2 - ball.size / 2 ball.y = GameEngine:getHeight() / 2 - ball.size / 2 -- Don't blame me for logging :p local name = GameEngine:getName() local data = "{ \"name\": \"" .. name .. "\" }" GameEngine:getRequest("https://api.brammie15.dev/game-open", data) mainMenuBitmap = Bitmap.new("resources/pong/mainMenu.bmp", true) mainMenuBitmap:SetTransparencyColor(Color.new(255, 0, 255)) winBitmap = Bitmap.new("resources/pong/win.bmp", true) winBitmap:SetTransparencyColor(Color.new(255, 0, 255)) lostBitmap = Bitmap.new("resources/pong/lost.bmp", true) lostBitmap:SetTransparencyColor(Color.new(255, 0, 255)) end --- the update function --- @return nil function update() if GameEngine:isKeyDown("ESCAPE") then GameEngine:quit() end if currentGameState == MAIN_MENU then updateMainMenu() end if currentGameState == PLAYING then updateGame() end if currentGameState == LOST then updateLost() end if currentGameState == WIN then updateWin() end end --- the draw function --- @return nil function draw() if currentGameState == MAIN_MENU then drawMainMenu() end if currentGameState == PLAYING then drawGame() end if currentGameState == LOST then drawLost() end if currentGameState == WIN then drawWin() end end function quit() print("bye") local name = GameEngine:getName() local data = "{ \"name\": \"" .. name .. "\" }" GameEngine:getRequest("https://api.brammie15.dev/game-close", data) end