diff options
Diffstat (limited to 'pixel-client')
| -rw-r--r-- | pixel-client/Cargo.toml | 2 | ||||
| -rw-r--r-- | pixel-client/src/game.rs | 159 | ||||
| -rw-r--r-- | pixel-client/src/main.rs | 65 | ||||
| -rw-r--r-- | pixel-client/src/menu.rs | 17 | 
4 files changed, 153 insertions, 90 deletions
diff --git a/pixel-client/Cargo.toml b/pixel-client/Cargo.toml index bd441236..dd46a9b6 100644 --- a/pixel-client/Cargo.toml +++ b/pixel-client/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0"  edition = "2021"  [dependencies] -sdl2 = { version = "0.37.0", features = [] } +sdl2 = { version = "0.37.0", features = ["gfx", "ttf", "mixer"] }  hurrycurry-protocol = { path = "../server/protocol" }  tungstenite = { version = "0.23.0", features = ["rustls-tls-native-roots"] }  serde_json = "1.0.120" diff --git a/pixel-client/src/game.rs b/pixel-client/src/game.rs index 170e6a6e..cbc9954c 100644 --- a/pixel-client/src/game.rs +++ b/pixel-client/src/game.rs @@ -17,6 +17,7 @@  */  use crate::{      helper::InterpolateExt, +    network::Network,      render::{          misc::MiscTextures,          sprite::{Sprite, SpriteDraw}, @@ -34,9 +35,11 @@ use sdl2::{      keyboard::{KeyboardState, Scancode},      rect::Rect,  }; -use std::collections::{HashMap, HashSet, VecDeque}; +use std::collections::{HashMap, HashSet};  pub struct Game { +    network: Network, +      data: ClientGamedata,      tiles: HashMap<IVec2, Tile>,      tilemap: Tilemap, @@ -82,8 +85,16 @@ pub struct Item {  }  impl Game { -    pub fn new(layout: &AtlasLayout) -> Self { +    pub fn new(mut network: Network, layout: &AtlasLayout) -> Self { +        network +            .queue_out +            .push_back(hurrycurry_protocol::PacketS::Join { +                name: "light".to_string(), +                character: 0, +            }); +          Self { +            network,              tiles: HashMap::new(),              players: HashMap::new(),              tilemap: Tilemap::default(), @@ -100,18 +111,90 @@ impl Game {          }      } -    pub fn packet_in(&mut self, packet: PacketC, renderer: &mut SpriteRenderer) { +    pub fn tick(&mut self, dt: f32, keyboard: &KeyboardState, layout: &AtlasLayout) { +        self.network.poll(); + +        // TODO perf +        for packet in self.network.queue_in.drain(..).collect::<Vec<_>>() { +            self.packet_in(packet, layout); +        } + +        let mut 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); + +        if interact { +            direction *= 0.; +        } + +        self.movement_send_cooldown -= dt; +        let send_movement = self.movement_send_cooldown < 0.; +        if send_movement { +            self.movement_send_cooldown += 0.04 +        } + +        self.score.time_remaining -= dt; +        self.score.time_remaining -= self.score.time_remaining.max(0.); + +        if interact != self.interacting { +            if interact { +                self.network.queue_out.push_back(PacketS::Interact { +                    pos: Some(self.players[&self.my_id].movement.get_interact_target()), +                }); +            } else { +                self.network +                    .queue_out +                    .push_back(PacketS::Interact { pos: None }); +            } +            self.interacting = interact; +        } + +        if let Some(player) = self.players.get_mut(&self.my_id) { +            let movement_packet = player +                .movement +                .update(&self.collision_map, direction, boost, dt); +            if send_movement { +                self.network.queue_out.push_back(movement_packet); +            } + +            self.camera_center.exp_to(player.movement.position, dt * 5.); +        } + +        for (_pid, player) in &mut self.players { +            if let Some(item) = &mut player.item { +                item.parent_position = player.movement.position; +                item.tick(1., dt); +            } +        } +        for (_pos, tile) in &mut self.tiles { +            if let Some(item) = &mut tile.item { +                item.tick(1., dt) +            } +        } +        self.items_removed.retain_mut(|i| { +            i.tick(0., dt); +            i.alive > 0.01 +        }) +    } + +    pub fn packet_in(&mut self, packet: PacketC, layout: &AtlasLayout) {          match packet {              PacketC::Init { id } => self.my_id = id,              PacketC::Data { data } => { -                self.tilemap.init(&data.tile_names, renderer.atlas_layout()); +                self.tilemap.init(&data.tile_names, layout);                  self.item_sprites = data                      .item_names                      .iter()                      .map(|name| {                          Sprite::new( -                            renderer -                                .atlas_layout() +                            layout                                  .get(&format!("{name}+a"))                                  .copied()                                  .unwrap_or_else(|| { @@ -264,70 +347,6 @@ impl Game {          }      } -    pub fn tick(&mut self, dt: f32, keyboard: &KeyboardState, packet_out: &mut VecDeque<PacketS>) { -        let mut 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); - -        if interact { -            direction *= 0.; -        } - -        self.movement_send_cooldown -= dt; -        let send_movement = self.movement_send_cooldown < 0.; -        if send_movement { -            self.movement_send_cooldown += 0.04 -        } - -        self.score.time_remaining -= dt; -        self.score.time_remaining -= self.score.time_remaining.max(0.); - -        if interact != self.interacting { -            if interact { -                packet_out.push_back(PacketS::Interact { -                    pos: Some(self.players[&self.my_id].movement.get_interact_target()), -                }); -            } else { -                packet_out.push_back(PacketS::Interact { pos: None }); -            } -            self.interacting = interact; -        } - -        if let Some(player) = self.players.get_mut(&self.my_id) { -            let movement_packet = player -                .movement -                .update(&self.collision_map, direction, boost, dt); -            if send_movement { -                packet_out.push_back(movement_packet); -            } - -            self.camera_center.exp_to(player.movement.position, dt * 5.); -        } - -        for (_pid, player) in &mut self.players { -            if let Some(item) = &mut player.item { -                item.parent_position = player.movement.position; -                item.tick(1., dt); -            } -        } -        for (_pos, tile) in &mut self.tiles { -            if let Some(item) = &mut tile.item { -                item.tick(1., dt) -            } -        } -        self.items_removed.retain_mut(|i| { -            i.tick(0., dt); -            i.alive > 0.01 -        }) -    } -      pub fn draw(&self, ctx: &mut SpriteRenderer) {          ctx.set_view(-self.camera_center + (ctx.size / ctx.get_scale() / 2.), 1.); diff --git a/pixel-client/src/main.rs b/pixel-client/src/main.rs index 76735c35..db2585af 100644 --- a/pixel-client/src/main.rs +++ b/pixel-client/src/main.rs @@ -1,5 +1,3 @@ -use anyhow::anyhow; -use clap::Parser;  /*      Hurry Curry! - a game about cooking      Copyright 2024 metamuffin @@ -17,8 +15,11 @@ use clap::Parser;      along with this program.  If not, see <https://www.gnu.org/licenses/>.  */ +use anyhow::anyhow; +use clap::{Parser, Subcommand};  use game::Game;  use hurrycurry_protocol::glam::{UVec2, Vec2}; +use menu::Menu;  use network::Network;  use render::SpriteRenderer;  use sdl2::{ @@ -33,17 +34,28 @@ use std::{  pub mod game;  pub mod helper; +pub mod menu;  pub mod network;  pub mod render;  pub mod tilemap;  #[derive(Debug, Parser)]  pub struct Args { -    #[arg(default_value = "ws://127.0.0.1/")] -    server_address: String, -      #[arg(short = 'r', long, default_value = "320x240")]      logical_resolution: Resolution, + +    #[clap(subcommand)] +    action: Option<Action>, +} + +#[derive(Debug, Subcommand, Default)] +pub enum Action { +    #[default] +    Menu, +    Join { +        #[arg(default_value = "ws://127.0.0.1/")] +        server_address: String, +    },  }  #[derive(Debug, Clone)] @@ -56,6 +68,11 @@ impl FromStr for Resolution {      }  } +enum State { +    Ingame(Game), +    Menu(Menu), +} +  fn main() {      env_logger::init_from_env("LOG"); @@ -66,6 +83,7 @@ fn main() {          .unwrap();      let sdl_context = sdl2::init().unwrap(); +    let ttf_context = sdl2::ttf::init().unwrap();      let video_subsystem = sdl_context.video().unwrap();      let window = video_subsystem @@ -82,16 +100,24 @@ fn main() {          .build()          .map_err(|e| e.to_string())          .unwrap(); +      let texture_creator = canvas.texture_creator(); -    let mut net = Network::connect(&args.server_address).unwrap();      let mut renderer = SpriteRenderer::init(&texture_creator); -    let mut game = Game::new(&renderer.atlas_layout()); -    net.queue_out.push_back(hurrycurry_protocol::PacketS::Join { -        name: "light".to_string(), -        character: 0, -    }); +    let mut state = match args.action.unwrap_or_default() { +        Action::Menu => State::Menu(Menu::new()), +        Action::Join { server_address } => State::Ingame(Game::new( +            Network::connect(&server_address).unwrap(), +            &renderer.atlas_layout(), +        )), +    }; + +    // let font = ttf_context +    //     .load_font("/usr/share/fonts/noto/NotoSansMono-Regular.ttf", 24) +    //     .unwrap(); +    // let text = font.render("Hello world").blended(Color::WHITE).unwrap(); +    // texture_creator.create_texture_from_surface(text).unwrap();      let mut events = sdl_context.event_pump().unwrap(); @@ -102,21 +128,22 @@ fn main() {          .unwrap();      'mainloop: loop { -        net.poll(); -          let (width, height) = canvas.logical_size();          renderer.size = Vec2::new(width as f32, height as f32); -        for packet in net.queue_in.drain(..) { -            game.packet_in(packet, &mut renderer); -        } -          let keyboard = KeyboardState::new(&events);          let dt = last_tick.elapsed().min(Duration::from_secs_f32(1. / 30.)); -        game.tick(dt.as_secs_f32(), &keyboard, &mut net.queue_out); +        match &mut state { +            State::Ingame(x) => x.tick(dt.as_secs_f32(), &keyboard, renderer.atlas_layout()), +            State::Menu(x) => x.tick(dt.as_secs_f32(), &keyboard, renderer.atlas_layout()), +        } +          last_tick += dt; -        game.draw(&mut renderer); +        match &mut state { +            State::Ingame(x) => x.draw(&mut renderer), +            State::Menu(x) => x.draw(&mut renderer), +        }          canvas.set_draw_color(Color::BLACK);          canvas.clear(); diff --git a/pixel-client/src/menu.rs b/pixel-client/src/menu.rs new file mode 100644 index 00000000..d1f43a84 --- /dev/null +++ b/pixel-client/src/menu.rs @@ -0,0 +1,17 @@ +use crate::render::{AtlasLayout, SpriteRenderer}; +use sdl2::keyboard::KeyboardState; + +pub struct Menu {} + +impl Menu { +    pub fn new() -> Self { +        Self {} +    } +    pub fn tick(&mut self, dt: f32, keyboard: &KeyboardState, layout: &AtlasLayout) {} +    pub fn draw(&self, ctx: &mut SpriteRenderer) { + +         + + +    } +}  |