buf fixed
This commit is contained in:
+57
-6
@@ -101,6 +101,7 @@ Engine::Engine()
|
|||||||
rendersystem = new RenderSystem();
|
rendersystem = new RenderSystem();
|
||||||
rendersystem->Initialize();
|
rendersystem->Initialize();
|
||||||
physicsengine = new Physics();
|
physicsengine = new Physics();
|
||||||
|
physicsengine->gravity *= 1.25f; // slightly stronger gravity to suit the larger map
|
||||||
mainf = new Folder();
|
mainf = new Folder();
|
||||||
camera = new Camera();
|
camera = new Camera();
|
||||||
camera->t.TranslateTo({ 0.0f, 5.0f, 0.0f });
|
camera->t.TranslateTo({ 0.0f, 5.0f, 0.0f });
|
||||||
@@ -248,6 +249,29 @@ void Engine::Initiate()
|
|||||||
crosshair->Dot = true;
|
crosshair->Dot = true;
|
||||||
crosshair->Apply();
|
crosshair->Apply();
|
||||||
|
|
||||||
|
// Hit marker: an X around the crosshair built from small squares (Box has no rotation),
|
||||||
|
// white for a normal hit and red for a headshot / kill. Fades out after each hit.
|
||||||
|
std::vector<Box*> hitMarker;
|
||||||
|
for (int corner = 0; corner < 4; ++corner) {
|
||||||
|
const float sx = (corner & 1) ? 1.0f : -1.0f, sy = (corner & 2) ? 1.0f : -1.0f;
|
||||||
|
for (int step = 0; step < 3; ++step) {
|
||||||
|
const float d = 7.0f + step * 3.5f;
|
||||||
|
Box* b = new Box();
|
||||||
|
b->Opacity = 0.0f;
|
||||||
|
b->t2d.center = { 0.5f, 0.5f };
|
||||||
|
b->t2d.position = { 0.5f, 0.5f, sx * d, sy * d };
|
||||||
|
b->t2d.size = { 0.0f, 0.0f, 3.5f, 3.5f };
|
||||||
|
b->BindToRenderSystem();
|
||||||
|
hitMarker.push_back(b);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
float hitMarkerTime = 0.0f;
|
||||||
|
const float hitMarkerDuration = 0.25f;
|
||||||
|
auto ShowHitMarker = [&](bool strong) {
|
||||||
|
hitMarkerTime = hitMarkerDuration;
|
||||||
|
for (Box* b : hitMarker) b->Color = strong ? glm::vec3(1.0f, 0.15f, 0.15f) : glm::vec3(1.0f);
|
||||||
|
};
|
||||||
|
|
||||||
TextBox* fpsCounter = new TextBox();
|
TextBox* fpsCounter = new TextBox();
|
||||||
fpsCounter->font = arial;
|
fpsCounter->font = arial;
|
||||||
fpsCounter->text = "TEST1231231123";
|
fpsCounter->text = "TEST1231231123";
|
||||||
@@ -270,6 +294,18 @@ void Engine::Initiate()
|
|||||||
netText->t2d.size = { 0.0f, 0.0f, 360.0f, 40.0f };
|
netText->t2d.size = { 0.0f, 0.0f, 360.0f, 40.0f };
|
||||||
netText->BindToRenderSystem();
|
netText->BindToRenderSystem();
|
||||||
|
|
||||||
|
// Full-screen green flash when the player takes damage (drawn before the HUD text)
|
||||||
|
Box* damageFlash = new Box();
|
||||||
|
damageFlash->Color = { 0.0f, 1.0f, 0.2f };
|
||||||
|
damageFlash->Opacity = 0.0f;
|
||||||
|
damageFlash->t2d.position = { 0.0f, 0.0f, 0.0f, 0.0f };
|
||||||
|
damageFlash->t2d.center = { 0.0f, 0.0f };
|
||||||
|
damageFlash->t2d.size = { 1.0f, 1.0f, 0.0f, 0.0f };
|
||||||
|
damageFlash->BindToRenderSystem();
|
||||||
|
int lastPlayerHealth = 100;
|
||||||
|
float damageFlashTime = 0.0f;
|
||||||
|
const float damageFlashDuration = 0.35f;
|
||||||
|
|
||||||
TextBox* hpText = new TextBox();
|
TextBox* hpText = new TextBox();
|
||||||
hpText->font = arial;
|
hpText->font = arial;
|
||||||
hpText->text = "100/100 HP";
|
hpText->text = "100/100 HP";
|
||||||
@@ -322,10 +358,11 @@ void Engine::Initiate()
|
|||||||
// Punch hitbox only: intentionally not bound to the render system, so it isn't drawn
|
// Punch hitbox only: intentionally not bound to the render system, so it isn't drawn
|
||||||
mainf->AddChild(debugcube);
|
mainf->AddChild(debugcube);
|
||||||
|
|
||||||
|
const float mapScale = 1.5f; // uniform scale applied to the floor and every map prop
|
||||||
Mesh* floor = CreateCubeMesh();
|
Mesh* floor = CreateCubeMesh();
|
||||||
floor->name = "floor";
|
floor->name = "floor";
|
||||||
floor->meshTexture = blanktex;
|
floor->meshTexture = blanktex;
|
||||||
floor->t.ScaleTo({ 80.0f, 2.0f, 40.0f });
|
floor->t.ScaleTo({ 80.0f * mapScale, 2.0f, 40.0f * mapScale });
|
||||||
floor->t.TranslateTo({ 0.0f, -1.0f, 0.0f });
|
floor->t.TranslateTo({ 0.0f, -1.0f, 0.0f });
|
||||||
floor->BindToRenderSystem();
|
floor->BindToRenderSystem();
|
||||||
mainf->AddChild(floor);
|
mainf->AddChild(floor);
|
||||||
@@ -340,6 +377,8 @@ void Engine::Initiate()
|
|||||||
// pos = centre of the block's footprint on the floor; it sits on y = 0 and is `size.y` tall.
|
// pos = centre of the block's footprint on the floor; it sits on y = 0 and is `size.y` tall.
|
||||||
// Walls are frictionless (player friction is 0 too) so you slide along them.
|
// Walls are frictionless (player friction is 0 too) so you slide along them.
|
||||||
auto AddBlock = [&](const char* name, glm::vec3 pos, glm::vec3 size, bool slippery = false) {
|
auto AddBlock = [&](const char* name, glm::vec3 pos, glm::vec3 size, bool slippery = false) {
|
||||||
|
pos *= mapScale;
|
||||||
|
size *= mapScale;
|
||||||
Mesh* m = CreateCubeMesh();
|
Mesh* m = CreateCubeMesh();
|
||||||
m->name = name;
|
m->name = name;
|
||||||
m->meshTexture = blanktex;
|
m->meshTexture = blanktex;
|
||||||
@@ -362,15 +401,15 @@ void Engine::Initiate()
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Map is a rectangle: x in [-40, 40], z in [-20, 20]
|
// Map is a rectangle: x in [-60, 60], z in [-30, 30] (authored at 1x, scaled by mapScale)
|
||||||
// Centre dome
|
// Centre dome
|
||||||
AddTiers("dome", { 0.0f, 0.0f }, 18.0f, 1.0f, 5);
|
AddTiers("dome", { 0.0f, 0.0f }, 18.0f, 1.0f, 5);
|
||||||
// Cones, opposite corners of the dome
|
// Cones, opposite corners of the dome
|
||||||
AddTiers("cone", { -12.0f, -13.0f }, 6.0f, 1.0f, 5);
|
AddTiers("cone", { -12.0f, -13.0f }, 6.0f, 1.0f, 5);
|
||||||
AddTiers("cone", { 12.0f, 13.0f }, 6.0f, 1.0f, 5);
|
AddTiers("cone", { 12.0f, 13.0f }, 6.0f, 1.0f, 5);
|
||||||
// Big cubes either side of the dome
|
// Big cubes either side of the dome
|
||||||
AddBlock("cube", { -24.0f, -2.0f, 0.0f }, { 7.0f, 7.0f, 7.0f });
|
AddBlock("cube", { -24.0f, 0.0f, 0.0f }, { 7.0f, 7.0f, 7.0f });
|
||||||
AddBlock("cube", { 24.0f, 2.0f, 0.0f }, { 7.0f, 7.0f, 7.0f });
|
AddBlock("cube", { 24.0f, 0.0f, 0.0f }, { 7.0f, 7.0f, 7.0f });
|
||||||
// Stairs climbing to a tall back wall (the ramp), back right
|
// Stairs climbing to a tall back wall (the ramp), back right
|
||||||
AddBlock("stair", { 29.0f, 0.0f, -12.0f }, { 2.5f, 1.0f, 10.0f });
|
AddBlock("stair", { 29.0f, 0.0f, -12.0f }, { 2.5f, 1.0f, 10.0f });
|
||||||
AddBlock("stair", { 31.5f, 0.0f, -12.0f }, { 2.5f, 2.0f, 10.0f });
|
AddBlock("stair", { 31.5f, 0.0f, -12.0f }, { 2.5f, 2.0f, 10.0f });
|
||||||
@@ -511,8 +550,9 @@ void Engine::Initiate()
|
|||||||
|
|
||||||
// Random respawn spot on the floor (NPC and player), kept clear of every map prop
|
// Random respawn spot on the floor (NPC and player), kept clear of every map prop
|
||||||
std::mt19937 respawnRng(std::random_device{}());
|
std::mt19937 respawnRng(std::random_device{}());
|
||||||
|
const float respawnHeight = 10.0f; // respawn in the air and drop to the floor
|
||||||
auto RandomSpawn = [&]() -> glm::vec3 {
|
auto RandomSpawn = [&]() -> glm::vec3 {
|
||||||
std::uniform_real_distribution<float> spreadX(-37.0f, 37.0f), spreadZ(-17.0f, 17.0f);
|
std::uniform_real_distribution<float> spreadX(-37.0f * mapScale, 37.0f * mapScale), spreadZ(-17.0f * mapScale, 17.0f * mapScale);
|
||||||
const float margin = 1.5f;
|
const float margin = 1.5f;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
const float x = spreadX(respawnRng), z = spreadZ(respawnRng);
|
const float x = spreadX(respawnRng), z = spreadZ(respawnRng);
|
||||||
@@ -522,7 +562,7 @@ void Engine::Initiate()
|
|||||||
z > f.minZ - margin && z < f.maxZ + margin) { blocked = true; break; }
|
z > f.minZ - margin && z < f.maxZ + margin) { blocked = true; break; }
|
||||||
}
|
}
|
||||||
if (blocked) continue;
|
if (blocked) continue;
|
||||||
return { x, 0.9f, z };
|
return { x, respawnHeight, z };
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -560,6 +600,7 @@ void Engine::Initiate()
|
|||||||
const bool headshot = heightFrac >= headFraction;
|
const bool headshot = heightFrac >= headFraction;
|
||||||
const int damage = headshot ? maxHealth : bodyDamage;
|
const int damage = headshot ? maxHealth : bodyDamage;
|
||||||
camera->AddScreenshake(0.05f);
|
camera->AddScreenshake(0.05f);
|
||||||
|
ShowHitMarker(headshot);
|
||||||
|
|
||||||
if (targetRemoteId >= 0) {
|
if (targetRemoteId >= 0) {
|
||||||
// Another player: their machine owns their health, so tell it
|
// Another player: their machine owns their health, so tell it
|
||||||
@@ -654,6 +695,7 @@ void Engine::Initiate()
|
|||||||
npcBody->WakeUp();
|
npcBody->WakeUp();
|
||||||
npcBody->linearvelocity += playerFront * 5.0f + glm::vec3(0.0f, 3.0f, 0.0f);
|
npcBody->linearvelocity += playerFront * 5.0f + glm::vec3(0.0f, 3.0f, 0.0f);
|
||||||
camera->AddScreenshake(0.15f); // landing a punch feels impactful
|
camera->AddScreenshake(0.15f); // landing a punch feels impactful
|
||||||
|
ShowHitMarker(false);
|
||||||
|
|
||||||
npc->body->Health -= punchDamage;
|
npc->body->Health -= punchDamage;
|
||||||
std::cout << "PUNCH - NPC HP " << npc->body->Health << "\n";
|
std::cout << "PUNCH - NPC HP " << npc->body->Health << "\n";
|
||||||
@@ -676,6 +718,7 @@ void Engine::Initiate()
|
|||||||
ph.knockback = playerFront * 5.0f + glm::vec3(0.0f, 3.0f, 0.0f);
|
ph.knockback = playerFront * 5.0f + glm::vec3(0.0f, 3.0f, 0.0f);
|
||||||
if (lan && lan->IsActive()) lan->SendHit((uint8_t)kv.first, ph);
|
if (lan && lan->IsActive()) lan->SendHit((uint8_t)kv.first, ph);
|
||||||
camera->AddScreenshake(0.15f);
|
camera->AddScreenshake(0.15f);
|
||||||
|
ShowHitMarker(false);
|
||||||
std::cout << "PUNCH - player " << kv.first << "\n";
|
std::cout << "PUNCH - player " << kv.first << "\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -883,6 +926,14 @@ void Engine::Initiate()
|
|||||||
}
|
}
|
||||||
fpsCounter->text = std::to_string(measuredFps) + " FPS";
|
fpsCounter->text = std::to_string(measuredFps) + " FPS";
|
||||||
}
|
}
|
||||||
|
hitMarkerTime = std::max(hitMarkerTime - deltatime, 0.0f);
|
||||||
|
for (Box* b : hitMarker) b->Opacity = hitMarkerTime / hitMarkerDuration;
|
||||||
|
// Damage flash: any HP loss restarts a short green fade-out
|
||||||
|
if (testcharacter->body->Health < lastPlayerHealth)
|
||||||
|
damageFlashTime = damageFlashDuration;
|
||||||
|
lastPlayerHealth = testcharacter->body->Health;
|
||||||
|
damageFlashTime = std::max(damageFlashTime - deltatime, 0.0f);
|
||||||
|
damageFlash->Opacity = 0.45f * (damageFlashTime / damageFlashDuration);
|
||||||
// Player respawn: at 0 HP or after falling off the map, teleport to a random spot
|
// Player respawn: at 0 HP or after falling off the map, teleport to a random spot
|
||||||
if (testcharacter->body->Health <= 0 || testcharacter->body->t.GetTranslation().y < -20.0f) {
|
if (testcharacter->body->Health <= 0 || testcharacter->body->t.GetTranslation().y < -20.0f) {
|
||||||
testcharacter->body->Health = maxHealth;
|
testcharacter->body->Health = maxHealth;
|
||||||
|
|||||||
+11
-9
@@ -16,8 +16,8 @@ public:
|
|||||||
Invalid
|
Invalid
|
||||||
};
|
};
|
||||||
|
|
||||||
Event() : type(Type::Invalid), code(0u) {}
|
Event() : type(Type::Invalid), code(0) {}
|
||||||
Event(Type typ, unsigned char cod) : type(typ), code(cod) {}
|
Event(Type typ, int cod) : type(typ), code(cod) {}
|
||||||
bool IsPress() const noexcept {
|
bool IsPress() const noexcept {
|
||||||
return type == Type::Press;
|
return type == Type::Press;
|
||||||
};
|
};
|
||||||
@@ -28,7 +28,7 @@ public:
|
|||||||
return type != Type::Invalid;
|
return type != Type::Invalid;
|
||||||
};
|
};
|
||||||
|
|
||||||
unsigned char GetCode() const noexcept {
|
int GetCode() const noexcept {
|
||||||
return code;
|
return code;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -37,7 +37,7 @@ public:
|
|||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
Type type;
|
Type type;
|
||||||
unsigned char code;
|
int code;
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@@ -45,8 +45,8 @@ public:
|
|||||||
~Keyboard() = default;
|
~Keyboard() = default;
|
||||||
Keyboard(const Keyboard&) = delete;
|
Keyboard(const Keyboard&) = delete;
|
||||||
|
|
||||||
bool IsKeyDown(const unsigned char key) const noexcept {
|
bool IsKeyDown(const int key) const noexcept {
|
||||||
return keys[key];
|
return key >= 0 && key < (int)numerodekeys && keys[key];
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsKeyEmpty() const noexcept {
|
bool IsKeyEmpty() const noexcept {
|
||||||
@@ -92,12 +92,14 @@ public:
|
|||||||
TrimBuffer(charbuffer);
|
TrimBuffer(charbuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void KeyDown(const unsigned char key) noexcept {
|
void KeyDown(const int key) noexcept {
|
||||||
|
if (key < 0 || key >= (int)numerodekeys) return; // GLFW_KEY_UNKNOWN etc.
|
||||||
keybuffer.push(Event(Event::Type::Press, key));
|
keybuffer.push(Event(Event::Type::Press, key));
|
||||||
keys[key] = true;
|
keys[key] = true;
|
||||||
TrimBuffer(keybuffer);
|
TrimBuffer(keybuffer);
|
||||||
}
|
}
|
||||||
void KeyUp(const unsigned char key) noexcept {
|
void KeyUp(const int key) noexcept {
|
||||||
|
if (key < 0 || key >= (int)numerodekeys) return;
|
||||||
keybuffer.push(Event(Event::Type::Release, key));
|
keybuffer.push(Event(Event::Type::Release, key));
|
||||||
keys[key] = false;
|
keys[key] = false;
|
||||||
TrimBuffer(keybuffer);
|
TrimBuffer(keybuffer);
|
||||||
@@ -129,7 +131,7 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool AutorepeatEnabled = false;
|
bool AutorepeatEnabled = false;
|
||||||
static constexpr unsigned int numerodekeys = 256u;
|
static constexpr unsigned int numerodekeys = 512u; // GLFW key codes go up to ~348
|
||||||
static constexpr unsigned int bufferSize = 16u;
|
static constexpr unsigned int bufferSize = 16u;
|
||||||
std::bitset<numerodekeys> keys;
|
std::bitset<numerodekeys> keys;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user