Merge origin/main into camera2
This commit is contained in:
commit
1dcdf10d6a
BIN
resources/MainCharacter_Base_color_sRGB.png
(Stored with Git LFS)
Normal file
BIN
resources/MainCharacter_Base_color_sRGB.png
(Stored with Git LFS)
Normal file
Binary file not shown.
15
resources/config/explosion_config.json
Normal file
15
resources/config/explosion_config.json
Normal file
@ -0,0 +1,15 @@
|
||||
{
|
||||
"emissionPoints": [
|
||||
{ "position": [0.0, 0.0, 0.0] }
|
||||
],
|
||||
"texture": "resources/spark_white.png",
|
||||
"speedRange": [10.0, 30.0],
|
||||
"zSpeedRange": [-1.0, 1.0],
|
||||
"scaleRange": [0.5, 1.0],
|
||||
"lifeTimeRange": [200.0, 800.0],
|
||||
"emissionRate": 50.0,
|
||||
"maxParticles": 5,
|
||||
"particleSize": 0.5,
|
||||
"biasX": 0.1,
|
||||
"shaderProgramName": "default"
|
||||
}
|
||||
55
resources/config/game_over.json
Normal file
55
resources/config/game_over.json
Normal file
@ -0,0 +1,55 @@
|
||||
{
|
||||
"root": {
|
||||
"type": "LinearLayout",
|
||||
"orientation": "vertical",
|
||||
"align": "center",
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"width": 1920,
|
||||
"height": 1080,
|
||||
"background": {
|
||||
"color": [0, 0, 0, 0.7]
|
||||
},
|
||||
"children": [
|
||||
{
|
||||
"type": "Button",
|
||||
"name": "gameOverText",
|
||||
"x": 350,
|
||||
"y": 400,
|
||||
"width": 600,
|
||||
"height": 150,
|
||||
"textures": {
|
||||
"normal": "resources/gameover.png",
|
||||
"hover": "resources/gameover.png",
|
||||
"pressed": "resources/gameover.png"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "Button",
|
||||
"name": "restartButton",
|
||||
"x": 350,
|
||||
"y": 300,
|
||||
"width": 300,
|
||||
"height": 80,
|
||||
"textures": {
|
||||
"normal": "resources/shoot_normal.png",
|
||||
"hover": "resources/shoot_normal.png",
|
||||
"pressed": "resources/shoot_normal.png"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "Button",
|
||||
"name": "gameOverExitButton",
|
||||
"x": 650,
|
||||
"y": 300,
|
||||
"width": 300,
|
||||
"height": 80,
|
||||
"textures": {
|
||||
"normal": "resources/sand2.png",
|
||||
"hover": "resources/sand2.png",
|
||||
"pressed": "resources/sand2.png"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@ -27,7 +27,7 @@
|
||||
{
|
||||
"type": "Button",
|
||||
"name": "playButton",
|
||||
"x": 100,
|
||||
"x": -1000,
|
||||
"y": 500,
|
||||
"width": 200,
|
||||
"height": 50,
|
||||
@ -56,7 +56,7 @@
|
||||
{
|
||||
"type": "Button",
|
||||
"name": "settingsButton",
|
||||
"x": 100,
|
||||
"x": -1000,
|
||||
"y": 400,
|
||||
"width": 200,
|
||||
"height": 50,
|
||||
@ -89,7 +89,7 @@
|
||||
{
|
||||
"type": "Button",
|
||||
"name": "exitButton",
|
||||
"x": 100,
|
||||
"x": -1000,
|
||||
"y": 300,
|
||||
"width": 200,
|
||||
"height": 50,
|
||||
|
||||
BIN
resources/gameover.png
(Stored with Git LFS)
Normal file
BIN
resources/gameover.png
(Stored with Git LFS)
Normal file
Binary file not shown.
5337
resources/spaceshipnew001.txt
Normal file
5337
resources/spaceshipnew001.txt
Normal file
File diff suppressed because it is too large
Load Diff
@ -13,7 +13,8 @@ namespace ZL {
|
||||
int Environment::windowHeaderHeight = 0;
|
||||
int Environment::width = 0;
|
||||
int Environment::height = 0;
|
||||
float Environment::zoom = 18.f;
|
||||
float Environment::zoom = 36.f;
|
||||
|
||||
|
||||
bool Environment::leftPressed = false;
|
||||
bool Environment::rightPressed = false;
|
||||
|
||||
156
src/Game.cpp
156
src/Game.cpp
@ -23,6 +23,8 @@ namespace ZL
|
||||
|
||||
static bool g_exitBgAnimating = false;
|
||||
|
||||
float x = 0;
|
||||
|
||||
Eigen::Quaternionf generateRandomQuaternion(std::mt19937& gen)
|
||||
{
|
||||
|
||||
@ -107,6 +109,7 @@ namespace ZL
|
||||
, glContext(nullptr)
|
||||
, newTickCount(0)
|
||||
, lastTickCount(0)
|
||||
, planetObject(renderer, taskManager, mainThreadHandler)
|
||||
{
|
||||
projectiles.reserve(maxProjectiles);
|
||||
for (int i = 0; i < maxProjectiles; ++i) {
|
||||
@ -204,6 +207,8 @@ namespace ZL
|
||||
|
||||
bool cfgLoaded = sparkEmitter.loadFromJsonFile("resources/config/spark_config.json", renderer, CONST_ZIP_FILE);
|
||||
bool projCfgLoaded = projectileEmitter.loadFromJsonFile("resources/config/spark_projectile_config.json", renderer, CONST_ZIP_FILE);
|
||||
bool explosionCfgLoaded = explosionEmitter.loadFromJsonFile("resources/config/explosion_config.json", renderer, CONST_ZIP_FILE);
|
||||
explosionEmitter.setEmissionPoints(std::vector<Vector3f>());
|
||||
projectileEmitter.setEmissionPoints(std::vector<Vector3f>());
|
||||
uiManager.loadFromFile("resources/config/ui.json", renderer, CONST_ZIP_FILE);
|
||||
|
||||
@ -312,17 +317,22 @@ namespace ZL
|
||||
|
||||
|
||||
//Load texture
|
||||
spaceshipTexture = std::make_unique<Texture>(CreateTextureDataFromPng("resources/DefaultMaterial_BaseColor_shine.png", CONST_ZIP_FILE));
|
||||
spaceshipBase = LoadFromTextFile02("resources/spaceship006.txt", CONST_ZIP_FILE);
|
||||
spaceshipBase.RotateByMatrix(Eigen::Quaternionf(Eigen::AngleAxisf(M_PI / 2.0, Eigen::Vector3f::UnitY())).toRotationMatrix());// QuatFromRotateAroundY(M_PI / 2.0).toRotationMatrix());
|
||||
|
||||
//spaceshipTexture = std::make_unique<Texture>(CreateTextureDataFromPng("resources/DefaultMaterial_BaseColor_shine.png", CONST_ZIP_FILE));
|
||||
//spaceshipBase = LoadFromTextFile02("resources/spaceship006.txt", CONST_ZIP_FILE);
|
||||
//spaceshipBase.RotateByMatrix(Eigen::Quaternionf(Eigen::AngleAxisf(M_PI / 2.0, Eigen::Vector3f::UnitY())).toRotationMatrix());// QuatFromRotateAroundY(M_PI / 2.0).toRotationMatrix());
|
||||
|
||||
//spaceshipTexture = std::make_unique<Texture>(CreateTextureDataFromPng("./resources/cap_D.png", CONST_ZIP_FILE));
|
||||
//spaceshipBase = LoadFromTextFile02("./resources/spaceship006x.txt", CONST_ZIP_FILE);
|
||||
//spaceshipBase.RotateByMatrix(Eigen::Quaternionf(Eigen::AngleAxisf(-M_PI / 2.0, Eigen::Vector3f::UnitY())).toRotationMatrix());// QuatFromRotateAroundY(M_PI / 2.0).toRotationMatrix());
|
||||
|
||||
spaceshipTexture = std::make_unique<Texture>(CreateTextureDataFromPng("resources/MainCharacter_Base_color_sRGB.png", CONST_ZIP_FILE));
|
||||
spaceshipBase = LoadFromTextFile02("resources/spaceshipnew001.txt", CONST_ZIP_FILE);
|
||||
spaceshipBase.RotateByMatrix(Eigen::Quaternionf(Eigen::AngleAxisf(M_PI, Eigen::Vector3f::UnitY())).toRotationMatrix());// QuatFromRotateAroundY(M_PI / 2.0).toRotationMatrix());
|
||||
|
||||
//spaceshipBase.Move(Vector3f{ 1.2, 0, -5 });
|
||||
//spaceshipBase.Move(Vector3f{ -0.52998, -13, 0 });
|
||||
spaceshipBase.Move(Vector3f{ -0.52998, 0, 10 });
|
||||
spaceshipBase.Move(Vector3f{ -0.52998, 0, -10 });
|
||||
|
||||
//spaceshipBase.RotateByMatrix(Eigen::Quaternionf(Eigen::AngleAxisf(M_PI / 2.0, Eigen::Vector3f::UnitY())).toRotationMatrix());
|
||||
|
||||
@ -351,6 +361,7 @@ namespace ZL
|
||||
boxRenderArr[i].RefreshVBO();
|
||||
}
|
||||
|
||||
boxAlive.resize(boxCoordsArr.size(), true);
|
||||
|
||||
std::cout << "Init step 4 " << std::endl;
|
||||
|
||||
@ -367,8 +378,6 @@ namespace ZL
|
||||
std::cout << "Init step 6 " << std::endl;
|
||||
planetObject.init();
|
||||
|
||||
planetObject.taskManager = &taskManager;
|
||||
|
||||
std::cout << "Init step 7 " << std::endl;
|
||||
//rockTexture = std::make_unique<Texture>(CreateTextureDataFromPng("./resources/rock.png", CONST_ZIP_FILE));
|
||||
|
||||
@ -460,22 +469,39 @@ namespace ZL
|
||||
renderer.PushMatrix();
|
||||
renderer.LoadIdentity();
|
||||
renderer.TranslateMatrix({ 0,0, -1.0f * Environment::zoom });
|
||||
renderer.TranslateMatrix({ 0, -6.f, 0 }); //Ship camera offset
|
||||
|
||||
// Корабль рисуется с учётом разницы между его ориентацией и камерой
|
||||
// shipWorldOrientation - куда смотрит корабль в мире
|
||||
// Environment::inverseShipMatrix - обратная матрица камеры
|
||||
Matrix3f shipRelativeToCamera = Environment::inverseShipMatrix * shipWorldOrientation;
|
||||
renderer.RotateMatrix(shipRelativeToCamera);
|
||||
|
||||
renderer.TranslateMatrix({ 0, -Environment::zoom * 0.03f, 0 });
|
||||
renderer.RotateMatrix(rotateShipMat);
|
||||
glBindTexture(GL_TEXTURE_2D, spaceshipTexture->getTexID());
|
||||
renderer.DrawVertexRenderStruct(spaceship);
|
||||
if (shipAlive) {
|
||||
glBindTexture(GL_TEXTURE_2D, spaceshipTexture->getTexID());
|
||||
renderer.DrawVertexRenderStruct(spaceship);
|
||||
}
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
for (const auto& p : projectiles) {
|
||||
if (p && p->isActive()) {
|
||||
p->draw(renderer);
|
||||
}
|
||||
}
|
||||
|
||||
if (shipAlive) {
|
||||
renderer.PushMatrix();
|
||||
renderer.TranslateMatrix({ 0, 0, 16 });
|
||||
sparkEmitter.draw(renderer, Environment::zoom, Environment::width, Environment::height);
|
||||
renderer.PopMatrix();
|
||||
projectileEmitter.draw(renderer, Environment::zoom, Environment::width, Environment::height);
|
||||
}
|
||||
|
||||
if (showExplosion) {
|
||||
explosionEmitter.draw(renderer, Environment::zoom, Environment::width, Environment::height);
|
||||
}
|
||||
|
||||
sparkEmitter.draw(renderer, Environment::zoom, Environment::width, Environment::height);
|
||||
projectileEmitter.draw(renderer, Environment::zoom, Environment::width, Environment::height);
|
||||
glDisable(GL_BLEND);
|
||||
renderer.PopMatrix();
|
||||
renderer.PopProjectionMatrix();
|
||||
@ -505,6 +531,7 @@ namespace ZL
|
||||
|
||||
for (int i = 0; i < boxCoordsArr.size(); i++)
|
||||
{
|
||||
if (!boxAlive[i]) continue;
|
||||
renderer.PushMatrix();
|
||||
|
||||
renderer.LoadIdentity();
|
||||
@ -622,17 +649,16 @@ namespace ZL
|
||||
// Скорость пропорциональна отклонению джойстика
|
||||
Environment::shipVelocity = magnitude * 500.0f * static_cast<float>(delta) / 100.0f;
|
||||
|
||||
// Угол поворота корабля на основе направления джойстика
|
||||
// Направление джойстика относительно камеры
|
||||
// joyY отрицательный = вперёд, joyX = влево/вправо
|
||||
float angleY = std::atan2(-joyX, -joyY);
|
||||
|
||||
Eigen::Quaternionf q(Eigen::AngleAxisf(angleY, Eigen::Vector3f::UnitY()));
|
||||
rotateShipMat = q.toRotationMatrix();
|
||||
// Локальный поворот в пространстве камеры
|
||||
Eigen::Quaternionf localRotation(Eigen::AngleAxisf(angleY, Eigen::Vector3f::UnitY()));
|
||||
Matrix3f localRotMat = localRotation.toRotationMatrix();
|
||||
|
||||
if (!shipMoveLockActive) {
|
||||
lockedCameraMat = Environment::shipMatrix;
|
||||
shipMoveLockActive = true;
|
||||
}
|
||||
// Преобразуем в мировую ориентацию: камера * локальный_поворот
|
||||
shipWorldOrientation = Environment::shipMatrix * localRotMat;
|
||||
}
|
||||
else {
|
||||
Environment::shipVelocity = 0.0f;
|
||||
@ -668,11 +694,9 @@ namespace ZL
|
||||
|
||||
if (std::fabs(Environment::shipVelocity) > 0.01f)
|
||||
{
|
||||
Vector3f localMove = rotateShipMat * Vector3f{ 0, 0, -Environment::shipVelocity * static_cast<float>(delta) / 1000.f };
|
||||
|
||||
Matrix3f camMat = shipMoveLockActive ? lockedCameraMat : Environment::shipMatrix;
|
||||
|
||||
Vector3f worldMove = camMat * localMove;
|
||||
// Корабль двигается вперёд в направлении своей ориентации
|
||||
Vector3f localForward = Vector3f{ 0, 0, -1 };
|
||||
Vector3f worldMove = shipWorldOrientation * localForward * Environment::shipVelocity * static_cast<float>(delta) / 1000.f;
|
||||
|
||||
Environment::shipPosition = Environment::shipPosition + worldMove;
|
||||
}
|
||||
@ -712,6 +736,76 @@ namespace ZL
|
||||
sparkEmitter.update(static_cast<float>(delta));
|
||||
projectileEmitter.update(static_cast<float>(delta));
|
||||
|
||||
explosionEmitter.update(static_cast<float>(delta));
|
||||
if (shipAlive) {
|
||||
float distToSurface = planetObject.distanceToPlanetSurface(Environment::shipPosition);
|
||||
if (distToSurface <= 0.0f) {
|
||||
Vector3f localForward = { 0,0,-1 };
|
||||
Vector3f worldForward = (Environment::shipMatrix * localForward).normalized();
|
||||
const float backDistance = 400.0f;
|
||||
Environment::shipPosition = Environment::shipPosition - worldForward * backDistance;
|
||||
|
||||
shipAlive = false;
|
||||
gameOver = true;
|
||||
Environment::shipVelocity = 0.0f;
|
||||
showExplosion = true;
|
||||
|
||||
explosionEmitter.setUseWorldSpace(false);
|
||||
explosionEmitter.setEmissionPoints(std::vector<Vector3f>{ Vector3f{ 0.0f,0.0f,0.0f } });
|
||||
explosionEmitter.emit();
|
||||
|
||||
std::cerr << "GAME OVER: collision with planet (moved back and exploded)\n";
|
||||
|
||||
if (!uiGameOverShown) {
|
||||
if (uiManager.pushMenuFromFile("resources/config/game_over.json", this->renderer, CONST_ZIP_FILE)) {
|
||||
uiManager.setButtonCallback("restartButton", [this](const std::string& name) {
|
||||
this->shipAlive = true;
|
||||
this->gameOver = false;
|
||||
this->uiGameOverShown = false;
|
||||
this->showExplosion = false;
|
||||
this->explosionEmitter.setEmissionPoints(std::vector<Vector3f>());
|
||||
Environment::shipPosition = Vector3f{ 0, 0, 45000.f };
|
||||
Environment::shipVelocity = 0.0f;
|
||||
uiManager.popMenu();
|
||||
std::cerr << "Game restarted\n";
|
||||
});
|
||||
|
||||
uiManager.setButtonCallback("gameOverExitButton", [this](const std::string& name) {
|
||||
Environment::exitGameLoop = true;
|
||||
});
|
||||
|
||||
uiGameOverShown = true;
|
||||
}
|
||||
else {
|
||||
std::cerr << "Failed to load game_over.json\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < boxCoordsArr.size(); ++i) {
|
||||
if (!boxAlive[i]) continue;
|
||||
Vector3f boxWorld = boxCoordsArr[i].pos + Vector3f{ 0.0f, 0.0f, 45000.0f };
|
||||
Vector3f diff = Environment::shipPosition - boxWorld;
|
||||
float thresh = shipCollisionRadius + boxCollisionRadius;
|
||||
if (diff.squaredNorm() <= thresh * thresh) {
|
||||
boxAlive[i] = false;
|
||||
|
||||
boxRenderArr[i].data.PositionData.clear();
|
||||
boxRenderArr[i].vao.reset();
|
||||
boxRenderArr[i].positionVBO.reset();
|
||||
boxRenderArr[i].texCoordVBO.reset();
|
||||
showExplosion = true;
|
||||
|
||||
Vector3f rel = boxWorld - Environment::shipPosition;
|
||||
Vector3f camPos = Environment::inverseShipMatrix * rel;
|
||||
explosionEmitter.setUseWorldSpace(true);
|
||||
explosionEmitter.setEmissionPoints(std::vector<Vector3f>{ boxWorld });
|
||||
explosionEmitter.emit();
|
||||
|
||||
std::cerr << "Box destroyed at index " << i << std::endl;
|
||||
}
|
||||
}
|
||||
uiManager.update(static_cast<float>(delta));
|
||||
//#endif
|
||||
lastTickCount = newTickCount;
|
||||
@ -728,14 +822,13 @@ namespace ZL
|
||||
const float lifeMs = 5000.0f;
|
||||
const float size = 0.5f;
|
||||
|
||||
Vector3f localForward = { 0,0,-1 };
|
||||
Matrix3f camMat1 = shipMoveLockActive ? lockedCameraMat : Environment::shipMatrix;
|
||||
|
||||
Vector3f localForward1 = { 0,0,-1 };
|
||||
Vector3f worldForward = (camMat1 * (rotateShipMat * localForward1)).normalized();
|
||||
// Снаряды летят в направлении корабля (shipWorldOrientation)
|
||||
Vector3f localForward = { 0, 0, -1 };
|
||||
Vector3f worldForward = (shipWorldOrientation * localForward).normalized();
|
||||
|
||||
for (const auto& lo : localOffsets) {
|
||||
Vector3f worldPos = Environment::shipPosition + Environment::shipMatrix * lo;
|
||||
// Позиция снаряда относительно корабля
|
||||
Vector3f worldPos = Environment::shipPosition + shipWorldOrientation * lo;
|
||||
Vector3f worldVel = worldForward * (projectileSpeed + Environment::shipVelocity);
|
||||
|
||||
for (auto& p : projectiles) {
|
||||
@ -860,15 +953,18 @@ namespace ZL
|
||||
if (event.key.keysym.sym == SDLK_o)
|
||||
{
|
||||
Environment::shipVelocity += 50.f;
|
||||
//x = x + 2.0;
|
||||
}
|
||||
if (event.key.keysym.sym == SDLK_l)
|
||||
{
|
||||
Environment::shipVelocity -= 50.f;
|
||||
//x = x - 2.0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
render();
|
||||
mainThreadHandler.processMainThreadTasks();
|
||||
}
|
||||
|
||||
void Game::handleDown(int mx, int my)
|
||||
|
||||
51
src/Game.h
51
src/Game.h
@ -1,4 +1,4 @@
|
||||
#pragma once
|
||||
#pragma once
|
||||
|
||||
#include "render/Renderer.h"
|
||||
#include "Environment.h"
|
||||
@ -12,7 +12,7 @@
|
||||
|
||||
namespace ZL {
|
||||
|
||||
|
||||
|
||||
struct BoxCoords
|
||||
{
|
||||
Vector3f pos;
|
||||
@ -29,9 +29,11 @@ namespace ZL {
|
||||
void update();
|
||||
void render();
|
||||
|
||||
|
||||
bool shouldExit() const { return Environment::exitGameLoop; }
|
||||
|
||||
Renderer renderer;
|
||||
TaskManager taskManager;
|
||||
MainThreadHandler mainThreadHandler;
|
||||
private:
|
||||
void processTickCount();
|
||||
void drawScene();
|
||||
@ -48,42 +50,16 @@ namespace ZL {
|
||||
|
||||
SDL_Window* window;
|
||||
SDL_GLContext glContext;
|
||||
Renderer renderer;
|
||||
|
||||
|
||||
|
||||
size_t newTickCount;
|
||||
size_t lastTickCount;
|
||||
|
||||
//std::shared_ptr<Texture> rockTexture;
|
||||
|
||||
|
||||
|
||||
std::vector<BoxCoords> boxCoordsArr;
|
||||
std::vector<VertexRenderStruct> boxRenderArr;
|
||||
|
||||
|
||||
//std::shared_ptr<Texture> buttonTexture;
|
||||
//VertexRenderStruct button;
|
||||
|
||||
//std::shared_ptr<Texture> musicVolumeBarTexture;
|
||||
//VertexRenderStruct musicVolumeBar;
|
||||
|
||||
//std::shared_ptr<Texture> musicVolumeBarButtonTexture;
|
||||
//VertexRenderStruct musicVolumeBarButton;
|
||||
|
||||
|
||||
//bool isDraggingVolume = false;
|
||||
/*
|
||||
float velocitySlider = 0.0f;
|
||||
float volumeBarMinX = 1190.0f;
|
||||
float volumeBarMaxX = 1200.0f;
|
||||
float volumeBarMinY = 100.0f;
|
||||
float volumeBarMaxY = 600.0f;*/
|
||||
//float musicVolumeBarButtonButtonCenterX = 1195.0f;
|
||||
//float musicVolumeBarButtonButtonRadius = 25.0f;
|
||||
//void UpdateVolumeFromMouse(int mouseX, int mouseY);
|
||||
//void UpdateVolumeKnob();
|
||||
|
||||
|
||||
static const size_t CONST_TIMER_INTERVAL = 10;
|
||||
static const size_t CONST_MAX_TIME_INTERVAL = 1000;
|
||||
|
||||
@ -100,6 +76,7 @@ namespace ZL {
|
||||
|
||||
SparkEmitter sparkEmitter;
|
||||
SparkEmitter projectileEmitter;
|
||||
SparkEmitter explosionEmitter;
|
||||
PlanetObject planetObject;
|
||||
UiManager uiManager;
|
||||
|
||||
@ -110,14 +87,22 @@ namespace ZL {
|
||||
int maxProjectiles = 32;
|
||||
std::vector<Vector3f> shipLocalEmissionPoints;
|
||||
|
||||
TaskManager taskManager;
|
||||
|
||||
bool isDraggingShip = false;
|
||||
bool isDraggingCamera = false;
|
||||
Matrix3f rotateShipMat = Matrix3f::Identity();
|
||||
Matrix3f rotateShipMat = Matrix3f::Identity(); // Локальный поворот от джойстика
|
||||
Matrix3f shipWorldOrientation = Matrix3f::Identity(); // Ориентация корабля в мире (независимо от камеры)
|
||||
bool shipMoveLockActive = false;
|
||||
Matrix3f lockedCameraMat = Matrix3f::Identity();
|
||||
|
||||
|
||||
bool shipAlive = true;
|
||||
bool gameOver = false;
|
||||
std::vector<bool> boxAlive;
|
||||
float shipCollisionRadius = 3.5f;
|
||||
float boxCollisionRadius = 2.0f;
|
||||
bool uiGameOverShown = false;
|
||||
bool showExplosion = false;
|
||||
|
||||
};
|
||||
|
||||
|
||||
@ -13,10 +13,10 @@ namespace ZL {
|
||||
|
||||
using json = nlohmann::json;
|
||||
|
||||
|
||||
SparkEmitter::SparkEmitter()
|
||||
: emissionRate(100.0f), isActive(true), drawDataDirty(true), maxParticles(200),
|
||||
shaderProgramName("default"), particleSize(0.04f), biasX(0.3f), configured(false) {
|
||||
shaderProgramName("default"), particleSize(0.04f), biasX(0.3f), configured(false),
|
||||
useWorldSpace(false) {
|
||||
particles.resize(maxParticles);
|
||||
drawPositions.reserve(maxParticles * 6);
|
||||
drawTexCoords.reserve(maxParticles * 6);
|
||||
@ -28,7 +28,8 @@ namespace ZL {
|
||||
SparkEmitter::SparkEmitter(const std::vector<Vector3f>& positions, float rate)
|
||||
: emissionPoints(positions), emissionRate(rate), isActive(true),
|
||||
drawDataDirty(true), maxParticles(positions.size() * 100),
|
||||
shaderProgramName("default"), particleSize(0.04f), biasX(0.3f), configured(false) {
|
||||
shaderProgramName("default"), particleSize(0.04f), biasX(0.3f), configured(false),
|
||||
useWorldSpace(false) {
|
||||
particles.resize(maxParticles);
|
||||
drawPositions.reserve(maxParticles * 6);
|
||||
drawTexCoords.reserve(maxParticles * 6);
|
||||
@ -42,7 +43,8 @@ namespace ZL {
|
||||
float rate)
|
||||
: emissionPoints(positions), texture(tex), emissionRate(rate),
|
||||
isActive(true), drawDataDirty(true), maxParticles(positions.size() * 100),
|
||||
shaderProgramName("default"), particleSize(0.04f), biasX(0.3f), configured(false) {
|
||||
shaderProgramName("default"), particleSize(0.04f), biasX(0.3f), configured(false),
|
||||
useWorldSpace(false) {
|
||||
particles.resize(maxParticles);
|
||||
drawPositions.reserve(maxParticles * 6);
|
||||
drawTexCoords.reserve(maxParticles * 6);
|
||||
@ -71,7 +73,15 @@ namespace ZL {
|
||||
|
||||
for (const auto& particle : particles) {
|
||||
if (particle.active) {
|
||||
sortedParticles.push_back({ &particle, particle.position(2) });
|
||||
Vector3f posCam;
|
||||
if (useWorldSpace) {
|
||||
Vector3f rel = particle.position - Environment::shipPosition;
|
||||
posCam = Environment::inverseShipMatrix * rel;
|
||||
}
|
||||
else {
|
||||
posCam = particle.position;
|
||||
}
|
||||
sortedParticles.push_back({ &particle, posCam(2) });
|
||||
}
|
||||
}
|
||||
|
||||
@ -82,25 +92,33 @@ namespace ZL {
|
||||
|
||||
for (const auto& [particlePtr, depth] : sortedParticles) {
|
||||
const auto& particle = *particlePtr;
|
||||
Vector3f pos = particle.position;
|
||||
Vector3f posCam;
|
||||
if (useWorldSpace) {
|
||||
Vector3f rel = particle.position - Environment::shipPosition;
|
||||
posCam = Environment::inverseShipMatrix * rel;
|
||||
}
|
||||
else {
|
||||
posCam = particle.position;
|
||||
}
|
||||
|
||||
float size = particleSize * particle.scale;
|
||||
|
||||
drawPositions.push_back({ pos(0) - size, pos(1) - size, pos(2) });
|
||||
drawPositions.push_back({ posCam(0) - size, posCam(1) - size, posCam(2) });
|
||||
drawTexCoords.push_back({ 0.0f, 0.0f });
|
||||
|
||||
drawPositions.push_back({ pos(0) - size, pos(1) + size, pos(2) });
|
||||
drawPositions.push_back({ posCam(0) - size, posCam(1) + size, posCam(2) });
|
||||
drawTexCoords.push_back({ 0.0f, 1.0f });
|
||||
|
||||
drawPositions.push_back({ pos(0) + size, pos(1) + size, pos(2) });
|
||||
drawPositions.push_back({ posCam(0) + size, posCam(1) + size, posCam(2) });
|
||||
drawTexCoords.push_back({ 1.0f, 1.0f });
|
||||
|
||||
drawPositions.push_back({ pos(0) - size, pos(1) - size, pos(2) });
|
||||
drawPositions.push_back({ posCam(0) - size, posCam(1) - size, posCam(2) });
|
||||
drawTexCoords.push_back({ 0.0f, 0.0f });
|
||||
|
||||
drawPositions.push_back({ pos(0) + size, pos(1) + size, pos(2) });
|
||||
drawPositions.push_back({ posCam(0) + size, posCam(1) + size, posCam(2) });
|
||||
drawTexCoords.push_back({ 1.0f, 1.0f });
|
||||
|
||||
drawPositions.push_back({ pos(0) + size, pos(1) - size, pos(2) });
|
||||
drawPositions.push_back({ posCam(0) + size, posCam(1) - size, posCam(2) });
|
||||
drawTexCoords.push_back({ 1.0f, 0.0f });
|
||||
}
|
||||
|
||||
@ -139,8 +157,8 @@ namespace ZL {
|
||||
renderer.EnableVertexAttribArray(vPositionName);
|
||||
renderer.EnableVertexAttribArray(vTexCoordName);
|
||||
|
||||
float aspectRatio = static_cast<float>(screenWidth) / static_cast<float>(screenHeight);
|
||||
renderer.PushPerspectiveProjectionMatrix(1.0 / 1.5, aspectRatio, Environment::CONST_Z_NEAR, Environment::CONST_Z_FAR);
|
||||
//float aspectRatio = static_cast<float>(screenWidth) / static_cast<float>(screenHeight);
|
||||
//renderer.PushPerspectiveProjectionMatrix(1.0 / 1.5, aspectRatio, Environment::CONST_Z_NEAR, Environment::CONST_Z_FAR);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, texture->getTexID());
|
||||
|
||||
@ -148,13 +166,13 @@ namespace ZL {
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
|
||||
|
||||
renderer.PushMatrix();
|
||||
renderer.LoadIdentity();
|
||||
renderer.TranslateMatrix({ 0, 0, -1.0f * zoom });
|
||||
//renderer.LoadIdentity();
|
||||
//renderer.TranslateMatrix({ 0, 0, -1.0f * zoom });
|
||||
|
||||
renderer.DrawVertexRenderStruct(sparkQuad);
|
||||
|
||||
renderer.PopMatrix();
|
||||
renderer.PopProjectionMatrix();
|
||||
//renderer.PopProjectionMatrix();
|
||||
|
||||
glDisable(GL_BLEND);
|
||||
|
||||
|
||||
@ -51,6 +51,7 @@ namespace ZL {
|
||||
|
||||
bool configured;
|
||||
void prepareDrawData();
|
||||
bool useWorldSpace;
|
||||
|
||||
public:
|
||||
SparkEmitter();
|
||||
@ -67,6 +68,7 @@ namespace ZL {
|
||||
void setParticleSize(float size) { particleSize = size; }
|
||||
void setBiasX(float bias) { biasX = bias; }
|
||||
|
||||
void setUseWorldSpace(bool use) { useWorldSpace = use; }
|
||||
bool loadFromJsonFile(const std::string& path, Renderer& renderer, const std::string& zipFile = "");
|
||||
|
||||
void update(float deltaTimeMs);
|
||||
|
||||
@ -57,9 +57,11 @@ namespace ZL {
|
||||
return rot;
|
||||
}
|
||||
|
||||
PlanetObject::PlanetObject()
|
||||
PlanetObject::PlanetObject(Renderer& iRenderer, TaskManager& iTaskManager, MainThreadHandler& iMainThreadHandler)
|
||||
: renderer(iRenderer),
|
||||
taskManager(iTaskManager),
|
||||
mainThreadHandler(iMainThreadHandler)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void PlanetObject::init() {
|
||||
@ -101,7 +103,7 @@ namespace ZL {
|
||||
float movementThreshold = 1.0f;
|
||||
if ((Environment::shipPosition - lastUpdatePos).squaredNorm() < movementThreshold * movementThreshold
|
||||
&& !triangleIndicesToDraw.empty()) {
|
||||
processMainThreadTasks(); // Все равно обрабатываем очередь OpenGL задач
|
||||
//processMainThreadTasks(); // Все равно обрабатываем очередь OpenGL задач
|
||||
return;
|
||||
}
|
||||
lastUpdatePos = Environment::shipPosition;
|
||||
@ -117,13 +119,13 @@ namespace ZL {
|
||||
planetStones.statuses[triIdx] = ChunkStatus::Generating;
|
||||
|
||||
// Отправляем тяжелую математику в TaskManager
|
||||
taskManager->EnqueueBackgroundTask([this, triIdx]() {
|
||||
taskManager.EnqueueBackgroundTask([this, triIdx]() {
|
||||
// Выполняется в фоновом потоке: только генерация геометрии в RAM
|
||||
float scaleModifier = 1.0f;
|
||||
VertexDataStruct generatedData = planetStones.inflateOneDataOnly(triIdx, scaleModifier);
|
||||
|
||||
// Передаем задачу на загрузку в GPU в очередь главного потока
|
||||
this->EnqueueMainThreadTask([this, triIdx, data = std::move(generatedData)]() mutable {
|
||||
this->mainThreadHandler.EnqueueMainThreadTask([this, triIdx, data = std::move(generatedData)]() mutable {
|
||||
// Проверяем актуальность: если треугольник всё еще в списке видимых
|
||||
auto it = std::find(triangleIndicesToDraw.begin(), triangleIndicesToDraw.end(), triIdx);
|
||||
if (it != triangleIndicesToDraw.end()) {
|
||||
@ -164,22 +166,7 @@ namespace ZL {
|
||||
triangleIndicesToDraw = std::move(newIndices);
|
||||
|
||||
// 5. Выполняем одну задачу из очереди OpenGL (RefreshVBO и т.д.)
|
||||
processMainThreadTasks();
|
||||
/*
|
||||
float movementThreshold = 1.0f;
|
||||
if ((Environment::shipPosition - lastUpdatePos).squaredNorm() < movementThreshold * movementThreshold && !triangleIndicesToDraw.empty()) {
|
||||
return;
|
||||
}
|
||||
lastUpdatePos = Environment::shipPosition;
|
||||
|
||||
auto newIndices = planetData.getTrianglesUnderCameraNew2(Environment::shipPosition);
|
||||
|
||||
// Сортировка важна для сравнения векторов
|
||||
std::sort(newIndices.begin(), newIndices.end());
|
||||
|
||||
if (newIndices != triangleIndicesToDraw) {
|
||||
triangleIndicesToDraw = std::move(newIndices);
|
||||
}*/
|
||||
//processMainThreadTasks();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -21,6 +21,7 @@
|
||||
|
||||
namespace ZL {
|
||||
class TaskManager;
|
||||
class MainThreadHandler;
|
||||
|
||||
class PlanetObject {
|
||||
public:
|
||||
@ -42,10 +43,12 @@ namespace ZL {
|
||||
|
||||
Vector3f lastUpdatePos;
|
||||
|
||||
TaskManager* taskManager = nullptr;
|
||||
|
||||
// External items, set outside
|
||||
Renderer& renderer;
|
||||
TaskManager& taskManager;
|
||||
MainThreadHandler& mainThreadHandler;
|
||||
public:
|
||||
PlanetObject();
|
||||
PlanetObject(Renderer& iRenderer, TaskManager& iTaskManager, MainThreadHandler& iMainThreadHandler);
|
||||
|
||||
void init();
|
||||
void update(float deltaTimeMs);
|
||||
@ -56,32 +59,6 @@ namespace ZL {
|
||||
void drawAtmosphere(Renderer& renderer);
|
||||
|
||||
float distanceToPlanetSurface(const Vector3f& viewerPosition);
|
||||
|
||||
std::queue<std::function<void()>> mainThreadTasks;
|
||||
std::mutex mainThreadMutex;
|
||||
|
||||
void EnqueueMainThreadTask(std::function<void()> task) {
|
||||
std::lock_guard<std::mutex> lock(mainThreadMutex);
|
||||
mainThreadTasks.push(task);
|
||||
}
|
||||
|
||||
// Выполнение задач по одной (или пачкой) за кадр
|
||||
void processMainThreadTasks() {
|
||||
std::function<void()> task;
|
||||
|
||||
// Извлекаем только одну задачу, чтобы не блокировать update надолго
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mainThreadMutex);
|
||||
if (!mainThreadTasks.empty()) {
|
||||
task = std::move(mainThreadTasks.front());
|
||||
mainThreadTasks.pop();
|
||||
}
|
||||
}
|
||||
|
||||
if (task) {
|
||||
task(); // Здесь выполняется RefreshVBO или загрузка текстуры
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace ZL
|
||||
@ -0,0 +1,50 @@
|
||||
#include "TaskManager.h"
|
||||
|
||||
|
||||
namespace ZL
|
||||
{
|
||||
|
||||
TaskManager::TaskManager(size_t threadCount) {
|
||||
workGuard = std::make_unique<boost::asio::executor_work_guard<boost::asio::io_context::executor_type>>(ioContext.get_executor());
|
||||
|
||||
for (size_t i = 0; i < threadCount; ++i) {
|
||||
workers.emplace_back([this]() {
|
||||
ioContext.run();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void TaskManager::EnqueueBackgroundTask(std::function<void()> task) {
|
||||
boost::asio::post(ioContext, task);
|
||||
}
|
||||
|
||||
TaskManager::~TaskManager() {
|
||||
workGuard.reset(); // Ðàçðåøàåì ioContext.run() çàâåðøèòüñÿ, êîãäà çàäà÷ íå îñòàíåòñÿ
|
||||
ioContext.stop(); // Îïöèîíàëüíî: íåìåäëåííàÿ îñòàíîâêà
|
||||
for (auto& t : workers) {
|
||||
if (t.joinable()) t.join();
|
||||
}
|
||||
}
|
||||
|
||||
void MainThreadHandler::EnqueueMainThreadTask(std::function<void()> task) {
|
||||
std::lock_guard<std::mutex> lock(mainThreadMutex);
|
||||
mainThreadTasks.push(task);
|
||||
}
|
||||
|
||||
void MainThreadHandler::processMainThreadTasks() {
|
||||
std::function<void()> task;
|
||||
|
||||
// Èçâëåêàåì òîëüêî îäíó çàäà÷ó, ÷òîáû íå áëîêèðîâàòü update íàäîëãî
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mainThreadMutex);
|
||||
if (!mainThreadTasks.empty()) {
|
||||
task = std::move(mainThreadTasks.front());
|
||||
mainThreadTasks.pop();
|
||||
}
|
||||
}
|
||||
|
||||
if (task) {
|
||||
task(); // Çäåñü âûïîëíÿåòñÿ RefreshVBO èëè çàãðóçêà òåêñòóðû
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -4,6 +4,8 @@
|
||||
#include <vector>
|
||||
#include <thread>
|
||||
#include <memory>
|
||||
#include <queue>
|
||||
|
||||
|
||||
namespace ZL {
|
||||
|
||||
@ -14,30 +16,28 @@ namespace ZL {
|
||||
std::vector<std::thread> workers;
|
||||
|
||||
public:
|
||||
//TaskManager(size_t threadCount = std::thread::hardware_concurrency()) {
|
||||
TaskManager(size_t threadCount = 2) {
|
||||
workGuard = std::make_unique<boost::asio::executor_work_guard<boost::asio::io_context::executor_type>>(ioContext.get_executor());
|
||||
|
||||
for (size_t i = 0; i < threadCount; ++i) {
|
||||
workers.emplace_back([this]() {
|
||||
ioContext.run();
|
||||
});
|
||||
}
|
||||
}
|
||||
//TaskManager(size_t threadCount = std::thread::hardware_concurrency());
|
||||
TaskManager(size_t threadCount = 2);
|
||||
|
||||
// Ìåòîä äëÿ äîáàâëåíèÿ ôîíîâîé çàäà÷è
|
||||
void EnqueueBackgroundTask(std::function<void()> task) {
|
||||
boost::asio::post(ioContext, task);
|
||||
}
|
||||
void EnqueueBackgroundTask(std::function<void()> task);
|
||||
|
||||
// Graceful shutdown
|
||||
~TaskManager() {
|
||||
workGuard.reset(); // Ðàçðåøàåì ioContext.run() çàâåðøèòüñÿ, êîãäà çàäà÷ íå îñòàíåòñÿ
|
||||
ioContext.stop(); // Îïöèîíàëüíî: íåìåäëåííàÿ îñòàíîâêà
|
||||
for (auto& t : workers) {
|
||||
if (t.joinable()) t.join();
|
||||
}
|
||||
}
|
||||
~TaskManager();
|
||||
};
|
||||
|
||||
|
||||
class MainThreadHandler
|
||||
{
|
||||
private:
|
||||
std::queue<std::function<void()>> mainThreadTasks;
|
||||
std::mutex mainThreadMutex;
|
||||
|
||||
public:
|
||||
void EnqueueMainThreadTask(std::function<void()> task);
|
||||
|
||||
// Âûïîëíåíèå çàäà÷ ïî îäíîé (èëè ïà÷êîé) çà êàäð
|
||||
void processMainThreadTasks();
|
||||
};
|
||||
|
||||
} // namespace ZL
|
||||
Loading…
Reference in New Issue
Block a user