From 996fac43dc6e2c6a1a5f45c090ac303752217bf5 Mon Sep 17 00:00:00 2001 From: Gabriel Martinez Date: Sun, 12 Jun 2022 15:58:27 -0700 Subject: [PATCH] Render ground as tiling textures Kind of a hack based on https://github.com/bevyengine/bevy/issues/399, but good enough for now. --- TODO.md | 4 +- .../sprites/Tileset/Style 1/OldS2-Ground.png | Bin 0 -> 157 bytes .../Tileset/Style 1/OldS2-GroundTop.png | Bin 0 -> 189 bytes .../Tileset/Style 1/OldS2-PipeCenter.png | Bin 0 -> 155 bytes src/assets.rs | 68 ++++++++++++++++++ src/game.rs | 55 +++++++++++--- src/main.rs | 3 +- src/menu.rs | 2 +- 8 files changed, 118 insertions(+), 14 deletions(-) create mode 100644 assets/sprites/Tileset/Style 1/OldS2-Ground.png create mode 100644 assets/sprites/Tileset/Style 1/OldS2-GroundTop.png create mode 100644 assets/sprites/Tileset/Style 1/OldS2-PipeCenter.png diff --git a/TODO.md b/TODO.md index f3de440..eec52a0 100644 --- a/TODO.md +++ b/TODO.md @@ -7,8 +7,10 @@ * [ ] Save out window state when closing app. ## Graphics -* [ ] Set up animating bird +* [x] Set up animating bird * Try [benimator](https://github.com/jcornaz/benimator) or [bevy_sprite_animation](https://github.com/PhaestusFox/bevy_sprite_animation) +* [ ] Draw tiling textures for art and pipes + * https://github.com/bevyengine/bevy/issues/399#issuecomment-1015353924 # Done ## Gameplay diff --git a/assets/sprites/Tileset/Style 1/OldS2-Ground.png b/assets/sprites/Tileset/Style 1/OldS2-Ground.png new file mode 100644 index 0000000000000000000000000000000000000000..5747f98ef2342fda9090984e447af8eb4742fc5a GIT binary patch literal 157 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|!aZFaLo9le zZJw?AG{3R2(a|fug;CaK_m4Kl=`ud^Jb_%G5X(A=NTKO6n{2p!7-AJSt-Zn1cye=s z@Da9xlZLjtf3U3Y4RfL1Vgy85}Sb4q9e0HEG5 AMgRZ+ literal 0 HcmV?d00001 diff --git a/assets/sprites/Tileset/Style 1/OldS2-GroundTop.png b/assets/sprites/Tileset/Style 1/OldS2-GroundTop.png new file mode 100644 index 0000000000000000000000000000000000000000..12ea735ebf286004a433f09d2e5435f6432bcff1 GIT binary patch literal 189 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|$~|2iLo9le zpIj{ddES9B;pJUL-_AO=Y0cm515y}-U3aZaWKcfZxWoGoqpP084}*kBm&6k%ToOO1 z)#=ZtcE06|8H{`uZ~?(Bncfenn3GJF0vf>;k9{N?94(lC4ae*+L$@p{vNn+6Nkoj!B`2sUVb w)@BwCTox$U6J?S0a7F84u|6O}F_D3xz+YhQ#U01JfEF-#y85}Sb4q9e075i58UO$Q literal 0 HcmV?d00001 diff --git a/src/assets.rs b/src/assets.rs index 2b89624..33acec7 100644 --- a/src/assets.rs +++ b/src/assets.rs @@ -2,6 +2,10 @@ use std::time::Duration; use benimator::SpriteSheetAnimation; use bevy::prelude::*; +use bevy::{ + sprite::Rect, + render::render_resource::AddressMode, +}; use bevy_asset_loader::{AssetCollection, AssetLoader}; use iyes_loopless::prelude::*; @@ -31,15 +35,79 @@ pub struct GameAssets { #[asset(path = "sprites/Background/Background5.png")] pub background: Handle, + + #[asset(path = "sprites/Tileset/Style 1/OldS2.png")] + pub terrain_image: Handle, + pub terrain_atlas: Handle, + pub terrain_indices: TerrainAtlasIndices, + + #[asset(path = "sprites/Tileset/Style 1/OldS2-PipeCenter.png")] + pub pipe_center: Handle, + #[asset(path = "sprites/Tileset/Style 1/OldS2-GroundTop.png")] + pub ground_top: Handle, + #[asset(path = "sprites/Tileset/Style 1/OldS2-Ground.png")] + pub ground: Handle, +} + +#[derive(Default)] +pub struct TerrainAtlasIndices { + pub pipe_top: usize, + pub pipe_bottom: usize, + pub pipe_center: usize, + + pub ground_top: usize, + pub ground: usize, } fn assets_loaded( mut assets: ResMut, mut animations: ResMut>, + mut atlases: ResMut>, + mut images: ResMut>, ) { eprintln!("Loaded assets!"); // Bird anim info asset. let bird_anim = SpriteSheetAnimation::from_range(0..=3, Duration::from_millis(150)); assets.bird_anim = animations.add(bird_anim); + + // Populate terrain texture atlas. + if let Some(image) = images.get_mut(&assets.terrain_image) { + image.sampler_descriptor.address_mode_u = AddressMode::Repeat; + image.sampler_descriptor.address_mode_v = AddressMode::Repeat; + + let mut atlas = TextureAtlas::new_empty(assets.terrain_image.clone(), image.size()); + assets.terrain_indices.pipe_top = atlas.add_texture(Rect { + min: Vec2::new(0.0, 0.0), + max: Vec2::new(32.0, 16.0), + }); + assets.terrain_indices.pipe_bottom = atlas.add_texture(Rect { + min: Vec2::new(0.0, 64.0), + max: Vec2::new(32.0, 80.0), + }); + assets.terrain_indices.pipe_center = atlas.add_texture(Rect { + min: Vec2::new(2.0, 32.0), + max: Vec2::new(30.0, 48.0), + }); + assets.terrain_indices.ground_top = atlas.add_texture(Rect { + min: Vec2::new(0.0, 80.0), + max: Vec2::new(16.0, 96.0), + }); + assets.terrain_indices.ground = atlas.add_texture(Rect { + min: Vec2::new(0.0, 96.0), + max: Vec2::new(16.0, 112.0), + }); + + assets.terrain_atlas = atlases.add(atlas); + } + + // Set repeat address mode on tiling textures. + if let Some(image) = images.get_mut(&assets.ground) { + image.sampler_descriptor.address_mode_u = AddressMode::Repeat; + image.sampler_descriptor.address_mode_v = AddressMode::Repeat; + } + if let Some(image) = images.get_mut(&assets.ground_top) { + image.sampler_descriptor.address_mode_u = AddressMode::Repeat; + image.sampler_descriptor.address_mode_v = AddressMode::Repeat; + } } diff --git a/src/game.rs b/src/game.rs index fd51759..f1a46dd 100644 --- a/src/game.rs +++ b/src/game.rs @@ -1,6 +1,6 @@ use bevy::prelude::*; use bevy::{ - render::camera::WindowOrigin, + render::{camera::WindowOrigin, mesh::VertexAttributeValues}, sprite::Anchor, }; use bevy_egui::EguiContext; @@ -200,6 +200,9 @@ fn setup_game( assets: Res, mut game_data: ResMut, window_scale: Res, + images: Res>, + mut materials: ResMut>, + mut meshes: ResMut>, ) { eprintln!("Setting up game"); @@ -229,17 +232,49 @@ fn setup_game( commands.spawn_bundle(background_sprite) .insert(Name::new("Background")); - // Spawn ground sprite - let ground_sprite = SpriteBundle { - transform: Transform::from_translation(Vec3::new(GAME_SIZE.0 / 2.0, GROUND_OFFSET, 10.0)), - sprite: Sprite { - color: Color::DARK_GREEN, - custom_size: Some(Vec2::new(GAME_SIZE.0, GROUND_OFFSET * 2.0)), - ..default() - }, + // Spawn tiling ground texture. + let ground_image_size = images.get(&assets.ground).unwrap().size(); + let mut ground_mesh = Mesh::from(shape::Quad::default()); + if let Some(VertexAttributeValues::Float32x2(uvs)) = ground_mesh.attribute_mut(Mesh::ATTRIBUTE_UV_0) { + for uv in uvs { + uv[0] *= GAME_SIZE.0 / ground_image_size.x; + uv[1] *= (GROUND_OFFSET * 2.0) / ground_image_size.y; + } + } + let ground_transform = Transform { + translation: Vec3::new(GAME_SIZE.0 / 2.0, GROUND_OFFSET, 10.0), + scale: Vec3::new(GAME_SIZE.0, GROUND_OFFSET * 2.0, 1.0), + ..default() + }; + let ground_bundle = ColorMesh2dBundle { + transform: ground_transform, + material: materials.add(assets.ground.clone().into()), + mesh: meshes.add(ground_mesh.into()).into(), + ..default() + }; + commands.spawn_bundle(ground_bundle) + .insert(Name::new("Ground")); + + // Spawn tiling ground top texture. + let ground_image_size = images.get(&assets.ground_top).unwrap().size(); + let mut ground_mesh = Mesh::from(shape::Quad::default()); + if let Some(VertexAttributeValues::Float32x2(uvs)) = ground_mesh.attribute_mut(Mesh::ATTRIBUTE_UV_0) { + for uv in uvs { + uv[0] *= GAME_SIZE.0 / ground_image_size.x; + } + } + let ground_transform = Transform { + translation: Vec3::new(GAME_SIZE.0 / 2.0, (GROUND_OFFSET * 2.0) - (ground_image_size.y / 2.0), 10.0), + scale: Vec3::new(GAME_SIZE.0, ground_image_size.y, 1.0), + ..default() + }; + let ground_bundle = ColorMesh2dBundle { + transform: ground_transform, + material: materials.add(assets.ground_top.clone().into()), + mesh: meshes.add(ground_mesh.into()).into(), ..default() }; - commands.spawn_bundle(ground_sprite) + commands.spawn_bundle(ground_bundle) .insert(Name::new("Ground")); // Spawn pipes offscreen. diff --git a/src/main.rs b/src/main.rs index c5d7f75..4f86440 100644 --- a/src/main.rs +++ b/src/main.rs @@ -65,8 +65,7 @@ fn main() { mode: WindowMode::Windowed, ..default() }) - // .insert_resource(ClearColor(Color::hex("018893").unwrap())) - .insert_resource(ClearColor(Color::rgb_u8(230, 230, 230))) + .insert_resource(ClearColor(Color::rgb_u8(0, 57, 109))) // External plugins .add_plugins(DefaultPlugins) diff --git a/src/menu.rs b/src/menu.rs index 89dd0bc..9c6e61b 100644 --- a/src/menu.rs +++ b/src/menu.rs @@ -31,7 +31,7 @@ fn setup_main_menu( let style = TextStyle { font: assets.font.clone(), font_size: 80.0, - color: Color::BLACK, + color: Color::WHITE, }; let alignment = TextAlignment { horizontal: HorizontalAlign::Center,