readme
This commit is contained in:
+923
@@ -0,0 +1,923 @@
|
||||
#include "Engine.h"
|
||||
|
||||
// ============================================================================
|
||||
// Standard library
|
||||
// ============================================================================
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <random>
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include <type_traits>
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
|
||||
// ============================================================================
|
||||
// OpenGL
|
||||
// ============================================================================
|
||||
#include <glad/glad.h>
|
||||
#include <GLFW/glfw3.h>
|
||||
|
||||
// ============================================================================
|
||||
// Math
|
||||
// ============================================================================
|
||||
#include <glm/glm.hpp>
|
||||
#include <glm/gtc/matrix_transform.hpp>
|
||||
#include <glm/gtc/type_ptr.hpp>
|
||||
#include <glm/gtc/quaternion.hpp>
|
||||
|
||||
// ============================================================================
|
||||
// Third party
|
||||
// ============================================================================
|
||||
#include <ft2build.h>
|
||||
#include FT_FREETYPE_H
|
||||
|
||||
// ============================================================================
|
||||
// Engine core
|
||||
// ============================================================================
|
||||
#include "common.h"
|
||||
#include "Window.h"
|
||||
#include "Camera.h"
|
||||
#include "Keyboard.h"
|
||||
#include "Mouse.h"
|
||||
#include "Physics.h"
|
||||
#include "RenderSystem.h"
|
||||
#include "SoundSystem.h"
|
||||
#include "ResourceManager.h"
|
||||
#include "tFunctions.h"
|
||||
#include "Debug.h"
|
||||
|
||||
// Rendering
|
||||
#include "shaderClass.h"
|
||||
#include "VBO.h"
|
||||
#include "VAO.h"
|
||||
#include "EBO.h"
|
||||
#include "FBO.h"
|
||||
#include "texture.h"
|
||||
#include "Material.h"
|
||||
#include "Mesh.h"
|
||||
#include "Model.h"
|
||||
#include "Cubemap.h"
|
||||
#include "QuadVertices.h"
|
||||
#include "Particle.h"
|
||||
#include "Lighting.h"
|
||||
#include "DirLight.h"
|
||||
|
||||
// Scene
|
||||
#include "Folder.h"
|
||||
#include "Sound.h"
|
||||
#include "Gui.h"
|
||||
#include "font.h"
|
||||
|
||||
// Character / animation
|
||||
#include "Rig.h"
|
||||
#include "Animator.h"
|
||||
#include "Character.h"
|
||||
#include "CharacterManager.h"
|
||||
#include "DefaultBodyComponents.h"
|
||||
#include "BodyComponentActions.h"
|
||||
|
||||
#define STB_IMAGE_IMPLEMENTATION
|
||||
#include "stb_image.h"
|
||||
|
||||
// ============================================================================
|
||||
// Constructor - window, callbacks, systems, shaders
|
||||
// ============================================================================
|
||||
Engine::Engine()
|
||||
{
|
||||
engine = this;
|
||||
|
||||
glfwSetFramebufferSizeCallback(window->handle, framebuffer_size_callback);
|
||||
glfwSetCursorPosCallback(window->handle, mouse_callback);
|
||||
glfwSetScrollCallback(window->handle, scroll_callback);
|
||||
glfwSetKeyCallback(window->handle, key_callback);
|
||||
glfwSetMouseButtonCallback(window->handle, mouse_button_callback);
|
||||
glfwSwapInterval(1);
|
||||
|
||||
int fbw, fbh;
|
||||
glfwGetFramebufferSize(window->handle, &fbw, &fbh);
|
||||
framebuffer_size_callback(window->handle, fbw, fbh);
|
||||
|
||||
rendersystem = new RenderSystem();
|
||||
rendersystem->Initialize();
|
||||
physicsengine = new Physics();
|
||||
physicsengine->SetGravity(physicsengine->GetGravity() * 1.25f);
|
||||
mainf = new Folder();
|
||||
camera = new Camera();
|
||||
camera->t.TranslateTo({ 0.0f, 5.0f, 0.0f });
|
||||
|
||||
rendersystem->RigShader = new Shader("shaders/rig.vert", "shaders/default.frag");
|
||||
rendersystem->MeshShader = new Shader("shaders/default.vert", "shaders/default.frag");
|
||||
rendersystem->MeshShadowShader = new Shader("shaders/meshshadow.vert", "shaders/shadow.frag");
|
||||
rendersystem->RigShadowShader = new Shader("shaders/rigshadow.vert", "shaders/shadow.frag");
|
||||
rendersystem->SkyboxShader = new Shader("shaders/skybox.vert", "shaders/skybox.frag");
|
||||
rendersystem->ScreenShader = new Shader("shaders/ScreenShader.vert", "shaders/ScreenShader.frag");
|
||||
rendersystem->ImageBoxShader = new Shader("shaders/ImageBox.vert", "shaders/ImageBox.frag");
|
||||
rendersystem->BoxShader = new Shader("shaders/Box.vert", "shaders/Box.frag");
|
||||
rendersystem->Text2DShader = new Shader("shaders/2DText.vert", "shaders/2DText.frag");
|
||||
rendersystem->ParticleShader = new Shader("shaders/Particle.vert", "shaders/Particle.frag");
|
||||
rendersystem->HitboxShader = new Shader("shaders/Hitbox.vert", "shaders/Hitbox.frag");
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Initiate - scene setup + game loop
|
||||
// ============================================================================
|
||||
void Engine::Initiate()
|
||||
{
|
||||
Font* arial = new Font("assets/ft/arial.ttf");
|
||||
Texture* blanktex = new Texture("assets/blanktexture.png");
|
||||
Texture* snowflake = new Texture("assets/snowflake.png");
|
||||
|
||||
charactermanager = new CharacterManager();
|
||||
charactermanager->LoadRig("humanoid", "assets/rig.glb");
|
||||
charactermanager->LoadAnimation("walk", "assets/walkanim.glb", "humanoid");
|
||||
charactermanager->LoadAnimation("punch", "assets/punchanim.glb", "humanoid");
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// Player character
|
||||
// ------------------------------------------------------------------------
|
||||
Character& testcharacter = *charactermanager->CreateCharacter("character", "humanoid", "walk");
|
||||
charactermanager->SetControlledCharacter("character");
|
||||
testcharacter.castshadow = true;
|
||||
testcharacter.colorOverride = glm::vec4(0.62f, 0.64f, 0.68f, 1.0f);
|
||||
testcharacter.roughness = 0.65f;
|
||||
testcharacter.body->t.ScaleBy({ 0.7f, 2.5f, 0.7f });
|
||||
testcharacter.body->t.TranslateTo({ 0.0f, 1.5f, 0.0f });
|
||||
testcharacter.body->animator->loops = true;
|
||||
testcharacter.SetPunchAnimation(charactermanager->GetAnimation("punch"));
|
||||
testcharacter.BindToRenderSystem();
|
||||
|
||||
p* characterBody = new p(testcharacter.body);
|
||||
characterBody->mass = 80.0f;
|
||||
characterBody->lockRotation = true;
|
||||
characterBody->friction = 0.0f;
|
||||
physicsengine->AddObject(characterBody);
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// NPC
|
||||
// ------------------------------------------------------------------------
|
||||
Character& npc = *charactermanager->CreateCharacter("npc", "humanoid", "walk");
|
||||
npc.castshadow = true;
|
||||
npc.colorOverride = glm::vec4(0.10f, 0.20f, 0.48f, 1.0f);
|
||||
npc.metallic = 0.1f;
|
||||
npc.roughness = 0.5f;
|
||||
npc.body->t.ScaleBy({ 0.7f, 2.5f, 0.7f });
|
||||
npc.body->t.TranslateTo({ 3.0f, 1.25f, 3.0f });
|
||||
npc.SetPunchAnimation(charactermanager->GetAnimation("punch"));
|
||||
npc.SetPunchLooping(true);
|
||||
npc.Punch();
|
||||
npc.BindToRenderSystem();
|
||||
|
||||
p* npcBody = new p(npc.body);
|
||||
npcBody->mass = 80.0f;
|
||||
npcBody->lockRotation = true;
|
||||
npcBody->friction = 0.0f;
|
||||
physicsengine->AddObject(npcBody);
|
||||
|
||||
testcharacter.SetWalking(false);
|
||||
npc.SetWalking(false);
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// Rain particles
|
||||
// ------------------------------------------------------------------------
|
||||
ParticleEmitter* rain = new ParticleEmitter();
|
||||
rain->name = "rain";
|
||||
rain->tex = snowflake;
|
||||
rain->opaque = false;
|
||||
rain->speed = 35.0f;
|
||||
rain->lifespan = 0.6f;
|
||||
rain->angularvelocity = { 0.0f, 0.0f, glm::radians(10.0f) };
|
||||
rain->size = { 0.04f, 0.4f, 0.0f };
|
||||
rain->emitangle = { glm::radians(60.0f), glm::radians(360.0f), glm::radians(60.0f) };
|
||||
rain->facecamera = false;
|
||||
rain->color = { 1.0f, 1.0f, 1.0f, 1.0f };
|
||||
rain->emitdirection = ParticleEmitter::EmitDirection::Perpendicular;
|
||||
rain->t.TranslateTo({ 0.0f, 10.0f, 0.0f });
|
||||
rain->t.RotateToQuaternion(glm::quat(glm::vec3(glm::radians(85.0f), 0.0f, 0.0f)));
|
||||
rain->BindToRenderSystem();
|
||||
mainf->AddChild(rain);
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// 3D audio
|
||||
// ------------------------------------------------------------------------
|
||||
Sound* music = new Sound();
|
||||
music->name = "music";
|
||||
music->LoadSound("assets/fs.wav", true);
|
||||
music->Update3DPosition(0.0f, 0.0f, 0.0f);
|
||||
music->PlayTrack(true);
|
||||
mainf->AddChild(music);
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// GUI
|
||||
// ------------------------------------------------------------------------
|
||||
TextBox* fpsCounter = new TextBox();
|
||||
fpsCounter->font = arial;
|
||||
fpsCounter->text = "";
|
||||
fpsCounter->fontsize = 0.5f;
|
||||
fpsCounter->Color = { 0.0f, 0.0f, 0.0f };
|
||||
fpsCounter->t2d.position = { 1.0f, 0.0f, 0.0f, 0.0f };
|
||||
fpsCounter->t2d.center = { 1.0f, 0.0f };
|
||||
fpsCounter->textCenter = { 0.0f, 0.5f };
|
||||
fpsCounter->t2d.size = { 0.1f, 0.1f, 0.0f, 0.0f };
|
||||
fpsCounter->BindToRenderSystem();
|
||||
|
||||
TextBox* healthText = new TextBox();
|
||||
healthText->font = arial;
|
||||
healthText->text = "";
|
||||
healthText->fontsize = 0.5f;
|
||||
healthText->Color = { 0.95f, 0.97f, 1.0f };
|
||||
healthText->t2d.position = { 0.02f, 0.02f, 0.0f, 0.0f };
|
||||
healthText->t2d.size = { 0.45f, 0.0f, 0.0f, 40.0f };
|
||||
healthText->textCenter = { 0.0f, 0.0f };
|
||||
healthText->BindToRenderSystem();
|
||||
|
||||
const float healthBarFillWidth = 314.0f;
|
||||
|
||||
Box* healthBarBack = new Box();
|
||||
healthBarBack->Color = { 0.03f, 0.04f, 0.06f };
|
||||
healthBarBack->Opacity = 0.85f;
|
||||
healthBarBack->t2d.position = { 0.02f, 1.0f, 0.0f, -30.0f };
|
||||
healthBarBack->t2d.center = { 0.0f, 1.0f };
|
||||
healthBarBack->t2d.size = { 0.0f, 0.0f, 320.0f, 26.0f };
|
||||
healthBarBack->BindToRenderSystem();
|
||||
|
||||
Box* healthBarFill = new Box();
|
||||
healthBarFill->Color = { 0.2f, 0.85f, 0.35f };
|
||||
healthBarFill->t2d.position = { 0.02f, 1.0f, 3.0f, -33.0f };
|
||||
healthBarFill->t2d.center = { 0.0f, 1.0f };
|
||||
healthBarFill->t2d.size = { 0.0f, 0.0f, healthBarFillWidth, 20.0f };
|
||||
healthBarFill->BindToRenderSystem();
|
||||
|
||||
struct MenuButton {
|
||||
Box* box;
|
||||
TextBox* label;
|
||||
glm::vec3 color;
|
||||
};
|
||||
|
||||
enum class MenuScreen { Main, Paused, Settings };
|
||||
MenuScreen menuScreen = MenuScreen::Main;
|
||||
MenuScreen settingsReturn = MenuScreen::Main;
|
||||
bool menuActive = true;
|
||||
bool prevMouseDown = false;
|
||||
std::vector<Box*> menuItems;
|
||||
|
||||
Box* menuVeil = new Box();
|
||||
menuVeil->Color = { 0.02f, 0.03f, 0.05f };
|
||||
menuVeil->Opacity = 0.55f;
|
||||
menuVeil->t2d.position = { 0.0f, 0.0f, 0.0f, 0.0f };
|
||||
menuVeil->t2d.size = { 1.0f, 1.0f, 0.0f, 0.0f };
|
||||
menuVeil->BindToRenderSystem();
|
||||
menuItems.push_back(menuVeil);
|
||||
|
||||
TextBox* menuTitle = new TextBox();
|
||||
menuTitle->font = arial;
|
||||
menuTitle->text = "EIIFWHRN";
|
||||
menuTitle->fontsize = 3.0f;
|
||||
menuTitle->Color = { 0.95f, 0.97f, 1.0f };
|
||||
menuTitle->t2d.position = { 0.5f, 0.17f, 0.0f, 0.0f };
|
||||
menuTitle->t2d.center = { 0.5f, 0.5f };
|
||||
menuTitle->t2d.size = { 0.8f, 0.0f, 0.0f, 170.0f };
|
||||
menuTitle->textCenter = { 0.5f, 0.5f };
|
||||
menuTitle->BindToRenderSystem();
|
||||
menuItems.push_back(menuTitle);
|
||||
|
||||
TextBox* menuSubtitle = new TextBox();
|
||||
menuSubtitle->font = arial;
|
||||
menuSubtitle->text = "MAIN MENU";
|
||||
menuSubtitle->fontsize = 0.65f;
|
||||
menuSubtitle->Color = { 0.55f, 0.65f, 0.78f };
|
||||
menuSubtitle->t2d.position = { 0.5f, 0.285f, 0.0f, 0.0f };
|
||||
menuSubtitle->t2d.center = { 0.5f, 0.5f };
|
||||
menuSubtitle->t2d.size = { 0.4f, 0.0f, 0.0f, 50.0f };
|
||||
menuSubtitle->textCenter = { 0.5f, 0.5f };
|
||||
menuSubtitle->BindToRenderSystem();
|
||||
menuItems.push_back(menuSubtitle);
|
||||
|
||||
auto MakeMenuButton = [&](const char* text, float x, float y, glm::vec3 color,
|
||||
float width = 340.0f, float height = 62.0f,
|
||||
float fontsize = 0.85f) {
|
||||
Box* box = new Box();
|
||||
box->Color = color;
|
||||
box->Opacity = 0.92f;
|
||||
box->t2d.position = { x, y, 0.0f, 0.0f };
|
||||
box->t2d.center = { 0.5f, 0.5f };
|
||||
box->t2d.size = { 0.0f, 0.0f, width, height };
|
||||
box->BindToRenderSystem();
|
||||
menuItems.push_back(box);
|
||||
|
||||
TextBox* label = new TextBox();
|
||||
label->font = arial;
|
||||
label->text = text;
|
||||
label->fontsize = fontsize;
|
||||
label->Color = { 0.95f, 0.97f, 1.0f };
|
||||
label->t2d.position = { x, y, 0.0f, 0.0f };
|
||||
label->t2d.center = { 0.5f, 0.5f };
|
||||
label->t2d.size = { 0.0f, 0.0f, width, height };
|
||||
label->textCenter = { 0.5f, 0.5f };
|
||||
label->BindToRenderSystem();
|
||||
menuItems.push_back(label);
|
||||
|
||||
return MenuButton{ box, label, color };
|
||||
};
|
||||
|
||||
MenuButton playButton = MakeMenuButton("PLAY", 0.5f, 0.46f, glm::vec3(0.12f, 0.30f, 0.22f));
|
||||
MenuButton settingsButton = MakeMenuButton("SETTINGS", 0.5f, 0.58f, glm::vec3(0.15f, 0.23f, 0.34f));
|
||||
MenuButton quitButton = MakeMenuButton("QUIT", 0.5f, 0.70f, glm::vec3(0.17f, 0.18f, 0.22f));
|
||||
|
||||
MenuButton sensitivityDown = MakeMenuButton("- SENS", 0.40f, 0.47f,
|
||||
glm::vec3(0.15f, 0.23f, 0.34f), 170.0f, 50.0f, 0.65f);
|
||||
MenuButton sensitivityUp = MakeMenuButton("+ SENS", 0.60f, 0.47f,
|
||||
glm::vec3(0.15f, 0.23f, 0.34f), 170.0f, 50.0f, 0.65f);
|
||||
MenuButton fovDown = MakeMenuButton("- FOV", 0.40f, 0.58f,
|
||||
glm::vec3(0.15f, 0.23f, 0.34f), 170.0f, 50.0f, 0.65f);
|
||||
MenuButton fovUp = MakeMenuButton("+ FOV", 0.60f, 0.58f,
|
||||
glm::vec3(0.15f, 0.23f, 0.34f), 170.0f, 50.0f, 0.65f);
|
||||
MenuButton hitboxToggle = MakeMenuButton("HITBOXES: OFF", 0.5f, 0.68f,
|
||||
glm::vec3(0.20f, 0.22f, 0.28f), 340.0f, 50.0f, 0.65f);
|
||||
MenuButton resetButton = MakeMenuButton("RESET DEFAULTS", 0.5f, 0.77f,
|
||||
glm::vec3(0.20f, 0.22f, 0.28f), 340.0f, 52.0f, 0.65f);
|
||||
MenuButton backButton = MakeMenuButton("BACK", 0.5f, 0.86f,
|
||||
glm::vec3(0.12f, 0.30f, 0.22f), 340.0f, 52.0f, 0.85f);
|
||||
|
||||
TextBox* settingsInfo = new TextBox();
|
||||
settingsInfo->font = arial;
|
||||
settingsInfo->fontsize = 0.65f;
|
||||
settingsInfo->Color = { 0.85f, 0.90f, 0.97f };
|
||||
settingsInfo->t2d.position = { 0.5f, 0.37f, 0.0f, 0.0f };
|
||||
settingsInfo->t2d.center = { 0.5f, 0.5f };
|
||||
settingsInfo->t2d.size = { 0.8f, 0.0f, 0.0f, 90.0f };
|
||||
settingsInfo->textCenter = { 0.5f, 0.5f };
|
||||
settingsInfo->BindToRenderSystem();
|
||||
menuItems.push_back(settingsInfo);
|
||||
|
||||
TextBox* menuHint = new TextBox();
|
||||
menuHint->font = arial;
|
||||
menuHint->text = "WASD TO MOVE | LEFT CLICK TO PUNCH | ESC FOR MENU";
|
||||
menuHint->fontsize = 0.5f;
|
||||
menuHint->Color = { 0.55f, 0.61f, 0.70f };
|
||||
menuHint->t2d.position = { 0.5f, 0.92f, 0.0f, 0.0f };
|
||||
menuHint->t2d.center = { 0.5f, 0.5f };
|
||||
menuHint->t2d.size = { 0.9f, 0.0f, 0.0f, 40.0f };
|
||||
menuHint->textCenter = { 0.5f, 0.5f };
|
||||
menuHint->BindToRenderSystem();
|
||||
menuItems.push_back(menuHint);
|
||||
|
||||
auto SetButtonVisible = [](MenuButton& button, bool visible) {
|
||||
button.box->Opacity = visible ? 0.92f : 0.0f;
|
||||
button.label->Opacity = visible ? 1.0f : 0.0f;
|
||||
};
|
||||
|
||||
auto ApplyMenuLayout = [&]() {
|
||||
const bool main = menuScreen == MenuScreen::Main;
|
||||
const bool paused = menuScreen == MenuScreen::Paused;
|
||||
const bool settings = menuScreen == MenuScreen::Settings;
|
||||
|
||||
menuVeil->Opacity = 0.55f;
|
||||
menuTitle->Opacity = 1.0f;
|
||||
menuSubtitle->Opacity = 1.0f;
|
||||
menuHint->Opacity = 1.0f;
|
||||
menuSubtitle->text = main ? "MAIN MENU" : (paused ? "PAUSED" : "SETTINGS");
|
||||
playButton.label->text = paused ? "RESUME" : "PLAY";
|
||||
quitButton.label->text = paused ? "QUIT TO MENU" : "QUIT";
|
||||
menuHint->text = settings
|
||||
? "ESC TO GO BACK | ADJUST MOUSE, FOV, AND HITBOXES"
|
||||
: "WASD TO MOVE | LEFT CLICK TO PUNCH | ESC FOR MENU";
|
||||
|
||||
SetButtonVisible(playButton, !settings);
|
||||
SetButtonVisible(settingsButton, !settings);
|
||||
SetButtonVisible(quitButton, !settings);
|
||||
SetButtonVisible(sensitivityDown, settings);
|
||||
SetButtonVisible(sensitivityUp, settings);
|
||||
SetButtonVisible(fovDown, settings);
|
||||
SetButtonVisible(fovUp, settings);
|
||||
SetButtonVisible(hitboxToggle, settings);
|
||||
SetButtonVisible(resetButton, settings);
|
||||
SetButtonVisible(backButton, settings);
|
||||
settingsInfo->Opacity = settings ? 1.0f : 0.0f;
|
||||
|
||||
hitboxToggle.label->text = showHitboxes ? "HITBOXES: ON" : "HITBOXES: OFF";
|
||||
hitboxToggle.color = showHitboxes
|
||||
? glm::vec3(0.12f, 0.30f, 0.22f)
|
||||
: glm::vec3(0.20f, 0.22f, 0.28f);
|
||||
|
||||
settingsInfo->text = "MOUSE SENSITIVITY: " +
|
||||
std::to_string((int)std::lround(StartupCmPer360)) +
|
||||
" CM / 360\nFIELD OF VIEW: " + std::to_string((int)std::lround(camera->FOV));
|
||||
};
|
||||
|
||||
auto OpenMenu = [&](MenuScreen screen) {
|
||||
menuActive = true;
|
||||
menuScreen = screen;
|
||||
charactermanager->ClearInput();
|
||||
testcharacter.SetWalking(false);
|
||||
npc.SetWalking(false);
|
||||
fpsCounter->Opacity = 0.0f;
|
||||
healthText->Opacity = 0.0f;
|
||||
healthBarBack->Opacity = 0.0f;
|
||||
healthBarFill->Opacity = 0.0f;
|
||||
camera->lockedcursor = false;
|
||||
glfwSetInputMode(window->handle, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
|
||||
prevMouseDown = mouse->IsLeftDown();
|
||||
};
|
||||
|
||||
auto ResumeGame = [&]() {
|
||||
menuActive = false;
|
||||
charactermanager->ClearInput();
|
||||
for (Box* item : menuItems) item->Opacity = 0.0f;
|
||||
fpsCounter->Opacity = 1.0f;
|
||||
healthText->Opacity = 1.0f;
|
||||
healthBarBack->Opacity = 0.85f;
|
||||
healthBarFill->Opacity = 1.0f;
|
||||
camera->lockedcursor = true;
|
||||
glfwSetInputMode(window->handle, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
|
||||
int ww, wh;
|
||||
glfwGetWindowSize(window->handle, &ww, &wh);
|
||||
glfwSetCursorPos(window->handle, ww * 0.5, wh * 0.5);
|
||||
};
|
||||
|
||||
fpsCounter->Opacity = 0.0f;
|
||||
healthText->Opacity = 0.0f;
|
||||
healthBarBack->Opacity = 0.0f;
|
||||
healthBarFill->Opacity = 0.0f;
|
||||
camera->lockedcursor = false;
|
||||
glfwSetInputMode(window->handle, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// Baseplate
|
||||
// ------------------------------------------------------------------------
|
||||
Mesh* floor = CreateCubeMesh();
|
||||
floor->name = "baseplate";
|
||||
floor->meshTexture = blanktex;
|
||||
floor->roughness = 0.9f;
|
||||
floor->t.ScaleTo({ 32.0f, 2.0f, 32.0f });
|
||||
floor->t.TranslateTo({ 0.0f, -1.0f, 0.0f });
|
||||
floor->BindToRenderSystem();
|
||||
mainf->AddChild(floor);
|
||||
|
||||
p* floorBody = new p(floor);
|
||||
floorBody->velocity = false;
|
||||
physicsengine->AddObject(floorBody);
|
||||
const BoundingBox floorBounds = floor->t.GetRotationlessAABB();
|
||||
|
||||
const float wallHeight = 4.0f;
|
||||
const float wallThickness = 1.0f;
|
||||
const float wallOffset = 16.0f + wallThickness * 0.5f;
|
||||
const float wallSpan = 32.0f + wallThickness;
|
||||
|
||||
auto AddWall = [&](const char* name, const glm::vec3& position, const glm::vec3& scale) {
|
||||
Mesh* wall = CreateCubeMesh();
|
||||
wall->name = name;
|
||||
wall->meshTexture = blanktex;
|
||||
wall->roughness = 0.9f;
|
||||
wall->t.ScaleTo(scale);
|
||||
wall->t.TranslateTo(position);
|
||||
wall->BindToRenderSystem();
|
||||
mainf->AddChild(wall);
|
||||
|
||||
p* wallBody = new p(wall);
|
||||
wallBody->velocity = false;
|
||||
physicsengine->AddObject(wallBody);
|
||||
};
|
||||
|
||||
AddWall("wall_north", { 0.0f, wallHeight * 0.5f, -wallOffset }, { wallSpan, wallHeight, wallThickness });
|
||||
AddWall("wall_south", { 0.0f, wallHeight * 0.5f, wallOffset }, { wallSpan, wallHeight, wallThickness });
|
||||
AddWall("wall_west", { -wallOffset, wallHeight * 0.5f, 0.0f }, { wallThickness, wallHeight, 32.0f });
|
||||
AddWall("wall_east", { wallOffset, wallHeight * 0.5f, 0.0f }, { wallThickness, wallHeight, 32.0f });
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// Ground check + respawn
|
||||
// ------------------------------------------------------------------------
|
||||
auto IsGrounded = [&]() -> bool {
|
||||
Ray downRay;
|
||||
downRay.origin = testcharacter.body->t.GetTranslation();
|
||||
downRay.direction = glm::vec3(0.0f, -1.0f, 0.0f);
|
||||
const float halfHeight = testcharacter.body->t.GetScale().y * 0.5f;
|
||||
for (p* obj : physicsengine->GetObjects()) {
|
||||
if (obj->pointer == testcharacter.body) continue;
|
||||
if (!obj->collision) continue;
|
||||
auto hit = IsRayInT(downRay, obj->pointer->t);
|
||||
if (hit.has_value()) {
|
||||
if (glm::distance(downRay.origin, hit.value()) < halfHeight + 0.15f)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
std::mt19937 respawnRng(std::random_device{}());
|
||||
auto RandomSpawn = [&]() -> glm::vec3 {
|
||||
std::uniform_real_distribution<float> spread(-14.0f, 14.0f);
|
||||
return { spread(respawnRng), 15.0f, spread(respawnRng) };
|
||||
};
|
||||
|
||||
auto UpdateHitboxDebug = [&]() {
|
||||
std::vector<HitboxDebugLine> lines;
|
||||
if (showHitboxes) {
|
||||
for (Character* character : charactermanager->GetCharacters()) {
|
||||
if (!character->body) continue;
|
||||
lines.push_back({ character->body->t.GetMatrix(), glm::vec3(0.2f, 0.9f, 0.35f) });
|
||||
const Hitbox& punch = character->GetPunchHitbox();
|
||||
if (punch.active)
|
||||
lines.push_back({ punch.transform.GetMatrix(), glm::vec3(1.0f, 0.25f, 0.1f) });
|
||||
}
|
||||
}
|
||||
rendersystem->SetHitboxDebugLines(lines);
|
||||
};
|
||||
|
||||
// ========================================================================
|
||||
// Game loop
|
||||
// ========================================================================
|
||||
while (!glfwWindowShouldClose(window->handle))
|
||||
{
|
||||
frame++;
|
||||
|
||||
static double prevFrameTime = glfwGetTime();
|
||||
const double frameNow = glfwGetTime();
|
||||
const float deltatime = glm::clamp(float(frameNow - prevFrameTime), 0.001f, 1.0f / 60.0f) * (144.0f / float(fps));
|
||||
prevFrameTime = frameNow;
|
||||
const float refDt = 1.0f / float(fps);
|
||||
|
||||
static bool prevEscapeDown = false;
|
||||
const bool escapeDown = keyboard->IsKeyDown(GLFW_KEY_ESCAPE);
|
||||
const bool escapePressed = escapeDown && !prevEscapeDown;
|
||||
prevEscapeDown = escapeDown;
|
||||
|
||||
if (escapePressed) {
|
||||
if (!menuActive)
|
||||
OpenMenu(MenuScreen::Paused);
|
||||
else if (menuScreen == MenuScreen::Settings)
|
||||
menuScreen = settingsReturn;
|
||||
else if (menuScreen == MenuScreen::Paused)
|
||||
ResumeGame();
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
// Mouse look
|
||||
// --------------------------------------------------------------------
|
||||
while (Mouse::Event buffer = mouse->Read()) {
|
||||
if (menuActive) continue;
|
||||
if (buffer.GetType() == Mouse::Event::Type::Move && camera->lockedcursor) {
|
||||
float xoffset = mouse->GetX() - mouse->GetLastX();
|
||||
float yoffset = mouse->GetLastY() - mouse->GetY();
|
||||
camera->ProcessMouseMovement(xoffset, yoffset);
|
||||
}
|
||||
else if (buffer.GetType() == Mouse::Event::Type::LPress) {
|
||||
testcharacter.Punch(camera->t.GetFrontVector());
|
||||
}
|
||||
else if (buffer.GetType() == Mouse::Event::Type::RPress) {
|
||||
camera->lockedcursor = !camera->lockedcursor;
|
||||
if (camera->lockedcursor) {
|
||||
glfwSetInputMode(window->handle, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
|
||||
int ww, wh;
|
||||
glfwGetWindowSize(window->handle, &ww, &wh);
|
||||
glfwSetCursorPos(window->handle, ww * 0.5, wh * 0.5);
|
||||
}
|
||||
else {
|
||||
glfwSetInputMode(window->handle, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (menuActive) {
|
||||
ApplyMenuLayout();
|
||||
|
||||
const bool liveBackdrop = menuScreen == MenuScreen::Main ||
|
||||
(menuScreen == MenuScreen::Settings && settingsReturn == MenuScreen::Main);
|
||||
if (liveBackdrop) {
|
||||
static float menuAngle = 0.6f;
|
||||
menuAngle += deltatime * 0.12f;
|
||||
const glm::vec3 menuTarget(0.0f, 1.4f, 0.0f);
|
||||
const glm::vec3 menuCamera = menuTarget +
|
||||
glm::vec3(std::sin(menuAngle) * 7.5f, 2.6f, std::cos(menuAngle) * 7.5f);
|
||||
camera->t.TranslateTo(menuCamera);
|
||||
camera->t.RotateToQuaternion(LookAt(menuTarget - menuCamera));
|
||||
camera->Step(deltatime);
|
||||
|
||||
npc.SetTurnDirection(testcharacter.body->t.GetTranslation() -
|
||||
npc.body->t.GetTranslation());
|
||||
charactermanager->Step(deltatime);
|
||||
rain->t.TranslateTo(camera->t.GetTranslation() + glm::vec3(0.0f, 20.0f, 0.0f));
|
||||
rain->Step(deltatime);
|
||||
}
|
||||
|
||||
soundsystem->SetListenerPosition(
|
||||
camera->t.GetTranslation(),
|
||||
camera->t.GetFrontVector(),
|
||||
camera->t.GetUpVector()
|
||||
);
|
||||
soundsystem->Update();
|
||||
|
||||
MenuButton* buttons[] = {
|
||||
&playButton, &settingsButton, &quitButton,
|
||||
&sensitivityDown, &sensitivityUp, &fovDown, &fovUp,
|
||||
&hitboxToggle, &resetButton, &backButton
|
||||
};
|
||||
for (MenuButton* button : buttons)
|
||||
button->box->t2d.Recalculate();
|
||||
|
||||
const glm::vec2 mousePos((float)mouse->GetX(), (float)mouse->GetY());
|
||||
auto Hovered = [&](const MenuButton& button) {
|
||||
return mousePos.x > button.box->t2d.pixelposition.x &&
|
||||
mousePos.y > button.box->t2d.pixelposition.y &&
|
||||
mousePos.x < button.box->t2d.pixelposition.x + button.box->t2d.pixelsize.x &&
|
||||
mousePos.y < button.box->t2d.pixelposition.y + button.box->t2d.pixelsize.y;
|
||||
};
|
||||
|
||||
const bool playHovered = Hovered(playButton);
|
||||
const bool settingsHovered = Hovered(settingsButton);
|
||||
const bool quitHovered = Hovered(quitButton);
|
||||
const bool sensDownHovered = Hovered(sensitivityDown);
|
||||
const bool sensUpHovered = Hovered(sensitivityUp);
|
||||
const bool fovDownHovered = Hovered(fovDown);
|
||||
const bool fovUpHovered = Hovered(fovUp);
|
||||
const bool hitboxHovered = Hovered(hitboxToggle);
|
||||
const bool resetHovered = Hovered(resetButton);
|
||||
const bool backHovered = Hovered(backButton);
|
||||
|
||||
playButton.box->Color = playHovered ? glm::vec3(0.18f, 0.44f, 0.32f) : playButton.color;
|
||||
settingsButton.box->Color = settingsHovered ? glm::vec3(0.22f, 0.34f, 0.50f) : settingsButton.color;
|
||||
quitButton.box->Color = quitHovered ? glm::vec3(0.30f, 0.20f, 0.22f) : quitButton.color;
|
||||
sensitivityDown.box->Color = sensDownHovered ? glm::vec3(0.22f, 0.34f, 0.50f) : sensitivityDown.color;
|
||||
sensitivityUp.box->Color = sensUpHovered ? glm::vec3(0.22f, 0.34f, 0.50f) : sensitivityUp.color;
|
||||
fovDown.box->Color = fovDownHovered ? glm::vec3(0.22f, 0.34f, 0.50f) : fovDown.color;
|
||||
fovUp.box->Color = fovUpHovered ? glm::vec3(0.22f, 0.34f, 0.50f) : fovUp.color;
|
||||
hitboxToggle.box->Color = hitboxHovered ? glm::vec3(0.22f, 0.34f, 0.50f) : hitboxToggle.color;
|
||||
resetButton.box->Color = resetHovered ? glm::vec3(0.30f, 0.32f, 0.40f) : resetButton.color;
|
||||
backButton.box->Color = backHovered ? glm::vec3(0.18f, 0.44f, 0.32f) : backButton.color;
|
||||
|
||||
const bool mouseDown = mouse->IsLeftDown();
|
||||
if (mouseDown && !prevMouseDown) {
|
||||
if (menuScreen == MenuScreen::Settings) {
|
||||
if (sensDownHovered) {
|
||||
StartupCmPer360 = glm::clamp(StartupCmPer360 + 2.0f, 4.0f, 80.0f);
|
||||
camera->SetSensitivityCm(StartupCmPer360, StartupMouseDpi);
|
||||
}
|
||||
else if (sensUpHovered) {
|
||||
StartupCmPer360 = glm::clamp(StartupCmPer360 - 2.0f, 4.0f, 80.0f);
|
||||
camera->SetSensitivityCm(StartupCmPer360, StartupMouseDpi);
|
||||
}
|
||||
else if (fovDownHovered) {
|
||||
camera->FOV = glm::clamp(camera->FOV - 5.0f, 60.0f, 130.0f);
|
||||
}
|
||||
else if (fovUpHovered) {
|
||||
camera->FOV = glm::clamp(camera->FOV + 5.0f, 60.0f, 130.0f);
|
||||
}
|
||||
else if (hitboxHovered) {
|
||||
showHitboxes = !showHitboxes;
|
||||
}
|
||||
else if (resetHovered) {
|
||||
StartupCmPer360 = 16.0f;
|
||||
StartupMouseDpi = 800.0f;
|
||||
camera->SetSensitivityCm(StartupCmPer360, StartupMouseDpi);
|
||||
camera->FOV = 110.0f;
|
||||
showHitboxes = false;
|
||||
}
|
||||
else if (backHovered) {
|
||||
menuScreen = settingsReturn;
|
||||
}
|
||||
}
|
||||
else if (playHovered) {
|
||||
ResumeGame();
|
||||
}
|
||||
else if (settingsHovered) {
|
||||
settingsReturn = menuScreen;
|
||||
menuScreen = MenuScreen::Settings;
|
||||
}
|
||||
else if (quitHovered) {
|
||||
if (menuScreen == MenuScreen::Main)
|
||||
glfwSetWindowShouldClose(window->handle, 1);
|
||||
else
|
||||
menuScreen = MenuScreen::Main;
|
||||
}
|
||||
}
|
||||
prevMouseDown = mouseDown;
|
||||
|
||||
UpdateHitboxDebug();
|
||||
rendersystem->Render(*camera);
|
||||
glfwPollEvents();
|
||||
continue;
|
||||
}
|
||||
|
||||
const glm::vec3 camFront = camera->t.GetFrontVector();
|
||||
const glm::vec3 camRight = camera->t.GetRightVector();
|
||||
const float movespeed = 3.0f * 1.3f * 0.6f;
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
// WASD movement
|
||||
// --------------------------------------------------------------------
|
||||
const glm::vec3 inputDirection = testcharacter.GetMovementDirection(camFront, camRight);
|
||||
const bool hasMoveInput = glm::length(inputDirection) > 0.0f;
|
||||
|
||||
if (hasMoveInput)
|
||||
testcharacter.SetTurnDirection(inputDirection);
|
||||
testcharacter.SetWalking(hasMoveInput);
|
||||
|
||||
const glm::vec3 npcVelocity(npcBody->linearvelocity.x, 0.0f, npcBody->linearvelocity.z);
|
||||
npc.SetWalking(glm::length(npcVelocity) > 0.1f);
|
||||
npc.SetTurnDirection(testcharacter.body->t.GetTranslation() -
|
||||
npc.body->t.GetTranslation());
|
||||
|
||||
charactermanager->Step(deltatime);
|
||||
|
||||
const glm::vec3 inputVel = hasMoveInput
|
||||
? testcharacter.GetForwardDirection() * movespeed
|
||||
: glm::vec3(0.0f);
|
||||
|
||||
const float accel = 40.0f;
|
||||
const float damp = 0.75f;
|
||||
const float airControl = 0.5f;
|
||||
const float groundTopSpeed = movespeed * accel * refDt * damp / (1.0f - damp);
|
||||
|
||||
if (IsGrounded()) {
|
||||
const float dampStep = std::pow(damp, deltatime / refDt);
|
||||
const float accelScale = refDt * damp * (1.0f - dampStep) / (deltatime * dampStep * (1.0f - damp));
|
||||
characterBody->linearvelocity.x *= dampStep;
|
||||
characterBody->linearvelocity.z *= dampStep;
|
||||
characterBody->linearvelocity.x += inputVel.x * accel * deltatime * accelScale;
|
||||
characterBody->linearvelocity.z += inputVel.z * accel * deltatime * accelScale;
|
||||
}
|
||||
else if (glm::length(inputVel) > 0.0f) {
|
||||
const glm::vec3 wishDir = glm::normalize(inputVel);
|
||||
const float current = glm::dot(glm::vec3(characterBody->linearvelocity.x, 0.0f,
|
||||
characterBody->linearvelocity.z), wishDir);
|
||||
const float add = glm::clamp(groundTopSpeed - current, 0.0f,
|
||||
accel * airControl * movespeed * deltatime);
|
||||
characterBody->linearvelocity.x += wishDir.x * add;
|
||||
characterBody->linearvelocity.z += wishDir.z * add;
|
||||
}
|
||||
|
||||
charactermanager->ResolveCombat(*physicsengine);
|
||||
|
||||
{
|
||||
const int substeps = std::max(1, (int)std::ceil(deltatime * 120.0f));
|
||||
const float subDt = deltatime / float(substeps);
|
||||
for (int i = 0; i < substeps; i++) physicsengine->Step(subDt);
|
||||
}
|
||||
|
||||
if (testcharacter.body->t.GetTranslation().y < -20.0f) {
|
||||
testcharacter.body->t.TranslateTo(RandomSpawn());
|
||||
characterBody->linearvelocity = glm::vec3(0.0f);
|
||||
characterBody->WakeUp();
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
// Third person camera
|
||||
// --------------------------------------------------------------------
|
||||
{
|
||||
const glm::vec3 playerPos = testcharacter.body->t.GetTranslation();
|
||||
const glm::vec3 target = playerPos + glm::vec3(0.0f, 0.8f, 0.0f);
|
||||
glm::vec3 cameraPos = target - camera->t.GetFrontVector() * 5.0f;
|
||||
|
||||
const bool playerOffFloor =
|
||||
playerPos.x < floorBounds.min.x || playerPos.x > floorBounds.max.x ||
|
||||
playerPos.z < floorBounds.min.z || playerPos.z > floorBounds.max.z;
|
||||
const bool ignoreFloorCollision = playerOffFloor || playerPos.y < floorBounds.max.y;
|
||||
|
||||
const glm::vec3 cameraRay = cameraPos - target;
|
||||
const float desiredDistance = glm::length(cameraRay);
|
||||
const glm::vec3 cameraDir = desiredDistance > 0.0001f ? cameraRay / desiredDistance : glm::vec3(0.0f);
|
||||
|
||||
Ray cameraSweep;
|
||||
cameraSweep.origin = target;
|
||||
cameraSweep.direction = cameraDir;
|
||||
float nearestHit = desiredDistance;
|
||||
for (p* obj : physicsengine->GetObjects()) {
|
||||
if (obj->pointer == testcharacter.body || !obj->collision)
|
||||
continue;
|
||||
if (obj == floorBody && ignoreFloorCollision)
|
||||
continue;
|
||||
auto hit = IsRayInT(cameraSweep, obj->pointer->t);
|
||||
if (!hit.has_value())
|
||||
continue;
|
||||
const float hitDistance = glm::dot(hit.value() - target, cameraDir);
|
||||
if (hitDistance > 0.001f && hitDistance < nearestHit)
|
||||
nearestHit = hitDistance;
|
||||
}
|
||||
|
||||
const float cameraPadding = 0.3f;
|
||||
cameraPos = target + cameraDir * glm::max(nearestHit - cameraPadding, 0.05f);
|
||||
camera->t.TranslateTo(cameraPos);
|
||||
}
|
||||
camera->Step(deltatime);
|
||||
|
||||
rain->t.TranslateTo(camera->t.GetTranslation() + glm::vec3(0.0f, 20.0f, 0.0f));
|
||||
rain->Step(deltatime);
|
||||
|
||||
Sound* music = static_cast<Sound*>(mainf->GetFirstChildOfName("music"));
|
||||
if (music) music->Update3DPosition(0.0f, 0.0f, 0.0f);
|
||||
|
||||
soundsystem->SetListenerPosition(
|
||||
camera->t.GetTranslation(),
|
||||
camera->t.GetFrontVector(),
|
||||
camera->t.GetUpVector()
|
||||
);
|
||||
soundsystem->Update();
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
// FPS counter
|
||||
// --------------------------------------------------------------------
|
||||
{
|
||||
static double lastTime = glfwGetTime();
|
||||
static int frameCount = 0;
|
||||
static int measuredFps = 0;
|
||||
static float accumulator = 0.0f;
|
||||
double now = glfwGetTime();
|
||||
accumulator += (float)(now - lastTime);
|
||||
lastTime = now;
|
||||
frameCount++;
|
||||
if (accumulator >= 0.25f) {
|
||||
measuredFps = (int)(frameCount / accumulator);
|
||||
frameCount = 0;
|
||||
accumulator = 0.0f;
|
||||
}
|
||||
fpsCounter->text = std::to_string(measuredFps) + " FPS";
|
||||
}
|
||||
|
||||
healthText->text = "PLAYER " + std::to_string((int)std::lround(testcharacter.body->Health)) +
|
||||
" HP DUMMY " + std::to_string((int)std::lround(npc.body->Health)) + " HP";
|
||||
|
||||
const float healthRatio = glm::clamp((float)testcharacter.body->Health / 100.0f, 0.0f, 1.0f);
|
||||
healthBarFill->t2d.size.z = healthBarFillWidth * healthRatio;
|
||||
healthBarFill->Color = glm::mix(glm::vec3(0.85f, 0.20f, 0.12f),
|
||||
glm::vec3(0.20f, 0.85f, 0.35f), healthRatio);
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
// Render
|
||||
// --------------------------------------------------------------------
|
||||
UpdateHitboxDebug();
|
||||
rendersystem->Render(*camera);
|
||||
|
||||
glfwPollEvents();
|
||||
}
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// GLFW callbacks
|
||||
// ============================================================================
|
||||
void framebuffer_size_callback(GLFWwindow* window, int w, int h)
|
||||
{
|
||||
if (w <= 0 || h <= 0) return;
|
||||
::window->width = w;
|
||||
::window->height = h;
|
||||
glViewport(0, 0, w, h);
|
||||
if (engine && engine->rendersystem)
|
||||
engine->rendersystem->Resize(w, h);
|
||||
}
|
||||
|
||||
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
|
||||
{
|
||||
if (key == GLFW_KEY_F11 && action == GLFW_PRESS) {
|
||||
static int wx = 100, wy = 100, ww = 1920, wh = 1080;
|
||||
if (glfwGetWindowMonitor(window)) {
|
||||
glfwSetWindowMonitor(window, nullptr, wx, wy, ww, wh, 0);
|
||||
}
|
||||
else {
|
||||
glfwGetWindowPos(window, &wx, &wy);
|
||||
glfwGetWindowSize(window, &ww, &wh);
|
||||
GLFWmonitor* monitor = glfwGetPrimaryMonitor();
|
||||
const GLFWvidmode* mode = glfwGetVideoMode(monitor);
|
||||
glfwSetWindowMonitor(window, monitor, 0, 0, mode->width, mode->height, mode->refreshRate);
|
||||
}
|
||||
glfwSwapInterval(1);
|
||||
}
|
||||
|
||||
if (action == GLFW_PRESS) keyboard->KeyDown(key);
|
||||
else if (action == GLFW_RELEASE) keyboard->KeyUp(key);
|
||||
|
||||
if (key >= GLFW_KEY_A && key <= GLFW_KEY_Z && engine && engine->charactermanager) {
|
||||
const char letter = (char)('A' + (key - GLFW_KEY_A));
|
||||
if (action == GLFW_PRESS) engine->charactermanager->PressInput(letter);
|
||||
else if (action == GLFW_RELEASE) engine->charactermanager->ReleaseInput(letter);
|
||||
}
|
||||
}
|
||||
|
||||
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset)
|
||||
{
|
||||
}
|
||||
|
||||
void mouse_callback(GLFWwindow* window, double xposIn, double yposIn)
|
||||
{
|
||||
mouse->OnMouseMove(static_cast<float>(xposIn), static_cast<float>(yposIn));
|
||||
if (!engine || !engine->camera || !engine->camera->lockedcursor) return;
|
||||
|
||||
int ww, wh;
|
||||
glfwGetWindowSize(window, &ww, &wh);
|
||||
const double cx = ww / 2.0;
|
||||
const double cy = wh / 2.0;
|
||||
if (std::abs(xposIn - cx) < 0.5 && std::abs(yposIn - cy) < 0.5) return;
|
||||
|
||||
glfwSetCursorPos(window, cx, cy);
|
||||
mouse->OnMouseMove((float)cx, (float)cy);
|
||||
}
|
||||
|
||||
void mouse_button_callback(GLFWwindow* window, int button, int action, int mods)
|
||||
{
|
||||
if (button == GLFW_MOUSE_BUTTON_RIGHT) {
|
||||
if (action == GLFW_PRESS) mouse->RightDown();
|
||||
else mouse->RightUp();
|
||||
}
|
||||
else if (button == GLFW_MOUSE_BUTTON_LEFT) {
|
||||
if (action == GLFW_PRESS) mouse->LeftDown();
|
||||
else mouse->LeftUp();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user