diff options
author | metamuffin <metamuffin@disroot.org> | 2024-07-16 16:21:37 +0200 |
---|---|---|
committer | metamuffin <metamuffin@disroot.org> | 2024-07-16 16:21:37 +0200 |
commit | 7c83fe7eeaac3736d5a59b270bbbbde59780e536 (patch) | |
tree | 65c59e07f7c72305690312b2d057a9b0d494a847 /light-client/src/game.rs | |
parent | 5cad8fad7c8e8b4358c9b0290c228ac9fac164f5 (diff) | |
download | hurrycurry-7c83fe7eeaac3736d5a59b270bbbbde59780e536.tar hurrycurry-7c83fe7eeaac3736d5a59b270bbbbde59780e536.tar.bz2 hurrycurry-7c83fe7eeaac3736d5a59b270bbbbde59780e536.tar.zst |
item rendering and movement
Diffstat (limited to 'light-client/src/game.rs')
-rw-r--r-- | light-client/src/game.rs | 155 |
1 files changed, 135 insertions, 20 deletions
diff --git a/light-client/src/game.rs b/light-client/src/game.rs index cf265344..b35a15d7 100644 --- a/light-client/src/game.rs +++ b/light-client/src/game.rs @@ -15,31 +15,47 @@ along with this program. If not, see <https://www.gnu.org/licenses/>. */ -use crate::{sprite_renderer::SpriteRenderer, tilemap::Tilemap}; +use crate::{ + sprite_renderer::{SpriteRect, SpriteRenderer}, + tilemap::Tilemap, +}; use hurrycurry_protocol::{ glam::{IVec2, Vec2}, - PacketC, PlayerID, TileIndex, + movement::MovementBase, + ClientGamedata, ItemIndex, ItemLocation, PacketC, PacketS, PlayerID, TileIndex, }; use log::{info, warn}; -use sdl2::rect::FRect; -use std::collections::HashMap; +use sdl2::{ + keyboard::{KeyboardState, Scancode}, + rect::{FRect, Rect}, +}; +use std::collections::{HashMap, HashSet, VecDeque}; pub struct Game { + data: ClientGamedata, tiles: HashMap<IVec2, Tile>, tilemap: Tilemap, + collision_map: HashSet<IVec2>, players: HashMap<PlayerID, Player>, my_id: PlayerID, + + item_sprites: Vec<SpriteRect>, + movement_send_cooldown: f32, } pub struct Tile { kind: TileIndex, + item: Option<Item>, } pub struct Player { + movement: MovementBase, + item: Option<Item>, + name: String, character: i32, +} +pub struct Item { position: Vec2, - name: String, - boosting: bool, - rot: f32, + kind: ItemIndex, } impl Game { @@ -49,6 +65,10 @@ impl Game { players: HashMap::new(), tilemap: Tilemap::default(), my_id: PlayerID(0), + data: ClientGamedata::default(), + collision_map: HashSet::new(), + movement_send_cooldown: 0., + item_sprites: Vec::new(), } } @@ -57,6 +77,20 @@ impl Game { PacketC::Init { id } => self.my_id = id, PacketC::Data { data } => { self.tilemap.init(&data.tile_names, renderer.metadata()); + self.item_sprites = data + .item_names + .iter() + .map(|name| { + SpriteRect::new( + renderer + .metadata() + .get(&format!("{name}:a")) + .copied() + .unwrap_or(Rect::new(0, 0, 32, 24)), + ) + }) + .collect(); + self.data = data; } PacketC::UpdateMap { tile, @@ -64,9 +98,15 @@ impl Game { neighbors, } => { if let Some(kind) = kind { - self.tiles.insert(tile, Tile { kind }); + self.tiles.insert(tile, Tile { kind, item: None }); + if self.data.tile_collide[kind.0] { + self.collision_map.remove(&tile); + } else { + self.collision_map.insert(tile); + } } else { self.tiles.remove(&tile); + self.collision_map.remove(&tile); } self.tilemap.set(tile, kind, neighbors); } @@ -81,10 +121,16 @@ impl Game { id, Player { character, - position, name, - boosting: false, - rot: 0., + item: None, + movement: MovementBase { + position, + facing: Vec2::X, + rotation: 0., + velocity: Vec2::ZERO, + boosting: false, + stamina: 0., + }, }, ); } @@ -98,14 +144,21 @@ impl Game { rot, boosting, } => { - if let Some(p) = self.players.get_mut(&player) { - p.position = pos; - p.rot = rot; - p.boosting = boosting; + if player != self.my_id { + if let Some(p) = self.players.get_mut(&player) { + p.movement.position = pos; + p.movement.rotation = rot; + p.movement.boosting = boosting; + } } } - PacketC::MoveItem { from, to } => (), - PacketC::SetItem { location, item } => (), + PacketC::MoveItem { from, to } => *self.get_item(to) = self.get_item(from).take(), + PacketC::SetItem { location, item } => { + *self.get_item(location) = item.map(|kind| Item { + kind, + position: Vec2::ZERO, + }) + } PacketC::SetProgress { item, progress, @@ -132,18 +185,80 @@ impl Game { } } + pub fn get_item(&mut self, location: ItemLocation) -> &mut Option<Item> { + match location { + ItemLocation::Tile(pos) => &mut self.tiles.get_mut(&pos).unwrap().item, + ItemLocation::Player(pid) => &mut self.players.get_mut(&pid).unwrap().item, + } + } + + pub fn tick(&mut self, dt: f32, keyboard: &KeyboardState, packet_out: &mut VecDeque<PacketS>) { + let direction = IVec2::new( + keyboard.is_scancode_pressed(Scancode::D) as i32 + - keyboard.is_scancode_pressed(Scancode::A) as i32, + keyboard.is_scancode_pressed(Scancode::S) as i32 + - keyboard.is_scancode_pressed(Scancode::W) as i32, + ) + .as_vec2(); + let boost = keyboard.is_scancode_pressed(Scancode::K); + let interact = keyboard.is_scancode_pressed(Scancode::Space) + | keyboard.is_scancode_pressed(Scancode::J); + + self.movement_send_cooldown -= dt; + let send_movement = self.movement_send_cooldown < 0.; + if send_movement { + self.movement_send_cooldown += 0.04 + } + + for (pid, player) in &mut self.players { + if *pid == self.my_id { + let movement_packet = + player + .movement + .update(&self.collision_map, direction, boost, dt); + + if send_movement { + packet_out.push_back(movement_packet); + } + } + if let Some(item) = &mut player.item { + item.position = player.movement.position + } + } + for (pos, tile) in &mut self.tiles { + if let Some(item) = &mut tile.item { + item.position = pos.as_vec2() + 0.5 + } + } + } + pub fn draw(&self, ctx: &mut SpriteRenderer) { self.tilemap.draw(ctx); for p in self.players.values() { let src = ctx.misc_textures().player; let dst = FRect::new( - p.position.x - src.width() as f32 / 32. / 2., - p.position.y + 1. - src.height() as f32 / 24., + 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.) * 24.) as i32, src, dst); + ctx.draw(dst.y + dst.h + 1., src, dst); + if let Some(item) = &p.item { + item.draw(ctx, &self.item_sprites) + } + } + for tile in self.tiles.values() { + if let Some(item) = &tile.item { + item.draw(ctx, &self.item_sprites) + } } } } + +impl Item { + pub fn draw(&self, ctx: &mut SpriteRenderer, item_sprites: &[SpriteRect]) { + eprintln!("item {} at {}", self.kind.0, self.position); + item_sprites[self.kind.0].draw_at(ctx, self.position) + } +} |