Working on web version
This commit is contained in:
parent
2ffd8124f2
commit
22ee99418d
@ -141,9 +141,9 @@
|
||||
"type": "Slider",
|
||||
"name": "velocitySlider",
|
||||
"x": 1140,
|
||||
"y": 100,
|
||||
"y": 300,
|
||||
"width": 50,
|
||||
"height": 500,
|
||||
"height": 300,
|
||||
"value": 0.0,
|
||||
"orientation": "vertical",
|
||||
"textures": {
|
||||
@ -164,6 +164,19 @@
|
||||
"pressed": "resources/shoot_pressed.png"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "Button",
|
||||
"name": "shootButton2",
|
||||
"x": 1000,
|
||||
"y": 100,
|
||||
"width": 100,
|
||||
"height": 100,
|
||||
"textures": {
|
||||
"normal": "resources/shoot_normal.png",
|
||||
"hover": "resources/shoot_hover.png",
|
||||
"pressed": "resources/shoot_pressed.png"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "TextView",
|
||||
"name": "velocityText",
|
||||
|
||||
BIN
resources/sky/space_red.png
(Stored with Git LFS)
Normal file
BIN
resources/sky/space_red.png
(Stored with Git LFS)
Normal file
Binary file not shown.
@ -41,6 +41,42 @@ std::vector<std::string> split(const std::string& s, char delimiter) {
|
||||
return tokens;
|
||||
}
|
||||
|
||||
// Вспомогательная функция для проверки столкновения снаряда с объектом-сферой
|
||||
bool checkSegmentSphereCollision(
|
||||
int x,
|
||||
const Eigen::Vector3f& pStart,
|
||||
const Eigen::Vector3f& pEnd,
|
||||
const Eigen::Vector3f& targetCenter,
|
||||
float combinedRadius)
|
||||
{
|
||||
Eigen::Vector3f segment = pEnd - pStart;
|
||||
Eigen::Vector3f toTarget = targetCenter - pStart;
|
||||
|
||||
float segmentLenSq = segment.squaredNorm();
|
||||
if (segmentLenSq < 1e-6f) {
|
||||
return toTarget.norm() <= combinedRadius;
|
||||
}
|
||||
|
||||
// Находим проекцию точки targetCenter на прямую, содержащую отрезок
|
||||
// t — это нормализованный параметр вдоль отрезка (от 0 до 1)
|
||||
float t = toTarget.dot(segment) / segmentLenSq;
|
||||
|
||||
// Ограничиваем t, чтобы найти ближайшую точку именно на ОТРЕЗКЕ
|
||||
t = std::max(0.0f, std::min(1.0f, t));
|
||||
|
||||
// Ближайшая точка на отрезке к центру цели
|
||||
Eigen::Vector3f closestPoint = pStart + t * segment;
|
||||
/*
|
||||
std::cout << "Collision for box: " << x << " pStart: " << pStart
|
||||
<< " pEnd: " << pEnd
|
||||
<< " targetCenter: " << targetCenter
|
||||
<< " closestPoint: " << closestPoint
|
||||
<< " t: " << t << std::endl;
|
||||
*/
|
||||
// Проверяем расстояние от ближайшей точки до центра цели
|
||||
return (targetCenter - closestPoint).squaredNorm() <= (combinedRadius * combinedRadius);
|
||||
}
|
||||
|
||||
struct ServerBox {
|
||||
Eigen::Vector3f position;
|
||||
Eigen::Matrix3f rotation;
|
||||
@ -63,9 +99,6 @@ struct BoxDestroyedInfo {
|
||||
int destroyedBy = -1;
|
||||
};
|
||||
|
||||
std::vector<BoxDestroyedInfo> g_boxDestructions;
|
||||
std::mutex g_boxDestructions_mutex;
|
||||
|
||||
std::vector<ServerBox> g_serverBoxes;
|
||||
std::mutex g_boxes_mutex;
|
||||
|
||||
@ -152,20 +185,6 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
/*
|
||||
void init() {
|
||||
sendBoxesToClient();
|
||||
|
||||
auto timer = std::make_shared<net::steady_timer>(ws_.get_executor());
|
||||
timer->expires_after(std::chrono::milliseconds(100));
|
||||
timer->async_wait([self = shared_from_this(), timer](const boost::system::error_code& ec) {
|
||||
if (!ec) {
|
||||
self->send_message("ID:" + std::to_string(self->id_));
|
||||
self->do_read();
|
||||
}
|
||||
});
|
||||
}
|
||||
*/
|
||||
|
||||
void sendBoxesToClient() {
|
||||
std::lock_guard<std::mutex> lock(g_boxes_mutex);
|
||||
@ -189,10 +208,6 @@ private:
|
||||
|
||||
|
||||
public:
|
||||
/*
|
||||
explicit Session(tcp::socket&& socket, int id)
|
||||
: ws_(std::move(socket)), id_(id) {
|
||||
}*/
|
||||
|
||||
void init()
|
||||
{
|
||||
@ -209,31 +224,7 @@ public:
|
||||
}
|
||||
});
|
||||
}
|
||||
/*
|
||||
void run() {
|
||||
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(g_sessions_mutex);
|
||||
g_sessions.push_back(shared_from_this());
|
||||
}
|
||||
|
||||
ws_.async_accept([self = shared_from_this()](beast::error_code ec) {
|
||||
if (ec) return;
|
||||
std::cout << "Client " << self->id_ << " connected\n";
|
||||
self->init();
|
||||
// self->send_message("ID:" + std::to_string(self->id_));
|
||||
// self->do_read();
|
||||
});
|
||||
}*/
|
||||
|
||||
/*void send_message(std::string msg) {
|
||||
auto ss = std::make_shared<std::string>(std::move(msg));
|
||||
ws_.async_write(net::buffer(*ss), [ss](beast::error_code, std::size_t) {});
|
||||
}
|
||||
|
||||
int get_id() const {
|
||||
return id_;
|
||||
}*/
|
||||
|
||||
ClientState get_latest_state(std::chrono::system_clock::time_point now) {
|
||||
if (timedClientStates.timedStates.empty()) {
|
||||
@ -250,30 +241,6 @@ public:
|
||||
|
||||
return latest;
|
||||
}
|
||||
/*
|
||||
void send_message(std::string msg) {
|
||||
auto ss = std::make_shared<std::string>(std::move(msg));
|
||||
|
||||
if (is_writing_) {
|
||||
|
||||
ws_.async_write(net::buffer(*ss),
|
||||
[self = shared_from_this(), ss](beast::error_code ec, std::size_t) {
|
||||
if (ec) {
|
||||
std::cerr << "Write error: " << ec.message() << std::endl;
|
||||
}
|
||||
});
|
||||
}
|
||||
else {
|
||||
is_writing_ = true;
|
||||
ws_.async_write(net::buffer(*ss),
|
||||
[self = shared_from_this(), ss](beast::error_code ec, std::size_t) {
|
||||
self->is_writing_ = false;
|
||||
if (ec) {
|
||||
std::cerr << "Write error: " << ec.message() << std::endl;
|
||||
}
|
||||
});
|
||||
}
|
||||
}*/
|
||||
|
||||
void doWrite() {
|
||||
std::lock_guard<std::mutex> lock(writeMutex_);
|
||||
@ -460,240 +427,61 @@ void broadcastToAll(const std::string& message) {
|
||||
}
|
||||
}
|
||||
|
||||
void update_world(net::steady_timer& timer, net::io_context& ioc) {
|
||||
|
||||
static auto last_snapshot_time = std::chrono::steady_clock::now();
|
||||
auto now = std::chrono::steady_clock::now();
|
||||
/*static uint64_t lastTickCount = 0;
|
||||
|
||||
if (lastTickCount == 0) {
|
||||
//lastTickCount = SDL_GetTicks64();
|
||||
lastTickCount = std::chrono::duration_cast<std::chrono::milliseconds>(
|
||||
std::chrono::system_clock::now().time_since_epoch()
|
||||
).count();
|
||||
|
||||
lastTickCount = (lastTickCount / 50) * 50;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
auto newTickCount = std::chrono::duration_cast<std::chrono::milliseconds>(
|
||||
std::chrono::system_clock::now().time_since_epoch()
|
||||
).count();
|
||||
|
||||
newTickCount = (newTickCount / 50) * 50;
|
||||
|
||||
int64_t deltaMs = static_cast<int64_t>(newTickCount - lastTickCount);
|
||||
|
||||
std::chrono::system_clock::time_point nowRounded = std::chrono::system_clock::time_point(std::chrono::milliseconds(newTickCount));
|
||||
*/
|
||||
// For each player
|
||||
// Get letest state + add time (until newTickCount)
|
||||
// Calculate if collisions with boxes
|
||||
|
||||
|
||||
|
||||
|
||||
// Рассылка Snapshot раз в 1000мс
|
||||
/*
|
||||
if (std::chrono::duration_cast<std::chrono::milliseconds>(now - last_snapshot_time).count() >= 1000) {
|
||||
last_snapshot_time = now;
|
||||
|
||||
auto system_now = std::chrono::system_clock::now();
|
||||
|
||||
std::string snapshot_msg = "SNAPSHOT:" + std::to_string(
|
||||
std::chrono::duration_cast<std::chrono::milliseconds>(
|
||||
system_now.time_since_epoch()).count()
|
||||
);
|
||||
|
||||
std::lock_guard<std::mutex> lock(g_sessions_mutex);
|
||||
|
||||
// Формируем общую строку состояний всех игроков
|
||||
for (auto& session : g_sessions) {
|
||||
ClientState st = session->get_latest_state(system_now);
|
||||
snapshot_msg += "|" + std::to_string(session->get_id()) + ":" + st.formPingMessageContent();
|
||||
}
|
||||
|
||||
for (auto& session : g_sessions) {
|
||||
session->send_message(snapshot_msg);
|
||||
}
|
||||
}*/
|
||||
|
||||
const std::chrono::milliseconds interval(50);
|
||||
timer.expires_after(interval);
|
||||
|
||||
timer.async_wait([&](const boost::system::error_code& ec) {
|
||||
if (ec) return;
|
||||
|
||||
auto now = std::chrono::system_clock::now();
|
||||
uint64_t now_ms = static_cast<uint64_t>(std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch()).count());
|
||||
|
||||
std::vector<DeathInfo> deathEvents;
|
||||
|
||||
{
|
||||
std::lock_guard<std::mutex> pl(g_projectiles_mutex);
|
||||
std::vector<int> indicesToRemove;
|
||||
|
||||
float dt = 50.0f / 1000.0f;
|
||||
|
||||
for (size_t i = 0; i < g_projectiles.size(); ++i) {
|
||||
auto& pr = g_projectiles[i];
|
||||
|
||||
pr.pos += pr.vel * dt;
|
||||
|
||||
if (now_ms > pr.spawnMs + static_cast<uint64_t>(pr.lifeMs)) {
|
||||
indicesToRemove.push_back(static_cast<int>(i));
|
||||
continue;
|
||||
}
|
||||
|
||||
bool hitDetected = false;
|
||||
|
||||
{
|
||||
std::lock_guard<std::mutex> lm(g_sessions_mutex);
|
||||
std::lock_guard<std::mutex> gd(g_dead_mutex);
|
||||
|
||||
for (auto& session : g_sessions) {
|
||||
int targetId = session->get_id();
|
||||
|
||||
if (targetId == pr.shooterId) continue;
|
||||
if (g_dead_players.find(targetId) != g_dead_players.end()) continue;
|
||||
|
||||
ClientState targetState;
|
||||
if (!session->fetchStateAtTime(now, targetState)) continue;
|
||||
|
||||
Eigen::Vector3f diff = pr.pos - targetState.position;
|
||||
const float shipRadius = 15.0f;
|
||||
const float projectileRadius = 1.5f;
|
||||
float combinedRadius = shipRadius + projectileRadius;
|
||||
|
||||
if (diff.squaredNorm() <= combinedRadius * combinedRadius) {
|
||||
DeathInfo death;
|
||||
death.targetId = targetId;
|
||||
death.serverTime = now_ms;
|
||||
death.position = pr.pos;
|
||||
death.killerId = pr.shooterId;
|
||||
|
||||
deathEvents.push_back(death);
|
||||
g_dead_players.insert(targetId);
|
||||
indicesToRemove.push_back(static_cast<int>(i));
|
||||
hitDetected = true;
|
||||
|
||||
std::cout << "Server: *** HIT DETECTED! ***" << std::endl;
|
||||
std::cout << "Server: Projectile at ("
|
||||
<< pr.pos.x() << ", " << pr.pos.y() << ", " << pr.pos.z()
|
||||
<< ") hit player " << targetId << std::endl;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (hitDetected) continue;
|
||||
}
|
||||
|
||||
if (!indicesToRemove.empty()) {
|
||||
std::sort(indicesToRemove.rbegin(), indicesToRemove.rend());
|
||||
for (int idx : indicesToRemove) {
|
||||
if (idx >= 0 && idx < (int)g_projectiles.size()) {
|
||||
g_projectiles.erase(g_projectiles.begin() + idx);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
std::lock_guard<std::mutex> bm(g_boxes_mutex);
|
||||
const float projectileHitRadius = 1.5f;
|
||||
const float boxCollisionRadius = 2.0f;
|
||||
|
||||
std::vector<std::pair<size_t, size_t>> boxProjectileCollisions;
|
||||
|
||||
for (size_t bi = 0; bi < g_serverBoxes.size(); ++bi) {
|
||||
if (g_serverBoxes[bi].destroyed) continue;
|
||||
|
||||
Eigen::Vector3f boxWorld = g_serverBoxes[bi].position + Eigen::Vector3f(0.0f, 6.0f, 45000.0f);
|
||||
|
||||
for (size_t pi = 0; pi < g_projectiles.size(); ++pi) {
|
||||
const auto& pr = g_projectiles[pi];
|
||||
Eigen::Vector3f diff = pr.pos - boxWorld;
|
||||
float thresh = boxCollisionRadius + projectileHitRadius;
|
||||
|
||||
if (diff.squaredNorm() <= thresh * thresh) {
|
||||
boxProjectileCollisions.push_back({ bi, pi });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto& [boxIdx, projIdx] : boxProjectileCollisions) {
|
||||
g_serverBoxes[boxIdx].destroyed = true;
|
||||
|
||||
Eigen::Vector3f boxWorld = g_serverBoxes[boxIdx].position + Eigen::Vector3f(0.0f, 0.0f, 45000.0f);
|
||||
|
||||
BoxDestroyedInfo destruction;
|
||||
destruction.boxIndex = static_cast<int>(boxIdx);
|
||||
destruction.serverTime = now_ms;
|
||||
destruction.position = boxWorld;
|
||||
destruction.destroyedBy = g_projectiles[projIdx].shooterId;
|
||||
|
||||
{
|
||||
std::lock_guard<std::mutex> dm(g_boxDestructions_mutex);
|
||||
g_boxDestructions.push_back(destruction);
|
||||
}
|
||||
|
||||
std::cout << "Server: Box " << boxIdx << " destroyed by projectile from player "
|
||||
<< g_projectiles[projIdx].shooterId << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
std::lock_guard<std::mutex> bm(g_boxes_mutex);
|
||||
std::lock_guard<std::mutex> lm(g_sessions_mutex);
|
||||
void checkShipBoxCollisions(std::chrono::system_clock::time_point now, uint64_t now_ms, std::vector<BoxDestroyedInfo>& boxDestructions) {
|
||||
// Внимание: Мьютексы g_boxes_mutex и g_sessions_mutex должны быть захвачены
|
||||
// внешним кодом в update_world перед вызовом этой функции.
|
||||
|
||||
const float shipCollisionRadius = 15.0f;
|
||||
const float boxCollisionRadius = 2.0f;
|
||||
const float thresh = shipCollisionRadius + boxCollisionRadius;
|
||||
const float threshSq = thresh * thresh;
|
||||
|
||||
for (size_t bi = 0; bi < g_serverBoxes.size(); ++bi) {
|
||||
if (g_serverBoxes[bi].destroyed) continue;
|
||||
|
||||
// Центр ящика в мировых координатах
|
||||
Eigen::Vector3f boxWorld = g_serverBoxes[bi].position + Eigen::Vector3f(0.0f, 0.0f, 45000.0f);
|
||||
|
||||
for (auto& session : g_sessions) {
|
||||
int playerId = session->get_id();
|
||||
|
||||
// Пропускаем мертвых игроков
|
||||
{
|
||||
std::lock_guard<std::mutex> gd(g_dead_mutex);
|
||||
if (g_dead_players.find(session->get_id()) != g_dead_players.end()) {
|
||||
continue;
|
||||
}
|
||||
// Если g_dead_mutex не захвачен глобально в update_world, раскомментируйте:
|
||||
// std::lock_guard<std::mutex> gd(g_dead_mutex);
|
||||
if (g_dead_players.count(playerId)) continue;
|
||||
}
|
||||
|
||||
ClientState shipState;
|
||||
// Получаем состояние игрока на текущий момент времени сервера
|
||||
if (!session->fetchStateAtTime(now, shipState)) continue;
|
||||
|
||||
Eigen::Vector3f diff = shipState.position - boxWorld;
|
||||
float thresh = shipCollisionRadius + boxCollisionRadius;
|
||||
|
||||
if (diff.squaredNorm() <= thresh * thresh) {
|
||||
// Проверка столкновения сфер
|
||||
if (diff.squaredNorm() <= threshSq) {
|
||||
g_serverBoxes[bi].destroyed = true;
|
||||
|
||||
// Регистрируем уничтожение ящика
|
||||
BoxDestroyedInfo destruction;
|
||||
destruction.boxIndex = static_cast<int>(bi);
|
||||
destruction.serverTime = now_ms;
|
||||
destruction.position = boxWorld;
|
||||
destruction.destroyedBy = session->get_id();
|
||||
destruction.destroyedBy = playerId;
|
||||
|
||||
{
|
||||
std::lock_guard<std::mutex> dm(g_boxDestructions_mutex);
|
||||
g_boxDestructions.push_back(destruction);
|
||||
}
|
||||
boxDestructions.push_back(destruction);
|
||||
|
||||
std::cout << "Server: Box " << bi << " destroyed by ship collision with player "
|
||||
<< session->get_id() << std::endl;
|
||||
std::cout << "Server: Box " << bi << " smashed by player " << playerId << std::endl;
|
||||
|
||||
// Один ящик не может быть уничтожен дважды за один проход
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!deathEvents.empty()) {
|
||||
void dispatchEvents(const std::vector<DeathInfo>& deathEvents, const std::vector<BoxDestroyedInfo>& boxDestructions) {
|
||||
// 1. Рассылка событий смерти игроков
|
||||
for (const auto& death : deathEvents) {
|
||||
std::string deadMsg = "DEAD:" +
|
||||
std::to_string(death.serverTime) + ":" +
|
||||
@ -708,11 +496,10 @@ void update_world(net::steady_timer& timer, net::io_context& ioc) {
|
||||
std::cout << "Server: Sent DEAD event - Player " << death.targetId
|
||||
<< " killed by " << death.killerId << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
std::lock_guard<std::mutex> dm(g_boxDestructions_mutex);
|
||||
for (const auto& destruction : g_boxDestructions) {
|
||||
// 2. Рассылка событий разрушения ящиков
|
||||
|
||||
for (const auto& destruction : boxDestructions) {
|
||||
std::string boxMsg = "BOX_DESTROYED:" +
|
||||
std::to_string(destruction.boxIndex) + ":" +
|
||||
std::to_string(destruction.serverTime) + ":" +
|
||||
@ -722,11 +509,105 @@ void update_world(net::steady_timer& timer, net::io_context& ioc) {
|
||||
std::to_string(destruction.destroyedBy);
|
||||
|
||||
broadcastToAll(boxMsg);
|
||||
std::cout << "Server: Broadcasted BOX_DESTROYED for box " << destruction.boxIndex << std::endl;
|
||||
|
||||
std::cout << "Server: Broadcasted BOX_DESTROYED for box "
|
||||
<< destruction.boxIndex << std::endl;
|
||||
}
|
||||
g_boxDestructions.clear();
|
||||
}
|
||||
|
||||
void update_world(net::steady_timer& timer, net::io_context& ioc) {
|
||||
const std::chrono::milliseconds interval(50);
|
||||
timer.expires_after(interval);
|
||||
|
||||
timer.async_wait([&](const boost::system::error_code& ec) {
|
||||
if (ec) return;
|
||||
|
||||
auto now = std::chrono::system_clock::now();
|
||||
uint64_t now_ms = std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch()).count();
|
||||
float dt = 50.0f / 1000.0f;
|
||||
|
||||
std::vector<DeathInfo> deathEvents;
|
||||
std::vector<BoxDestroyedInfo> boxDestructions;
|
||||
std::vector<int> projectilesToRemove;
|
||||
|
||||
{
|
||||
// Захватываем необходимые данные под мьютексами один раз
|
||||
std::lock_guard<std::mutex> pl(g_projectiles_mutex);
|
||||
std::lock_guard<std::mutex> bm(g_boxes_mutex);
|
||||
std::lock_guard<std::mutex> sm(g_sessions_mutex);
|
||||
std::lock_guard<std::mutex> gm(g_dead_mutex);
|
||||
|
||||
for (size_t i = 0; i < g_projectiles.size(); ++i) {
|
||||
auto& pr = g_projectiles[i];
|
||||
Eigen::Vector3f oldPos = pr.pos;
|
||||
pr.pos += pr.vel * dt;
|
||||
Eigen::Vector3f newPos = pr.pos;
|
||||
|
||||
// 1. Проверка времени жизни снаряда
|
||||
if (now_ms > pr.spawnMs + static_cast<uint64_t>(pr.lifeMs)) {
|
||||
projectilesToRemove.push_back(static_cast<int>(i));
|
||||
continue;
|
||||
}
|
||||
|
||||
bool hitDetected = false;
|
||||
|
||||
// 2. Проверка коллизий снаряда с игроками (Ray-cast)
|
||||
for (auto& session : g_sessions) {
|
||||
int targetId = session->get_id();
|
||||
if (targetId == pr.shooterId || g_dead_players.count(targetId)) continue;
|
||||
|
||||
ClientState targetState;
|
||||
if (!session->fetchStateAtTime(now, targetState)) continue;
|
||||
|
||||
if (checkSegmentSphereCollision(0, oldPos, newPos, targetState.position, 15.0f + 1.5f)) {
|
||||
deathEvents.push_back({ targetId, now_ms, newPos, pr.shooterId });
|
||||
g_dead_players.insert(targetId);
|
||||
hitDetected = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (hitDetected) {
|
||||
projectilesToRemove.push_back(static_cast<int>(i));
|
||||
continue;
|
||||
}
|
||||
|
||||
// 3. Проверка коллизий снаряда с ящиками (Ray-cast)
|
||||
for (size_t bi = 0; bi < g_serverBoxes.size(); ++bi) {
|
||||
if (g_serverBoxes[bi].destroyed) continue;
|
||||
|
||||
// Центр ящика с учетом смещения мира
|
||||
Eigen::Vector3f boxWorld = g_serverBoxes[bi].position + Eigen::Vector3f(0.0f, 0.0f, 45000.0f);
|
||||
|
||||
if (checkSegmentSphereCollision(bi, oldPos, newPos, boxWorld, 2.0f + 1.5f)) {
|
||||
g_serverBoxes[bi].destroyed = true;
|
||||
|
||||
boxDestructions.push_back({ static_cast<int>(bi), now_ms, boxWorld, pr.shooterId });
|
||||
|
||||
hitDetected = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (hitDetected) {
|
||||
projectilesToRemove.push_back(static_cast<int>(i));
|
||||
}
|
||||
}
|
||||
|
||||
// Удаляем отработавшие снаряды (с конца)
|
||||
std::sort(projectilesToRemove.rbegin(), projectilesToRemove.rend());
|
||||
for (int idx : projectilesToRemove) {
|
||||
g_projectiles.erase(g_projectiles.begin() + idx);
|
||||
}
|
||||
}
|
||||
|
||||
// 4. Отдельная проверка столкновения кораблей с ящиками (Point-Sphere)
|
||||
// Эту логику оставляем отдельно, так как она не привязана к снарядам
|
||||
checkShipBoxCollisions(now, now_ms, boxDestructions);
|
||||
|
||||
// Рассылка событий
|
||||
dispatchEvents(deathEvents, boxDestructions);
|
||||
|
||||
update_world(timer, ioc);
|
||||
});
|
||||
}
|
||||
|
||||
28
src/Game.cpp
28
src/Game.cpp
@ -30,8 +30,8 @@ namespace ZL
|
||||
#ifdef EMSCRIPTEN
|
||||
const char* CONST_ZIP_FILE = "resources.zip";
|
||||
#else
|
||||
const char* CONST_ZIP_FILE = "C:\\Work\\Projects\\space-game001\\resources.zip";
|
||||
//const char* CONST_ZIP_FILE = "";
|
||||
//const char* CONST_ZIP_FILE = "C:\\Work\\Projects\\space-game001\\resources.zip";
|
||||
const char* CONST_ZIP_FILE = "";
|
||||
#endif
|
||||
|
||||
static bool g_exitBgAnimating = false;
|
||||
@ -366,9 +366,16 @@ namespace ZL
|
||||
uiManager.setButtonCallback("shootButton", [this](const std::string& name) {
|
||||
firePressed = true;
|
||||
});
|
||||
|
||||
uiManager.setButtonCallback("shootButton2", [this](const std::string& name) {
|
||||
firePressed = true;
|
||||
});
|
||||
uiManager.setSliderCallback("velocitySlider", [this](const std::string& name, float value) {
|
||||
int newVel = roundf(value * 10);
|
||||
if (newVel > 2)
|
||||
{
|
||||
newVel = 2;
|
||||
}
|
||||
|
||||
if (newVel != Environment::shipState.selectedVelocity) {
|
||||
newShipVelocity = newVel;
|
||||
}
|
||||
@ -390,12 +397,12 @@ namespace ZL
|
||||
|
||||
cubemapTexture = std::make_shared<Texture>(
|
||||
std::array<TextureDataStruct, 6>{
|
||||
CreateTextureDataFromPng("resources/sky/space1.png", CONST_ZIP_FILE),
|
||||
CreateTextureDataFromPng("resources/sky/space1.png", CONST_ZIP_FILE),
|
||||
CreateTextureDataFromPng("resources/sky/space1.png", CONST_ZIP_FILE),
|
||||
CreateTextureDataFromPng("resources/sky/space1.png", CONST_ZIP_FILE),
|
||||
CreateTextureDataFromPng("resources/sky/space1.png", CONST_ZIP_FILE),
|
||||
CreateTextureDataFromPng("resources/sky/space1.png", CONST_ZIP_FILE)
|
||||
CreateTextureDataFromPng("resources/sky/space_red.png", CONST_ZIP_FILE),
|
||||
CreateTextureDataFromPng("resources/sky/space_red.png", CONST_ZIP_FILE),
|
||||
CreateTextureDataFromPng("resources/sky/space_red.png", CONST_ZIP_FILE),
|
||||
CreateTextureDataFromPng("resources/sky/space_red.png", CONST_ZIP_FILE),
|
||||
CreateTextureDataFromPng("resources/sky/space_red.png", CONST_ZIP_FILE),
|
||||
CreateTextureDataFromPng("resources/sky/space_red.png", CONST_ZIP_FILE)
|
||||
});
|
||||
|
||||
|
||||
@ -703,11 +710,12 @@ namespace ZL
|
||||
{
|
||||
glClear(GL_DEPTH_BUFFER_BIT);
|
||||
}
|
||||
drawShip();
|
||||
|
||||
drawRemoteShips();
|
||||
drawRemoteShipsLabels();
|
||||
drawBoxes();
|
||||
drawBoxesLabels();
|
||||
drawShip();
|
||||
|
||||
drawUI();
|
||||
CheckGlError();
|
||||
|
||||
@ -291,7 +291,7 @@ namespace ZL {
|
||||
|
||||
drawPlanet(renderer);
|
||||
drawStones(renderer);
|
||||
drawCamp(renderer);
|
||||
//drawCamp(renderer);
|
||||
glClear(GL_DEPTH_BUFFER_BIT);
|
||||
drawAtmosphere(renderer);
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user