aboutsummaryrefslogtreecommitdiff
path: root/light-client/src
diff options
context:
space:
mode:
Diffstat (limited to 'light-client/src')
-rw-r--r--light-client/src/game.rs103
-rw-r--r--light-client/src/main.rs2
-rw-r--r--light-client/src/render/misc.rs17
-rw-r--r--light-client/src/render/mod.rs30
-rw-r--r--light-client/src/render/sprite.rs15
5 files changed, 121 insertions, 46 deletions
diff --git a/light-client/src/game.rs b/light-client/src/game.rs
index ac5c3571..1425a3f8 100644
--- a/light-client/src/game.rs
+++ b/light-client/src/game.rs
@@ -16,7 +16,7 @@
*/
use crate::{
- render::{sprite::Sprite, MiscTextures, SpriteRenderer},
+ render::{misc::MiscTextures, sprite::Sprite, AtlasLayout, SpriteRenderer},
tilemap::Tilemap,
};
use hurrycurry_protocol::{
@@ -42,25 +42,38 @@ pub struct Game {
misc_textures: MiscTextures,
item_sprites: Vec<Sprite>,
movement_send_cooldown: f32,
+ interacting: bool,
+ score: Score,
+}
+
+#[derive(Debug, Default)]
+pub struct Score {
+ points: i64,
+ demands_failed: usize,
+ demands_completed: usize,
+ time_remaining: f32,
}
pub struct Tile {
- kind: TileIndex,
+ _kind: TileIndex,
item: Option<Item>,
}
+
pub struct Player {
movement: MovementBase,
item: Option<Item>,
- name: String,
- character: i32,
+ _name: String,
+ _character: i32,
}
+
pub struct Item {
position: Vec2,
kind: ItemIndex,
+ progress: Option<(f32, bool)>,
}
impl Game {
- pub fn new(renderer: &SpriteRenderer) -> Self {
+ pub fn new(layout: &AtlasLayout) -> Self {
Self {
tiles: HashMap::new(),
players: HashMap::new(),
@@ -69,8 +82,10 @@ impl Game {
data: ClientGamedata::default(),
collision_map: HashSet::new(),
movement_send_cooldown: 0.,
- misc_textures: MiscTextures::init(renderer),
+ misc_textures: MiscTextures::init(layout),
item_sprites: Vec::new(),
+ interacting: false,
+ score: Score::default(),
}
}
@@ -78,18 +93,21 @@ impl Game {
match packet {
PacketC::Init { id } => self.my_id = id,
PacketC::Data { data } => {
- self.tilemap.init(&data.tile_names, renderer.metadata());
+ self.tilemap.init(&data.tile_names, renderer.atlas_layout());
self.item_sprites = data
.item_names
.iter()
.map(|name| {
Sprite::new(
renderer
- .metadata()
- .get(&format!("{name}:a"))
+ .atlas_layout()
+ .get(&format!("{name}+a"))
.copied()
- .unwrap_or(Rect::new(0, 0, 32, 24)),
- Vec2::ZERO,
+ .unwrap_or_else(|| {
+ warn!("no sprite for item {name:?}");
+ Rect::new(0, 0, 32, 24)
+ }),
+ Vec2::new(0., 0.0),
0.1,
)
})
@@ -102,7 +120,13 @@ impl Game {
neighbors,
} => {
if let Some(kind) = kind {
- self.tiles.insert(tile, Tile { kind, item: None });
+ self.tiles.insert(
+ tile,
+ Tile {
+ _kind: kind,
+ item: None,
+ },
+ );
if self.data.tile_collide[kind.0] {
self.collision_map.remove(&tile);
} else {
@@ -124,8 +148,8 @@ impl Game {
self.players.insert(
id,
Player {
- character,
- name,
+ _character: character,
+ _name: name,
item: None,
movement: MovementBase {
position,
@@ -161,27 +185,40 @@ impl Game {
*self.get_item(location) = item.map(|kind| Item {
kind,
position: Vec2::ZERO,
+ progress: None,
})
}
PacketC::SetProgress {
item,
progress,
warn,
+ } => {
+ self.get_item(item).as_mut().unwrap().progress = progress.map(|s| (s, warn));
+ }
+ PacketC::Collide {
+ player: _,
+ force: _,
} => (),
- PacketC::Collide { player, force } => (),
- PacketC::Communicate {
- player,
- message,
- persist,
- } => (),
- PacketC::ServerMessage { text } => (),
+ PacketC::Communicate { .. } => {
+ // TODO
+ }
+ PacketC::ServerMessage { text: _ } => {
+ // TODO
+ }
PacketC::Score {
points,
demands_failed,
demands_completed,
time_remaining,
- } => (),
- PacketC::SetIngame { state, lobby } => (),
+ } => {
+ self.score.points = points;
+ self.score.demands_completed = demands_completed;
+ self.score.demands_failed = demands_failed;
+ self.score.time_remaining = time_remaining.unwrap_or(-1.);
+ }
+ PacketC::SetIngame { state: _, lobby: _ } => {
+ // TODO
+ }
PacketC::Error { message } => {
warn!("server error: {message:?}")
}
@@ -197,7 +234,7 @@ impl Game {
}
pub fn tick(&mut self, dt: f32, keyboard: &KeyboardState, packet_out: &mut VecDeque<PacketS>) {
- let direction = IVec2::new(
+ 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
@@ -208,12 +245,30 @@ impl Game {
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;
+ }
+
for (pid, player) in &mut self.players {
if *pid == self.my_id {
let movement_packet =
diff --git a/light-client/src/main.rs b/light-client/src/main.rs
index 278229d2..7526b394 100644
--- a/light-client/src/main.rs
+++ b/light-client/src/main.rs
@@ -53,7 +53,7 @@ fn main() {
let mut net = Network::connect("ws://127.0.0.1/").unwrap();
let mut renderer = SpriteRenderer::init(&texture_creator);
- let mut game = Game::new(&renderer);
+ let mut game = Game::new(&renderer.atlas_layout());
net.queue_out.push_back(hurrycurry_protocol::PacketS::Join {
name: "light".to_string(),
diff --git a/light-client/src/render/misc.rs b/light-client/src/render/misc.rs
new file mode 100644
index 00000000..9f866568
--- /dev/null
+++ b/light-client/src/render/misc.rs
@@ -0,0 +1,17 @@
+use super::{sprite::Sprite, AtlasLayout};
+use hurrycurry_protocol::glam::Vec2;
+use sdl2::rect::Rect;
+
+pub struct MiscTextures {
+ pub player: Sprite,
+ pub solid: Rect,
+}
+
+impl MiscTextures {
+ pub fn init(layout: &AtlasLayout) -> Self {
+ MiscTextures {
+ player: Sprite::new(*layout.get("player+a").unwrap(), Vec2::Y * 0.3, 0.5 + 0.3),
+ solid: *layout.get("solid+a").unwrap(),
+ }
+ }
+}
diff --git a/light-client/src/render/mod.rs b/light-client/src/render/mod.rs
index fbf3d7a5..a410da6f 100644
--- a/light-client/src/render/mod.rs
+++ b/light-client/src/render/mod.rs
@@ -15,6 +15,7 @@
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
+pub mod misc;
pub mod sprite;
use hurrycurry_protocol::glam::Vec2;
@@ -24,11 +25,11 @@ use sdl2::{
render::{BlendMode, Canvas, Texture, TextureAccess, TextureCreator},
video::{Window, WindowContext},
};
-use sprite::{Sprite, SpriteDraw};
+use sprite::SpriteDraw;
use std::collections::HashMap;
pub struct SpriteRenderer<'a> {
- metadata: HashMap<String, Rect>,
+ metadata: AtlasLayout,
texture: Texture<'a>,
@@ -38,6 +39,8 @@ pub struct SpriteRenderer<'a> {
sprites: Vec<SpriteDraw>,
}
+pub type AtlasLayout = HashMap<String, Rect>;
+
impl<'a> SpriteRenderer<'a> {
pub fn init(texture_creator: &'a TextureCreator<WindowContext>) -> Self {
let palette = include_str!("../../assets/palette.csv")
@@ -108,7 +111,7 @@ impl<'a> SpriteRenderer<'a> {
}
#[inline]
- pub fn metadata(&self) -> &HashMap<String, Rect> {
+ pub fn atlas_layout(&self) -> &HashMap<String, Rect> {
&self.metadata
}
@@ -122,6 +125,7 @@ impl<'a> SpriteRenderer<'a> {
pub fn draw_world(&mut self, sprite: SpriteDraw) {
self.sprites.push(SpriteDraw {
+ tint: sprite.tint,
z_order: sprite.z_order,
src: sprite.src,
dst: FRect::new(
@@ -135,24 +139,10 @@ impl<'a> SpriteRenderer<'a> {
pub fn submit(&mut self, canvas: &mut Canvas<Window>) {
self.sprites.sort();
- for SpriteDraw { src, dst, .. } in self.sprites.drain(..) {
+ for SpriteDraw { src, dst, tint, .. } in self.sprites.drain(..) {
+ self.texture.set_color_mod(tint[0], tint[1], tint[2]);
+ self.texture.set_alpha_mod(tint[3]);
canvas.copy_f(&self.texture, src, dst).unwrap();
}
}
}
-
-pub struct MiscTextures {
- pub player: Sprite,
-}
-
-impl MiscTextures {
- pub fn init(renderer: &SpriteRenderer) -> Self {
- MiscTextures {
- player: Sprite::new(
- *renderer.metadata().get("player+a").unwrap(),
- Vec2::Y * 0.3,
- 0.,
- ),
- }
- }
-}
diff --git a/light-client/src/render/sprite.rs b/light-client/src/render/sprite.rs
index c19f8392..711f45bf 100644
--- a/light-client/src/render/sprite.rs
+++ b/light-client/src/render/sprite.rs
@@ -22,7 +22,7 @@ impl Sprite {
}
}
pub fn new_tile(src: Rect) -> Self {
- Self::new(src, Vec2::new(0.5, 1.0), 0.)
+ Self::new(src, Vec2::new(0.5, 1.0), 0.5)
}
pub fn at(&self, pos: Vec2) -> SpriteDraw {
SpriteDraw {
@@ -34,17 +34,30 @@ impl Sprite {
self.relative_dst.w,
self.relative_dst.h,
),
+ tint: [0xff; 4],
}
}
}
#[derive(Debug, Clone, Copy)]
pub struct SpriteDraw {
+ pub tint: [u8; 4],
pub z_order: i32,
pub src: Rect,
pub dst: FRect,
}
+impl SpriteDraw {
+ pub fn overlay(src: Rect, pos: Vec2, size: Vec2, tint: Option<[u8; 4]>) -> Self {
+ Self {
+ dst: FRect::new(pos.x, pos.y, size.x, size.y),
+ src,
+ tint: tint.unwrap_or([0xff; 4]),
+ z_order: i32::MAX,
+ }
+ }
+}
+
impl Ord for SpriteDraw {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
self.z_order.cmp(&other.z_order)