diff --git a/.gitignore b/.gitignore index f8a2da4..05c7d92 100644 --- a/.gitignore +++ b/.gitignore @@ -8,7 +8,9 @@ sdl2-config *.exclude *.o +highscoretest.c *.psd *.exe !bhi.exe .tags* +*.txt diff --git a/Dokumentation.pdf b/Dokumentation.pdf new file mode 100644 index 0000000..bb4e4c9 Binary files /dev/null and b/Dokumentation.pdf differ diff --git a/Makefile b/Makefile index 2ae71aa..64bd708 100644 --- a/Makefile +++ b/Makefile @@ -10,7 +10,4 @@ args = -o all: $(compiler) $(warningLevel) $(includes) $(sources) $(linker) $(libs) $(args) $(dir)\$(target) - -run: - cd $(dir) && \ - $(target) + cd $(dir) && $(target) diff --git a/bin/System.Web.Helpers.dll b/bin/System.Web.Helpers.dll new file mode 100644 index 0000000..be23db7 Binary files /dev/null and b/bin/System.Web.Helpers.dll differ diff --git a/assets/images/ball.png b/bin/assets/images/ball.png similarity index 100% rename from assets/images/ball.png rename to bin/assets/images/ball.png diff --git a/bin/assets/images/paddle.png b/bin/assets/images/paddle.png new file mode 100644 index 0000000..4d54f4b Binary files /dev/null and b/bin/assets/images/paddle.png differ diff --git a/bin/bhi.exe b/bin/bhi.exe index a9e5451..0008cb1 100644 Binary files a/bin/bhi.exe and b/bin/bhi.exe differ diff --git a/bin/zlib1.dll b/bin/zlib1.dll index a364c4c..1aa57ce 100644 Binary files a/bin/zlib1.dll and b/bin/zlib1.dll differ diff --git a/breakout.c b/breakout.c index 47a7b3d..19bdec2 100644 --- a/breakout.c +++ b/breakout.c @@ -1,4 +1,6 @@ #include +#include +#include #include #include #include @@ -14,25 +16,246 @@ int BREAKOUT_BoxWidth, BREAKOUT_BoxHeight; SDL_Texture * BALL_Texture; +SDL_Rect * BALL_SourceRects; +Ball ball; +Paddle paddle; +SDL_Texture * PADDLE_Texture; +SDL_Rect * PADDLE_SourceRects; +Uint8 * PADDLE_MoveLeftKeys, * PADDLE_MoveRightKeys; +double BALL_Speed = 15.0f; +int PADDLE_Speed = 10; +bool BREAKOUT_IsInit = false; +bool BALL_IsInit = false; +bool PADDLE_IsInit = false; void BREAKOUT_INITIALIZE(SDL_Renderer * renderer, int width, int height){ - printf("Initializing Game...\n"); + if (!BREAKOUT_IsInit) { + printf("Initializing Game...\n"); + srand(time(NULL)); + BREAKOUT_BoxWidth = width; + BREAKOUT_BoxHeight = height; + BALL_Initialize(renderer); + PADDLE_Initialize(renderer); + printf("Game initialized!\n"); + BREAKOUT_IsInit = true; + } else printf("Game is already initialized!\n"); +} + +void BREAKOUT_ChangeSize(int width, int height){ BREAKOUT_BoxWidth = width; BREAKOUT_BoxHeight = height; - BALL_Texture = IMG_LoadTexture(renderer, "assets/images/ball.png"); - if (!BALL_Texture) printf("Ball texture cannot be loaded!\n"); - printf("Game initialized!\n"); } -void BREAKOUT_GAMELOOP(Uint8 * keystate){ - +void BREAKOUT_Update(Uint8 * keystate){ + BALL_Update(&ball, &paddle); + PADDLE_Update(&paddle, keystate); } -void BALL_DRAW(Ball * ball){ +void BREAKOUT_Draw(SDL_Renderer * renderer){ + BALL_Draw(renderer, &ball); + PADDLE_Draw(renderer, &paddle); } -void BREAKOUT_DEINITIALIZE(SDL_Renderer * renderer, int width, int height){ - printf("De-initializing Game...\n"); - SDL_DestroyTexture(BALL_Texture); - printf("Game de-initialized!\n"); +void BREAKOUT_DEINITIALIZE(){ + if (BREAKOUT_IsInit) { + printf("De-initializing Game...\n"); + SDL_DestroyTexture(BALL_Texture); + SDL_DestroyTexture(PADDLE_Texture); + printf("Game de-initialized!\n"); + BREAKOUT_IsInit = false; + } else printf("Game is already de-initialized!\n"); +} + +void BALL_Initialize(SDL_Renderer * renderer){ + if (!BALL_IsInit) { + printf("Initializing Ball...\n"); + BALL_Texture = IMG_LoadTexture(renderer, "assets/images/ball.png"); + if (!BALL_Texture) printf("Ball texture failed to load!\n"); + BALL_SourceRects = (SDL_Rect *)malloc(1 * sizeof(SDL_Rect)); + if (!BALL_SourceRects) printf("FATAL! Memory allocation failed!\n"); + BALL_SourceRects[0] = (SDL_Rect) {.x = 0, .y = 0, .w = 512, .h = 512 }; + ball = BALL_CreateDefault(); + paddle = PADDLE_CreateDefault(); + printf("Ball initialized!\n"); + BALL_IsInit = true; + } else printf("Ball is already initialized!\n"); +} + +Ball BALL_CreateDefault(){ + double rotation = (double)(rand() % 360); + + return (Ball) { + .Location = (Vector) {.x = BREAKOUT_BoxWidth / 2, .y = BREAKOUT_BoxHeight / 2 }, + .Momentum = (Vector) {.x = 0.0f, .y = BALL_Speed }, + .TargetRect = (SDL_Rect) {.x = 0, .y = 0, .w = 50, .h = 50 }, + .Size = 25.0f, + .Rotation = rotation, + .RotationValue = 2, + .TextureIndex = 0 + }; // Objekt für die Eigenschaften des Balls +} + +void BALL_Draw(SDL_Renderer * renderer, Ball * obj){ + // printf("Ball drawn at (%d|%d)!\n", (obj->TargetRect).x, (obj->TargetRect).x); + SDL_RenderCopyEx(renderer, BALL_Texture, BALL_SourceRects + (obj->TextureIndex), &(obj->TargetRect), obj->Rotation, NULL, SDL_FLIP_NONE); +} + +bool BALL_CollideWithRect(Ball * obj, SDL_Rect * rect){ + SDL_Point ballCenter = (SDL_Point) {.x = ((obj->TargetRect).x) + (obj->Size), .y = ((obj->TargetRect).y) + (obj->Size) }; + + // THIS IS CURRENTLY A RECTANGLE COLLIDE + if (((obj->TargetRect).x) + ((obj->TargetRect).w) < (rect->x)) { + return false; + } + if (((obj->TargetRect).x) > (rect->x) + (rect->w)) { + return false; + } + if (((obj->TargetRect).y) + ((obj->TargetRect).w) < (rect->y)) { + return false; + } + if (((obj->TargetRect).y) > (rect->y) + (rect->h)) { + return false; + } + // Folgender Algorithmus ist gefickt, wenn der Ballmittelpunkt + if ((ballCenter.x) < (rect->x) || (ballCenter.x) > (rect->x) + (rect->w)) { + (obj->Momentum).x = -(obj->Momentum).x; + } + if ((ballCenter.y) < (rect->y) || (ballCenter.y) > (rect->y) + (rect->h)) { + (obj->Momentum).y = -(obj->Momentum).y; + } + return true; +} /* BALL_CollideWithRect */ + +bool RECT_Collide(SDL_Rect * rect1, SDL_Rect * rect2){ + if ((rect1->x) + (rect1->w) < (rect2->x)) { + return false; + } + if ((rect1->x) > (rect2->x) + (rect2->w)) { + return false; + } + if ((rect1->y) + (rect1->w) < (rect2->y)) { + return false; + } + if ((rect1->y) > (rect2->y) + (rect2->h)) { + return false; + } + return true; +} + +void BALL_SteerMomentum(Ball * obj, Paddle * paddle){ + int paddleHalfLen = ((paddle->TargetRect).w / 2.0f); + double offset = (((obj->TargetRect).x) + (obj->Size)) - ((paddle->TargetRect).x + paddleHalfLen); + + offset *= 60.0f; + offset /= (double)(paddleHalfLen); + printf("Offset = %.2f\n", offset); + (obj->Momentum) = getScaledDirectionalUnitVector(offset, BALL_Speed); +} + +void BALL_Update(Ball * obj, Paddle * paddle){ + Vector oldMomentum = obj->Momentum; + + (obj->Rotation) += (obj->RotationValue); + (obj->Location) = vectorAdd((obj->Location), oldMomentum); + + if (BALL_CollideWithRect(obj, &(paddle->TargetRect))) { + (obj->Location) = vectorSub((obj->Location), oldMomentum); // Maybe remove this + BALL_SteerMomentum(obj, paddle); + (obj->Location) = vectorAdd((obj->Location), (obj->Momentum)); // Maybe remove this + } + + if ((obj->Location).y > BREAKOUT_BoxHeight) + (obj->Location) = (Vector) {.x = BREAKOUT_BoxWidth / 2, .y = BREAKOUT_BoxHeight / 2 }; // Dead + if ((obj->Location).y < 0.0f) + (obj->Momentum).y = -(obj->Momentum).y; + if ((obj->Location).x < 0.0f || (obj->Location).x > BREAKOUT_BoxWidth - (2 * (obj->Size))) + (obj->Momentum).x = -(obj->Momentum).x; + (obj->TargetRect).x = (int)round((obj->Location).x); + (obj->TargetRect).y = (int)round((obj->Location).y); +} /* BALL_Update */ +void BALL_DestroyObject(Ball * obj){ +} +void BALL_Deinitialize(){ + if (BALL_IsInit) { + printf("De-initializing Ball...\n"); + + printf("Ball de-initialized!\n"); + BALL_IsInit = false; + } else printf("Ball is already de-initialized!\n"); +} + + +void PADDLE_Initialize(SDL_Renderer * renderer){ + if (!PADDLE_IsInit) { + printf("Initializing Paddle...\n"); + PADDLE_Texture = IMG_LoadTexture(renderer, "assets/images/paddle.png"); + if (!PADDLE_Texture) printf("Paddle texture failed to load!\n"); + PADDLE_SourceRects = (SDL_Rect *)malloc(1 * sizeof(SDL_Rect)); + if (!PADDLE_SourceRects) printf("FATAL! Memory allocation failed!\n"); + PADDLE_SourceRects[0] = (SDL_Rect) {.x = 0, .y = 0, .w = 512, .h = 512 }; + PADDLE_MoveLeftKeys = (Uint8 *)malloc(2 * sizeof(Uint8)); + if (!PADDLE_MoveLeftKeys) printf("FATAL! Memory allocation failed!\n"); + PADDLE_MoveRightKeys = (Uint8 *)malloc(2 * sizeof(Uint8)); + if (!PADDLE_MoveRightKeys) printf("FATAL! Memory allocation failed!\n"); + PADDLE_MoveLeftKeys[0] = 2; // Erster wert gibt größe des arrays an + PADDLE_MoveLeftKeys[1] = SDL_SCANCODE_LEFT; + PADDLE_MoveLeftKeys[2] = SDL_SCANCODE_A; + PADDLE_MoveRightKeys[0] = 2; + PADDLE_MoveRightKeys[1] = SDL_SCANCODE_RIGHT; + PADDLE_MoveRightKeys[2] = SDL_SCANCODE_D; + ball = BALL_CreateDefault(); + printf("Paddle initialized!\n"); + PADDLE_IsInit = true; + } else printf("Paddle is already initialized!\n"); +} /* PADDLE_Initialize */ + +Paddle PADDLE_CreateDefault(){ + int defaultpaddlewidth = 300; + + return (Paddle) { + .TargetRect = (SDL_Rect) {.x = (BREAKOUT_BoxWidth - defaultpaddlewidth) / 2, .y = BREAKOUT_BoxHeight - 100, .w = defaultpaddlewidth, .h = 30 }, + .TextureIndex = 0 + }; // Objekt für die Eigenschaften des Balls +} + +void PADDLE_Draw(SDL_Renderer * renderer, Paddle * obj){ + // printf("Paddle drawn at (%d|%d)!\n", (obj->TargetRect).x, (obj->TargetRect).x); + // SDL_RenderCopy(renderer, PADDLE_Texture, PADDLE_SourceRects + (obj->TextureIndex), &(obj->TargetRect)); + SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255); + SDL_RenderDrawRect(renderer, &(obj->TargetRect)); +} + +bool KeyPressed(Uint8 * keystate, Uint8 * keyArray){ + for (int i = 0; i < (*keyArray); i++) { + if (keystate[keyArray[(i + 1)]]) return true; + } + return false; +} + +void constrain(int * variable, int min, int max){ + if (*variable > max) + *variable = max; + else if (*variable < min) + *variable = min; +} + +void PADDLE_Update(Paddle * obj, Uint8 * keystate){ + bool leftKeyPressed = KeyPressed(keystate, PADDLE_MoveLeftKeys), rightKeyPressed = KeyPressed(keystate, PADDLE_MoveRightKeys); + + if (leftKeyPressed && (!rightKeyPressed)) { + ((obj->TargetRect).x) -= PADDLE_Speed; + } else if ((!leftKeyPressed) && rightKeyPressed) { + ((obj->TargetRect).x) += PADDLE_Speed; + } + constrain(&((obj->TargetRect).x), 0, (BREAKOUT_BoxWidth - ((obj->TargetRect).w))); +} +void PADDLE_DestroyObject(Paddle * obj){ +} +void PADDLE_Deinitialize(){ + if (PADDLE_IsInit) { + printf("De-initializing Paddle...\n"); + + printf("Paddle de-initialized!\n"); + PADDLE_IsInit = false; + } else printf("Paddle is already de-initialized!\n"); } diff --git a/breakout.h b/breakout.h index f1eba4f..82fec60 100644 --- a/breakout.h +++ b/breakout.h @@ -1,5 +1,11 @@ #ifndef __breakout_h__ #define __breakout_h__ +#include +#include +#include +#include +#include +#include #include "vector.h" @@ -12,9 +18,8 @@ typedef struct ballStruct { } Ball; // Objekt für die Eigenschaften des Balls typedef struct paddleStruct { - double XLocation; // Notice: Locked Y-Coordinate SDL_Rect TargetRect; - int XSize, TextureIndex; + int TextureIndex; } Paddle; // Objekt für die Eigenschaften des Paddles typedef struct blockStruct { @@ -26,8 +31,26 @@ typedef struct blockStruct { // Prototypes void BREAKOUT_INITIALIZE(SDL_Renderer * renderer, int width, int height); -void BREAKOUT_GAMELOOP(Uint8 * keystate); -void BREAKOUT_DEINITIALIZE(SDL_Renderer * renderer, int width, int height); +void BREAKOUT_ChangeSize(int width, int height); +void BREAKOUT_Update(Uint8 * keystate); +void BREAKOUT_Draw(SDL_Renderer * renderer); +void BREAKOUT_DEINITIALIZE(); +void BALL_Initialize(SDL_Renderer * renderer); +Ball BALL_CreateDefault(); +void BALL_Draw(SDL_Renderer * renderer, Ball * obj); +bool BALL_CollideWithRect(Ball * obj, SDL_Rect * rect); +bool RECT_Collide(SDL_Rect * rect1, SDL_Rect * rect2); +void BALL_Update(Ball * obj, Paddle * paddle); +void BALL_DestroyObject(Ball * obj); +void BALL_Deinitialize(); +void PADDLE_Initialize(SDL_Renderer * renderer); +Paddle PADDLE_CreateDefault(); +void PADDLE_Draw(SDL_Renderer * renderer, Paddle * obj); +bool KeyPressed(Uint8 * keystate, Uint8 * keyArray); +void constrain(int * variable, int min, int max); +void PADDLE_Update(Paddle * obj, Uint8 * keystate); +void PADDLE_DestroyObject(Paddle * obj); +void PADDLE_Deinitialize(); // End Prototypes #endif // __breakout_h__ diff --git a/main.c b/main.c index e451d4e..e286a30 100644 --- a/main.c +++ b/main.c @@ -38,8 +38,6 @@ int main(int argc, char * args[]){ // system("bhi.exe"); INITIALIZE(); while (running) { // Gameloop - GAMELOOP(); - DrawFrame(); while (SDL_PollEvent(&event)) { switch (event.type) { case SDL_QUIT: @@ -57,6 +55,8 @@ int main(int argc, char * args[]){ break; } } + GAMELOOP(); + DrawFrame(); } QUIT(); return 0; @@ -64,6 +64,7 @@ int main(int argc, char * args[]){ void GAMELOOP() { keystate = SDL_GetKeyboardState(NULL); + BREAKOUT_Update(keystate); } /* GAMELOOP */ void mousePress(SDL_MouseButtonEvent b){ // Debug prop @@ -78,7 +79,7 @@ void mousePress(SDL_MouseButtonEvent b){ // Debug prop void keyPress(SDL_KeyboardEvent b){ // Debug prop printf("Key pressed: ID is %d\n", b.keysym.scancode); - if (b.keysym.scancode == SDL_SCANCODE_F11) { + if (b.keysym.scancode == SDL_SCANCODE_F11 || b.keysym.scancode == SDL_SCANCODE_5) { toggleFullscreen(); } } @@ -96,18 +97,15 @@ void windowChanged(SDL_WindowEvent b){ // Debug prop switch (b.event) { case SDL_WINDOWEVENT_SIZE_CHANGED: printf("Window was resized to (%d|%d)!\n", event.window.data1, event.window.data2); + BREAKOUT_ChangeSize(event.window.data1, event.window.data2); break; } } void DrawFrame(){ - SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255); - SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255); SDL_RenderClear(renderer); - // BALL_DRAW(); - SDL_RenderPresent(renderer); - + BREAKOUT_Draw(renderer); SDL_RenderPresent(renderer); } @@ -124,10 +122,12 @@ void INITIALIZE() { printf("Window was created!\n"); renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC); printf("Renderer was created!\n"); + BREAKOUT_INITIALIZE(renderer, width, height); } /* INITIALIZE */ void QUIT(){ printf("De-initializing started...\n"); + BREAKOUT_DEINITIALIZE(); free(keystate); TTF_Quit(); IMG_Quit();