Added ingame HUD and texture helper functions
This commit is contained in:
		
							
								
								
									
										116
									
								
								breakout.c
									
									
									
									
									
								
							
							
						
						
									
										116
									
								
								breakout.c
									
									
									
									
									
								
							| @@ -9,8 +9,12 @@ | ||||
|  | ||||
| #include "breakout.h" | ||||
| #include "vector.h" | ||||
| #include "gamestate.h" | ||||
| #include "gameover.h" | ||||
| #include "main.h" | ||||
|  | ||||
| extern float XScale, YScale; | ||||
| extern int width, height; | ||||
|  | ||||
| #define BALL_TexturePath              "assets/images/ball.png" | ||||
| #define PADDLE_TexturePath            "assets/images/paddle.png" | ||||
| @@ -19,6 +23,8 @@ extern float XScale, YScale; | ||||
| #define BALL_MinSpeed                 8.0f | ||||
| #define BALL_MaxSpeed                 50.0f | ||||
| #define BALL_AccelerationTime         18000 | ||||
| #define BREAKOUT_LiveHUDSize          35 | ||||
| #define BREAKOUT_LiveHUDMargin        8 | ||||
|  | ||||
| #ifndef __nullptr__ | ||||
| #define Nullptr(type) (type *)0 | ||||
| @@ -29,7 +35,6 @@ int BLOCK_TextureCount = 24; | ||||
| int BALL_TextureCount = 9; | ||||
| int GAME_CountdownTextureCount = 4; | ||||
| int PADDLE_TextureCount = 9; | ||||
| int BREAKOUT_BoxWidth, BREAKOUT_BoxHeight; | ||||
| SDL_Texture * BALL_Texture; | ||||
| SDL_Texture * GAME_CountdownTexture; | ||||
| SDL_Texture * PADDLE_Texture; | ||||
| @@ -44,12 +49,10 @@ bool BALL_IsInit = false; | ||||
| bool PADDLE_IsInit = false; | ||||
| bool BLOCK_IsInit = false; | ||||
|  | ||||
| void BREAKOUT_INITIALIZE(SDL_Renderer * renderer, int width, int height){ | ||||
| void BREAKOUT_INITIALIZE(SDL_Renderer * renderer){ | ||||
|     if (!BREAKOUT_IsInit) { | ||||
|         printf("Initializing Game...\n"); | ||||
|         srand(time(NULL)); | ||||
|         BREAKOUT_BoxWidth = width; | ||||
|         BREAKOUT_BoxHeight = height; | ||||
|         BALL_Initialize(renderer); | ||||
|         PADDLE_Initialize(renderer); | ||||
|         BLOCK_Initialize(renderer); | ||||
| @@ -94,18 +97,15 @@ Scenery BREAKOUT_CreateDefault(){ | ||||
|     return scenery; | ||||
| } /* BREAKOUT_CreateDefault */ | ||||
|  | ||||
|  | ||||
| int BREAKOUT_RefreshScore(Scenery * scenery){ | ||||
|     (scenery->Score) = (int)round((double)(scenery->Frames) * 0.005f * ((scenery->ball).Speed) + (double)(50 * (scenery->DestroyedBlocks))); | ||||
|     printf("Score: %d\n", (scenery->Score)); | ||||
|     return (scenery->Score); | ||||
| void BREAKOUT_IncreaseScoreBy(Scenery * scenery, int scoreInc){ | ||||
|     (scenery->Score) += scoreInc; | ||||
| } | ||||
|  | ||||
| // This Function is obsolete! Do not use it! | ||||
| void BREAKOUT_ChangeSize(int width, int height){ | ||||
|     BREAKOUT_BoxWidth = width; | ||||
|     BREAKOUT_BoxHeight = height; | ||||
| } | ||||
| // int BREAKOUT_RefreshScore(Scenery * scenery){ | ||||
| //     (scenery->Score) = (int)round(((scenery->ball).Speed) * (double)(scenery->DestroyedBlocks)); | ||||
| //     printf("Score: %d\n", (scenery->Score)); | ||||
| //     return (scenery->Score); | ||||
| // } | ||||
|  | ||||
| void BREAKOUT_Update(Scenery * scenery, const Uint8 * keystate){ | ||||
|     if (scenery->IsPaused) { | ||||
| @@ -113,11 +113,10 @@ void BREAKOUT_Update(Scenery * scenery, const Uint8 * keystate){ | ||||
|         return; | ||||
|     } | ||||
|     if ((scenery->StartCountdown)-- > 0) { | ||||
|         // Render "Countdown" | ||||
|         // SDL_WarpMouse(960, 540); Doesn't exist | ||||
|         return; | ||||
|     } | ||||
|     (scenery->Frames)++; | ||||
|     BREAKOUT_RefreshScore(scenery); | ||||
|     if (scenery->IsGameOver) { | ||||
|         BALL_ResetPosition(&(scenery->ball)); | ||||
|         PADDLE_ResetPosition(&(scenery->paddle)); | ||||
| @@ -125,7 +124,7 @@ void BREAKOUT_Update(Scenery * scenery, const Uint8 * keystate){ | ||||
|         scenery->IsGameOver = false; | ||||
|         scenery->Frames = 0; | ||||
|         if (--(scenery->Lives) <= 0) | ||||
|             printf("Game over, no lives left!\n"); | ||||
|             GAME_ChangeState(GameOver); | ||||
|         else | ||||
|             printf("Oh oh, only %d lives left!\n", scenery->Lives); | ||||
|         return; | ||||
| @@ -146,10 +145,26 @@ void BREAKOUT_Draw(Scenery * scenery, SDL_Renderer * renderer){ | ||||
|     if ((scenery->StartCountdown) > 0) { // ! Render Z-Layer ! | ||||
|         SDL_Rect * rect =  GAME_CountdownSourceRects + (((scenery->StartCountdown) - 1) / 60); | ||||
|         SDL_Rect target = *rect; | ||||
|         target.x = ((BREAKOUT_BoxWidth - (rect->w)) / 2); | ||||
|         target.y = ((BREAKOUT_BoxHeight - (rect->h)) / 2); | ||||
|         target.x = ((width - (rect->w)) / 2); | ||||
|         target.y = ((height - (rect->h)) / 2); | ||||
|         SDL_RenderCopy(renderer, GAME_CountdownTexture, rect, &target); | ||||
|     } | ||||
|     SCORE_DrawHUD(renderer, scenery); | ||||
|     BREAKOUT_DrawLivesHUD(renderer, scenery); | ||||
| } | ||||
|  | ||||
| void BREAKOUT_DrawLivesHUD(SDL_Renderer * renderer, Scenery * scenery){ | ||||
|     SDL_Rect tmpRect; | ||||
|  | ||||
|     tmpRect.y = BREAKOUT_LiveHUDMargin; | ||||
|     tmpRect.w = BREAKOUT_LiveHUDSize; | ||||
|     tmpRect.h = BREAKOUT_LiveHUDSize; | ||||
|     tmpRect.x = width - BREAKOUT_LiveHUDMargin; | ||||
|  | ||||
|     for (int i = 0; i < (scenery->Lives); i++) { | ||||
|         tmpRect.x -= (BREAKOUT_LiveHUDSize + BREAKOUT_LiveHUDMargin); | ||||
|         BALL_DrawTexture(renderer, &tmpRect, (scenery->ball).TextureIndex); | ||||
|     } | ||||
| } | ||||
|  | ||||
| void BREAKOUT_DEINITIALIZE(){ | ||||
| @@ -202,27 +217,33 @@ void BALL_Initialize(SDL_Renderer * renderer){ | ||||
| } /* BALL_Initialize */ | ||||
|  | ||||
| Ball BALL_CreateDefault(){ | ||||
|     double rotation = (double)(rand() % 360); | ||||
|  | ||||
|     return (Ball) { | ||||
|                .Location = (Vector) {.x = BREAKOUT_BoxWidth / 2 - 15, .y = BREAKOUT_BoxHeight - 132 }, | ||||
|                .Momentum = (Vector) {.x = 0.0f, .y = 15.0f }, | ||||
|                .TargetRect = (SDL_Rect) {.x = BREAKOUT_BoxWidth / 2 - 15, .y = BREAKOUT_BoxHeight - 130, .w = 30, .h = 30 }, | ||||
|                .Location = (Vector) {.x = (width / 2) - 15, .y = height - 132 }, | ||||
|                .Momentum = (Vector) {.x = 0.0f, .y = BALL_MinSpeed }, | ||||
|                .TargetRect = (SDL_Rect) {.x = width / 2 - 15, .y = height - 130, .w = 30, .h = 30 }, | ||||
|                .Size = 15.0f, | ||||
|                .Rotation = rotation, | ||||
|                .RotationValue = 5, | ||||
|                .Rotation = 0, | ||||
|                .RotationValue = 9, | ||||
|                .TextureIndex = 0, | ||||
|                .Speed = 15.0f | ||||
|     }; // 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; | ||||
|     (obj->Location).x = width / 2 - 15; | ||||
|     (obj->Location).y = height - 130; | ||||
|     RECT_SetTargetPos(&(obj->TargetRect), &(obj->Location)); | ||||
|     (obj->Momentum) = VECTOR_GetScaledDirectionalUnitVector(0.0f, (obj->Speed)); | ||||
| } | ||||
|  | ||||
| void BALL_DrawTexture(SDL_Renderer * renderer, SDL_Rect * dstRect, int index){ | ||||
|     if (index > BALL_TextureCount || index < 0) { | ||||
|         printf("Ball with unkown texture index %d aus [0,...,%d]\n", index, (BALL_TextureCount - 1)); | ||||
|         return; | ||||
|     } | ||||
|     SDL_RenderCopy(renderer, BALL_Texture, BALL_SourceRects + index, dstRect); | ||||
| } | ||||
|  | ||||
| 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); | ||||
| @@ -308,7 +329,7 @@ SDL_Point BALL_GetCenter(Ball * obj){ | ||||
| void BALL_CollideWithBorders(Ball * obj){ | ||||
|     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))) | ||||
|     if ((obj->Location).x < 0.0f || (obj->Location).x > width - (2 * (obj->Size))) | ||||
|         (obj->Momentum).x = -(obj->Momentum).x; | ||||
| } | ||||
|  | ||||
| @@ -317,7 +338,7 @@ void BALL_MoveAwayFromBoundaries(Ball * obj){ | ||||
|         ((obj->Location).y)++; | ||||
|     while (((obj->Location).x) < 0) | ||||
|         ((obj->Location).x)++; | ||||
|     while ((((obj->Location).x) + ((obj->Size) * 2)) > BREAKOUT_BoxWidth) | ||||
|     while ((((obj->Location).x) + ((obj->Size) * 2)) > width) | ||||
|         ((obj->Location).x)--; | ||||
| } | ||||
|  | ||||
| @@ -328,7 +349,7 @@ bool BALL_CollideWithPaddle(Ball * obj, Paddle * paddle){ | ||||
|             BALL_CollideWithRect(obj, &(paddle->TargetRect)); | ||||
|         else | ||||
|             BALL_SteerMomentum(obj, paddle);       // Sets it to unit vector! | ||||
|         // Following assumes that the paddle position was udated before the ball was updated | ||||
|                                                    // Following assumes that the paddle position was udated before the ball was updated | ||||
|         while (RECT_Collide(&(obj->TargetRect), &(paddle->TargetRect))) { // Move away from rect in small steps | ||||
|             (obj->Location) = VECTOR_Add((obj->Location), (obj->Momentum)); | ||||
|             BALL_MoveAwayFromBoundaries(obj); | ||||
| @@ -367,16 +388,19 @@ void BALL_Update(Ball * obj, Scenery * scenery){ | ||||
|             oldLocation = obj->Location; | ||||
|             if (BALL_CollideWithRect(obj, &(blocks[i].TargetRect))) { | ||||
|                 BLOCK_DealDamage(blocks + i, 1); | ||||
|                 if (blocks[i].HP <= 0) | ||||
|                 if (blocks[i].HP <= 0) { | ||||
|                     (scenery->DestroyedBlocks)++; | ||||
|                     BREAKOUT_IncreaseScoreBy(scenery, (int)round((((scenery->ball).Speed) * ((scenery->ball).Speed) / 5.0f))); | ||||
|                 } | ||||
|                 (obj->Location) = VECTOR_Add(oldLocation, (obj->Momentum)); | ||||
|                 BALL_MoveAwayFromBoundaries(obj); | ||||
|                 RECT_SetTargetPos(&(obj->TargetRect), &(obj->Location)); | ||||
|             } | ||||
|         } | ||||
|     if ((obj->Location).y > BREAKOUT_BoxHeight)                                                       // Collide with box boundaries | ||||
|     if ((obj->Location).y > height) { // Collide with box boundaries | ||||
|         scenery->IsGameOver = true; | ||||
|     else BALL_CollideWithBorders(obj); | ||||
|         printf("Ball called game_over!\n"); | ||||
|     } else BALL_CollideWithBorders(obj); | ||||
|     RECT_SetTargetPos(&(obj->TargetRect), &(obj->Location)); | ||||
| } /* BALL_Update */ | ||||
|  | ||||
| @@ -419,7 +443,7 @@ Paddle PADDLE_CreateDefault(){ | ||||
|     int defaultpaddlewidth = 300; | ||||
|  | ||||
|     return (Paddle) { | ||||
|                .TargetRect = (SDL_Rect) {.x = (BREAKOUT_BoxWidth -  defaultpaddlewidth) / 2, .y = BREAKOUT_BoxHeight - 100, .w = defaultpaddlewidth, .h = 30 }, | ||||
|                .TargetRect = (SDL_Rect) {.x = (width -  defaultpaddlewidth) / 2, .y = height - 100, .w = defaultpaddlewidth, .h = 30 }, | ||||
|                .TextureIndex = 0, | ||||
|                .Speed = 10, | ||||
|                .SteeringAngle = 40.0f, | ||||
| @@ -428,8 +452,16 @@ Paddle PADDLE_CreateDefault(){ | ||||
| } | ||||
|  | ||||
| void PADDLE_ResetPosition(Paddle * obj){ | ||||
|     (obj->TargetRect).x = (BREAKOUT_BoxWidth - ((obj->TargetRect).w)) / 2; | ||||
|     (obj->TargetRect).y = BREAKOUT_BoxHeight - 100; | ||||
|     (obj->TargetRect).x = (width - ((obj->TargetRect).w)) / 2; | ||||
|     (obj->TargetRect).y = height - 100; | ||||
| } | ||||
|  | ||||
| void PADDLE_DrawTexture(SDL_Renderer * renderer, SDL_Rect * dstRect, int index){ | ||||
|     if (index > PADDLE_TextureCount || index < 0) { | ||||
|         printf("Paddle with unkown texture index %d aus [0,...,%d]\n", index, (PADDLE_TextureCount - 1)); | ||||
|         return; | ||||
|     } | ||||
|     SDL_RenderCopy(renderer, PADDLE_Texture, PADDLE_SourceRects + index, dstRect); | ||||
| } | ||||
|  | ||||
| void PADDLE_Draw(SDL_Renderer * renderer, Paddle * obj){ | ||||
| @@ -488,7 +520,7 @@ void PADDLE_Update(Paddle * obj, const Uint8 * keystate){ | ||||
|             printf("Unknown Paddle Control Mode: %d!\n", obj->Mode); | ||||
|             break; | ||||
|     } /* switch */ | ||||
|     INT_Constrain(&((obj->TargetRect).x), 0, (BREAKOUT_BoxWidth - ((obj->TargetRect).w))); | ||||
|     INT_Constrain(&((obj->TargetRect).x), 0, (width - ((obj->TargetRect).w))); | ||||
| } /* PADDLE_Update */ | ||||
|  | ||||
| void PADDLE_DestroyObject(Paddle * obj){ | ||||
| @@ -547,6 +579,14 @@ Block BLOCK_CreateDefault() { | ||||
|     };   // Objekt für die Eigenschaften des Balls | ||||
| } | ||||
|  | ||||
| void BLOCK_DrawTexture(SDL_Renderer * renderer, SDL_Rect * dstRect, int index){ | ||||
|     if (index > BLOCK_TextureCount || index < 0) { | ||||
|         printf("Block with unkown texture index %d aus [0,...,%d]\n", index, (BLOCK_TextureCount - 1)); | ||||
|         return; | ||||
|     } | ||||
|     SDL_RenderCopy(renderer, BLOCK_Texture, BLOCK_SourceRects + index, dstRect); | ||||
| } | ||||
|  | ||||
| void BLOCK_Draw(SDL_Renderer * renderer, Block * obj){ | ||||
|     if ((obj->HP) > 0) { | ||||
|         // printf("Block drawn at (%d|%d)!\n", (obj->TargetRect).x, (obj->TargetRect).y); | ||||
|   | ||||
| @@ -45,17 +45,18 @@ typedef struct sceneryStruct { | ||||
| // End Structs | ||||
|  | ||||
| // Prototypes | ||||
| void BREAKOUT_INITIALIZE(SDL_Renderer * renderer, int width, int height); | ||||
| void BREAKOUT_INITIALIZE(SDL_Renderer * renderer); | ||||
| Scenery BREAKOUT_CreateDefault(); | ||||
| int BREAKOUT_RefreshScore(Scenery * scenery); | ||||
| void BREAKOUT_ChangeSize(int width, int height); | ||||
| void BREAKOUT_Update(Scenery * scenery, const Uint8 * keystate); | ||||
| void BREAKOUT_Draw(Scenery * scenery, SDL_Renderer * renderer); | ||||
| void BREAKOUT_DrawLivesHUD(SDL_Renderer * renderer, Scenery * scenery); | ||||
| void BREAKOUT_DEINITIALIZE(); | ||||
| void BREAKOUT_DestroyObject(Scenery * scenery); | ||||
| void BALL_Initialize(SDL_Renderer * renderer); | ||||
| Ball BALL_CreateDefault(); | ||||
| void BALL_ResetPosition(Ball * obj); | ||||
| void BALL_DrawTexture(SDL_Renderer * renderer, SDL_Rect * dstRect, int index); | ||||
| 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); | ||||
| @@ -72,6 +73,7 @@ void BALL_Deinitialize(); | ||||
| void PADDLE_Initialize(SDL_Renderer * renderer); | ||||
| Paddle PADDLE_CreateDefault(); | ||||
| void PADDLE_ResetPosition(Paddle * obj); | ||||
| void PADDLE_DrawTexture(SDL_Renderer * renderer, SDL_Rect * dstRect, int index); | ||||
| void PADDLE_Draw(SDL_Renderer * renderer, Paddle * obj); | ||||
| bool KeyPressed(const Uint8 * keystate, Uint8 * keyArray); | ||||
| void INT_Constrain(int * variable, int min, int max); | ||||
| @@ -82,6 +84,7 @@ void PADDLE_DestroyObject(Paddle * obj); | ||||
| void PADDLE_Deinitialize(); | ||||
| void BLOCK_Initialize(SDL_Renderer * renderer); | ||||
| Block BLOCK_CreateDefault() ; | ||||
| void BLOCK_DrawTexture(SDL_Renderer * renderer, SDL_Rect * dstRect, int index); | ||||
| void BLOCK_Draw(SDL_Renderer * renderer, Block * obj); | ||||
| void BLOCK_DealDamage(Block * obj, int dmg); | ||||
| void BLOCK_Update(Block * obj); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user