Skip to content

Commit

Permalink
feat: Buffered Read and Write, Save player pos to file (#48)
Browse files Browse the repository at this point in the history
* Changed wording

* Added Buffered read/write, player pos also saved
  • Loading branch information
Zac8668 authored Jan 10, 2024
1 parent cd2f7cd commit 6862454
Show file tree
Hide file tree
Showing 6 changed files with 56 additions and 30 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/target
.vscode/
/assets/worlds/**
/assets/world/**
.cargo/config.toml
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ Powered by a similar engine as Noita, made from scratch with Rust.
- Multithreaded sand simulation
- GPU rendering optimizations of the sim
- AABB colliders for the player and mobs
- Player with special gun to shoot and suck atoms, and also a jetpack
- Player with special gun to push and pull atoms, and also a jetpack
- Bigger map, with saving/loading

**What's next:**
Expand All @@ -27,7 +27,7 @@ Powered by a similar engine as Noita, made from scratch with Rust.
In the bigger picture we also aim to achieve intergalactic travel like Starbound, procedurally generated animations inspired by Rainworld, all the cool mechanics you see in Noita, multiplayer and modding, the last two made possible by a future engine migration to [Bones](https://github.com/fishfolk/bones/).

## Controls
Left Mouse button to suck atoms, Right Mouse button to shoot atoms.
Left Mouse button to pull atoms, Right Mouse button to push atoms.
Mouse wheel to zoom in/out.

## Last Update Changelog
Expand All @@ -38,7 +38,7 @@ We added:
- Player
- The player is pretty cool! It has some animations, a jetpack and a pretty nice tool!
- Player tool
- The tool can suck atoms(Left Mouse Button), and also shoot(Right Mouse Button) the atoms you sucked!
- The tool can pull atoms(Left Mouse Button), and also push(Right Mouse Button) the atoms you pulled!
- Engine Changes
- We changed the Chunk Manager approach to store Chunks in a Vec to storing them in a HashMap, this lays the ground for future updates, like Save/Load worlds, and big explorable worlds. It was needed to simplify addind the other additions and unfortunately took some time to do.

Expand Down
2 changes: 1 addition & 1 deletion src/actors.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::prelude::*;

#[derive(Component, Clone, Copy)]
#[derive(Component, Clone)]
pub struct Actor {
pub width: u8,
pub height: u8,
Expand Down
47 changes: 26 additions & 21 deletions src/chunk_manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,9 +113,10 @@ impl ChunkManager {

impl Drop for ChunkManager {
fn drop(&mut self) {
let file = fs::read("assets/worlds/world").unwrap_or_default();
let file = File::open("assets/world/world").unwrap();
let mut buffered = BufReader::new(file);
let mut file_chunks: HashMap<IVec2, Chunk> =
bincode::deserialize(&file).unwrap_or_default();
bincode::deserialize_from(&mut buffered).unwrap();

for (pos, chunk) in &self.chunks {
if let Some(file_chunk) = file_chunks.get_mut(pos) {
Expand All @@ -125,12 +126,9 @@ impl Drop for ChunkManager {
}
}

let data = bincode::serialize(&file_chunks).unwrap();
//Save file
let _ = File::create("assets/worlds/world")
.unwrap()
.write(&data)
.unwrap();
let file = File::create("assets/world/world").unwrap();
let mut buffered = BufWriter::new(file);
bincode::serialize_into(&mut buffered, &file_chunks).unwrap();
}
}

Expand Down Expand Up @@ -177,8 +175,16 @@ pub fn manager_setup(
let mut images_vec = vec![];
chunk_manager.pos = ivec2(-16, -16);

let file = fs::read("assets/worlds/world").unwrap_or_default();
let file_chunks: HashMap<IVec2, Chunk> = bincode::deserialize(&file).unwrap_or_default();
let file_chunks: HashMap<IVec2, Chunk>;
if let Ok(file) = File::open("assets/world/world") {
let mut buffered = BufReader::new(file);
file_chunks = bincode::deserialize_from(&mut buffered).unwrap();
} else {
file_chunks = HashMap::new();
let file = File::create("assets/world/world").unwrap();
let mut buffered = BufWriter::new(file);
bincode::serialize_into(&mut buffered, &file_chunks).unwrap();
}

for (x, y) in (chunk_manager.pos.x..chunk_manager.pos.x + width)
.cartesian_product(chunk_manager.pos.y..chunk_manager.pos.y + height)
Expand Down Expand Up @@ -543,22 +549,24 @@ pub fn update_manager_pos(

if new_diff != IVec2::ZERO {
task_executor.start(async move {
let file = fs::read("assets/worlds/world").unwrap_or_default();
let file = File::open("assets/world/world").unwrap();
let mut buffered = BufReader::new(file);

let chunks: HashMap<IVec2, Chunk> =
bincode::deserialize(&file).unwrap_or_default();
bincode::deserialize_from(&mut buffered).unwrap();
(chunks, new_diff)
});
}
}
AsyncTaskStatus::Finished((mut file, diff)) => {
AsyncTaskStatus::Finished((mut file_chunks, diff)) => {
let chunk_textures = chunk_textures.single();
for _ in 0..diff.x.abs() {
chunk_manager.move_manager(
&mut commands,
&mut images,
&chunk_textures,
&image_entities,
&mut file,
&mut file_chunks,
MoveDir::X(diff.x.signum()),
);
}
Expand All @@ -569,19 +577,16 @@ pub fn update_manager_pos(
&mut images,
&chunk_textures,
&image_entities,
&mut file,
&mut file_chunks,
MoveDir::Y(diff.y.signum()),
);
}

let pool = AsyncComputeTaskPool::get();
saving_task.0 = Some(pool.spawn(async move {
let data = bincode::serialize(&file).unwrap();
//Save file
let _ = File::create("assets/worlds/world")
.unwrap()
.write(&data)
.unwrap();
let file = File::create("assets/world/world").unwrap();
let mut buffered = BufWriter::new(file);
bincode::serialize_into(&mut buffered, &file_chunks).unwrap();
}));
}
AsyncTaskStatus::Pending => {}
Expand Down
2 changes: 1 addition & 1 deletion src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,9 @@ mod prelude {

pub use std::collections::{HashMap, HashSet};
pub use std::env;
pub use std::fs;
pub use std::fs::File;
pub use std::io::Write;
pub use std::io::{BufReader, BufWriter};

pub use crate::materials::Material;
}
Expand Down
27 changes: 24 additions & 3 deletions src/player.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,14 @@ impl Default for Player {
}
}

impl Drop for Actor {
fn drop(&mut self) {
let file = File::create("assets/world/player").unwrap();
let mut buffered = BufWriter::new(file);
bincode::serialize_into(&mut buffered, &self.pos).unwrap();
}
}

#[derive(Default)]
pub enum PlayerState {
#[default]
Expand All @@ -39,10 +47,21 @@ pub fn player_setup(
asset_server: Res<AssetServer>,
mut texture_atlases: ResMut<Assets<TextureAtlas>>,
) {
let pos: IVec2;
if let Ok(file) = File::open("assets/world/player") {
let mut buffered = BufReader::new(file);
pos = bincode::deserialize_from(&mut buffered).unwrap();
} else {
pos = IVec2::default();
let file = File::create("assets/world/player").unwrap();
let mut buffered = BufWriter::new(file);
bincode::serialize_into(&mut buffered, &pos).unwrap();
}

let player_actor = Actor {
height: 17,
width: 10,
pos: ivec2(0, 0),
pos,
vel: vec2(0., 0.),
};

Expand Down Expand Up @@ -221,7 +240,9 @@ pub fn tool_system(
let (window, mut player) = querys;
let (mut textatlas_sprite, player) = player.single_mut();
let (mut chunk_manager, mut dirty_rects, mouse) = resources;
let window = window.single();
let Ok(window) = window.get_single() else {
return;
};
let materials = materials.0.get(materials.1 .0.clone()).unwrap();

if let Some(world_position) = window
Expand All @@ -241,7 +262,7 @@ pub fn tool_system(
tool_transform.translation.x =
tool_transform.translation.x.abs() * (flip_bool as i8 * 2 - 1) as f32;

//Tool shooting and sucking atoms
//Tool pulling and pushing atoms
let mut center_vec_y_flipped = center_vec;
center_vec_y_flipped.y *= -1.;

Expand Down

0 comments on commit 6862454

Please sign in to comment.