aboutsummaryrefslogtreecommitdiff
path: root/games/rstnode/rst-client
diff options
context:
space:
mode:
authorKatharina Fey <kookie@spacekookie.de>2021-02-06 22:54:28 +0100
committerKatharina Fey <kookie@spacekookie.de>2021-02-06 22:54:28 +0100
commita6a1949914fb2074fb5fec9c75b075eac369541f (patch)
treea112f4ce0e88298c1d8a25c504d7a0478a0c39dc /games/rstnode/rst-client
parentcf9392a33bb99ae581f818d3ddb8be1231521a02 (diff)
rstnode: create small graphics example
Diffstat (limited to 'games/rstnode/rst-client')
-rw-r--r--games/rstnode/rst-client/Cargo.toml5
-rw-r--r--games/rstnode/rst-client/src/cli.rs1
-rw-r--r--games/rstnode/rst-client/src/constants.rs5
-rw-r--r--games/rstnode/rst-client/src/ctx.rs30
-rw-r--r--games/rstnode/rst-client/src/graphics/entities/mod.rs43
-rw-r--r--games/rstnode/rst-client/src/graphics/mod.rs16
-rw-r--r--games/rstnode/rst-client/src/graphics/ui/mod.rs1
-rw-r--r--games/rstnode/rst-client/src/main.rs21
-rw-r--r--games/rstnode/rst-client/src/settings.rs73
-rw-r--r--games/rstnode/rst-client/src/state.rs48
-rw-r--r--games/rstnode/rst-client/src/window.rs10
11 files changed, 251 insertions, 2 deletions
diff --git a/games/rstnode/rst-client/Cargo.toml b/games/rstnode/rst-client/Cargo.toml
index 7ebf7092d0a0..eae6672cd51d 100644
--- a/games/rstnode/rst-client/Cargo.toml
+++ b/games/rstnode/rst-client/Cargo.toml
@@ -8,4 +8,7 @@ authors = ["Bread Machine", "Katharina Fey <kookie@spacekookie.de>"]
[dependencies]
rst-core = { path = "../rst-core" }
-ggez = "0.5" \ No newline at end of file
+
+clap = "2.0"
+ggez = "0.6.0-rc0"
+mint = "0.5" # Required because ggez is trash \ No newline at end of file
diff --git a/games/rstnode/rst-client/src/cli.rs b/games/rstnode/rst-client/src/cli.rs
new file mode 100644
index 000000000000..b8a93b237a7b
--- /dev/null
+++ b/games/rstnode/rst-client/src/cli.rs
@@ -0,0 +1 @@
+//! Handle user CLI inputs
diff --git a/games/rstnode/rst-client/src/constants.rs b/games/rstnode/rst-client/src/constants.rs
new file mode 100644
index 000000000000..e40a5c35c5db
--- /dev/null
+++ b/games/rstnode/rst-client/src/constants.rs
@@ -0,0 +1,5 @@
+
+
+pub const NAME: &'static str = "RST Node";
+pub const VERSION: &'static str = env!("CARGO_PKG_VERSION");
+pub const AUTHORS: &'static str = env!("CARGO_PKG_AUTHORS");
diff --git a/games/rstnode/rst-client/src/ctx.rs b/games/rstnode/rst-client/src/ctx.rs
new file mode 100644
index 000000000000..7590867f18e2
--- /dev/null
+++ b/games/rstnode/rst-client/src/ctx.rs
@@ -0,0 +1,30 @@
+//! Small context builder
+
+use crate::{
+ constants::{AUTHORS, NAME, VERSION},
+ GameSettings,
+};
+
+use ggez::{
+ conf::{WindowMode, WindowSetup},
+ ContextBuilder,
+};
+
+/// Construct a context builder with default & user window settings
+pub fn build(settings: &GameSettings) -> ContextBuilder {
+ ContextBuilder::new(NAME, AUTHORS)
+ .window_setup(WindowSetup {
+ title: format!("{} (v{})", NAME, VERSION),
+ samples: (&settings.graphics.samples).into(),
+ vsync: settings.graphics.vsync,
+ icon: "".into(),
+ srgb: true,
+ })
+ .window_mode(WindowMode {
+ width: settings.window.width as f32,
+ height: settings.window.height as f32,
+ maximized: settings.window.window_mode.maximized(),
+ fullscreen_type: settings.window.window_mode._type(),
+ ..Default::default()
+ })
+}
diff --git a/games/rstnode/rst-client/src/graphics/entities/mod.rs b/games/rstnode/rst-client/src/graphics/entities/mod.rs
new file mode 100644
index 000000000000..168f40d2aeee
--- /dev/null
+++ b/games/rstnode/rst-client/src/graphics/entities/mod.rs
@@ -0,0 +1,43 @@
+//! Game entity rendering
+//!
+//! Generally the naming convention should be: `{type}Rndr`
+//! (`Renderer`, but shorter).
+
+use super::prelude::*;
+
+use rst_core::data::Node;
+use std::sync::Arc;
+
+/// A set of universal X/Y coordinates
+pub struct Coordinates(pub f32, pub f32);
+
+impl<'a> From<&'a Coordinates> for Point2<f32> {
+ fn from(c: &'a Coordinates) -> Self {
+ Point2 { x: c.0, y: c.1 }
+ }
+}
+
+pub struct NodeRndr {
+ pub loc: Coordinates,
+ pub inner: Arc<Node>,
+}
+
+impl EventHandler for NodeRndr {
+ fn update(&mut self, _: &mut Context) -> GameResult<()> {
+ Ok(())
+ }
+
+ fn draw(&mut self, ctx: &mut Context) -> GameResult<()> {
+ let circ = Mesh::new_circle(
+ ctx,
+ DrawMode::fill(),
+ Point2::from(&self.loc),
+ 35.0,
+ 0.1,
+ graphics::WHITE,
+ ).unwrap();
+
+ circ.draw(ctx, DrawParam::new()).unwrap();
+ Ok(())
+ }
+}
diff --git a/games/rstnode/rst-client/src/graphics/mod.rs b/games/rstnode/rst-client/src/graphics/mod.rs
new file mode 100644
index 000000000000..8118207d70af
--- /dev/null
+++ b/games/rstnode/rst-client/src/graphics/mod.rs
@@ -0,0 +1,16 @@
+//! Graphics module
+//!
+//! Each entity in the game has a graphics companion object in
+//! [`entities`](self::entities), which knows how to render a given
+//! object. Different game screens and UI elements can be found in
+//! [`ui`](self::ui).
+
+pub mod entities;
+pub mod ui;
+
+/// A utility module to include everything required to implement a
+/// graphics entity
+pub(self) mod prelude {
+ pub use ggez::{event::EventHandler, graphics::{self, Drawable, DrawParam, Mesh, DrawMode}, Context, GameResult};
+ pub use mint::Point2;
+}
diff --git a/games/rstnode/rst-client/src/graphics/ui/mod.rs b/games/rstnode/rst-client/src/graphics/ui/mod.rs
new file mode 100644
index 000000000000..3b63b5b9b0aa
--- /dev/null
+++ b/games/rstnode/rst-client/src/graphics/ui/mod.rs
@@ -0,0 +1 @@
+//! Different UI states
diff --git a/games/rstnode/rst-client/src/main.rs b/games/rstnode/rst-client/src/main.rs
index e7a11a969c03..9de33fce81c6 100644
--- a/games/rstnode/rst-client/src/main.rs
+++ b/games/rstnode/rst-client/src/main.rs
@@ -1,3 +1,22 @@
+mod cli;
+mod constants;
+mod ctx;
+mod graphics;
+mod settings;
+mod state;
+mod window;
+
+pub(crate) use settings::*;
+pub(crate) use state::*;
+
fn main() {
- println!("Hello, world!");
+ let settings = default();
+
+ let state = ClientState::new(&settings);
+ window::run(&settings, state)
+
+ // let my_game = GameState::new(&mut ctx);
+
+ // // Run!
+ // event::run(ctx, eloop, my_game);
}
diff --git a/games/rstnode/rst-client/src/settings.rs b/games/rstnode/rst-client/src/settings.rs
new file mode 100644
index 000000000000..971e8e6f50b7
--- /dev/null
+++ b/games/rstnode/rst-client/src/settings.rs
@@ -0,0 +1,73 @@
+//! Configuration structures for the game client
+
+use ggez::conf::{FullscreenType, NumSamples};
+
+pub fn default() -> GameSettings {
+ GameSettings {
+ window: WindowSettings {
+ width: 1280,
+ height: 720,
+ window_mode: WindowMode::Windowed,
+ },
+ graphics: GraphicsSettings {
+ samples: Samples(0),
+ vsync: true,
+ },
+ }
+}
+
+/// Complete tree of basic game client settings
+pub struct GameSettings {
+ pub window: WindowSettings,
+ pub graphics: GraphicsSettings,
+}
+
+/// Window setup specific settings
+pub struct WindowSettings {
+ pub width: u16,
+ pub height: u16,
+ pub window_mode: WindowMode,
+}
+
+/// Graphic settings
+pub struct GraphicsSettings {
+ pub samples: Samples,
+ pub vsync: bool,
+}
+
+pub struct Samples(pub u8);
+
+impl<'s> From<&'s Samples> for NumSamples {
+ fn from(s: &'s Samples) -> Self {
+ match s.0 {
+ 0 => Self::Zero,
+ 1 => Self::One,
+ 2 => Self::Two,
+ 4 => Self::Four,
+ 8 => Self::Eight,
+ 16 => Self::Sixteen,
+ _ => panic!("Invalid multisampling value: {}", s.0),
+ }
+ }
+}
+
+pub enum WindowMode {
+ Windowed,
+ Fullscreen,
+}
+
+impl WindowMode {
+ pub fn maximized(&self) -> bool {
+ match self {
+ Self::Fullscreen => true,
+ _ => false,
+ }
+ }
+
+ pub fn _type(&self) -> FullscreenType {
+ match self {
+ Self::Fullscreen => FullscreenType::Desktop,
+ Self::Windowed => FullscreenType::Windowed,
+ }
+ }
+}
diff --git a/games/rstnode/rst-client/src/state.rs b/games/rstnode/rst-client/src/state.rs
new file mode 100644
index 000000000000..c55dc2faa6d6
--- /dev/null
+++ b/games/rstnode/rst-client/src/state.rs
@@ -0,0 +1,48 @@
+//! Game client state handling
+
+use crate::{
+ graphics::entities::{Coordinates, NodeRndr},
+ GameSettings,
+};
+use ggez::{event::EventHandler, graphics, Context, GameResult};
+use rst_core::data::{Node, Owner, Upgrade};
+use std::sync::Arc;
+
+pub struct ClientState {
+ node: NodeRndr,
+}
+
+impl ClientState {
+ pub fn new(_settings: &GameSettings) -> Self {
+ Self {
+ node: NodeRndr {
+ loc: Coordinates(250.0, 250.0),
+ inner: Arc::new(Node {
+ id: 0,
+ health: 100.into(),
+ max_health: 100.into(),
+ owner: Owner::Neutral,
+ type_: Upgrade::Base,
+ links: 0,
+ link_states: vec![],
+ buffer: vec![],
+ }),
+ },
+ }
+ }
+}
+
+impl EventHandler for ClientState {
+ fn update(&mut self, _ctx: &mut Context) -> GameResult<()> {
+ Ok(())
+ }
+
+ fn draw(&mut self, ctx: &mut Context) -> GameResult<()> {
+ graphics::clear(ctx, graphics::Color::from_rgb(15, 15, 15));
+
+ // Render the node
+ self.node.draw(ctx).unwrap();
+
+ graphics::present(ctx)
+ }
+}
diff --git a/games/rstnode/rst-client/src/window.rs b/games/rstnode/rst-client/src/window.rs
new file mode 100644
index 000000000000..ad58c38e0ffb
--- /dev/null
+++ b/games/rstnode/rst-client/src/window.rs
@@ -0,0 +1,10 @@
+//! Basic window setup code
+
+use crate::{ctx, state::ClientState, GameSettings};
+use ggez::event;
+
+/// Start the main event loop with game settings and state
+pub fn run(settings: &GameSettings, state: ClientState) -> ! {
+ let (ctx, eloop) = ctx::build(settings).build().unwrap();
+ event::run(ctx, eloop, state)
+}