Kenneth Bruen
3 years ago
commit
e2a0f56261
10 changed files with 462 additions and 0 deletions
@ -0,0 +1,33 @@
|
||||
{ |
||||
// Use IntelliSense to learn about possible attributes. |
||||
// Hover to view descriptions of existing attributes. |
||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 |
||||
"version": "0.2.0", |
||||
"configurations": [ |
||||
{ |
||||
"name": "(gdb) Launch", |
||||
"type": "cppdbg", |
||||
"request": "launch", |
||||
"program": "${workspaceFolder}/program", |
||||
"args": [], |
||||
"stopAtEntry": false, |
||||
"cwd": "${fileDirname}", |
||||
"environment": [], |
||||
"externalConsole": false, |
||||
"MIMode": "gdb", |
||||
"setupCommands": [ |
||||
{ |
||||
"description": "Enable pretty-printing for gdb", |
||||
"text": "-enable-pretty-printing", |
||||
"ignoreFailures": true |
||||
}, |
||||
{ |
||||
"description": "Set Disassembly Flavor to Intel", |
||||
"text": "-gdb-set disassembly-flavor intel", |
||||
"ignoreFailures": true |
||||
} |
||||
], |
||||
"preLaunchTask": "build debug" |
||||
} |
||||
] |
||||
} |
@ -0,0 +1,5 @@
|
||||
{ |
||||
"files.associations": { |
||||
"array": "cpp" |
||||
} |
||||
} |
@ -0,0 +1,27 @@
|
||||
{ |
||||
// See https://go.microsoft.com/fwlink/?LinkId=733558 |
||||
// for the documentation about the tasks.json format |
||||
"version": "2.0.0", |
||||
"tasks": [ |
||||
{ |
||||
"label": "build", |
||||
"type": "shell", |
||||
"command": "make -B", |
||||
"problemMatcher": [], |
||||
"group": { |
||||
"kind": "build", |
||||
"isDefault": true |
||||
} |
||||
}, |
||||
{ |
||||
"label": "build debug", |
||||
"type": "shell", |
||||
"options": { |
||||
"env": { |
||||
"CXX_PARAMS": "-g" |
||||
} |
||||
}, |
||||
"command": "make -B" |
||||
} |
||||
] |
||||
} |
@ -0,0 +1,20 @@
|
||||
LD_PARAMS := -lglut -lGL -lGLU
|
||||
SRC := src
|
||||
OBJ := obj
|
||||
CXX := g++
|
||||
LD := g++
|
||||
|
||||
SOURCES := $(wildcard $(SRC)/*.cpp)
|
||||
OBJECTS := $(patsubst $(SRC)/%.cpp, $(OBJ)/%.o, $(SOURCES))
|
||||
|
||||
all: program |
||||
|
||||
clean: |
||||
rm -f program
|
||||
rm -rf obj
|
||||
|
||||
program: ${OBJECTS} |
||||
$(LD) ${LD_PARAMS} $^ -o $@
|
||||
|
||||
$(OBJECTS): $(OBJ)/%.o: $(SRC)/%.cpp |
||||
$(CXX) ${CXX_PARAMS} $< -c -o $@
|
@ -0,0 +1,6 @@
|
||||
#pragma once |
||||
|
||||
class Drawable { |
||||
public: |
||||
virtual void draw() = 0; |
||||
}; |
@ -0,0 +1,201 @@
|
||||
#include <functional> |
||||
#include <string> |
||||
#include <cmath> |
||||
|
||||
#include <GL/gl.h> |
||||
#include <GL/glu.h> |
||||
#include <GL/glut.h> |
||||
|
||||
#include "pixel_wise.h" |
||||
#include "drawable.h" |
||||
#include "utils.hpp" |
||||
|
||||
GLfloat deltaTime; |
||||
|
||||
bool gameRunning = false; |
||||
|
||||
bool mouseDown = false; |
||||
int leftScore = 0; |
||||
int rightScore = 0; |
||||
|
||||
int leftMove = 0; |
||||
int rightMove = 0; |
||||
|
||||
void mouse(int button, int state, int x, int y) { |
||||
if (state == GLUT_DOWN) { |
||||
gameRunning = true; |
||||
} |
||||
} |
||||
|
||||
class BoardMiddle : public Drawable { |
||||
public: |
||||
virtual void draw() { |
||||
glBegin(GL_POLYGON); |
||||
glColor3ub(0xBD, 0xBD, 0xBD); |
||||
glVertex2fv(PW::nm(-2, -1).data()); |
||||
glVertex2fv(PW::nm(2, -1).data()); |
||||
glVertex2fv(PW::nm(2, 1).data()); |
||||
glVertex2fv(PW::nm(-2, 1).data()); |
||||
glEnd(); |
||||
} |
||||
} bm; |
||||
|
||||
class Ball : public Drawable { |
||||
public: |
||||
GLfloat radius; |
||||
GLfloat x, y; |
||||
GLfloat veloX, veloY; |
||||
|
||||
Ball(GLfloat x, GLfloat y) : x(x), y(y), radius(0.025), veloX(0.4) { |
||||
|
||||
} |
||||
|
||||
virtual void draw() { |
||||
glBegin(GL_POLYGON); |
||||
glColor3ub(0xFF, 0xEE, 0x58); |
||||
for (float i = 0; i < 360; i += 0.5) { |
||||
const auto rad = Utils::toRad(i); |
||||
glVertex2f(x + radius * cos(rad), y + radius * sin(rad)); |
||||
} |
||||
glEnd(); |
||||
} |
||||
|
||||
void update() { |
||||
x += veloX * deltaTime; |
||||
y += veloY * deltaTime; |
||||
} |
||||
} ball {0, 0}; |
||||
|
||||
class Text : public Drawable { |
||||
std::function<std::string()> strObtainer; |
||||
public: |
||||
std::function<GLfloat()> x, y; |
||||
void *font; |
||||
Text(std::function<std::string()> strObtainer, GLfloat x, GLfloat y) : strObtainer(strObtainer), x([=](){return x;}), y([=](){return y;}), font(GLUT_BITMAP_HELVETICA_18) {} |
||||
Text(std::function<std::string()> strObtainer, std::function<GLfloat()> x, std::function<GLfloat()> y) : strObtainer(strObtainer), x(x), y(y), font(GLUT_BITMAP_HELVETICA_18) {} |
||||
Text(std::function<std::string()> strObtainer, std::array<GLfloat, 2> pos) : strObtainer(strObtainer), x([=](){return pos[0];}), y([=](){return pos[1];}), font(GLUT_BITMAP_HELVETICA_18) {} |
||||
Text(std::function<std::string()> strObtainer, std::function<std::array<GLfloat, 2>()> pos) : strObtainer(strObtainer), x([=](){return pos()[0];}), y([=](){return pos()[1];}), font(GLUT_BITMAP_HELVETICA_18) {} |
||||
|
||||
virtual void draw() { |
||||
glRasterPos2f(x(), y()); |
||||
for (const auto& c: strObtainer()) { |
||||
glutBitmapCharacter(font, c); |
||||
} |
||||
} |
||||
} leftScoreText{[](){ return std::to_string(leftScore); }, [](){return PW::tm(-100, 20);}}, |
||||
rightScoreText{[](){ return std::to_string(rightScore); }, [](){return PW::tm(100, 20);}}; |
||||
|
||||
class Paddle : public Drawable { |
||||
public: |
||||
GLfloat height, width; |
||||
GLfloat x, y; |
||||
|
||||
Paddle(GLfloat x, GLfloat y) : x(x), y(y), height(0.4), width(0.02) {} |
||||
|
||||
virtual void draw() { |
||||
glBegin(GL_POLYGON); |
||||
glVertex2f(x, y); |
||||
glVertex2f(x + width, y); |
||||
glVertex2f(x + width, y + height); |
||||
glVertex2f(x, y + height); |
||||
glEnd(); |
||||
} |
||||
} leftPaddle{-0.9, -0.2}, rightPaddle{0.9 - 0.02, -0.2}; |
||||
|
||||
void display(void) { |
||||
glClear(GL_COLOR_BUFFER_BIT); |
||||
|
||||
bm.draw(); |
||||
ball.draw(); |
||||
|
||||
glColor3ub(0x66, 0xBB, 0x6A); |
||||
leftScoreText.draw(); |
||||
leftPaddle.draw(); |
||||
|
||||
glColor3ub(0x42, 0xA5, 0xF5); |
||||
rightScoreText.draw(); |
||||
rightPaddle.draw(); |
||||
|
||||
glFlush(); |
||||
} |
||||
|
||||
int gameTime; |
||||
|
||||
const GLfloat paddleMoveSpeed = 0.75; |
||||
|
||||
void idle() { |
||||
int newTime = glutGet(GLUT_ELAPSED_TIME); |
||||
deltaTime = (newTime - gameTime) / 1000.0; |
||||
gameTime = newTime; |
||||
|
||||
if (gameRunning) { |
||||
ball.update(); |
||||
|
||||
// Move paddle
|
||||
leftPaddle.y += leftMove * paddleMoveSpeed * deltaTime; |
||||
rightPaddle.y += rightMove * paddleMoveSpeed * deltaTime; |
||||
|
||||
// Clamp paddle to stay on screen
|
||||
if (leftPaddle.y < -1) leftPaddle.y = -1; |
||||
if (rightPaddle.y < -1) rightPaddle.y = -1; |
||||
if (leftPaddle.y > 1 - leftPaddle.height) leftPaddle.y = 1 - leftPaddle.height; |
||||
if (rightPaddle.y > 1 - rightPaddle.height) rightPaddle.y = 1 - rightPaddle.height; |
||||
} |
||||
|
||||
glutPostRedisplay(); |
||||
} |
||||
|
||||
void keyDown(unsigned char key, int x, int y) { |
||||
switch(key) { |
||||
case 'w': |
||||
case 'W': |
||||
leftMove = 1; |
||||
break; |
||||
case 's': |
||||
case 'S': |
||||
leftMove = -1; |
||||
break; |
||||
case 'p': |
||||
case 'P': |
||||
rightMove = 1; |
||||
break; |
||||
case ';': |
||||
case ':': |
||||
rightMove = -1; |
||||
break; |
||||
} |
||||
} |
||||
|
||||
void keyUp(unsigned char key, int x, int y) { |
||||
switch(key) { |
||||
case 'w': |
||||
case 'W': |
||||
case 's': |
||||
case 'S': |
||||
leftMove = 0; |
||||
break; |
||||
case 'p': |
||||
case 'P': |
||||
case ';': |
||||
case ':': |
||||
rightMove = 0; |
||||
break; |
||||
} |
||||
} |
||||
|
||||
int main(int argc, char** argv) |
||||
{ |
||||
glutInit(&argc, argv); |
||||
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB); |
||||
glutInitWindowSize(600, 600); |
||||
glutInitWindowPosition(glutGet(GLUT_SCREEN_WIDTH) * 0.6, (glutGet(GLUT_SCREEN_HEIGHT) - 600) * 0.5); |
||||
glutCreateWindow("Pong"); |
||||
glutSetKeyRepeat(GLUT_KEY_REPEAT_OFF); |
||||
glutKeyboardFunc(keyDown); |
||||
glutKeyboardUpFunc(keyUp); |
||||
glutDisplayFunc(display); |
||||
glutMouseFunc(mouse); |
||||
glutIdleFunc(idle); |
||||
glutMainLoop(); |
||||
return 0; |
||||
} |
@ -0,0 +1,63 @@
|
||||
#include "pixel_wise.h" |
||||
|
||||
#include <GL/glut.h> |
||||
#include "utils.hpp" |
||||
|
||||
// For personal reference:
|
||||
// x - left->right
|
||||
// y - bottom->top
|
||||
|
||||
std::array<GLfloat, 2> PW::toRelative(GLfloat x, GLfloat y, PW::Anchor anchor) { |
||||
auto winWidth = glutGet(GLUT_WINDOW_WIDTH); |
||||
auto winHeight = glutGet(GLUT_WINDOW_HEIGHT); |
||||
|
||||
std::array<GLfloat, 2> result; |
||||
|
||||
switch (anchor) { |
||||
case PW::BOTTOM_LEFT: |
||||
case PW::MID_LEFT: |
||||
case PW::TOP_LEFT: |
||||
case PW::NONE_LEFT: |
||||
result[0] = Utils::nummap(x, (GLfloat)0, (GLfloat)winWidth, (GLfloat)-1, (GLfloat)1); |
||||
break; |
||||
case PW::BOTTOM_MID: |
||||
case PW::CENTER: |
||||
case PW::TOP_MID: |
||||
case PW::NONE_MID: |
||||
result[0] = Utils::nummap(x, -((GLfloat)winWidth) / 2, ((GLfloat)winWidth) / 2, (GLfloat)-1, (GLfloat)1); |
||||
break; |
||||
case PW::BOTTOM_RIGHT: |
||||
case PW::MID_RIGHT: |
||||
case PW::TOP_RIGHT: |
||||
case PW::NONE_RIGHT: |
||||
result[0] = Utils::nummap(x, -(GLfloat)winWidth, (GLfloat)0, (GLfloat)-1, (GLfloat)1); |
||||
break; |
||||
default: |
||||
result[0] = x; |
||||
} |
||||
|
||||
switch (anchor) { |
||||
case PW::TOP_LEFT: |
||||
case PW::TOP_MID: |
||||
case PW::TOP_RIGHT: |
||||
case PW::TOP_NONE: |
||||
result[1] = Utils::nummap(y, (GLfloat)0, (GLfloat)winHeight, (GLfloat)1, (GLfloat)-1); |
||||
break; |
||||
case PW::MID_LEFT: |
||||
case PW::CENTER: |
||||
case PW::MID_RIGHT: |
||||
case PW::MID_NONE: |
||||
result[1] = Utils::nummap(y, -((GLfloat)winHeight) / 2, ((GLfloat)winHeight) / 2, (GLfloat)1, (GLfloat)-1); |
||||
break; |
||||
case PW::BOTTOM_LEFT: |
||||
case PW::BOTTOM_MID: |
||||
case PW::BOTTOM_RIGHT: |
||||
case PW::BOTTOM_NONE: |
||||
result[1] = Utils::nummap(y, (GLfloat)0, -(GLfloat)winHeight, (GLfloat)1, (GLfloat)-1); |
||||
break; |
||||
default: |
||||
result[1] = y; |
||||
} |
||||
|
||||
return std::move(result); |
||||
} |
@ -0,0 +1,89 @@
|
||||
#pragma once |
||||
|
||||
#include <array> |
||||
|
||||
#include <GL/gl.h> |
||||
|
||||
namespace PW { |
||||
enum Anchor |
||||
{ |
||||
MID_LEFT, |
||||
TOP_LEFT, |
||||
TOP_MID, |
||||
TOP_RIGHT, |
||||
MID_RIGHT, |
||||
BOTTOM_RIGHT, |
||||
BOTTOM_MID, |
||||
BOTTOM_LEFT, |
||||
CENTER, |
||||
TOP_NONE, |
||||
MID_NONE, |
||||
BOTTOM_NONE, |
||||
NONE_LEFT, |
||||
NONE_MID, |
||||
NONE_RIGHT, |
||||
}; |
||||
|
||||
/// Convert pixel-space x and y to relative-space (-1 -> 0 -> 1) coords
|
||||
std::array<GLfloat, 2> toRelative(GLfloat x, GLfloat y, Anchor anchor); |
||||
/// Mid-Left `toRelative`
|
||||
inline std::array<GLfloat, 2> ml(GLfloat x, GLfloat y) { |
||||
return PW::toRelative(x, y, PW::MID_LEFT); |
||||
} |
||||
/// Top-Left `toRelative`
|
||||
inline std::array<GLfloat, 2> tl(GLfloat x, GLfloat y) { |
||||
return PW::toRelative(x, y, PW::TOP_LEFT); |
||||
} |
||||
/// Top-Mid `toRelative`
|
||||
inline std::array<GLfloat, 2> tm(GLfloat x, GLfloat y) { |
||||
return PW::toRelative(x, y, PW::TOP_MID); |
||||
} |
||||
/// Top-Right `toRelative`
|
||||
inline std::array<GLfloat, 2> tr(GLfloat x, GLfloat y) { |
||||
return PW::toRelative(x, y, PW::TOP_RIGHT); |
||||
} |
||||
/// Mid-Right `toRelative`
|
||||
inline std::array<GLfloat, 2> mr(GLfloat x, GLfloat y) { |
||||
return PW::toRelative(x, y, PW::MID_RIGHT); |
||||
} |
||||
/// Bottom-Right `toRelative`
|
||||
inline std::array<GLfloat, 2> br(GLfloat x, GLfloat y) { |
||||
return PW::toRelative(x, y, PW::BOTTOM_RIGHT); |
||||
} |
||||
/// Bottom-Mid `toRelative`
|
||||
inline std::array<GLfloat, 2> bm(GLfloat x, GLfloat y) { |
||||
return PW::toRelative(x, y, PW::BOTTOM_MID); |
||||
} |
||||
/// Bottom-Left `toRelative`
|
||||
inline std::array<GLfloat, 2> bl(GLfloat x, GLfloat y) { |
||||
return PW::toRelative(x, y, PW::BOTTOM_LEFT); |
||||
} |
||||
/// Center `toRelative`
|
||||
inline std::array<GLfloat, 2> c(GLfloat x, GLfloat y) { |
||||
return PW::toRelative(x, y, PW::CENTER); |
||||
} |
||||
/// Top-None `toRelative`
|
||||
inline std::array<GLfloat, 2> tn(GLfloat x, GLfloat y) { |
||||
return PW::toRelative(x, y, PW::TOP_NONE); |
||||
} |
||||
/// Mid-None `toRelative`
|
||||
inline std::array<GLfloat, 2> mn(GLfloat x, GLfloat y) { |
||||
return PW::toRelative(x, y, PW::MID_NONE); |
||||
} |
||||
/// Bottom-None `toRelative`
|
||||
inline std::array<GLfloat, 2> bn(GLfloat x, GLfloat y) { |
||||
return PW::toRelative(x, y, PW::BOTTOM_NONE); |
||||
} |
||||
/// None-Left `toRelative`
|
||||
inline std::array<GLfloat, 2> nl(GLfloat x, GLfloat y) { |
||||
return PW::toRelative(x, y, PW::NONE_LEFT); |
||||
} |
||||
/// None-Mid `toRelative`
|
||||
inline std::array<GLfloat, 2> nm(GLfloat x, GLfloat y) { |
||||
return PW::toRelative(x, y, PW::NONE_MID); |
||||
} |
||||
/// None-Right `toRelative`
|
||||
inline std::array<GLfloat, 2> nr(GLfloat x, GLfloat y) { |
||||
return PW::toRelative(x, y, PW::NONE_RIGHT); |
||||
} |
||||
} |
@ -0,0 +1,16 @@
|
||||
#pragma once |
||||
|
||||
namespace Utils { |
||||
const double PI = 3.14159265358979323846; |
||||
|
||||
template <typename T> |
||||
T nummap(T input, T inMin, T inMax, T outMin, T outMax) { |
||||
// From: https://www.arduino.cc/reference/en/language/functions/math/map/
|
||||
return (input - inMin) * (outMax - outMin) / (inMax - inMin) + outMin; |
||||
} |
||||
|
||||
template <typename T> |
||||
constexpr T toRad(T deg) { |
||||
return deg * PI / 180; |
||||
} |
||||
} |
Loading…
Reference in new issue