Started to split sections of the program into their own header / source files
This commit is contained in:
parent
f29f78e634
commit
bf52ead7cc
1445
breakout/breakout.c
1445
breakout/breakout.c
File diff suppressed because it is too large
Load Diff
1103
breakout/bricks.c
Normal file
1103
breakout/bricks.c
Normal file
File diff suppressed because it is too large
Load Diff
2
breakout/include/bricks.h
Normal file
2
breakout/include/bricks.h
Normal file
@ -0,0 +1,2 @@
|
||||
void initialiseBricks(brick *bricks, int *brickCount);
|
||||
void initialiseBricks2(brick *bricks, int *brickCount);
|
||||
2
breakout/include/paddleAndBall.h
Normal file
2
breakout/include/paddleAndBall.h
Normal file
@ -0,0 +1,2 @@
|
||||
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, int *playerLives);
|
||||
6
breakout/include/render.h
Normal file
6
breakout/include/render.h
Normal file
@ -0,0 +1,6 @@
|
||||
void drawHearts(GLuint heartFullTex, GLuint heartEmptyTex, int playerLives, int winWidth, int winHeight);
|
||||
void drawPaddle(paddle *thePaddle, int winWidth, int winHeight, colour *c);
|
||||
void drawBall(ball *theBall, colour *c);
|
||||
void drawBricks(brick *bricks, int brickCount, int winWidth, int winHeight, colour *colours);
|
||||
void drawBg(int winWidth, int winHeight, colour *c1, colour *c2);
|
||||
void drawText(const char *text, TTF_Font *font, SDL_Color txtColour, coord loc);
|
||||
48
breakout/include/structs.h
Normal file
48
breakout/include/structs.h
Normal file
@ -0,0 +1,48 @@
|
||||
typedef struct coord {
|
||||
double x;
|
||||
double y;
|
||||
} coord;
|
||||
|
||||
typedef struct colour {
|
||||
double r;
|
||||
double g;
|
||||
double b;
|
||||
double a;
|
||||
} colour;
|
||||
|
||||
typedef struct paddle {
|
||||
int width;
|
||||
int height;
|
||||
double x;
|
||||
} paddle;
|
||||
|
||||
typedef struct ball {
|
||||
double x;
|
||||
double y;
|
||||
double vX;
|
||||
double vY;
|
||||
double initVX;
|
||||
double initVY;
|
||||
double radius;
|
||||
char isColliding;
|
||||
char stickToPaddle;
|
||||
} ball;
|
||||
|
||||
typedef struct brick {
|
||||
char brickType;
|
||||
int x;
|
||||
int y;
|
||||
int width;
|
||||
int height;
|
||||
char destroyed;
|
||||
} brick;
|
||||
|
||||
typedef struct brickCD {
|
||||
char isLeaf;
|
||||
int x;
|
||||
int y;
|
||||
int width;
|
||||
int height;
|
||||
struct brickCD *container;
|
||||
int brickID;
|
||||
} brickCD;
|
||||
2
breakout/include/utilityFunctions.h
Normal file
2
breakout/include/utilityFunctions.h
Normal file
@ -0,0 +1,2 @@
|
||||
double heronsFormula(coord a, coord b, coord c);
|
||||
char vertexWithinQuad(coord point, coord *quad);
|
||||
129
breakout/paddleAndBall.c
Normal file
129
breakout/paddleAndBall.c
Normal file
@ -0,0 +1,129 @@
|
||||
#ifdef _WIN32
|
||||
#include <SDL.h>
|
||||
#else
|
||||
#include <SDL2/SDL.h>
|
||||
#endif
|
||||
#include "include/structs.h"
|
||||
#include "include/utilityFunctions.h"
|
||||
|
||||
void updatePaddle(Uint32 tickrate, paddle *thePaddle, char moveX, int winWidth, int winHeight) {
|
||||
thePaddle->x += moveX * 0.5 * tickrate;
|
||||
if (thePaddle->x < 0 - (thePaddle->width / 2)) thePaddle->x = 0 - (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, int *playerLives) {
|
||||
if (theBall->stickToPaddle == 0) {
|
||||
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 paddleRX = thePaddle->x - (double)(winWidth / 2); // Converts paddle X/Y to coordinates relative to the center of the window as the ball
|
||||
double paddleRY = 20 - (double)(winHeight / 2); // (Default is absolute, offset from the top left corner of window)
|
||||
|
||||
coord paddleQ[4] = {
|
||||
{ .x = paddleRX,.y = paddleRY }, // Sets up a quad (coord array) to pass to vertexWithinQuad function later
|
||||
{ .x = paddleRX,.y = paddleRY - thePaddle->height },
|
||||
{ .x = paddleRX + thePaddle->width,.y = paddleRY - thePaddle->height },
|
||||
{ .x = paddleRX + thePaddle->width,.y = paddleRY },
|
||||
};
|
||||
|
||||
// Collision with paddle
|
||||
// (Testing each vertex of ball against paddle quad)
|
||||
|
||||
char colliding = 0;
|
||||
int mults[4] = { -1,-1,1,1 };
|
||||
|
||||
for (int i = 0, j = 3; i < 4; i++, j++) {
|
||||
coord ballN = { .x = ballNX + (theBall->radius*mults[i % 4]),.y = ballNY + (theBall->radius*mults[j % 4]) }; // Constructs pairs of coordinates referring to each vertex of the ball
|
||||
if (vertexWithinQuad(ballN, paddleQ)) colliding = 1;
|
||||
}
|
||||
|
||||
if (colliding) {
|
||||
if (theBall->isColliding == 0) {
|
||||
|
||||
theBall->isColliding = 1; // This keeps track of any current attepmts to 'solve' collision
|
||||
// Without this flag, if the ball ends up within another object and moving slow enough that on the next frame it has not escaped the object,
|
||||
// it will repeatedly have its velocity multiplied by -1 and get stuck, effectively moving only along one axis. With this flag,
|
||||
// the game will ignore subsequent collisions, until it is no longer colliding. Note this does not solve the same problem where two objects
|
||||
// are very close to each other and on exiting one object it enters another, in which case the ball will move through the other objects
|
||||
|
||||
if (theBall->x + theBall->radius < paddleRX) { // Left side collision
|
||||
theBall->vX *= -1.0;
|
||||
}
|
||||
else if (theBall->x - theBall->radius > paddleRX + thePaddle->width) { // Right side collision
|
||||
theBall->vX *= -1.0;
|
||||
}
|
||||
else { // Top or bottom collision
|
||||
theBall->vY *= -1.0;
|
||||
theBall->vX = ((ballNX - paddleRX - (double)(thePaddle->width / 2)) / ((double)thePaddle->width / 2))*theBall->initVX; // Sets X velocity to be proportional to the relative position of the ball and the paddle on collision
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Already solving a collision
|
||||
}
|
||||
}
|
||||
else {
|
||||
theBall->isColliding = 0;
|
||||
}
|
||||
|
||||
// Collision with bricks
|
||||
// (Testing each vertex of ball against every brick)
|
||||
|
||||
for (int i = 0; i < brickCount; i++) {
|
||||
colliding = 0;
|
||||
|
||||
if (bricks[i].destroyed == 0) {
|
||||
coord brick[4] = {
|
||||
{ .x = bricks[i].x - (winWidth / 2),.y = bricks[i].y },
|
||||
{ .x = bricks[i].x - (winWidth / 2),.y = bricks[i].y - bricks[i].height },
|
||||
{ .x = bricks[i].x - (winWidth / 2) + bricks[i].width,.y = bricks[i].y - bricks[i].height },
|
||||
{ .x = bricks[i].x - (winWidth / 2) + bricks[i].width,.y = bricks[i].y },
|
||||
};
|
||||
|
||||
for (int j = 0, k = 3; j < 4; j++, k++) {
|
||||
coord ballN = { .x = ballNX + (theBall->radius*mults[j % 4]),.y = ballNY + (theBall->radius*mults[k % 4]) };
|
||||
if (vertexWithinQuad(ballN, brick)) colliding = 1;
|
||||
}
|
||||
|
||||
if (colliding) {
|
||||
if (theBall->x + theBall->radius < bricks[i].x - (winWidth / 2)) { // Left side collision
|
||||
theBall->vX *= -1.0;
|
||||
}
|
||||
else if (theBall->x - theBall->radius > bricks[i].x - (winWidth / 2) + bricks[i].width) { // Right side collision
|
||||
theBall->vX *= -1.0;
|
||||
}
|
||||
else {
|
||||
theBall->vY *= -1.0;
|
||||
}
|
||||
bricks[i].destroyed = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Collision with window boundaries
|
||||
|
||||
if (ballNX > winWidth / 2 || ballNX < (-1.0*winWidth / 2)) { // Collision with walls
|
||||
theBall->vX *= -1.0;
|
||||
}
|
||||
if (ballNY > winHeight / 2) { // Collision with ceiling
|
||||
theBall->vY *= -1.0;
|
||||
}
|
||||
if (ballNY < (-1.0*winHeight / 2)) { // Collision with floor
|
||||
theBall->x = 0;
|
||||
theBall->y = 0;
|
||||
theBall->vX = theBall->initVX;
|
||||
theBall->vY = theBall->initVY;
|
||||
*playerLives -= 1;
|
||||
}
|
||||
|
||||
// Update the ball's position
|
||||
|
||||
theBall->x += theBall->vX * 0.1 * tickrate;
|
||||
theBall->y += theBall->vY * 0.1 * tickrate;
|
||||
}
|
||||
else {
|
||||
theBall->x = thePaddle->x - (double)(winWidth / 2) + (thePaddle->width) / 2;
|
||||
theBall->y = 26 - (double)(winHeight / 2);
|
||||
}
|
||||
}
|
||||
154
breakout/render.c
Normal file
154
breakout/render.c
Normal file
@ -0,0 +1,154 @@
|
||||
#ifdef _WIN32
|
||||
#include <Windows.h>
|
||||
#include <SDL.h>
|
||||
#include <SDL_ttf.h>
|
||||
#include <SDL_image.h>
|
||||
#else
|
||||
#include <SDL2/SDL.h>
|
||||
#include <SDL2/SDL_ttf.h>
|
||||
#include <SDL2/SDL_image.h>
|
||||
#endif
|
||||
#include <GL/gl.h>
|
||||
#include <GL/glu.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "include/structs.h"
|
||||
|
||||
void drawText(const char *text, TTF_Font *font, SDL_Color txtColour, coord loc) {
|
||||
SDL_Surface *text_surface = TTF_RenderUTF8_Blended(font, text, txtColour);
|
||||
if (text_surface == NULL) {
|
||||
fprintf(stderr, "Error generating text");
|
||||
}
|
||||
else {
|
||||
GLuint testTxt;
|
||||
surfaceToTexture(&testTxt, text_surface);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, testTxt);
|
||||
|
||||
GLint matrixmode = 0;
|
||||
glGetIntegerv(GL_MATRIX_MODE, &matrixmode);
|
||||
glPushMatrix();
|
||||
glTranslated(loc.x - (text_surface->w / 2), loc.y, 0.0);
|
||||
|
||||
glBegin(GL_QUADS);
|
||||
glTexCoord2f(0, 0); glVertex3d(0.0, 0.0, 0.0);
|
||||
glTexCoord2f(0, 1); glVertex3d(0.0, -1 * text_surface->h, 0.0);
|
||||
glTexCoord2f(1, 1); glVertex3d(text_surface->w, -1 * text_surface->h, 0.0);
|
||||
glTexCoord2f(1, 0); glVertex3d(text_surface->w, 0.0, 0.0);
|
||||
glEnd();
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
|
||||
glPopMatrix();
|
||||
glMatrixMode(matrixmode);
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
GLint matrixmode = 0;
|
||||
glGetIntegerv(GL_MATRIX_MODE, &matrixmode);
|
||||
glPushMatrix();
|
||||
glTranslated((GLdouble)(-1 * winWidth / 2), (GLdouble)(-1 * winHeight / 2), 0.0);
|
||||
|
||||
glBegin(GL_QUADS);
|
||||
//Top colour
|
||||
glColor3f(c1->r, c1->g, c1->b);
|
||||
glVertex2f(winWidth, 0.0);
|
||||
glVertex2f(0.0, 0.0);
|
||||
//Bottom colour
|
||||
glColor3f(c2->r, c2->g, c2->b);
|
||||
glVertex2f(0.0, winHeight);
|
||||
glVertex2f(winWidth, winHeight);
|
||||
glEnd();
|
||||
}
|
||||
|
||||
void drawPaddle(paddle *thePaddle, int winWidth, int winHeight, colour *c) {
|
||||
GLint matrixmode = 0;
|
||||
glGetIntegerv(GL_MATRIX_MODE, &matrixmode);
|
||||
glPushMatrix();
|
||||
glTranslated((GLdouble)(thePaddle->x) - winWidth / 2, (GLdouble)(20 - winHeight / 2), 0.0);
|
||||
|
||||
glBegin(GL_QUADS);
|
||||
glColor3f(c->r, c->g, c->b);
|
||||
glVertex3d(0.0, 0.0, 0.0);
|
||||
glVertex3d(0.0, (double)-1 * thePaddle->height, 0.0);
|
||||
glVertex3d((double)thePaddle->width, (double)-1 * thePaddle->height, 0.0);
|
||||
glVertex3d((double)thePaddle->width, 0.0, 0.0);
|
||||
glEnd();
|
||||
|
||||
glPopMatrix();
|
||||
glMatrixMode(matrixmode);
|
||||
}
|
||||
|
||||
void drawBall(ball *theBall, colour *c) {
|
||||
GLint matrixmode = 0;
|
||||
glGetIntegerv(GL_MATRIX_MODE, &matrixmode);
|
||||
glPushMatrix();
|
||||
glTranslated(theBall->x, theBall->y, 0.0);
|
||||
|
||||
glBegin(GL_QUADS);
|
||||
glColor3f(c->r, c->g, c->b);
|
||||
glVertex3d(-1.0*theBall->radius, 1.0*theBall->radius, 0.0);
|
||||
glVertex3d(-1.0*theBall->radius, -1.0*theBall->radius, 0.0);
|
||||
glVertex3d(1.0*theBall->radius, -1.0*theBall->radius, 0.0);
|
||||
glVertex3d(1.0*theBall->radius, 1.0*theBall->radius, 0.0);
|
||||
glEnd();
|
||||
|
||||
glPopMatrix();
|
||||
glMatrixMode(matrixmode);
|
||||
}
|
||||
|
||||
void drawBricks(brick *bricks, int brickCount, int winWidth, int winHeight, colour *colours) {
|
||||
for (int i = 0; i < brickCount; i++) {
|
||||
if (bricks[i].destroyed == 0) {
|
||||
GLint matrixmode = 0;
|
||||
glGetIntegerv(GL_MATRIX_MODE, &matrixmode);
|
||||
glPushMatrix();
|
||||
glTranslated((double)bricks[i].x - (winWidth / 2), (double)bricks[i].y, 0.0);
|
||||
glBegin(GL_QUADS);
|
||||
glColor3f(
|
||||
colours[bricks[i].brickType - 1].r,
|
||||
colours[bricks[i].brickType - 1].g,
|
||||
colours[bricks[i].brickType - 1].b
|
||||
);
|
||||
glVertex3d(0.0, 0.0, 0.0);
|
||||
glVertex3d(0.0, (double)bricks[i].height, 0.0);
|
||||
glVertex3d((double)bricks[i].width, (double)bricks[i].height, 0.0);
|
||||
glVertex3d((double)bricks[i].width, 0.0, 0.0);
|
||||
glEnd();
|
||||
glPopMatrix();
|
||||
glMatrixMode(matrixmode);
|
||||
}
|
||||
}
|
||||
}
|
||||
26
breakout/utilityFunctions.c
Normal file
26
breakout/utilityFunctions.c
Normal file
@ -0,0 +1,26 @@
|
||||
#include <math.h>
|
||||
#include "include/structs.h"
|
||||
|
||||
double heronsFormula(coord a, coord b, coord c) {
|
||||
double A = sqrt(pow((a.x - b.x), 2) + pow((a.y - b.y), 2));
|
||||
double B = sqrt(pow((b.x - c.x), 2) + pow((b.y - c.y), 2));
|
||||
double C = sqrt(pow((c.x - a.x), 2) + pow((c.y - a.y), 2));
|
||||
double s = (A + B + C) / 2;
|
||||
return sqrt(s*(s - A)*(s - B)*(s - C));
|
||||
}
|
||||
|
||||
char vertexWithinQuad(coord point, coord *quad) {
|
||||
double quadArea = heronsFormula(quad[0], quad[1], quad[2]) + heronsFormula(quad[1], quad[2], quad[3]);
|
||||
double testArea = 0;
|
||||
testArea += heronsFormula(point, quad[0], quad[1]);
|
||||
testArea += heronsFormula(point, quad[1], quad[2]);
|
||||
testArea += heronsFormula(point, quad[2], quad[3]);
|
||||
testArea += heronsFormula(point, quad[3], quad[0]);
|
||||
if ((int)testArea == (int)quadArea) {
|
||||
return 1;
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user