init
This commit is contained in:
commit
21295e7eb5
22 changed files with 2008 additions and 0 deletions
4
.gitignore
vendored
Normal file
4
.gitignore
vendored
Normal file
|
@ -0,0 +1,4 @@
|
|||
/target
|
||||
assets/blocks
|
||||
assets/break
|
||||
assets/font
|
245
Cargo.lock
generated
Normal file
245
Cargo.lock
generated
Normal file
|
@ -0,0 +1,245 @@
|
|||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "adler"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "1.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "crc32fast"
|
||||
version = "1.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fdeflate"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d329bdeac514ee06249dabc27877490f17f5d371ec693360768b838e19f3ae10"
|
||||
dependencies = [
|
||||
"simd-adler32",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "flate2"
|
||||
version = "1.0.25"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a8a2db397cb1c8772f31494cb8917e48cd1e64f0fa7efac59fbd741a0a8ce841"
|
||||
dependencies = [
|
||||
"crc32fast",
|
||||
"miniz_oxide 0.6.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.1.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"wasi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gl_matrix"
|
||||
version = "0.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "df64d0245c589931a0b5a385a63e7db2aeff209bdd471df0417e0f230a4c33ae"
|
||||
dependencies = [
|
||||
"rand",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "jucraft"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"gl_matrix",
|
||||
"miniquad",
|
||||
"opensimplex_noise_rs",
|
||||
"png",
|
||||
"quad-rand",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.141"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3304a64d199bb964be99741b7a14d26972741915b3649639149b2479bb46f4b5"
|
||||
|
||||
[[package]]
|
||||
name = "malloc_buf"
|
||||
version = "0.0.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "62bb907fe88d54d8d9ce32a3cceab4218ed2f6b7d35617cafe9adf84e43919cb"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "miniquad"
|
||||
version = "0.3.15"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"ndk-sys",
|
||||
"objc",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "miniz_oxide"
|
||||
version = "0.6.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa"
|
||||
dependencies = [
|
||||
"adler",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "miniz_oxide"
|
||||
version = "0.7.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7"
|
||||
dependencies = [
|
||||
"adler",
|
||||
"simd-adler32",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ndk-sys"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e1bcdd74c20ad5d95aacd60ef9ba40fdf77f767051040541df557b7a9b2a2121"
|
||||
|
||||
[[package]]
|
||||
name = "objc"
|
||||
version = "0.2.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "915b1b472bc21c53464d6c8461c9d3af805ba1ef837e1cac254428f4a77177b1"
|
||||
dependencies = [
|
||||
"malloc_buf",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "opensimplex_noise_rs"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ba77c545f2291bb66897afe90c8583c4fdc427fae9cb552db032e74d7526e8b5"
|
||||
|
||||
[[package]]
|
||||
name = "png"
|
||||
version = "0.17.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "aaeebc51f9e7d2c150d3f3bfeb667f2aa985db5ef1e3d212847bdedb488beeaa"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"crc32fast",
|
||||
"fdeflate",
|
||||
"flate2",
|
||||
"miniz_oxide 0.7.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ppv-lite86"
|
||||
version = "0.2.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
|
||||
|
||||
[[package]]
|
||||
name = "quad-rand"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "658fa1faf7a4cc5f057c9ee5ef560f717ad9d8dc66d975267f709624d6e1ab88"
|
||||
|
||||
[[package]]
|
||||
name = "rand"
|
||||
version = "0.7.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03"
|
||||
dependencies = [
|
||||
"getrandom",
|
||||
"libc",
|
||||
"rand_chacha",
|
||||
"rand_core",
|
||||
"rand_hc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_chacha"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402"
|
||||
dependencies = [
|
||||
"ppv-lite86",
|
||||
"rand_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_core"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19"
|
||||
dependencies = [
|
||||
"getrandom",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_hc"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c"
|
||||
dependencies = [
|
||||
"rand_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "simd-adler32"
|
||||
version = "0.3.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "238abfbb77c1915110ad968465608b68e869e0772622c9656714e73e5a1a522f"
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.9.0+wasi-snapshot-preview1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519"
|
||||
|
||||
[[package]]
|
||||
name = "winapi"
|
||||
version = "0.3.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
|
||||
dependencies = [
|
||||
"winapi-i686-pc-windows-gnu",
|
||||
"winapi-x86_64-pc-windows-gnu",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi-i686-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||
|
||||
[[package]]
|
||||
name = "winapi-x86_64-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
16
Cargo.toml
Normal file
16
Cargo.toml
Normal file
|
@ -0,0 +1,16 @@
|
|||
[package]
|
||||
name = "jucraft"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
gl_matrix = "0.0.2"
|
||||
miniquad = { path = '../../jucraft/miniquad' }
|
||||
opensimplex_noise_rs = "0.3.0"
|
||||
png = "0.17.8"
|
||||
quad-rand = "0.2.1"
|
||||
|
||||
# [replace]
|
||||
# "miniquad:0.3.14" = { path = '../../jucraft/miniquad' }
|
20
assets/shader/default.fsh.glsl
Normal file
20
assets/shader/default.fsh.glsl
Normal file
|
@ -0,0 +1,20 @@
|
|||
#version 100
|
||||
precision mediump float;
|
||||
|
||||
varying vec2 texcoord;
|
||||
varying float v_position;
|
||||
uniform sampler2D u_image0;
|
||||
uniform sampler2D u_image1;
|
||||
uniform vec2 fog;
|
||||
|
||||
void main() {
|
||||
|
||||
float fogAmount = smoothstep(fog.x, fog.y, v_position);
|
||||
|
||||
gl_FragColor =
|
||||
texture2D(u_image0, texcoord)
|
||||
* texture2D(u_image1, texcoord)
|
||||
* vec4(1.0 - fogAmount, 1.0 - fogAmount, 1.0 - fogAmount, 1.0 - fogAmount);
|
||||
if(gl_FragColor.a < 0.0000001)
|
||||
discard;
|
||||
}
|
26
assets/shader/default.vsh.glsl
Normal file
26
assets/shader/default.vsh.glsl
Normal file
|
@ -0,0 +1,26 @@
|
|||
#version 100
|
||||
precision mediump float;
|
||||
|
||||
attribute vec3 pos;
|
||||
attribute vec2 uv;
|
||||
attribute vec3 wpos;
|
||||
|
||||
varying vec2 texcoord;
|
||||
varying float v_position;
|
||||
uniform mat4 view;
|
||||
uniform mat4 proj;
|
||||
|
||||
|
||||
void main() {
|
||||
mat4 drawProj = mat4(
|
||||
vec4(-1.0, 0.0, 0.0, 0.0),
|
||||
vec4(0.0, 1.0, 0.0, 0.0),
|
||||
vec4(0.0, 0.0, -1.0, 0.0),
|
||||
vec4(-wpos.x, wpos.y, -wpos.z, 1.0)
|
||||
);
|
||||
texcoord = uv;
|
||||
|
||||
gl_Position = proj * view * drawProj * vec4(pos, 1.0);
|
||||
|
||||
v_position = length((view * drawProj * vec4(pos, 1.0)).xyz);
|
||||
}
|
29
assets/shader/post.fsh.glsl
Normal file
29
assets/shader/post.fsh.glsl
Normal file
|
@ -0,0 +1,29 @@
|
|||
#version 100
|
||||
precision lowp float;
|
||||
varying vec2 texcoord;
|
||||
uniform sampler2D tex;
|
||||
uniform vec2 wobble;
|
||||
uniform vec3 invert;
|
||||
uniform vec2 blur;
|
||||
|
||||
|
||||
|
||||
// Source: https://github.com/Jam3/glsl-fast-gaussian-blur/blob/master/5.glsl
|
||||
vec4 blur5(sampler2D image, vec2 uv, vec2 resolution, vec2 direction) {
|
||||
vec4 color = vec4(0.0);
|
||||
vec2 off1 = vec2(1.3333333333333333) * direction;
|
||||
color += texture2D(image, uv) * 0.29411764705882354;
|
||||
color += texture2D(image, uv + (off1 / resolution)) * 0.35294117647058826;
|
||||
color += texture2D(image, uv - (off1 / resolution)) * 0.35294117647058826;
|
||||
return color;
|
||||
}
|
||||
void main() {
|
||||
vec2 offset = wobble.x * vec2(
|
||||
sin(wobble.y + texcoord.y) * 0.1,
|
||||
cos(wobble.y + texcoord.x) * 0.1
|
||||
);
|
||||
vec4 col = texture2D(tex, texcoord + offset * (1.0 - length(texcoord - 0.5) ));
|
||||
gl_FragColor = (1.0 - col) * vec4(invert, 1.0) + col * (1.0 - vec4(invert, 1.0));//blur5(tex, texcoord, blur, vec2(3.0));
|
||||
}
|
||||
|
||||
|
8
assets/shader/post.vsh.glsl
Normal file
8
assets/shader/post.vsh.glsl
Normal file
|
@ -0,0 +1,8 @@
|
|||
#version 100
|
||||
attribute vec2 pos;
|
||||
attribute vec2 uv;
|
||||
varying lowp vec2 texcoord;
|
||||
void main() {
|
||||
gl_Position = vec4(pos, 0, 1);
|
||||
texcoord = uv;
|
||||
}
|
88
src/game.rs
Normal file
88
src/game.rs
Normal file
|
@ -0,0 +1,88 @@
|
|||
use crate::{
|
||||
tools::{WPos, Sides}, graphics::DrawType,
|
||||
};
|
||||
|
||||
use self::{block::BlockType, world::World};
|
||||
|
||||
pub mod block;
|
||||
pub mod chunk;
|
||||
pub mod world;
|
||||
|
||||
|
||||
pub struct Game {
|
||||
worlds: Vec<World>,
|
||||
types: Vec<Box<dyn BlockType>>,
|
||||
type_names: Vec<String>,
|
||||
}
|
||||
|
||||
impl Game {
|
||||
pub fn new() -> Self {
|
||||
let mut g = Game {
|
||||
worlds: vec![],
|
||||
types: vec![],
|
||||
type_names: vec![],
|
||||
};
|
||||
g.add_type(Box::new(Air {
|
||||
id: "air".to_string(),
|
||||
}));
|
||||
g
|
||||
}
|
||||
|
||||
pub fn get_type(&self, id: usize) -> Option<&Box<dyn BlockType>> {
|
||||
self.types.get(id)
|
||||
}
|
||||
|
||||
pub fn find_type(&self, id: String) -> Option<(usize, &Box<dyn BlockType>)> {
|
||||
let index = self.type_names.iter().position(|r| r.eq(&id));
|
||||
if let Some(i) = index {
|
||||
return Some((i,&self.types[i]));
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
pub fn do_tick(&mut self, instant: bool) -> usize {
|
||||
let mut num = 0;
|
||||
for w in 0..self.worlds.len() {
|
||||
num += self.worlds[w].do_tick(instant, &self.types);
|
||||
}
|
||||
num
|
||||
}
|
||||
pub fn do_tex_tick(&mut self) {
|
||||
for w in 0..self.worlds.len() {
|
||||
self.worlds[w].do_tex_tick(&self.types);
|
||||
}
|
||||
}
|
||||
pub fn add_type(&mut self, mut block_type: Box<dyn BlockType>) -> usize {
|
||||
self.type_names.push(block_type.get_id().to_string());
|
||||
let index = self.types.len();
|
||||
block_type.set_index(index);
|
||||
self.types.push(block_type);
|
||||
index
|
||||
}
|
||||
pub fn add_world(&mut self) -> usize {
|
||||
self.worlds.push(World::new());
|
||||
self.worlds.len() - 1
|
||||
}
|
||||
pub fn get_world(&mut self, id: usize) -> Option<&mut World> {
|
||||
self.worlds.get_mut(id)
|
||||
}
|
||||
pub fn get_world_im(&self, id: usize) -> Option<&World> {
|
||||
self.worlds.get(id)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Air {
|
||||
id: String,
|
||||
}
|
||||
impl BlockType for Air {
|
||||
fn get_id(&self) -> String {
|
||||
self.id.to_string()
|
||||
}
|
||||
fn is_sided(&self) -> bool {
|
||||
false
|
||||
}
|
||||
fn texture(&self) -> &DrawType {
|
||||
&DrawType::None()
|
||||
}
|
||||
}
|
53
src/game/block.rs
Normal file
53
src/game/block.rs
Normal file
|
@ -0,0 +1,53 @@
|
|||
use std::collections::HashMap;
|
||||
|
||||
use crate::{graphics::{Draw, DrawType}, tools::PrimitiveData};
|
||||
|
||||
use super::{WPos, world::World};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Block {
|
||||
//pub pos: WPos,
|
||||
pub block_type: usize,
|
||||
|
||||
pub solid: bool,
|
||||
pub destroy: u8,
|
||||
|
||||
string_state: HashMap<String, (PrimitiveData, bool)>,
|
||||
}
|
||||
|
||||
|
||||
|
||||
impl Block {
|
||||
pub fn new(block_type: usize/*, pos: WPos*/) -> Self {
|
||||
Block {
|
||||
//pos,
|
||||
block_type: block_type,
|
||||
solid: true,
|
||||
string_state: HashMap::new(),
|
||||
destroy: 0,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_state(&self, name: &String) -> Option<&PrimitiveData> {
|
||||
match self.string_state.get(name) {
|
||||
Some((data, save)) => Some(data),
|
||||
None => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_state(&mut self, name: &String, value: PrimitiveData, save: bool) {
|
||||
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<Box<dyn BlockType>>, _instant: bool) {}
|
||||
fn update(&self, _world: &mut World, _block: WPos, _types: &Vec<Box<dyn BlockType>>, _instant: bool) {}
|
||||
fn render(&self, _world: &mut World, _block: WPos, _types: &Vec<Box<dyn BlockType>>) -> Draw { Draw::None() }
|
||||
fn texture(&self) -> &DrawType;
|
||||
}
|
113
src/game/chunk.rs
Normal file
113
src/game/chunk.rs
Normal file
|
@ -0,0 +1,113 @@
|
|||
use std::collections::HashMap;
|
||||
|
||||
use gl_matrix::{common::*, vec2::clone};
|
||||
|
||||
use crate::{tools::Sides, world_generator::WorldGenerator};
|
||||
|
||||
use super::{block::Block, WPos};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Instances {
|
||||
Single(Vec<WPos>),
|
||||
Sided([Vec<WPos>; 6]),
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Chunk {
|
||||
pub blocks: HashMap<(u8, u8, u8), Block>, //[[[Block; 16]; 256]; 16],
|
||||
pub instances: HashMap<usize, Instances>,
|
||||
}
|
||||
|
||||
impl Chunk {
|
||||
pub fn new(_chunk_x: i32, _chunk_z: i32) -> Self {
|
||||
Self {
|
||||
#[rustfmt::skip]
|
||||
blocks: HashMap::new(),
|
||||
instances: HashMap::new(),
|
||||
}
|
||||
}
|
||||
pub fn new_gen(generator: Box<dyn WorldGenerator>,_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*/),
|
||||
);
|
||||
}
|
||||
|
||||
pub fn remove_pos(&mut self, block_type: usize, pos: &WPos) {
|
||||
if let Some(data) = self.instances.get_mut(&block_type) {
|
||||
match data {
|
||||
Instances::Single(d) => {
|
||||
d.retain(|f| pos[0] != f[0] || pos[1] != f[1] || pos[2] != f[2]);
|
||||
if d.len() == 0 {
|
||||
self.instances.remove(&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
|
||||
{
|
||||
self.instances.remove(&block_type);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
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 {
|
||||
if !vec.contains(&pos) {
|
||||
vec.push(pos.clone());
|
||||
}
|
||||
} else {
|
||||
panic!("Wrong side Type")
|
||||
}
|
||||
} else {
|
||||
self.instances
|
||||
.insert(block_type, Instances::Single(vec![pos.clone()]));
|
||||
}
|
||||
}
|
||||
pub fn add_tex_pos_sided(&mut self, block_type: usize, pos: &WPos, sides: Sides<bool>) {
|
||||
if let Some(inst) = self.instances.get_mut(&block_type) {
|
||||
|
||||
if let Instances::Sided(vec) = inst {
|
||||
for i in 0..6 {
|
||||
if sides[i] {
|
||||
if !vec[i].contains(&pos) {
|
||||
vec[i].push(pos.clone());
|
||||
}
|
||||
} else {
|
||||
vec[i].retain(|f| pos[0] != f[0] || pos[1] != f[1] || pos[2] != f[2]);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
panic!("Wrong side Type")
|
||||
}
|
||||
} else {
|
||||
let mut new_arr: [Vec<[i32; 3]>; 6] = [vec![], vec![], vec![], vec![], vec![], vec![]];
|
||||
for i in 0..6 {
|
||||
if sides[i] {
|
||||
new_arr[i].push(pos.clone());
|
||||
}
|
||||
}
|
||||
self.instances.insert(block_type, Instances::Sided(new_arr));
|
||||
}
|
||||
}
|
||||
}
|
245
src/game/world.rs
Normal file
245
src/game/world.rs
Normal file
|
@ -0,0 +1,245 @@
|
|||
use std::collections::HashMap;
|
||||
|
||||
use crate::{graphics::Draw, world_generator::WorldGenerator};
|
||||
|
||||
use super::{block::Block, chunk::Chunk, BlockType, Sides, WPos};
|
||||
|
||||
pub enum GetBlock<T> {
|
||||
Some(T),
|
||||
None,
|
||||
No,
|
||||
}
|
||||
|
||||
//#[derive(Debug)]
|
||||
pub struct World {
|
||||
pub chunks: HashMap<(i32, i32), Chunk>,
|
||||
|
||||
generator: Box<dyn WorldGenerator>,
|
||||
|
||||
updates: Vec<WPos>,
|
||||
i_updates: Vec<WPos>,
|
||||
t_updates: Vec<WPos>,
|
||||
}
|
||||
|
||||
impl World {
|
||||
pub fn new() -> Self {
|
||||
World {
|
||||
chunks: HashMap::new(),
|
||||
updates: vec![],
|
||||
i_updates: vec![],
|
||||
t_updates: vec![],
|
||||
generator: Box::new(EmptyGenerator {}),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_block(&mut self, pos: &WPos) -> GetBlock<&mut Block> {
|
||||
if pos[1] < 0 || pos[1] > 256 {
|
||||
return GetBlock::None;
|
||||
}
|
||||
let chunk_x = pos[0].div_euclid(16);
|
||||
let chunk_z = pos[2].div_euclid(16);
|
||||
|
||||
let inner_x = pos[0].rem_euclid(16);
|
||||
let inner_z = pos[2].rem_euclid(16);
|
||||
|
||||
let chunk = self.chunks.get_mut(&(chunk_x, chunk_z));
|
||||
match chunk {
|
||||
Some(c) => match c
|
||||
.blocks
|
||||
.get_mut(&(inner_x as u8, pos[1] as u8, inner_z as u8))
|
||||
{
|
||||
Some(b) => GetBlock::Some(b),
|
||||
None => GetBlock::No,
|
||||
},
|
||||
None => GetBlock::None,
|
||||
}
|
||||
}
|
||||
pub fn get_block_im(&self, pos: &WPos) -> GetBlock<&Block> {
|
||||
if pos[1] < 0 || pos[1] > 256 {
|
||||
return GetBlock::None;
|
||||
}
|
||||
let chunk_x = pos[0].div_euclid(16);
|
||||
let chunk_z = pos[2].div_euclid(16);
|
||||
|
||||
let inner_x = pos[0].rem_euclid(16);
|
||||
let inner_z = pos[2].rem_euclid(16);
|
||||
|
||||
let chunk = self.chunks.get(&(chunk_x, chunk_z));
|
||||
match chunk {
|
||||
Some(c) => match c.blocks.get(&(inner_x as u8, pos[1] as u8, inner_z as u8)) {
|
||||
Some(b) => GetBlock::Some(b),
|
||||
None => GetBlock::No,
|
||||
},
|
||||
None => GetBlock::None,
|
||||
}
|
||||
}
|
||||
|
||||
fn loadChunk(&mut self, chunk_x: i32, chunk_z: i32) {
|
||||
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 {
|
||||
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]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_block(
|
||||
&mut self,
|
||||
pos: &WPos,
|
||||
block_type: usize,
|
||||
update: Sides<bool>,
|
||||
update_self: bool,
|
||||
) {
|
||||
if pos[1] < 0 {
|
||||
return;
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
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_self {
|
||||
self.update(&[pos[0], pos[1], pos[2]], true);
|
||||
}
|
||||
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());
|
||||
}
|
||||
|
||||
pub fn update(&mut self, pos: &WPos, instant: bool) {
|
||||
if instant {
|
||||
self.i_updates.push(pos.clone())
|
||||
} else {
|
||||
self.updates.push(pos.clone())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn update_surr(&mut self, pos: &WPos, instant: bool) {
|
||||
self.update(&[pos[0] + 1, pos[1], pos[2]], instant);
|
||||
self.update(&[pos[0] - 1, pos[1], pos[2]], instant);
|
||||
self.update(&[pos[0], pos[1] + 1, pos[2]], instant);
|
||||
self.update(&[pos[0], pos[1] - 1, pos[2]], instant);
|
||||
self.update(&[pos[0], pos[1], pos[2] + 1], instant);
|
||||
self.update(&[pos[0], pos[1], pos[2] - 1], instant);
|
||||
}
|
||||
|
||||
pub fn do_tick(&mut self, instant: bool, types: &Vec<Box<dyn BlockType>>) -> usize {
|
||||
let upd = if instant {
|
||||
let o = self.i_updates.clone();
|
||||
self.i_updates = vec![];
|
||||
o
|
||||
} else {
|
||||
let o = self.updates.clone();
|
||||
self.updates = vec![];
|
||||
o
|
||||
};
|
||||
|
||||
for p in 0..upd.len() {
|
||||
let cord = upd[p].clone();
|
||||
if let GetBlock::Some(block) = self.get_block(&cord) {
|
||||
if let Some(b_t) = types.get(block.block_type) {
|
||||
b_t.update(self, cord.clone(), types, instant);
|
||||
}
|
||||
}
|
||||
}
|
||||
upd.len()
|
||||
}
|
||||
pub fn do_tex_tick(&mut self, types: &Vec<Box<dyn BlockType>>) {
|
||||
let upd = self.t_updates.clone();
|
||||
self.t_updates = vec![];
|
||||
for p in 0..upd.len() {
|
||||
let pos = upd[p];
|
||||
|
||||
let chunk_x = pos[0].div_euclid(16);
|
||||
let chunk_z = pos[2].div_euclid(16);
|
||||
|
||||
if let GetBlock::Some(block) = self.get_block(&pos) {
|
||||
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);
|
||||
|
||||
if let Some(chunk) = self.chunks.get_mut(&(chunk_x, chunk_z)) {
|
||||
match draw {
|
||||
Draw::Sides(s) => {
|
||||
if block_type.is_sided() {
|
||||
chunk.add_tex_pos_sided(block_type_num, &pos, s);
|
||||
} else {
|
||||
chunk.add_tex_pos(block_type_num, &pos);
|
||||
}
|
||||
}
|
||||
Draw::All() => {
|
||||
if block_type.is_sided() {
|
||||
chunk.add_tex_pos_sided(block_type_num, &pos, Sides::all(true));
|
||||
} else {
|
||||
chunk.add_tex_pos(block_type_num, &pos);
|
||||
}
|
||||
}
|
||||
Draw::None() => {
|
||||
chunk.remove_pos(block_type_num, &pos);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct EmptyGenerator {}
|
||||
impl WorldGenerator for EmptyGenerator {
|
||||
fn generateChunk(&self, chunk: &mut Chunk) {}
|
||||
}
|
58
src/graphics.rs
Normal file
58
src/graphics.rs
Normal file
|
@ -0,0 +1,58 @@
|
|||
use std::collections::HashMap;
|
||||
|
||||
use miniquad::*;
|
||||
|
||||
use crate::tools::Sides;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Draw {
|
||||
All(), //single Model
|
||||
None(),
|
||||
Sides(Sides<bool>),
|
||||
}
|
||||
|
||||
pub enum DrawType {
|
||||
All(Texture), //single Model
|
||||
None(),
|
||||
Sides(Sides<Texture>),
|
||||
}
|
||||
|
||||
pub struct Graphics {
|
||||
pub textures: HashMap<String, Texture>,
|
||||
pub pipelines: HashMap<String, Pipeline>,
|
||||
}
|
||||
|
||||
impl Graphics {
|
||||
pub fn new() -> Self {
|
||||
Graphics { textures: HashMap::new(), pipelines: HashMap::new() }
|
||||
}
|
||||
pub fn load_texture(&mut self, ctx: &mut Context, bytes: &[u8], id: String) -> Texture {
|
||||
let decoder = png::Decoder::new(bytes);
|
||||
let mut reader = decoder.read_info().unwrap();
|
||||
let mut buf = vec![0; reader.output_buffer_size()];
|
||||
let info = reader.next_frame(&mut buf).unwrap();
|
||||
let bytes = &buf[..info.buffer_size()];
|
||||
let text = Texture::from_data_and_format(
|
||||
ctx,
|
||||
bytes,
|
||||
TextureParams {
|
||||
format: TextureFormat::RGBA8,
|
||||
wrap: TextureWrap::Clamp,
|
||||
filter: FilterMode::Nearest,
|
||||
width: info.width,
|
||||
height: info.height,
|
||||
},
|
||||
);
|
||||
|
||||
//text.set_filter_min_mag(ctx, FilterMode::Linear, FilterMode::Nearest);
|
||||
|
||||
self.textures.insert(id, text);
|
||||
|
||||
text
|
||||
}
|
||||
pub fn addPipeline(&mut self, pipeline: Pipeline, id:String) {
|
||||
self.pipelines.insert(id, pipeline);
|
||||
}
|
||||
}
|
||||
|
||||
|
108
src/jucraft.rs
Normal file
108
src/jucraft.rs
Normal file
|
@ -0,0 +1,108 @@
|
|||
use crate::{game::*, graphics::*, tools::Sides};
|
||||
|
||||
use default_solid_block::DefaultSolidBlock;
|
||||
use miniquad::*;
|
||||
|
||||
mod default_solid_block;
|
||||
pub mod default_solid_shader;
|
||||
|
||||
pub fn register(ctx: &mut Context, game: &mut Game, graphics: &mut Graphics) {
|
||||
graphics.load_texture(
|
||||
ctx,
|
||||
include_bytes!(concat!("../assets/break/empty_overlay.png")),
|
||||
"d-1".to_string(),
|
||||
);
|
||||
graphics.load_texture(
|
||||
ctx,
|
||||
include_bytes!(concat!("../assets/break/destroy_stage_0.png")),
|
||||
"d0".to_string(),
|
||||
);
|
||||
graphics.load_texture(
|
||||
ctx,
|
||||
include_bytes!(concat!("../assets/break/destroy_stage_1.png")),
|
||||
"d1".to_string(),
|
||||
);
|
||||
graphics.load_texture(
|
||||
ctx,
|
||||
include_bytes!(concat!("../assets/break/destroy_stage_2.png")),
|
||||
"d2".to_string(),
|
||||
);
|
||||
graphics.load_texture(
|
||||
ctx,
|
||||
include_bytes!(concat!("../assets/break/destroy_stage_3.png")),
|
||||
"d3".to_string(),
|
||||
);
|
||||
graphics.load_texture(
|
||||
ctx,
|
||||
include_bytes!(concat!("../assets/break/destroy_stage_4.png")),
|
||||
"d4".to_string(),
|
||||
);
|
||||
graphics.load_texture(
|
||||
ctx,
|
||||
include_bytes!(concat!("../assets/break/destroy_stage_5.png")),
|
||||
"d5".to_string(),
|
||||
);
|
||||
graphics.load_texture(
|
||||
ctx,
|
||||
include_bytes!(concat!("../assets/break/destroy_stage_6.png")),
|
||||
"d6".to_string(),
|
||||
);
|
||||
graphics.load_texture(
|
||||
ctx,
|
||||
include_bytes!(concat!("../assets/break/destroy_stage_7.png")),
|
||||
"d7".to_string(),
|
||||
);
|
||||
let stone_tex = graphics.load_texture(
|
||||
ctx,
|
||||
include_bytes!(concat!("../assets/blocks/stone.png")),
|
||||
"stone".to_string(),
|
||||
);
|
||||
let dirt_tex = graphics.load_texture(
|
||||
ctx,
|
||||
include_bytes!(concat!("../assets/blocks/dirt.png")),
|
||||
"dirt".to_string(),
|
||||
);
|
||||
let cobble_tex = graphics.load_texture(
|
||||
ctx,
|
||||
include_bytes!(concat!("../assets/blocks/cobblestone.png")),
|
||||
"cobblestone".to_string(),
|
||||
);
|
||||
let grass_top = graphics.load_texture(
|
||||
ctx,
|
||||
include_bytes!(concat!("../assets/blocks/grass_top.png")),
|
||||
"grass_top".to_string(),
|
||||
);
|
||||
let grass_side = graphics.load_texture(
|
||||
ctx,
|
||||
include_bytes!(concat!("../assets/blocks/grass_side.png")),
|
||||
"grass_side".to_string(),
|
||||
);
|
||||
let grass_bottom = graphics.load_texture(
|
||||
ctx,
|
||||
include_bytes!(concat!("../assets/blocks/grass_bottom.png")),
|
||||
"grass_bottom".to_string(),
|
||||
);
|
||||
let stone = game.add_type(Box::new(DefaultSolidBlock {
|
||||
id: "stone".to_string(),
|
||||
texture: DrawType::All(stone_tex),
|
||||
}));
|
||||
let dirt = game.add_type(Box::new(DefaultSolidBlock {
|
||||
id: "dirt".to_string(),
|
||||
texture: DrawType::All(dirt_tex),
|
||||
}));
|
||||
let cobblestone = game.add_type(Box::new(DefaultSolidBlock {
|
||||
id: "cobblestone".to_string(),
|
||||
texture: DrawType::All(cobble_tex),
|
||||
}));
|
||||
let grassblock = game.add_type(Box::new(DefaultSolidBlock {
|
||||
id: "grassblock".to_string(),
|
||||
texture: DrawType::Sides(Sides {
|
||||
top: grass_top,
|
||||
bottom: grass_bottom,
|
||||
left: grass_side,
|
||||
right: grass_side,
|
||||
front: grass_side,
|
||||
back: grass_side,
|
||||
}),
|
||||
}));
|
||||
}
|
79
src/jucraft/default_solid_block.rs
Normal file
79
src/jucraft/default_solid_block.rs
Normal file
|
@ -0,0 +1,79 @@
|
|||
|
||||
use crate::{
|
||||
game::{block::*, world::*},
|
||||
graphics::*,
|
||||
tools::*,
|
||||
};
|
||||
|
||||
pub struct DefaultSolidBlock {
|
||||
pub id: String,
|
||||
pub texture: DrawType,
|
||||
}
|
||||
impl BlockType for DefaultSolidBlock {
|
||||
fn get_id(&self) -> String {
|
||||
self.id.to_string()
|
||||
}
|
||||
fn create(
|
||||
&self,
|
||||
world: &mut World,
|
||||
block: WPos,
|
||||
_types: &Vec<Box<dyn BlockType>>,
|
||||
_instant: bool,
|
||||
) {
|
||||
if let GetBlock::Some(b) = world.get_block(&block) {
|
||||
if !b.solid {
|
||||
b.solid = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
fn render(
|
||||
&self,
|
||||
world: &mut World,
|
||||
block: WPos,
|
||||
_types: &Vec<Box<dyn BlockType>>,
|
||||
) -> Draw {
|
||||
let mut sides = Sides::all(true);
|
||||
sides.top = match world.get_block(&[block[0], block[1] + 1, block[2]]) {
|
||||
GetBlock::Some(bt) => !bt.solid,
|
||||
GetBlock::None => false,
|
||||
GetBlock::No => true,
|
||||
};
|
||||
sides.bottom = match world.get_block(&[block[0], block[1] - 1, block[2]]) {
|
||||
GetBlock::Some(bt) => !bt.solid,
|
||||
GetBlock::None => false,
|
||||
GetBlock::No => true,
|
||||
};
|
||||
sides.right = match world.get_block(&[block[0] - 1, block[1], block[2]]) {
|
||||
GetBlock::Some(bt) => !bt.solid,
|
||||
GetBlock::None => false,
|
||||
GetBlock::No => true,
|
||||
};
|
||||
sides.left = match world.get_block(&[block[0] + 1, block[1], block[2]]) {
|
||||
GetBlock::Some(bt) => !bt.solid,
|
||||
GetBlock::None => false,
|
||||
GetBlock::No => true,
|
||||
};
|
||||
sides.front = match world.get_block(&[block[0], block[1], block[2] - 1]) {
|
||||
GetBlock::Some(bt) => !bt.solid,
|
||||
GetBlock::None => false,
|
||||
GetBlock::No => true,
|
||||
};
|
||||
sides.back = match world.get_block(&[block[0], block[1], block[2] + 1]) {
|
||||
GetBlock::Some(bt) => !bt.solid,
|
||||
GetBlock::None => false,
|
||||
GetBlock::No => true,
|
||||
};
|
||||
if sides.are_all(false) {
|
||||
Draw::None()
|
||||
} else {
|
||||
Draw::Sides(sides)
|
||||
}
|
||||
}
|
||||
fn texture(&self) -> &DrawType {
|
||||
&self.texture
|
||||
}
|
||||
|
||||
fn is_sided(&self) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
26
src/jucraft/default_solid_shader.rs
Normal file
26
src/jucraft/default_solid_shader.rs
Normal file
|
@ -0,0 +1,26 @@
|
|||
use gl_matrix::common::*;
|
||||
use miniquad::*;
|
||||
|
||||
pub const VERTEX: &str = include_str!(concat!("../../assets/shader/default.vsh.glsl"));
|
||||
|
||||
pub const FRAGMENT: &str = include_str!(concat!("../../assets/shader/default.fsh.glsl"));
|
||||
|
||||
pub fn meta() -> ShaderMeta {
|
||||
ShaderMeta {
|
||||
images: vec!["u_image0".to_string(), "u_image1".to_string()],
|
||||
uniforms: UniformBlockLayout {
|
||||
uniforms: vec![
|
||||
UniformDesc::new("view", UniformType::Mat4),
|
||||
UniformDesc::new("proj", UniformType::Mat4),
|
||||
UniformDesc::new("fog", UniformType::Float2),
|
||||
],
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct Uniforms {
|
||||
pub view: Mat4,
|
||||
pub proj: Mat4,
|
||||
pub fog: Vec2,
|
||||
}
|
27
src/main.rs
Normal file
27
src/main.rs
Normal file
|
@ -0,0 +1,27 @@
|
|||
use miniquad::*;
|
||||
use stage::Stage;
|
||||
|
||||
mod game;
|
||||
mod shader;
|
||||
mod stage;
|
||||
mod graphics;
|
||||
mod tools;
|
||||
mod jucraft;
|
||||
mod player;
|
||||
mod world_generator;
|
||||
|
||||
fn main() {
|
||||
start(conf::Conf{
|
||||
window_title: "Jucraft".to_string(),
|
||||
window_height: 900,
|
||||
window_width: 900* 16 / 9,
|
||||
..Default::default()
|
||||
|
||||
}, |mut ctx| {
|
||||
Box::new(Stage::new(&mut ctx))
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
// to read: for Map generation: https://www.redblobgames.com/maps/terrain-from-noise/
|
||||
// with opensimplex_noise_rs crate
|
218
src/player.rs
Normal file
218
src/player.rs
Normal file
|
@ -0,0 +1,218 @@
|
|||
use gl_matrix::{common::*, *};
|
||||
|
||||
use crate::{
|
||||
game::{world::GetBlock, Game},
|
||||
tools::*,
|
||||
};
|
||||
|
||||
pub struct Player {
|
||||
pub rot: Vec2,
|
||||
pub pos: Vec3,
|
||||
pub motion: Vec3,
|
||||
pub eyes: f32,
|
||||
pub size: Vec3,
|
||||
pub flying: bool,
|
||||
pub max_speed: f32,
|
||||
pub world: usize,
|
||||
|
||||
// retundant
|
||||
pub speed: f32,
|
||||
pub on_gound: bool,
|
||||
}
|
||||
|
||||
impl Player {
|
||||
pub fn new(rot: Vec2, pos: Vec3) -> Self {
|
||||
Self {
|
||||
rot,
|
||||
pos,
|
||||
motion: [0., 0., 0.],
|
||||
eyes: 1.7,
|
||||
size: [0.8, 1.99, 0.8],
|
||||
flying: true,
|
||||
max_speed: 10.,
|
||||
world: 0,
|
||||
|
||||
speed: 0.,
|
||||
on_gound: false,
|
||||
}
|
||||
}
|
||||
pub fn update(&mut self, game: &mut Game, s_move: &Sides<bool>, delta: f32) {
|
||||
if self.flying {
|
||||
if s_move.top {
|
||||
self.motion[1] += delta * 100.0;
|
||||
}
|
||||
if s_move.bottom {
|
||||
self.motion[1] -= delta * 100.0;
|
||||
}
|
||||
let decal = 70. * delta;
|
||||
if self.motion[1].abs() > decal {
|
||||
if self.motion[1] > 0. {
|
||||
self.motion[1] -= decal;
|
||||
} else {
|
||||
self.motion[1] += decal;
|
||||
}
|
||||
} 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.;
|
||||
} else {
|
||||
self.motion[1] = -30.;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let decalerate: f32 = if self.on_gound || self.flying {
|
||||
50.
|
||||
} else {
|
||||
1.
|
||||
};
|
||||
let acceleration: f32 = if self.on_gound || self.flying {
|
||||
100. * 50.
|
||||
} else {
|
||||
10. + 1.
|
||||
};
|
||||
|
||||
if s_move.front {
|
||||
self.motion[2] += self.rot[1].to_radians().cos() * delta * acceleration;
|
||||
self.motion[0] -= self.rot[1].to_radians().sin() * delta * acceleration;
|
||||
}
|
||||
if s_move.back {
|
||||
self.motion[2] -= self.rot[1].to_radians().cos() * delta * acceleration;
|
||||
self.motion[0] += self.rot[1].to_radians().sin() * delta * acceleration;
|
||||
}
|
||||
if s_move.left {
|
||||
self.motion[2] += self.rot[1].to_radians().sin() * delta * acceleration;
|
||||
self.motion[0] += self.rot[1].to_radians().cos() * delta * acceleration;
|
||||
}
|
||||
if s_move.right {
|
||||
self.motion[2] -= self.rot[1].to_radians().sin() * delta * acceleration;
|
||||
self.motion[0] -= self.rot[1].to_radians().cos() * delta * acceleration;
|
||||
}
|
||||
|
||||
self.speed = (self.motion[0].powi(2) + self.motion[2].powi(2)).sqrt();
|
||||
|
||||
if self.speed > self.max_speed {
|
||||
let modifier = self.max_speed / self.speed;
|
||||
self.motion[0] = self.motion[0] * modifier;
|
||||
self.motion[2] = self.motion[2] * modifier;
|
||||
} else {
|
||||
if self.speed > 0.1 {
|
||||
let modi_x = delta * decalerate * self.motion[0] / self.speed;
|
||||
if (self.motion[0] > 0.) == (self.motion[0] - modi_x > 0.) {
|
||||
self.motion[0] -= modi_x;
|
||||
} else {
|
||||
self.motion[0] = 0.;
|
||||
}
|
||||
|
||||
let modi_z = delta * decalerate * self.motion[2] / self.speed;
|
||||
if (self.motion[2] > 0.) == (self.motion[2] - modi_z > 0.) {
|
||||
self.motion[2] -= modi_z;
|
||||
} else {
|
||||
self.motion[2] = 0.;
|
||||
}
|
||||
} else {
|
||||
self.motion[0] = 0.;
|
||||
self.motion[2] = 0.;
|
||||
}
|
||||
}
|
||||
|
||||
//self.pos[0] += self.motion[0] * delta;
|
||||
//self.pos[1] += self.motion[1] * delta;
|
||||
//self.pos[2] += self.motion[2] * delta;
|
||||
self.on_gound = false;
|
||||
for cord in 0..3 {
|
||||
let mut dist = self.motion[cord] * delta;
|
||||
while dist.abs() > 0. {
|
||||
let do_dist = if dist.abs() < 0.5 {
|
||||
let d = dist;
|
||||
dist = 0.;
|
||||
d
|
||||
} else {
|
||||
if dist > 0. {
|
||||
dist -= 0.5;
|
||||
0.5
|
||||
} else {
|
||||
dist += 0.5;
|
||||
-0.5
|
||||
}
|
||||
};
|
||||
|
||||
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;
|
||||
} else if do_dist < 0. {
|
||||
self.pos[cord] = b_pos[cord] + b_size[cord] + self_offset + 0.001;
|
||||
if cord == 1 {
|
||||
self.on_gound = true;
|
||||
}
|
||||
}
|
||||
self.motion[cord] = 0.;
|
||||
}
|
||||
} else {
|
||||
self.pos[cord] += do_dist;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_clipped(&self, game: &mut Game) -> Option<(Vec3, Vec3)> {
|
||||
if let Some(world) = game.get_world_im(self.world) {
|
||||
let mx = self.pos[0].floor() as i32;
|
||||
let my = self.pos[1].floor() as i32;
|
||||
let mz = self.pos[2].floor() as i32;
|
||||
let vx = (self.size[0] / 2.).ceil() as i32;
|
||||
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 {
|
||||
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.]));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
pub fn rotate(&mut self, x: f32, y: f32) {
|
||||
self.rot[0] -= y / 10.0;
|
||||
self.rot[1] += x / 10.0;
|
||||
while self.rot[0] > 90.0 {
|
||||
self.rot[0] = 90.;
|
||||
}
|
||||
while self.rot[0] < -90.0 {
|
||||
self.rot[0] = -90.;
|
||||
}
|
||||
while self.rot[1] > 180.0 {
|
||||
self.rot[1] -= 360.;
|
||||
}
|
||||
while self.rot[1] < -180.0 {
|
||||
self.rot[1] += 360.;
|
||||
}
|
||||
}
|
||||
}
|
141
src/shader.rs
Normal file
141
src/shader.rs
Normal file
|
@ -0,0 +1,141 @@
|
|||
use std::f64::consts::PI;
|
||||
|
||||
use gl_matrix::{common::*, *};
|
||||
use miniquad::*;
|
||||
|
||||
pub mod post;
|
||||
|
||||
pub struct RenderHelper {
|
||||
post_processing_pipeline: Pipeline,
|
||||
post_processing_bind: Bindings,
|
||||
offscreen_pass: RenderPass,
|
||||
post_enabled: bool,
|
||||
}
|
||||
|
||||
impl RenderHelper {
|
||||
pub fn new(ctx: &mut Context) -> Self {
|
||||
let (w, h) = ctx.screen_size();
|
||||
let color_img = Texture::new_render_texture(
|
||||
ctx,
|
||||
TextureParams {
|
||||
width: w as _,
|
||||
height: h as _,
|
||||
format: TextureFormat::RGBA8,
|
||||
..Default::default()
|
||||
},
|
||||
);
|
||||
let depth_img = Texture::new_render_texture(
|
||||
ctx,
|
||||
TextureParams {
|
||||
width: w as _,
|
||||
height: h as _,
|
||||
format: TextureFormat::Depth,
|
||||
..Default::default()
|
||||
},
|
||||
);
|
||||
let offscreen_pass = RenderPass::new(ctx, color_img, depth_img);
|
||||
|
||||
#[rustfmt::skip]
|
||||
let post_vertices: &[f32] = &[
|
||||
/* pos uvs */
|
||||
-1.0, -1.0, 0.1, 0.1,
|
||||
1.0, -1.0, 0.9, 0.1,
|
||||
1.0, 1.0, 0.9, 0.9,
|
||||
-1.0, 1.0, 0.1, 0.9,
|
||||
];
|
||||
|
||||
let post_vertex_buffer = Buffer::immutable(ctx, BufferType::VertexBuffer, &post_vertices);
|
||||
|
||||
let post_indices: &[u16] = &[0, 1, 2, 0, 2, 3];
|
||||
|
||||
let post_index_buffer = Buffer::immutable(ctx, BufferType::IndexBuffer, &post_indices);
|
||||
|
||||
let post_processing_bind = Bindings {
|
||||
vertex_buffers: vec![post_vertex_buffer],
|
||||
index_buffer: post_index_buffer,
|
||||
images: vec![color_img],
|
||||
};
|
||||
let post_shader = Shader::new(ctx, post::VERTEX, post::FRAGMENT, post::meta()).unwrap();
|
||||
|
||||
let post_processing_pipeline = Pipeline::new(
|
||||
ctx,
|
||||
&[BufferLayout::default()],
|
||||
&[
|
||||
VertexAttribute::new("pos", VertexFormat::Float2),
|
||||
VertexAttribute::new("uv", VertexFormat::Float2),
|
||||
],
|
||||
post_shader,
|
||||
);
|
||||
|
||||
Self {
|
||||
post_processing_pipeline,
|
||||
post_processing_bind,
|
||||
offscreen_pass,
|
||||
post_enabled: true,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn resize(&mut self, ctx: &mut Context, width: f32, height: f32) {
|
||||
let color_img = Texture::new_render_texture(
|
||||
ctx,
|
||||
TextureParams {
|
||||
width: width as _,
|
||||
height: height as _,
|
||||
format: TextureFormat::RGBA8,
|
||||
..Default::default()
|
||||
},
|
||||
);
|
||||
let depth_img = Texture::new_render_texture(
|
||||
ctx,
|
||||
TextureParams {
|
||||
width: width as _,
|
||||
height: height as _,
|
||||
format: TextureFormat::Depth,
|
||||
..Default::default()
|
||||
},
|
||||
);
|
||||
|
||||
let offscreen_pass = RenderPass::new(ctx, color_img, depth_img);
|
||||
|
||||
self.offscreen_pass.delete(ctx);
|
||||
self.offscreen_pass = offscreen_pass;
|
||||
self.post_processing_bind.images[0] = color_img;
|
||||
}
|
||||
|
||||
pub fn begin_world(&self, ctx: &mut Context) {
|
||||
if self.post_enabled {
|
||||
ctx.begin_pass(
|
||||
self.offscreen_pass,
|
||||
PassAction::clear_color(0.75, 0.85, 0.8, 1.0),
|
||||
);
|
||||
} else {
|
||||
ctx.begin_default_pass(PassAction::clear_color(0.75, 0.85, 0.8, 1.0));
|
||||
}
|
||||
}
|
||||
|
||||
pub fn do_post_begin_ui(&self, ctx: &mut Context) {
|
||||
ctx.end_render_pass();
|
||||
if self.post_enabled {
|
||||
let t = date::now();
|
||||
ctx.begin_default_pass(PassAction::Nothing);
|
||||
ctx.apply_pipeline(&self.post_processing_pipeline);
|
||||
ctx.apply_bindings(&self.post_processing_bind);
|
||||
|
||||
let invert = ((t).sin()/2.0 + 0.5) as f32;
|
||||
ctx.apply_uniforms(&post::Uniforms {
|
||||
wobble: [1., ((t * 6.0) % (2.0 * PI)) as f32],
|
||||
invert: [invert, invert, invert],
|
||||
blur: [1., 1.],
|
||||
});
|
||||
ctx.draw(0, 6, 1);
|
||||
|
||||
ctx.end_render_pass();
|
||||
}
|
||||
ctx.begin_default_pass(PassAction::Nothing);
|
||||
}
|
||||
|
||||
pub fn end_ui(&self, ctx: &mut Context) {
|
||||
ctx.end_render_pass();
|
||||
ctx.commit_frame();
|
||||
}
|
||||
}
|
26
src/shader/post.rs
Normal file
26
src/shader/post.rs
Normal file
|
@ -0,0 +1,26 @@
|
|||
use gl_matrix::common::*;
|
||||
use miniquad::*;
|
||||
|
||||
pub const VERTEX: &str = include_str!(concat!("../../assets/shader/post.vsh.glsl"));
|
||||
|
||||
pub const FRAGMENT: &str = include_str!(concat!("../../assets/shader/post.fsh.glsl"));
|
||||
|
||||
pub fn meta() -> ShaderMeta {
|
||||
ShaderMeta {
|
||||
images: vec!["tex".to_string()],
|
||||
uniforms: UniformBlockLayout {
|
||||
uniforms: vec![
|
||||
UniformDesc::new("wobble", UniformType::Float2),
|
||||
UniformDesc::new("invert", UniformType::Float3),
|
||||
UniformDesc::new("blur", UniformType::Float2),
|
||||
],
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct Uniforms {
|
||||
pub wobble: Vec2,
|
||||
pub invert: Vec3,
|
||||
pub blur: Vec2,
|
||||
}
|
400
src/stage.rs
Normal file
400
src/stage.rs
Normal file
|
@ -0,0 +1,400 @@
|
|||
|
||||
use gl_matrix::{mat4, common::*};
|
||||
use miniquad::*;
|
||||
|
||||
use crate::{game::{Game, chunk::*}, graphics::{Graphics, DrawType}, jucraft::{*, self}, shader::RenderHelper, tools::*, player::Player};
|
||||
|
||||
const MAX_INSTANT_TICKS: i32 = 50;
|
||||
|
||||
pub struct Stage {
|
||||
game: Game,
|
||||
graphics: Graphics,
|
||||
|
||||
render_helper: RenderHelper,
|
||||
|
||||
last_tick: f64,
|
||||
delta: f64,
|
||||
last_frame: f64,
|
||||
|
||||
pipeline: Pipeline,
|
||||
bindings: Bindings,
|
||||
|
||||
|
||||
fullscreen: bool,
|
||||
player: Player,
|
||||
mouse_grab: bool,
|
||||
s_move: Sides<bool>,
|
||||
|
||||
x: i32,
|
||||
y: i32,
|
||||
z: i32,
|
||||
|
||||
t_fp:f64,
|
||||
}
|
||||
|
||||
impl Stage {
|
||||
pub fn new(ctx: &mut Context) -> Stage {
|
||||
let mut game = Game::new();
|
||||
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.],
|
||||
);
|
||||
player.world = world;
|
||||
|
||||
let post = RenderHelper::new(ctx);
|
||||
|
||||
#[rustfmt::skip]
|
||||
let vertices = vec![
|
||||
Vertex{pos:[0.0, 0.0, 1.0], uv:[0.0, 1.0]},
|
||||
Vertex{pos:[1.0, 0.0, 1.0], uv:[1.0, 1.0]},
|
||||
Vertex{pos:[0.0, 1.0, 1.0], uv:[0.0, 0.0]},
|
||||
Vertex{pos:[1.0, 1.0, 1.0], uv:[1.0, 0.0]},
|
||||
|
||||
Vertex{pos:[0.0, 0.0, 0.0], uv:[0.0, 1.0]},
|
||||
Vertex{pos:[0.0, 0.0, 1.0], uv:[1.0, 1.0]},
|
||||
Vertex{pos:[0.0, 1.0, 0.0], uv:[0.0, 0.0]},
|
||||
Vertex{pos:[0.0, 1.0, 1.0], uv:[1.0, 0.0]},
|
||||
|
||||
Vertex{pos:[1.0, 0.0, 0.0], uv:[0.0, 1.0]},
|
||||
Vertex{pos:[0.0, 0.0, 0.0], uv:[1.0, 1.0]},
|
||||
Vertex{pos:[1.0, 1.0, 0.0], uv:[0.0, 0.0]},
|
||||
Vertex{pos:[0.0, 1.0, 0.0], uv:[1.0, 0.0]},
|
||||
|
||||
Vertex{pos:[1.0, 0.0, 1.0], uv:[0.0, 1.0]},
|
||||
Vertex{pos:[1.0, 0.0, 0.0], uv:[1.0, 1.0]},
|
||||
Vertex{pos:[1.0, 1.0, 1.0], uv:[0.0, 0.0]},
|
||||
Vertex{pos:[1.0, 1.0, 0.0], uv:[1.0, 0.0]},
|
||||
|
||||
Vertex{pos:[0.0, 1.0, 0.0], uv:[0.0, 1.0]},
|
||||
Vertex{pos:[0.0, 1.0, 1.0], uv:[1.0, 1.0]},
|
||||
Vertex{pos:[1.0, 1.0, 0.0], uv:[0.0, 0.0]},
|
||||
Vertex{pos:[1.0, 1.0, 1.0], uv:[1.0, 0.0]},
|
||||
|
||||
Vertex{pos:[0.0, 0.0, 0.0], uv:[0.0, 1.0]},
|
||||
Vertex{pos:[1.0, 0.0, 0.0], uv:[1.0, 1.0]},
|
||||
Vertex{pos:[0.0, 0.0, 1.0], uv:[0.0, 0.0]},
|
||||
Vertex{pos:[1.0, 0.0, 1.0], uv:[1.0, 0.0]}
|
||||
];
|
||||
let vertex_buffer = Buffer::immutable(ctx, BufferType::VertexBuffer, &vertices);
|
||||
|
||||
let indices = vec![
|
||||
16, 17, 18, // top
|
||||
19, 18, 17,
|
||||
|
||||
20, 21, 22, // bottom
|
||||
23, 22, 21,
|
||||
|
||||
12, 13, 14, // left
|
||||
15, 14, 13,
|
||||
|
||||
4, 5, 6, //right
|
||||
7, 6, 5,
|
||||
|
||||
8, 9, 10, // front
|
||||
11, 10, 9,
|
||||
|
||||
0, 1, 2, // back
|
||||
3, 2, 1,
|
||||
|
||||
];
|
||||
let index_buffer = Buffer::immutable(ctx, BufferType::IndexBuffer, &indices);
|
||||
|
||||
let positions_vertex_buffer = Buffer::stream(
|
||||
ctx,
|
||||
BufferType::VertexBuffer,
|
||||
16*16*256 * std::mem::size_of::<WPos>(),
|
||||
);
|
||||
|
||||
let bindings = Bindings {
|
||||
vertex_buffers: vec![vertex_buffer, positions_vertex_buffer],
|
||||
index_buffer: index_buffer,
|
||||
images: vec![graphics.textures["stone"], graphics.textures["d-1"]],
|
||||
};
|
||||
|
||||
let shader = Shader::new(ctx, default_solid_shader::VERTEX, default_solid_shader::FRAGMENT, default_solid_shader::meta()).unwrap();
|
||||
|
||||
let pipeline = Pipeline::with_params(
|
||||
ctx,
|
||||
&[BufferLayout::default(), BufferLayout {
|
||||
step_func: VertexStep::PerInstance,
|
||||
..Default::default()
|
||||
},],
|
||||
&[
|
||||
VertexAttribute::with_buffer("pos", VertexFormat::Float3,0),
|
||||
VertexAttribute::with_buffer("uv", VertexFormat::Float2,0),
|
||||
VertexAttribute::with_buffer("wpos", VertexFormat::Int3, 1),
|
||||
],
|
||||
shader,
|
||||
PipelineParams {
|
||||
depth_test: Comparison::LessOrEqual,
|
||||
depth_write: true,
|
||||
cull_face: CullFace::Back,
|
||||
front_face_order: FrontFaceOrder::CounterClockwise,
|
||||
color_blend: Some(BlendState::new(Equation::Add, BlendFactor::One, BlendFactor::OneMinusValue(BlendValue::SourceAlpha))),
|
||||
alpha_blend: Some(BlendState::new(Equation::Add, BlendFactor::One, BlendFactor::Zero)),
|
||||
..Default::default()
|
||||
}
|
||||
);
|
||||
|
||||
println!("created");
|
||||
|
||||
Self {
|
||||
game,
|
||||
graphics,
|
||||
last_tick: date::now(),
|
||||
delta: 0.1,
|
||||
last_frame: date::now(),
|
||||
render_helper: post,
|
||||
pipeline,
|
||||
bindings,
|
||||
|
||||
fullscreen: false,
|
||||
|
||||
player,
|
||||
|
||||
mouse_grab: false,
|
||||
s_move: Sides::all(false),
|
||||
x: 2,
|
||||
y: 1,
|
||||
z: 1,
|
||||
|
||||
t_fp: 20.,
|
||||
}
|
||||
}
|
||||
}
|
||||
impl EventHandler for Stage {
|
||||
fn update(&mut self, _ctx: &mut Context) {
|
||||
let t = date::now();
|
||||
self.delta = t - self.last_frame;
|
||||
self.last_frame = t;
|
||||
|
||||
let mut l_a = 1;
|
||||
let mut count = 0;
|
||||
while l_a > 0 {
|
||||
if count > MAX_INSTANT_TICKS {
|
||||
eprintln!("Instant tick overflow");
|
||||
break;
|
||||
}
|
||||
l_a = self.game.do_tick(true);
|
||||
count += 1;
|
||||
}
|
||||
if self.last_tick < t - 1. / 20. {
|
||||
self.last_tick += 1. / 20.;
|
||||
self.game.do_tick(false);
|
||||
|
||||
//eprintln!("fps: {}|{}", 1. / self.delta, self.t_fp);
|
||||
|
||||
if self.last_tick < t - 5. {
|
||||
self.last_tick = t - 1. / 20.;
|
||||
}
|
||||
}
|
||||
self.game.do_tex_tick();
|
||||
|
||||
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) {
|
||||
self.render_helper.begin_world(ctx);
|
||||
|
||||
let t = date::now();
|
||||
|
||||
ctx.apply_pipeline(&self.pipeline);
|
||||
ctx.apply_bindings(&self.bindings);
|
||||
|
||||
let (w,h) = ctx.screen_size();
|
||||
let mut proj_matrix = mat4::create();
|
||||
mat4::perspective(&mut proj_matrix, 90.0f32.to_radians(), w as f32 / h as f32, 0.1, Some(10000.0));
|
||||
|
||||
let mut cammat = mat4::create();
|
||||
let mut cammat1 = mat4::create();
|
||||
|
||||
mat4::identity(&mut cammat);
|
||||
mat4::rotate_x(&mut cammat1, &cammat, -(self.player.rot[0] / 180. * PI));
|
||||
mat4::rotate_y(&mut cammat, &cammat1, self.player.rot[1] / 180. * PI);
|
||||
mat4::translate(&mut cammat1, &cammat, &[self.player.pos[0], -self.player.pos[1]- self.player.eyes, self.player.pos[2]]);
|
||||
|
||||
let mut view_matrix = mat4::create();
|
||||
mat4::look_at(&mut view_matrix, &[0., 0., 0.], &[0., 0., 0.], &[0., 0., 0.]);
|
||||
mat4::multiply(&mut cammat, &cammat1, &view_matrix);
|
||||
|
||||
ctx.apply_uniforms(&default_solid_shader::Uniforms {
|
||||
proj: proj_matrix,
|
||||
view: cammat,
|
||||
fog: [140.0, 160.0]
|
||||
});
|
||||
|
||||
if let Some(world) = self.game.get_world_im(self.player.world){
|
||||
for (_,chunk) in &world.chunks {
|
||||
for (b_type, inst) in &chunk.instances{
|
||||
if let Some(b_t) = self.game.get_type(*b_type){
|
||||
let tex = b_t.texture();
|
||||
if let DrawType::All(ttt) = tex {
|
||||
self.bindings.images[0] = *ttt;
|
||||
ctx.apply_bindings(&self.bindings);
|
||||
}
|
||||
match inst {
|
||||
Instances::Single(c) => {
|
||||
if c.len() > 0{
|
||||
self.bindings.vertex_buffers[1].update(ctx, &c);
|
||||
ctx.draw(0, 36, c.len() as i32);
|
||||
}
|
||||
},
|
||||
Instances::Sided(s) => {
|
||||
for i in 0..6 {
|
||||
let len = s[i].len() as i32;
|
||||
if len > 0{
|
||||
if let DrawType::Sides(ttt) = tex {
|
||||
self.bindings.images[0] = ttt[i];
|
||||
ctx.apply_bindings(&self.bindings);
|
||||
}
|
||||
self.bindings.vertex_buffers[1].update(ctx, &s[i]);
|
||||
ctx.draw(6 * i as i32, 6, len);
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
self.render_helper.do_post_begin_ui(ctx);
|
||||
|
||||
let end = date::now();
|
||||
|
||||
self.t_fp = self.t_fp *0.9 + 0.1/(end-t);
|
||||
|
||||
// TODO: render 2D UI
|
||||
|
||||
self.render_helper.end_ui(ctx);
|
||||
}
|
||||
|
||||
fn resize_event(&mut self, ctx: &mut Context, width: f32, height: f32) {
|
||||
self.render_helper.resize(ctx, width, height);
|
||||
}
|
||||
|
||||
fn key_down_event(&mut self, _ctx: &mut Context, keycode: KeyCode, _keymods: KeyMods,_repeatt: bool) {
|
||||
if keycode == KeyCode::Space{
|
||||
self.s_move.top = true;
|
||||
}else if keycode == KeyCode::LeftShift{
|
||||
self.s_move.bottom = true;
|
||||
}else if keycode == KeyCode::W{
|
||||
self.s_move.front = true;
|
||||
}else if keycode == KeyCode::A{
|
||||
self.s_move.left = true;
|
||||
}else if keycode == KeyCode::S{
|
||||
self.s_move.back = true;
|
||||
}else if keycode == KeyCode::D{
|
||||
self.s_move.right = true;
|
||||
}
|
||||
}
|
||||
|
||||
fn key_up_event(&mut self, ctx: &mut Context, keycode: KeyCode, _keymods: KeyMods) {
|
||||
|
||||
if keycode == KeyCode::F11 {
|
||||
if self.fullscreen {
|
||||
ctx.set_fullscreen(false);
|
||||
ctx.set_window_size(900* 16 / 9, 900);
|
||||
self.fullscreen = false;
|
||||
}else {
|
||||
ctx.set_fullscreen(true);
|
||||
self.fullscreen = true;
|
||||
}
|
||||
if self.mouse_grab {
|
||||
//println!("reloc");
|
||||
ctx.set_cursor_grab(false);
|
||||
ctx.show_mouse(true);
|
||||
self.mouse_grab = false;
|
||||
}
|
||||
}else if keycode == KeyCode::Escape {
|
||||
ctx.set_cursor_grab(false);
|
||||
ctx.show_mouse(true);
|
||||
self.mouse_grab = false;
|
||||
|
||||
}else if keycode == KeyCode::Space{
|
||||
self.s_move.top = false;
|
||||
}else if keycode == KeyCode::LeftShift{
|
||||
self.s_move.bottom = false;
|
||||
}else if keycode == KeyCode::W{
|
||||
self.s_move.front = false;
|
||||
}else if keycode == KeyCode::A{
|
||||
self.s_move.left = false;
|
||||
}else if keycode == KeyCode::S{
|
||||
self.s_move.back = false;
|
||||
}else if keycode == KeyCode::D{
|
||||
self.s_move.right = false;
|
||||
}else if keycode == KeyCode::F{
|
||||
self.player.flying = !self.player.flying;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fn window_minimized_event(&mut self, ctx: &mut Context) {
|
||||
ctx.set_cursor_grab(false);
|
||||
ctx.show_mouse(true);
|
||||
self.mouse_grab = false;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
fn raw_mouse_motion(&mut self, _ctx: &mut Context, x: f32, y: f32) {
|
||||
if self.mouse_grab {
|
||||
self.player.rotate(x, y);
|
||||
}
|
||||
}
|
||||
|
||||
fn touch_event(&mut self, ctx: &mut Context, phase: TouchPhase, _id: u64, x: f32, y: f32) {
|
||||
|
||||
}
|
||||
}
|
71
src/tools.rs
Normal file
71
src/tools.rs
Normal file
|
@ -0,0 +1,71 @@
|
|||
use std::ops::Index;
|
||||
|
||||
use gl_matrix::common::*;
|
||||
|
||||
pub type WPos = [i32; 3];
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Sides<T: Copy + PartialEq> {
|
||||
pub top: T,
|
||||
pub bottom: T,
|
||||
pub left: T,
|
||||
pub right: T,
|
||||
pub front: T,
|
||||
pub back: T,
|
||||
}
|
||||
|
||||
impl<T: Copy + PartialEq> Sides<T> {
|
||||
pub fn all(v: T) -> Sides<T> {
|
||||
Sides {
|
||||
top: v,
|
||||
bottom: v,
|
||||
left: v,
|
||||
right: v,
|
||||
front: v,
|
||||
back: v,
|
||||
}
|
||||
}
|
||||
pub fn are_all(&self, v: T) -> bool {
|
||||
self.top == v
|
||||
&& self.bottom == v
|
||||
&& self.left == v
|
||||
&& self.right == v
|
||||
&& self.front == v
|
||||
&& self.back == v
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Copy + PartialEq> Index<usize> for Sides<T> {
|
||||
type Output = T;
|
||||
|
||||
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");}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct Vertex {
|
||||
pub pos: Vec3,
|
||||
pub uv: Vec2,
|
||||
}
|
||||
|
||||
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.
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum PrimitiveData {
|
||||
String(String),
|
||||
Number(i32),
|
||||
Boolean(bool)
|
||||
}
|
7
src/world_generator.rs
Normal file
7
src/world_generator.rs
Normal file
|
@ -0,0 +1,7 @@
|
|||
use crate::game::chunk::Chunk;
|
||||
|
||||
|
||||
|
||||
pub trait WorldGenerator {
|
||||
fn generateChunk(&self, chunk: &mut Chunk);
|
||||
}
|
Loading…
Reference in a new issue