bevyengine / bevy

A refreshingly simple data-driven game engine built in Rust
https://bevyengine.org
Apache License 2.0
36.45k stars 3.6k forks source link

Add a turn-based example game #9635

Open alice-i-cecile opened 1 year ago

alice-i-cecile commented 1 year ago

How can Bevy's documentation be improved?

Turn-based games are popular and simple, but are surprisingly tricky to figure out how to architect in a framework designed around a game update loop like Bevy.

We should have a simple turn-based game in our examples to demonstrate a reasonable architecture.

EmiOnGit commented 1 year ago

Do you envision a simple but still fully playable game? I'm currently thinking about something like 'tic tac toe' or '4 in a row', what are your thoughts? I'd love to give it a try though

ickshonpe commented 1 year ago

A 'tic tac toe' or '4 in a row' game wouldn't be bad to have as an example but normally you'd implement one as just a grid of buttons that when clicked the UI changes the state of another button in response, until someone wins. It wouldn't capture any of the complexity of a roguelike or rebelstar-style game.

JMS55 commented 1 year ago

I used to work on a 2d roguelike in bevy. This was ~2 years ago, before the current schedule system. Imo a simple roguelike would be ideal.

The biggest issue with a turn based game is the discrete nature of turns and game logic, mixed with the non-discrete nature of everything else. You still want the typical scheduler for things like rendering, animation ticking, sound effects and music, etc.

At the same time, you want to run game logic systems at a much slower pace, but also interspersed with the animations. So you'll want something like a spell that summons a poison cloud, which damages all nearby enemies, and then one of the enemies explode, which damages others, and then the turn finally switches. But that all needs to be run over multiple frames with animations running, and the animations need to be kept in sync and started and stopped by the game logic.

At the time, the way I did this was with a manually coded action queue, and passing &mut World around manually. Using events or the not-yet-implemented one-shot systems might be cleaner. I was even thinking of some kind of async system runner that would let you write synchronous gameplay logic in systems, and then run them over multiple frames.

So yeah TLDR; non-realtime logic systems are hard, and I think we might want some kind of async system runner for this kind of thing.

Curious to hear other people's thoughts.

EDIT: A roguelike would also be very useful for showing the pattern of storing a 2d grid of entities in a resource, so that you can do spatial queries (what other entities are around ), in addition to querying the position component of an entity. This is a pretty frequent question I see get asked.

rlidwka commented 1 year ago

Turn-based games are popular and simple, but are surprisingly tricky to figure out how to architect in a framework designed around a game update loop like Bevy.

Why is it tricky?

Turn-based games have a game loop - that's "turn". Which is naturally represented in Bevy with a custom schedule, that you manually run when user presses "end turn" button.

Presumably, it should also have an AppState or a Resource that defines whose turn is it.

ItsDoot commented 1 year ago

Turn-based games have a game loop - that's "turn". Which is naturally represented in Bevy with a custom schedule, that you manually run when user presses "end turn" button.

That is basically what I've presented here: https://gist.github.com/ItsDoot/c5e95258ec7b65fb6b2ace32fac79b7e

JohnForster commented 1 year ago

I tangled myself up in knots trying to recreate Advance Wars in Bevy, an example like this would've been invaluable.

wandbrandon commented 11 months ago

With the new one-shot systems in place for Bevy 0.12.0, perhaps an example of setting up a simple turn queue for final fantasy type games would be helpful?