added npc
This commit is contained in:
parent
629c9ba7b1
commit
5df2216da6
@ -10,6 +10,7 @@ namespace ZL {
|
|||||||
|
|
||||||
void LocalClient::Connect(const std::string& host, uint16_t port) {
|
void LocalClient::Connect(const std::string& host, uint16_t port) {
|
||||||
generateBoxes();
|
generateBoxes();
|
||||||
|
initializeNPCs();
|
||||||
lastUpdateMs = std::chrono::duration_cast<std::chrono::milliseconds>(
|
lastUpdateMs = std::chrono::duration_cast<std::chrono::milliseconds>(
|
||||||
std::chrono::system_clock::now().time_since_epoch()).count();
|
std::chrono::system_clock::now().time_since_epoch()).count();
|
||||||
}
|
}
|
||||||
@ -64,8 +65,89 @@ namespace ZL {
|
|||||||
std::cout << "LocalClient: Generated " << serverBoxes.size() << " boxes\n";
|
std::cout << "LocalClient: Generated " << serverBoxes.size() << " boxes\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Eigen::Vector3f LocalClient::generateRandomPosition() {
|
||||||
|
std::random_device rd;
|
||||||
|
std::mt19937 gen(rd());
|
||||||
|
std::uniform_real_distribution<> distrib(-50.0, 50.0);
|
||||||
|
|
||||||
|
return Eigen::Vector3f(
|
||||||
|
(float)distrib(gen),
|
||||||
|
(float)distrib(gen),
|
||||||
|
(float)distrib(gen) + 45000.0f
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LocalClient::initializeNPCs() {
|
||||||
|
npcs.clear();
|
||||||
|
|
||||||
|
for (int i = 0; i < 3; ++i) {
|
||||||
|
LocalNPC npc;
|
||||||
|
npc.id = 100 + i;
|
||||||
|
npc.speed = 20.0f + (i * 5.0f);
|
||||||
|
npc.currentState.id = npc.id;
|
||||||
|
npc.currentState.position = generateRandomPosition();
|
||||||
|
npc.currentState.rotation = Eigen::Matrix3f::Identity();
|
||||||
|
npc.currentState.velocity = npc.speed;
|
||||||
|
npc.targetPosition = generateRandomPosition();
|
||||||
|
npc.lastStateUpdateMs = std::chrono::duration_cast<std::chrono::milliseconds>(
|
||||||
|
std::chrono::system_clock::now().time_since_epoch()).count();
|
||||||
|
|
||||||
|
npc.stateHistory.add_state(npc.currentState);
|
||||||
|
npcs.push_back(npc);
|
||||||
|
|
||||||
|
std::cout << "LocalClient: Created NPC with id=" << npc.id
|
||||||
|
<< " at pos (" << npc.currentState.position.x() << ", "
|
||||||
|
<< npc.currentState.position.y() << ", "
|
||||||
|
<< npc.currentState.position.z() << ")" << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void LocalClient::updateNPCs() {
|
||||||
|
auto now_ms = std::chrono::duration_cast<std::chrono::milliseconds>(
|
||||||
|
std::chrono::system_clock::now().time_since_epoch()).count();
|
||||||
|
|
||||||
|
for (auto& npc : npcs) {
|
||||||
|
uint64_t deltaMs = now_ms - npc.lastStateUpdateMs;
|
||||||
|
float dt = deltaMs / 1000.0f;
|
||||||
|
npc.lastStateUpdateMs = now_ms;
|
||||||
|
|
||||||
|
Eigen::Vector3f direction = npc.targetPosition - npc.currentState.position;
|
||||||
|
float distance = direction.norm();
|
||||||
|
|
||||||
|
if (distance < 5.0f) {
|
||||||
|
npc.targetPosition = generateRandomPosition();
|
||||||
|
direction = npc.targetPosition - npc.currentState.position;
|
||||||
|
distance = direction.norm();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (distance > 0.001f) {
|
||||||
|
direction.normalize();
|
||||||
|
npc.currentState.position += direction * npc.speed * dt;
|
||||||
|
npc.currentState.velocity = npc.speed;
|
||||||
|
|
||||||
|
Eigen::Vector3f localForward(0.0f, 0.0f, -1.0f);
|
||||||
|
Eigen::Vector3f worldForward = direction;
|
||||||
|
|
||||||
|
Eigen::Vector3f cross = localForward.cross(worldForward);
|
||||||
|
float dot = localForward.dot(worldForward);
|
||||||
|
|
||||||
|
if (cross.norm() > 0.001f) {
|
||||||
|
float angle = std::atan2(cross.norm(), dot);
|
||||||
|
cross.normalize();
|
||||||
|
Eigen::AngleAxisf aa(angle * 0.05f, cross);
|
||||||
|
npc.currentState.rotation = npc.currentState.rotation * aa.toRotationMatrix();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
npc.currentState.lastUpdateServerTime = std::chrono::system_clock::time_point(
|
||||||
|
std::chrono::milliseconds(now_ms));
|
||||||
|
npc.stateHistory.add_state(npc.currentState);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void LocalClient::Poll() {
|
void LocalClient::Poll() {
|
||||||
updatePhysics();
|
updatePhysics();
|
||||||
|
updateNPCs();
|
||||||
checkCollisions();
|
checkCollisions();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -198,7 +280,7 @@ namespace ZL {
|
|||||||
tokens.push_back(token);
|
tokens.push_back(token);
|
||||||
}
|
}
|
||||||
return tokens;
|
return tokens;
|
||||||
}(message, ':');
|
}(message, ':');
|
||||||
|
|
||||||
if (parts.empty()) return;
|
if (parts.empty()) return;
|
||||||
|
|
||||||
@ -265,6 +347,14 @@ namespace ZL {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::unordered_map<int, ClientStateInterval> LocalClient::getRemotePlayers() {
|
||||||
|
std::unordered_map<int, ClientStateInterval> result;
|
||||||
|
for (const auto& npc : npcs) {
|
||||||
|
result[npc.id] = npc.stateHistory;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<std::pair<Eigen::Vector3f, Eigen::Matrix3f>> LocalClient::getServerBoxes() {
|
std::vector<std::pair<Eigen::Vector3f, Eigen::Matrix3f>> LocalClient::getServerBoxes() {
|
||||||
std::vector<std::pair<Eigen::Vector3f, Eigen::Matrix3f>> result;
|
std::vector<std::pair<Eigen::Vector3f, Eigen::Matrix3f>> result;
|
||||||
for (const auto& box : serverBoxes) {
|
for (const auto& box : serverBoxes) {
|
||||||
|
|||||||
@ -9,67 +9,79 @@
|
|||||||
|
|
||||||
namespace ZL {
|
namespace ZL {
|
||||||
|
|
||||||
struct LocalServerBox {
|
struct LocalServerBox {
|
||||||
Eigen::Vector3f position;
|
Eigen::Vector3f position;
|
||||||
Eigen::Matrix3f rotation;
|
Eigen::Matrix3f rotation;
|
||||||
float collisionRadius = 2.0f;
|
float collisionRadius = 2.0f;
|
||||||
bool destroyed = false;
|
bool destroyed = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct LocalProjectile {
|
struct LocalProjectile {
|
||||||
int shooterId = -1;
|
int shooterId = -1;
|
||||||
uint64_t spawnMs = 0;
|
uint64_t spawnMs = 0;
|
||||||
Eigen::Vector3f pos;
|
Eigen::Vector3f pos;
|
||||||
Eigen::Vector3f vel;
|
Eigen::Vector3f vel;
|
||||||
float lifeMs = 5000.0f;
|
float lifeMs = 5000.0f;
|
||||||
};
|
};
|
||||||
|
|
||||||
class LocalClient : public INetworkClient {
|
struct LocalNPC {
|
||||||
private:
|
int id = -1;
|
||||||
std::queue<std::string> messageQueue;
|
ClientState currentState;
|
||||||
std::vector<LocalServerBox> serverBoxes;
|
ClientStateInterval stateHistory;
|
||||||
std::vector<LocalProjectile> projectiles;
|
Eigen::Vector3f targetPosition;
|
||||||
std::vector<ProjectileInfo> pendingProjectiles;
|
float speed = 30.0f;
|
||||||
std::vector<DeathInfo> pendingDeaths;
|
uint64_t lastStateUpdateMs = 0;
|
||||||
std::vector<BoxDestroyedInfo> pendingBoxDestructions;
|
};
|
||||||
std::vector<int> pendingRespawns;
|
|
||||||
|
|
||||||
uint64_t lastUpdateMs = 0;
|
class LocalClient : public INetworkClient {
|
||||||
ClientState localPlayerState;
|
private:
|
||||||
bool hasLocalPlayerState = false;
|
std::queue<std::string> messageQueue;
|
||||||
|
std::vector<LocalServerBox> serverBoxes;
|
||||||
|
std::vector<LocalProjectile> projectiles;
|
||||||
|
std::vector<ProjectileInfo> pendingProjectiles;
|
||||||
|
std::vector<DeathInfo> pendingDeaths;
|
||||||
|
std::vector<BoxDestroyedInfo> pendingBoxDestructions;
|
||||||
|
std::vector<int> pendingRespawns;
|
||||||
|
|
||||||
void updatePhysics();
|
uint64_t lastUpdateMs = 0;
|
||||||
void checkCollisions();
|
ClientState localPlayerState;
|
||||||
void generateBoxes();
|
bool hasLocalPlayerState = false;
|
||||||
|
|
||||||
public:
|
std::vector<LocalNPC> npcs;
|
||||||
void Connect(const std::string& host, uint16_t port) override;
|
|
||||||
|
|
||||||
void Poll() override;
|
void updatePhysics();
|
||||||
|
void checkCollisions();
|
||||||
|
void generateBoxes();
|
||||||
|
void initializeNPCs();
|
||||||
|
void updateNPCs();
|
||||||
|
Eigen::Vector3f generateRandomPosition();
|
||||||
|
|
||||||
void Send(const std::string& message) override;
|
public:
|
||||||
|
void Connect(const std::string& host, uint16_t port) override;
|
||||||
|
|
||||||
bool IsConnected() const override { return true; }
|
void Poll() override;
|
||||||
int GetClientId() const override { return 1; }
|
|
||||||
std::vector<ProjectileInfo> getPendingProjectiles() override;
|
|
||||||
|
|
||||||
std::unordered_map<int, ClientStateInterval> getRemotePlayers() override {
|
void Send(const std::string& message) override;
|
||||||
return std::unordered_map<int, ClientStateInterval>();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<std::pair<Eigen::Vector3f, Eigen::Matrix3f>> getServerBoxes() override;
|
bool IsConnected() const override { return true; }
|
||||||
|
int GetClientId() const override { return 1; }
|
||||||
|
std::vector<ProjectileInfo> getPendingProjectiles() override;
|
||||||
|
|
||||||
std::vector<DeathInfo> getPendingDeaths() override;
|
std::unordered_map<int, ClientStateInterval> getRemotePlayers() override;
|
||||||
|
|
||||||
std::vector<int> getPendingRespawns() override {
|
std::vector<std::pair<Eigen::Vector3f, Eigen::Matrix3f>> getServerBoxes() override;
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<BoxDestroyedInfo> getPendingBoxDestructions() override;
|
std::vector<DeathInfo> getPendingDeaths() override;
|
||||||
|
|
||||||
void setLocalPlayerState(const ClientState& state) {
|
std::vector<int> getPendingRespawns() override {
|
||||||
localPlayerState = state;
|
return {};
|
||||||
hasLocalPlayerState = true;
|
}
|
||||||
}
|
|
||||||
};
|
std::vector<BoxDestroyedInfo> getPendingBoxDestructions() override;
|
||||||
|
|
||||||
|
void setLocalPlayerState(const ClientState& state) {
|
||||||
|
localPlayerState = state;
|
||||||
|
hasLocalPlayerState = true;
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
Loading…
Reference in New Issue
Block a user