diff --git a/Engine.cpp b/Engine.cpp index 22bcd10..47d8f91 100644 --- a/Engine.cpp +++ b/Engine.cpp @@ -325,7 +325,7 @@ void Engine::Initiate() Mesh* floor = CreateCubeMesh(); floor->name = "floor"; floor->meshTexture = blanktex; - floor->t.ScaleTo({ 100.0f, 2.0f, 100.0f }); + floor->t.ScaleTo({ 80.0f, 2.0f, 40.0f }); floor->t.TranslateTo({ 0.0f, -1.0f, 0.0f }); floor->BindToRenderSystem(); mainf->AddChild(floor); @@ -333,18 +333,58 @@ void Engine::Initiate() floorBody->velocity = false; physicsengine->AddObject(floorBody); - // Wall: frictionless (player friction is 0 too) so you slide along it - Mesh* wall = CreateCubeMesh(); - wall->name = "wall"; - wall->meshTexture = blanktex; - wall->t.ScaleTo({ 1.0f, 6.0f, 20.0f }); - wall->t.TranslateTo({ -8.0f, 3.0f, 0.0f }); - wall->BindToRenderSystem(); - mainf->AddChild(wall); - p* wallBody = new p(wall); - wallBody->velocity = false; - wallBody->friction = 0.0f; - physicsengine->AddObject(wallBody); + // Static map props: axis-aligned blocks (collision is AABB-based, so dome/cones/ramp are + // built from stacked tiers and stairs). Footprints are recorded so respawns avoid them. + struct Footprint { float minX, maxX, minZ, maxZ; }; + std::vector propFootprints; + // 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. + auto AddBlock = [&](const char* name, glm::vec3 pos, glm::vec3 size, bool slippery = false) { + Mesh* m = CreateCubeMesh(); + m->name = name; + m->meshTexture = blanktex; + m->t.ScaleTo(size); + m->t.TranslateTo({ pos.x, pos.y + size.y * 0.5f, pos.z }); + m->BindToRenderSystem(); + mainf->AddChild(m); + p* body = new p(m); + body->velocity = false; + if (slippery) body->friction = 0.0f; + physicsengine->AddObject(body); + propFootprints.push_back({ pos.x - size.x * 0.5f, pos.x + size.x * 0.5f, + pos.z - size.z * 0.5f, pos.z + size.z * 0.5f }); + }; + // Concentric stack of square tiers, widest at the bottom (stands in for dome / cone) + auto AddTiers = [&](const char* name, glm::vec2 pos, float baseWidth, float tierHeight, int tiers) { + for (int i = 0; i < tiers; ++i) { + const float w = baseWidth * (1.0f - float(i) / float(tiers)); + AddBlock(name, { pos.x, tierHeight * i, pos.y }, { w, tierHeight, w }); + } + }; + + // Map is a rectangle: x in [-40, 40], z in [-20, 20] + // Centre dome + AddTiers("dome", { 0.0f, 0.0f }, 18.0f, 1.0f, 5); + // 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); + // 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, 2.0f, 0.0f }, { 7.0f, 7.0f, 7.0f }); + // 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", { 31.5f, 0.0f, -12.0f }, { 2.5f, 2.0f, 10.0f }); + AddBlock("stair", { 34.0f, 0.0f, -12.0f }, { 2.5f, 3.0f, 10.0f }); + AddBlock("wall", { 36.5f, 0.0f, -12.0f }, { 1.0f, 9.0f, 10.0f }, true); + // Stacked boxes, front right + AddBlock("box", { 30.0f, 0.0f, 12.0f }, { 6.0f, 2.5f, 6.0f }); + AddBlock("box", { 34.5f, 0.0f, 15.0f }, { 5.0f, 5.0f, 5.0f }); + // Long wall with a small block at its end, left front + AddBlock("wall", { -33.0f, 0.0f, 9.0f }, { 1.0f, 7.0f, 18.0f }, true); + AddBlock("box", { -30.0f, 0.0f, 17.5f }, { 3.0f, 2.0f, 3.0f }); + // Small box cluster, back left + AddBlock("box", { -26.0f, 0.0f, -12.0f }, { 6.0f, 2.0f, 6.0f }); + AddBlock("box", { -22.0f, 0.0f, -15.5f }, { 6.0f, 1.0f, 4.0f }); // Ground check auto IsGrounded = [&]() -> bool { @@ -419,8 +459,8 @@ void Engine::Initiate() // fromNet = another player's blast: we only launch ourselves (the other machines launch // themselves the same way, since remote players are just puppets on this machine). - auto Explode = [&](const glm::vec3& center, bool fromNet = false, - float radius = shockRadius, float power = shockPower) { + // (Lambda default arguments can't reference locals, so callers pass radius/power explicitly.) + auto Explode = [&](const glm::vec3& center, bool fromNet, float radius, float power) { auto launch = [&](const glm::vec3& pos, p* body) { const glm::vec3 offset = pos - center; const float dist = glm::length(offset); @@ -469,13 +509,19 @@ void Engine::Initiate() const int punchDamage = 25; const float headFraction = 0.8f; - // Random respawn spot on the floor (NPC and player), kept out of the wall (x -9.5..-6.5, z -11..11) + // Random respawn spot on the floor (NPC and player), kept clear of every map prop std::mt19937 respawnRng(std::random_device{}()); auto RandomSpawn = [&]() -> glm::vec3 { - std::uniform_real_distribution spread(-20.0f, 20.0f); + std::uniform_real_distribution spreadX(-37.0f, 37.0f), spreadZ(-17.0f, 17.0f); + const float margin = 1.5f; for (;;) { - const float x = spread(respawnRng), z = spread(respawnRng); - if (x > -9.5f && x < -6.5f && z > -11.0f && z < 11.0f) continue; + const float x = spreadX(respawnRng), z = spreadZ(respawnRng); + bool blocked = false; + for (const Footprint& f : propFootprints) { + if (x > f.minX - margin && x < f.maxX + margin && + z > f.minZ - margin && z < f.maxZ + margin) { blocked = true; break; } + } + if (blocked) continue; return { x, 0.9f, z }; } }; @@ -778,7 +824,7 @@ void Engine::Initiate() if (d <= bestDist) { bestDist = d; bestPoint = hit.value(); found = true; } } - if (found) Explode(bestPoint); + if (found) Explode(bestPoint, false, shockRadius, shockPower); else if (shockAge >= shockLifetime) { shockActive = false; shockMesh->t.TranslateTo(hiddenPos);