Added playerLives variable that is updated when the ball is reset, and used SDL_Image to load bitmaps of heart icons and function to visually represent the lives
SDL Surface to GL Texture code in loadTextures function used from http://www.sdltutorials.com/sdl-tip-sdl-surface-to-opengl-texture
This commit is contained in:
parent
a8898fe13a
commit
0d5153ea57
BIN
breakout/assets/heartFull.png
Normal file
BIN
breakout/assets/heartFull.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 315 B |
BIN
breakout/assets/heartUsed.png
Normal file
BIN
breakout/assets/heartUsed.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 269 B |
@ -2,8 +2,11 @@
|
|||||||
#include <Windows.h>
|
#include <Windows.h>
|
||||||
#include <SDL.h>
|
#include <SDL.h>
|
||||||
#include <SDL_ttf.h>
|
#include <SDL_ttf.h>
|
||||||
|
#include <SDL_image.h>
|
||||||
#else
|
#else
|
||||||
#include <SDL2/SDL.h>
|
#include <SDL2/SDL.h>
|
||||||
|
#include <SDL2/SDL_ttf.h>
|
||||||
|
#include <SDL2/SDL_image.h>
|
||||||
#endif
|
#endif
|
||||||
#include <GL/gl.h>
|
#include <GL/gl.h>
|
||||||
#include <GL/glu.h>
|
#include <GL/glu.h>
|
||||||
@ -65,16 +68,20 @@ double heronsFormula(coord a, coord b, coord c) {
|
|||||||
double s = (A + B + C) / 2;
|
double s = (A + B + C) / 2;
|
||||||
return sqrt(s*(s - A)*(s - B)*(s - C));
|
return sqrt(s*(s - A)*(s - B)*(s - C));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int loadTextures(GLuint *texture, const char *imageLoc);
|
||||||
|
|
||||||
char vertexWithinQuad(coord point, coord *quad);
|
char vertexWithinQuad(coord point, coord *quad);
|
||||||
|
|
||||||
void updatePaddle(Uint32 tickrate, paddle *thePaddle, char moveX, int winWidth, int winHeight);
|
void updatePaddle(Uint32 tickrate, paddle *thePaddle, char moveX, int winWidth, int winHeight);
|
||||||
void updateBall(Uint32 tickrate, ball *theBall, paddle *thePaddle, int winWidth, int winHeight, brick *bricks, int brickCount);
|
void updateBall(Uint32 tickrate, ball *theBall, paddle *thePaddle, int winWidth, int winHeight, brick *bricks, int brickCount, int *playerLives);
|
||||||
void updateScore(int *playerScore, brick *bricks, int brickCount);
|
void updateScore(int *playerScore, brick *bricks, int brickCount);
|
||||||
|
|
||||||
|
void drawHearts(GLuint heartFullTex, GLuint heartEmptyTex, int playerLives, int winWidth, int winHeight);
|
||||||
void drawPaddle(paddle *thePaddle, int winWidth, int winHeight, colour *c);
|
void drawPaddle(paddle *thePaddle, int winWidth, int winHeight, colour *c);
|
||||||
void drawBall(ball *theBall, colour *c);
|
void drawBall(ball *theBall, colour *c);
|
||||||
void drawBg(int winWidth, int winHeight, colour *c1, colour *c2);
|
|
||||||
void drawBricks(brick *bricks, int brickCount, int winWidth, int winHeight, colour *colours);
|
void drawBricks(brick *bricks, int brickCount, int winWidth, int winHeight, colour *colours);
|
||||||
|
void drawBg(int winWidth, int winHeight, colour *c1, colour *c2);
|
||||||
|
|
||||||
void initialiseBricks(brick *bricks, int *brickCount);
|
void initialiseBricks(brick *bricks, int *brickCount);
|
||||||
|
|
||||||
@ -88,6 +95,7 @@ int main(void) {
|
|||||||
* 3: Error creating context
|
* 3: Error creating context
|
||||||
* 4: SDL_TTF init fail
|
* 4: SDL_TTF init fail
|
||||||
* 5: Error loading font(s)
|
* 5: Error loading font(s)
|
||||||
|
* 6: Error loading image asset(s)
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -162,6 +170,8 @@ int main(void) {
|
|||||||
glShadeModel(GL_SMOOTH); // GL_FLAT for flat shading instead
|
glShadeModel(GL_SMOOTH); // GL_FLAT for flat shading instead
|
||||||
glEnable(GL_DEPTH_TEST); // Enables depth comparisons
|
glEnable(GL_DEPTH_TEST); // Enables depth comparisons
|
||||||
glEnable(GL_TEXTURE_2D); // Enables use of textures
|
glEnable(GL_TEXTURE_2D); // Enables use of textures
|
||||||
|
glAlphaFunc(GL_GREATER, 0);
|
||||||
|
glEnable(GL_ALPHA_TEST);
|
||||||
|
|
||||||
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
|
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
|
||||||
|
|
||||||
@ -220,6 +230,8 @@ int main(void) {
|
|||||||
|
|
||||||
int playerScore = 0;
|
int playerScore = 0;
|
||||||
|
|
||||||
|
int playerLives = 3;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ----------------
|
* ----------------
|
||||||
* Font stuff
|
* Font stuff
|
||||||
@ -238,6 +250,19 @@ int main(void) {
|
|||||||
.b = 255
|
.b = 255
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* --------------------------------
|
||||||
|
* Loading required textures
|
||||||
|
* --------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
GLuint heartFullTex;
|
||||||
|
GLuint heartEmptyTex;
|
||||||
|
if (
|
||||||
|
loadTextures(&heartEmptyTex, "assets/heartUsed.png") ||
|
||||||
|
loadTextures(&heartFullTex, "assets/heartFull.png") > 1) {
|
||||||
|
return 6;
|
||||||
|
}
|
||||||
/*
|
/*
|
||||||
* ----------------
|
* ----------------
|
||||||
* Let's go!
|
* Let's go!
|
||||||
@ -303,8 +328,11 @@ int main(void) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
updatePaddle(tickrate, &thePaddle, moveX, winWidth, winHeight);
|
updatePaddle(tickrate, &thePaddle, moveX, winWidth, winHeight);
|
||||||
updateBall(tickrate, &theBall, &thePaddle, winWidth, winHeight, &bricks, brickCount);
|
updateBall(tickrate, &theBall, &thePaddle, winWidth, winHeight, &bricks, brickCount, &playerLives);
|
||||||
updateScore(&playerScore, &bricks, brickCount);
|
updateScore(&playerScore, &bricks, brickCount);
|
||||||
|
if (playerLives < 1) {
|
||||||
|
go = 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (step % (subSteps+1) == 0) {
|
if (step % (subSteps+1) == 0) {
|
||||||
//step = 0;
|
//step = 0;
|
||||||
@ -316,7 +344,7 @@ int main(void) {
|
|||||||
|
|
||||||
SDL_GL_MakeCurrent(window1, context1);
|
SDL_GL_MakeCurrent(window1, context1);
|
||||||
|
|
||||||
sprintf(windowTitle, "Breakout: Score %d", playerScore);
|
sprintf(windowTitle, "Breakout: Score (%d), lives remaining (%d)", playerScore, playerLives);
|
||||||
SDL_SetWindowTitle(window1, windowTitle);
|
SDL_SetWindowTitle(window1, windowTitle);
|
||||||
|
|
||||||
glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
|
glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
|
||||||
@ -335,6 +363,7 @@ int main(void) {
|
|||||||
bgcol1.b = 0.6078; /*155*/ bgcol2.b = 0.4431; /*113*/
|
bgcol1.b = 0.6078; /*155*/ bgcol2.b = 0.4431; /*113*/
|
||||||
bgcol1.a = 1.0000; /*255*/ bgcol2.a = 1.0000; /*255*/
|
bgcol1.a = 1.0000; /*255*/ bgcol2.a = 1.0000; /*255*/
|
||||||
|
|
||||||
|
drawHearts(heartFullTex, heartEmptyTex, playerLives, winWidth, winHeight);
|
||||||
drawPaddle(&thePaddle, winWidth, winHeight, &paddleCol);
|
drawPaddle(&thePaddle, winWidth, winHeight, &paddleCol);
|
||||||
drawBall(&theBall, &paddleCol);
|
drawBall(&theBall, &paddleCol);
|
||||||
drawBricks(&bricks, brickCount, winWidth, winHeight, &brickColours);
|
drawBricks(&bricks, brickCount, winWidth, winHeight, &brickColours);
|
||||||
@ -365,6 +394,37 @@ int main(void) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int loadTextures(GLuint *texture, const char *imageLoc) {
|
||||||
|
char errorMsg[512];
|
||||||
|
sprintf(errorMsg, "[FAILED] Opening %s", imageLoc);
|
||||||
|
SDL_Surface *surface = IMG_Load(imageLoc);
|
||||||
|
if (surface == NULL) {
|
||||||
|
fprintf(stderr, errorMsg);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
*texture = 0;
|
||||||
|
|
||||||
|
// Start of code from SDLTutorials.com
|
||||||
|
|
||||||
|
int Mode = GL_RGB;
|
||||||
|
|
||||||
|
glGenTextures(1, texture);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, *texture);
|
||||||
|
|
||||||
|
if (surface->format->BytesPerPixel == 4) {
|
||||||
|
Mode = GL_RGBA;
|
||||||
|
}
|
||||||
|
glTexImage2D(GL_TEXTURE_2D, 0, Mode, surface->w, surface->h, 0, Mode, GL_UNSIGNED_BYTE, surface->pixels);
|
||||||
|
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
|
|
||||||
|
// End of code from SDLTutorials.com
|
||||||
|
// Tim Jones (2011) SDL Surface to OpenGL Texture, Available at: http://www.sdltutorials.com/sdl-tip-sdl-surface-to-opengl-texture (Accessed: 10/01/2018)
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
char vertexWithinQuad(coord point, coord *quad) {
|
char vertexWithinQuad(coord point, coord *quad) {
|
||||||
double quadArea = heronsFormula(quad[0], quad[1], quad[2]) + heronsFormula(quad[1], quad[2], quad[3]);
|
double quadArea = heronsFormula(quad[0], quad[1], quad[2]) + heronsFormula(quad[1], quad[2], quad[3]);
|
||||||
double testArea = 0;
|
double testArea = 0;
|
||||||
@ -385,7 +445,7 @@ void updatePaddle(Uint32 tickrate, paddle *thePaddle, char moveX, int winWidth,
|
|||||||
if (thePaddle->x > winWidth-(thePaddle->width/2)) thePaddle->x = winWidth-(thePaddle->width/2);
|
if (thePaddle->x > winWidth-(thePaddle->width/2)) thePaddle->x = winWidth-(thePaddle->width/2);
|
||||||
}
|
}
|
||||||
|
|
||||||
void updateBall(Uint32 tickrate, ball *theBall, paddle *thePaddle, int winWidth, int winHeight, brick *bricks, int brickCount) {
|
void updateBall(Uint32 tickrate, ball *theBall, paddle *thePaddle, int winWidth, int winHeight, brick *bricks, int brickCount, int *playerLives) {
|
||||||
double ballNX = theBall->x + theBall->vX * 0.1 * tickrate; // Calculates the position of the ball's centre on the next step
|
double ballNX = theBall->x + theBall->vX * 0.1 * tickrate; // Calculates the position of the ball's centre on the next step
|
||||||
double ballNY = theBall->y + theBall->vY * 0.1 * tickrate;
|
double ballNY = theBall->y + theBall->vY * 0.1 * tickrate;
|
||||||
|
|
||||||
@ -482,6 +542,7 @@ void updateBall(Uint32 tickrate, ball *theBall, paddle *thePaddle, int winWidth,
|
|||||||
theBall->y = 0;
|
theBall->y = 0;
|
||||||
theBall->vX = theBall->initVX;
|
theBall->vX = theBall->initVX;
|
||||||
theBall->vY = theBall->initVY;
|
theBall->vY = theBall->initVY;
|
||||||
|
*playerLives -= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update the ball's position
|
// Update the ball's position
|
||||||
@ -512,6 +573,34 @@ void updateScore(int *playerScore, brick *bricks, int brickCount) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void drawHearts(GLuint heartFullTex, GLuint heartEmptyTex, int playerLives, int winWidth, int winHeight) {
|
||||||
|
coord locations[3] = { {.x = -19, .y = -32}, { .x = 0, .y = -32 }, { .x = 19, .y = -32 } };
|
||||||
|
|
||||||
|
for (int i = 0; i < 3; i++) {
|
||||||
|
if (i > playerLives-1) {
|
||||||
|
glBindTexture(GL_TEXTURE_2D, heartEmptyTex);
|
||||||
|
} else {
|
||||||
|
glBindTexture(GL_TEXTURE_2D, heartFullTex);
|
||||||
|
}
|
||||||
|
GLint matrixmode = 0;
|
||||||
|
glGetIntegerv(GL_MATRIX_MODE, &matrixmode);
|
||||||
|
glPushMatrix();
|
||||||
|
glTranslated(0.0, (winHeight/2), 0.0);
|
||||||
|
|
||||||
|
glBegin(GL_QUADS);
|
||||||
|
glTexCoord2f(0, 0); glVertex3d(0.0+locations[i].x, 0.0+locations[i].y, 0.0);
|
||||||
|
glTexCoord2f(0, 1); glVertex3d(0.0+locations[i].x, -15.0 + locations[i].y, 0.0);
|
||||||
|
glTexCoord2f(1, 1); glVertex3d(15.0+locations[i].x, -15.0 + locations[i].y, 0.0);
|
||||||
|
glTexCoord2f(1, 0); glVertex3d(15.0+locations[i].x, 0.0 + locations[i].y, 0.0);
|
||||||
|
glEnd();
|
||||||
|
|
||||||
|
glPopMatrix();
|
||||||
|
glMatrixMode(matrixmode);
|
||||||
|
}
|
||||||
|
|
||||||
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
|
}
|
||||||
|
|
||||||
void drawBg(int winWidth, int winHeight, colour *c1, colour *c2) {
|
void drawBg(int winWidth, int winHeight, colour *c1, colour *c2) {
|
||||||
GLint matrixmode = 0;
|
GLint matrixmode = 0;
|
||||||
glGetIntegerv(GL_MATRIX_MODE, &matrixmode);
|
glGetIntegerv(GL_MATRIX_MODE, &matrixmode);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user