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 "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);

View File

@ -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);