rstnode: create small graphics example

wip/yesman
Katharina Fey 3 years ago
parent cf9392a33b
commit a6a1949914
Signed by: kookie
GPG Key ID: 90734A9E619C8A6C
  1. 1696
      games/rstnode/Cargo.lock
  2. 5
      games/rstnode/rst-client/Cargo.toml
  3. 1
      games/rstnode/rst-client/src/cli.rs
  4. 5
      games/rstnode/rst-client/src/constants.rs
  5. 30
      games/rstnode/rst-client/src/ctx.rs
  6. 43
      games/rstnode/rst-client/src/graphics/entities/mod.rs
  7. 16
      games/rstnode/rst-client/src/graphics/mod.rs
  8. 1
      games/rstnode/rst-client/src/graphics/ui/mod.rs
  9. 21
      games/rstnode/rst-client/src/main.rs
  10. 73
      games/rstnode/rst-client/src/settings.rs
  11. 48
      games/rstnode/rst-client/src/state.rs
  12. 10
      games/rstnode/rst-client/src/window.rs
  13. 7
      games/rstnode/rst-core/src/data.rs
  14. 2
      games/rstnode/rst-core/src/lib.rs
  15. 6
      games/rstnode/shell.nix

File diff suppressed because it is too large Load Diff

@ -8,4 +8,7 @@ authors = ["Bread Machine", "Katharina Fey <kookie@spacekookie.de>"]
[dependencies]
rst-core = { path = "../rst-core" }
ggez = "0.5"
clap = "2.0"
ggez = "0.6.0-rc0"
mint = "0.5" # Required because ggez is trash

@ -0,0 +1 @@
//! Handle user CLI inputs

@ -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");

@ -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()
})
}

@ -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(())
}
}

@ -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;
}

@ -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);
}

@ -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,
}
}
}

@ -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)
}
}

@ -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)
}

@ -1,14 +1,13 @@
//! Data structures for the game
#![allow(unused)]
use crate::io::Io;
use async_std::sync::Arc;
use rand::seq::SliceRandom;
use rand::thread_rng;
use serde::{Deserialize, Serialize};
use std::{
collections::BTreeMap,
sync::atomic::{AtomicBool, AtomicU16, AtomicU32},
};
use std::sync::atomic::{AtomicBool, AtomicU16, AtomicU32};
pub type NodeId = usize;

@ -1,4 +1,4 @@
//! # RST Node
//! # RST Node Core
//!
//! RST Node is a real-time strategy game about computers on a
//! network, fighting for dominance against a set of other network

@ -1,7 +1,7 @@
with import <nixpkgs> {};
stdenv.mkDerivation {
name = "rstnode";
mkShell rec {
name = "rstnode-shell";
buildInputs = with pkgs; [
rustc cargo clangStdenv rust-analyzer rustfmt
alsaLib pkg-config libudev
@ -18,4 +18,6 @@ stdenv.mkDerivation {
libxcb
libxkbcommon
]);
LD_LIBRARY_PATH = (lib.makeLibraryPath buildInputs);
}

Loading…
Cancel
Save