Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Upgrade to 0.7 #6

Merged
merged 4 commits into from
Apr 23, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
/target
Cargo.lock
.idea
6 changes: 3 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
[package]
name = "bevy_pixel_camera"
version = "0.1.1"
version = "0.1.2"
authors = ["drakmaniso <[email protected]>"]
edition = "2018"
edition = "2021"
description = "A simple pixel-perfect camera plugin for Bevy, suitable for pixel-art"
readme = "README.md"
repository = "https://github.com/drakmaniso/bevy_pixel_camera"
Expand All @@ -14,4 +14,4 @@ license = "MIT OR Apache-2.0"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
bevy = "0.5"
bevy = { version = "0.7" }
82 changes: 45 additions & 37 deletions examples/flappin.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
use bevy::sprite::Anchor;
use bevy::window;
use bevy::{core::FixedTimestep, prelude::*};
use bevy_pixel_camera::{PixelBorderPlugin, PixelCameraBundle, PixelCameraPlugin, PixelSpriteQuad};
use bevy_pixel_camera::{PixelBorderPlugin, PixelCameraBundle, PixelCameraPlugin};

// GAME CONSTANTS /////////////////////////////////////////////////////////////

Expand Down Expand Up @@ -40,14 +42,14 @@ enum GameState {
}

fn main() {
App::build()
App::new()
.add_state(GameState::StartScreen)
.add_event::<ActionEvent>()
.insert_resource(WindowDescriptor {
title: "Flappin'".to_string(),
width: 720.0,
height: 720.0,
vsync: true,
present_mode: window::PresentMode::Mailbox,
..Default::default()
})
.add_plugins(DefaultPlugins)
Expand All @@ -56,41 +58,37 @@ fn main() {
color: Color::rgb(0.1, 0.1, 0.1),
})
.insert_resource(Rng { mz: 0, mw: 0 })
.insert_resource(ClearColor(Color::rgb(0.0, 0.0, 0.0)))
.insert_resource(ClearColor(Color::rgb(0.000001, 0.000001, 0.000001)))
.insert_resource(Timer::from_seconds(0.25, false))
.add_startup_system(setup.system().label("setup"))
.add_startup_system(spawn_bird.system().after("setup"))
.add_startup_system(spawn_clouds.system().after("setup"))
.add_system(bevy::input::system::exit_on_esc_system.system())
.add_system(on_press.system())
.add_startup_system(setup.label("setup"))
.add_startup_system(spawn_bird.after("setup"))
.add_startup_system(spawn_clouds.after("setup"))
.add_system(bevy::input::system::exit_on_esc_system)
.add_system(on_press)
.add_system_set(
SystemSet::on_update(GameState::StartScreen)
.with_system(animate_flying_bird.system())
.with_system(press_to_start.system()),
.with_system(animate_flying_bird)
.with_system(press_to_start),
)
.add_system_set(SystemSet::on_enter(GameState::Playing).with_system(spawn_pillars.system()))
.add_system_set(SystemSet::on_enter(GameState::Playing).with_system(spawn_pillars))
.add_system_set(
SystemSet::on_update(GameState::Playing)
.with_system(animate_flappin_bird.system())
.with_system(flap.system())
.with_system(collision_detection.system()),
)
.add_system_set(SystemSet::on_enter(GameState::GameOver).with_system(game_over.system()))
.add_system_set(
SystemSet::on_update(GameState::GameOver).with_system(press_to_start.system()),
)
.add_system_set(
SystemSet::on_exit(GameState::GameOver).with_system(despawn_pillars.system()),
.with_system(animate_flappin_bird)
.with_system(flap)
.with_system(collision_detection),
)
.add_system_set(SystemSet::on_enter(GameState::GameOver).with_system(game_over))
.add_system_set(SystemSet::on_update(GameState::GameOver).with_system(press_to_start))
.add_system_set(SystemSet::on_exit(GameState::GameOver).with_system(despawn_pillars))
.add_system_set(
SystemSet::new()
.with_run_criteria(FixedTimestep::step(1.0 * FRAME))
.with_system(animate_pillars.system()),
.with_system(animate_pillars),
)
.add_system_set(
SystemSet::new()
.with_run_criteria(FixedTimestep::step(2.0 * FRAME))
.with_system(animate_clouds.system()),
.with_system(animate_clouds),
)
.run();
}
Expand Down Expand Up @@ -152,19 +150,23 @@ fn press_to_start(
// THE BIRD ///////////////////////////////////////////////////////////////////

// Component
#[derive(Component)]
struct Bird;

// Component
#[derive(Component)]
struct BirdPhysics {
velocity: f32,
acceleration: f32,
}

#[derive(Component)]
struct BirdTimer(Timer);

fn spawn_bird(
mut commands: Commands,
asset_server: Res<AssetServer>,
mut texture_atlases: ResMut<Assets<TextureAtlas>>,
quad: Res<PixelSpriteQuad>,
) {
let texture_atlas = texture_atlases.add(TextureAtlas::from_grid(
asset_server.load("flappin-bird.png"),
Expand All @@ -182,20 +184,23 @@ fn spawn_bird(
.insert_bundle(SpriteSheetBundle {
texture_atlas,
transform: Transform::from_translation(Vec3::new(BIRD_X, 0.0, 1.0)),
mesh: quad.clone().into(),
sprite: TextureAtlasSprite {
anchor: Anchor::BottomLeft,
..Default::default()
},
..Default::default()
})
.insert(Timer::from_seconds(0.150, true));
.insert(BirdTimer(Timer::from_seconds(0.150, true)));
}

fn animate_flying_bird(
time: Res<Time>,
mut query: Query<(&mut Timer, &mut TextureAtlasSprite), With<Bird>>,
mut query: Query<(&mut BirdTimer, &mut TextureAtlasSprite), With<Bird>>,
) {
for (mut timer, mut sprite) in query.iter_mut() {
timer.tick(time.delta());
if timer.finished() {
sprite.index = ((sprite.index as usize + 1) % 3) as u32;
timer.0.tick(time.delta());
if timer.0.finished() {
sprite.index = ((sprite.index as usize + 1) % 3) as usize;
}
}
}
Expand Down Expand Up @@ -279,13 +284,13 @@ fn collision_detection(
// THE PILLARS ////////////////////////////////////////////////////////////////

// Component
#[derive(Component)]
struct Pillar;

fn spawn_pillars(
mut commands: Commands,
asset_server: Res<AssetServer>,
mut texture_atlases: ResMut<Assets<TextureAtlas>>,
quad: Res<PixelSpriteQuad>,
mut rng: ResMut<Rng>,
) {
let atlas = texture_atlases.add(TextureAtlas::from_grid(
Expand All @@ -304,7 +309,10 @@ fn spawn_pillars(
.insert_bundle(SpriteSheetBundle {
texture_atlas: atlas.clone(),
transform: Transform::from_xyz(x, (y - PILLAR_HEIGHT / 2.0).round(), 2.0),
mesh: quad.clone().into(),
sprite: TextureAtlasSprite {
anchor: Anchor::BottomLeft,
..Default::default()
},
..Default::default()
});
x += PILLAR_SPACING;
Expand Down Expand Up @@ -337,13 +345,13 @@ fn despawn_pillars(mut commands: Commands, pillars: Query<Entity, With<Pillar>>)
// THE CLOUDS /////////////////////////////////////////////////////////////////

// Component
#[derive(Component)]
struct Cloud;

fn spawn_clouds(
mut commands: Commands,
asset_server: Res<AssetServer>,
mut texture_atlases: ResMut<Assets<TextureAtlas>>,
quad: Res<PixelSpriteQuad>,
mut rng: ResMut<Rng>,
) {
let clouds_atlas = texture_atlases.add(TextureAtlas::from_grid(
Expand All @@ -363,10 +371,10 @@ fn spawn_clouds(
texture_atlas: clouds_atlas.clone(),
transform: Transform::from_xyz(x, y, 0.0),
sprite: TextureAtlasSprite {
index: rng.rand_range(0..4),
index: rng.rand_range(0..4) as usize,
anchor: Anchor::BottomLeft,
..Default::default()
},
mesh: quad.clone().into(),
..Default::default()
});
x += CLOUD_WIDTH;
Expand All @@ -386,7 +394,7 @@ fn animate_clouds(
if transform.translation.x + CLOUD_WIDTH < LEFT {
let y = BOTTOM + 40.0 + rng.rand_range(0..(HEIGHT - 80.0 - CLOUD_HEIGHT) as u32) as f32;
*transform = Transform::from_xyz(RIGHT, y, 0.0);
sprite.index = rng.rand_range(0..4);
sprite.index = rng.rand_range(0..4) as usize;
sprite.flip_x = rng.rand_range(0..2) > 0;
}
}
Expand Down
56 changes: 34 additions & 22 deletions examples/mire.rs
Original file line number Diff line number Diff line change
@@ -1,64 +1,76 @@
use bevy::prelude::*;
use bevy_pixel_camera::{PixelCameraBundle, PixelCameraPlugin, PixelSpriteQuad};
use bevy::sprite::Anchor;
use bevy_pixel_camera::{PixelCameraBundle, PixelCameraPlugin};

fn main() {
App::build()
App::new()
.insert_resource(ClearColor(Color::rgb(0.000001, 0.000001, 0.000001)))
.add_plugins(DefaultPlugins)
.add_plugin(PixelCameraPlugin)
.insert_resource(ClearColor(Color::rgb(0.0, 0.0, 0.0)))
.add_startup_system(setup.system())
.add_startup_system(setup)
.run();
}

fn setup(
mut commands: Commands,
asset_server: Res<AssetServer>,
mut materials: ResMut<Assets<ColorMaterial>>,
quad: Res<PixelSpriteQuad>,
) {
fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
// Add a camera that will always fit the virtual resolution 320x180 inside
// the window.
commands.spawn_bundle(PixelCameraBundle::from_resolution(320, 180));
// commands.spawn_bundle(OrthographicCameraBundle::new_2d());

let mire_32x32_handle = materials.add(asset_server.load("mire-32x32.png").into());
let mire_31x31_handle = materials.add(asset_server.load("mire-31x31.png").into());
let mire_32x32_handle = asset_server.load("mire-32x32.png");
// let mire_31x31_handle = asset_server.load("mire-31x31.png");

// Add a 31x31 sprite in the center of the window.
commands.spawn_bundle(SpriteBundle {
material: mire_31x31_handle.clone(),
mesh: quad.clone().into(),
texture: asset_server.load("mire-31x31.png"),
sprite: Sprite {
anchor: Anchor::BottomLeft,
..Default::default()
},
transform: Transform::from_translation(Vec3::new(-16.0, -16.0, 0.0)),
..Default::default()
});

// Add a 32x32 sprite in the bottom-left corner of our virtual resolution.
commands.spawn_bundle(SpriteBundle {
material: mire_32x32_handle.clone(),
mesh: quad.clone().into(),
texture: asset_server.load("mire-32x32.png"),
sprite: Sprite {
anchor: Anchor::BottomLeft,
..Default::default()
},
transform: Transform::from_translation(Vec3::new(-160.0, -90.0, 0.0)),
..Default::default()
});

// Add a 32x32 sprite in the bottom-right corner of our virtual resolution.
commands.spawn_bundle(SpriteBundle {
material: mire_32x32_handle.clone(),
mesh: quad.clone().into(),
texture: mire_32x32_handle.clone(),
sprite: Sprite {
anchor: Anchor::BottomLeft,
..Default::default()
},
transform: Transform::from_translation(Vec3::new(160.0 - 32.0, -90.0, 0.0)),
..Default::default()
});

// Add a 32x32 sprite in the top-left corner of our virtual resolution.
commands.spawn_bundle(SpriteBundle {
material: mire_32x32_handle.clone(),
mesh: quad.clone().into(),
texture: mire_32x32_handle.clone(),
sprite: Sprite {
anchor: Anchor::BottomLeft,
..Default::default()
},
transform: Transform::from_translation(Vec3::new(-160.0, 90.0 - 32.0, 0.0)),
..Default::default()
});

// Add a 32x32 sprite in the top-right corner of our virtual resolution.
commands.spawn_bundle(SpriteBundle {
material: mire_32x32_handle.clone(),
mesh: quad.clone().into(),
texture: mire_32x32_handle.clone(),
sprite: Sprite {
anchor: Anchor::BottomLeft,
..Default::default()
},
transform: Transform::from_translation(Vec3::new(160.0 - 32.0, 90.0 - 32.0, 0.0)),
..Default::default()
});
Expand Down
25 changes: 13 additions & 12 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,11 @@
//! This plugin provides a camera which can be easily configured by specifying
//! either the size of the virtual pixels, or the desired resolution.
//!
//! It also includes a quad mesh resource to replace the default one used in
//! Bevy's `SpriteBundle`. The default quad has its origin at the center of the
//! image, but if the image has an odd width or height, that origin is not
//! pixel-aligned. The resource included in this plugin puts the origin at the
//! bottom-left corner of the image.
//! Note that if either the width or the height of your sprite is not divisible
//! by 2, you need to change the anchor of the sprite (which is at the center by
//! default), or it will not be pixel aligned.
//!
//! Finally, the crate also includes a separate plugin to put an opaque border
//! The crate also includes a separate plugin to put an opaque border
//! around the desired resolution. This way, if the window size is not an exact
//! multiple of the virtual resolution, anything out of bounds will still be
//! hidden.
Expand All @@ -44,33 +42,36 @@
//!
//! ```no_run
//! use bevy::prelude::*;
//! use bevy::sprite::Anchor;
//! use bevy_pixel_camera::{
//! PixelBorderPlugin, PixelCameraBundle, PixelCameraPlugin, PixelSpriteQuad
//! PixelBorderPlugin, PixelCameraBundle, PixelCameraPlugin
//! };
//!
//! fn main() {
//! App::build()
//! App::new()
//! .add_plugins(DefaultPlugins)
//! .add_plugin(PixelCameraPlugin)
//! .add_plugin(PixelBorderPlugin {
//! color: Color::rgb(0.1, 0.1, 0.1),
//! })
//! .add_startup_system(setup.system())
//! .add_startup_system(setup)
//! .run();
//! }
//!
//! fn setup(
//! mut commands: Commands,
//! asset_server: Res<AssetServer>,
//! mut materials: ResMut<Assets<ColorMaterial>>,
//! quad: Res<PixelSpriteQuad>,
//! ) {
//! commands.spawn_bundle(PixelCameraBundle::from_resolution(320, 240));
//!
//! let sprite_handle = materials.add(asset_server.load("my-pixel-art-sprite.png").into());
//! commands.spawn_bundle(SpriteBundle {
//! material: sprite_handle,
//! mesh: quad.clone().into(),
//! texture: asset_server.load("my-pixel-art-sprite.png"),
//! sprite: Sprite {
//! anchor: Anchor::BottomLeft,
//! ..Default::default()
//! },
//! ..Default::default()
//! });
//! }
Expand Down
Loading