Skip to content

Conversation

@LuHaot1an
Copy link

Summary

This PR adds a Projectile Attack example: a simple 2D projectile mini-game built with Mesa (simulation) + Solara (visualization). Players control a stationary tank, tune angle/power, and fire shells to hit a target. The example includes optional moving target, a fixed wall obstacle, and a trajectory trace overlay.

Motive

Explore the possibility of applying ABM in game. By using agents, the game can simulate physical feedback in the real world, such as the effect of gravity.

Implementation

  • agents.py: defines Tank, Shell, Target, Wall.
  • model.py: builds the Mesa model, grid, wall, trajectories, firing mechanics, and win/lose state.
  • run.py: Solara UI for controls, rendering the grid and overlays, and user interactions.

Some rules:

  • Only one shell can exist at a time; press Fire to launch when no shell is active.
  • Shell motion follows gravity.
  • Hitting the ground, leaving the grid, or striking the wall removes the shell; hitting the target ends the round and shows a win message.
  • You have at most 5 shots; after all shots are used, the game stops and asks you to reset.
  • If target movement is enabled, it moves vertically every 3 steps within bounds (y from 1 to 25, clamped to grid height).
  • The wall is fixed at x=17 with height 10 (from y=1 to y=10).

Usage Examples

From the project root: solara run run.py

Additional Notes

To start the game:

  • First, click the "Pause" button on the left to start the simulation. One simulation can be regarded as one game. In one game, you have five chances to fire the cannonball. Hitting the target is considered a success in this game, otherwise it is a failure. After the game ends, you can click the "Reset" button on the left to reset and start the next game.
  • For each launch, you can adjust sliders (angle, power), then press Fire. If the "Fire" button is gray and unclickable, remember to click the "Reloading" button beside it.
  • You can also make the target move to increase the difficulty.
tank_game_vis

Copy link
Member

@EwoutH EwoutH left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some goofy fun!

We currently don't have games in our repo, but maybe we should. I'm going to discuss that in a bit.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The convention is to use app.py for Solara visualisations.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have already modified the file name.


renderer = SpaceRenderer(model, backend="matplotlib")
renderer.draw_structure()
renderer.draw_agents(agent_portrayal)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FutureWarning: Passing agent_portrayal to draw_agents() is deprecated and will be removed in Mesa 4.0. Use setup_agents(agent_portrayal, **kwargs) before calling draw_agents().
renderer.draw_agents(agent_portrayal)

See mesa/mesa#3202

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The version of Mesa I'm using is 3.3.1, but it seems that there is no "setup_agents" method. Therefore, I adopted a compatibility approach to ensure that my code can run on both Mesa 3.3.1 and Mesa 4.0. :

if hasattr(renderer, "setup_agents"):
renderer.setup_agents(agent_portrayal).draw_agents()
else:
renderer.draw_agents(agent_portrayal)

renderer = SpaceRenderer(model, backend="matplotlib")
renderer.draw_structure()
renderer.draw_agents(agent_portrayal)
renderer.draw_propertylayer(propertylayer_portrayal)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FutureWarning: Passing propertylayer_portrayal to draw_propertylayer() is deprecated and will be removed in Mesa 4.0. Use setup_propertylayer(propertylayer_portrayal) before calling draw_propertylayer().

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The same modification method as above :

if hasattr(renderer, "setup_propertylayer"):
renderer.setup_propertylayer(propertylayer_portrayal).draw_propertylayer()
else:
renderer.draw_propertylayer(propertylayer_portrayal)

@LuHaot1an
Copy link
Author

@EwoutH Got it! I'll fix this in the next couple of days.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants