From 9642194faca119bcf48a4c94d7f55da3fd4c4277 Mon Sep 17 00:00:00 2001 From: SimonFJ20 Date: Mon, 1 Apr 2024 04:51:30 +0200 Subject: [PATCH] whaaaaaaaaaaaa --- src/engine.rs | 150 ++++++++++++++++++++++++++++++++++++++++---- src/main.rs | 37 +++++++++-- textures/dirt.png | Bin 0 -> 333 bytes textures/grass.png | Bin 0 -> 398 bytes textures/player.png | Bin 0 -> 1189 bytes 5 files changed, 169 insertions(+), 18 deletions(-) create mode 100644 textures/dirt.png create mode 100644 textures/grass.png create mode 100644 textures/player.png diff --git a/src/engine.rs b/src/engine.rs index a37da1b..62dffe6 100644 --- a/src/engine.rs +++ b/src/engine.rs @@ -1,17 +1,16 @@ -use std::time::Duration; +use std::{path::Component, time::Duration}; use sdl2::{ - event::Event, keyboard::Keycode, pixels::Color, render::Canvas, video::Window, Sdl, - VideoSubsystem, + event::Event, + image::{self, LoadTexture, Sdl2ImageContext}, + keyboard::Keycode, + pixels::Color, + rect::Rect, + render::{Canvas, Texture, TextureCreator}, + video::{Window, WindowBuildError, WindowContext}, + IntegerOrSdlError, Sdl, VideoSubsystem, }; -pub struct Game { - sdl_context: Sdl, - video_subsystem: VideoSubsystem, - canvas: Canvas, - event_pump: sdl2::EventPump, -} - #[derive(Debug, Clone)] pub struct Error(String); @@ -21,29 +20,143 @@ impl std::fmt::Display for Error { } } -impl From for Error { - fn from(value: T) -> Self { - Self(value.to_string()) +macro_rules! impl_from_T_for_Error { + ($t:ty) => { + impl From<$t> for Error { + fn from(value: $t) -> Self { + Self(value.to_string()) + } + } + }; + ($t:ty, $($ts:ty),+) => { + impl From<$t> for Error { + fn from(value: $t) -> Self { + Self(value.to_string()) + } + } + impl_from_T_for_Error!($($ts),+); + }; +} + +impl_from_T_for_Error!(String, WindowBuildError, IntegerOrSdlError); + +static RANDOM_U64_COUNTER: u64 = 0; + +pub struct Entity(u64); + +pub trait Component {} + +pub struct Sprite<'a> { + texture: Texture<'a>, +} + +pub struct Context<'a> { + id_counter: &'a mut u64, + canvas: &'a mut Canvas, + texture_creator: &'a TextureCreator, + entities: &'a mut Vec, + components: &'a mut Vec<(u64, Box)>, + systems: &'a mut Vec>, +} + +impl<'a> Context<'a> { + pub fn load_sprite<'b, P>(&self, path: P) -> Result, Error> + where + 'a: 'b, + P: AsRef, + { + let texture = self.texture_creator.load_texture(path)?; + Ok(Sprite { texture }) } + + pub fn draw_sprite<'b>(&mut self, sprite: &Sprite<'b>, x: i32, y: i32) -> Result<(), Error> { + self.canvas.copy( + &sprite.texture, + None, + Rect::new( + x * 4, + y * 4, + sprite.texture.query().width * 4, + sprite.texture.query().height * 4, + ), + )?; + Ok(()) + } + + pub fn spawn(&mut self, components: Vec>) { + let id = *self.id_counter; + *self.id_counter += 1; + self.entities.push(Entity(id)); + self.components + .extend(components.into_iter().map(|component| (id, component))); + } + + pub fn add_system(&mut self, system: Box) { + system.on_add(self); + self.systems.push(system) + } + + pub fn query bool>(&mut self, predicate: F) -> Vec { + let mut entities = Vec::::new(); + for entity in &mut *self.entities { + if predicate(entity.0) { + entities.push(entity.0) + } + } + entities + } + + pub fn has_component(&mut self, entity_id: u64) -> bool { + for (id, component) in self.components {} + } +} + +pub trait System { + fn on_add(&self, _ctx: &mut Context) {} + fn on_update(&self, _ctx: &mut Context) {} +} + +pub struct Game { + id_counter: u64, + sdl_context: Sdl, + video_subsystem: VideoSubsystem, + image_context: Sdl2ImageContext, + canvas: Canvas, + texture_creator: TextureCreator, + event_pump: sdl2::EventPump, + entities: Vec, + components: Vec<(u64, Box)>, + systems: Vec>, } impl Game { pub fn new() -> Result { let sdl_context = sdl2::init()?; let video_subsystem = sdl_context.video()?; + let image_context = image::init(image::InitFlag::PNG)?; let window = video_subsystem .window("pvp-game-dilapidation", 1280, 720) .position_centered() .build()?; + let mut canvas = window.into_canvas().build()?; + let texture_creator = canvas.texture_creator(); + canvas.set_draw_color(Color::RGB(60, 180, 180)); canvas.clear(); + canvas.present(); let event_pump = sdl_context.event_pump()?; Ok(Self { + id_counter: 0, sdl_context, video_subsystem, + image_context, canvas, + texture_creator, event_pump, + entities: vec![], + components: vec![], + systems: vec![], }) } @@ -64,4 +177,15 @@ impl Game { self.canvas.present(); std::thread::sleep(Duration::new(0, 1_000_000_000u32 / 60)) } + + pub fn context<'a>(&'a mut self) -> Context<'a> { + Context { + id_counter: &mut self.id_counter, + canvas: &mut self.canvas, + texture_creator: &self.texture_creator, + entities: &mut self.entities, + components: &mut self.components, + systems: &mut self.systems, + } + } } diff --git a/src/main.rs b/src/main.rs index 66ace41..fc70348 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,8 +1,35 @@ -#[allow(dead_code)] +#![allow(dead_code)] + +use engine::{Component, Sprite, System}; mod engine; -fn main() { - let game = engine::Game::new().unwrap(); - game.run(); - println!("Hello, world!"); +struct Player<'a> { + sprite: Option>, +} + +impl<'a> Component for Player<'a> {} + +struct PlayerRenderer; + +impl System for PlayerRenderer { + fn on_add(&self, ctx: &mut engine::Context) { + for entity in ctx.query(|id| ) {} + } + + fn on_update(&self, _ctx: &mut engine::Context) {} +} + +fn main() { + let mut game = engine::Game::new().unwrap(); + + { + let mut context = game.context(); + context.add_system(Box::new(PlayerRenderer)); + context.spawn(vec![Box::new(Player { sprite: None })]); + + // let sprite = context.load_sprite("textures/player.png").unwrap(); + // context.draw_sprite(&sprite, 16, 16).unwrap(); + } + + game.run(); } diff --git a/textures/dirt.png b/textures/dirt.png new file mode 100644 index 0000000000000000000000000000000000000000..2255474e9429054a1be73d08e858861e7b1a82a9 GIT binary patch literal 333 zcmV-T0kZyyP)Dg|iN963p&~L|?_vg!g5Wyrnqw z-J}H4gZW(FPDk?i()Y1Yfhos)0l+cG5F&sWARJY2A(@3lRt0_vKo4f~C8=BwQ|EaR fz7Ty0s7d$&WvgSod1#K`00000NkvXXu0mjfsNIJ( literal 0 HcmV?d00001 diff --git a/textures/grass.png b/textures/grass.png new file mode 100644 index 0000000000000000000000000000000000000000..e7736981472382982b9f61940d12ae24894ddba8 GIT binary patch literal 398 zcmV;90df9`P)!2zg%#u2V6S(u!ok8>BujuKd@{a@ zY)IbACV3lUeHtgA5oWd#MlRDi9iD|I2_skd-<$v>r4x+y0mNW{x&0-GClF&{)Na={3sv246(EbUJP=t55?d8Gi`^O>z_ z112xnHfgB;_LKVM$~ zJAa;FqiZKkaT>uxZ-3d*RB7`V2C|SQiFd3+FKpu%IG4j>k0#)0_ zag2bvtC1;Q$kq6JK(>}Nehp=_*t!qU0z{3kb046BIu}4QAhZQ#j|^Et3Lyb1#G=q% s3;tgKbwF8bt|fqysnmtWw?NhjKMB=>nb#maVgLXD07*qoM6N<$f}X~pPXGV_ literal 0 HcmV?d00001 diff --git a/textures/player.png b/textures/player.png new file mode 100644 index 0000000000000000000000000000000000000000..881d686c0b6072a2f5c114b389103c7e79883c2c GIT binary patch literal 1189 zcmV;W1X}xvP)g(^ls`r}c6xXj`hln(q_a0Fc zfyS`9x(aJ8oO7+QI-WgyhQq@{IOkfnMFd3DSP$<##xWX=S`!C@0Yn5lJ3C z))u_?6h#p+^HiGv$T@e?+1%Wm>Z`g6-g_`JmY0_?91f?tY-?)^d7jTypb>2x}T87JX9sO*gY z)?uxsm6esR527e)NmTt#YLg`G_xt$p;R7B%d{|vv)!l*5pFcO|K6vl|s52{yqOoC? zWnppEm^oa%<0P!LVVs$vwGLy(nAS0mq6i{_@lb{_hP2jXttDnAt#zePnB<%zr4)^$ z{tQ59Ns^E;CX8iSMnzGathsdQ61?}-TT!>$B@sCZ5Tzy_x4N-usFM*9VrF{%`ZXz~ zNJL0$O>=W|M9hq$DDeLMdn8E`q)|!*sf{rWd8b`4^*P;cH>^*Rq~YGmEg_vVbHhg> z(%7i#SFNU4V@;Z-U}h+#8XHyw>cM^W>eXf%XJ!~CdyF}RH~y9$_on%q*F!7o%@opn3+U`MC5CFB_it`(cUh_-q8=sKT({X-D<|bwQJWJ{x?W`#h+}M;ynvefu_y zF(5jrz9tp1EmY?}%QC!t`LY#!vo_aSLn(zS&ClAWeVqp~cg8f0cFih|NKrMq|UlGb{9<#JXW9UX;)au#=p2nK@z%Cfwe{9e^~M092X z)>_1I{7nL9lE-@wtu6g*WZ-Q~)v?6lOO