From cae43e4578e685b55d24e1c4946b8da7edb7437e Mon Sep 17 00:00:00 2001 From: jusax23 Date: Wed, 19 Apr 2023 09:05:48 +0200 Subject: [PATCH] breakable blocks --- src/game.rs | 9 +- src/game/block.rs | 12 -- src/game/chunk.rs | 52 ++++++-- src/game/world.rs | 190 +++++++++++++++++++++++------ src/jucraft.rs | 20 ++- src/jucraft/default_solid_block.rs | 11 +- src/main.rs | 2 +- src/player.rs | 159 +++++++++++++++++++----- src/shader.rs | 2 +- src/stage.rs | 55 ++------- src/systems.rs | 25 ++++ src/tools.rs | 100 +++++++++++++-- src/world_generator.rs | 7 -- 13 files changed, 485 insertions(+), 159 deletions(-) create mode 100644 src/systems.rs delete mode 100644 src/world_generator.rs diff --git a/src/game.rs b/src/game.rs index 2a411ba..7fddf5f 100644 --- a/src/game.rs +++ b/src/game.rs @@ -1,8 +1,10 @@ +use std::vec; + use crate::{ - tools::{WPos, Sides}, graphics::DrawType, + tools::{WPos, Sides}, graphics::DrawType, systems::{WorldGenerator, BlockType}, }; -use self::{block::BlockType, world::World}; +use self::{world::World}; pub mod block; pub mod chunk; @@ -35,7 +37,7 @@ impl Game { pub fn find_type(&self, id: String) -> Option<(usize, &Box)> { let index = self.type_names.iter().position(|r| r.eq(&id)); if let Some(i) = index { - return Some((i,&self.types[i])); + return Some((i, &self.types[i])); } None } @@ -59,6 +61,7 @@ impl Game { self.types.push(block_type); index } + pub fn add_world(&mut self) -> usize { self.worlds.push(World::new()); self.worlds.len() - 1 diff --git a/src/game/block.rs b/src/game/block.rs index aca5b9d..12f52d3 100644 --- a/src/game/block.rs +++ b/src/game/block.rs @@ -39,15 +39,3 @@ impl Block { self.string_state.insert(name.to_string(), (value, save)); } } - - -pub trait BlockType { - fn get_id(&self) -> String; - fn is_sided(&self) -> bool; - - fn set_index(&mut self, _id: usize) {} - fn create(&self, _world: &mut World, _block: WPos, _types: &Vec>, _instant: bool) {} - fn update(&self, _world: &mut World, _block: WPos, _types: &Vec>, _instant: bool) {} - fn render(&self, _world: &mut World, _block: WPos, _types: &Vec>) -> Draw { Draw::None() } - fn texture(&self) -> &DrawType; -} \ No newline at end of file diff --git a/src/game/chunk.rs b/src/game/chunk.rs index d249189..c33ceac 100644 --- a/src/game/chunk.rs +++ b/src/game/chunk.rs @@ -1,8 +1,9 @@ use std::collections::HashMap; use gl_matrix::{common::*, vec2::clone}; +use png::chunk; -use crate::{tools::Sides, world_generator::WorldGenerator}; +use crate::{systems::WorldGenerator, tools::Sides}; use super::{block::Block, WPos}; @@ -26,24 +27,22 @@ impl Chunk { instances: HashMap::new(), } } - pub fn new_gen(generator: Box,_chunk_x: i32, _chunk_z: i32) -> Self { - let mut c = Self { - blocks: HashMap::new(), - instances: HashMap::new(), - }; - generator.generateChunk(&mut c); - c - } pub fn set_block(&mut self, pos: &WPos, block_type: usize) { let inner_x = pos[0].rem_euclid(16) as u8; let inner_z = pos[2].rem_euclid(16) as u8; self.blocks.insert( (inner_x, pos[1] as u8, inner_z), - Block::new(block_type/*, *pos*/), + Block::new(block_type /*, *pos*/), ); } + pub fn delete_block(&mut self, pos: &WPos) { + let inner_x = pos[0].rem_euclid(16) as u8; + let inner_z = pos[2].rem_euclid(16) as u8; + self.blocks.remove(&(inner_x, pos[1] as u8, inner_z)); + } + pub fn remove_pos(&mut self, block_type: usize, pos: &WPos) { if let Some(data) = self.instances.get_mut(&block_type) { match data { @@ -70,6 +69,38 @@ impl Chunk { } } } + + pub fn remove_all_pos(&mut self, pos: &WPos) { + let mut rem_inst: Vec = vec![]; + for (block_type, data) in &mut self.instances { + match data { + Instances::Single(d) => { + d.retain(|f| pos[0] != f[0] || pos[1] != f[1] || pos[2] != f[2]); + if d.len() == 0 { + rem_inst.push(*block_type); + } + } + Instances::Sided(d) => { + for i in 0..6 { + d[i].retain(|f| pos[0] != f[0] || pos[1] != f[1] || pos[2] != f[2]); + } + if d[0].len() == 0 + && d[1].len() == 0 + && d[2].len() == 0 + && d[3].len() == 0 + && d[4].len() == 0 + && d[5].len() == 0 + { + rem_inst.push(*block_type); + } + } + } + } + for b_t in rem_inst.iter() { + self.instances.remove(&b_t); + } + } + pub fn add_tex_pos(&mut self, block_type: usize, pos: &WPos) { if let Some(inst) = self.instances.get_mut(&block_type) { if let Instances::Single(vec) = inst { @@ -86,7 +117,6 @@ impl Chunk { } pub fn add_tex_pos_sided(&mut self, block_type: usize, pos: &WPos, sides: Sides) { if let Some(inst) = self.instances.get_mut(&block_type) { - if let Instances::Sided(vec) = inst { for i in 0..6 { if sides[i] { diff --git a/src/game/world.rs b/src/game/world.rs index f69fef7..e612acc 100644 --- a/src/game/world.rs +++ b/src/game/world.rs @@ -1,6 +1,8 @@ use std::collections::HashMap; -use crate::{graphics::Draw, world_generator::WorldGenerator}; +use png::chunk; + +use crate::{graphics::Draw, systems::WorldGenerator}; use super::{block::Block, chunk::Chunk, BlockType, Sides, WPos}; @@ -14,11 +16,11 @@ pub enum GetBlock { pub struct World { pub chunks: HashMap<(i32, i32), Chunk>, - generator: Box, - updates: Vec, i_updates: Vec, t_updates: Vec, + + gen: Box, } impl World { @@ -28,10 +30,14 @@ impl World { updates: vec![], i_updates: vec![], t_updates: vec![], - generator: Box::new(EmptyGenerator {}), + gen: Box::new(|world: &mut World, chunk_x: i32, chunk_z: i32| {}), } } + pub fn set_gen(&mut self, gen: Box) { + self.gen = gen; + } + pub fn get_block(&mut self, pos: &WPos) -> GetBlock<&mut Block> { if pos[1] < 0 || pos[1] > 256 { return GetBlock::None; @@ -74,19 +80,73 @@ impl World { } } - fn loadChunk(&mut self, chunk_x: i32, chunk_z: i32) { + pub fn load_chunk_around_point( + &mut self, + //gen: &Box, + chunk_x: i32, + chunk_z: i32, + width: i32, + ) { + if !self.chunks.contains_key(&(chunk_x, chunk_z)) { + self.load_chunk(chunk_x, chunk_z); + return; + } + for w in 1..=width { + for side_w in 0..=w { + if side_w * side_w + w * w > width * width { + continue; + } + if self.load_chunk(chunk_x + w, chunk_z + side_w) { + return; + } + if self.load_chunk(chunk_x + w, chunk_z - side_w) { + return; + } + if self.load_chunk(chunk_x - w, chunk_z + side_w) { + return; + } + if self.load_chunk(chunk_x - w, chunk_z - side_w) { + return; + } + if self.load_chunk(chunk_x + side_w, chunk_z + w) { + return; + } + if self.load_chunk(chunk_x - side_w, chunk_z + w) { + return; + } + if self.load_chunk(chunk_x + side_w, chunk_z - w) { + return; + } + if self.load_chunk(chunk_x - side_w, chunk_z - w) { + return; + } + } + } + } + + pub fn load_chunk(&mut self, chunk_x: i32, chunk_z: i32) -> bool { if !self.chunks.contains_key(&(chunk_x, chunk_z)) { self.chunks .insert((chunk_x, chunk_z), Chunk::new(chunk_x, chunk_z)); - for x in 0..16 { + self.gen.as_mut()(self, chunk_x, chunk_z); + for x in chunk_x * 16 - 1..=chunk_x * 16 + 16 { + for z in chunk_z * 16 - 1..=chunk_z * 16 + 16 { + for y in 0..256 { + self.update_texture(&[x, y, z]); + } + } + } + return true; + /*for x in 0..16 { for y in 0..256 { self.update_texture(&[chunk_x * 16 + x, y, chunk_z * 16 - 1]); self.update_texture(&[chunk_x * 16 + x, y, chunk_z * 16 + 16]); self.update_texture(&[chunk_x * 16 - 1, y, chunk_z * 16 + x]); self.update_texture(&[chunk_x * 16 + 16, y, chunk_z * 16 + x]); } - } + }*/ } + false } pub fn set_block( @@ -95,6 +155,17 @@ impl World { block_type: usize, update: Sides, update_self: bool, + ) { + self.set_block_tex(pos, block_type, update, update_self, true); + } + + pub fn set_block_tex( + &mut self, + pos: &WPos, + block_type: usize, + update: Sides, + update_self: bool, + update_tex_surr: bool, ) { if pos[1] < 0 { return; @@ -102,34 +173,20 @@ impl World { let chunk_x = pos[0].div_euclid(16); let chunk_z = pos[2].div_euclid(16); - //let mut new_c = false; - if !self.chunks.contains_key(&(chunk_x, chunk_z)) { - self.chunks - .insert((chunk_x, chunk_z), Chunk::new(chunk_x, chunk_z)); - //new_c = true; - } - - /*if new_c { - for x in 0..16 { - for y in 0..256 { - self.update(&[chunk_x * 16 + x, y, chunk_z * 16 - 1], false); - self.update(&[chunk_x * 16 + x, y, chunk_z * 16 + 16], false); - self.update(&[chunk_x * 16 - 1, y, chunk_z * 16 + x], false); - self.update(&[chunk_x * 16 + 16, y, chunk_z * 16 + x], false); - } - } - }*/ + //self.load_chunk(chunk_x, chunk_z); if let Some(chunk) = self.chunks.get_mut(&(chunk_x, chunk_z)) { chunk.set_block(pos, block_type); - self.update_texture(&[pos[0], pos[1], pos[2]]); - self.update_texture(&[pos[0] + 1, pos[1], pos[2]]); - self.update_texture(&[pos[0] - 1, pos[1], pos[2]]); - self.update_texture(&[pos[0], pos[1] + 1, pos[2]]); - self.update_texture(&[pos[0], pos[1] - 1, pos[2]]); - self.update_texture(&[pos[0], pos[1], pos[2] + 1]); - self.update_texture(&[pos[0], pos[1], pos[2] - 1]); + if update_tex_surr { + self.update_texture(&[pos[0], pos[1], pos[2]]); + self.update_texture(&[pos[0] + 1, pos[1], pos[2]]); + self.update_texture(&[pos[0] - 1, pos[1], pos[2]]); + self.update_texture(&[pos[0], pos[1] + 1, pos[2]]); + self.update_texture(&[pos[0], pos[1] - 1, pos[2]]); + self.update_texture(&[pos[0], pos[1], pos[2] + 1]); + self.update_texture(&[pos[0], pos[1], pos[2] - 1]); + } if update_self { self.update(&[pos[0], pos[1], pos[2]], true); @@ -155,6 +212,62 @@ impl World { } } + pub fn delete_block( + &mut self, + pos: &WPos, + update: Sides, + ) { + self.delete_block_tex(pos, update, true); + } + + pub fn delete_block_tex( + &mut self, + pos: &WPos, + update: Sides, + update_tex_surr: bool, + ) { + if pos[1] < 0 { + return; + } + let chunk_x = pos[0].div_euclid(16); + let chunk_z = pos[2].div_euclid(16); + + //self.load_chunk(chunk_x, chunk_z); + + if let Some(chunk) = self.chunks.get_mut(&(chunk_x, chunk_z)) { + chunk.delete_block(pos); + + if update_tex_surr { + self.update_texture(&[pos[0], pos[1], pos[2]]); + self.update_texture(&[pos[0] + 1, pos[1], pos[2]]); + self.update_texture(&[pos[0] - 1, pos[1], pos[2]]); + self.update_texture(&[pos[0], pos[1] + 1, pos[2]]); + self.update_texture(&[pos[0], pos[1] - 1, pos[2]]); + self.update_texture(&[pos[0], pos[1], pos[2] + 1]); + self.update_texture(&[pos[0], pos[1], pos[2] - 1]); + } + + if update.right { + self.update(&[pos[0] - 1, pos[1], pos[2]], false); + } + if update.left { + self.update(&[pos[0] + 1, pos[1], pos[2]], false); + } + if update.top { + self.update(&[pos[0], pos[1] + 1, pos[2]], false); + } + if update.bottom { + self.update(&[pos[0], pos[1] - 1, pos[2]], false); + } + if update.front { + self.update(&[pos[0], pos[1], pos[2] + 1], false); + } + if update.back { + self.update(&[pos[0], pos[1], pos[2] - 1], false); + } + } + } + pub fn update_texture(&mut self, pos: &WPos) { self.t_updates.push(pos.clone()); } @@ -210,7 +323,7 @@ impl World { let block_type_num = block.block_type; if let Some(block_type) = types.get(block_type_num) { - let draw = block_type.render(self, pos.clone(), types); + let draw = block_type.render(self, pos.clone()); if let Some(chunk) = self.chunks.get_mut(&(chunk_x, chunk_z)) { match draw { @@ -233,13 +346,16 @@ impl World { } } } + }else{ + if let Some(chunk) = self.chunks.get_mut(&(chunk_x, chunk_z)) { + chunk.remove_all_pos(&pos) + } + } + }else{ + if let Some(chunk) = self.chunks.get_mut(&(chunk_x, chunk_z)) { + chunk.remove_all_pos(&pos) } } } } } - -struct EmptyGenerator {} -impl WorldGenerator for EmptyGenerator { - fn generateChunk(&self, chunk: &mut Chunk) {} -} diff --git a/src/jucraft.rs b/src/jucraft.rs index bd645ce..f06db3b 100644 --- a/src/jucraft.rs +++ b/src/jucraft.rs @@ -1,4 +1,8 @@ -use crate::{game::*, graphics::*, tools::Sides}; +use crate::{ + game::{world::World, *}, + graphics::*, + tools::Sides, +}; use default_solid_block::DefaultSolidBlock; use miniquad::*; @@ -6,7 +10,7 @@ use miniquad::*; mod default_solid_block; pub mod default_solid_shader; -pub fn register(ctx: &mut Context, game: &mut Game, graphics: &mut Graphics) { +pub fn register(ctx: &mut Context, game: &mut Game, graphics: &mut Graphics, default_world: usize) { graphics.load_texture( ctx, include_bytes!(concat!("../assets/break/empty_overlay.png")), @@ -105,4 +109,16 @@ pub fn register(ctx: &mut Context, game: &mut Game, graphics: &mut Graphics) { back: grass_side, }), })); + + if let Some(world) = game.get_world(default_world) { + world.set_gen(Box::new(|world: &mut World, chunk_x: i32, chunk_z: i32| { + for x in chunk_x * 16..chunk_x * 16 + 16 { + for z in chunk_z * 16..chunk_z * 16 + 16 { + for y in 0..64 { + world.set_block_tex(&[x, y, z], 1, Sides::all(false), false, false); + } + } + } + })); + } } diff --git a/src/jucraft/default_solid_block.rs b/src/jucraft/default_solid_block.rs index f56123b..c1ecca9 100644 --- a/src/jucraft/default_solid_block.rs +++ b/src/jucraft/default_solid_block.rs @@ -1,8 +1,10 @@ +use gl_matrix::common::*; + use crate::{ game::{block::*, world::*}, graphics::*, - tools::*, + tools::*, systems::BlockType, }; pub struct DefaultSolidBlock { @@ -30,7 +32,6 @@ impl BlockType for DefaultSolidBlock { &self, world: &mut World, block: WPos, - _types: &Vec>, ) -> Draw { let mut sides = Sides::all(true); sides.top = match world.get_block(&[block[0], block[1] + 1, block[2]]) { @@ -76,4 +77,10 @@ impl BlockType for DefaultSolidBlock { fn is_sided(&self) -> bool { true } + fn collision(&self, _world: &World, _block: WPos) -> Vec<(Vec3, Vec3)> { + vec![([0.,0.,0.], [1.,1.,1.])] + } + fn interaction(&self, _world: &World, block: &Block, _block: WPos) -> Vec<(Vec3, Vec3)> { + vec![([0.,0.,0.], [1.,1.,1.])] + } } diff --git a/src/main.rs b/src/main.rs index 4b5b34e..8b22a97 100644 --- a/src/main.rs +++ b/src/main.rs @@ -8,7 +8,7 @@ mod graphics; mod tools; mod jucraft; mod player; -mod world_generator; +mod systems; fn main() { start(conf::Conf{ diff --git a/src/player.rs b/src/player.rs index badd171..04c6066 100644 --- a/src/player.rs +++ b/src/player.rs @@ -1,7 +1,11 @@ use gl_matrix::{common::*, *}; +use miniquad::*; use crate::{ - game::{world::GetBlock, Game}, + game::{ + world::{GetBlock, World}, + Game, + }, tools::*, }; @@ -26,8 +30,8 @@ impl Player { rot, pos, motion: [0., 0., 0.], - eyes: 1.7, - size: [0.8, 1.99, 0.8], + eyes: 1.61, + size: [0.8, 1.8, 0.8], flying: true, max_speed: 10., world: 0, @@ -39,12 +43,12 @@ impl Player { pub fn update(&mut self, game: &mut Game, s_move: &Sides, delta: f32) { if self.flying { if s_move.top { - self.motion[1] += delta * 100.0; + self.motion[1] += delta * 200.0; } if s_move.bottom { - self.motion[1] -= delta * 100.0; + self.motion[1] -= delta * 200.0; } - let decal = 70. * delta; + let decal = 150. * delta; if self.motion[1].abs() > decal { if self.motion[1] > 0. { self.motion[1] -= decal; @@ -54,11 +58,6 @@ impl Player { } else { self.motion[1] = 0.; } - } else { - if self.on_gound && s_move.top { - self.motion[1] = 10.; - } - self.motion[1] -= delta * 30.; if self.motion[1].abs() > 30. { if self.motion[1] > 0. { self.motion[1] = 30.; @@ -66,6 +65,18 @@ impl Player { self.motion[1] = -30.; } } + } else { + if self.on_gound && s_move.top { + self.motion[1] = 10.; + } + self.motion[1] -= delta * 30.; + if self.motion[1].abs() > 50. { + if self.motion[1] > 0. { + self.motion[1] = 50.; + } else { + self.motion[1] = -50.; + } + } } let decalerate: f32 = if self.on_gound || self.flying { @@ -147,11 +158,19 @@ impl Player { if self.is_clipped(game).is_none() { self.pos[cord] += do_dist; if let Some((b_pos, b_size)) = self.is_clipped(game) { - let self_offset = if cord == 1 { 0. } else { self.size[cord] / 2. }; if do_dist > 0. { - self.pos[cord] = b_pos[cord] - self_offset - 0.001; + self.pos[cord] = b_pos[cord] + - if cord == 1 { + self.size[cord] + } else { + self.size[cord] / 2. + } + - 0.001; } else if do_dist < 0. { - self.pos[cord] = b_pos[cord] + b_size[cord] + self_offset + 0.001; + self.pos[cord] = b_pos[cord] + + b_size[cord] + + if cord == 1 { 0. } else { self.size[cord] / 2. } + + 0.001; if cord == 1 { self.on_gound = true; } @@ -159,10 +178,15 @@ impl Player { self.motion[cord] = 0.; } } else { - self.pos[cord] += do_dist; + if cord != 1 || do_dist > 0. { + self.pos[cord] += do_dist; + } } } } + if self.pos[1] < -50. { + self.pos[1] = 256. + 128.; + } } pub fn is_clipped(&self, game: &mut Game) -> Option<(Vec3, Vec3)> { @@ -174,22 +198,36 @@ impl Player { let vy = (self.size[1]).ceil() as i32; let vz = (self.size[2] / 2.).ceil() as i32; for x in mx - vx..=mx + vy { - for z in mz - 1..=mz + vz { - for y in my - vy..=my + vy { + for z in mz - vy..=mz + vz { + for y in my - 1..=my + vy + 1 { if let GetBlock::Some(_block) = world.get_block_im(&[x, y, z]) { - // TODO: block size - //println!("inner clip"); - if check_overlap( - [self.pos[0], self.pos[1] + (self.size[1] / 2.0), self.pos[2]], - [ - x as f32 + 1.0 / 2.0, - y as f32 + 1.0 / 2.0, - z as f32 + 1.0 / 2.0, - ], - self.size, - [1., 1., 1.], - ) { - return Some(([x as f32, y as f32, z as f32], [1., 1., 1.])); + if let Some(b_t) = game.get_type(_block.block_type) { + let boxes = b_t.collision(&world, [x, y, z]); + for (pos, size) in boxes { + if check_overlap( + [ + self.pos[0], + self.pos[1] + (self.size[1] / 2.0), + self.pos[2], + ], + [ + x as f32 + pos[0] + size[0] / 2.0, + y as f32 + pos[1] + size[1] / 2.0, + z as f32 + pos[2] + size[2] / 2.0, + ], + self.size, + size, + ) { + return Some(( + [ + x as f32 + pos[0], + y as f32 + pos[1], + z as f32 + pos[2], + ], + size, + )); + } + } } } } @@ -199,6 +237,67 @@ impl Player { None } + pub fn right_click(&self, game: &mut Game) {} + pub fn left_click(&self, game: &mut Game) { + + let start = date::now(); + if let Some((_, pos)) = self.looking_at(&game, 6., 0.1) { + if let Some(world) = game.get_world(self.world) { + world.delete_block(&pos, Sides::all(true)); + } + } + + println!("pos trace time: {}µs", (date::now() - start) * 1000000.); + } + + pub fn looking_at(&self, game: &Game, dist: f32, offset: f32) -> Option<(Side, WPos)> { + if let Some(world) = game.get_world_im(self.world) { + let mut start = self.pos.clone(); + start[1] += self.eyes; + let dirc = [ + -self.rot[1].to_radians().sin() * self.rot[0].to_radians().cos(), + self.rot[0].to_radians().sin(), + self.rot[1].to_radians().cos() * self.rot[0].to_radians().cos(), + ]; + + let mut curr_dist = offset; + let mut c_x:i32 = i32::max_value(); + let mut c_y:i32 = i32::max_value(); + let mut c_z:i32 = i32::max_value(); + while curr_dist < dist { + let x = (start[0] + dirc[0] * curr_dist).floor() as i32; + let y = (start[1] + dirc[1] * curr_dist).floor() as i32; + let z = (start[2] + dirc[2] * curr_dist).floor() as i32; + if x != c_x || y != c_y || z != c_z { + c_x = x; + c_y = y; + c_z = z; + if let GetBlock::Some(block) = world.get_block_im(&[x, y, z]) { + if let Some(b_t) = game.get_type(block.block_type) { + let boxes: Vec<([f32; 3], [f32; 3])> = + b_t.interaction(&world, block, [x, y, z]); + for (pos, size) in boxes { + if let Some((b_dist, side)) = block_collision( + start, + [x as f32 + pos[0], y as f32 + pos[1], z as f32 + pos[2]], + dirc, + size, + ) { + if b_dist < dist { + return Some((side, [x, y, z])); + } + } + } + } + } + } + curr_dist += 0.05; + } + } + + None + } + pub fn rotate(&mut self, x: f32, y: f32) { self.rot[0] -= y / 10.0; self.rot[1] += x / 10.0; diff --git a/src/shader.rs b/src/shader.rs index d644c5d..6374846 100644 --- a/src/shader.rs +++ b/src/shader.rs @@ -71,7 +71,7 @@ impl RenderHelper { post_processing_pipeline, post_processing_bind, offscreen_pass, - post_enabled: true, + post_enabled: false, } } diff --git a/src/stage.rs b/src/stage.rs index 09cd402..ae88327 100644 --- a/src/stage.rs +++ b/src/stage.rs @@ -2,7 +2,7 @@ use gl_matrix::{mat4, common::*}; use miniquad::*; -use crate::{game::{Game, chunk::*}, graphics::{Graphics, DrawType}, jucraft::{*, self}, shader::RenderHelper, tools::*, player::Player}; +use crate::{game::{Game, chunk::*, world::World}, graphics::{Graphics, DrawType}, jucraft::{*, self}, shader::RenderHelper, tools::*, player::Player}; const MAX_INSTANT_TICKS: i32 = 50; @@ -38,25 +38,15 @@ impl Stage { let mut graphics = Graphics::new(); let world = game.add_world(); - jucraft::register(ctx,&mut game, &mut graphics); - - let (grass,_) = game.find_type("grassblock".to_string()).unwrap(); - let (stone,_) = game.find_type("stone".to_string()).unwrap(); - let (cobblestone,_) = game.find_type("cobblestone".to_string()).unwrap(); - - if let Some(world) = game.get_world(world){ - world.set_block(&[162,65,161], cobblestone, Sides::all(true), true); - world.set_block(&[162,64,161], grass, Sides::all(true), true); - world.set_block(&[162,64,162], grass, Sides::all(true), true); - - world.set_block(&[163,64,161], stone, Sides::all(true), true); - world.set_block(&[161,64,161], stone, Sides::all(true), true); - } - let mut player = Player::new( [0.,0.], - [16.*10.,63.,16.*10.], + [16.*10.,64.,16.*10.], ); + + + + jucraft::register(ctx,&mut game, &mut graphics, world); + player.world = world; let post = RenderHelper::new(ctx); @@ -201,7 +191,9 @@ impl EventHandler for Stage { self.game.do_tick(false); //eprintln!("fps: {}|{}", 1. / self.delta, self.t_fp); - + if let Some(world) = self.game.get_world(0) { + world.load_chunk_around_point( (self.player.pos[0] as i32).div_euclid(16), (self.player.pos[2] as i32).div_euclid(16), 10); + } if self.last_tick < t - 5. { self.last_tick = t - 1. / 20.; } @@ -210,27 +202,6 @@ impl EventHandler for Stage { self.player.update(&mut self.game, &self.s_move, self.delta as f32); - - let (index,_) = self.game.find_type("stone".to_string()).unwrap(); - - if self.z < 16*20 { - if let Some(world) = self.game.get_world(0) { - for _ in 0..10000 { - if self.z >= 16*20 {break;} - world.set_block(&[self.x, self.y, self.z], index+((self.x+ self.y + self.z) as usize)%4, Sides::all(true), true); - self.x+=1; - if self.x >= 16*20 { - self.x = 0; - self.y += 1; - if self.y > 63{ - self.y = 0; - self.z += 1; - } - } - } - - } - } } fn draw(&mut self, ctx: &mut Context) { @@ -376,15 +347,15 @@ impl EventHandler for Stage { self.mouse_grab = false; } - fn mouse_button_down_event(&mut self,ctx: &mut Context,button: MouseButton,_x: f32,_y: f32) { + fn mouse_button_down_event(&mut self,ctx: &mut Context, button: MouseButton,_x: f32,_y: f32) { if button == MouseButton::Left { if !self.mouse_grab { ctx.set_cursor_grab(true); ctx.show_mouse(false); self.mouse_grab = true; + } else { + self.player.left_click(&mut self.game); } - - } } diff --git a/src/systems.rs b/src/systems.rs new file mode 100644 index 0000000..4d9de5b --- /dev/null +++ b/src/systems.rs @@ -0,0 +1,25 @@ +use gl_matrix::common::*; + +use crate::{game::{world::World, block::Block}, tools::WPos, graphics::{Draw, DrawType}}; + + + +/*pub trait WorldGenerator { + fn get_id(&self) -> String; + fn generate_chunk(&self, world: &mut World, chunk_x: i32, chunk_z:i32); +}*/ + +pub type WorldGenerator = fn(world: &mut World, chunk_x: i32, chunk_z:i32); + +pub trait BlockType { + fn get_id(&self) -> String; + fn is_sided(&self) -> bool; + + fn set_index(&mut self, _id: usize) {} + fn create(&self, _world: &mut World, _block: WPos, _types: &Vec>, _instant: bool) {} + fn update(&self, _world: &mut World, _block: WPos, _types: &Vec>, _instant: bool) {} + fn render(&self, _world: &mut World, _block: WPos) -> Draw { Draw::None() } + fn collision(&self, _world: &World, _block: WPos) -> Vec<(Vec3, Vec3)> { vec![] } + fn interaction(&self, _world: &World, block: &Block, _block: WPos) -> Vec<(Vec3, Vec3)> { vec![] } + fn texture(&self) -> &DrawType; +} \ No newline at end of file diff --git a/src/tools.rs b/src/tools.rs index 7ab09c1..efb0591 100644 --- a/src/tools.rs +++ b/src/tools.rs @@ -4,6 +4,15 @@ use gl_matrix::common::*; pub type WPos = [i32; 3]; +pub enum Side { + Top, + Bottom, + Left, + Right, + Front, + Back, +} + #[derive(Debug)] pub struct Sides { pub top: T, @@ -40,13 +49,15 @@ impl Index for Sides { fn index(&self, i: usize) -> &Self::Output { match i { - 0 => {&self.top}, - 1 => {&self.bottom}, - 2 => {&self.left}, - 3 => {&self.right}, - 4 => {&self.front}, - 5 => {&self.back}, - _ => {panic!("SidesOutOfBoundsException");} + 0 => &self.top, + 1 => &self.bottom, + 2 => &self.left, + 3 => &self.right, + 4 => &self.front, + 5 => &self.back, + _ => { + panic!("SidesOutOfBoundsException"); + } } } } @@ -59,13 +70,80 @@ pub struct Vertex { pub fn check_overlap(pos1: Vec3, pos2: Vec3, size1: Vec3, size2: Vec3) -> bool { (pos1[0] - pos2[0]).abs() < (size1[0] + size2[0]) / 2. - && (pos1[1] - pos2[1]).abs() < (size1[1] + size2[1]) / 2. - && (pos1[2] - pos2[2]).abs() < (size1[2] + size2[2]) / 2. + && (pos1[1] - pos2[1]).abs() < (size1[1] + size2[1]) / 2. + && (pos1[2] - pos2[2]).abs() < (size1[2] + size2[2]) / 2. +} + +pub fn block_collision( + pos1: Vec3, + pos2: Vec3, + direction: Vec3, + size2: Vec3, +) -> Option<(f32, Side)> { + let mut d_x = (pos2[0] - pos1[0]) / direction[0]; + let mut d_y = (pos2[1] - pos1[1]) / direction[1]; + let mut d_z = (pos2[2] - pos1[2]) / direction[2]; + let mut d_b_x = (pos2[0] + size2[0] - pos1[0]) / direction[0]; + let mut d_b_y = (pos2[1] + size2[1] - pos1[1]) / direction[1]; + let mut d_b_z = (pos2[2] + size2[2] - pos1[2]) / direction[2]; + + let mut out: Option<(f32, Side)> = None; + let mut dist = INFINITY; + + if d_x > 0. { + let y = pos1[1] + d_x * direction[1]; + let z = pos1[2] + d_x * direction[2]; + if y > pos2[1] && y < pos2[1] + size2[1] && z > pos2[2] && z < pos2[2] + size2[2] { + out = Some((d_x, Side::Right)); + dist = d_x; + } + } + if d_y > 0. && dist > d_y { + let x = pos1[0] + d_y * direction[0]; + let z = pos1[2] + d_y * direction[2]; + if x > pos2[0] && x < pos2[0] + size2[0] && z > pos2[2] && z < pos2[2] + size2[2] { + out = Some((d_y, Side::Bottom)); + dist = d_y; + } + } + if d_z > 0. && dist > d_z { + let x = pos1[0] + d_z * direction[0]; + let y = pos1[1] + d_z * direction[1]; + if x > pos2[0] && x < pos2[0] + size2[0] && y > pos2[1] && y < pos2[1] + size2[1] { + out = Some((d_z, Side::Back)); + dist = d_z; + } + } + + if d_b_x > 0. && dist > d_b_x{ + let y = pos1[1] + d_x * direction[1]; + let z = pos1[2] + d_x * direction[2]; + if y > pos2[1] && y < pos2[1] + size2[1] && z > pos2[2] && z < pos2[2] + size2[2] { + out = Some((d_b_x, Side::Left)); + dist = d_b_x; + } + } + if d_b_y > 0. && dist > d_b_y { + let x = pos1[0] + d_y * direction[0]; + let z = pos1[2] + d_y * direction[2]; + if x > pos2[0] && x < pos2[0] + size2[0] && z > pos2[2] && z < pos2[2] + size2[2] { + out = Some((d_b_y, Side::Top)); + dist = d_b_y; + } + } + if d_b_z > 0. && dist > d_b_z { + let x = pos1[0] + d_z * direction[0]; + let y = pos1[1] + d_z * direction[1]; + if x > pos2[0] && x < pos2[0] + size2[0] && y > pos2[1] && y < pos2[1] + size2[1] { + return Some((d_b_z, Side::Back)); + } + } + out } #[derive(Debug)] pub enum PrimitiveData { String(String), Number(i32), - Boolean(bool) -} \ No newline at end of file + Boolean(bool), +} diff --git a/src/world_generator.rs b/src/world_generator.rs deleted file mode 100644 index a526e01..0000000 --- a/src/world_generator.rs +++ /dev/null @@ -1,7 +0,0 @@ -use crate::game::chunk::Chunk; - - - -pub trait WorldGenerator { - fn generateChunk(&self, chunk: &mut Chunk); -} \ No newline at end of file