Browse Source

Initial commit

master
Kenneth Bruen 3 years ago
commit
e2a0f56261
Signed by: kbruen
GPG Key ID: C1980A470C3EE5B1
  1. 2
      .gitignore
  2. 33
      .vscode/launch.json
  3. 5
      .vscode/settings.json
  4. 27
      .vscode/tasks.json
  5. 20
      Makefile
  6. 6
      src/drawable.h
  7. 201
      src/main.cpp
  8. 63
      src/pixel_wise.cpp
  9. 89
      src/pixel_wise.h
  10. 16
      src/utils.hpp

2
.gitignore vendored

@ -0,0 +1,2 @@
program
obj/**

33
.vscode/launch.json vendored

@ -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"
}
]
}

5
.vscode/settings.json vendored

@ -0,0 +1,5 @@
{
"files.associations": {
"array": "cpp"
}
}

27
.vscode/tasks.json vendored

@ -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"
}
]
}

20
Makefile

@ -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 $@

6
src/drawable.h

@ -0,0 +1,6 @@
#pragma once
class Drawable {
public:
virtual void draw() = 0;
};

201
src/main.cpp

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

63
src/pixel_wise.cpp

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

89
src/pixel_wise.h

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

16
src/utils.hpp

@ -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…
Cancel
Save