#include #include #include #include #include #include #include #include #include "breakout.h" #include "vector.h" #ifndef __nullptr__ #define Nullptr(type) (type *)0 #endif // __nullptr__ 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){ 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; } void BREAKOUT_Update(Uint8 * keystate){ BALL_Update(&ball, &paddle); PADDLE_Update(&paddle, keystate); } void BREAKOUT_Draw(SDL_Renderer * renderer){ BALL_Draw(renderer, &ball); PADDLE_Draw(renderer, &paddle); } 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"); }