diff --git a/main.cpp b/main.cpp index 7e2601a..2d7b31e 100644 --- a/main.cpp +++ b/main.cpp @@ -1,5 +1,8 @@ // #define SDL_MAIN_USE_CALLBACKS 1 /* use the callbacks instead of main() */ #include +#include +#include +#include #include #include #include @@ -12,11 +15,17 @@ #define SDL_WINDOW_FLAG 0 #endif -#define SCREEN_WIDTH 1600 -#define SCREEN_HEIGHT 720 +#define SCREEN_WIDTH 1600.f +#define SCREEN_HEIGHT 720.f -#define BOX_WIDTH 100 -#define BOX_HEIGHT 100 +#define BALL_SIZE 50.f + +#define PLATE_WIDTH 50.f +#define PLATE_HEIGHT 150.f + +#define max(a, b) ((a) > (b) ? (a) : (b)) +#define min(a, b) ((a) < (b) ? (a) : (b)) +#define clamp(x, minV, maxV) max((minV), min((maxV), (x))) static SDL_Window *window = NULL; @@ -25,24 +34,32 @@ static bool running = true; static Uint8 color = 0x18; static Uint64 elapsed = 0; -static float boxVelX = 0.5f; -static float boxVelY = 0.5f; -static float boxSpeed = 300.f; +static float ballVelX = -0.5f; +static float ballVelY = 0.5f; +static float ballSpeed = 600.f; +static float ballAccel = 25.f; + +static float opponentSpeed = 450.f; +static float opponentVelY = 0.f; const char* vShader = "#version 300 es\n" "layout (location = 0) in vec2 aPos;\n" +"uniform vec4 uColor;\n" +"out vec4 color;\n" "void main()\n" "{\n" " gl_Position = vec4(aPos, 0.0, 1.0);\n" +" color = uColor;\n" "}"; const char* fShader = "#version 300 es\n" "precision mediump float;\n" "out vec4 fragColor;\n" +"in vec4 color;\n" "void main()\n" "{\n" -" fragColor = vec4(0.8, 0.8, 0.8, 1.0);\n" +" fragColor = color;\n" "}"; void computeLetterbox(int windowW, int windowH, @@ -62,12 +79,101 @@ void computeLetterbox(int windowW, int windowH, } struct Rect { +public: float x; float y; float w; float h; +private: + float vertices[12]; + GLuint vao, vbo; +public: + Rect(float x, float y, float w, float h) { + this->x = x; + this->y = y; + this->w = w; + this->h = h; + } + + void Init() { + glGenVertexArrays(1, &vao); + glGenBuffers(1, &vbo); + + glBindVertexArray(vao); + glBindBuffer(GL_ARRAY_BUFFER, vbo); + glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_DYNAMIC_DRAW); + + glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), (void *)0); + glEnableVertexAttribArray(0); + + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindVertexArray(0); + } + + void Draw() { + float xProj = (x / SCREEN_WIDTH) * 2.0f - 1.0f; + float yProj = 1.0f - (y / SCREEN_HEIGHT) * 2.0f; + + float wProj = (w / SCREEN_WIDTH) * 2.0f; + float hProj = (h / SCREEN_HEIGHT) * 2.0f; + + vertices[0] = xProj; + vertices[1] = yProj; + vertices[2] = xProj + wProj; + vertices[3] = yProj; + vertices[4] = xProj + wProj; + vertices[5] = yProj - hProj; + + vertices[6] = xProj; + vertices[7] = yProj; + vertices[8] = xProj; + vertices[9] = yProj - hProj; + vertices[10] = xProj + wProj; + vertices[11] = yProj - hProj; + + glBindVertexArray(vao); + glBindBuffer(GL_ARRAY_BUFFER, vbo); + glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_DYNAMIC_DRAW); + + glBindVertexArray(vao); + + glDrawArrays(GL_TRIANGLES, 0, 6); + + glBindVertexArray(0); + glBindBuffer(GL_ARRAY_BUFFER, 0); + } + + bool CollidesWith(const Rect& b) { + return (x < b.x + b.w && + x + w > b.x && + y < b.y + b.h && + y + h > b.y); + } }; +static Rect ball( + SCREEN_WIDTH / 2 - BALL_SIZE / 2, + SCREEN_HEIGHT / 2 - BALL_SIZE / 2, + BALL_SIZE, + BALL_SIZE +); + +static Rect player( + 50.f, + SCREEN_HEIGHT / 2 - PLATE_HEIGHT / 2, + PLATE_WIDTH, + PLATE_HEIGHT +); + +static Rect opponent( + SCREEN_WIDTH - PLATE_WIDTH - 50.f, + SCREEN_HEIGHT / 2 - PLATE_HEIGHT / 2, + PLATE_WIDTH, + PLATE_HEIGHT +); + +bool paused = true; + extern "C" int APP_MAIN(int argc, char **argv) { SDL_SetAppMetadata("Example Renderer Primitives", "1.0", "com.example.renderer-primitives"); SDL_SetHint(SDL_HINT_ORIENTATIONS, "LandscapeLeft LandscapeRight"); @@ -129,28 +235,9 @@ extern "C" int APP_MAIN(int argc, char **argv) { glDeleteShader(vertexShader); glDeleteShader(fragmentShader); - float vertices[12] = {0}; - - Rect rect = { - .x = 50.f, - .y = 50.f, - .w = BOX_WIDTH, - .h = BOX_HEIGHT, - }; - - GLuint vao, vbo; - glGenVertexArrays(1, &vao); - glGenBuffers(1, &vbo); - - glBindVertexArray(vao); - glBindBuffer(GL_ARRAY_BUFFER, vbo); - glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_DYNAMIC_DRAW); - - glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), (void *)0); - glEnableVertexAttribArray(0); - - glBindBuffer(GL_ARRAY_BUFFER, 0); - glBindVertexArray(0); + ball.Init(); + player.Init(); + opponent.Init(); int drawableW, drawableH; SDL_GetWindowSizeInPixels(window, &drawableW, &drawableH); @@ -173,57 +260,77 @@ extern "C" int APP_MAIN(int argc, char **argv) { if (event.type == SDL_EVENT_QUIT) { running = false; } + if (!paused) { + if (event.type == SDL_EVENT_MOUSE_MOTION) { + player.y = clamp(event.motion.y - PLATE_HEIGHT / 2, 0, SCREEN_HEIGHT - PLATE_HEIGHT); + } else if (event.type == SDL_EVENT_FINGER_MOTION) { + player.y = clamp(event.motion.y - PLATE_HEIGHT / 2, 0, SCREEN_HEIGHT - PLATE_HEIGHT); + } + } + if (paused && event.type == SDL_EVENT_KEY_DOWN && event.key.key == SDLK_SPACE) { + paused = false; + } else if (paused && event.type == SDL_EVENT_FINGER_UP) { + paused = false; + } } auto now = SDL_GetTicks(); float dt = now - elapsed; elapsed = now; - // SDL_Log("dt: %f\n", dt); dt /= 1000.f; - rect.x += boxSpeed * boxVelX * dt; - rect.y += boxSpeed * boxVelY * dt; - // boxSpeed += 50.f * dt; + if (!paused) { + ball.x += ballSpeed * ballVelX * dt; + ball.y += ballSpeed * ballVelY * dt; + ballSpeed += ballAccel * dt; - if (rect.x + BOX_WIDTH >= SCREEN_WIDTH || rect.x <= 0) boxVelX *= -1.f; - if (rect.y + BOX_HEIGHT >= SCREEN_HEIGHT || rect.y <= 0) boxVelY *= -1.f; + if (ball.x + BALL_SIZE >= SCREEN_WIDTH || ball.x <= 0) ballVelX *= -1.f; - // float xProj = -1 + rect.x / ((float)SCREEN_WIDTH / 2); - // float yProj = rect.y / ((float)SCREEN_HEIGHT / 2); + if (ball.x <= 0) { + ball.x = 1.f; + paused = true; + } + if (ball.x + BALL_SIZE >= SCREEN_WIDTH) { + ball.x = SCREEN_WIDTH - BALL_SIZE - 1.f; + paused = true; + } - float xProj = (rect.x / SCREEN_WIDTH) * 2.0f - 1.0f; - float yProj = 1.0f - (rect.y / SCREEN_HEIGHT) * 2.0f; + if (ball.y + BALL_SIZE >= SCREEN_HEIGHT || ball.y <= 0) ballVelY *= -1.f; + if (ball.y + BALL_SIZE >= SCREEN_HEIGHT) ball.y = SCREEN_HEIGHT - BALL_SIZE - 1.f; + if (ball.y <= 0) ball.y = 1.f; - float wProj = (rect.w / SCREEN_WIDTH) * 2.0f; - float hProj = (rect.h / SCREEN_HEIGHT) * 2.0f; - SDL_Log("%f::%f (%f:%f)\n", xProj, yProj, wProj, hProj); + if (ball.CollidesWith(player)) { + ball.x = player.x + PLATE_WIDTH + 1.f; + ballVelX *= -1; + } + if (ball.CollidesWith(opponent)) { + ball.x = opponent.x - BALL_SIZE - 1.f; + ballVelX *= -1; + } - vertices[0] = xProj; - vertices[1] = yProj; - vertices[2] = xProj + wProj; - vertices[3] = yProj; - vertices[4] = xProj + wProj; - vertices[5] = yProj - hProj; - - vertices[6] = xProj; - vertices[7] = yProj; - vertices[8] = xProj; - vertices[9] = yProj - hProj; - vertices[10] = xProj + wProj; - vertices[11] = yProj - hProj; + opponentVelY = clamp(ball.y - (opponent.y + PLATE_HEIGHT / 2 - BALL_SIZE / 2), -1.f, 1.f); + opponent.y = clamp(opponent.y + opponentSpeed * opponentVelY * dt, 0, SCREEN_HEIGHT - PLATE_HEIGHT); + } glClearColor(0x18/255.f, 0x18/255.f, 0x18/255.f, 1.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Draw your 3D stuff here - glBindVertexArray(vao); - glBindBuffer(GL_ARRAY_BUFFER, vbo); - glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_DYNAMIC_DRAW); glUseProgram(program); - glBindVertexArray(vao); + auto colorLoc = glGetUniformLocation(program, "uColor"); + float color[4] = {0.8f, 0.8f, 0.8f, 1.0f}; - glDrawArrays(GL_TRIANGLES, 0, 6); + glUniform4fv(colorLoc, 1, color); + ball.Draw(); + player.Draw(); + + color[0] = 0.8f; + color[1] = 0.2f; + color[2] = 0.25f; + color[3] = 1.0f; + glUniform4fv(colorLoc, 1, color); + opponent.Draw(); SDL_GL_SwapWindow(window); }