#include <iostream>
#include <cmath>
// GLEW
#define GLEW_STATIC
#include <GL/glew.h>
// GLFW
#include <GLFW/glfw3.h>
// Window dimensions
const GLuint WIDTH = 800, HEIGHT = 600;
// Bird position and speed
float birdX = 0.0f;
float birdY = 0.0f;
float birdSpeed = 1.0f; // Use deltaTime for actual speed
float wingFlapTimer = 0.0f;
float wingFlapSpeed = 5.0f;
bool isMoving = false;
static void Initialize(void);
void processInput(GLFWwindow* window, float deltaTime)
{
float speed = birdSpeed * deltaTime;
isMoving = false;
if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
glfwSetWindowShouldClose(window, true);
if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS && birdY + 0.3f < 1.0f) {
birdY += speed;
isMoving = true;
}
if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS && birdY - 0.2f > -1.0f) {
birdY -= speed;
isMoving = true;
}
if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS && birdX - 0.4f > -1.0f) {
birdX -= speed;
isMoving = true;
}
if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS && birdX + 0.3f < 1.0f) {
birdX += speed;
isMoving = true;
}
}
void RenderBird()
{
int numSegments = 100;
// Head
float headX = birdX + 0.1f, headY = birdY + 0.05f;
float headRadius = 0.1f;
glColor3f(0.0f, 0.0f, 0.0f); // Black
glBegin(GL_TRIANGLE_FAN);
glVertex2f(headX, headY);
for (int i = 0; i <= numSegments; i++) {
float angle = 2.0f * 3.14159f * i / numSegments;
float x = headRadius * cos(angle);
float y = headRadius * sin(angle);
glVertex2f(headX + x, headY + y);
}
glEnd();
// Eye
float eyeX = birdX + 0.14f, eyeY = birdY + 0.05f;
float eyeRadius = 0.02f;
glColor3f(1.0f, 1.0f, 1.0f); // White
glBegin(GL_TRIANGLE_FAN);
glVertex2f(eyeX, eyeY);
for (int i = 0; i <= numSegments; i++) {
float angle = 2.0f * 3.14159f * i / numSegments;
float x = eyeRadius * cos(angle);
float y = eyeRadius * sin(angle);
glVertex2f(eyeX + x, eyeY + y);
}
glEnd();
// Body
glColor3f(0.0f, 0.0f, 0.0f);
glBegin(GL_TRIANGLES);
glVertex2f(birdX - 0.2f, birdY - 0.2f); // bottom left
glVertex2f(birdX + 0.1f, birdY - 0.05f); // bottom right
glVertex2f(birdX, birdY + 0.08f); // top
glEnd();
// Wing (flaps up/down)
glBegin(GL_TRIANGLES);
if (isMoving)
{
wingFlapTimer += 0.05f * wingFlapSpeed;
if (wingFlapTimer > 2.0f * 3.14159f)
wingFlapTimer -= 2.0f * 3.14159f;
float t = (sin(wingFlapTimer) + 1.0f) / 2.0f; // cycles from 0 to 1
// Position 1: original wing flap
float x1[3] = { birdX - 0.15f, birdX + 0.01f, birdX - 0.05f };
float y1[3] = { birdY + 0.25f, birdY + 0.08f, birdY - 0.1f };
// Position 2: wing down
float x2[3] = { birdX - 0.15f, birdX + 0.01f, birdX - 0.05f };
float y2[3] = { birdY - 0.25f, birdY - 0.08f, birdY - 0.1f };
for (int i = 0; i < 3; ++i)
{
float x = x1[i] * (1 - t) + x2[i] * t;
float y = y1[i] * (1 - t) + y2[i] * t;
glVertex2f(x, y);
}
}
else
{
// Not moving: wing stays fixed in the original position (up)
glVertex2f(birdX - 0.15f, birdY + 0.25f);
glVertex2f(birdX + 0.01f, birdY + 0.08f);
glVertex2f(birdX - 0.05f, birdY - 0.1f);
}
glEnd();
// Beak
glBegin(GL_TRIANGLES);
glVertex2f(birdX + 0.18f, birdY + 0.06f);
glVertex2f(birdX + 0.3f, birdY + 0.05f);
glVertex2f(birdX + 0.18f, birdY + 0.02f);
glEnd();
// Belly
glBegin(GL_TRIANGLE_FAN);
glVertex2f(birdX - 0.02f, birdY - 0.08f); // Center of fan
float angleOffset = -145.0f * 3.14159f / 180.0f; // rotation offset
for (int i = 0; i <= 10; ++i)
{
float angle = angleOffset + (3.14159f * i / 10);
float x = 0.15f * cos(angle); // stretch X
float y = 0.1f * sin(angle); // keep Y size
glVertex2f(birdX - 0.02f + x, birdY - 0.08f + y);
}
glEnd();
}
int main()
{
// Initialize GLFW
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1);
glfwWindowHint(GLFW_OPENGL_ANY_PROFILE, GLFW_OPENGL_ANY_PROFILE);
GLFWwindow* window = glfwCreateWindow(WIDTH, HEIGHT, "Bird Movement", nullptr, nullptr);
glfwMakeContextCurrent(window);
// Set up orthographic projection
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-1, 1, -1, 1, -1, 1); // Coordinate system from -1 to 1
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
float lastFrame = glfwGetTime();
// Game loop
while (!glfwWindowShouldClose(window))
{
float currentFrame = glfwGetTime();
float deltaTime = currentFrame - lastFrame;
lastFrame = currentFrame;
processInput(window, deltaTime);
Initialize();
RenderBird();
glfwSwapBuffers(window);
glfwPollEvents();
}
glfwTerminate();
return EXIT_SUCCESS;
}
static void Initialize(void)
{
glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
}