aboutsummaryrefslogtreecommitdiff
path: root/games/samples/arkanoid.c
diff options
context:
space:
mode:
authorRay <raysan5@gmail.com>2016-01-29 07:26:06 -0800
committerRay <raysan5@gmail.com>2016-01-29 07:26:06 -0800
commit708e8c558cb843b5e4b071bc2b99102533bafaea (patch)
tree83561a8bf0b640c565a684c7a2b1ec80f490c044 /games/samples/arkanoid.c
parent4ec0ac89cda482031c393425381a2627a9468f09 (diff)
downloadraylib-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.c349
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