Adding a Ball Config
For simplicity, we will wrap all of our Config objects into a single PongConfig object backed by a single
config.ron file, but know that you can just as easily keep them in separate files and read from each file
separately.
To prepare for our BallConfig, add the following line to the top of config.rs:
use amethyst::core::cgmath::Vector2;
The BallConfig will replace the BALL_VELOCITY_X, BALL_VELOCITY_Y, BALL_RADIUS, and BALL_COLOR
variables. We'll use a Vector2 to store the velocity for simplicity and to demonstrate how to add
a non-trivial data type to a RON file. The BALL_COLOR was originally an array, but [Serde][serde] and RON
handle arrays as tuples, so it will read in a tuple and convert the colour values to an array if needed by a
particular function (e.g., in pong.rs).
#[derive(Debug, Deserialize, Serialize)]
pub struct BallConfig {
pub velocity: Vector2<f32>,
pub radius: f32,
pub colour: (f32, f32, f32, f32),
}
We'll also add the Default trait to this config that will match what the full example uses.
impl Default for BallConfig {
fn default() -> Self {
BallConfig {
velocity: Vector2::new(75.0, 50.0),
radius: 2.5,
colour: (1.0, 0.0, 0.0, 1.0),
}
}
}
Still in config.rs, add the following structure definition at the very bottom. This structure will be
backed by the whole config.ron file.
#[derive(Debug, Default, Deserialize, Serialize)]
pub struct PongConfig {
pub arena: ArenaConfig,
pub ball: BallConfig,
}
Replacing Ball Constants
Now we need to replace our usage of the BALL_* constants with our new BallConfig.
We use these values in pong.rs in the initialise_ball() function, so the substition is even simpler than
the ArenaConfig.
In pong.rs, underneath our loading of the ArenaConfig, add the following lines
let (velocity_x, velocity_y, radius, colour) = {
let config = world.read_resource::<BallConfig>();
let c: [f32; 4] = [
config.colour.0,
config.colour.1,
config.colour.2,
config.colour.3,
];
(config.velocity.x, config.velocity.y, config.radius, c)
};
Our functions expect a [f32; 4] array, so we had to convert the tuple to an array. This is relatively
simple to do, but for more complex arrays it might be worth it to add a function to the impl BallConfig to
avoid duplicating this effort.
Now, within the initialise_ball function, replace BALL_VELOCITY_X with velocity_x, BALL_VELOCITY_Y
with velocity_y, BALL_RADIUS with radius, and BALL_COLOR with color.
Modifying the initialisation
Now we will modify our application initialisation. We don't want everyone to always access all the config files, so we need to add each resource separately so systems can use only what they want.
First, we need to change what main.rs is using. Change
use config::ArenaConfig;
to
use config::PongConfig;
Now, modify the run() function, from
let arena_config = ArenaConfig::load(&config);
[..]
.with_resource(arena_config)
.with_bundle(PongBundle::default())?
to
let pong_config = PongConfig::load(&config);
[..]
.with_resource(pong_config.arena)
.with_resource(pong_config.ball)
.with_bundle(PongBundle::default())?
Adding the BallConfig to config.ron
Now we need to modify our configuration file to allow multiple structures to be included. This is actually very easy with RON; we just add an additional level of nesting.
(
arena: (
height: 100.0,
width: 100.0,
),
ball: (
velocity: Vector2(
x: 75.0,
y: 50.0,
),
radius: 2.5,
color: (1.0, 0.647, 0.0, 1.0),
),
)
This configuration sets the ball to be orange, while retaining the same size and velocity as the original example.
Click here to continue to the last chapter, configuring paddles