bomberman-of-the-hill's People
bomberman-of-the-hill's Issues
Player action logic
Business logic for the effects that player actions have on the world, as well as designing the Action
enum itself.
Movement
Movement action should, well, move the character, but it may have non-obvious edge cases:
- What happens when a character walks into a bomb? In some bomberman games the bomb is pushed and starts sliding (though this is often with a powerup). We can assume the bomb is immobile for the MVP most likely.
- What happens when a character walks into a location that another character is moving to? How is this resolved? (it would be ideal if we could avoid solving it arbitrarily, such as through iteration order. An idea could be to just visually "bump" them and return them to their original position).
Placing bombs
- Where is the bomb placed? In most bomberman games, the bomb is placed exactly under you, which causes a bit of an exceptional state as it's the only "normal" way you can share position with a bomb. As soon as you move away from the bomb, you are unable to occupy the same tile again. I don't see a reason we can't do that ourselves, though it means we'll have to accomodate for this in the "tile" enum passed to the player (i.e.
Tile::EmptyFloor(Some(player), Some(bomb))
). - What happens when the player tries to place a bomb and is unable to? (bomb limit). Animating the failure, even if it's just a little bomb with a red cross on top of their head, could do a lot for people to visually "debug" what they did wrong.
Bomb chain reactions
If bomb's blast touches another ticking bomb, it should detonate immediately regardless of its fuse.
Q: Shall we detonate the "secondary" bomb in the very same tick, or perhaps in the next one?
Music + Game Audio
Assuming we're going to want audio (though I'm not sure how the final setup will work, during the meetup).
Music
- As with #4, is copyright a problem? If not, do we take straight from bomberman or go for something different?
- Audio support in bevy is pretty basic, though I can't imagine this being a huge problem for a game like this. If it turned out to be an issue, there are other audio integrations for bevy out there.
Sound effects
- We'll need sound effects for the basic stuff: explosions, powerup pickups, deaths, round countdown...?
- We may want sound effects for players joining and "brain swaps".
WASM actor upload system
At the moment, the number of live players is equal to the number of valid .wasm
player files under crates/bomber_game/assets/players
. For the meetup, we want a system that makes it easy for attendees to upload their compiled players and see them reflected on the game field immediately.
How it would be used
- It would be amazing if we could make it part of
build.rs
so an attendee only needs to runcargo build
on their player crate and have the build script pick up the output and stream it to the right port. Unfortunatelybuild.rs
can do pre-build steps but not really post-build steps as far as I know, so the only ways I can think of making this happen would be a bit hacky. - An alternative could be to come up with a custom
cargo
command, so that attendees can callcargo upload-player
, which will in turn build the crate for thewasm
target and upload the resulting.wasm
file in one go.
Server side
- An option could be to have a bevy system (using one of the network plugins) just picking up connections to a TCP socket and streaming the bytes directly into
.wasm
files. This would then be picked up by the folder watcher, and we'd have a way to mix uploaded players and players we manually "drag and drop" into the server. - Alternatively we could get rid of the folder watching altogether, and have it so the networked
bevy
system directly builds thewasm
asset from the TCP stream. This would be cleaner but lose the benefit of the "drag and drop" option.
Concerns
- Ideally attendees will have only one hero at any given time, so we have to come up with a robust way of identifying which
.wasm
upload belongs to which attendee. We could pin it to IP addresses, or request attendees to implement aplayer_name()
method in the player trait so that we can decide at runtime whether they are a duplicate.
Game rendering
Assuming we have all the necessary sprites from #4.
- Pure sprites, or do we want any particle effects or custom shaders?
- What surface(s) is this meant to be rendered on? I'm imagining a big screen.
- Given the above, will resolution be a problem? We might need pixel-perfect rendering, and there's a good discussion here
Misc gameplay improvements
There are a few tidbits that I've realized while testing the current demo (since it has very recently become fully "playable"). These aren't new features per se, but quick changes that could potentially improve the gameplay experience for the MVP we drafted.
- Bombs explode a bit too fast for the current character move speeds, so it's probably best to increase the fuse timing so players aren't forced to take the immediate next turn into a corridor.
- A typical bomberman action is missing: Placing a bomb while moving! I'm thinking of adding one entry to
Action
withDropBombWhileMoving(Direction)
. Without this, people won't be able to create the classic bomb chains, which we totally need ;). - Bomb limits are missing, which I think are important regardless of whether we have time to make powerups happen. An initial limit of two or three simultaneous bombs seems okay.
- I feel like the character sight range should be higher by default. It's currently 3 tiles, which is barely enough to spot a bomb. Bumping it up to 5 should be good for now.
Assigning myself to this as these are quick, easy wins which will work well for the rest of my week, since I will be busier. If anyone comes up with other improvements to make, post them here and I'll add them to the list.
World upkeep logic
I imagine the game will roughly proceed in alternating phases, spaced by an even number of frames:
- A phase where all players decide and commit their actions, and these actions take effect on the world.
- A phase where all passive world effects trigger (bombs ticking down or exploding, points being granted, etc).
We'll need bevy systems to perform all of these "world upkeep" tasks. Some examples:
- Ticking down the bombs and/or exploding them.
- Increasing the point value of players on the hill.
- Cleaning up dead players, adjusting their point scores, and respawning them.
- Removing the breakable tiles that got hit by an explosion.
Running the game server locally and updating .wasm files crashes the game
This seem to be a Bevy issue, that surfaces when you symlink an asset directory outside of the main Bevy asset directory, as it is currently set up in this repo. I reported it to Bevy: bevyengine/bevy#5689
Queueing/many player support mini-RFC
The problem
With the resolution we're aiming for and the map size that we have, there's a clear limit to the number of players that can compete on the same arena. From my initial testing, I'd say 12 simultaneous players is about as far as we can go before we run out of breathing room. 8 would be ideal.
We want more than 8-12 players to participate, especially after deciding we want to open the event to outside participants and stream it on twitch, so we need to find a way to have everyone play for a fair amount of time and keep them engaged.
A queue system proposal.
I propose we rework the file upload/file handle systems to behave under a simple set of rules:
- If the current game has fewer than MAX players, simply add the players to the current arena.
- Players that die should continue to respawn indefinitely in the current round, taking priority over the queue. This is important not to discourage inexperienced devs by pushing them to the back of the queue after an unfortunate death. The penalty for dying should be losing points, not losing the opportunity to play!
- When a player tries to join a full match, they're instead added to the global queue.
- When a match ends, all players on it get pushed to the back of the queue, and the next set of MAX players get added to the next round.
- Players should be encouraged to re-upload their wasm blobs as much as they like, so reuploading should not affect position in the queue. Reuploading should not even despawn the character: The AI change will happen live.
- When a player is inactive (no new uploads) for a long time and their character has played enough rounds, it will be removed from the queue (this is just to prevent idlers that left the twitch steam long ago from taking space).
There's a couple implicit principles in the proposal that I think we should maintain even if the implementation particulars change:
- When a character starts playing, they should always get five minutes of play. This is why I think it's better to throw in a new set of challengers every round, instead of constantly churning them in the same round every time someone dies.
- People should felt encouraged to experiment. Knowing that your character will stay in the round no matter how badly you do will make people less scared to try crazy things.
An illustrated example
For the example, I'm going to assume that MAX = 4 (the number of players that can play at the same time in an arena) and that players are named alphabetically from A to Z.
- The first round starts, and the game field is empty. 3 minutes pass as people fiddle with the logic.
- Players A, B, C, D join, and they appear in the arena.
- Players E and F join, and the queue is now [E, F] . Those players are notified of their position somehow.
- Player A dies and respawns, but the queue situation is unaffected.
- Players E and C decide to reupload their AI. C continues playing normally without respawning, and E's position in the queue is unaffected.
- The round ends and all players in it are pushed to the back of the queue, which is now [E, F, A, B, C, D].
- The next round starts, with players [E, F, A, B].
- Player G joins, and the queue is now [C, D, G].
- ...etc
As always, open to thoughts, suggestions. implementation concerns, etc :) I'm also unsure how much of this process we want to represent in the UI. Maybe some sort of message signaling who's playing the next round could be fun!
Game rules (Open question)
Which game rules (from bomberman or otherwise) are we going to implement?
General principles
- Players can join asynchronously at any time by uploading their latest actor version.
- If we are to have rounds, joining late is not penalized (in other words, the reward for joining late but with an accurate strategy should be higher than joining early with a poor one).
- Should be easy to parse visually without heavy rules explanations. Anything that isn't obvious should become obvious when reading the
Player
trait to implement.
Discrete movement?
We seemed to roughly agree that discrete movement would work well. Some thoughts on how it could work:
- Increase the frequency of the "universal tick" but make players capable of acting at certain tick intervals depending on their move speeds (e.g. a default bomber would act each 10 ticks, one with multiple boot powerups each 6).
- We need to think of how to resolve moves for cases where two incompatible moves happen simultaneously (e.g. two players moving to the same tile). It would be best not to rely on arbitrary iteration order.
Tiles
What tiles do we want?
Obvious ones:
- Walls, floors, bombs, players, crates (i.e. breakable terrain)
Optional or not so obvious ones:
- Powerups (might be redundant with the "shop" idea, but bomberman is very fun with powerups!) Here's the canonical list from the bomberman wiki.
- Hazards (lava, spikes, etc?) Only makes sense if players can be moved against their will or if the hazards can appear under them (maybe telegraphed/with a timer...)
- Switches that make hazards, powerups, bombs etc spawn.
- "Hill" terrain (i.e. the terrain you're meant to hold to gain points).
Scoring
How do we score the game?
Hill points + powerup bounty idea
- Players/teams gain points per second they spend in the hill. If they leave the hill or die, all points are lost. Also, a good number of their powerups (maybe all?) get spread around their point of death. Every X minutes the round closes, the winner is declared and the map rotates. This way people joining the round late can still win if they manage to be the last one standing in the hill.
- Dead players wouldn't need to be removed from the game; they could just respawn at a free corner and keep playing until they choose to replace their algorithm.
- Question: Should replacing the algorithm be allowed while the character is still alive, or should it be put on hold until death or the next round? If it's allowed, could it happen immediately? It's a silly worry but I wonder if crafty players would think of live-swapping their bomberman brain to manually control the character! (though this would make for an interesting story and make a good argument for Wasm performance). It's tempting to leave it "exploitable" to see if someone is crazy enough to build a virtual controller where each keypress uploads a new algorithm :)
Rounds
Do we want rounds at all? Some thoughts:
- Rounds could be an interesting way to give some closure and rotate the maps, while still keeping the asynchronous join system.
- Competitive bomberman usually starts with a bunch of crates/obstacles blocking the way, so it would be good to have rounds if nothing else to change the pace.
Actor interface
What "window" into the world do we give the actors? How much can they see? What can they do?
- One way to do it would be to have all actions be worth certain number of ticks, so everything takes a bit of time, for example:
- Inspecting a single adjacent tile is free (future calls to the
inspect
function would return None or error out, during the same turn). - Inspecting all your adjacent tiles takes 1 tick (if we want to be fancy we could animate bomberman just looking around).
- Looking at an entire row/file in front of you takes 2 ticks.
- Inspecting a single adjacent tile is free (future calls to the
- If we implement the above, I'm not exactly sure how the API would look. You probably wouldn't have an
inspect
method, but rather a more expressiveAction
return type with more variants than just movement, and a way to retrieve the result of your last action (so for example if you returnAction::Look(North)
, the next turn you'd enter youract
method with anActionResult::Look(Tile)
passed to you. If you returnAction::Move(East)
your next turn would happen later, and you'd get anActionResult::Move(EmptyTile)
). - Alternatively, we can keep it roughly as it is and have
wasm
imports you can call through theWorld
API to inspect your surroundings, and do it as many times as you want during your turn, but have your next turn take longer to happen if you've done too much (go into "tick debt" as it were).
Webassembly module metering
We need to ensure that broken wasm
modules don't hinder the game's progress.
- Time out players that take too long and remove or rename their
wasm
files. - Ensure players that time out or panic are removed from the handle list (deleted or renamed
wasm
files), since at the moment a crashing player is repeteadly spawned causing a large performance hit.
Game UI
How much UI do we actually need?
Essentials:
- Round timer
- Name tags on top of players
- Player score trackers (probably on the side not to clutter the screen too much)
- Player powerup trackers
Optional stuff:
- Map name + next map name (for people to prepare)
- Some form of event logger (e.g. "Team XXX's bomber has entered the battle!")
Do we use the Bevy native UI?
- It's a bit unwieldy and one of the pain points of Bevy as of 0.5, but it's also well documented in the examples.
- An alternative could be the
egui
integration, which is super comfortable to use, but hard to make it look pretty (is this a problem?) - A particular problem I stumbled on was making text live in the world space (as opposed to the UI space) in order to track game elements. This was notoriously difficult back then so I'm hoping it has gotten better.
Improve map generation and representation, develop the tile system.
At the moment, the tile system in the demo is very basic.
Expand ASCII map parsing
- Add more tiles and their associated ASCII characters to represent the current MVP.
- Add spawn point markers to the ASCII representation.
- Add a bevy system to choose the maps to be changed between rounds.
Map representation
Currently, the map is an immutable, Arc
wrapped structure to deal with the limitations of wasm
callbacks, and game objects such as the character and death marker don't reside in the map at all, but are simply rendered on top of it. This wasm
limitation will be gone, so we don't have to worry about Arc
to share references with the wasm
instances.
Some thoughts:
- To be idiomatic in an ECS system we likely don't want the map to be a big struct that literally contains the game elements. Instead renderable elements will be represented by entities containing some kind of
WorldLocation
component. - When passing the "surroundings" to a character's wasm module, we'll probably have to change abstractions a bit and pass
Tile
enums to the character which may contain things in them, e.g.Tile::Wall
,Tile::Floor(None)
,Tile::Floor(Some(Bomb(countdown: 2)))
. So we need a bevy system/function that iterates over all things withWorldLocation
and works out the configuration of these enums to pass to the character.
Helpful crates
There are crates out there designed for this sort of situation that may help us, bevy_tilemap is the original one I looked at, though I see bevy_ecs_tilemap helps representing tiles in a more ECS idiomatic way so it may be worth looking into as well.
Scoring, round and victory logic
We'll need systems to keep track of player score, count down the game time, and switch game state to a victory screen at the end of a round, then scheduling a new one.
- Bevy supports states since the latest version, which help organizing the transition between rounds and to/from a victory screen.
Gather/make basic spritework
I'm assuming 2D rendering, so we'll need some sprites :). I don't know exactly how this will be rendered in the November meetup so I'll leave it to you to define the requirements.
- Is copyright a problem? I imagine it's not an issue for a fun meetup project, but I'm not a lawyer so asking just in case.
- Do we want animation? There should be plenty of bomberman sprite sheets around, but not sure how complicated we want to get here.
Improve the .wasm glue code layer
At the moment the shims around the Player
trait are a bit rough, and it could be a big win to automate as much of the process as possible (within reason) so we don't waste a lot of time keeping the glue code up to date manually as the Player<->World interaction changes.
Some pointers:
- This blog post series, even though it uses
wasmer
instead ofwasmtime
, remains the best reference I've found since he's trying to solve a problem almost identical to ours. - Wasmtime supports a much better way of managing imports and exports to what's currently in the codebase, using a Linker. Doing this properly would also solve some annoying panics I found while testing (for example a
Player
module that doesn't actually look into the result ofinspect
at all would cause the import symbol not to be emitted, which would currently cause a panic as ourspawn_player
function expects exactly one import). - It would be good to think early of some basic form of metering, to handle the case where someone uploads a loop hero (of the
loop {}
kind) and stalls the entire process.
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. ๐๐๐
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google โค๏ธ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.