aboutsummaryrefslogtreecommitdiff
path: root/light-client/src
diff options
context:
space:
mode:
authormetamuffin <metamuffin@disroot.org>2024-07-16 02:02:14 +0200
committermetamuffin <metamuffin@disroot.org>2024-07-16 02:02:14 +0200
commit1ab54f3155eff431fb1bd65a0bcad71701e9d9b5 (patch)
tree8f58d6846a45db402cf167f62960ae6647ebd8d8 /light-client/src
parent1671370f1e95b3ae0cdede6e16511fd91ea4feac (diff)
downloadhurrycurry-1ab54f3155eff431fb1bd65a0bcad71701e9d9b5.tar
hurrycurry-1ab54f3155eff431fb1bd65a0bcad71701e9d9b5.tar.bz2
hurrycurry-1ab54f3155eff431fb1bd65a0bcad71701e9d9b5.tar.zst
render connected tiles
Diffstat (limited to 'light-client/src')
-rw-r--r--light-client/src/game.rs37
-rw-r--r--light-client/src/main.rs20
-rw-r--r--light-client/src/sprite_renderer.rs (renamed from light-client/src/atlas.rs)78
-rw-r--r--light-client/src/tilemap.rs77
4 files changed, 142 insertions, 70 deletions
diff --git a/light-client/src/game.rs b/light-client/src/game.rs
index c9b20e56..ed1cb7fe 100644
--- a/light-client/src/game.rs
+++ b/light-client/src/game.rs
@@ -15,41 +15,58 @@
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
-use crate::atlas::SpriteRenderer;
-use hurrycurry_protocol::{glam::IVec2, PacketC, TileIndex};
+use crate::{sprite_renderer::SpriteRenderer, tilemap::Tilemap};
+use hurrycurry_protocol::{
+ glam::{IVec2, Vec2},
+ PacketC, PlayerID, TileIndex,
+};
use std::collections::HashMap;
pub struct Game {
- tiles: HashMap<IVec2, TileIndex>,
+ tiles: HashMap<IVec2, Tile>,
+ tilemap: Tilemap,
+ players: HashMap<PlayerID, Player>,
+}
+
+pub struct Tile {
+ kind: TileIndex,
+}
+pub struct Player {
+ character: i32,
+ position: Vec2,
}
impl Game {
pub fn new() -> Self {
Self {
tiles: HashMap::new(),
+ players: HashMap::new(),
+ tilemap: Tilemap::default(),
}
}
- pub fn packet_in(&mut self, packet: PacketC) {
+ pub fn packet_in(&mut self, packet: PacketC, renderer: &mut SpriteRenderer) {
match packet {
+ PacketC::Data { data } => {
+ self.tilemap.init(&data.tile_names, renderer.metadata());
+ }
PacketC::UpdateMap {
tile,
kind,
- neighbors: _,
+ neighbors,
} => {
if let Some(kind) = kind {
- self.tiles.insert(tile, kind);
+ self.tiles.insert(tile, Tile { kind });
} else {
self.tiles.remove(&tile);
}
+ self.tilemap.set(tile, kind, neighbors);
}
_ => (),
}
}
- pub fn render(&self, ctx: &mut SpriteRenderer) {
- for (p, tile) in &self.tiles {
- ctx.draw_tile(*tile, *p)
- }
+ pub fn draw(&self, ctx: &mut SpriteRenderer) {
+ self.tilemap.draw(ctx)
}
}
diff --git a/light-client/src/main.rs b/light-client/src/main.rs
index fa1a38ba..6d28647f 100644
--- a/light-client/src/main.rs
+++ b/light-client/src/main.rs
@@ -1,3 +1,5 @@
+use std::time::Instant;
+
/*
Hurry Curry! - a game about cooking
Copyright 2024 metamuffin
@@ -15,15 +17,15 @@
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
-use atlas::SpriteRenderer;
use game::Game;
-use hurrycurry_protocol::PacketC;
use network::Network;
use sdl2::{event::Event, keyboard::Keycode, pixels::Color};
+use sprite_renderer::SpriteRenderer;
-pub mod atlas;
pub mod game;
pub mod network;
+pub mod sprite_renderer;
+pub mod tilemap;
fn main() {
let sdl_context = sdl2::init().unwrap();
@@ -52,21 +54,17 @@ fn main() {
net.poll();
for packet in net.queue_in.drain(..) {
- match packet {
- PacketC::Data { data } => {
- renderer.set_sprite_map(data);
- }
- _ => game.packet_in(packet),
- }
+ game.packet_in(packet, &mut renderer);
}
- game.render(&mut renderer);
+ game.draw(&mut renderer);
+ let t = Instant::now();
canvas.set_draw_color(Color::BLACK);
canvas.clear();
renderer.submit(&mut canvas);
canvas.present();
-
+ eprintln!("{:?}", t.elapsed());
for event in sdl_context.event_pump().unwrap().poll_iter() {
match event {
Event::Quit { .. }
diff --git a/light-client/src/atlas.rs b/light-client/src/sprite_renderer.rs
index 6d3f7645..64eef8f6 100644
--- a/light-client/src/atlas.rs
+++ b/light-client/src/sprite_renderer.rs
@@ -15,10 +15,7 @@
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
-use hurrycurry_protocol::{
- glam::{IVec2, Vec2},
- ClientGamedata, ItemIndex, TileIndex,
-};
+use hurrycurry_protocol::glam::Vec2;
use sdl2::{
pixels::PixelFormatEnum,
rect::{FRect, Rect},
@@ -28,18 +25,16 @@ use sdl2::{
use std::collections::HashMap;
pub struct SpriteRenderer<'a> {
+ metadata: HashMap<String, Rect>,
texture: Texture<'a>,
- tiles: Vec<Rect>,
- items: Vec<Rect>,
-
view_scale: Vec2,
view_offset: Vec2,
- sprites: Vec<DrawItem>,
+ sprites: Vec<SpriteDraw>,
}
-pub struct DrawItem {
+pub struct SpriteDraw {
z_order: i32,
src: Rect,
dst: FRect,
@@ -91,18 +86,7 @@ impl<'a> SpriteRenderer<'a> {
texture.update(None, &texels, 1024 * 4).unwrap();
texture.set_blend_mode(BlendMode::Blend);
- Self {
- texture,
- items: vec![],
- tiles: vec![],
- sprites: vec![],
- view_offset: Vec2::ZERO,
- view_scale: Vec2::splat(4.),
- }
- }
-
- pub fn set_sprite_map(&mut self, data: ClientGamedata) {
- let meta = include_str!("../assets/atlas.meta.csv")
+ let metadata = include_str!("../assets/atlas.meta.csv")
.lines()
.filter(|l| !l.is_empty())
.map(|l| {
@@ -116,56 +100,52 @@ impl<'a> SpriteRenderer<'a> {
})
.collect::<HashMap<_, _>>();
- self.items = data
- .item_names
- .iter()
- .map(|i| meta.get(i).copied().unwrap_or(Rect::new(0, 0, 0, 0)))
- .collect();
- self.tiles = data
- .tile_names
- .iter()
- .map(|i| meta.get(i).copied().unwrap_or(Rect::new(0, 0, 0, 0)))
- .collect();
+ Self {
+ texture,
+ metadata,
+ sprites: vec![],
+ view_offset: Vec2::ZERO,
+ view_scale: Vec2::splat(64.),
+ }
+ }
+
+ pub fn metadata(&self) -> &HashMap<String, Rect> {
+ &self.metadata
}
- pub fn draw_tile(&mut self, TileIndex(i): TileIndex, position: IVec2) {
- let p = self.view_offset + position.as_vec2();
- let src = self.tiles[i];
- self.sprites.push(DrawItem {
- z_order: position.y,
+ pub fn draw(&mut self, z_order: i32, src: Rect, dst: FRect) {
+ self.sprites.push(SpriteDraw {
+ z_order,
src,
dst: FRect::new(
- (p.x * 32.) * self.view_scale.x,
- (p.y * 24. + 24. - src.height() as f32) * self.view_scale.y,
- src.width() as f32 * self.view_scale.x,
- src.height() as f32 * self.view_scale.y,
+ (dst.x + self.view_offset.x) * self.view_scale.x,
+ (dst.y + self.view_offset.y) * self.view_scale.y,
+ dst.w * self.view_scale.x,
+ dst.h * self.view_scale.y,
),
- });
- }
- pub fn draw_item(&mut self, ItemIndex(_i): ItemIndex, _position: Vec2) {
- todo!()
+ })
}
pub fn submit(&mut self, canvas: &mut Canvas<Window>) {
self.sprites.sort();
- for DrawItem { src, dst, .. } in self.sprites.drain(..) {
+ for SpriteDraw { src, dst, .. } in self.sprites.drain(..) {
canvas.copy_f(&self.texture, src, dst).unwrap();
}
}
}
-impl Ord for DrawItem {
+impl Ord for SpriteDraw {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
self.z_order.cmp(&other.z_order)
}
}
-impl PartialOrd for DrawItem {
+impl PartialOrd for SpriteDraw {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
Some(self.cmp(&other))
}
}
-impl Eq for DrawItem {}
-impl PartialEq for DrawItem {
+impl Eq for SpriteDraw {}
+impl PartialEq for SpriteDraw {
fn eq(&self, other: &Self) -> bool {
self.z_order == other.z_order && self.src == other.src && self.dst == other.dst
}
diff --git a/light-client/src/tilemap.rs b/light-client/src/tilemap.rs
new file mode 100644
index 00000000..cd0f13ac
--- /dev/null
+++ b/light-client/src/tilemap.rs
@@ -0,0 +1,77 @@
+use crate::sprite_renderer::SpriteRenderer;
+use hurrycurry_protocol::{glam::IVec2, TileIndex};
+use sdl2::rect::{FRect, Rect};
+use std::collections::HashMap;
+
+#[derive(Default)]
+pub struct Tilemap {
+ tile_srcs: Vec<[Rect; 16]>,
+ tiles: HashMap<IVec2, (Rect, FRect)>,
+}
+
+impl Tilemap {
+ pub fn init(&mut self, tile_names: &[String], sprite_rects: &HashMap<String, Rect>) {
+ self.tile_srcs = tile_names
+ .iter()
+ .map(|name| {
+ let fallback = sprite_rects
+ .get(&format!("{name}+a"))
+ .copied()
+ .unwrap_or(Rect::new(0, 0, 0, 0));
+
+ [
+ sprite_rects.get(&format!("{name}+")),
+ sprite_rects.get(&format!("{name}+w")),
+ sprite_rects.get(&format!("{name}+e")),
+ sprite_rects.get(&format!("{name}+we")),
+ sprite_rects.get(&format!("{name}+n")),
+ sprite_rects.get(&format!("{name}+wn")),
+ sprite_rects.get(&format!("{name}+en")),
+ sprite_rects.get(&format!("{name}+wen")),
+ sprite_rects.get(&format!("{name}+s")),
+ sprite_rects.get(&format!("{name}+ws")),
+ sprite_rects.get(&format!("{name}+es")),
+ sprite_rects.get(&format!("{name}+wes")),
+ sprite_rects.get(&format!("{name}+ns")),
+ sprite_rects.get(&format!("{name}+wns")),
+ sprite_rects.get(&format!("{name}+ens")),
+ sprite_rects.get(&format!("{name}+wens")),
+ ]
+ .map(|e| e.copied().unwrap_or(fallback))
+ })
+ .collect();
+ }
+
+ pub fn set(&mut self, pos: IVec2, tile: Option<TileIndex>, neighbors: [Option<TileIndex>; 4]) {
+ let Some(tile) = tile else {
+ self.tiles.remove(&pos);
+ return;
+ };
+
+ let mut idx = 0;
+ idx |= 0b0100 * (Some(tile) == neighbors[0]) as usize;
+ idx |= 0b0001 * (Some(tile) == neighbors[1]) as usize;
+ idx |= 0b1000 * (Some(tile) == neighbors[2]) as usize;
+ idx |= 0b0010 * (Some(tile) == neighbors[3]) as usize;
+
+ let src = self.tile_srcs[tile.0][idx];
+ self.tiles.insert(
+ pos,
+ (
+ src,
+ FRect::new(
+ pos.x as f32,
+ pos.y as f32 + 1. - src.height() as f32 / 24.,
+ src.width() as f32 / 32.,
+ src.height() as f32 / 24.,
+ ),
+ ),
+ );
+ }
+
+ pub fn draw(&self, ctx: &mut SpriteRenderer) {
+ for &(src, dst) in self.tiles.values() {
+ ctx.draw(((dst.y + dst.h) * 32.) as i32, src, dst);
+ }
+ }
+}