summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOskari Timperi <oskari.timperi@iki.fi>2016-09-07 18:22:41 +0300
committerOskari Timperi <oskari.timperi@iki.fi>2016-09-07 18:22:41 +0300
commit7a080b6d053fd0965641ee38dcd55fb7f015ebba (patch)
tree2b2e8a784cc729649b4bf2107305b3b788980618
downloadbreakout-master.tar.gz
breakout-master.zip
Initial commitHEADmaster
-rw-r--r--Makefile16
-rw-r--r--Makefile.mingw15
-rw-r--r--main.c274
-rw-r--r--timer.c48
-rw-r--r--timer.h16
5 files changed, 369 insertions, 0 deletions
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..35c00a4
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,16 @@
+CC = gcc
+RAYLIB = ../raylib
+INCDIR = -I$(RAYLIB)/src
+CFLAGS += -Wall $(INCDIR)
+LDFLAGS += $(LIBDIR)
+LIBRAYLIB = $(RAYLIB)/release/linux/libraylib.a
+LIBGLFW3 = $(RAYLIB)/src/external/glfw3/lib/linux/libglfw3.a
+LDLIBS += $(LIBRAYLIB) $(LIBGLFW3) -lm -ldl -lpthread -lX11 -lXrandr \
+ -lXinerama -lXi -lXxf86vm -lXcursor
+
+breakout: main.c timer.c
+ $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ $(LDLIBS)
+
+.PHONY: clean
+clean:
+ rm -f breakout
diff --git a/Makefile.mingw b/Makefile.mingw
new file mode 100644
index 0000000..dd4c833
--- /dev/null
+++ b/Makefile.mingw
@@ -0,0 +1,15 @@
+CC = i686-w64-mingw32-gcc
+RAYLIB = ../raylib
+INCDIR = -I$(RAYLIB)/src
+CFLAGS += -Wall $(INCDIR)
+LDFLAGS += $(LIBDIR)
+LIBRAYLIB = $(RAYLIB)/release/win32/mingw32/libraylib.a
+LIBGLFW3 = $(RAYLIB)/src/external/glfw3/lib/win32/libglfw3.a
+LDLIBS += $(LIBRAYLIB) $(LIBGLFW3) -lgdi32
+
+breakout.exe: main.c timer.c
+ $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ $(LDLIBS)
+
+.PHONY: clean
+clean:
+ rm -f breakout
diff --git a/main.c b/main.c
new file mode 100644
index 0000000..79ae2ce
--- /dev/null
+++ b/main.c
@@ -0,0 +1,274 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+#include <time.h>
+
+#include "raylib.h"
+
+#include "timer.h"
+
+#define screenWidth (800)
+#define screenHeight (600)
+#define tileCountX (7)
+#define tileCountY (5)
+#define xMargin (10)
+#define yMargin (10)
+#define levelYOffset (20)
+#define ballRadius (5)
+#define tileWidth ((screenWidth - xMargin*2) / tileCountX)
+#define tileHeight ((screenHeight / 2 - yMargin - levelYOffset) / tileCountY)
+static const Color tileColor[5] = { RED, GREEN, BLUE };
+
+typedef struct Game
+{
+ Rectangle paddle;
+ Vector2 ball;
+ Vector2 ballVelocity;
+ Timer movementTimer;
+ int tiles[tileCountX][tileCountY];
+ bool started;
+ int score;
+ bool gameOver;
+} Game;
+
+bool CheckBallCollisionRec(Vector2 center, float radius, Rectangle rec,
+ Vector2 *velocity)
+{
+ if (CheckCollisionCircleRec(center, radius, rec))
+ {
+ if (rec.x >= center.x)
+ {
+ velocity->x = -velocity->x;
+ }
+ else if (rec.x+rec.width <= center.x)
+ {
+ velocity->x = -velocity->x;
+ }
+ else if (rec.y >= center.y)
+ {
+ velocity->y = -velocity->y;
+ }
+ else if (rec.y+rec.height <= center.y)
+ {
+ velocity->y = -velocity->y;
+ }
+
+ return true;
+ }
+
+ return false;
+}
+
+void GameInitialize(Game *game)
+{
+ memset(game, 0, sizeof(*game));
+
+ game->paddle.width = 50;
+ game->paddle.height = 10;
+ game->paddle.x = screenWidth / 2 - game->paddle.width / 2;
+ game->paddle.y = screenHeight - yMargin - game->paddle.height;
+
+ game->ball.x = screenWidth / 2;
+ game->ball.y = screenHeight - screenHeight / 4;
+
+ game->ballVelocity.x = 100;
+ game->ballVelocity.y = -100;
+
+ TimerStart(&game->movementTimer);
+
+ for (int i = 0; i < tileCountX; ++i)
+ {
+ for (int j = 0; j < tileCountY; ++j)
+ {
+ game->tiles[i][j] = GetRandomValue(1, 3);
+ }
+ }
+}
+
+Rectangle GetTileRect(int tx, int ty)
+{
+ Rectangle tile;
+
+ tile.x = xMargin + tx * tileWidth;
+ tile.y = yMargin + levelYOffset + ty * tileHeight;
+ tile.width = tileWidth;
+ tile.height = tileHeight;
+
+ return tile;
+}
+
+void GameHandleKeys(Game *game, int64_t elapsed)
+{
+ if (!game->gameOver)
+ {
+ if (IsKeyDown(KEY_RIGHT))
+ {
+ game->paddle.x += 160 * elapsed / 1000 / 1000;
+ if (!game->started)
+ game->started = true;
+ }
+ else if (IsKeyDown(KEY_LEFT))
+ {
+ game->paddle.x -= 160 * elapsed / 1000 / 1000;
+ if (!game->started)
+ game->started = true;
+ }
+
+ if (game->paddle.x < 0)
+ game->paddle.x = 0;
+ else if (game->paddle.x > screenWidth - game->paddle.width)
+ game->paddle.x = screenWidth - game->paddle.width;
+ }
+ else
+ {
+ if (IsKeyPressed(KEY_SPACE))
+ {
+ GameInitialize(game);
+ }
+ }
+}
+
+void GameHandleBallTileCollisions(Game *game)
+{
+ for (int i = 0; i < tileCountX; ++i)
+ {
+ for (int j = 0; j < tileCountY; ++j)
+ {
+ Rectangle tileRect = GetTileRect(i, j);
+
+ if (!game->tiles[i][j])
+ continue;
+
+ if (CheckBallCollisionRec(game->ball, 5, tileRect,
+ &game->ballVelocity))
+ {
+ game->tiles[i][j] -= 1;
+ game->score++;
+ if (game->tiles[i][j] == 0)
+ game->score++;
+ return;
+ }
+ }
+ }
+}
+
+void GameHandleBallPaddleCollision(Game *game)
+{
+ CheckBallCollisionRec(game->ball, 5, game->paddle, &game->ballVelocity);
+}
+
+void GameHandleBallScreenCollision(Game *game)
+{
+ if (game->ball.x+5 >= screenWidth)
+ {
+ game->ball.x = screenWidth-5;
+ game->ballVelocity.x = -game->ballVelocity.x;
+ }
+ else if (game->ball.x-5 <= 0)
+ {
+ game->ball.x = 5;
+ game->ballVelocity.x = -game->ballVelocity.x;
+ }
+
+ if (game->ball.y-5 <= 0)
+ {
+ game->ball.y = 5;
+ game->ballVelocity.y = -game->ballVelocity.y;
+ }
+ else if (game->ball.y+5 >= screenHeight)
+ {
+ game->gameOver = true;
+ }
+}
+
+void GameUpdate(Game *game)
+{
+ int64_t elapsed = TimerElapsedMicro(&game->movementTimer);
+
+ GameHandleKeys(game, elapsed);
+
+ if (!game->gameOver)
+ {
+ if (game->started)
+ {
+ game->ball.x += game->ballVelocity.x * elapsed / 1000 / 1000;
+ game->ball.y += game->ballVelocity.y * elapsed / 1000 / 1000;
+
+ GameHandleBallScreenCollision(game);
+ GameHandleBallPaddleCollision(game);
+ GameHandleBallTileCollisions(game);
+ }
+ }
+
+ TimerStart(&game->movementTimer);
+}
+
+void DrawTextCentered(const char *text, int width, int y, int size, Color color)
+{
+ int textWidth = MeasureText(text, size);
+ DrawText(text, width/2 - textWidth/2, y, size, color);
+}
+
+void GameDraw(Game *game)
+{
+ BeginDrawing();
+
+ ClearBackground(RAYWHITE);
+
+ DrawRectangleRec(game->paddle, BLACK);
+
+ DrawCircle(game->ball.x, game->ball.y, 5, BLACK);
+
+ for (int i = 0; i < tileCountX; ++i)
+ {
+ for (int j = 0; j < tileCountY; ++j)
+ {
+ Rectangle tileRect = GetTileRect(i, j);
+ Color color = tileColor[game->tiles[i][j]-1];
+ DrawRectangleRec(tileRect, color);
+ }
+ }
+
+ DrawText(FormatText("SCORE: %i", game->score), xMargin, yMargin, 20,
+ MAROON);
+
+ if (!game->started)
+ {
+ DrawTextCentered("START!", screenWidth, screenHeight/2, 40, BLACK);
+ }
+
+ if (game->gameOver)
+ {
+ DrawTextCentered("GAME OVER!", screenWidth, screenHeight/2, 40, BLACK);
+ DrawTextCentered("Press SPACE to try again.", screenWidth,
+ screenHeight/2 + 40, 20, BLACK);
+ }
+
+ EndDrawing();
+}
+
+int main(int argc, char **argv)
+{
+ Game game;
+
+ srand(time(0));
+
+ TimerInit();
+
+ GameInitialize(&game);
+
+ InitWindow(screenWidth, screenHeight, "Breakout");
+
+ SetTargetFPS(60);
+
+ while (!WindowShouldClose())
+ {
+ GameUpdate(&game);
+ GameDraw(&game);
+ }
+
+ CloseWindow();
+
+ return 0;
+}
diff --git a/timer.c b/timer.c
new file mode 100644
index 0000000..e437397
--- /dev/null
+++ b/timer.c
@@ -0,0 +1,48 @@
+#include "timer.h"
+
+#include <time.h>
+
+#if defined(_WIN32)
+#include <windows.h>
+int64_t frequency;
+#endif
+
+void TimerInit()
+{
+#if defined(_WIN32)
+ QueryPerformanceFrequency((LARGE_INTEGER *) &frequency);
+#endif
+}
+
+int64_t TimerGetTimeMicro()
+{
+#if defined(_WIN32)
+ int64_t value;
+ QueryPerformanceCounter((LARGE_INTEGER *) &value);
+ value = value * 1000LL*1000LL;
+ return value / frequency;
+#else
+ struct timespec tp;
+ if (clock_gettime(CLOCK_MONOTONIC, &tp))
+ {
+ return 0;
+ }
+ return (((int64_t) tp.tv_sec) * 1000LL*1000LL*1000LL + ((int64_t) tp.tv_nsec)) / 1000LL;
+#endif
+}
+
+void TimerStart(Timer *timer)
+{
+ *timer = TimerGetTimeMicro();
+}
+
+int64_t TimerElapsedMicro(Timer *timer)
+{
+ int64_t now = TimerGetTimeMicro(timer);
+ return now - *timer;
+}
+
+int64_t TimerElapsedMilli(Timer *timer)
+{
+ return TimerElapsedMicro(timer) / 1000LL;
+}
diff --git a/timer.h b/timer.h
new file mode 100644
index 0000000..fd74efe
--- /dev/null
+++ b/timer.h
@@ -0,0 +1,16 @@
+#ifndef TIMER_H
+#define TIMER_H
+
+#include <stdint.h>
+
+typedef int64_t Timer;
+
+void TimerInit();
+
+void TimerStart(Timer *timer);
+
+int64_t TimerElapsedMicro(Timer *timer);
+
+int64_t TimerElapsedMilli(Timer *timer);
+
+#endif