Skip to content

Commit

Permalink
Feat/blink and layer to z (#168)
Browse files Browse the repository at this point in the history
* feat: Blink animation

* chore: Rename layer to z in coords and position
  • Loading branch information
suspistew authored Aug 15, 2021
1 parent 8f89259 commit ee61b50
Show file tree
Hide file tree
Showing 16 changed files with 107 additions and 69 deletions.
18 changes: 8 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,27 +7,26 @@ Scion is a 2D game library made in rust.
## Why this project ?

Well, firstly because it' a good way to learn.
Well, firstly because it' a good way to learn.
Then, because I wanted to create something with modest goals, focused on ease of use and a short list of principles that also serves as a guideline.

Then because a lot of projects these days focus on adding a lot of feature pretexting feature parity with big editors or game engines.
Here I focus on the features that I really need for my projects. I won't add things just because they are cool, but because I need them in
a game project

Scion relies on a short list of principles that also serves as a guideline.
Scion is not 'inspired' by any other engine, it's inspired by the needs from real projects.

### Goals

- Strong focus on **2D** only.
- **Easy** and **Fun** to use.
- Clean and readable source code.
- Tiled integration
- Maybe one day (Editor)
- Clean and readable source code
- I hope one day (Editor)

### Non goals

- Ultra/over optimized code and performances. For this, please try other engines or build your own !
- 3D

## Documentations, Tutorials ?

Yes, they are planned and being worked on. If you want to see scion in action, check the examples for now.

## Why ECS ?

Expand All @@ -46,7 +45,6 @@ These are the dependencies this project is relying on. Thanks to these awesome c
- <a href="https://github.com/amethyst/legion" target="blank">legion</a> (Entity component system)
- <a href="https://github.com/termhn/ultraviolet" target="blank">ultraviolet</a> (Maths)


## Showcase

<img src="./examples/taquin/taquin.gif" alt="Taquin" style="width:300px"/>
Expand Down
14 changes: 7 additions & 7 deletions examples/bomberman/character_control_system.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ pub fn controller(
.get(posx + 1).unwrap() == &0
{
character.pos_x += 1;
animations.run_animation("MOVE_RIGHT".to_string());
animations.run_animation("MOVE_RIGHT");
}
});
inputs.keyboard_mut().on_key_pressed(KeyCode::Left, || {
Expand All @@ -37,7 +37,7 @@ pub fn controller(
.get(posx - 1).unwrap() == &0
{
character.pos_x -= 1;
animations.run_animation("MOVE_LEFT".to_string());
animations.run_animation("MOVE_LEFT");
}
});
inputs.keyboard_mut().on_key_pressed(KeyCode::Up, || {
Expand All @@ -48,7 +48,7 @@ pub fn controller(
.get(posx).unwrap() == &0
{
character.pos_y -= 1;
animations.run_animation("MOVE_TOP".to_string());
animations.run_animation("MOVE_TOP");
}
});
inputs.keyboard_mut().on_key_pressed(KeyCode::Down, || {
Expand All @@ -59,15 +59,15 @@ pub fn controller(
.get(posx).unwrap() == &0
{
character.pos_y += 1;
animations.run_animation("MOVE_BOTTOM".to_string());
animations.run_animation("MOVE_BOTTOM");
}
});
inputs.keyboard_mut().on_key_pressed(KeyCode::Space, || {
let mut animations =
Animations::single("EXPLODE".to_string(), bomb_animations::explode());
animations.run_animation("EXPLODE".to_string());
Animations::single("EXPLODE", bomb_animations::explode());
animations.run_animation("EXPLODE");
cmd.push((
Transform::from_xy_with_layer(
Transform::from_xyz(
(character.pos_x * 64) as f32,
(character.pos_y * 64) as f32,
level_data.tilemap.len() + 1,
Expand Down
4 changes: 2 additions & 2 deletions examples/bomberman/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ impl SimpleGameLayer for BombermanLayer {
Some(
*level
.tilemap
.get(p.layer())
.get(p.z())
.unwrap()
.values
.get(p.y())
Expand Down Expand Up @@ -106,7 +106,7 @@ fn create_char(
level: &Level,
) -> (Transform, Sprite, AssetRef<Material>, Animations, BombermanInfos) {
(
Transform::from_xy_with_layer(
Transform::from_xyz(
(level.character_x * 64) as f32,
(level.character_y * 64) as f32,
level.tilemap.len() + 2,
Expand Down
4 changes: 2 additions & 2 deletions examples/mario/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ fn add_background(world: &mut World) {
let background = (
Rectangle::new(2560., 640., None),
Material::Texture(app_base_path().join("examples/mario/assets/level.png").get()),
Transform::from_xy_with_layer(0., 0., 1),
Transform::from_xyz(0., 0., 1),
);
world.push(background);
}
Expand All @@ -160,7 +160,7 @@ fn add_character(world: &mut World) -> Entity {
ColliderType::Square(64),
),
Square::new(64., None),
Transform::from_xy_with_layer(256., 320., 2),
Transform::from_xyz(256., 320., 2),
Material::Color(Color::new_rgb(100, 120, 23)),
))
}
Expand Down
8 changes: 4 additions & 4 deletions examples/tetris/layer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,14 +62,14 @@ fn add_score_ui(world: &mut World) -> Entity {
let txt = UiText::new("SCORE".to_string(), font.clone());
let mut transform = Transform::default();
transform.append_translation(394., 250.);
transform.set_layer(2);
transform.set_z(2);

world.push((txt, transform));

let txt = UiText::new("".to_string(), font);
let mut transform = Transform::default();
transform.append_translation(394., 290.);
transform.set_layer(2);
transform.set_z(2);
world.push((txt, transform))
}

Expand All @@ -78,7 +78,7 @@ fn add_main_ui_mask(world: &mut World) {
let image = UiImage::new(544., 704., path);

let mut t = Transform::default();
t.set_layer(0);
t.set_z(0);
world.push((image, t));
}

Expand All @@ -87,7 +87,7 @@ fn add_ui_top_overflow(world: &mut World) {
let image = UiImage::new(324., 32., path);

let mut t = Transform::default();
t.set_layer(2);
t.set_z(2);
t.append_translation(32., 0.);
world.push((image, t));
}
2 changes: 1 addition & 1 deletion examples/tetris/systems/piece_system.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ pub fn initialize_bloc(
coord_x * BLOC_SIZE + offset.0 * BLOC_SIZE,
coord_y * BLOC_SIZE + offset.1 * BLOC_SIZE,
);
bloc_transform.set_layer(1);
bloc_transform.set_z(1);
let tuple = (
bloc_transform,
Sprite::new(if is_next_bloc { tetris.next_piece.color } else { tetris.active_piece.color }),
Expand Down
13 changes: 8 additions & 5 deletions examples/world-cup/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,19 +27,18 @@ pub struct WorldCup {
impl SimpleGameLayer for WorldCup {
fn on_start(&mut self, world: &mut World, _resources: &mut Resources) {
let animation = Animation::new(
Duration::from_millis(2000),
vec![AnimationModifier::color(60, Color::new(125, 176, 0, 1.0))],
Duration::from_millis(500),
vec![AnimationModifier::blink(1)],
false,
);

let animations = Animations::single("color".to_string(), animation);
let animations = Animations::single("color", animation);

self.entity = Some(world.push((
Square::new(500., None),
Transform::from_xy(100., 100.),
Material::Color(Color::new(0, 0, 255, 1.0)),
animations,
Hide,
)));

world.push((
Expand All @@ -56,7 +55,11 @@ impl SimpleGameLayer for WorldCup {
let mut entry = world.entry_mut(*self.entity.as_ref().unwrap()).unwrap();
let animations = entry.get_component_mut::<Animations>().unwrap();
resources.inputs().keyboard_mut().on_key_pressed(KeyCode::P, || {
animations.run_animation("color".to_string());
if animations.any_animation_running() {
animations.stop_animation("color",false);
}else{
animations.loop_animation("color");
}
});
}
}
Expand Down
33 changes: 23 additions & 10 deletions src/core/components/animations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,17 @@ impl Animations {
pub fn new(animations: HashMap<String, Animation>) -> Self { Animations { animations } }

/// Create a new Animations component with a single animation provided
pub fn single(name: String, animation: Animation) -> Self {
pub fn single(name: &str, animation: Animation) -> Self {
let mut animations = HashMap::new();
animations.insert(name, animation);
animations.insert(name.to_string(), animation);
Animations { animations }
}

fn run(&mut self, animation_name: String, status: AnimationStatus) -> bool {
if self.animations.contains_key(animation_name.as_str()) {
fn run(&mut self, animation_name: &str, status: AnimationStatus) -> bool {
if self.animations.contains_key(animation_name) {
let mut animation = self
.animations
.get_mut(animation_name.as_str())
.get_mut(animation_name)
.expect("An animation has not been found after the security check");
if AnimationStatus::STOPPED == animation.status {
animation.status = status;
Expand All @@ -41,21 +41,21 @@ impl Animations {
}

/// Runs the animation `name`. Returns true is the animation has been started, false if it does not exist or was already running
pub fn run_animation(&mut self, animation_name: String) -> bool {
pub fn run_animation(&mut self, animation_name: &str) -> bool {
self.run(animation_name, AnimationStatus::RUNNING)
}

/// Runs the animation `name`. Returns true is the animation has been started, false if it does not exist or was already running
pub fn loop_animation(&mut self, animation_name: String) -> bool {
pub fn loop_animation(&mut self, animation_name: &str) -> bool {
self.run(animation_name, AnimationStatus::LOOPING)
}

/// Stops the animation `name`. Returns true is the animation has been stopped, false if it does not exist or was already stopped
pub fn stop_animation(&mut self, animation_name: String, force: bool) -> bool {
if self.animations.contains_key(animation_name.as_str()) {
pub fn stop_animation(&mut self, animation_name: &str, force: bool) -> bool {
if self.animations.contains_key(animation_name) {
let mut animation = self
.animations
.get_mut(animation_name.as_str())
.get_mut(animation_name)
.expect("An animation has not been found after the security check");
if animation.status == AnimationStatus::LOOPING
|| animation.status == AnimationStatus::RUNNING
Expand Down Expand Up @@ -185,13 +185,19 @@ impl AnimationModifier {
)
}

/// Convenience function to create a color animation
pub fn color(number_of_keyframes: usize, target_color: Color) -> Self {
AnimationModifier::new(
number_of_keyframes,
AnimationModifierType::Color { target: target_color },
)
}

/// Convenience function to create a blink animation.
pub fn blink(number_of_blinks: usize) -> Self {
AnimationModifier::new(number_of_blinks * 2, AnimationModifierType::Blink)
}

pub(crate) fn compute_keyframe_modifier_for_animation(&mut self, initial_color: &Color) {
self.single_keyframe_modifier = match &self.modifier_type {
AnimationModifierType::Color { target } => {
Expand Down Expand Up @@ -220,6 +226,7 @@ pub enum AnimationModifierType {
TransformModifier { vector: Option<Vector>, scale: Option<f32>, rotation: Option<f32> },
SpriteModifier { tile_numbers: Vec<usize>, end_tile_number: usize },
Color { target: Color },
Blink
}

pub(crate) enum ComputedKeyframeModifier {
Expand All @@ -242,6 +249,9 @@ impl Display for AnimationModifier {
AnimationModifierType::Color { .. } => {
"Color"
}
AnimationModifierType::Blink => {
"Blink"
}
}
)
}
Expand All @@ -264,6 +274,9 @@ fn compute_animation_keyframe_modifier(modifier: &mut AnimationModifier) {
// We can't compute here because we need the initial color
None
}
AnimationModifierType::Blink => {
None
}
};
}

Expand Down
10 changes: 5 additions & 5 deletions src/core/components/maths/coordinates.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,23 @@
pub struct Coordinates {
pub(crate) x: f32,
pub(crate) y: f32,
pub(crate) layer: usize,
pub(crate) z: usize,
}

impl Coordinates {
pub fn new(x: f32, y: f32) -> Self { Self { x, y, layer: 0 } }
pub fn new(x: f32, y: f32) -> Self { Self { x, y, z: 0 } }

pub fn new_with_layer(x: f32, y: f32, layer: usize) -> Self { Self { x, y, layer } }
pub fn new_with_z(x: f32, y: f32, layer: usize) -> Self { Self { x, y, z: layer } }

pub fn x(&self) -> f32 { self.x }

pub fn y(&self) -> f32 { self.y }

pub fn layer(&self) -> usize { self.layer }
pub fn z(&self) -> usize { self.z }

pub fn set_x(&mut self, x: f32) { self.x = x }

pub fn set_y(&mut self, y: f32) { self.y = y; }

pub fn set_layer(&mut self, layer: usize) { self.layer = layer; }
pub fn set_z(&mut self, z: usize) { self.z = z; }
}
14 changes: 7 additions & 7 deletions src/core/components/maths/transform.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,8 @@ impl Transform {

pub fn from_xy(x: f32, y: f32) -> Self { Self::new(Coordinates::new(x, y), 1., 0.) }

pub fn from_xy_with_layer(x: f32, y: f32, layer: usize) -> Self {
Self::new(Coordinates::new_with_layer(x, y, layer), 1., 0.)
pub fn from_xyz(x: f32, y: f32, z: usize) -> Self {
Self::new(Coordinates::new_with_z(x, y, z), 1., 0.)
}

/// Append a translation to this transform's position
Expand Down Expand Up @@ -105,8 +105,8 @@ impl Transform {
/// Change the scale value to a new one.
pub fn set_scale(&mut self, scale: f32) { self.scale = scale }

/// Change the layer value in the coordinates.
pub fn set_layer(&mut self, layer: usize) { self.local_translation.layer = layer }
/// Change the z value in the coordinates.
pub fn set_z(&mut self, z: usize) { self.local_translation.z = z }

/// Configure the minimum global x position for this transform to be min_x
pub fn set_min_x(&mut self, min_x: Option<f32>) {
Expand Down Expand Up @@ -152,7 +152,7 @@ impl Transform {
let mut new_global = parent_translation.clone();
new_global.x += self.local_translation.x;
new_global.y += self.local_translation.y;
new_global.layer = self.local_translation.layer;
new_global.z = self.local_translation.z;
self.global_translation = new_global;
self.dirty = true;
self.handle_bounds();
Expand Down Expand Up @@ -198,8 +198,8 @@ impl TransformBuilder {
self.transform.global_translation = translation;
self
}
pub fn with_translation(mut self, x: f32, y: f32, layer: usize) -> Self {
let translation = Coordinates::new_with_layer(x, y, layer);
pub fn with_translation(mut self, x: f32, y: f32, z: usize) -> Self {
let translation = Coordinates::new_with_z(x, y, z);
self.transform.local_translation = translation;
self.transform.global_translation = translation;
self
Expand Down
6 changes: 3 additions & 3 deletions src/core/components/tiles/tilemap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,8 @@ impl Tilemap {

for x in 0..infos.dimensions.width() {
for y in 0..infos.dimensions.height() {
for layer in 0..infos.dimensions.number_of_layers() {
let position = Position::new(x, y, layer);
for z in 0..infos.dimensions.depth() {
let position = Position::new(x, y, z);
let tile_infos = tile_resolver(&position);

let entity = world
Expand All @@ -78,7 +78,7 @@ impl Tilemap {

if let Some(animation) = tile_infos.animation {
world.entry(entity).unwrap().add_component(Animations::single(
"TileAnimation".to_string(),
"TileAnimation",
animation,
));
}
Expand Down
Loading

0 comments on commit ee61b50

Please # to comment.