The output for this code
#pragma once
// GLEW
#define GLEW_STATIC
#include <GL/glew.h>
// GLFW
#include <GLFW/glfw3.h>
class Collider
{
public:
float minX, minY, maxX, maxY;
float targetX, targetY;
void targetPosition(float targetx, float targety)
{
targetX = targetx; targetY = targety;
}
bool checkCollider(float minx, float miny, float maxx, float maxy)
{
minX = minx; minY = miny; maxX = maxx; maxY = maxy;
if (targetX > minX && targetY > minY && targetX < maxX && targetY < maxY)
{
return true;
}
return false;
}
};
#include <iostream>
#include <cmath>
#include "Bar.h"
#include "Collider.h"
// GLEW
#define GLEW_STATIC
#include <GL/glew.h>
// GLFW
#include <GLFW/glfw3.h>
using namespace std;
// Window dimensions
const GLuint WIDTH = 800, HEIGHT = 600;
// Bird position and speed
float birdX = -0.7f;
float birdY = -0.65f;
float birdSpeed = 1.0f; // Use deltaTime for actual speed
float wingFlapTimer = 0.0f;
float wingFlapSpeed = 5.0f;
bool isMoving = false;
static int delta;
float barValue[3] = {0,0,0};
static void Initialize(void);
void barDrawing();
int timerForbar, countDownTimer=3;
void reduceBarFunction();
void DrawCircle(float cx, float cy, float radius, float r, float g, float b);
void RenderTree(float x, float y, float scale);
void drawGrid();
int barTimer[3] = { 0,0,0 };
void drawHalfCircle(float cx, float cy, float radius, int numSegments);
void showIcon();
void RenderHappiness(float x, float y);
void RenderFood(float x, float y, float size);
void ShowerIcon(float baseX, float baseY);
Collider ChangeCloth, eating;
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();
}
void LoadingBar()
{
glPointSize(5);
glBegin(GL_POINTS);
delta = glfwGetTime();
for (int i = delta; i < 18; i++)
{
float k = -0.8 + i / 10.0;
glVertex2f(k,-0.6f);
birdX = delta*0.1-1.2;
}
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();
showIcon();
RenderTree(0.0f, 0.0f, 2.0f);
ChangeCloth.targetPosition(birdX, birdY);
//cout<< ChangeCloth.checkCollider(-0.5f,-0.3f,0.6,0.9);
if (ChangeCloth.checkCollider(-0.5f, -0.3f, 0.6, 0.9))
{
if (barValue[2] <= 0)
barValue[2] += 0.0001;
}
eating.targetPosition(birdX, birdY);
// eating.checkCollider(-0.1,-0.8,0.1,0);
if (eating.checkCollider(-0.1, -0.8, 0.1, 0))
{
if (barValue[0] <= 0)
barValue[0] += 0.0001;
}
RenderBird();
//drawGrid();
// LoadingBar();
reduceBarFunction();
barDrawing();
glfwSwapBuffers(window);
glfwPollEvents();
}
glfwTerminate();
return EXIT_SUCCESS;
}
void barDrawing()
{
//bacground
Color barBCGColor = {1,0.0f,0};
BarStatus hungerBarBackground(-0.8f,0.8f,0.5f,0.1f, barBCGColor);
hungerBarBackground.drawing();
BarStatus hygieneBarBackground(-0.8f, 0.65f, 0.5f, 0.1f, barBCGColor);
hygieneBarBackground.drawing();
BarStatus happinessBarBackground(-0.8f, 0.5f, 0.5f, 0.1f, barBCGColor);
happinessBarBackground.drawing();
BarStatus hungerBar(-0.8f , 0.8f , 0.5f + barValue[0], 0.1f, { 0,1.0f,0 });
hungerBar.drawing();
BarStatus hygieneBar(-0.8f , 0.65f, 0.5f + barValue[1], 0.1f, { 0,0.0f,1 });
hygieneBar.drawing();
BarStatus happinessBar(-0.8f , 0.5f , 0.5f + barValue[2], 0.1f, { 1,1.0f,0 });
happinessBar.drawing();
}
void reduceBarFunction()
{
timerForbar = glfwGetTime();
//cout << "time for bar " << timerForbar << endl;
if (timerForbar - barTimer[0] >= 5)
{
barTimer[0] = timerForbar;
barValue[0] = std::max(barValue[0] - 0.1, -0.5); //ensures the result won't go below -0.5
}
if (timerForbar - barTimer[1] >= 3)
{
barTimer[1] = timerForbar;
barValue[1] = std::max(barValue[1] - 0.1, -0.5);
}
if (timerForbar - barTimer[2] >= 2)
{
barTimer[2] = timerForbar;
barValue[2] = std::max(barValue[2] - 0.1, -0.5);
}
}
static void Initialize(void)
{
glClearColor(0.5f, 0.5f, 0.5f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
}
void DrawCircle(float cx, float cy, float radius, float r, float g, float b)
{
glColor3f(r, g, b);
glBegin(GL_TRIANGLE_FAN);
glVertex2f(cx, cy);
int numSegments = 50;
for (int i = 0; i <= numSegments; i++) {
float angle = 2.0f * 3.14159f * i / numSegments;
float x = radius * cosf(angle);
float y = radius * sinf(angle);
glVertex2f(cx + x, cy + y);
}
glEnd();
}
void RenderTree(float x, float y, float scale)
{
// === Leaves (3 circles) ===
float r = 0.2f * scale;
float leafY = y + 0.05f * scale;
// Left circle (darker green)
DrawCircle(x - 0.07f * scale, leafY, r, 0.45f, 0.65f, 0.32f);
// Center circle (lighter green)
DrawCircle(x, leafY + 0.3f, r, 0.55f, 0.80f, 0.40f);
// Right circle (lighter green)
DrawCircle(x + 0.07f * scale, leafY, r, 0.55f, 0.80f, 0.40f);
// === Trunk ===
glColor3f(0.60f, 0.40f, 0.26f); // Brown
float trunkWidth = 0.05f * scale;
float trunkHeight = 0.4f * scale;
glBegin(GL_QUADS);
glVertex2f(x - trunkWidth / 2, y - trunkHeight);
glVertex2f(x + trunkWidth / 2, y - trunkHeight);
glVertex2f(x + trunkWidth / 2, y);
glVertex2f(x - trunkWidth / 2, y);
glEnd();
// === RightBranch (slanted rectangle coming from the middle of trunk) ===
glColor3f(0.60f, 0.40f, 0.26f);
float branchStartX = x - 0.01f;
float branchStartY = y - trunkHeight * 0.3f;
float branchLength = 0.08f * scale;
float branchHeight = 0.15f * scale;
float yOffset = -0.3f;
glBegin(GL_QUADS);
glVertex2f(branchStartX, branchStartY + yOffset);
glVertex2f(branchStartX + branchLength, branchStartY + branchHeight + yOffset);
glVertex2f(branchStartX + branchLength + 0.03f * scale, branchStartY + branchHeight + yOffset);
glVertex2f(branchStartX + 0.03f * scale, branchStartY + yOffset);
glEnd();
// === LeftBranch (flipped horizontally to point left) ===
glColor3f(0.60f, 0.40f, 0.26f);
float branchStartA = x + 0.01f; // start on right side of trunk
float branchStartB = y - trunkHeight * 0.3f;
float branchLength2 = 0.05f * scale;
float branchHeight2 = 0.1f * scale;
float yOffset2 = -0.1f;
glBegin(GL_QUADS);
glVertex2f(branchStartA, branchStartB + yOffset2);
glVertex2f(branchStartA - branchLength2, branchStartB + branchHeight2 + yOffset2);
glVertex2f(branchStartA - branchLength2 - 0.03f * scale, branchStartB + branchHeight2 + yOffset2);
glVertex2f(branchStartA - 0.03f * scale, branchStartB + yOffset2);
glEnd();
}
void drawGrid()
{
glColor3f(1,1,1);
glPointSize(3);
glBegin(GL_POINTS);
for (float i = -1; i < 1; i+=0.1)
{
for (float j = -1; j < 1; j += 0.1)
{
glVertex2f(i, j);
}
}
glEnd();
}
void ShowerIcon(float baseX, float baseY)
{
glColor3f(1.0f, 1.0f, 1.0f); // 白色喷头
glBegin(GL_QUADS);
glVertex2f(baseX, baseY);
glVertex2f(baseX + 0.05f, baseY - 0.1f);
glVertex2f(baseX + 0.08f, baseY - 0.03f);
glVertex2f(baseX + 0.05f, baseY + 0.02f);
glEnd();
glBegin(GL_LINES);
glVertex2d(baseX, baseY - 0.02);
glVertex2f(baseX - 0.05, baseY - 0.05);
glVertex2d(baseX + 0.01, baseY - 0.04);
glVertex2f(baseX - 0.04, baseY - 0.07);
glVertex2d(baseX + 0.02, baseY - 0.06);
glVertex2f(baseX - 0.03, baseY - 0.09);
glEnd();
}
void RenderFood(float x, float y, float size)
{
glColor3f(1.0f, 0.5f, 0.2f); // 虫头颜色
drawHalfCircle(x, y + size * 0.1f, size * 0.3f, 20);
DrawCircle(x, y - size * 0.2f, size * 0.4f, 1.0f, 0.7f, 0.4f);
glColor3f(0.7f, 0.4f, 0.1f); // 腿颜色
glBegin(GL_LINES);
float legLenShort = size * 0.2f; // 前腿
float legLenMid = size * 0.2f; // 中腿
float legLenLong = size * 0.2f; // 后腿
// 左边前腿
glVertex2f(x - size * 0.4f, y - size * 0.05f);
glVertex2f(x - size * 0.4f - legLenShort, y + size * 0.05f);
// 左边中腿
glVertex2f(x - size * 0.4f, y - size * 0.15f);
glVertex2f(x - size * 0.4f - legLenMid, y - size * 0.15f);
// 左边后腿
glVertex2f(x - size * 0.4f, y - size * 0.25f);
glVertex2f(x - size * 0.4f - legLenLong, y - size * 0.35f);
// 右边前腿
glVertex2f(x + size * 0.4f, y - size * 0.05f);
glVertex2f(x + size * 0.4f + legLenShort, y + size * 0.05f);
// 右边中腿
glVertex2f(x + size * 0.4f, y - size * 0.15f);
glVertex2f(x + size * 0.4f + legLenMid, y - size * 0.15f);
// 右边后腿
glVertex2f(x + size * 0.4f, y - size * 0.25f);
glVertex2f(x + size * 0.4f + legLenLong, y - size * 0.35f);
glEnd();
}
void RenderHappiness(float x, float y)
{
float scale = 0.6f;
float faceRadius = 0.1f * scale;
DrawCircle(x, y, faceRadius, 1.0f, 1.0f, 0.0f);
float eyeWidth = 0.015f * scale;
float eyeHeight = 0.05f * scale;
float eyeOffsetX = 0.035f * scale;
float eyeOffsetY = 0.035f * scale;
glColor3f(0.0f, 0.0f, 0.0f);
// Left eye
glBegin(GL_QUADS);
glVertex2f(x - eyeOffsetX - eyeWidth / 2, y + eyeOffsetY - eyeHeight / 2);
glVertex2f(x - eyeOffsetX + eyeWidth / 2, y + eyeOffsetY - eyeHeight / 2);
glVertex2f(x - eyeOffsetX + eyeWidth / 2, y + eyeOffsetY + eyeHeight / 2);
glVertex2f(x - eyeOffsetX - eyeWidth / 2, y + eyeOffsetY + eyeHeight / 2);
glEnd();
// Right eye
glBegin(GL_QUADS);
glVertex2f(x + eyeOffsetX - eyeWidth / 2, y + eyeOffsetY - eyeHeight / 2);
glVertex2f(x + eyeOffsetX + eyeWidth / 2, y + eyeOffsetY - eyeHeight / 2);
glVertex2f(x + eyeOffsetX + eyeWidth / 2, y + eyeOffsetY + eyeHeight / 2);
glVertex2f(x + eyeOffsetX - eyeWidth / 2, y + eyeOffsetY + eyeHeight / 2);
glEnd();
glColor3f(0.0f, 0.0f, 0.0f);
float smileCenterX = x;
float smileCenterY = y - (0.025f * scale);
float smileRadiusX = 0.05f * scale;
float smileRadiusY = 0.025f * scale;
glBegin(GL_TRIANGLE_FAN);
glVertex2f(smileCenterX, smileCenterY);
for (int i = 0; i <= 50; ++i)
{
float angle = 3.14159f + (3.14159f * i / 50);
float sx = smileRadiusX * cos(angle);
float sy = smileRadiusY * sin(angle);
glVertex2f(smileCenterX + sx, smileCenterY + sy);
}
glEnd();
}
void showIcon()
{
RenderFood(-0.9f, 0.85f, 0.1f);
ShowerIcon(-0.9f, 0.75f);
RenderHappiness(-0.9f, 0.55f);
}
void drawHalfCircle(float cx, float cy, float radius, int numSegments)
{
glBegin(GL_TRIANGLE_FAN);
glVertex2f(cx, cy); // 半圆中心
for (int i = 0; i <= numSegments; i++) {
// 画上半圆(从 0 到 pi)
float angle = 3.14159f * i / numSegments;
float x = radius * cosf(angle);
float y = radius * sinf(angle);
glVertex2f(cx + x, cy + y);
}
glEnd();
}