aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
This commit is contained in:
43
src/main.rs
Normal file
43
src/main.rs
Normal file
@@ -0,0 +1,43 @@
|
||||
use log::LevelFilter;
|
||||
use raylib::prelude::*;
|
||||
|
||||
mod player;
|
||||
mod world;
|
||||
mod renderer;
|
||||
|
||||
pub const VEL: f32 = 20000.0;
|
||||
|
||||
fn main() {
|
||||
env_logger::builder()
|
||||
.filter_level(LevelFilter::Trace)
|
||||
.init();
|
||||
let mut rend = renderer::Renderer::init();
|
||||
|
||||
let surface_level = 16;
|
||||
|
||||
let mut world = world::World::new();
|
||||
world.generate_new(surface_level);
|
||||
|
||||
let mut player = player::Player::new((0.0, (surface_level+1) as f32).into());
|
||||
|
||||
log::info!("Started up!");
|
||||
while !rend.should_close() {
|
||||
let dt = rend.get_delta_time() / 1000.0;
|
||||
if rend.raylib.0.is_key_down(KeyboardKey::KEY_A) {
|
||||
player.vel.x = VEL;
|
||||
}
|
||||
if rend.raylib.0.is_key_down(KeyboardKey::KEY_D) {
|
||||
player.vel.x = -VEL;
|
||||
}
|
||||
|
||||
if rend.raylib.0.is_key_down(KeyboardKey::KEY_SPACE) && world.is_on_ground(player.pos){
|
||||
player.vel.y = VEL;
|
||||
}
|
||||
|
||||
player.calc_phisics(&world, dt);
|
||||
|
||||
// log::debug!("VEL: {:?}", player.vel);
|
||||
|
||||
rend.draw_world(&world, &player);
|
||||
}
|
||||
}
|
||||
36
src/player/mod.rs
Normal file
36
src/player/mod.rs
Normal file
@@ -0,0 +1,36 @@
|
||||
use raylib::math::Vector2;
|
||||
|
||||
use crate::world::World;
|
||||
|
||||
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Player {
|
||||
pub pos: Vector2,
|
||||
pub vel: Vector2
|
||||
}
|
||||
|
||||
impl Player {
|
||||
pub fn new(pos: Vector2) -> Self {
|
||||
Self { pos, vel: (0.0, 0.0).into() }
|
||||
}
|
||||
|
||||
pub fn calc_phisics(&mut self, world: &World, dt: f32) {
|
||||
self.pos += self.vel * dt;
|
||||
|
||||
self.vel.x *= 0.7;
|
||||
self.vel.y *= 0.7;
|
||||
if self.vel.x.abs() < 1.0 {
|
||||
self.vel.x = 0.0;
|
||||
}
|
||||
if self.vel.y.abs() < 1.0 {
|
||||
self.vel.y = 0.0;
|
||||
}
|
||||
|
||||
self.check_collisions(world);
|
||||
}
|
||||
|
||||
fn check_collisions(&mut self, world: &World) {
|
||||
|
||||
}
|
||||
}
|
||||
76
src/renderer/mod.rs
Normal file
76
src/renderer/mod.rs
Normal file
@@ -0,0 +1,76 @@
|
||||
|
||||
use raylib::{math::Vector2, prelude::*};
|
||||
use crate::{player::Player, world::{chunk::CHUNK_WIDTH, id::BlockId, World}};
|
||||
|
||||
const SCREEN_BLOCK_WIDTH: f32 = 64.0;
|
||||
|
||||
pub struct Renderer {
|
||||
pub raylib: (RaylibHandle, RaylibThread),
|
||||
}
|
||||
|
||||
impl Renderer {
|
||||
pub fn init() -> Self {
|
||||
let (rl, thread) = raylib::init()
|
||||
.vsync()
|
||||
.msaa_4x()
|
||||
.resizable()
|
||||
.size(640, 480)
|
||||
.title("Minecwaft :3")
|
||||
.log_level(raylib::ffi::TraceLogLevel::LOG_NONE)
|
||||
.build();
|
||||
Self { raylib: (rl, thread) }
|
||||
}
|
||||
|
||||
pub fn should_close(&self) -> bool {
|
||||
self.raylib.0.window_should_close()
|
||||
}
|
||||
|
||||
pub fn draw_world(&mut self, world: &World, player: &Player) {
|
||||
let (rl, thread) = &mut self.raylib;
|
||||
let scrn_wh: Vector2 = (rl.get_screen_width() as f32, rl.get_screen_height() as f32).into();
|
||||
|
||||
let mut rl_draw = rl.begin_drawing(&thread);
|
||||
rl_draw.clear_background(Color::BLUE);
|
||||
|
||||
let block_wh = scrn_wh.x as f32 / SCREEN_BLOCK_WIDTH;
|
||||
// let player_pos: Vector2;
|
||||
{ // Player
|
||||
let scrn_mid: Vector2 = ((scrn_wh.x/2.0) as f32, (scrn_wh.y/2.0) as f32).into();
|
||||
// player_pos = (scrn_mid.x + block_wh/2.0, scrn_mid.y).into();
|
||||
let player_draw_pos: Vector2 = (scrn_mid.x + block_wh/2.0, scrn_mid.y + block_wh*2.0).into();
|
||||
|
||||
let player_sz = Vector2::new(block_wh, block_wh*2.0);
|
||||
rl_draw.draw_rectangle_v(player_draw_pos, player_sz, Color::PINK);
|
||||
}
|
||||
|
||||
{ // World
|
||||
let block_sz = Vector2::new(block_wh, block_wh);
|
||||
|
||||
for (chunk_x, chunk) in world.chunks() {
|
||||
for ((rel_x, block_y), block) in chunk.blocks() {
|
||||
let block_x = (*chunk_x * CHUNK_WIDTH as isize) + *rel_x as isize;
|
||||
|
||||
let block_y = (*block_y as f32 - 1.0) + player.pos.y;
|
||||
let block_x = (block_x as f32) + player.pos.x;
|
||||
|
||||
let real_x = block_x as f32 * block_wh;
|
||||
let real_y = scrn_wh.y - (block_wh) - (block_y as f32 * block_wh);
|
||||
|
||||
let color = match block.id {
|
||||
BlockId::Dirt => Color::BROWN,
|
||||
BlockId::Grass => Color::GREEN,
|
||||
BlockId::Stone => Color::GRAY,
|
||||
BlockId::Bedrock => Color::BLACK,
|
||||
};
|
||||
rl_draw.draw_rectangle_v(Vector2::new(real_x, real_y), block_sz, color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
pub fn get_delta_time(&self) -> f32 {
|
||||
self.raylib.0.get_frame_time()
|
||||
}
|
||||
|
||||
}
|
||||
11
src/world/block/mod.rs
Normal file
11
src/world/block/mod.rs
Normal file
@@ -0,0 +1,11 @@
|
||||
use super::id::BlockId;
|
||||
|
||||
pub struct Block {
|
||||
pub id: BlockId,
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
73
src/world/chunk.rs
Normal file
73
src/world/chunk.rs
Normal file
@@ -0,0 +1,73 @@
|
||||
use std::collections::HashMap;
|
||||
|
||||
use nalgebra::Vector2;
|
||||
|
||||
use super::{block::Block, id::BlockId};
|
||||
|
||||
|
||||
pub const CHUNK_WIDTH: usize = 32;
|
||||
pub const CHUNK_HEIGHT: usize = 512;
|
||||
const DIRT_LEVEL: u8 = 5;
|
||||
|
||||
pub struct Chunk {
|
||||
blocks: HashMap<(u8, u8), Block>,
|
||||
}
|
||||
|
||||
impl Chunk {
|
||||
pub fn new_empty() -> Self {
|
||||
Self {
|
||||
blocks: HashMap::new()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_flat(surface_level: u8) -> Self {
|
||||
let mut w = Self::new_empty();
|
||||
for i in 0..CHUNK_WIDTH {
|
||||
w.add_block(BlockId::Grass, (i as u8, surface_level));
|
||||
}
|
||||
|
||||
if surface_level < DIRT_LEVEL { return w; }
|
||||
|
||||
for y in 1..=DIRT_LEVEL {
|
||||
for x in 0..CHUNK_WIDTH {
|
||||
|
||||
let rv;
|
||||
if y < 4 {
|
||||
rv = 0.0
|
||||
} else {
|
||||
rv = rand::random::<f32>() * (y / 2) as f32;
|
||||
}
|
||||
|
||||
let id;
|
||||
if rv > 0.6 {
|
||||
id = BlockId::Stone;
|
||||
} else {
|
||||
id = BlockId::Dirt;
|
||||
}
|
||||
|
||||
w.add_block(id, (x as u8, surface_level-y));
|
||||
}
|
||||
}
|
||||
|
||||
for y in 1..surface_level-DIRT_LEVEL {
|
||||
for x in 0..CHUNK_WIDTH {
|
||||
w.add_block(BlockId::Stone, (x as u8, y));
|
||||
}
|
||||
}
|
||||
|
||||
w
|
||||
}
|
||||
|
||||
pub fn add_block(&mut self, id: BlockId, pos: (u8, u8)) {
|
||||
self.blocks.insert(pos, Block { id });
|
||||
}
|
||||
|
||||
pub fn blocks(&self) -> &HashMap<(u8, u8), Block> {
|
||||
&self.blocks
|
||||
}
|
||||
|
||||
pub fn blocks_mut(&mut self) -> &mut HashMap<(u8, u8), Block> {
|
||||
&mut self.blocks
|
||||
}
|
||||
}
|
||||
|
||||
8
src/world/entity.rs
Normal file
8
src/world/entity.rs
Normal file
@@ -0,0 +1,8 @@
|
||||
use nalgebra::Vector2;
|
||||
|
||||
|
||||
pub struct Entity {
|
||||
id: String,
|
||||
pos: Vector2<f32>,
|
||||
}
|
||||
|
||||
8
src/world/id/block.rs
Normal file
8
src/world/id/block.rs
Normal file
@@ -0,0 +1,8 @@
|
||||
|
||||
#[repr(usize)]
|
||||
pub enum BlockId {
|
||||
Grass = 0,
|
||||
Dirt,
|
||||
Stone,
|
||||
Bedrock
|
||||
}
|
||||
5
src/world/id/entity.rs
Normal file
5
src/world/id/entity.rs
Normal file
@@ -0,0 +1,5 @@
|
||||
|
||||
#[repr(usize)]
|
||||
pub enum EntityId {
|
||||
Cat = 0,
|
||||
}
|
||||
5
src/world/id/mod.rs
Normal file
5
src/world/id/mod.rs
Normal file
@@ -0,0 +1,5 @@
|
||||
mod block;
|
||||
mod entity;
|
||||
|
||||
pub use block::*;
|
||||
pub use entity::*;
|
||||
59
src/world/mod.rs
Normal file
59
src/world/mod.rs
Normal file
@@ -0,0 +1,59 @@
|
||||
use std::collections::HashMap;
|
||||
|
||||
use raylib::math::Vector2;
|
||||
|
||||
use self::chunk::{Chunk, CHUNK_WIDTH};
|
||||
|
||||
|
||||
pub mod chunk;
|
||||
mod entity;
|
||||
mod block;
|
||||
pub mod id;
|
||||
|
||||
pub struct World {
|
||||
chunks: HashMap<isize, chunk::Chunk>,
|
||||
entities: Vec<entity::Entity>
|
||||
}
|
||||
|
||||
|
||||
impl World {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
chunks: HashMap::new(),
|
||||
entities: Vec::new()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn generate_new(&mut self, surface_level: u8) {
|
||||
self.chunks.clear();
|
||||
self.entities.clear();
|
||||
for i in -2..=2 {
|
||||
self.chunks.insert(i, Chunk::new_flat(surface_level));
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_on_ground(&self, pos: Vector2) -> bool {
|
||||
let chunk_id = pos.x / CHUNK_WIDTH as f32;
|
||||
let rel_pos_x = pos.x % CHUNK_WIDTH as f32;
|
||||
|
||||
let Some(chunk) = self.chunks().get(&(chunk_id as isize)) else {
|
||||
return false;
|
||||
};
|
||||
|
||||
let Some(((_, by), _)) = chunk.blocks().get_key_value(&(rel_pos_x as u8, pos.y as u8)) else {
|
||||
return false;
|
||||
};
|
||||
|
||||
log::debug!("by: {}, py: {}", by, pos.y);
|
||||
|
||||
*by as u8 == pos.y as u8
|
||||
}
|
||||
|
||||
pub fn chunks(&self) -> &HashMap<isize, chunk::Chunk> {
|
||||
&self.chunks
|
||||
}
|
||||
|
||||
pub fn chunks_mut(&mut self) -> &mut HashMap<isize, chunk::Chunk> {
|
||||
&mut self.chunks
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user