Skip to content

Commit 1086e5f

Browse files
committed
Wrote the whole cannon_practice scenario and some of the labrinth scenario
1 parent 5d2e659 commit 1086e5f

2 files changed

Lines changed: 71 additions & 4 deletions

File tree

scenarios/cannon_practice.md

Lines changed: 52 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,64 @@ In this scenario you will create a cannon that sits on the bottom left side of t
88

99
1. Follow the instructions in the [Common Setup](https://github.com/CleanCut/rusty_engine/tree/main/scenarios#common-setup-do-this-first) section of the scenarios readme to set up the skeleton of the project.
1010

11+
## Game State & Constants
12+
13+
1. Define a game state struct with fields for:
14+
- The firing magnitude of the cannon (an `f32`)
15+
- The rotation of the cannon (an `f32`)
16+
- The current velocity of the cannon ball (a `Vec2`)
17+
1. Define a constant for acceleration due to gravity. The unit will be pixels per second per second.
18+
1. Decide on a sprite to use as a cannon ball
19+
1. Decide on a sprite to use as the cannon
20+
1. Decide on a sprite to use for the goal that you are trying to hit
21+
1. Decide on a sprite (or sprites) to use for obstacles that you should avoid hitting
22+
1123
## Game Initialization
1224

1325
In your `// setup goes here` section of `main()`...
1426

15-
1.
27+
1. Create the initial game state struct with good starting values
28+
1. Create and place the cannon, obstacles, and goal sprites. You may use the `level_creator` example to do this, if you wish.
29+
- Place the cannon on the lower left side of the screen
30+
- Use a field from the game state to set the rotation of the cannon
31+
- Place a single obstacle in lower middle of the screen (so you have to fire over it)
32+
- Place the goal on the lower right side of the screen
33+
1. Create the text for displaying the firing magnitude of the cannon, place it in the top left corner of the screen.
34+
1. If you want music, start it now.
1635

1736
## Gameplay Logic
1837

1938
In your `game_logic(...)` function...
2039

21-
1.
40+
1. Decide which keyboard/mouse input will control the rotation of the cannon, and implement rotating the cannon.
41+
- Constrain the min/max angle of rotation to angles in the first quadrant (from straight up to straight right) with [the `.clamp` method](https://doc.rust-lang.org/std/primitive.f32.html#method.clamp) and the [`UP` and `RIGHT` constants](https://docs.rs/rusty_engine/latest/rusty_engine/#constants).
42+
1. Decide which keyboard/mouse input will fire the cannon. Implement it so that pressing (whatever you chose) creates a cannon ball sprite, but only if one does not exist. Place it at the same coordinates as the cannon, but at a layer lower than the cannon so the cannon obscures it until it is out from underneath it.
43+
- Play a sound when the cannon is fired.
44+
1. Set the initial velocity `Vec2` for the cannon ball. This is fairly straightforward math:
45+
```rust
46+
let initial_cannonball_velocity = Vec2::new(
47+
game_state.firing_magnitude * cannon.rotation.cos(),
48+
game_state.firing_magnitude * cannon.rotation.sin(),
49+
);
50+
```
51+
52+
1. Move the cannon ball sprite by the amount stored in the game state's velocity field multiplied by `engine_state.delta_f32` each frame. At this point, you should be able to run the game, rotate the cannon, fire the cannon, and see the cannon move across the screen in a straight line.
53+
1. Implement the gravity logic. Each frame, subtract (_gravity constant_ * `engine_state.delta_f32`) from the "Y" value of the cannon ball's velocity.
54+
1. Decide which keyboard/mouse input will change the firing magnitude of the cannon, and implement it.
55+
- Constrain the firing magnitude between `0.0` and some semi-reasonable value.
56+
- Every time the firing magnitude changes, change the value of the `Text` that is displaying it in the top left corner of the screen. Don't change the value of the `Text` if the firing magnitude didn't change.
57+
1. Detect collisions between the cannon ball and obstacles. The cannon ball should be destroyed if it hits an obstacle.
58+
1. For collisions to be detected between two sprites, the `.collision` field of _both_ sprites must be set to true. Set this field on the cannon ball, the obstacles, and the goal.
59+
1. Play a sound when the cannon ball hits an obstacle
60+
1. Detect collisions between the cannon ball and the goal. The game is won if the cannon ball hits the goal.
61+
1. Play a sound when the cannon ball hits the goal.
62+
63+
64+
## Challenge
65+
66+
- Introduce constant wind that varies between shots
67+
- Make the obstactle move, rotate, or scale dynamically to make it so you have to time your shot correctly as well
68+
- Replace the `Text` displaying the magnitude of your starting velocity with a visual slider (literally slide a barrier from the edge of the screen to some pre-defined point)
69+
- Make destructible obstactles that reduce the cannon ball's velocity by half in the X direction
70+
- Allow the cannon to move a small distance in the +/- X direction
71+
- Add scorekeeping and alter the layout of the obstacles each time the cannon hits the goal

scenarios/labrinth.md

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,31 @@ This game consists of a [Labrinth](https://en.wikipedia.org/wiki/Labyrinth) or m
88

99
1. Follow the instructions in the [Common Setup](https://github.com/CleanCut/rusty_engine/tree/main/scenarios#common-setup-do-this-first) section of the scenarios readme to set up the skeleton of the project.
1010

11+
## Game State
12+
13+
1. Define a game state struct with fields for:
14+
- Current velocity of the marble (a `Vec2`)
15+
- Lives left (a u8)
16+
1. Choose a sprite to represent the player's marble
17+
1. Choose a sprite to represent the starting area or spot
18+
1. Choose a sprite to represent holes in the labrinth
19+
1. Choose a sprite to represent the ending area or spot
20+
1. Choose a sprite to represent walls of the labrinth
21+
1122
## Game Initialization
1223

1324
In your `// setup goes here` section of `main()`...
1425

15-
1.
26+
1. Use the `level_creator` example to create a labrinth (maze) with the sprite you selected for walls.
27+
- Place "holes" as obstacles to avoid.
28+
- Place one "starting area" sprite, where the marble will start on top of
29+
- Place one "ending area" sprite, which will signal winning the game when touched
30+
- Save out the game, copy and paste the sprite positioning code into your `main.rs`
31+
1. Create the player's marble sprite and place it at the same coordinates as the "starting area" sprite, but at a high layer so it will be on top of any sprites it overlaps.
32+
1. If you would like music, start playing it now.
1633

1734
## Gameplay Logic
1835

1936
In your `game_logic(...)` function...
2037

21-
1.
38+
1. We will move the marble by virtually tilting the whole labrinth. The relative movement of the mouse will do the tilting. The more tilted the labrinth is, the faster the marble will accelerate in that direction.

0 commit comments

Comments
 (0)