From b1de6008bdfbd5bdeb62d2d3dad953019555556b Mon Sep 17 00:00:00 2001 From: Charadon Date: Mon, 30 May 2022 21:07:45 -0400 Subject: Initial Commit --- Makefile | 25 ++++++ net.iotib.Pong.yml | 20 +++++ resources/ball.png | Bin 0 -> 120 bytes resources/bounce.wav | Bin 0 -> 417592 bytes resources/defeat.wav | Bin 0 -> 488992 bytes resources/paddle.png | Bin 0 -> 586 bytes resources/title.wav | Bin 0 -> 11835216 bytes resources/victory.wav | Bin 0 -> 521000 bytes src/ball.c | 68 ++++++++++++++++ src/enemy.c | 37 +++++++++ src/main.c | 218 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/pong.h | 49 ++++++++++++ src/sounds.h | 10 +++ src/title.c | 72 +++++++++++++++++ 14 files changed, 499 insertions(+) create mode 100644 Makefile create mode 100644 net.iotib.Pong.yml create mode 100644 resources/ball.png create mode 100644 resources/bounce.wav create mode 100644 resources/defeat.wav create mode 100644 resources/paddle.png create mode 100644 resources/title.wav create mode 100644 resources/victory.wav create mode 100644 src/ball.c create mode 100644 src/enemy.c create mode 100644 src/main.c create mode 100644 src/pong.h create mode 100644 src/sounds.h create mode 100644 src/title.c diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..153d346 --- /dev/null +++ b/Makefile @@ -0,0 +1,25 @@ +CC := gcc +CFLAGS = -Og -Wall -std=c11 -Isrc/ +LDFLAGS = +PKG_CONF := pkg-config +PKG_CONF_ARGS = --exists --modversion +PKG_CONF_LDFLAGS = `pkgconf --libs raylib` +PKG_CONF_CFLAGS = `pkgconf --cflags raylib` + +all: check_deps build pong + + +check_deps: + @echo "Checking for dependencies..." + @printf "Raylib | " + @$(PKG_CONF) $(PKG_CONF_ARGS) raylib + +build: src/main.c src/enemy.c src/ball.c src/title.c + $(CC) $(CFLAGS) $(PKG_CONF_CFLAGS) -c $? + +pong: main.o enemy.o ball.o title.o + $(CC) $? -o $@ $(LDFLAGS) $(PKG_CONF_LDFLAGS) -lGL -lm -lpthread -ldl -lrt -lX11 + +clean: + rm -fv *.o + rm -fv pong diff --git a/net.iotib.Pong.yml b/net.iotib.Pong.yml new file mode 100644 index 0000000..49d10bd --- /dev/null +++ b/net.iotib.Pong.yml @@ -0,0 +1,20 @@ +app-id: net.iotib.Pong +runtime: org.freedesktop.Platform +runtime-version: '21.08' +sdk: org.freedesktop.Sdk +command: /app/Pong/Pong +modules: + - name: Pong + buildsystem: simple + build-commands: + - make + - mkdir -p /app/Pong + - cp -r resources /app/Pong + - install -Dm755 Pong /app/Pong/Pong + sources: + - type: file + path: Makefile + - type: dir + path: src/ + - type: dir + path: resources/ \ No newline at end of file diff --git a/resources/ball.png b/resources/ball.png new file mode 100644 index 0000000..cba7f00 Binary files /dev/null and b/resources/ball.png differ diff --git a/resources/bounce.wav b/resources/bounce.wav new file mode 100644 index 0000000..6b3e7fc Binary files /dev/null and b/resources/bounce.wav differ diff --git a/resources/defeat.wav b/resources/defeat.wav new file mode 100644 index 0000000..010707d Binary files /dev/null and b/resources/defeat.wav differ diff --git a/resources/paddle.png b/resources/paddle.png new file mode 100644 index 0000000..c27108b Binary files /dev/null and b/resources/paddle.png differ diff --git a/resources/title.wav b/resources/title.wav new file mode 100644 index 0000000..5641e18 Binary files /dev/null and b/resources/title.wav differ diff --git a/resources/victory.wav b/resources/victory.wav new file mode 100644 index 0000000..7ac4dfa Binary files /dev/null and b/resources/victory.wav differ diff --git a/src/ball.c b/src/ball.c new file mode 100644 index 0000000..7a9e7cb --- /dev/null +++ b/src/ball.c @@ -0,0 +1,68 @@ +#include "raylib.h" +#include "pong.h" + +void ball(Rectangle *Player, Rectangle *Enemy, struct Balls *Ball, int *PlayerScore, int *EnemyScore) { + + // Moves ball + Ball->Y += Ball->Angle; + if (Ball->Direction == LEFT) { + Ball->X -= Ball->Speed; + } else { + Ball->X += Ball->Speed; + } + // Moves hitbox with ball. + Ball->HitBox.x = Ball->X; + Ball->HitBox.y = Ball->Y; + + // Check collisions against players. + if (CheckCollisionRecs(*Player, Ball->HitBox) && Ball->Direction == LEFT) { + Ball->Direction = RIGHT; + Ball->Speed *= 1.5f; + if (Ball->Speed > 40) { + Ball->Speed = 40; + } + if (Ball->Speed != 40) { + Ball->Angle = GetRandomValue(-10, 10); + } else { + Ball->Angle = GetRandomValue(-20, 20); + } + play_audio(0); + } + if (CheckCollisionRecs(*Enemy, Ball->HitBox) && Ball->Direction == RIGHT) { + Ball->Direction = LEFT; + Ball->Speed *= 1.5f; + if (Ball->Speed > 40) { + Ball->Speed = 40; + } + if (Ball->Speed != 40) { + Ball->Angle = GetRandomValue(-10, 10); + } else { + Ball->Angle = GetRandomValue(-30, 30); + } + play_audio(SOUND_BOUNCE); + } + + // Bounce ball if touches top or bottom of screen. + if ( (Ball->Y+32 >= 720 && Ball->Angle >=1) || (Ball->Y <= 0 && Ball->Angle <= -1) ) { + Ball->Angle *= -1; + play_audio(SOUND_BOUNCE); + } + + // Calculates score and resets ball. + bool Scored = false; + if (Ball->X < 0) { + *EnemyScore += 1; + Scored = true; + } else if (Ball ->X > 1280) { + *PlayerScore += 1; + Scored = true; + } + if (Scored == true) { + Ball->X = 1280/2.0f; + Ball->Y = 720/2.0f; + Ball->Speed = 3.0f; + Ball->Angle = 0; + } + + return; +} \ No newline at end of file diff --git a/src/enemy.c b/src/enemy.c new file mode 100644 index 0000000..e5e0a2b --- /dev/null +++ b/src/enemy.c @@ -0,0 +1,37 @@ +#include "raylib.h" +#include "pong.h" + +void enemy(struct Players *Enemy, struct Balls ball) { + if (atomic_load(&Ticks) % 1 == 0) { + if (!CheckCollisionRecs(ball.HitBox, Enemy->BallDetector)) { + if (Enemy->Y+120 > ball.Y) { + Enemy->Direction = 0; + } else if (Enemy->Y < ball.Y) { + Enemy->Direction = 1; + } + } else { + Enemy->Direction = 3; + } + } + + switch(Enemy->Direction) { + case 0: + Enemy->Y -= 15; + break; + case 1: + Enemy->Y += 15; + break; + default: + break; + } + + // Prevents from going off screen. + if ( Enemy->Y > 480 ) { + Enemy->Y = 480; + } else if (Enemy->Y < 0) { + Enemy->Y = 0; + } + Enemy->HitBox.y = Enemy->Y; + Enemy->BallDetector.y = Enemy->Y+80; + return; +} \ No newline at end of file diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..d4120e8 --- /dev/null +++ b/src/main.c @@ -0,0 +1,218 @@ +#include "pong.h" +#include "sounds.h" +#include + + +int Difficulty = 1; +atomic_int Ticks = 0; +bool GameGoing = true; + +mtx_t AudioQueueBeingModified; + +int AudioQueue[20]; + +int internal_clock() { + const struct timespec Delay = { + 0, 20000000 + }; + struct timespec Remaining; + while(GameGoing == true) { + atomic_fetch_add(&Ticks, 1); + thrd_sleep(&Delay, &Remaining); + } + thrd_exit(0); +} + +int audio() { + int i; + InitAudioDevice(); + Sound Bounce = LoadSound("resources/bounce.wav"); + Sound TitleScreen = LoadSound("resources/title.wav"); + Sound Victory = LoadSound("resources/victory.wav"); + Sound Defeat = LoadSound("resources/defeat.wav"); + const struct timespec Delay = { + 0, 20000000 + }; + struct timespec Remaining; + while(GameGoing == true) { + for(i = 0; i < 20; i++) { + if(AudioQueue[i] != -1){ + switch(AudioQueue[i]) { + case 0: //Play bounce sound. + PlaySoundMulti(Bounce); + break; + case 1: //Play game over + PlaySoundMulti(Defeat); + break; + case 2: //Play win + PlaySoundMulti(Victory); + break; + case 3: //Title Screen + PlaySoundMulti(TitleScreen); + break; + case 99: //Stop All Sounds + StopSoundMulti(); + break; + default: + break; + } + while(mtx_trylock(&AudioQueueBeingModified) == thrd_busy) thrd_sleep(&Delay, &Remaining); + AudioQueue[i] = -1; + mtx_unlock(&AudioQueueBeingModified); + } + } + thrd_sleep(&Delay, &Remaining); + } + thrd_exit(0); +} + +bool play_audio(int SoundEffect) { + int i; + while(mtx_trylock(&AudioQueueBeingModified) == thrd_busy); + for(i = 1; i != 20; i++) { + if (AudioQueue[i-1] == -1) { + AudioQueue[i-1] = AudioQueue[i]; + } + } + for(i = 0; AudioQueue[i] != -1; i++) { + if(i > sizeof(AudioQueue)) { + mtx_unlock(&AudioQueueBeingModified); + return false; + } + } + AudioQueue[i] = SoundEffect; + mtx_unlock(&AudioQueueBeingModified); + return true; +} + +int main() { + //Raylib Init + InitWindow(1280, 720, "Pong"); + SetTargetFPS(60); + SetExitKey(KEY_Q); + Image Icon = LoadImage("resources/ball.png"); + SetWindowIcon(Icon); + SetWindowState(FLAG_VSYNC_HINT); + SetWindowState(FLAG_WINDOW_RESIZABLE); + + //Initialize Variables + Camera2D MainCamera; + MainCamera.target = (Vector2){0, 0}; + MainCamera.offset = (Vector2){0, 0}; + MainCamera.rotation = 0; + //Populate Audio Queue + for(int i = 0; i < sizeof(AudioQueue); i++) { + AudioQueue[i] = -1; + printf("%d\n", AudioQueue[i]); + } + mtx_init(&AudioQueueBeingModified, mtx_plain); + + // Init Player Variables + struct Players Player; + Player.Score = 0; + char PlayerScore[50]; // Used later to display score on screen. + + // Init Enemy Variables + struct Players Enemy; + Enemy.Score = 0; + Enemy.Direction = 0; + char EnemyScore[50]; + + struct Balls Ball; + Ball.X = 1280/2.0f; + Ball.Y = 720/2.0f; + Ball.Direction = LEFT; + Ball.Speed = 3.0f; + Ball.Angle = 0.0f; + + + // Set Sprites + Texture2D PaddleSprite = LoadTexture("resources/paddle.png"); + Texture2D BallSprite = LoadTexture("resources/ball.png"); + + // Set Collision Boxes + Player.HitBox = (Rectangle){80, Player.Y, 5, PaddleSprite.height}; + Enemy.HitBox = (Rectangle){1200, Enemy.Y, 5, PaddleSprite.height}; + Ball.HitBox = (Rectangle){Ball.X, Ball.Y, BallSprite.width, BallSprite.height}; + Enemy.BallDetector = (Rectangle){0, Enemy.Y+120, 1280, PaddleSprite.height/5.0f}; + + // Debug + Player.Y = 200; + + // Initialize Internal Clock + thrd_t InternalClock; + thrd_create(&InternalClock, internal_clock, NULL); + thrd_t AudioThread; + thrd_create(&AudioThread, audio, NULL); + + // Launch Title Screen + jmp_buf RestartGame; + setjmp(RestartGame); + title_screen(); + play_audio(99); + Enemy.Score = 0; + Player.Score = 0; + + while(!WindowShouldClose() && GameGoing == true) { + MainCamera.zoom = GetScreenHeight()/720.0f; + if (Enemy.Score >= 5) { + play_audio(MUSIC_DEFEAT); + longjmp(RestartGame, 0); + } else if (Player.Score >= 5) { + play_audio(MUSIC_VICTORY); + longjmp(RestartGame, 0); + } + //Controls + if(IsKeyDown(KEY_UP)) { + Player.Y -= 10; + } else if (IsKeyDown(KEY_DOWN)) { + Player.Y += 10; + } else if(IsKeyPressed(KEY_ESCAPE)) { + EnableCursor(); + } else if(IsMouseButtonPressed(MOUSE_BUTTON_LEFT) || IsCursorHidden() == true) { + Player.Y = GetMouseY()-PaddleSprite.height/2.0f; + DisableCursor(); + } + + if(GetMouseY() < 0) { + SetMousePosition(0, 0); + } else if(GetMouseY() > 720) { + SetMousePosition(0, 720); + } + + //Check if players are off-screen + if (Player.Y < 0) { + Player.Y = 0; + } else if (Player.Y > 480) { + Player.Y = 480; + } + + enemy(&Enemy, Ball); + + // Collision + ball(&Player.HitBox, &Enemy.HitBox, &Ball, &Player.Score, &Enemy.Score); + + //Updates hitbox with player's position. + Player.HitBox.y = Player.Y; + + //Turn Scores into strings. + snprintf(PlayerScore, 50, "Player: %d", Player.Score); + snprintf(EnemyScore, 50, "Enemy: %d", Enemy.Score); + + BeginDrawing(); + ClearBackground(BLACK); + BeginMode2D(MainCamera); + DrawTexture(PaddleSprite, 0, Player.Y, WHITE); + DrawTexture(PaddleSprite, 1200, Enemy.Y, WHITE); + DrawTexture(BallSprite, Ball.X, Ball.Y, WHITE); + //DrawRectangleRec(Enemy.BallDetector, RED); + DrawText(PlayerScore, 0, 0, 32, GREEN); + DrawText(EnemyScore, 1130, 688, 32, RED); + EndMode2D(); + EndDrawing(); + } + GameGoing = false; + thrd_join(AudioThread, NULL); + CloseWindow(); + return(0); +} diff --git a/src/pong.h b/src/pong.h new file mode 100644 index 0000000..ab74d07 --- /dev/null +++ b/src/pong.h @@ -0,0 +1,49 @@ +#ifndef PONG_H +#define PONG_H +#include "raylib.h" +#include +#include +#include +#include +#include +#include +#include +#include + +#define LEFT 0 +#define RIGHT 1 + +struct Players { + float Y; + Rectangle HitBox; + int Score; + int Direction; + Rectangle BallDetector; +}; + +struct Balls { + float X; + float Y; + float Angle; + float Speed; + int Direction; + Rectangle HitBox; +}; + +extern int Difficulty; +extern bool GameGoing; +extern atomic_int Ticks; + +void enemy(struct Players *Enemy, struct Balls ball); +void ball(Rectangle *Player, Rectangle *Enemy, struct Balls *Ball, int *PlayerScore, int *EnemyScore); +bool play_audio(int SoundEffect); +void title_screen(); + +//Sounds +extern const int SOUND_BOUNCE; +extern const int MUSIC_DEFEAT; +extern const int MUSIC_VICTORY; +extern const int MUSIC_TITLE; +extern const int STOP_ALL_SOUNDS; + +#endif \ No newline at end of file diff --git a/src/sounds.h b/src/sounds.h new file mode 100644 index 0000000..75a2455 --- /dev/null +++ b/src/sounds.h @@ -0,0 +1,10 @@ +#ifndef SOUNDS_H +#define SOUNDS_H + +const int SOUND_BOUNCE = 0; +const int MUSIC_DEFEAT = 1; +const int MUSIC_VICTORY = 2; +const int MUSIC_TITLE = 3; +const int STOP_ALL_SOUNDS = 99; + +#endif \ No newline at end of file diff --git a/src/title.c b/src/title.c new file mode 100644 index 0000000..fd57c2e --- /dev/null +++ b/src/title.c @@ -0,0 +1,72 @@ +#include "pong.h" + +void help_text() { + +} + +void title_screen() { + Camera2D MainCamera; + MainCamera.offset = (Vector2){0,0}; + MainCamera.target = (Vector2){0,0}; + MainCamera.rotation = 0.0f; + bool TitleScreenGoing = true; + play_audio(MUSIC_TITLE); + Rectangle Versus = { + 20, 150, 230, 48 + }; + Rectangle Marathon = { + 20, 200, 230, 48 + }; + Rectangle Settings = { + 20, 250, 230, 48 + }; + Rectangle Help = { + 20, 300, 230, 48 + }; + Rectangle Exit = { + 20, 350, 230, 48 + }; + Rectangle Mouse = { + 0, 0, 10, 10 + }; + Rectangle *Selected; + Selected = &Versus; + while(!WindowShouldClose() && TitleScreenGoing == true) { + MainCamera.zoom = GetScreenHeight()/720.0f; + Mouse.x = GetMouseX()/MainCamera.zoom; + Mouse.y = GetMouseY()/MainCamera.zoom; + if (CheckCollisionRecs(Mouse, Versus)) { + Selected = &Versus; + if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT)) { + return; + } + } else if (CheckCollisionRecs(Mouse, Marathon)) { + Selected = &Marathon; + } else if (CheckCollisionRecs(Mouse, Settings)) { + Selected = &Settings; + } else if (CheckCollisionRecs(Mouse, Help)) { + Selected = &Help; + } else if (CheckCollisionRecs(Mouse, Exit)) { + Selected = &Exit; + if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT)) { + GameGoing = false; + return; + } + } + MainCamera.zoom = GetScreenHeight()/720.0f; + BeginDrawing(); + ClearBackground(BLACK); + BeginMode2D(MainCamera); + DrawRectangleRec(*Selected, RED); + DrawText("PONG", 0, 0, 128, WHITE); + DrawText("Versus", 20, 150, 48, WHITE); + DrawText("Marathon", 20, 200, 48, WHITE); + DrawText("Settings", 20, 250, 48, WHITE); + DrawText("Help", 20, 300, 48, WHITE); + DrawText("Exit", 20, 350, 48, WHITE); + DrawRectangleRec(Mouse, YELLOW); + EndMode2D(); + EndDrawing(); + } + return; +} \ No newline at end of file -- cgit 1.4.1-2-gfad0