#include "glm.hpp" #include "ext.hpp" #include #include #include "Bullet.h" #include "ParticleSystem.h" #include "GameEntity.h" #pragma once class Spaceship : public GameEntity { private: std::list bullets; float lastShootTime = 0.f; float shootInterval = 0.3f; ParticleSystem* leftParticle; ParticleSystem* rightParticle; // Prywatny konstruktor, aby zapobiec zewn�trznemu tworzeniu instancji Spaceship() : GameEntity(100.0f, 100.0f, 10.0f) { } // Prywatny destruktor, aby zapobiec przypadkowemu usuwaniu instancji ~Spaceship() {} public: static Spaceship* getInstance() { static Spaceship instance; // Jedna i jedyna instancja return &instance; } glm::vec3 color = glm::vec3(0.3, 0.3, 0.5); float roughness = 0.5; float metallic = 0.6; float turbo = 1.0f; float turboMAX = 1.0f; glm::vec3 spaceshipPos = glm::vec3(4.065808f, 10.250000f, -20.189549f); glm::vec3 spaceshipDir = glm::vec3(-0.490263f, 0.000000f, 0.871578f); glm::vec3 spotlightPos = glm::vec3(0, 0, 0); glm::vec3 spotlightConeDir = glm::vec3(0, 0, 0); glm::vec3 spotlightColor = glm::vec3(0.4, 0.4, 0.9) * 3; float spotlightPhi = 3.14 / 4; glm::vec3 cameraPos = glm::vec3(0.479490f, 1.250000f, -2.124680f); glm::vec3 cameraDir = glm::vec3(-0.354510f, 0.000000f, 0.935054f); glm::vec3 cameraPosHUDBar = cameraPos; glm::mat4 additionalHorRotationMatrix; glm::mat4 additionalVerRotationMatrix; glm::mat4 calculateModelMatrix() { glm::vec3 spaceshipSide = glm::normalize(glm::cross(spaceshipDir, glm::vec3(0.f, 1.f, 0.f))); glm::vec3 spaceshipUp = glm::normalize(glm::cross(spaceshipSide, spaceshipDir)); glm::mat4 spaceshipCameraRotationMatrix = glm::mat4({ spaceshipSide.x, spaceshipSide.y, spaceshipSide.z, 0, spaceshipUp.x, spaceshipUp.y, spaceshipUp.z, 0, -spaceshipDir.x, -spaceshipDir.y, -spaceshipDir.z, 0, 0., 0., 0., 1. }); float additionalVerRotationAngle = glm::radians(currentShipVerAngle); additionalVerRotationMatrix = glm::rotate(glm::mat4(1.0f), additionalVerRotationAngle, glm::vec3(1.f, 0.f, 0.f)); float additionalHorRotationAngle = glm::radians(currentShipHorAngle); additionalHorRotationMatrix = glm::rotate(glm::mat4(1.0f), additionalHorRotationAngle, glm::vec3(0.f, 0.2f, 1.f)); glm::mat4 modelMatrix = glm::translate(spaceshipPos) * spaceshipCameraRotationMatrix * additionalVerRotationMatrix * additionalHorRotationMatrix * glm::eulerAngleY(glm::pi()) * glm::scale(glm::vec3(0.02f)); return modelMatrix; } void setPerticlesParameters(float speed, float generationInterval) { leftParticle->speed = speed; leftParticle->generationInterval = generationInterval; rightParticle->speed = speed; rightParticle->generationInterval = generationInterval; } const float fromCameraDirHorizontalStateToStateTime = 0.2f; const float CAMERA_DISTANCE_STATIC_HOR = 0.7f; const float CAMERA_DISTANCE_SLOW_HOR = 0.85f; const float CAMERA_DISTANCE_FAST_HOR = 1.f; float currentCameraDistanceHor = CAMERA_DISTANCE_STATIC_HOR; float targetCameraDistanceHor = CAMERA_DISTANCE_STATIC_HOR; int currentWState = 0; int currentShiftState = 0; float calculateCameraDistanceHor(int wState, int shiftState, float time) { currentWState = wState; currentShiftState = shiftState; if (currentWState == 1 && currentShiftState == 0) { targetCameraDistanceHor = CAMERA_DISTANCE_SLOW_HOR; } else if (currentWState == 1 && currentShiftState == 1) { targetCameraDistanceHor = CAMERA_DISTANCE_FAST_HOR; } else { targetCameraDistanceHor = CAMERA_DISTANCE_STATIC_HOR; } float diff = targetCameraDistanceHor - currentCameraDistanceHor; float step = diff / fromCameraDirHorizontalStateToStateTime * time; currentCameraDistanceHor += step; return currentCameraDistanceHor; } const float fromCameraDirVerticalStateToStateTime = 0.2f; const float CAMERA_DISTANCE_STATIC_VER = 0.2f; const float CAMERA_DISTANCE_SLOW_VER = 0.25f; const float CAMERA_DISTANCE_FAST_VER = 0.3f; float currentCameraDistanceVer = CAMERA_DISTANCE_STATIC_VER; float targetCameraDistanceVer = CAMERA_DISTANCE_STATIC_VER; float calculateCameraDistanceVer(float time) { if (currentWState == 1 && currentShiftState == 0) { targetCameraDistanceVer = CAMERA_DISTANCE_SLOW_VER; } else if (currentWState == 1 && currentShiftState == 1) { targetCameraDistanceVer = CAMERA_DISTANCE_FAST_VER; } else { targetCameraDistanceVer = CAMERA_DISTANCE_STATIC_VER; } float diff = targetCameraDistanceVer - currentCameraDistanceVer; float step = diff / fromCameraDirVerticalStateToStateTime * time; currentCameraDistanceVer += step; return currentCameraDistanceVer; } const float MAX_VERTICAL_ANGLE = 15.f; float currentShipVerAngle = 0.f; float targetShipVerAngle = 0.f; int currentQState = 0; int currentEState = 0; float calculateShipAngleVer(int qState, int eState, float time) { currentQState = qState; currentEState = eState; if (currentQState == 1) { targetShipVerAngle = MAX_VERTICAL_ANGLE; } else if (currentEState == 1) { targetShipVerAngle = -MAX_VERTICAL_ANGLE; } else { targetShipVerAngle = 0.f; } float diff = targetShipVerAngle - currentShipVerAngle; float step = diff / 0.2f * time; currentShipVerAngle += step; return currentShipVerAngle; } const float MAX_HORIZONTALL_ANGLE = 15.f; float currentShipHorAngle = 0.f; float targetShipHorAngle = 0.f; int currentAState = 0; int currentDState = 0; float calculateShipAngleHor(int aState, int dState, float time) { currentAState = aState; currentDState = dState; if (currentAState == 1) { targetShipHorAngle = MAX_HORIZONTALL_ANGLE; } else if (currentDState == 1) { targetShipHorAngle = -MAX_HORIZONTALL_ANGLE; } else { targetShipHorAngle = 0.f; } float diff = targetShipHorAngle - currentShipHorAngle; float step = diff / 0.2f * time; currentShipHorAngle += step; return currentShipHorAngle; } void processInput(GLFWwindow* window, float deltaTime, float time) { static bool mouseButtonCallbackSet = false; if (!mouseButtonCallbackSet) { } glm::vec3 spaceshipSide = glm::normalize(glm::cross(spaceshipDir, glm::vec3(0.f, 1.f, 0.f))); glm::vec3 spaceshipUp = glm::vec3(0.f, 1.f, 0.f); float angleSpeed = 0.05f * deltaTime * 60; float moveSpeed = 0.05f * deltaTime * 60; int w = glfwGetKey(window, GLFW_KEY_W); int s = glfwGetKey(window, GLFW_KEY_S); int shiftState = glfwGetKey(window, GLFW_KEY_LEFT_SHIFT); int qState = glfwGetKey(window, GLFW_KEY_Q); int eState = glfwGetKey(window, GLFW_KEY_E); int aState = glfwGetKey(window, GLFW_KEY_A); int dState = glfwGetKey(window, GLFW_KEY_D); calculateShipAngleVer(qState, eState, deltaTime); calculateShipAngleHor(aState, dState, deltaTime); //spaceshipDir = glm::vec3(glm::eulerAngleX(verticalAngle) * glm::vec4(spaceshipDir, 0)); if (w == GLFW_PRESS) { if (shiftState == GLFW_PRESS) { turbo = glm::max(0.0f, turbo - 0.003f * deltaTime * 60); if (turbo == 0.0f) { shiftState = GLFW_RELEASE; moveSpeed = 0.05f * deltaTime * 60; setPerticlesParameters(100.f, 0.000001f); } else { moveSpeed *= 2; setPerticlesParameters(200.f, 0.0000005f); } } else { setPerticlesParameters(100.f, 0.000001f); turbo = glm::min(turboMAX, turbo + 0.001f * deltaTime * 60); } } else { setPerticlesParameters(50.f, 0.0002f); turbo = glm::min(turboMAX, turbo + 0.005f * deltaTime * 60); } if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS) { glfwSetWindowShouldClose(window, true); } if (w == GLFW_PRESS) spaceshipPos += spaceshipDir * moveSpeed; if (s == GLFW_PRESS) spaceshipPos -= spaceshipDir * moveSpeed; if (glfwGetKey(window, GLFW_KEY_X) == GLFW_PRESS) spaceshipPos += spaceshipSide * moveSpeed; if (glfwGetKey(window, GLFW_KEY_Z) == GLFW_PRESS) spaceshipPos -= spaceshipSide * moveSpeed; if (qState == GLFW_PRESS) spaceshipPos += spaceshipUp * moveSpeed; if (eState == GLFW_PRESS) spaceshipPos -= spaceshipUp * moveSpeed; if (aState == GLFW_PRESS) spaceshipDir = glm::vec3(glm::eulerAngleY(angleSpeed) * glm::vec4(spaceshipDir, 0)); if (dState == GLFW_PRESS) spaceshipDir = glm::vec3(glm::eulerAngleY(-angleSpeed) * glm::vec4(spaceshipDir, 0)); if (glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_LEFT) == GLFW_PRESS) requestShoot(time); cameraPos = spaceshipPos - calculateCameraDistanceHor(w, shiftState, deltaTime) * spaceshipDir + glm::vec3(0, calculateCameraDistanceVer(deltaTime), 0); cameraPosHUDBar = spaceshipPos - 1.f * spaceshipDir + glm::vec3(0, 1, 0) * 0.2f; cameraDir = spaceshipDir; glm::vec3 perpendicularVector = 0.08f * glm::normalize(glm::cross(spaceshipDir, glm::vec3(0.0f, 1.0f, 0.0f))); if (leftParticle != nullptr && rightParticle != nullptr) { leftParticle->sourcePosition = spaceshipPos + perpendicularVector - (0.25f * spaceshipDir); rightParticle->sourcePosition = spaceshipPos - perpendicularVector - (0.25f * spaceshipDir); leftParticle->sourceDirection = -spaceshipDir; rightParticle->sourceDirection = -spaceshipDir; } spotlightPos = spaceshipPos + 0.2 * spaceshipDir; spotlightConeDir = spaceshipDir; } void renderParticles(GLuint program, glm::mat4 view, glm::mat4 projection, float time) { if (leftParticle != nullptr && rightParticle != nullptr) { glm::mat4 modelSrc = additionalVerRotationMatrix * additionalHorRotationMatrix; leftParticle->drawParticles(program, view, projection, modelSrc, time); rightParticle->drawParticles(program, view, projection, modelSrc, time); } } void createParticles() { if (leftParticle != nullptr && rightParticle != nullptr) { delete leftParticle; delete rightParticle; } leftParticle = new ParticleSystem(); rightParticle = new ParticleSystem(); } glm::mat4 createCameraMatrix() { glm::vec3 cameraSide = glm::normalize(glm::cross(cameraDir, glm::vec3(0.f, 1.f, 0.f))); glm::vec3 cameraUp = glm::normalize(glm::cross(cameraSide, cameraDir)); glm::mat4 cameraRotrationMatrix = glm::mat4({ cameraSide.x,cameraSide.y,cameraSide.z,0, cameraUp.x,cameraUp.y,cameraUp.z ,0, -cameraDir.x,-cameraDir.y,-cameraDir.z,0, 0.,0.,0.,1., }); cameraRotrationMatrix = glm::transpose(cameraRotrationMatrix); glm::mat4 cameraMatrix = cameraRotrationMatrix * glm::translate(-cameraPos); return cameraMatrix; } void renderBullets(float time, GLuint program, std::vector& gameEntities) { for (auto it = bullets.begin(); it != bullets.end();) { Bullet* bullet = *it; if (bullet->shouldBeDestroyed(time, program, gameEntities, dmg)) { delete bullet; it = bullets.erase(it); } else { it++; } } } void requestShoot(float time) { if (canShoot(time)) { shoot(time); } } bool canShoot(float time) { return lastShootTime == 0 || time - lastShootTime > shootInterval; } void shoot(float time) { glm::vec3 perpendicularVector = 0.25f * glm::normalize(glm::cross(cameraDir, glm::vec3(0.0f, 1.0f, 0.0f))); glm::vec3 dir = glm::vec4(spaceshipDir.x, spaceshipDir.y, spaceshipDir.z, 1.f) * additionalVerRotationMatrix * additionalHorRotationMatrix; bullets.push_back(Bullet::createSimpleBullet(dir, spaceshipPos - perpendicularVector, time)); bullets.push_back(Bullet::createSimpleBullet(dir, spaceshipPos + perpendicularVector, time)); lastShootTime = time; } glm::vec3 getPosition() const override { return spaceshipPos; } glm::mat4 getModelMatrix() override { return calculateModelMatrix(); } glm::mat4 calculateModelMatrixForHUDBar() { glm::vec3 spaceshipSide = glm::normalize(glm::cross(spaceshipDir, glm::vec3(0.f, 1.f, 0.f))); glm::vec3 spaceshipUp = glm::normalize(glm::cross(spaceshipSide, spaceshipDir)); glm::mat4 spaceshipCameraRotationMatrix = glm::mat4({ spaceshipSide.x, spaceshipSide.y, spaceshipSide.z, 0, spaceshipUp.x, spaceshipUp.y, spaceshipUp.z, 0, -spaceshipDir.x, -spaceshipDir.y, -spaceshipDir.z, 0, 0., 0., 0., 1. }); return glm::translate(spaceshipPos) * spaceshipCameraRotationMatrix * glm::eulerAngleY(glm::pi()) * glm::scale(glm::vec3(0.02f)); } glm::mat4 createCameraMatrixForHUDBar() { glm::vec3 cameraSide = glm::normalize(glm::cross(cameraDir, glm::vec3(0.f, 1.f, 0.f))); glm::vec3 cameraUp = glm::normalize(glm::cross(cameraSide, cameraDir)); glm::mat4 cameraRotrationMatrix = glm::mat4({ cameraSide.x,cameraSide.y,cameraSide.z,0, cameraUp.x,cameraUp.y,cameraUp.z ,0, -cameraDir.x,-cameraDir.y,-cameraDir.z,0, 0.,0.,0.,1., }); cameraRotrationMatrix = glm::transpose(cameraRotrationMatrix); glm::mat4 cameraMatrix = cameraRotrationMatrix * glm::translate(-cameraPosHUDBar); return cameraMatrix; } void respawn() override { this->currentHP = this->maxHP; this->turbo = this->turboMAX; this->spaceshipPos = glm::vec3(4.065808f, 10.250000f, -20.189549f); return; } void heal() override { this->currentHP = this->currentHP + 3.f; } void turboBoost() { this->turbo = this->turboMAX; } };