Shared tomatoes, P1 sandbox spawns, and weapons left out
- Tomato splats are kept in the match, so everyone sees everyone's (others' arrive in replays, which play no effects), each splatting with juice and a sound once. - The sandbox's first player (solo or hosting) spawns on the arena's P1 mark. - A thrown flail ball or grapple stays out when switching weapons, and another weapon fires while a grapple hangs on. Mines, flail balls and grapples go once their slot no longer holds the weapon that put them out (mines fizzling). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
e88fed1f4c
commit
e55596b276
10 files changed
+84
-79
No files matched your search
@@ -14,12 +14,6 @@ constexpr float FLASH_LIFE = 0.05f;
|
|||||||
constexpr float FLASH_WIDTH = 6;
|
constexpr float FLASH_WIDTH = 6;
|
||||||
constexpr float RING_LIFE = 0.3f;
|
constexpr float RING_LIFE = 0.3f;
|
||||||
constexpr int RING_WIDTH = 2;
|
constexpr int RING_WIDTH = 2;
|
||||||
constexpr float SPLAT_CORE = 6;
|
|
||||||
constexpr float SPLAT_FADE = 0.6f;
|
|
||||||
constexpr float SPLAT_LIFE = 2;
|
|
||||||
constexpr float SPLAT_REACH = 10;
|
|
||||||
constexpr float SPLAT_SIZE_MAX = 3.5f;
|
|
||||||
constexpr float SPLAT_SIZE_MIN = 1.5f;
|
|
||||||
constexpr float AFTERIMAGE_LIFE = 0.12f;
|
constexpr float AFTERIMAGE_LIFE = 0.12f;
|
||||||
constexpr float NUMBER_GAP = 8;
|
constexpr float NUMBER_GAP = 8;
|
||||||
constexpr float POPUP_FADE = 0.4f;
|
constexpr float POPUP_FADE = 0.4f;
|
||||||
@@ -133,19 +127,6 @@ void Effects::ring_spawn(Vec2 position, float radius, Color color)
|
|||||||
effect_add(rings, Ring{color, position, RING_LIFE, radius});
|
effect_add(rings, Ring{color, position, RING_LIFE, radius});
|
||||||
}
|
}
|
||||||
|
|
||||||
// A big blob where it landed, with smaller ones flung round it.
|
|
||||||
void Effects::splat_spawn(Vec2 position, Color color)
|
|
||||||
{
|
|
||||||
Splat splat = {.color = color, .position = position, .life = SPLAT_LIFE};
|
|
||||||
splat.sizes[0] = SPLAT_CORE;
|
|
||||||
for (int i = 1; i < SPLAT_BLOBS; i++)
|
|
||||||
{
|
|
||||||
splat.blobs[i] = vec2_polar(random_get(0, 2 * PI), random_get(SPLAT_CORE, SPLAT_REACH));
|
|
||||||
splat.sizes[i] = random_get(SPLAT_SIZE_MIN, SPLAT_SIZE_MAX);
|
|
||||||
}
|
|
||||||
effect_add(splats, splat);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Effects::dps_record(int amount)
|
void Effects::dps_record(int amount)
|
||||||
{
|
{
|
||||||
hits.push_back({ticks * TICK, amount});
|
hits.push_back({ticks * TICK, amount});
|
||||||
@@ -187,10 +168,6 @@ void Effects::update()
|
|||||||
ring.life -= TICK;
|
ring.life -= TICK;
|
||||||
std::erase_if(rings, [](Ring& ring) { return ring.life <= 0; });
|
std::erase_if(rings, [](Ring& ring) { return ring.life <= 0; });
|
||||||
|
|
||||||
for (Splat& splat : splats)
|
|
||||||
splat.life -= TICK;
|
|
||||||
std::erase_if(splats, [](Splat& splat) { return splat.life <= 0; });
|
|
||||||
|
|
||||||
for (Afterimage& afterimage : afterimages)
|
for (Afterimage& afterimage : afterimages)
|
||||||
afterimage.life -= TICK;
|
afterimage.life -= TICK;
|
||||||
std::erase_if(afterimages, [](Afterimage& afterimage) { return afterimage.life <= 0; });
|
std::erase_if(afterimages, [](Afterimage& afterimage) { return afterimage.life <= 0; });
|
||||||
@@ -232,14 +209,6 @@ void Effects::draw(Game& game)
|
|||||||
renderer.line_draw(flash.position - across, flash.position + across, width * FLASH_CROSS, flash.color);
|
renderer.line_draw(flash.position - across, flash.position + across, width * FLASH_CROSS, flash.color);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Each splat holds, then fades out over its last moments.
|
|
||||||
for (Splat& splat : splats)
|
|
||||||
{
|
|
||||||
Color color = color_fade(splat.color, std::min(1.0f, splat.life / SPLAT_FADE));
|
|
||||||
for (int i = 0; i < SPLAT_BLOBS; i++)
|
|
||||||
renderer.circle_draw(splat.position + splat.blobs[i], splat.sizes[i], color);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Each ring eases out to its full radius as it fades.
|
// Each ring eases out to its full radius as it fades.
|
||||||
for (Ring& ring : rings)
|
for (Ring& ring : rings)
|
||||||
{
|
{
|
||||||
@@ -290,6 +259,5 @@ void Effects::clear()
|
|||||||
particles.clear();
|
particles.clear();
|
||||||
popups.clear();
|
popups.clear();
|
||||||
rings.clear();
|
rings.clear();
|
||||||
splats.clear();
|
|
||||||
shake = 0;
|
shake = 0;
|
||||||
}
|
}
|
||||||
@@ -58,18 +58,6 @@ struct Ring
|
|||||||
float radius = 0;
|
float radius = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
constexpr int SPLAT_BLOBS = 6;
|
|
||||||
|
|
||||||
// A tomato's splat: blobs of colour round where it landed, fading out.
|
|
||||||
struct Splat
|
|
||||||
{
|
|
||||||
Color color;
|
|
||||||
Vec2 position;
|
|
||||||
Vec2 blobs[SPLAT_BLOBS];
|
|
||||||
float sizes[SPLAT_BLOBS];
|
|
||||||
float life = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
// A fading copy of a sprite left behind by something moving fast.
|
// A fading copy of a sprite left behind by something moving fast.
|
||||||
struct Afterimage
|
struct Afterimage
|
||||||
{
|
{
|
||||||
@@ -85,7 +73,6 @@ public:
|
|||||||
void afterimage_spawn(Pose pose);
|
void afterimage_spawn(Pose pose);
|
||||||
void flash_spawn(Vec2 position, float angle, float size, Color color);
|
void flash_spawn(Vec2 position, float angle, float size, Color color);
|
||||||
void ring_spawn(Vec2 position, float radius, Color color);
|
void ring_spawn(Vec2 position, float radius, Color color);
|
||||||
void splat_spawn(Vec2 position, Color color);
|
|
||||||
void afterimage_draw(Game& game);
|
void afterimage_draw(Game& game);
|
||||||
void number_spawn(Vec2 position, int value, int target, Color color);
|
void number_spawn(Vec2 position, int value, int target, Color color);
|
||||||
void dps_record(int amount);
|
void dps_record(int amount);
|
||||||
@@ -104,7 +91,6 @@ private:
|
|||||||
std::vector<Particle> particles;
|
std::vector<Particle> particles;
|
||||||
std::vector<Popup> popups;
|
std::vector<Popup> popups;
|
||||||
std::vector<Ring> rings;
|
std::vector<Ring> rings;
|
||||||
std::vector<Splat> splats;
|
|
||||||
float shake = 0;
|
float shake = 0;
|
||||||
int ticks = 0;
|
int ticks = 0;
|
||||||
};
|
};
|
||||||
+3
-5
@@ -397,7 +397,7 @@ void Fighter::rope_update(Attack& hook)
|
|||||||
|
|
||||||
// The controls' slot picks a weapon slot, wrapping around, and the level buttons level the weapon copy in it. The
|
// The controls' slot picks a weapon slot, wrapping around, and the level buttons level the weapon copy in it. The
|
||||||
// weapon switched away from becomes the off-hand weapon for Dual Wield (a copy of the same weapon counts when weapons
|
// weapon switched away from becomes the off-hand weapon for Dual Wield (a copy of the same weapon counts when weapons
|
||||||
// stack), and a thrown flail ball is dropped.
|
// stack). A thrown flail ball or grapple out stays out.
|
||||||
void Fighter::slot_update(Sim& sim)
|
void Fighter::slot_update(Sim& sim)
|
||||||
{
|
{
|
||||||
int previous = slot;
|
int previous = slot;
|
||||||
@@ -408,10 +408,7 @@ void Fighter::slot_update(Sim& sim)
|
|||||||
if (slot != previous)
|
if (slot != previous)
|
||||||
sim.cues->sound_play(SOUND_SELECT);
|
sim.cues->sound_play(SOUND_SELECT);
|
||||||
if (slot != previous && weaponLoadout[previous] >= 0 && weapon_key(previous) != weapon_key(slot))
|
if (slot != previous && weaponLoadout[previous] >= 0 && weapon_key(previous) != weapon_key(slot))
|
||||||
{
|
|
||||||
slotSwitches[previous] = ++switches;
|
slotSwitches[previous] = ++switches;
|
||||||
sim.weapons.attacks_release(*this, ATTACK_FLAIL);
|
|
||||||
}
|
|
||||||
|
|
||||||
int step = (int)is_pressed(CONTROL_LEVEL_UP) - (int)is_pressed(CONTROL_LEVEL_DOWN);
|
int step = (int)is_pressed(CONTROL_LEVEL_UP) - (int)is_pressed(CONTROL_LEVEL_DOWN);
|
||||||
if (step != 0 && held >= 0 && sim.match.state == MATCH_PRACTICE)
|
if (step != 0 && held >= 0 && sim.match.state == MATCH_PRACTICE)
|
||||||
@@ -605,7 +602,8 @@ void Fighter::charge_update(Sim& sim)
|
|||||||
if (is_released(CONTROL_ATTACK))
|
if (is_released(CONTROL_ATTACK))
|
||||||
sim.weapons.wisps_release(*this);
|
sim.weapons.wisps_release(*this);
|
||||||
|
|
||||||
if (hook && (isLeftPressed || isRightPressed))
|
// A latched grapple lets go when clicked with the grapple in hand; another weapon fires as it hangs on.
|
||||||
|
if (hook && hook->key == weapon_key(slot) && (isLeftPressed || isRightPressed))
|
||||||
{
|
{
|
||||||
sim.weapons.attacks_release(*this, ATTACK_HOOK);
|
sim.weapons.attacks_release(*this, ATTACK_HOOK);
|
||||||
isFireBlocked = isLeftPressed;
|
isFireBlocked = isLeftPressed;
|
||||||
|
|||||||
+4
-1
@@ -86,6 +86,8 @@ Match::Match()
|
|||||||
void Match::update(Sim& sim)
|
void Match::update(Sim& sim)
|
||||||
{
|
{
|
||||||
timer -= TICK;
|
timer -= TICK;
|
||||||
|
for (Tomato& tomato : tomatoes)
|
||||||
|
tomato.age += TICK;
|
||||||
// Offline, the menu's Play starts a game, and leaving the results goes back to the sandbox.
|
// Offline, the menu's Play starts a game, and leaving the results goes back to the sandbox.
|
||||||
bool isPlay = !isOnline && isPlayRequested;
|
bool isPlay = !isOnline && isPlayRequested;
|
||||||
bool isSandbox = !isOnline && state == MATCH_OVER && isSandboxRequested;
|
bool isSandbox = !isOnline && state == MATCH_OVER && isSandboxRequested;
|
||||||
@@ -429,7 +431,8 @@ void Match::tomatoes_update(Sim& sim)
|
|||||||
if (i == winner || isGone[i] || tomatoCooldowns[i] > 0 || !isThrown)
|
if (i == winner || isGone[i] || tomatoCooldowns[i] > 0 || !isThrown)
|
||||||
continue;
|
continue;
|
||||||
tomatoCooldowns[i] = TOMATO_COOLDOWN;
|
tomatoCooldowns[i] = TOMATO_COOLDOWN;
|
||||||
sim.cues->tomato_splat(fighter.controls.cursor, i);
|
tomatoes[tomatoCount % TOMATO_MAX] = {.position = fighter.controls.cursor, .owner = i, .serial = tomatoCount};
|
||||||
|
tomatoCount++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+16
-1
@@ -175,6 +175,18 @@ struct Queue
|
|||||||
bool isActive = false;
|
bool isActive = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
constexpr int TOMATO_MAX = 32;
|
||||||
|
|
||||||
|
// A tomato splatted after a round: where it landed, who threw it, how long ago, and its number among every one thrown
|
||||||
|
// in the match (which also keeps its look the same on every screen).
|
||||||
|
struct Tomato
|
||||||
|
{
|
||||||
|
Vec2 position;
|
||||||
|
float age = 0;
|
||||||
|
int owner = -1;
|
||||||
|
int serial = 0;
|
||||||
|
};
|
||||||
|
|
||||||
// Best-of-three deathmatch, or a single race, played by the rules. Practice is the sandbox with the dummy and the menu.
|
// Best-of-three deathmatch, or a single race, played by the rules. Practice is the sandbox with the dummy and the menu.
|
||||||
// Each round opens with a long countdown to ready up in (cut short once every fighter is ready), at the round's level
|
// Each round opens with a long countdown to ready up in (cut short once every fighter is ready), at the round's level
|
||||||
// and health. Countdown is how long it ran from: longer on rounds where fighters choose items. On the rounds items are
|
// and health. Countdown is how long it ran from: longer on rounds where fighters choose items. On the rounds items are
|
||||||
@@ -192,8 +204,11 @@ public:
|
|||||||
float clock = 0;
|
float clock = 0;
|
||||||
float countdown = READY_TIME;
|
float countdown = READY_TIME;
|
||||||
float finishTimes[MAX_FIGHTERS] = {};
|
float finishTimes[MAX_FIGHTERS] = {};
|
||||||
// How long until each fighter can splat another tomato on the results.
|
// How long until each fighter can splat another tomato, and the latest splats, kept with the game so everyone sees
|
||||||
|
// everyone's.
|
||||||
float tomatoCooldowns[MAX_FIGHTERS] = {};
|
float tomatoCooldowns[MAX_FIGHTERS] = {};
|
||||||
|
Tomato tomatoes[TOMATO_MAX];
|
||||||
|
int tomatoCount = 0;
|
||||||
float timer = 0;
|
float timer = 0;
|
||||||
int round = 0;
|
int round = 0;
|
||||||
int winner = -1;
|
int winner = -1;
|
||||||
|
|||||||
+44
-11
@@ -69,6 +69,16 @@ constexpr float WHIP_INNER = 2;
|
|||||||
constexpr float WHIP_JITTER = 0.5f;
|
constexpr float WHIP_JITTER = 0.5f;
|
||||||
constexpr float WHIP_OUTER = 5;
|
constexpr float WHIP_OUTER = 5;
|
||||||
constexpr float WISP_FRAME_STAGGER = 0.3f;
|
constexpr float WISP_FRAME_STAGGER = 0.3f;
|
||||||
|
constexpr int TOMATO_BLOBS = 6;
|
||||||
|
constexpr float TOMATO_BLOB_MAX = 3.5f;
|
||||||
|
constexpr float TOMATO_BLOB_MIN = 1.5f;
|
||||||
|
constexpr float TOMATO_CORE = 6;
|
||||||
|
constexpr float TOMATO_FADE = 0.6f;
|
||||||
|
// How old a tomato can be when this screen first sees it and still splat with juice and a sound.
|
||||||
|
constexpr float TOMATO_FRESH = 0.5f;
|
||||||
|
constexpr float TOMATO_LIFE = 2;
|
||||||
|
constexpr Uint32 TOMATO_LOOK_STEP = 2654435761u;
|
||||||
|
constexpr float TOMATO_REACH = 10;
|
||||||
constexpr Burst TOMATO_BURST = {.gravity = 400, .life = 0.5f, .size = 2, .speed = 140, .spread = 1.2f, .count = 12};
|
constexpr Burst TOMATO_BURST = {.gravity = 400, .life = 0.5f, .size = 2, .speed = 140, .spread = 1.2f, .count = 12};
|
||||||
|
|
||||||
// A random offset for an empowered attack or fighter to shake by, wider the more its colour fills in, like a damage
|
// A random offset for an empowered attack or fighter to shake by, wider the more its colour fills in, like a damage
|
||||||
@@ -391,17 +401,6 @@ void Scene::match_start()
|
|||||||
game.menu.isOpen = false;
|
game.menu.isOpen = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// A tomato thrown on the results: a splat in the thrower's colour where it landed, spraying juice.
|
|
||||||
void Scene::tomato_splat(Vec2 position, int owner)
|
|
||||||
{
|
|
||||||
if (isMuted)
|
|
||||||
return;
|
|
||||||
Color color = game.color_get(owner, true);
|
|
||||||
game.effects.splat_spawn(position, color);
|
|
||||||
game.effects.burst(TOMATO_BURST, position, -PI / 2, color);
|
|
||||||
game.audio.play(SOUND_SPLAT);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Readying with empty slots dealt them: this screen's own fighters hear the items go in.
|
// Readying with empty slots dealt them: this screen's own fighters hear the items go in.
|
||||||
void Scene::deal_play(int fighter)
|
void Scene::deal_play(int fighter)
|
||||||
{
|
{
|
||||||
@@ -425,6 +424,39 @@ void Scene::update()
|
|||||||
{
|
{
|
||||||
for (int i = 0; i < game.sim.fighterCount; i++)
|
for (int i = 0; i < game.sim.fighterCount; i++)
|
||||||
animator_update(game.sim.fighters[i], game.sprites.fighters[i]);
|
animator_update(game.sim.fighters[i], game.sprites.fighters[i]);
|
||||||
|
|
||||||
|
// Each new tomato (this screen's, or someone else's once their click arrives) splats with juice and a sound, once.
|
||||||
|
Match& match = game.sim.match;
|
||||||
|
tomatoesSeen = std::min(tomatoesSeen, match.tomatoCount);
|
||||||
|
for (; tomatoesSeen < match.tomatoCount; tomatoesSeen++)
|
||||||
|
{
|
||||||
|
Tomato& tomato = match.tomatoes[tomatoesSeen % TOMATO_MAX];
|
||||||
|
if (tomato.serial != tomatoesSeen || tomato.age > TOMATO_FRESH)
|
||||||
|
continue;
|
||||||
|
game.effects.burst(TOMATO_BURST, tomato.position, -PI / 2, game.color_get(tomato.owner, true));
|
||||||
|
game.audio.play(SOUND_SPLAT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// The match's tomatoes as splats in their throwers' colours: a big blob where each landed with smaller ones flung round
|
||||||
|
// it (the same on every screen), holding and then fading out.
|
||||||
|
void Scene::tomatoes_draw()
|
||||||
|
{
|
||||||
|
for (Tomato& tomato : game.sim.match.tomatoes)
|
||||||
|
{
|
||||||
|
if (tomato.owner < 0 || tomato.age >= TOMATO_LIFE)
|
||||||
|
continue;
|
||||||
|
Color color =
|
||||||
|
color_fade(game.color_get(tomato.owner, true), std::min(1.0f, (TOMATO_LIFE - tomato.age) / TOMATO_FADE));
|
||||||
|
game.renderer.circle_draw(tomato.position, TOMATO_CORE, color);
|
||||||
|
Rng look = {.state = (Uint32)tomato.serial * TOMATO_LOOK_STEP + 1};
|
||||||
|
for (int i = 1; i < TOMATO_BLOBS; i++)
|
||||||
|
{
|
||||||
|
Vec2 offset = vec2_polar(look.random_get(0, 2 * PI), look.random_get(TOMATO_CORE, TOMATO_REACH));
|
||||||
|
game.renderer.circle_draw(tomato.position + offset, look.random_get(TOMATO_BLOB_MIN, TOMATO_BLOB_MAX),
|
||||||
|
color);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// The game between its last two ticks: the world, the bots' map (when debugging), afterimages, blasts under the
|
// The game between its last two ticks: the world, the bots' map (when debugging), afterimages, blasts under the
|
||||||
@@ -438,6 +470,7 @@ void Scene::draw()
|
|||||||
for (int i = 0; i < game.sim.fighterCount; i++)
|
for (int i = 0; i < game.sim.fighterCount; i++)
|
||||||
fighter_draw(game.sim.fighters[i]);
|
fighter_draw(game.sim.fighters[i]);
|
||||||
attacks_draw();
|
attacks_draw();
|
||||||
|
tomatoes_draw();
|
||||||
if (game.settings.isCollisionShown)
|
if (game.settings.isCollisionShown)
|
||||||
collision_draw();
|
collision_draw();
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-1
@@ -36,14 +36,16 @@ public:
|
|||||||
void level_step(bool isUp) override;
|
void level_step(bool isUp) override;
|
||||||
void match_start() override;
|
void match_start() override;
|
||||||
void deal_play(int fighter) override;
|
void deal_play(int fighter) override;
|
||||||
void tomato_splat(Vec2 position, int owner) override;
|
|
||||||
void sandbox_return() override;
|
void sandbox_return() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Game& game;
|
Game& game;
|
||||||
int chargeVoices[MAX_FIGHTERS];
|
int chargeVoices[MAX_FIGHTERS];
|
||||||
|
// How many of the match's tomatoes have splatted on this screen.
|
||||||
|
int tomatoesSeen = 0;
|
||||||
|
|
||||||
void world_draw();
|
void world_draw();
|
||||||
|
void tomatoes_draw();
|
||||||
void bot_draw();
|
void bot_draw();
|
||||||
void fighter_draw(Fighter& fighter);
|
void fighter_draw(Fighter& fighter);
|
||||||
const char* animation_get(Fighter& fighter);
|
const char* animation_get(Fighter& fighter);
|
||||||
|
|||||||
@@ -41,8 +41,6 @@ public:
|
|||||||
{}
|
{}
|
||||||
virtual void deal_play(int fighter)
|
virtual void deal_play(int fighter)
|
||||||
{}
|
{}
|
||||||
virtual void tomato_splat(Vec2 position, int owner)
|
|
||||||
{}
|
|
||||||
virtual void sandbox_return()
|
virtual void sandbox_return()
|
||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -908,6 +908,17 @@ void Weapons::attack_move(Sim& sim, Attack& attack)
|
|||||||
float progress = attack.time / attack.duration;
|
float progress = attack.time / attack.duration;
|
||||||
float range = attack.stats.range;
|
float range = attack.stats.range;
|
||||||
|
|
||||||
|
// A mine, flail ball or grapple left out goes once its slot no longer holds the weapon that put it there (which
|
||||||
|
// could no longer set it off, reel it in or let it go), a mine fizzling with a puff.
|
||||||
|
bool isLeftOut = def.kind == ATTACK_MINE || def.kind == ATTACK_FLAIL || def.kind == ATTACK_HOOK;
|
||||||
|
if (isLeftOut && !attack.isExplosion && fighter.weaponLoadout[attack.key] != attack.weapon)
|
||||||
|
{
|
||||||
|
attack.isDead = true;
|
||||||
|
if (def.kind == ATTACK_MINE)
|
||||||
|
sim.cues->attack_burst_spawn(SMOKE_BURST, attack.position, 0, attack);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
switch (def.kind)
|
switch (def.kind)
|
||||||
{
|
{
|
||||||
case ATTACK_SWING:
|
case ATTACK_SWING:
|
||||||
|
|||||||
+3
-12
@@ -211,9 +211,9 @@ static bool is_solid(Tile tile)
|
|||||||
return tile == TILE_SOLID || tile == TILE_BLOCK;
|
return tile == TILE_SOLID || tile == TILE_BLOCK;
|
||||||
}
|
}
|
||||||
|
|
||||||
// The arena with the practice dummy standing on the first surface below the middle of the map, and the player
|
// The arena with the practice dummy standing on the first surface below the middle of the map. Fighters spawn on the
|
||||||
// spawning right underneath it, on the next surface down. Its marked spawns are joined by more spread over its ground,
|
// arena's marked spawns (the first player, solo or hosting, on 1), joined by more spread over its ground for a lobby's
|
||||||
// for a lobby's sandbox full of players.
|
// sandbox full of players.
|
||||||
void World::sandbox_load()
|
void World::sandbox_load()
|
||||||
{
|
{
|
||||||
arena_load();
|
arena_load();
|
||||||
@@ -225,15 +225,6 @@ void World::sandbox_load()
|
|||||||
float standY = standRow * TILE_SIZE;
|
float standY = standRow * TILE_SIZE;
|
||||||
float centerX = width * TILE_SIZE / 2.0f;
|
float centerX = width * TILE_SIZE / 2.0f;
|
||||||
dummies.push_back({.box = {centerX - DUMMY_WIDTH / 2, standY - DUMMY_HEIGHT, DUMMY_WIDTH, DUMMY_HEIGHT}});
|
dummies.push_back({.box = {centerX - DUMMY_WIDTH / 2, standY - DUMMY_HEIGHT, DUMMY_WIDTH, DUMMY_HEIGHT}});
|
||||||
|
|
||||||
int groundRow = standRow;
|
|
||||||
while (groundRow < height && tile_get(column, groundRow) != TILE_EMPTY)
|
|
||||||
groundRow++;
|
|
||||||
while (groundRow < height && tile_get(column, groundRow) == TILE_EMPTY)
|
|
||||||
groundRow++;
|
|
||||||
float groundY = groundRow * TILE_SIZE;
|
|
||||||
Ramp* ramp = ramp_find({centerX, groundY + TILE_SIZE / 2.0f});
|
|
||||||
spawns[0] = {centerX, ramp ? ramp->y_at(centerX) : groundY};
|
|
||||||
spawns_spread(SPAWN_MARKS);
|
spawns_spread(SPAWN_MARKS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user