👁️ Eyes on me. Let’s go.

This update contains many improvements to game play and configuration.

What’s new:

Camera moves to track players, whilst staying within map bounds.

Play sounds from object configuration.

Spawn any kind of object, on any sequence.

Transfer momentum when hit.

Configuration has the following changes:

Markup language has switched from TOML to YAML.

Acceleration for objects can be specified.

Arbitrary sequence names can be used.

Spawn position and velocity configuration use named axes.

The new version can be downloaded on itch.io.

Play

Camera Tracking On Wide Maps

Camera shifted towards left.

Camera centered between tracked players.

Camera shifted towards right.

On maps with a play area larger than the window, the game camera will follow the players. It will also be weighted towards the direction that players are facing.

Hit Momentum

Weak shot does not transfer much momentum.

Medium shot transfers more momentum.

When hit, acceleration will be applied to objects – weak attacks will only move objects a little; strong attacks will knock them further.

Create

Configuration

Markup Language

The markup language has been switched from TOML to YAML. This reduces repetition of key names for hierarchical data.

TOML: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 [sequences.stand] next = "repeat" [sequences.stand.transitions.press_attack] next = "stand_attack_weak" [[sequences.stand.transitions.release_attack]] next = "stand_attack_strong" requirements = [{ charge = 40 }] [[sequences.stand.transitions.release_attack]] next = "stand_attack_mid" requirements = [{ charge = 13 }] [[sequences.stand.frames]] wait = 8 sprite = { sheet = 0 , index = 0 } body = [{ box = { x = 16 , y = 10 , w = 28 , h = 53 } }]

YAML: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 sequences: stand: next: "repeat" transitions: press_attack: { next: "stand_attack_weak" } release_attack: - next: "stand_attack_strong" requirements: [{ charge: 40 }] - next: "stand_attack_mid" requirements: [{ charge: 13 }] frames: - wait: 8 sprite: { sheet: 0 , index: 0 } body: [{ box: { x: 16 , y: 10 , w: 28 , h: 53 } }]

Additions

Sound can be specified per frame: 1 2 3 4 5 6 7 8 sequences: run: # .. frames: - wait: 2 sound: "default/object/character/rox/rox_run.wav" # ..

Any kind of object can be spawned, on specified sequence: 1 2 3 4 5 6 7 # rox/object.yaml spawns: - object: "default/rox" # Spawns a Rox character. position: { x: - 20 , y: 0 } # Position of the spawned object relative to this object. velocity: { z: - 20 } # Velocity of the spawned object relative to this object. sequence: "run_clone" # Spawned character begins on the "run_clone" sequence.

Object acceleration to the object: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 sequences: run: next: "repeat" # Sequence level acceleration -- applied to all frames. acceleration: # Apply the acceleration continuously in the frame. kind: "continuous" x: { multiplier: "x_axis" , value: 6.0 } # Multiply the value with X axis input. z: { multiplier: "z_axis" , value: 1.5 } # Multiply the value with Z axis input. frames: - wait: 2 # Override the sequence level acceleration for this frame. acceleration: kind: "once" # Apply the acceleration at the beginning of the frame. x: 8.0 # Use the acceleration value as is. # ..

Hit interactions inflict acceleration: 1 2 3 4 interactions: # Hit object velocity increases by 10 units to the right, and 5 units upwards. - hit: { acceleration: { x: 10 , y: 5 }, .. }

Spriting

Walk Run Jump

This time sprites added to Rox to test the new features – though not strictly necessary, it’s useful to see sprites that represent actions that a feature is built for. The above sprites are made using aseprite.

Sound Effects

Buster Shot Weak sound wave

The sound effects for Rox’s run, and buster shots – all 3 charge levels – are voice recordings, and edited using Audacity. Yeap, I was making “pew!” and “wsshhhh” sounds in my room.

New Moves

Rox clone attack

With arbitrary sequence IDs added, new behaviours can easily be added to objects. The above move is defined with the following (trimmed) configuration:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 sequences: run_attack_clone: # .. frames: - # .. spawns: - { object: "default/rox" , position: { x: - 20 }, velocity: { z: - 20 }, sequence: "run_clone" } - { object: "default/rox" , position: { x: - 10 }, velocity: { z: - 10 }, sequence: "run_clone" } - { object: "default/rox" , position: { x: - 10 }, velocity: { z: 10 }, sequence: "run_clone" } - { object: "default/rox" , position: { x: - 20 }, velocity: { z: 20 }, sequence: "run_clone" } run_clone: next: "delete" acceleration: kind: "continuous" x: 8.0 frames: - wait: 20 sprite: { sheet: 0 , index: 13 } - wait: 10 sprite: { sheet: 0 , index: 13 } spawns: - object: "default/buster_shot_weak" position: { x: 22 , y: 33 } velocity: { x: 10 , y: 0 }

What’s Next

Yay, both the arbitrary sequence IDs and kinematics in configuration items have been implemented, and a lot more than that. The next period will focus on:

Better menus / user interfaces.

Better code maintenance.

Just those two?

Yeap. It takes a lot of effort to make a good menu; code maintenance needs substantial work – this last development cycle traded maintainability for functionality. Until then.

Support Me

The game is still in development; if you would like to support me, please consider becoming a Patron.