diff options
| author | Ray <raysan5@gmail.com> | 2016-01-29 07:26:06 -0800 |
|---|---|---|
| committer | Ray <raysan5@gmail.com> | 2016-01-29 07:26:06 -0800 |
| commit | 708e8c558cb843b5e4b071bc2b99102533bafaea (patch) | |
| tree | 83561a8bf0b640c565a684c7a2b1ec80f490c044 /games/samples/arkanoid.c | |
| parent | 4ec0ac89cda482031c393425381a2627a9468f09 (diff) | |
| download | raylib-708e8c558cb843b5e4b071bc2b99102533bafaea.tar.gz raylib-708e8c558cb843b5e4b071bc2b99102533bafaea.zip | |
Added a bunch of sample games
Those games have been developed by students and ported to a common base
template. Some of them still require some review to be consistent with
each other (formatting, variables naming, code structure...)
Diffstat (limited to 'games/samples/arkanoid.c')
| -rw-r--r-- | games/samples/arkanoid.c | 349 |
1 files changed, 349 insertions, 0 deletions
diff --git a/games/samples/arkanoid.c b/games/samples/arkanoid.c new file mode 100644 index 00000000..f10f9383 --- /dev/null +++ b/games/samples/arkanoid.c @@ -0,0 +1,349 @@ +/******************************************************************************************* +* +* 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) +* +********************************************************************************************/ + +#include "raylib.h" + +#include <stdio.h> +#include <stdlib.h> +#include <time.h> +#include <math.h> + +#if defined(PLATFORM_WEB) + #include <emscripten/emscripten.h> +#endif + +//---------------------------------------------------------------------------------- +// Some Defines +//---------------------------------------------------------------------------------- + +#define PLAYER_MAX_LIFE 5 +#define LINES_OF_BRICKS 5 +#define BRICKS_PER_LINE 20 + +//---------------------------------------------------------------------------------- +// Types and Structures Definition +//---------------------------------------------------------------------------------- +typedef enum GameScreen { LOGO, TITLE, GAMEPLAY, ENDING } GameScreen; + +typedef struct Player { + Vector2 position; + Vector2 size; + int life; +} Player; + +typedef struct Ball { + Vector2 position; + Vector2 speed; + int radius; + bool active; +} Ball; + +typedef struct Brick { + Vector2 position; + bool active; +} Brick; + +//------------------------------------------------------------------------------------ +// Global Variables Declaration +//------------------------------------------------------------------------------------ +static int screenWidth = 800; +static int screenHeight = 450; + +static int framesCounter; +static bool gameOver; +static bool pause; + +static Player player; +static Ball ball; +static Brick brick[LINES_OF_BRICKS][BRICKS_PER_LINE]; +static Vector2 brickSize; + +//------------------------------------------------------------------------------------ +// Module Functions Declaration (local) +//------------------------------------------------------------------------------------ +static void InitGame(void); // Initialize game +static void UpdateGame(void); // Update game (one frame) +static void DrawGame(void); // Draw game (one frame) +static void UnloadGame(void); // Unload game +static void UpdateDrawFrame(void); // Update and Draw (one frame) + +// Additional module functions +static void UpdateBall(void); + +//------------------------------------------------------------------------------------ +// Program main entry point +//------------------------------------------------------------------------------------ +int main() +{ + // Initialization + //-------------------------------------------------------------------------------------- + InitWindow(screenWidth, screenHeight, "sample game: arkanoid"); + + InitGame(); + +#if defined(PLATFORM_WEB) + emscripten_set_main_loop(UpdateDrawFrame, 0, 1); +#else + + SetTargetFPS(60); + //-------------------------------------------------------------------------------------- + + // Main game loop + while (!WindowShouldClose()) // Detect window close button or ESC key + { + // Update + //---------------------------------------------------------------------------------- + UpdateGame(); + //---------------------------------------------------------------------------------- + + // Draw + //---------------------------------------------------------------------------------- + DrawGame(); + //---------------------------------------------------------------------------------- + } +#endif + + // De-Initialization + //-------------------------------------------------------------------------------------- + UnloadGame(); // Unload loaded data (textures, sounds, models...) + + CloseWindow(); // Close window and OpenGL context + //-------------------------------------------------------------------------------------- + + return 0; +} + +//------------------------------------------------------------------------------------ +// Module Functions Definitions (local) +//------------------------------------------------------------------------------------ + +// Initialize game variables +void InitGame(void) +{ + 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 + int initialDownPosition = 50; + + for (int i = 0; i < LINES_OF_BRICKS; i++) + { + for (int j = 0; j < BRICKS_PER_LINE; j++) + { + brick[i][j].position = (Vector2){ j*brickSize.x + brickSize.x/2, i*brickSize.y + initialDownPosition }; + brick[i][j].active = true; + } + } +} + +// Update game (one frame) +void UpdateGame(void) +{ + if (!gameOver) + { + if (IsKeyPressed('P')) pause = !pause; + + if (!pause) + { + // Player movement + if (IsKeyDown(KEY_LEFT)) player.position.x -= 5; + if ((player.position.x - player.size.x/2) <= 0) player.position.x = player.size.x/2; + if (IsKeyDown(KEY_RIGHT)) player.position.x += 5; + if ((player.position.x + player.size.x/2) >= screenWidth) player.position.x = screenWidth - player.size.x/2; + + // Launch ball + if (!ball.active) + { + if (IsKeyPressed(KEY_SPACE)) + { + ball.active = true; + ball.speed = (Vector2){ 0, -5 }; + } + } + + UpdateBall(); + + // Game over logic + if (player.life <= 0) gameOver = true; + else + { + gameOver = true; + + for (int i = 0; i < LINES_OF_BRICKS; i++) + { + for (int j = 0; j < BRICKS_PER_LINE; j++) + { + if (brick[i][j].active) gameOver = false; + } + } + } + } + } + else + { + if (IsKeyPressed(KEY_ENTER)) + { + InitGame(); + gameOver = false; + } + } + + +} + +// Draw game (one frame) +void DrawGame(void) +{ + BeginDrawing(); + + ClearBackground(RAYWHITE); + + if (!gameOver) + { + // 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 (int i = 0; i < player.life; i++) DrawRectangle(20 + 40*i, screenHeight - 30, 35, 10, LIGHTGRAY); + + // Draw ball + DrawCircleV(ball.position, ball.radius, MAROON); + + // Draw bricks + for (int i = 0; i < LINES_OF_BRICKS; i++) + { + for (int j = 0; j < BRICKS_PER_LINE; j++) + { + if (brick[i][j].active) + { + if ((i + j) % 2 == 0) 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); + } + } + } + + if (pause) DrawText("GAME PAUSED", screenWidth/2 - MeasureText("GAME PAUSED", 40)/2, screenHeight/2 - 40, 40, GRAY); + } + else DrawText("PRESS [ENTER] TO PLAY AGAIN", GetScreenWidth()/2 - MeasureText("PRESS [ENTER] TO PLAY AGAIN", 20)/2, GetScreenHeight()/2 - 50, 20, GRAY); + + EndDrawing(); +} + +// Unload game variables +void UnloadGame(void) +{ + // TODO: Unload all dynamic loaded data (textures, sounds, models...) +} + +// Update and Draw (one frame) +void UpdateDrawFrame(void) +{ + UpdateGame(); + DrawGame(); +} + +//-------------------------------------------------------------------------------------- +// Additional module functions +//-------------------------------------------------------------------------------------- +static void UpdateBall() +{ + // Update position + if (ball.active) + { + ball.position.x += ball.speed.x; + ball.position.y += ball.speed.y; + } + else + { + ball.position = (Vector2){ player.position.x, screenHeight*7/8 - 30 }; + } + + // Bounce in x + if (((ball.position.x + ball.radius) >= screenWidth) || ((ball.position.x - ball.radius) <= 0)) ball.speed.x *= -1; + + // Bounce in y + if ((ball.position.y - ball.radius) <= 0) ball.speed.y *= -1; + + // Ball reaches bottom of the screen + if ((ball.position.y + ball.radius) >= screenHeight) + { + ball.speed = (Vector2){ 0, 0 }; + ball.active = false; + + player.life--; + } + + // 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})) + { + if (ball.speed.y > 0) + { + ball.speed.y *= -1; + ball.speed.x = (ball.position.x - player.position.x)/(player.size.x/2)*5; + } + } + + // Collision logic: ball vs bricks + for (int i = 0; i < LINES_OF_BRICKS; i++) + { + for (int j = 0; j < BRICKS_PER_LINE; j++) + { + if (brick[i][j].active) + { + // Hit below + if (((ball.position.y - ball.radius) <= (brick[i][j].position.y + brickSize.y/2)) && + ((ball.position.y - ball.radius) > (brick[i][j].position.y + brickSize.y/2 + ball.speed.y)) && + ((fabs(ball.position.x - brick[i][j].position.x)) < (brickSize.x/2 + ball.radius*2/3)) && (ball.speed.y < 0)) + { + brick[i][j].active = false; + ball.speed.y *= -1; + } + // Hit above + else if (((ball.position.y + ball.radius) >= (brick[i][j].position.y - brickSize.y/2)) && + ((ball.position.y + ball.radius) < (brick[i][j].position.y - brickSize.y/2 + ball.speed.y)) && + ((fabs(ball.position.x - brick[i][j].position.x)) < (brickSize.x/2 + ball.radius*2/3)) && (ball.speed.y > 0)) + { + brick[i][j].active = false; + ball.speed.y *= -1; + } + // Hit left + else if (((ball.position.x + ball.radius) >= (brick[i][j].position.x - brickSize.x/2)) && + ((ball.position.x + ball.radius) < (brick[i][j].position.x - brickSize.x/2 + ball.speed.x)) && + ((fabs(ball.position.y - brick[i][j].position.y)) < (brickSize.y/2 + ball.radius*2/3)) && (ball.speed.x > 0)) + { + brick[i][j].active = false; + ball.speed.x *= -1; + } + // Hit right + else if (((ball.position.x - ball.radius) <= (brick[i][j].position.x + brickSize.x/2)) && + ((ball.position.x - ball.radius) > (brick[i][j].position.x + brickSize.x/2 + ball.speed.x)) && + ((fabs(ball.position.y - brick[i][j].position.y)) < (brickSize.y/2 + ball.radius*2/3)) && (ball.speed.x < 0)) + { + brick[i][j].active = false; + ball.speed.x *= -1; + } + } + } + } +}
\ No newline at end of file |
