Skip to content

Commit

Permalink
Use a prefab for animation instead of doing it by hand.
Browse files Browse the repository at this point in the history
Also creates the entire scene from a config file, which means adding static
objects (and objects of already-known types) doesn't require recompilation.
  • Loading branch information
IanTayler committed Nov 13, 2020
1 parent 4d12174 commit 5a89cb1
Show file tree
Hide file tree
Showing 13 changed files with 358 additions and 127 deletions.
Binary file added assets/sprites/field_ichi_1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
224 changes: 224 additions & 0 deletions assets/sprites/field_ichi_1.ron
Original file line number Diff line number Diff line change
@@ -0,0 +1,224 @@
#![enable(implicit_some)]
Prefab(
entities: [
// Player
PrefabEntity(
data: (
// SpriteScenePrefab
sprite_scene: (
// SpriteSheetPrefab with index 0
sheet: Sheet(
// TexturePrefab
texture: File("sprites/field_ichi_1.png", (
"IMAGE", (
sampler_info: (
min_filter: Nearest,
mag_filter: Nearest,
mip_filter: Nearest,
wrap_mode: (Tile, Tile, Tile),
lod_bias: (0),
lod_range: (
start: (0),
end: (8000),
),
comparison: None,
border: (0),
normalized: true,
anisotropic: Off,
),
),
)),
sprites: [
// All sprites in the field spritesheet.
// Includes player sprites, nets, ball.
List((
texture_width: 52,
texture_height: 80,
sprites: [
(x: 0, y: 0, width: 16, height: 16),
(x: 16, y: 0, width: 16, height: 16),
(x: 32, y: 0, width: 16, height: 16),
(x: 0, y: 16, width: 16, height: 16),
(x: 16, y: 16, width: 16, height: 16),
(x: 32, y: 16, width: 16, height: 16),
(x: 0, y: 32, width: 16, height: 16),
(x: 16, y: 32, width: 16, height: 16),
(x: 32, y: 32, width: 16, height: 16),
(x: 0, y: 48, width: 16, height: 16),
(x: 16, y: 48, width: 16, height: 16),
(x: 32, y: 48, width: 16, height: 16),
(x: 0, y: 64, width: 48, height: 8), // net upper 12
(x: 0, y: 72, width: 48, height: 8), // net lower 13
(x: 48, y: 0, width: 4, height: 4), // ball 14
],
))
],
name: "field",
),
// SpriteRenderPrefab
render: (
sheet: "field",
// 2 is the default standing player.
sprite_number: 2,
),
// Transform
// TODO: Can I live without this? I want to set it dynamically.
transform: (
translation: (128.0, 128.0, 0.0),
),
),
// AnimationSetPrefab
animation_set: (
animations: [
(
// AnimationId
PlayerRun,
(
samplers: [
(
0,
SpriteIndex,
(
// Time of key frames
input: [0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8],
// Sprite indexes from SpriteSheet for key frames
output: [2, 3, 0, 3, 2, 4, 1, 4, 2],
function: Step,
),
),
],
),
),
(
// AnimationId
PlayerCelebrate,
(
samplers: [
(
1,
SpriteIndex,
(
// Time of key frames
input: [0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.9, 1.0],
// Sprite indexes from SpriteSheet for key frames
output: [2, 5, 8, 5, 2, 7, 6, 7, 2],
function: Step,
),
),
],
),
),
(
// AnimationId
PlayerJump,
(
samplers: [
(
2,
SpriteIndex,
(
// Time of key frames
input: [0.0, 0.3, 0.5, 0.7, 0.8],
// Sprite indexes from SpriteSheet for key frames
output: [2, 7, 6, 7, 2],
function: Step,
),
),
],
),
),
(
// AnimationId
PlayerStand,
(
samplers: [
(
3,
SpriteIndex,
(
// Time of key frames
input: [
0.0, 2.4, 2.45, 2.5, 2.55,
2.6, 2.65, 2.7, 2.75, 2.8,
2.85, 2.9, 2.95,
],
// Sprite indexes from SpriteSheet for key frames
output: [
2, 8, 10, 11, 10,
9, 8, 9, 10, 11,
10, 8, 2
],
function: Step,
),
),
],
),
),
],
),
// What defines the specific type of entity.
extras: PlayerData(
player: (
height: 16.0,
width: 16.0,
speed: 32.0
)
),
),
),
// LowerNet
PrefabEntity(
data: (
sprite_scene: (
render: (
sheet: "field",
sprite_number: 13,
),
transform: (
translation: (128.0, 4.0, 0.1),
),
),
animation_set: (
animations: [],
),
extras: StaticData,
),
),
// UpperNet
PrefabEntity(
data: (
sprite_scene: (
render: (
sheet: "field",
sprite_number: 12,
),
transform: (
translation: (128.0, 252.0, -0.1),
),
),
animation_set: (
animations: [],
),
extras: StaticData,
),
),
// Ball
PrefabEntity(
data: (
sprite_scene: (
render: (
sheet: "field",
sprite_number: 14,
),
transform: (
translation: (128.0, 118.0, 0.1),
),
),
animation_set: (
animations: [],
),
extras: StaticData,
),
),
],
)
Binary file removed assets/sprites/nets_ichi_1.png
Binary file not shown.
8 changes: 0 additions & 8 deletions assets/sprites/nets_ichi_1_desc.ron

