added projectile
This commit is contained in:
parent
d57112be35
commit
ff3946a019
@ -442,6 +442,8 @@ add_executable(space-game001
|
|||||||
PlanetObject.h
|
PlanetObject.h
|
||||||
UiManager.cpp
|
UiManager.cpp
|
||||||
UiManager.h
|
UiManager.h
|
||||||
|
Projectile.h
|
||||||
|
Projectile.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
# Установка проекта по умолчанию для Visual Studio
|
# Установка проекта по умолчанию для Visual Studio
|
||||||
|
|||||||
91
Game.cpp
91
Game.cpp
@ -123,11 +123,10 @@ namespace ZL
|
|||||||
, newTickCount(0)
|
, newTickCount(0)
|
||||||
, lastTickCount(0)
|
, lastTickCount(0)
|
||||||
{
|
{
|
||||||
std::vector<Vector3f> emissionPoints = {
|
projectiles.reserve(maxProjectiles);
|
||||||
Vector3f{-2.1f, 0.9f, 5.0f},
|
for (int i = 0; i < maxProjectiles; ++i) {
|
||||||
Vector3f{2.1f, 0.9f, 5.0f}
|
projectiles.emplace_back(std::make_unique<Projectile>());
|
||||||
};
|
}
|
||||||
sparkEmitter = SparkEmitter(emissionPoints, 100.0f);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Game::~Game() {
|
Game::~Game() {
|
||||||
@ -163,6 +162,8 @@ namespace ZL
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
bool cfgLoaded = sparkEmitter.loadFromJsonFile("../config/spark_config.json", renderer, CONST_ZIP_FILE);
|
bool cfgLoaded = sparkEmitter.loadFromJsonFile("../config/spark_config.json", renderer, CONST_ZIP_FILE);
|
||||||
|
bool projCfgLoaded = projectileEmitter.loadFromJsonFile("../config/spark_projectile_config.json", renderer, CONST_ZIP_FILE);
|
||||||
|
projectileEmitter.setEmissionPoints(std::vector<Vector3f>());
|
||||||
uiManager.loadFromFile("../config/ui.json", renderer, CONST_ZIP_FILE);
|
uiManager.loadFromFile("../config/ui.json", renderer, CONST_ZIP_FILE);
|
||||||
|
|
||||||
uiManager.setButtonCallback("playButton", [this](const std::string& name) {
|
uiManager.setButtonCallback("playButton", [this](const std::string& name) {
|
||||||
@ -364,10 +365,18 @@ namespace ZL
|
|||||||
renderer.LoadIdentity();
|
renderer.LoadIdentity();
|
||||||
renderer.TranslateMatrix({ 0,0, -1.0f * Environment::zoom });
|
renderer.TranslateMatrix({ 0,0, -1.0f * Environment::zoom });
|
||||||
|
|
||||||
|
renderer.TranslateMatrix({ 0, -Environment::zoom * 0.03f, 0 });
|
||||||
glBindTexture(GL_TEXTURE_2D, spaceshipTexture->getTexID());
|
glBindTexture(GL_TEXTURE_2D, spaceshipTexture->getTexID());
|
||||||
renderer.DrawVertexRenderStruct(spaceship);
|
renderer.DrawVertexRenderStruct(spaceship);
|
||||||
|
|
||||||
|
for (const auto& p : projectiles) {
|
||||||
|
if (p && p->isActive()) {
|
||||||
|
p->draw(renderer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
sparkEmitter.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);
|
||||||
|
|
||||||
renderer.PopMatrix();
|
renderer.PopMatrix();
|
||||||
renderer.PopProjectionMatrix();
|
renderer.PopProjectionMatrix();
|
||||||
@ -584,14 +593,74 @@ namespace ZL
|
|||||||
{
|
{
|
||||||
Vector3f velocityDirection = { 0,0, -Environment::shipVelocity * delta / 1000.f };
|
Vector3f velocityDirection = { 0,0, -Environment::shipVelocity * delta / 1000.f };
|
||||||
Vector3f velocityDirectionAdjusted = MultMatrixVector(Environment::shipMatrix, velocityDirection);
|
Vector3f velocityDirectionAdjusted = MultMatrixVector(Environment::shipMatrix, velocityDirection);
|
||||||
|
|
||||||
Environment::shipPosition = Environment::shipPosition + velocityDirectionAdjusted;
|
Environment::shipPosition = Environment::shipPosition + velocityDirectionAdjusted;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (auto& p : projectiles) {
|
||||||
|
if (p && p->isActive()) {
|
||||||
|
p->update(static_cast<float>(delta), renderer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<Vector3f> projCameraPoints;
|
||||||
|
for (const auto& p : projectiles) {
|
||||||
|
if (p && p->isActive()) {
|
||||||
|
Vector3f worldPos = p->getPosition();
|
||||||
|
Vector3f rel = worldPos - Environment::shipPosition;
|
||||||
|
Vector3f camPos = MultMatrixVector(Environment::inverseShipMatrix, rel);
|
||||||
|
projCameraPoints.push_back(camPos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!projCameraPoints.empty()) {
|
||||||
|
projectileEmitter.setEmissionPoints(projCameraPoints);
|
||||||
|
projectileEmitter.emit();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
projectileEmitter.setEmissionPoints(std::vector<Vector3f>());
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<Vector3f> shipCameraPoints;
|
||||||
|
for (const auto& lp : shipLocalEmissionPoints) {
|
||||||
|
Vector3f adjusted = lp + Vector3f{ 0.0f, -Environment::zoom * 0.03f, 0.0f };
|
||||||
|
shipCameraPoints.push_back(adjusted);
|
||||||
|
}
|
||||||
|
if (!shipCameraPoints.empty()) {
|
||||||
|
sparkEmitter.setEmissionPoints(shipCameraPoints);
|
||||||
|
}
|
||||||
|
|
||||||
|
sparkEmitter.update(static_cast<float>(delta));
|
||||||
|
projectileEmitter.update(static_cast<float>(delta));
|
||||||
|
|
||||||
lastTickCount = newTickCount;
|
lastTickCount = newTickCount;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Game::fireProjectiles() {
|
||||||
|
std::vector<Vector3f> localOffsets = {
|
||||||
|
Vector3f{ -1.5f, 0.9f, 5.0f },
|
||||||
|
Vector3f{ 1.5f, 0.9f, 5.0f }
|
||||||
|
};
|
||||||
|
|
||||||
|
const float projectileSpeed = 60.0f;
|
||||||
|
const float lifeMs = 5000.0f;
|
||||||
|
const float size = 0.5f;
|
||||||
|
|
||||||
|
Vector3f localForward = { 0,0,-1 };
|
||||||
|
Vector3f worldForward = MultMatrixVector(Environment::shipMatrix, localForward).normalized();
|
||||||
|
|
||||||
|
for (const auto& lo : localOffsets) {
|
||||||
|
Vector3f worldPos = Environment::shipPosition + MultMatrixVector(Environment::shipMatrix, lo);
|
||||||
|
Vector3f worldVel = worldForward * projectileSpeed;
|
||||||
|
|
||||||
|
for (auto& p : projectiles) {
|
||||||
|
if (!p->isActive()) {
|
||||||
|
p->init(worldPos, worldVel, lifeMs, size, projectileTexture, renderer);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Game::render() {
|
void Game::render() {
|
||||||
SDL_GL_MakeCurrent(ZL::Environment::window, glContext);
|
SDL_GL_MakeCurrent(ZL::Environment::window, glContext);
|
||||||
ZL::CheckGlError();
|
ZL::CheckGlError();
|
||||||
@ -622,6 +691,14 @@ namespace ZL
|
|||||||
|
|
||||||
bool uiHandled = false;
|
bool uiHandled = false;
|
||||||
|
|
||||||
|
if (event.button.button == SDL_BUTTON_LEFT && !uiManager.isUiInteraction()) {
|
||||||
|
uint64_t now = SDL_GetTicks64();
|
||||||
|
if (now - lastProjectileFireTime >= static_cast<uint64_t>(projectileCooldownMs)) {
|
||||||
|
lastProjectileFireTime = now;
|
||||||
|
fireProjectiles();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (const auto& button : uiManager.findButton("") ? std::vector<std::shared_ptr<UiButton>>{} : std::vector<std::shared_ptr<UiButton>>{}) {
|
for (const auto& button : uiManager.findButton("") ? std::vector<std::shared_ptr<UiButton>>{} : std::vector<std::shared_ptr<UiButton>>{}) {
|
||||||
(void)button;
|
(void)button;
|
||||||
}
|
}
|
||||||
|
|||||||
11
Game.h
11
Game.h
@ -7,6 +7,7 @@
|
|||||||
#include "SparkEmitter.h"
|
#include "SparkEmitter.h"
|
||||||
#include "PlanetObject.h"
|
#include "PlanetObject.h"
|
||||||
#include "UiManager.h"
|
#include "UiManager.h"
|
||||||
|
#include "Projectile.h"
|
||||||
|
|
||||||
namespace ZL {
|
namespace ZL {
|
||||||
|
|
||||||
@ -38,6 +39,8 @@ namespace ZL {
|
|||||||
void drawBoxes();
|
void drawBoxes();
|
||||||
void drawUI();
|
void drawUI();
|
||||||
|
|
||||||
|
void fireProjectiles();
|
||||||
|
|
||||||
SDL_Window* window;
|
SDL_Window* window;
|
||||||
SDL_GLContext glContext;
|
SDL_GLContext glContext;
|
||||||
Renderer renderer;
|
Renderer renderer;
|
||||||
@ -88,8 +91,16 @@ namespace ZL {
|
|||||||
VertexDataStruct boxBase;
|
VertexDataStruct boxBase;
|
||||||
|
|
||||||
SparkEmitter sparkEmitter;
|
SparkEmitter sparkEmitter;
|
||||||
|
SparkEmitter projectileEmitter;
|
||||||
PlanetObject planetObject;
|
PlanetObject planetObject;
|
||||||
UiManager uiManager;
|
UiManager uiManager;
|
||||||
|
|
||||||
|
std::vector<std::unique_ptr<Projectile>> projectiles;
|
||||||
|
std::shared_ptr<Texture> projectileTexture;
|
||||||
|
float projectileCooldownMs = 500.0f;
|
||||||
|
uint64_t lastProjectileFireTime = 0;
|
||||||
|
int maxProjectiles = 32;
|
||||||
|
std::vector<Vector3f> shipLocalEmissionPoints;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
71
Projectile.cpp
Normal file
71
Projectile.cpp
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
#include "Projectile.h"
|
||||||
|
|
||||||
|
namespace ZL {
|
||||||
|
|
||||||
|
Projectile::Projectile()
|
||||||
|
: pos({ 0,0,0 })
|
||||||
|
, vel({ 0,0,0 })
|
||||||
|
, life(0.0f)
|
||||||
|
, maxLife(0.0f)
|
||||||
|
, active(false)
|
||||||
|
, size(0.5f)
|
||||||
|
, texture(nullptr)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void Projectile::init(const Vector3f& startPos, const Vector3f& startVel, float lifeMs, float s, std::shared_ptr<Texture> tex, Renderer& renderer) {
|
||||||
|
pos = startPos;
|
||||||
|
vel = startVel;
|
||||||
|
life = 0.0f;
|
||||||
|
maxLife = lifeMs;
|
||||||
|
size = s;
|
||||||
|
texture = tex;
|
||||||
|
active = true;
|
||||||
|
|
||||||
|
rebuildMesh(renderer);
|
||||||
|
mesh.RefreshVBO();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Projectile::update(float deltaMs, Renderer& renderer) {
|
||||||
|
if (!active) return;
|
||||||
|
|
||||||
|
pos = pos + vel * (deltaMs / 1000.0f);
|
||||||
|
life += deltaMs;
|
||||||
|
if (life >= maxLife) {
|
||||||
|
active = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
rebuildMesh(renderer);
|
||||||
|
mesh.RefreshVBO();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Projectile::rebuildMesh(Renderer&) {
|
||||||
|
float half = size * 0.5f;
|
||||||
|
|
||||||
|
mesh.data.PositionData.clear();
|
||||||
|
mesh.data.TexCoordData.clear();
|
||||||
|
|
||||||
|
mesh.data.PositionData.push_back({ pos.v[0] - half, pos.v[1] - half, pos.v[2] });
|
||||||
|
mesh.data.PositionData.push_back({ pos.v[0] - half, pos.v[1] + half, pos.v[2] });
|
||||||
|
mesh.data.PositionData.push_back({ pos.v[0] + half, pos.v[1] + half, pos.v[2] });
|
||||||
|
|
||||||
|
mesh.data.PositionData.push_back({ pos.v[0] - half, pos.v[1] - half, pos.v[2] });
|
||||||
|
mesh.data.PositionData.push_back({ pos.v[0] + half, pos.v[1] + half, pos.v[2] });
|
||||||
|
mesh.data.PositionData.push_back({ pos.v[0] + half, pos.v[1] - half, pos.v[2] });
|
||||||
|
|
||||||
|
mesh.data.TexCoordData.push_back({ 0.0f, 0.0f });
|
||||||
|
mesh.data.TexCoordData.push_back({ 0.0f, 1.0f });
|
||||||
|
mesh.data.TexCoordData.push_back({ 1.0f, 1.0f });
|
||||||
|
mesh.data.TexCoordData.push_back({ 0.0f, 0.0f });
|
||||||
|
mesh.data.TexCoordData.push_back({ 1.0f, 1.0f });
|
||||||
|
mesh.data.TexCoordData.push_back({ 1.0f, 0.0f });
|
||||||
|
}
|
||||||
|
|
||||||
|
void Projectile::draw(Renderer& renderer) const {
|
||||||
|
if (!active || !texture) return;
|
||||||
|
glBindTexture(GL_TEXTURE_2D, texture->getTexID());
|
||||||
|
renderer.DrawVertexRenderStruct(mesh);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace ZL
|
||||||
36
Projectile.h
Normal file
36
Projectile.h
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "ZLMath.h"
|
||||||
|
#include "Renderer.h"
|
||||||
|
#include "TextureManager.h"
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
namespace ZL {
|
||||||
|
|
||||||
|
class Projectile {
|
||||||
|
public:
|
||||||
|
Projectile();
|
||||||
|
~Projectile() = default;
|
||||||
|
|
||||||
|
void init(const Vector3f& startPos, const Vector3f& startVel, float lifeMs, float size, std::shared_ptr<Texture> tex, Renderer& renderer);
|
||||||
|
void update(float deltaMs, Renderer& renderer);
|
||||||
|
void draw(Renderer& renderer) const;
|
||||||
|
|
||||||
|
bool isActive() const { return active; }
|
||||||
|
|
||||||
|
Vector3f getPosition() const { return pos; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
Vector3f pos;
|
||||||
|
Vector3f vel;
|
||||||
|
float life;
|
||||||
|
float maxLife;
|
||||||
|
bool active;
|
||||||
|
float size;
|
||||||
|
VertexRenderStruct mesh;
|
||||||
|
std::shared_ptr<Texture> texture;
|
||||||
|
|
||||||
|
void rebuildMesh(Renderer& renderer);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace ZL
|
||||||
@ -5,10 +5,10 @@
|
|||||||
"biasX": 0.3,
|
"biasX": 0.3,
|
||||||
"emissionPoints": [
|
"emissionPoints": [
|
||||||
{
|
{
|
||||||
"position": [-2.1, 0.9, 5.0]
|
"position": [-2.1, 0.4, 5.0]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"position": [2.1, 0.9, 5.0]
|
"position": [2.1, 0.4, 5.0]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"speedRange": [0.5, 2.0],
|
"speedRange": [0.5, 2.0],
|
||||||
|
|||||||
15
config/spark_projectile_config.json
Normal file
15
config/spark_projectile_config.json
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
{
|
||||||
|
"emissionPoints": [
|
||||||
|
{ "position": [0.0, 0.0, 0.0] }
|
||||||
|
],
|
||||||
|
"texture": "./resources/sand.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": 10,
|
||||||
|
"particleSize": 0.09,
|
||||||
|
"biasX": 0.1,
|
||||||
|
"shaderProgramName": "default"
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user