summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormetamuffin <metamuffin@disroot.org>2024-07-17 20:32:06 +0200
committermetamuffin <metamuffin@disroot.org>2024-07-17 20:32:06 +0200
commit356e6976f10973ec5e1678534c9d8d9742033bee (patch)
tree455e671ff0c24b876f3156ee56e61e43d608decb
parent4e2f42cc87e33752c76e866009786d4f827d9cb2 (diff)
downloadhurrycurry-356e6976f10973ec5e1678534c9d8d9742033bee.tar
hurrycurry-356e6976f10973ec5e1678534c9d8d9742033bee.tar.bz2
hurrycurry-356e6976f10973ec5e1678534c9d8d9742033bee.tar.zst
a
-rw-r--r--Cargo.lock7
-rw-r--r--pixel-client/Cargo.toml2
-rw-r--r--pixel-client/src/game.rs159
-rw-r--r--pixel-client/src/main.rs65
-rw-r--r--pixel-client/src/menu.rs17
5 files changed, 160 insertions, 90 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 9bd87459..69fb8a85 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -313,6 +313,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a12916984aab3fa6e39d655a33e09c0071eb36d6ab3aea5c2d78551f1df6d952"
[[package]]
+name = "c_vec"
+version = "2.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fdd7a427adc0135366d99db65b36dae9237130997e560ed61118041fb72be6e8"
+
+[[package]]
name = "cc"
version = "1.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1628,6 +1634,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3b498da7d14d1ad6c839729bd4ad6fc11d90a57583605f3b4df2cd709a9cd380"
dependencies = [
"bitflags 1.3.2",
+ "c_vec",
"lazy_static",
"libc",
"sdl2-sys",
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) {
+
+
+
+
+ }
+}