raylib/games/arkanoid.lua
2016-08-06 16:58:48 +02:00

298 lines
10 KiB
Lua

--[[
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