aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--light-client/src/game.rs27
-rw-r--r--light-client/src/main.rs7
-rw-r--r--light-client/src/render/sprite.rs11
-rw-r--r--light-client/src/sprite_renderer.rs200
-rw-r--r--light-client/src/tilemap.rs28
5 files changed, 32 insertions, 241 deletions
diff --git a/light-client/src/game.rs b/light-client/src/game.rs
index b6bacf74..ac5c3571 100644
--- a/light-client/src/game.rs
+++ b/light-client/src/game.rs
@@ -16,7 +16,7 @@
*/
use crate::{
- sprite_renderer::{SpriteRect, SpriteRenderer},
+ render::{sprite::Sprite, MiscTextures, SpriteRenderer},
tilemap::Tilemap,
};
use hurrycurry_protocol::{
@@ -27,7 +27,7 @@ use hurrycurry_protocol::{
use log::{info, warn};
use sdl2::{
keyboard::{KeyboardState, Scancode},
- rect::{FRect, Rect},
+ rect::Rect,
};
use std::collections::{HashMap, HashSet, VecDeque};
@@ -39,7 +39,8 @@ pub struct Game {
players: HashMap<PlayerID, Player>,
my_id: PlayerID,
- item_sprites: Vec<SpriteRect>,
+ misc_textures: MiscTextures,
+ item_sprites: Vec<Sprite>,
movement_send_cooldown: f32,
}
@@ -59,7 +60,7 @@ pub struct Item {
}
impl Game {
- pub fn new() -> Self {
+ pub fn new(renderer: &SpriteRenderer) -> Self {
Self {
tiles: HashMap::new(),
players: HashMap::new(),
@@ -68,6 +69,7 @@ impl Game {
data: ClientGamedata::default(),
collision_map: HashSet::new(),
movement_send_cooldown: 0.,
+ misc_textures: MiscTextures::init(renderer),
item_sprites: Vec::new(),
}
}
@@ -81,12 +83,14 @@ impl Game {
.item_names
.iter()
.map(|name| {
- SpriteRect::new(
+ Sprite::new(
renderer
.metadata()
.get(&format!("{name}:a"))
.copied()
.unwrap_or(Rect::new(0, 0, 32, 24)),
+ Vec2::ZERO,
+ 0.1,
)
})
.collect();
@@ -236,14 +240,7 @@ impl Game {
self.tilemap.draw(ctx);
for p in self.players.values() {
- let src = ctx.misc_textures().player;
- let dst = FRect::new(
- p.movement.position.x - src.width() as f32 / 32. / 2.,
- p.movement.position.y + 0.3 - src.height() as f32 / 24.,
- src.width() as f32 / 32.,
- src.height() as f32 / 24.,
- );
- ctx.draw(dst.y + dst.h + 1., src, dst);
+ ctx.draw_world(self.misc_textures.player.at(p.movement.position));
if let Some(item) = &p.item {
item.draw(ctx, &self.item_sprites)
}
@@ -257,7 +254,7 @@ impl Game {
}
impl Item {
- pub fn draw(&self, ctx: &mut SpriteRenderer, item_sprites: &[SpriteRect]) {
- item_sprites[self.kind.0].draw_at(ctx, self.position)
+ pub fn draw(&self, ctx: &mut SpriteRenderer, item_sprites: &[Sprite]) {
+ ctx.draw_world(item_sprites[self.kind.0].at(self.position))
}
}
diff --git a/light-client/src/main.rs b/light-client/src/main.rs
index a1c02475..278229d2 100644
--- a/light-client/src/main.rs
+++ b/light-client/src/main.rs
@@ -17,19 +17,18 @@
*/
use game::Game;
use network::Network;
+use render::SpriteRenderer;
use sdl2::{
event::Event,
keyboard::{KeyboardState, Keycode},
pixels::Color,
};
-use sprite_renderer::SpriteRenderer;
use std::time::{Duration, Instant};
pub mod game;
pub mod network;
-pub mod sprite_renderer;
-pub mod tilemap;
pub mod render;
+pub mod tilemap;
fn main() {
env_logger::init_from_env("LOG");
@@ -53,8 +52,8 @@ fn main() {
let texture_creator = canvas.texture_creator();
let mut net = Network::connect("ws://127.0.0.1/").unwrap();
- let mut game = Game::new();
let mut renderer = SpriteRenderer::init(&texture_creator);
+ let mut game = Game::new(&renderer);
net.queue_out.push_back(hurrycurry_protocol::PacketS::Join {
name: "light".to_string(),
diff --git a/light-client/src/render/sprite.rs b/light-client/src/render/sprite.rs
index 942db611..13ede525 100644
--- a/light-client/src/render/sprite.rs
+++ b/light-client/src/render/sprite.rs
@@ -10,10 +10,10 @@ pub struct Sprite {
impl Sprite {
pub fn new(src: Rect, anchor: Vec2, elevation: f32) -> Self {
let relative_dst = FRect::new(
- anchor.x - (src.w as f32) / 32. / 2.,
- anchor.y - (src.h as f32) / 24.,
+ -anchor.x - (src.w as f32) / 32. / 2.,
+ -anchor.y - (src.h as f32) / 24.,
(src.w as f32) / 32.,
- (src.h as f32) / 32.,
+ (src.h as f32) / 24.,
);
Self {
z_offset: -relative_dst.h + anchor.y - elevation,
@@ -21,8 +21,8 @@ impl Sprite {
relative_dst,
}
}
- pub fn new_tile(src: Rect) {
- Self::new(src, Vec2::new(0.5, 1.0), 0.);
+ pub fn new_tile(src: Rect) -> Self {
+ Self::new(src, Vec2::new(0.5, 1.0), 0.)
}
pub fn at(&self, pos: Vec2) -> SpriteDraw {
SpriteDraw {
@@ -38,6 +38,7 @@ impl Sprite {
}
}
+#[derive(Debug, Clone, Copy)]
pub struct SpriteDraw {
pub z_order: i32,
pub src: Rect,
diff --git a/light-client/src/sprite_renderer.rs b/light-client/src/sprite_renderer.rs
deleted file mode 100644
index aadbfbe3..00000000
--- a/light-client/src/sprite_renderer.rs
+++ /dev/null
@@ -1,200 +0,0 @@
-/*
- Hurry Curry! - a game about cooking
- Copyright 2024 metamuffin
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Affero General Public License as published by
- the Free Software Foundation, version 3 of the License only.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see <https://www.gnu.org/licenses/>.
-
-*/
-use hurrycurry_protocol::glam::Vec2;
-use sdl2::{
- pixels::PixelFormatEnum,
- rect::{FRect, Rect},
- render::{BlendMode, Canvas, Texture, TextureAccess, TextureCreator},
- video::{Window, WindowContext},
-};
-use std::collections::HashMap;
-
-pub struct SpriteRenderer<'a> {
- metadata: HashMap<String, Rect>,
- misc_textures: MiscTextures,
-
- texture: Texture<'a>,
-
- view_scale: Vec2,
- view_offset: Vec2,
-
- sprites: Vec<SpriteDraw>,
-}
-
-pub struct MiscTextures {
- pub player: Rect,
-}
-
-pub struct SpriteDraw {
- z_order: i32,
- src: Rect,
- dst: FRect,
-}
-
-pub struct SpriteRect {
- z_offset: f32,
- src: Rect,
- relative_dst: FRect,
-}
-
-impl<'a> SpriteRenderer<'a> {
- pub fn init(texture_creator: &'a TextureCreator<WindowContext>) -> Self {
- let palette = include_str!("../assets/palette.csv")
- .split('\n')
- .filter(|l| !l.is_empty())
- .map(|s| {
- let mut toks = s.split(",");
- (
- toks.next().unwrap().chars().next().unwrap(),
- [
- toks.next().unwrap().parse::<u8>().unwrap(),
- toks.next().unwrap().parse::<u8>().unwrap(),
- toks.next().unwrap().parse::<u8>().unwrap(),
- toks.next().unwrap().parse::<u8>().unwrap(),
- ],
- )
- })
- .collect::<HashMap<_, _>>();
-
- let mut texels = vec![255; 1024 * 1024 * 4];
-
- for (y, line) in include_str!("../assets/atlas.ta").lines().enumerate() {
- if line.is_empty() {
- continue;
- }
- for (x, char) in line.chars().enumerate() {
- let color = palette.get(&char).unwrap();
- texels[(y * 1024 + x) * 4 + 0] = color[3];
- texels[(y * 1024 + x) * 4 + 1] = color[2];
- texels[(y * 1024 + x) * 4 + 2] = color[1];
- texels[(y * 1024 + x) * 4 + 3] = color[0];
- }
- }
-
- let mut texture = texture_creator
- .create_texture(
- Some(PixelFormatEnum::RGBA8888),
- TextureAccess::Streaming,
- 1024,
- 1024,
- )
- .unwrap();
-
- texture.update(None, &texels, 1024 * 4).unwrap();
- texture.set_blend_mode(BlendMode::Blend);
-
- let metadata = include_str!("../assets/atlas.meta.csv")
- .lines()
- .filter(|l| !l.is_empty())
- .map(|l| {
- let mut toks = l.split(",");
- let x: i32 = toks.next().unwrap().parse().unwrap();
- let y: i32 = toks.next().unwrap().parse().unwrap();
- let w: u32 = toks.next().unwrap().parse().unwrap();
- let h: u32 = toks.next().unwrap().parse().unwrap();
- let name = toks.next().unwrap().to_string();
- (name, Rect::new(x, y, w, h))
- })
- .collect::<HashMap<_, _>>();
-
- Self {
- misc_textures: MiscTextures {
- player: *metadata.get("player+a").unwrap(),
- },
- texture,
- metadata,
- sprites: vec![],
- view_offset: Vec2::ZERO,
- view_scale: Vec2::splat(3.),
- }
- }
-
- #[inline]
- pub fn metadata(&self) -> &HashMap<String, Rect> {
- &self.metadata
- }
- #[inline]
- pub fn misc_textures(&self) -> &MiscTextures {
- &self.misc_textures
- }
-
- pub fn draw(&mut self, z_order: f32, src: Rect, dst: FRect) {
- self.sprites.push(SpriteDraw {
- z_order: (z_order * 24.) as i32,
- src,
- dst: FRect::new(
- ((dst.x + self.view_offset.x) * 32.).round() * self.view_scale.x,
- ((dst.y + self.view_offset.y) * 24.).round() * self.view_scale.y,
- (dst.w * 32.).round() * self.view_scale.x,
- (dst.h * 24.).round() * self.view_scale.y,
- ),
- })
- }
-
- pub fn submit(&mut self, canvas: &mut Canvas<Window>) {
- self.sprites.sort();
- for SpriteDraw { src, dst, .. } in self.sprites.drain(..) {
- canvas.copy_f(&self.texture, src, dst).unwrap();
- }
- }
-}
-
-impl Ord for SpriteDraw {
- fn cmp(&self, other: &Self) -> std::cmp::Ordering {
- self.z_order.cmp(&other.z_order)
- }
-}
-impl PartialOrd for SpriteDraw {
- fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
- Some(self.cmp(&other))
- }
-}
-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
- }
-}
-
-impl SpriteRect {
- pub fn draw_at(&self, ctx: &mut SpriteRenderer, pos: Vec2) {
- ctx.draw(
- self.z_offset + pos.y + 5.,
- self.src,
- FRect::new(
- self.relative_dst.x + pos.x,
- self.relative_dst.y + pos.y,
- self.relative_dst.w,
- self.relative_dst.h,
- ),
- )
- }
- pub fn new(src: Rect) -> Self {
- let relative_dst = FRect::new(
- 0.0 - src.width() as f32 / 32. / 2.,
- 0.3 - src.height() as f32 / 24.,
- src.width() as f32 / 32.,
- src.height() as f32 / 24.,
- );
- Self {
- z_offset: -relative_dst.h,
- relative_dst,
- src,
- }
- }
-}
diff --git a/light-client/src/tilemap.rs b/light-client/src/tilemap.rs
index e84db8b1..cf8c5eef 100644
--- a/light-client/src/tilemap.rs
+++ b/light-client/src/tilemap.rs
@@ -15,15 +15,19 @@
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
-use crate::sprite_renderer::SpriteRenderer;
use hurrycurry_protocol::{glam::IVec2, TileIndex};
-use sdl2::rect::{FRect, Rect};
+use sdl2::rect::Rect;
use std::collections::HashMap;
+use crate::render::{
+ sprite::{Sprite, SpriteDraw},
+ SpriteRenderer,
+};
+
#[derive(Default)]
pub struct Tilemap {
tile_srcs: Vec<[Rect; 16]>,
- tiles: HashMap<IVec2, (Rect, FRect)>,
+ tiles: HashMap<IVec2, SpriteDraw>,
}
impl Tilemap {
@@ -72,23 +76,13 @@ impl Tilemap {
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.,
- ),
- ),
- );
+ self.tiles
+ .insert(pos, Sprite::new_tile(src).at(pos.as_vec2() + 0.5));
}
pub fn draw(&self, ctx: &mut SpriteRenderer) {
- for &(src, dst) in self.tiles.values() {
- ctx.draw(dst.y + dst.h, src, dst);
+ for &sprite in self.tiles.values() {
+ ctx.draw_world(sprite);
}
}
}