#include "pong.h"
#include "sounds.h"
#include <setjmp.h>
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);
}