Added ingame HUD and texture helper functions

This commit is contained in:
Michael Chen 2018-01-23 21:22:59 +01:00
parent 3b2a0c8741
commit d7e5845e4e
2 changed files with 83 additions and 40 deletions

View File

@ -9,8 +9,12 @@
#include "breakout.h" #include "breakout.h"
#include "vector.h" #include "vector.h"
#include "gamestate.h"
#include "gameover.h"
#include "main.h"
extern float XScale, YScale; extern float XScale, YScale;
extern int width, height;
#define BALL_TexturePath "assets/images/ball.png" #define BALL_TexturePath "assets/images/ball.png"
#define PADDLE_TexturePath "assets/images/paddle.png" #define PADDLE_TexturePath "assets/images/paddle.png"
@ -19,6 +23,8 @@ extern float XScale, YScale;
#define BALL_MinSpeed 8.0f #define BALL_MinSpeed 8.0f
#define BALL_MaxSpeed 50.0f #define BALL_MaxSpeed 50.0f
#define BALL_AccelerationTime 18000 #define BALL_AccelerationTime 18000
#define BREAKOUT_LiveHUDSize 35
#define BREAKOUT_LiveHUDMargin 8
#ifndef __nullptr__ #ifndef __nullptr__
#define Nullptr(type) (type *)0 #define Nullptr(type) (type *)0
@ -29,7 +35,6 @@ int BLOCK_TextureCount = 24;
int BALL_TextureCount = 9; int BALL_TextureCount = 9;
int GAME_CountdownTextureCount = 4; int GAME_CountdownTextureCount = 4;
int PADDLE_TextureCount = 9; int PADDLE_TextureCount = 9;
int BREAKOUT_BoxWidth, BREAKOUT_BoxHeight;
SDL_Texture * BALL_Texture; SDL_Texture * BALL_Texture;
SDL_Texture * GAME_CountdownTexture; SDL_Texture * GAME_CountdownTexture;
SDL_Texture * PADDLE_Texture; SDL_Texture * PADDLE_Texture;
@ -44,12 +49,10 @@ bool BALL_IsInit = false;
bool PADDLE_IsInit = false; bool PADDLE_IsInit = false;
bool BLOCK_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) { if (!BREAKOUT_IsInit) {
printf("Initializing Game...\n"); printf("Initializing Game...\n");
srand(time(NULL)); srand(time(NULL));
BREAKOUT_BoxWidth = width;
BREAKOUT_BoxHeight = height;
BALL_Initialize(renderer); BALL_Initialize(renderer);
PADDLE_Initialize(renderer); PADDLE_Initialize(renderer);
BLOCK_Initialize(renderer); BLOCK_Initialize(renderer);
@ -94,18 +97,15 @@ Scenery BREAKOUT_CreateDefault(){
return scenery; return scenery;
} /* BREAKOUT_CreateDefault */ } /* BREAKOUT_CreateDefault */
void BREAKOUT_IncreaseScoreBy(Scenery * scenery, int scoreInc){
int BREAKOUT_RefreshScore(Scenery * scenery){ (scenery->Score) += scoreInc;
(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);
} }
// This Function is obsolete! Do not use it! // int BREAKOUT_RefreshScore(Scenery * scenery){
void BREAKOUT_ChangeSize(int width, int height){ // (scenery->Score) = (int)round(((scenery->ball).Speed) * (double)(scenery->DestroyedBlocks));
BREAKOUT_BoxWidth = width; // printf("Score: %d\n", (scenery->Score));
BREAKOUT_BoxHeight = height; // return (scenery->Score);
} // }
void BREAKOUT_Update(Scenery * scenery, const Uint8 * keystate){ void BREAKOUT_Update(Scenery * scenery, const Uint8 * keystate){
if (scenery->IsPaused) { if (scenery->IsPaused) {
@ -113,11 +113,10 @@ void BREAKOUT_Update(Scenery * scenery, const Uint8 * keystate){
return; return;
} }
if ((scenery->StartCountdown)-- > 0) { if ((scenery->StartCountdown)-- > 0) {
// Render "Countdown" // SDL_WarpMouse(960, 540); Doesn't exist
return; return;
} }
(scenery->Frames)++; (scenery->Frames)++;
BREAKOUT_RefreshScore(scenery);
if (scenery->IsGameOver) { if (scenery->IsGameOver) {
BALL_ResetPosition(&(scenery->ball)); BALL_ResetPosition(&(scenery->ball));
PADDLE_ResetPosition(&(scenery->paddle)); PADDLE_ResetPosition(&(scenery->paddle));
@ -125,7 +124,7 @@ void BREAKOUT_Update(Scenery * scenery, const Uint8 * keystate){
scenery->IsGameOver = false; scenery->IsGameOver = false;
scenery->Frames = 0; scenery->Frames = 0;
if (--(scenery->Lives) <= 0) if (--(scenery->Lives) <= 0)
printf("Game over, no lives left!\n"); GAME_ChangeState(GameOver);
else else
printf("Oh oh, only %d lives left!\n", scenery->Lives); printf("Oh oh, only %d lives left!\n", scenery->Lives);
return; return;
@ -146,10 +145,26 @@ void BREAKOUT_Draw(Scenery * scenery, SDL_Renderer * renderer){
if ((scenery->StartCountdown) > 0) { // ! Render Z-Layer ! if ((scenery->StartCountdown) > 0) { // ! Render Z-Layer !
SDL_Rect * rect = GAME_CountdownSourceRects + (((scenery->StartCountdown) - 1) / 60); SDL_Rect * rect = GAME_CountdownSourceRects + (((scenery->StartCountdown) - 1) / 60);
SDL_Rect target = *rect; SDL_Rect target = *rect;
target.x = ((BREAKOUT_BoxWidth - (rect->w)) / 2); target.x = ((width - (rect->w)) / 2);
target.y = ((BREAKOUT_BoxHeight - (rect->h)) / 2); target.y = ((height - (rect->h)) / 2);
SDL_RenderCopy(renderer, GAME_CountdownTexture, rect, &target); 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(){ void BREAKOUT_DEINITIALIZE(){
@ -202,27 +217,33 @@ void BALL_Initialize(SDL_Renderer * renderer){
} /* BALL_Initialize */ } /* BALL_Initialize */
Ball BALL_CreateDefault(){ Ball BALL_CreateDefault(){
double rotation = (double)(rand() % 360);
return (Ball) { return (Ball) {
.Location = (Vector) {.x = BREAKOUT_BoxWidth / 2 - 15, .y = BREAKOUT_BoxHeight - 132 }, .Location = (Vector) {.x = (width / 2) - 15, .y = height - 132 },
.Momentum = (Vector) {.x = 0.0f, .y = 15.0f }, .Momentum = (Vector) {.x = 0.0f, .y = BALL_MinSpeed },
.TargetRect = (SDL_Rect) {.x = BREAKOUT_BoxWidth / 2 - 15, .y = BREAKOUT_BoxHeight - 130, .w = 30, .h = 30 }, .TargetRect = (SDL_Rect) {.x = width / 2 - 15, .y = height - 130, .w = 30, .h = 30 },
.Size = 15.0f, .Size = 15.0f,
.Rotation = rotation, .Rotation = 0,
.RotationValue = 5, .RotationValue = 9,
.TextureIndex = 0, .TextureIndex = 0,
.Speed = 15.0f .Speed = 15.0f
}; // Objekt für die Eigenschaften des Balls }; // Objekt für die Eigenschaften des Balls
} }
void BALL_ResetPosition(Ball * obj){ void BALL_ResetPosition(Ball * obj){
(obj->Location).x = BREAKOUT_BoxWidth / 2 - 15; (obj->Location).x = width / 2 - 15;
(obj->Location).y = BREAKOUT_BoxHeight - 130; (obj->Location).y = height - 130;
RECT_SetTargetPos(&(obj->TargetRect), &(obj->Location)); RECT_SetTargetPos(&(obj->TargetRect), &(obj->Location));
(obj->Momentum) = VECTOR_GetScaledDirectionalUnitVector(0.0f, (obj->Speed)); (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){ void BALL_Draw(SDL_Renderer * renderer, Ball * obj){
// printf("Ball drawn at (%d|%d)!\n", (obj->TargetRect).x, (obj->TargetRect).x); // 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); 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){ void BALL_CollideWithBorders(Ball * obj){
if ((obj->Location).y < 0.0f) if ((obj->Location).y < 0.0f)
(obj->Momentum).y = -(obj->Momentum).y; (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; (obj->Momentum).x = -(obj->Momentum).x;
} }
@ -317,7 +338,7 @@ void BALL_MoveAwayFromBoundaries(Ball * obj){
((obj->Location).y)++; ((obj->Location).y)++;
while (((obj->Location).x) < 0) while (((obj->Location).x) < 0)
((obj->Location).x)++; ((obj->Location).x)++;
while ((((obj->Location).x) + ((obj->Size) * 2)) > BREAKOUT_BoxWidth) while ((((obj->Location).x) + ((obj->Size) * 2)) > width)
((obj->Location).x)--; ((obj->Location).x)--;
} }
@ -328,7 +349,7 @@ bool BALL_CollideWithPaddle(Ball * obj, Paddle * paddle){
BALL_CollideWithRect(obj, &(paddle->TargetRect)); BALL_CollideWithRect(obj, &(paddle->TargetRect));
else else
BALL_SteerMomentum(obj, paddle); // Sets it to unit vector! 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 while (RECT_Collide(&(obj->TargetRect), &(paddle->TargetRect))) { // Move away from rect in small steps
(obj->Location) = VECTOR_Add((obj->Location), (obj->Momentum)); (obj->Location) = VECTOR_Add((obj->Location), (obj->Momentum));
BALL_MoveAwayFromBoundaries(obj); BALL_MoveAwayFromBoundaries(obj);
@ -367,16 +388,19 @@ void BALL_Update(Ball * obj, Scenery * scenery){
oldLocation = obj->Location; oldLocation = obj->Location;
if (BALL_CollideWithRect(obj, &(blocks[i].TargetRect))) { if (BALL_CollideWithRect(obj, &(blocks[i].TargetRect))) {
BLOCK_DealDamage(blocks + i, 1); BLOCK_DealDamage(blocks + i, 1);
if (blocks[i].HP <= 0) if (blocks[i].HP <= 0) {
(scenery->DestroyedBlocks)++; (scenery->DestroyedBlocks)++;
BREAKOUT_IncreaseScoreBy(scenery, (int)round((((scenery->ball).Speed) * ((scenery->ball).Speed) / 5.0f)));
}
(obj->Location) = VECTOR_Add(oldLocation, (obj->Momentum)); (obj->Location) = VECTOR_Add(oldLocation, (obj->Momentum));
BALL_MoveAwayFromBoundaries(obj); BALL_MoveAwayFromBoundaries(obj);
RECT_SetTargetPos(&(obj->TargetRect), &(obj->Location)); 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; scenery->IsGameOver = true;
else BALL_CollideWithBorders(obj); printf("Ball called game_over!\n");
} else BALL_CollideWithBorders(obj);
RECT_SetTargetPos(&(obj->TargetRect), &(obj->Location)); RECT_SetTargetPos(&(obj->TargetRect), &(obj->Location));
} /* BALL_Update */ } /* BALL_Update */
@ -419,7 +443,7 @@ Paddle PADDLE_CreateDefault(){
int defaultpaddlewidth = 300; int defaultpaddlewidth = 300;
return (Paddle) { 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, .TextureIndex = 0,
.Speed = 10, .Speed = 10,
.SteeringAngle = 40.0f, .SteeringAngle = 40.0f,
@ -428,8 +452,16 @@ Paddle PADDLE_CreateDefault(){
} }
void PADDLE_ResetPosition(Paddle * obj){ void PADDLE_ResetPosition(Paddle * obj){
(obj->TargetRect).x = (BREAKOUT_BoxWidth - ((obj->TargetRect).w)) / 2; (obj->TargetRect).x = (width - ((obj->TargetRect).w)) / 2;
(obj->TargetRect).y = BREAKOUT_BoxHeight - 100; (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){ 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); printf("Unknown Paddle Control Mode: %d!\n", obj->Mode);
break; break;
} /* switch */ } /* switch */
INT_Constrain(&((obj->TargetRect).x), 0, (BREAKOUT_BoxWidth - ((obj->TargetRect).w))); INT_Constrain(&((obj->TargetRect).x), 0, (width - ((obj->TargetRect).w)));
} /* PADDLE_Update */ } /* PADDLE_Update */
void PADDLE_DestroyObject(Paddle * obj){ void PADDLE_DestroyObject(Paddle * obj){
@ -547,6 +579,14 @@ Block BLOCK_CreateDefault() {
}; // Objekt für die Eigenschaften des Balls }; // 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){ void BLOCK_Draw(SDL_Renderer * renderer, Block * obj){
if ((obj->HP) > 0) { if ((obj->HP) > 0) {
// printf("Block drawn at (%d|%d)!\n", (obj->TargetRect).x, (obj->TargetRect).y); // printf("Block drawn at (%d|%d)!\n", (obj->TargetRect).x, (obj->TargetRect).y);

View File

@ -45,17 +45,18 @@ typedef struct sceneryStruct {
// End Structs // End Structs
// Prototypes // Prototypes
void BREAKOUT_INITIALIZE(SDL_Renderer * renderer, int width, int height); void BREAKOUT_INITIALIZE(SDL_Renderer * renderer);
Scenery BREAKOUT_CreateDefault(); Scenery BREAKOUT_CreateDefault();
int BREAKOUT_RefreshScore(Scenery * scenery); int BREAKOUT_RefreshScore(Scenery * scenery);
void BREAKOUT_ChangeSize(int width, int height);
void BREAKOUT_Update(Scenery * scenery, const Uint8 * keystate); void BREAKOUT_Update(Scenery * scenery, const Uint8 * keystate);
void BREAKOUT_Draw(Scenery * scenery, SDL_Renderer * renderer); void BREAKOUT_Draw(Scenery * scenery, SDL_Renderer * renderer);
void BREAKOUT_DrawLivesHUD(SDL_Renderer * renderer, Scenery * scenery);
void BREAKOUT_DEINITIALIZE(); void BREAKOUT_DEINITIALIZE();
void BREAKOUT_DestroyObject(Scenery * scenery); void BREAKOUT_DestroyObject(Scenery * scenery);
void BALL_Initialize(SDL_Renderer * renderer); void BALL_Initialize(SDL_Renderer * renderer);
Ball BALL_CreateDefault(); Ball BALL_CreateDefault();
void BALL_ResetPosition(Ball * obj); void BALL_ResetPosition(Ball * obj);
void BALL_DrawTexture(SDL_Renderer * renderer, SDL_Rect * dstRect, int index);
void BALL_Draw(SDL_Renderer * renderer, Ball * obj); void BALL_Draw(SDL_Renderer * renderer, Ball * obj);
bool BALL_CollideWithRect(Ball * obj, SDL_Rect * rect); bool BALL_CollideWithRect(Ball * obj, SDL_Rect * rect);
bool RECT_Collide(SDL_Rect * rect1, SDL_Rect * rect2); bool RECT_Collide(SDL_Rect * rect1, SDL_Rect * rect2);
@ -72,6 +73,7 @@ void BALL_Deinitialize();
void PADDLE_Initialize(SDL_Renderer * renderer); void PADDLE_Initialize(SDL_Renderer * renderer);
Paddle PADDLE_CreateDefault(); Paddle PADDLE_CreateDefault();
void PADDLE_ResetPosition(Paddle * obj); void PADDLE_ResetPosition(Paddle * obj);
void PADDLE_DrawTexture(SDL_Renderer * renderer, SDL_Rect * dstRect, int index);
void PADDLE_Draw(SDL_Renderer * renderer, Paddle * obj); void PADDLE_Draw(SDL_Renderer * renderer, Paddle * obj);
bool KeyPressed(const Uint8 * keystate, Uint8 * keyArray); bool KeyPressed(const Uint8 * keystate, Uint8 * keyArray);
void INT_Constrain(int * variable, int min, int max); void INT_Constrain(int * variable, int min, int max);
@ -82,6 +84,7 @@ void PADDLE_DestroyObject(Paddle * obj);
void PADDLE_Deinitialize(); void PADDLE_Deinitialize();
void BLOCK_Initialize(SDL_Renderer * renderer); void BLOCK_Initialize(SDL_Renderer * renderer);
Block BLOCK_CreateDefault() ; Block BLOCK_CreateDefault() ;
void BLOCK_DrawTexture(SDL_Renderer * renderer, SDL_Rect * dstRect, int index);
void BLOCK_Draw(SDL_Renderer * renderer, Block * obj); void BLOCK_Draw(SDL_Renderer * renderer, Block * obj);
void BLOCK_DealDamage(Block * obj, int dmg); void BLOCK_DealDamage(Block * obj, int dmg);
void BLOCK_Update(Block * obj); void BLOCK_Update(Block * obj);