This file was deleted.

Binary file removed assets/sprites/player_ichi_1.png
Binary file not shown.
15 changes: 0 additions & 15 deletions assets/sprites/player_ichi_1_desc.ron

This file was deleted.

2 changes: 2 additions & 0 deletions src/components/net.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@ extern crate amethyst;

use amethyst::ecs::{Component, DenseVecStorage};

#[derive(Debug)]
pub enum NetSide {
Upper,
Lower,
}

#[derive(Debug)]
pub struct Net {
side: NetSide,
}
Expand Down
31 changes: 9 additions & 22 deletions src/components/player.rs
Original file line number Diff line number Diff line change
@@ -1,20 +1,19 @@
extern crate amethyst;

use amethyst::ecs::{Component, DenseVecStorage};
use amethyst::{
assets::PrefabData,
derive::PrefabData,
ecs::{Component, DenseVecStorage, Entity, WriteStorage},
Error,
};
use serde::{Deserialize, Serialize};

use crate::config;

// TODO: change this to use amethyst's animation types
// and load them from configuration files.
const PLAYER_ANIMATION_TIME: f32 = 0.5;
const PLAYER_ANIMATION_FRAMES: usize = 8;
const PLAYER_ANIMATION_FRAME_VECTOR: [usize; PLAYER_ANIMATION_FRAMES] = [2, 3, 0, 3, 2, 4, 1, 4];

#[derive(Clone, Copy, Debug, Default, Serialize, Deserialize, PrefabData)]
#[prefab(Component)]
pub struct Player {
pub height: f32,
pub width: f32,
pub speed: f32,
moment: f32,
}

impl Player {
Expand All @@ -23,20 +22,8 @@ impl Player {
width: config::PLAYER_WIDTH,
height: config::PLAYER_HEIGHT,
speed: config::DEFAULT_PLAYER_SPEED,
moment: 0.0,
}
}

pub fn add_delta(&mut self, delta: f32) {
self.moment = (self.moment + delta / PLAYER_ANIMATION_TIME).fract()
}

pub fn frame(&self) -> usize {
let scaled_moment = self.moment * (PLAYER_ANIMATION_FRAMES + 1) as f32;
let position = scaled_moment.trunc() as usize;
// The modulo wouldn't be necessary if not for floating point rounding errors.
PLAYER_ANIMATION_FRAME_VECTOR[position % PLAYER_ANIMATION_FRAMES]
}
}

impl Component for Player {
Expand Down
Loading

0 comments on commit 5a89cb1

Please sign in to comment.