From 7cc5f6dc2d3376d1ff6baa9ebc0cead75b42c7c3 Mon Sep 17 00:00:00 2001 From: hheik <4469778+hheik@users.noreply.github.com> Date: Fri, 2 Dec 2022 18:25:22 +0200 Subject: [PATCH] wip: added some debug chunk generators and fixed camera projection --- src/game.rs | 9 ++-- src/game/camera.rs | 11 ++--- src/terrain2d/chunk2d.rs | 96 +++++++++++++++++++++++++++++++++++----- src/util/vector2.rs | 4 ++ 4 files changed, 100 insertions(+), 20 deletions(-) diff --git a/src/game.rs b/src/game.rs index 224cadb..16a3104 100644 --- a/src/game.rs +++ b/src/game.rs @@ -30,10 +30,11 @@ pub fn init() { } fn setup_debug_terrain(mut terrain: ResMut) { - terrain.add_chunk(Vector2I { x: 0, y: 0 }, Chunk2D::new()); - terrain.add_chunk(Vector2I { x: 1, y: 0 }, Chunk2D::new()); - terrain.add_chunk(Vector2I { x: 0, y: 1 }, Chunk2D::new()); - terrain.add_chunk(Vector2I { x: 1, y: 1 }, Chunk2D::new()); + for y in 0..32 { + for x in 0..8 { + terrain.add_chunk(Vector2I { x, y }, Chunk2D::new_circle()); + } + } } fn setup_debug_ground(mut commands: Commands) { diff --git a/src/game/camera.rs b/src/game/camera.rs index 6368e14..29ec458 100644 --- a/src/game/camera.rs +++ b/src/game/camera.rs @@ -1,4 +1,4 @@ -use bevy::{prelude::*, render::camera::ScalingMode}; +use bevy::{prelude::*, render::camera::{ScalingMode, WindowOrigin}}; use bevy_inspector_egui::{Inspectable, RegisterInspectable}; use crate::util::{move_towards_vec3, vec3_lerp}; @@ -37,10 +37,11 @@ fn camera_setup(mut commands: Commands) { commands.spawn(( Name::new("Camera"), Camera2dBundle { - // projection: OrthographicProjection { - // scaling_mode: ScalingMode::FixedHorizontal(320.0), - // ..default() - // }, + projection: OrthographicProjection { + scaling_mode: ScalingMode::FixedHorizontal(512.0), + window_origin: WindowOrigin::BottomLeft, + ..default() + }, ..default() }, )); diff --git a/src/terrain2d/chunk2d.rs b/src/terrain2d/chunk2d.rs index bbe5e8d..4520502 100644 --- a/src/terrain2d/chunk2d.rs +++ b/src/terrain2d/chunk2d.rs @@ -1,6 +1,18 @@ +use std::collections::HashMap; + use super::{local_to_texel_index, Terrain2D, TerrainEvent, Texel2D, TexelID, NEIGHBOUR_INDEX_MAP}; use crate::util::Vector2I; -use bevy::{prelude::*, render::render_resource::Extent3d}; +use bevy::{prelude::*, render::{render_resource::Extent3d, texture::ImageSampler}}; +use lazy_static::lazy_static; + +lazy_static! { + pub static ref COLOR_MAP: HashMap = { + let mut map = HashMap::new(); + map.insert(0, [0x20, 0x20, 0x20, 0xff]); + map.insert(1, [0xff, 0xff, 0xff, 0xff]); + map + }; +} #[derive(Reflect, Component, Default)] #[reflect(Component)] @@ -43,6 +55,53 @@ impl Chunk2D { } } + pub fn new_full() -> Chunk2D { + let mut chunk = Chunk2D { + texels: Self::new_texel_array(), + dirty_rect: None, + }; + for y in 0..Self::SIZE_Y { + for x in 0..Self::SIZE_X { + chunk.set_texel(&Vector2I::new(x as i32, y as i32), 1); + } + } + chunk + } + + pub fn new_half() -> Chunk2D { + let mut chunk = Chunk2D { + texels: Self::new_texel_array(), + dirty_rect: None, + }; + for y in 0..Self::SIZE_Y { + for x in 0..Self::SIZE_X { + if x <= Self::SIZE_Y - y { + chunk.set_texel(&Vector2I::new(x as i32, y as i32), 1); + } + } + } + chunk + } + + pub fn new_circle() -> Chunk2D { + let mut chunk = Chunk2D { + texels: Self::new_texel_array(), + dirty_rect: None, + }; + let origin = Self::SIZE / 2; + let radius = Self::SIZE_X as i32 / 2; + for y in 0..Self::SIZE_Y { + for x in 0..Self::SIZE_X { + let dx = (x as i32 - origin.x).abs(); + let dy = (y as i32 - origin.y).abs(); + if dx * dx + dy * dy <= (radius - 1) * (radius - 1) { + chunk.set_texel(&Vector2I::new(x as i32, y as i32), 1); + } + } + } + chunk + } + pub fn new_texel_array() -> [Texel2D; Self::SIZE_X * Self::SIZE_Y] { [Texel2D::default(); Self::SIZE_X * Self::SIZE_Y] } @@ -75,7 +134,7 @@ impl Chunk2D { local_to_texel_index(position).map(|i| self.texels[i]) } - pub fn get_texel_option_mut(&mut self, position: &Vector2I) -> Option<&mut Texel2D> { + pub fn get_texel_mut(&mut self, position: &Vector2I) -> Option<&mut Texel2D> { local_to_texel_index(position).map(|i| &mut self.texels[i]) } @@ -95,7 +154,7 @@ impl Chunk2D { if update_neighbours { for offset in Texel2D::NEIGHBOUR_OFFSET_VECTORS { // Flip neighbour's bit - match self.get_texel_option_mut(&(*position + offset)) { + match self.get_texel_mut(&(*position + offset)) { Some(mut neighbour) => { neighbour.neighbour_mask ^= 1 << NEIGHBOUR_INDEX_MAP[&-offset]; } @@ -116,16 +175,27 @@ pub fn chunk_spawner( for terrain_event in terrain_events.iter() { match terrain_event { TerrainEvent::ChunkAdded(chunk_index) => { + let chunk = terrain.index_to_chunk(chunk_index).unwrap(); + let mut data = Vec::with_capacity(Chunk2D::SIZE_X * Chunk2D::SIZE_Y * 4); - for _y in 0..Chunk2D::SIZE_Y { - for _x in 0..Chunk2D::SIZE_X { - data.push(0x00); - data.push(0x00); - data.push(0x00); - data.push(0x00); + let fallback: [u8; 4] = [0x00, 0x00, 0x00, 0x00]; + for y in (0..Chunk2D::SIZE_Y).rev() { + for x in 0..Chunk2D::SIZE_X { + data.append( + &mut COLOR_MAP + .get( + &chunk + .get_texel(&Vector2I::new(x as i32, y as i32)) + .unwrap() + .id, + ) + .unwrap_or(&fallback) + .to_vec() + .clone(), + ); } } - let image = Image::new( + let mut image = Image::new( Extent3d { width: Chunk2D::SIZE_X as u32, height: Chunk2D::SIZE_Y as u32, @@ -136,7 +206,9 @@ pub fn chunk_spawner( bevy::render::render_resource::TextureFormat::Rgba8Unorm, ); - images.add(image); + image.sampler_descriptor = ImageSampler::nearest(); + + let texture = images.add(image); let pos = Vec2::from(*chunk_index * Chunk2D::SIZE); commands @@ -152,8 +224,10 @@ pub fn chunk_spawner( 0.75, ), custom_size: Some(Vec2::from(Chunk2D::SIZE)), + anchor: bevy::sprite::Anchor::BottomLeft, ..default() }, + texture, transform: Transform::from_translation(Vec3::new(pos.x, pos.y, 0.0)), ..default() }, diff --git a/src/util/vector2.rs b/src/util/vector2.rs index f093f06..8d386fb 100644 --- a/src/util/vector2.rs +++ b/src/util/vector2.rs @@ -37,6 +37,10 @@ pub struct Vector2 { } impl Vector2 { + pub fn new(x: T, y: T) -> Vector2 { + Vector2 { x, y } + } + pub fn min(&self, other: &Vector2) -> Vector2 { Vector2 { x: Ord::min(self.x, other.x),