--[[ raylib - sample game: arkanoid Sample game Marc Palau and Ramon Santamaria This game has been created using raylib v1.3 (www.raylib.com) raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) Copyright (c) 2015 Ramon Santamaria (@raysan5) Translated to Lua by Ghassan Al-Mashareqa (ghassan@ghassan.pl) --]] ------------------------------------------------------------------------------------ -- Some Defines ------------------------------------------------------------------------------------ PLAYER_MAX_LIFE = 5 LINES_OF_BRICKS = 5 BRICKS_PER_LINE = 20 ------------------------------------------------------------------------------------ -- Types and Structures Definition ------------------------------------------------------------------------------------ GameScreen = { LOGO = 0, TITLE = 1, GAMEPLAY = 2, ENDING = 3 } function Player() return { position = Vector2(0,0), size = Vector2(0,0), life = 0 } end function Ball() return { position = Vector2(0,0), speed = Vector2(0,0), radius = 0, active = false } end function Brick() return { position = Vector2(0,0), active = false } end -------------------------------------------------------------------------------------- -- Global Variables Declaration -------------------------------------------------------------------------------------- screenWidth = 800; screenHeight = 450; framesCounter = 0; gameOver = false; pause = false; player = Player() ball = Ball() brick = {}--[LINES_OF_BRICKS][BRICKS_PER_LINE]; for i = 0, LINES_OF_BRICKS-1 do brick[i] = {} for j = 0, BRICKS_PER_LINE-1 do brick[i][j] = Brick() end end brickSize = Vector2(0,0) -------------------------------------------------------------------------------------- -- Module Functions Definitions (local) -------------------------------------------------------------------------------------- -- Initialize game variables function InitGame() brickSize = Vector2(GetScreenWidth()/BRICKS_PER_LINE, 40) -- Initialize player player.position = Vector2(screenWidth/2, screenHeight*7/8) player.size = Vector2(screenWidth/10, 20) player.life = PLAYER_MAX_LIFE; -- Initialize ball ball.position = Vector2(screenWidth/2, screenHeight*7/8 - 30) ball.speed = Vector2(0, 0) ball.radius = 7; ball.active = false; -- Initialize bricks local initialDownPosition = 50; for i = 0, LINES_OF_BRICKS-1 do for j = 0, BRICKS_PER_LINE-1 do brick[i][j].position = Vector2(j*brickSize.x + brickSize.x/2, i*brickSize.y + initialDownPosition) brick[i][j].active = true; end end end -- Update game (one frame) function UpdateGame() if (not gameOver) then if (IsKeyPressed(KEY.P)) then pause = not pause; end if (not pause) then -- Player movement if (IsKeyDown(KEY.LEFT)) then player.position.x = player.position.x - 5; end if ((player.position.x - player.size.x/2) <= 0) then player.position.x = player.size.x/2; end if (IsKeyDown(KEY.RIGHT)) then player.position.x = player.position.x + 5; end if ((player.position.x + player.size.x/2) >= screenWidth) then player.position.x = screenWidth - player.size.x/2; end -- Launch ball if (not ball.active) then if (IsKeyPressed(KEY.SPACE)) then ball.active = true; ball.speed = Vector2(0, -5) end end UpdateBall(); -- Game over logic if (player.life <= 0) then gameOver = true; else gameOver = true; for i = 0, LINES_OF_BRICKS-1 do for j = 0, BRICKS_PER_LINE-1 do if (brick[i][j].active) then gameOver = false; end end end end end else if (IsKeyPressed(KEY.ENTER)) then InitGame(); gameOver = false; end end end -- Draw game (one frame) function DrawGame() BeginDrawing(); ClearBackground(RAYWHITE); if (not gameOver) then -- Draw player bar DrawRectangle(player.position.x - player.size.x/2, player.position.y - player.size.y/2, player.size.x, player.size.y, BLACK); -- Draw player lives for i = 0, player.life-1 do DrawRectangle(20 + 40*i, screenHeight - 30, 35, 10, LIGHTGRAY); end -- Draw ball DrawCircleV(ball.position, ball.radius, MAROON); -- Draw bricks for i = 0, LINES_OF_BRICKS-1 do for j = 0, BRICKS_PER_LINE-1 do if (brick[i][j].active) then if ((i + j) % 2 == 0) then DrawRectangle(brick[i][j].position.x - brickSize.x/2, brick[i][j].position.y - brickSize.y/2, brickSize.x, brickSize.y, GRAY); else DrawRectangle(brick[i][j].position.x - brickSize.x/2, brick[i][j].position.y - brickSize.y/2, brickSize.x, brickSize.y, DARKGRAY); end end end end if (pause) then DrawText("GAME PAUSED", screenWidth/2 - MeasureText("GAME PAUSED", 40)/2, screenHeight/2 - 40, 40, GRAY); end else DrawText("PRESS [ENTER] TO PLAY AGAIN", GetScreenWidth()/2 - MeasureText("PRESS [ENTER] TO PLAY AGAIN", 20)/2, GetScreenHeight()/2 - 50, 20, GRAY); end EndDrawing(); end -- Unload game variables function UnloadGame() -- TODO: Unload all dynamic loaded data (textures, sounds, models...) end -- Update and Draw (one frame) function UpdateDrawFrame() UpdateGame(); DrawGame(); end ---------------------------------------------------------------------------------------- -- Additional module functions ---------------------------------------------------------------------------------------- function UpdateBall() -- Update position if (ball.active) then ball.position.x = ball.position.x + ball.speed.x; ball.position.y = ball.position.y + ball.speed.y; else ball.position = Vector2(player.position.x, screenHeight*7/8 - 30); end -- Bounce in x if (((ball.position.x + ball.radius) >= screenWidth) or ((ball.position.x - ball.radius) <= 0)) then ball.speed.x = ball.speed.x * -1; end -- Bounce in y if ((ball.position.y - ball.radius) <= 0) then ball.speed.y = ball.speed.y * -1; end -- Ball reaches bottom of the screen if ((ball.position.y + ball.radius) >= screenHeight) then ball.speed = Vector2(0, 0); ball.active = false; player.life = player.life - 1; end -- Collision logic: ball vs player if CheckCollisionCircleRec(ball.position, ball.radius, Rectangle( player.position.x - player.size.x/2, player.position.y - player.size.y/2, player.size.x, player.size.y)) then if (ball.speed.y > 0) then ball.speed.y = ball.speed.y * -1; ball.speed.x = (ball.position.x - player.position.x)/(player.size.x/2)*5; end end -- Collision logic: ball vs bricks for i = 0,LINES_OF_BRICKS-1 do for j = 0,BRICKS_PER_LINE-1 do if (brick[i][j].active) then -- Hit below if (((ball.position.y - ball.radius) <= (brick[i][j].position.y + brickSize.y/2)) and ((ball.position.y - ball.radius) > (brick[i][j].position.y + brickSize.y/2 + ball.speed.y)) and ((math.abs(ball.position.x - brick[i][j].position.x)) < (brickSize.x/2 + ball.radius*2/3)) and (ball.speed.y < 0)) then brick[i][j].active = false; ball.speed.y = ball.speed.y * -1; -- Hit above elseif (((ball.position.y + ball.radius) >= (brick[i][j].position.y - brickSize.y/2)) and ((ball.position.y + ball.radius) < (brick[i][j].position.y - brickSize.y/2 + ball.speed.y)) and ((math.abs(ball.position.x - brick[i][j].position.x)) < (brickSize.x/2 + ball.radius*2/3)) and (ball.speed.y > 0)) then brick[i][j].active = false; ball.speed.y = ball.speed.y * -1; -- Hit left elseif (((ball.position.x + ball.radius) >= (brick[i][j].position.x - brickSize.x/2)) and ((ball.position.x + ball.radius) < (brick[i][j].position.x - brickSize.x/2 + ball.speed.x)) and ((math.abs(ball.position.y - brick[i][j].position.y)) < (brickSize.y/2 + ball.radius*2/3)) and (ball.speed.x > 0)) then brick[i][j].active = false; ball.speed.x = ball.speed.x * -1; -- Hit right elseif (((ball.position.x - ball.radius) <= (brick[i][j].position.x + brickSize.x/2)) and ((ball.position.x - ball.radius) > (brick[i][j].position.x + brickSize.x/2 + ball.speed.x)) and ((math.abs(ball.position.y - brick[i][j].position.y)) < (brickSize.y/2 + ball.radius*2/3)) and (ball.speed.x < 0)) then brick[i][j].active = false; ball.speed.x = ball.speed.x * -1; end end end end end InitWindow(screenWidth, screenHeight, "sample game: arkanoid"); InitGame(); SetTargetFPS(60); ---------------------------------------------------------------------------------------- -- Main game loop while (not WindowShouldClose()) -- Detect window close button or ESC key do -- Update ------------------------------------------------------------------------------------ UpdateGame(); ------------------------------------------------------------------------------------ -- Draw ------------------------------------------------------------------------------------ DrawGame(); ------------------------------------------------------------------------------------ end UnloadGame(); -- Unload loaded data (textures, sounds, models...) CloseWindow(); -- Close window and OpenGL context