diff --git a/breakout.c b/breakout.c index 416dcda..2a98669 100644 --- a/breakout.c +++ b/breakout.c @@ -49,21 +49,22 @@ void BREAKOUT_INITIALIZE(SDL_Renderer * renderer, int width, int height){ Scenery BREAKOUT_CreateDefault(){ Scenery scenery; - scenery.BlockCount = 60; + scenery.StartCountdown = 240; + scenery.IsGameOver = false; + scenery.BlockCount = 135; scenery.ball = BALL_CreateDefault(); scenery.paddle = PADDLE_CreateDefault(); scenery.blocks = malloc(scenery.BlockCount * sizeof(Block)); + if (!(scenery.blocks)) printf("FATAL! Memory allocation failed!\n"); + scenery.IsPaused = false; + scenery.Lives = 3; int index; - for (int y = 0; y < 6; y++) { - index = 10 * y; - for (int x = 0; x < 10; x++) { + for (int y = 0; y < 9; y++) { + index = 15 * y; + for (int x = 0; x < 15; x++) { scenery.blocks[x + index] = BLOCK_CreateDefault(); - scenery.blocks[x + index].TargetRect = (SDL_Rect) {.x = ((192 * x) + 4), .y = ((96 * y) + 2), .w = 184, .h = 92 }; - scenery.blocks[x + index].TextureIndex = y + x + 2; - // printf("Block created at index: %d\n", (x + index)); - // printf("Block Target: %d %d %d %d\n", ( scenery.blocks[x + index].TargetRect.x), ( scenery.blocks[x + index].TargetRect.y), ( scenery.blocks[x + index].TargetRect.w), ( scenery.blocks[x + index].TargetRect.h)); - // printf("Block Texture index: %d\n", scenery.blocks[x + index].TextureIndex); - // system("pause"); + scenery.blocks[x + index].TargetRect = (SDL_Rect) {.x = ((128 * x) + 2), .y = ((64 * y) + 1), .w = 124, .h = 62 }; + scenery.blocks[x + index].TextureIndex = y + x; } } return scenery; @@ -76,12 +77,31 @@ void BREAKOUT_ChangeSize(int width, int height){ } void BREAKOUT_Update(Scenery * scenery, const Uint8 * keystate){ + if (scenery->IsPaused) { + // Render "Paused" + return; + } + if ((scenery->StartCountdown)-- > 0) { + // Render "Countdown" + return; + } + if (scenery->IsGameOver) { + BALL_ResetPosition(&(scenery->ball)); + PADDLE_ResetPosition(&(scenery->paddle)); + scenery->StartCountdown = 240; + scenery->IsGameOver = false; + if (--(scenery->Lives) <= 0) + printf("Game over, no lives left!\n"); + else + printf("Oh oh, only %d lives left!\n", scenery->Lives); + return; + } PADDLE_Update(&(scenery->paddle), keystate); // Update paddle before ball because paddle is not static! - BALL_Update(&(scenery->ball), &(scenery->paddle), (scenery->blocks), (scenery->BlockCount)); + BALL_Update(&(scenery->ball), scenery); for (int i = 0; i < (scenery->BlockCount); i++) { BLOCK_Update((scenery->blocks) + i); } -} +} /* BREAKOUT_Update */ void BREAKOUT_Draw(Scenery * scenery, SDL_Renderer * renderer){ for (int i = 0; i < (scenery->BlockCount); i++) { @@ -133,10 +153,10 @@ Ball BALL_CreateDefault(){ double rotation = (double)(rand() % 360); return (Ball) { - .Location = (Vector) {.x = BREAKOUT_BoxWidth / 2 + 300, .y = BREAKOUT_BoxHeight / 2 }, + .Location = (Vector) {.x = BREAKOUT_BoxWidth / 2 - 15, .y = BREAKOUT_BoxHeight - 130 }, .Momentum = (Vector) {.x = 0.0f, .y = 15.0f }, - .TargetRect = (SDL_Rect) {.x = 0, .y = 0, .w = 50, .h = 50 }, - .Size = 25.0f, + .TargetRect = (SDL_Rect) {.x = BREAKOUT_BoxWidth / 2 - 15, .y = BREAKOUT_BoxHeight - 130, .w = 30, .h = 30 }, + .Size = 15.0f, .Rotation = rotation, .RotationValue = 2, .TextureIndex = 0, @@ -144,6 +164,12 @@ Ball BALL_CreateDefault(){ }; // Objekt für die Eigenschaften des Balls } +void BALL_ResetPosition(Ball * obj){ + (obj->Location).x = BREAKOUT_BoxWidth / 2 - 15; + (obj->Location).y = BREAKOUT_BoxHeight - 130; + RECT_SetTargetPos(&(obj->TargetRect), &(obj->Location)); +} + 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); @@ -182,7 +208,11 @@ bool BALL_CollideWithRect(Ball * obj, SDL_Rect * rect){ // printf("Hit corner at %.0f|%.0f!\n", corner.x, corner.y); // printf("Ball center at %.0f|%.0f!\n", center.x, center.y); // TODO: Reflection at lot - (obj->Momentum) = VECTOR_GetScaledVectorFromTo(corner, center, (obj->Speed)); + double lot = VECTOR_GetRotation(VECTOR_GetVectorFromTo(corner, center)); + double inRotation = fmod(VECTOR_GetRotation(obj->Momentum) + 180.0f, 360.0f); + double outAngle = fmod(lot + (0.5 * (lot - inRotation)), 360.0f); + printf("In: %.2f | Lot: %.2f | Out: %.2f\n", inRotation, lot, outAngle); + (obj->Momentum) = VECTOR_GetScaledDirectionalUnitVector(outAngle, (obj->Speed)); // printf("New Magnitude = %.2f\n", VECTOR_GetMagnitude((obj->Momentum))); return true; } /* BALL_CollideWithRect */ @@ -257,7 +287,10 @@ bool BALL_CollideWithPaddle(Ball * obj, Paddle * paddle){ return false; } /* BALL_CollideWithPaddle */ -void BALL_Update(Ball * obj, Paddle * paddle, Block * blocks, int BlockCount){ +void BALL_Update(Ball * obj, Scenery * scenery){ + Block * blocks = (scenery->blocks); + Paddle * paddle = &(scenery->paddle); + int BlockCount = scenery->BlockCount; Vector oldMomentum = obj->Momentum; Vector oldLocation = obj->Location; @@ -265,7 +298,7 @@ void BALL_Update(Ball * obj, Paddle * paddle, Block * blocks, int BlockCount){ (obj->Location) = VECTOR_Add((obj->Location), oldMomentum); if (!BALL_CollideWithPaddle(obj, paddle)) // Collide with Paddle - for (size_t i = 0; i < BlockCount; i++) { // Check Collide with each block + for (int i = 0; i < BlockCount; i++) { // Check Collide with each block if (blocks[i].HP <= 0) continue; oldMomentum = obj->Momentum; oldLocation = obj->Location; @@ -277,7 +310,7 @@ void BALL_Update(Ball * obj, Paddle * paddle, Block * blocks, int BlockCount){ } } if ((obj->Location).y > BREAKOUT_BoxHeight) // Collide with box boundaries - (obj->Location) = (Vector) {.x = BREAKOUT_BoxWidth / 2 + 300, .y = BREAKOUT_BoxHeight / 2 }; // Dead + scenery->IsGameOver = true; else BALL_CollideWithBorders(obj); RECT_SetTargetPos(&(obj->TargetRect), &(obj->Location)); } /* BALL_Update */ @@ -329,6 +362,11 @@ Paddle PADDLE_CreateDefault(){ }; // Objekt für die Eigenschaften des Balls } +void PADDLE_ResetPosition(Paddle * obj){ + (obj->TargetRect).x = (BREAKOUT_BoxWidth - ((obj->TargetRect).w)) / 2; + (obj->TargetRect).y = BREAKOUT_BoxHeight - 100; +} + 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)); diff --git a/breakout.h b/breakout.h index 70e3efc..90cd196 100644 --- a/breakout.h +++ b/breakout.h @@ -39,7 +39,8 @@ typedef struct sceneryStruct { Ball ball; Paddle paddle; Block * blocks; - int BlockCount; // Move to scenery + int BlockCount, Lives, StartCountdown; + bool IsPaused, IsGameOver; } Scenery; // Objekt für die Objekte und Eigenschaften einer Szenerie // End Structs @@ -53,6 +54,7 @@ void BREAKOUT_DEINITIALIZE(); void BREAKOUT_DestroyObject(Scenery * scenery); void BALL_Initialize(SDL_Renderer * renderer); Ball BALL_CreateDefault(); +void BALL_ResetPosition(Ball * obj); 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); @@ -62,11 +64,12 @@ SDL_Point BALL_GetCenter(Ball * obj); void BALL_CollideWithBorders(Ball * obj); void BALL_MoveAwayFromBoundaries(Ball * obj); bool BALL_CollideWithPaddle(Ball * obj, Paddle * paddle); -void BALL_Update(Ball * obj, Paddle * paddle, Block * blocks, int BlockCount); +void BALL_Update(Ball * obj, Scenery * scenery); void BALL_DestroyObject(Ball * obj); void BALL_Deinitialize(); void PADDLE_Initialize(SDL_Renderer * renderer); Paddle PADDLE_CreateDefault(); +void PADDLE_ResetPosition(Paddle * obj); void PADDLE_Draw(SDL_Renderer * renderer, Paddle * obj); bool KeyPressed(const Uint8 * keystate, Uint8 * keyArray); void INT_Constrain(int * variable, int min, int max); diff --git a/vector.c b/vector.c index eb553df..5afc5c3 100644 --- a/vector.c +++ b/vector.c @@ -82,3 +82,7 @@ Vector VECTOR_GetScaledDirectionalUnitVector(double rotation, double Magnitude){ Vector VECTOR_GetScaledVectorFromTo(Vector from, Vector to, double Magnitude){ return VECTOR_ChangeScaleTo(VECTOR_Subtract(to, from), Magnitude); } + +Vector VECTOR_GetVectorFromTo(Vector from, Vector to){ + return VECTOR_Subtract(to, from); +} diff --git a/vector.h b/vector.h index 39130ae..f4b3896 100644 --- a/vector.h +++ b/vector.h @@ -21,6 +21,7 @@ double degreeCos(double x); Vector VECTOR_GetDirectionalUnitVector(double rotation); Vector VECTOR_GetScaledDirectionalUnitVector(double rotation, double Magnitude); Vector VECTOR_GetScaledVectorFromTo(Vector from, Vector to, double Magnitude); +Vector VECTOR_GetVectorFromTo(Vector from, Vector to); // End Prototypes #endif // __vector_h__