~comcloudway/little_town

d0dfce71aaaec3bc98fbcbb14c8e9d810989436d — Jakob Meier 1 year, 8 months ago
Initial commit, featuring a welcome screen
A  => .gitignore +5 -0
@@ 1,5 @@
target/
assets/base/
assets/exp/
assets/fonts/
assets/ui/

A  => Cargo.lock +401 -0
@@ 1,401 @@
# 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 = "ahash"
version = "0.7.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47"
dependencies = [
 "getrandom",
 "once_cell",
 "version_check",
]

[[package]]
name = "audir-sles"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ea47348666a8edb7ad80cbee3940eb2bccf70df0e6ce09009abe1a836cb779f5"

[[package]]
name = "audrey"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "58b92a84e89497e3cd25d3672cd5d1c288abaac02c18ff21283f17d118b889b8"
dependencies = [
 "dasp_frame",
 "dasp_sample",
 "hound",
 "lewton",
]

[[package]]
name = "autocfg"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"

[[package]]
name = "bitflags"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"

[[package]]
name = "bumpalo"
version = "3.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0d261e256854913907f67ed06efbc3338dfe6179796deefc1ff763fc1aee5535"

[[package]]
name = "bytemuck"
version = "1.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c041d3eab048880cb0b86b256447da3f18859a163c3b8d8893f4e6368abe6393"

[[package]]
name = "byteorder"
version = "1.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"

[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"

[[package]]
name = "color_quant"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b"

[[package]]
name = "crc32fast"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d"
dependencies = [
 "cfg-if",
]

[[package]]
name = "dasp_frame"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b2a3937f5fe2135702897535c8d4a5553f8b116f76c1529088797f2eee7c5cd6"
dependencies = [
 "dasp_sample",
]

[[package]]
name = "dasp_sample"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0c87e182de0887fd5361989c677c4e8f5000cd9491d6d563161a8f3a5519fc7f"

[[package]]
name = "flate2"
version = "1.0.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a8a2db397cb1c8772f31494cb8917e48cd1e64f0fa7efac59fbd741a0a8ce841"
dependencies = [
 "crc32fast",
 "miniz_oxide",
]

[[package]]
name = "fontdue"
version = "0.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6a62391ecb864cf12ed06b2af4eda2e609b97657950d6a8f06841b17726ab253"
dependencies = [
 "hashbrown",
 "ttf-parser",
]

[[package]]
name = "getrandom"
version = "0.2.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31"
dependencies = [
 "cfg-if",
 "libc",
 "wasi",
]

[[package]]
name = "glam"
version = "0.21.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "518faa5064866338b013ff9b2350dc318e14cc4fcd6cb8206d7e7c9886c98815"

[[package]]
name = "hashbrown"
version = "0.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e"
dependencies = [
 "ahash",
]

[[package]]
name = "hound"
version = "3.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4d13cdbd5dbb29f9c88095bbdc2590c9cba0d0a1269b983fef6b2cdd7e9f4db1"

[[package]]
name = "image"
version = "0.24.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "69b7ea949b537b0fd0af141fff8c77690f2ce96f4f41f042ccb6c69c6c965945"
dependencies = [
 "bytemuck",
 "byteorder",
 "color_quant",
 "num-rational",
 "num-traits",
 "png",
]

[[package]]
name = "lewton"
version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8d542c1a317036c45c2aa1cf10cc9d403ca91eb2d333ef1a4917e5cb10628bd0"
dependencies = [
 "byteorder",
 "ogg",
 "smallvec",
]

[[package]]
name = "libc"
version = "0.2.139"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79"

[[package]]
name = "little_town"
version = "0.0.1"
dependencies = [
 "macroquad",
]

[[package]]
name = "macroquad"
version = "0.3.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f3790f7fd2e4c480108cbfc86488f023b72e1e0bb6ffd5c6cba38049c7e2fbfc"
dependencies = [
 "bumpalo",
 "fontdue",
 "glam",
 "image",
 "macroquad_macro",
 "miniquad",
 "quad-rand",
 "quad-snd",
]

[[package]]
name = "macroquad_macro"
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f5cecfede1e530599c8686f7f2d609489101d3d63741a6dc423afc997ce3fcc8"

[[package]]
name = "malloc_buf"
version = "0.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "62bb907fe88d54d8d9ce32a3cceab4218ed2f6b7d35617cafe9adf84e43919cb"
dependencies = [
 "libc",
]

[[package]]
name = "maybe-uninit"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00"

[[package]]
name = "miniquad"
version = "0.3.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "46381fe09fbf91bfa402a3e4fc26a104c9130562d51f89964c46adbc00591496"
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 = "ndk-sys"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e1bcdd74c20ad5d95aacd60ef9ba40fdf77f767051040541df557b7a9b2a2121"

[[package]]
name = "num-integer"
version = "0.1.45"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9"
dependencies = [
 "autocfg",
 "num-traits",
]

[[package]]
name = "num-rational"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0"
dependencies = [
 "autocfg",
 "num-integer",
 "num-traits",
]

[[package]]
name = "num-traits"
version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd"
dependencies = [
 "autocfg",
]

[[package]]
name = "objc"
version = "0.2.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "915b1b472bc21c53464d6c8461c9d3af805ba1ef837e1cac254428f4a77177b1"
dependencies = [
 "malloc_buf",
]

[[package]]
name = "ogg"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "13e571c3517af9e1729d4c63571a27edd660ade0667973bfc74a67c660c2b651"
dependencies = [
 "byteorder",
]

[[package]]
name = "once_cell"
version = "1.17.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3"

[[package]]
name = "png"
version = "0.17.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5d708eaf860a19b19ce538740d2b4bdeeb8337fa53f7738455e706623ad5c638"
dependencies = [
 "bitflags",
 "crc32fast",
 "flate2",
 "miniz_oxide",
]

[[package]]
name = "quad-alsa-sys"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c66c2f04a6946293477973d85adc251d502da51c57b08cd9c997f0cfd8dcd4b5"
dependencies = [
 "libc",
]

[[package]]
name = "quad-rand"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "658fa1faf7a4cc5f057c9ee5ef560f717ad9d8dc66d975267f709624d6e1ab88"

[[package]]
name = "quad-snd"
version = "0.2.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "53c954bb70493a2872775b74b663a767686e6d96d242e789d6a92cc4ebd2a64e"
dependencies = [
 "audir-sles",
 "audrey",
 "libc",
 "quad-alsa-sys",
 "winapi",
]

[[package]]
name = "smallvec"
version = "0.6.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b97fcaeba89edba30f044a10c6a3cc39df9c3f17d7cd829dd1446cab35f890e0"
dependencies = [
 "maybe-uninit",
]

[[package]]
name = "ttf-parser"
version = "0.15.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7b3e06c9b9d80ed6b745c7159c40b311ad2916abb34a49e9be2653b90db0d8dd"

[[package]]
name = "version_check"
version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"

[[package]]
name = "wasi"
version = "0.11.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"

[[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"

A  => Cargo.toml +14 -0
@@ 1,14 @@
[package]
name = "little_town"
description = "Build a small isometric town"
version = "0.0.1"
edition = "2021"
authors = [ "Jakob Meier <comcloudway@ccw.icu>" ]
readme = "README.org"
homepage = "https://codeberg.org/comcloudway/little_town"
repository = "https://codeberg.org/comcloudway/little_town"
license = "AGPL-3.0-or-later"
keywords = ["game", "isometric", "town", "macroquad"]

[dependencies]
macroquad = "0.3.25"

A  => README.org +11 -0
@@ 1,11 @@
* Little Town
Build a small isometric town.

** Credits
The Assets were created by [[][Kenney]]
and are licensed under [[https://creativecommons.org/publicdomain/zero/1.0/][CC0 1.0 Universal]].
See below or a detailed list:
- [[https://kenney.nl/assets/sketch-town][Sketch Town]] assets pack
- [[Sketch Town Expansion][Sketch Town Expansion]] asset pack
- [[https://kenney.nl/assets/ui-pack-rpg-expansion][UI Pack: RPG Expansion]] asset pack
- [[pack 3 done][Kenney Fonts]]

A  => assets/.gitkeep +0 -0
A  => fetch-assets.sh +46 -0
@@ 1,46 @@
#!/bin/bash

# delete old assets
rm -rf assets/
# enable failsafe
set -e

# fetch the base pack
echo "⏳ Downloading Sketch Town base pack"
echo "from https://kenney.nl/assets/sketch-town"
mkdir -p assets/base
wget https://kenney.nl/content/3-assets/31-sketch-town/kenney_sketchtown_1.zip \
    -O assets/base.zip
unzip assets/base.zip -d assets/base
rm assets/base.zip
echo "✅ Extracting pack 1 done"

# fetch the expansion pack
echo "⏳ Downloading Sketch Town Expansion pack"
echo "from https://kenney.nl/assets/sketch-town-expansion"
mkdir -p assets/exp
wget https://kenney.nl/content/3-assets/17-sketch-town-expansion/kenney_sketchtownexpansion.zip \
    -O assets/exp.zip
unzip assets/exp.zip -d assets/exp
rm assets/exp.zip
echo "✅ Extracting pack 2 done"

# fetch ui pack
echo "⏳ Downloading RPG UI Pack"
echo "from https://kenney.nl/assets/ui-pack-rpg-expansion"
mkdir -p assets/ui
wget https://kenney.nl/content/3-assets/164-ui-pack-rpg-expansion/uipack-rpg.zip \
    -O assets/ui.zip
unzip assets/ui.zip -d assets/ui
rm assets/ui.zip
echo "✅ Extracting pack 3 done"

# fetch font
echo "⏳ Downloading Kenney Fonts"
echo "from https://kenney.nl/assets/kenney-fonts"
mkdir -p assets/fonts
wget https://kenney.nl/content/3-assets/137-kenney-fonts/kenney_fontpackage.zip \
    -O assets/fonts.zip
unzip assets/fonts.zip -d assets/fonts
rm assets/fonts.zip
echo "✅ Extracting fonts done"

A  => src/main.rs +54 -0
@@ 1,54 @@
use macroquad::prelude::*;

mod screens;
mod textures;
mod types;

use types::{
    GameComponent,
    GameEvent
};
use textures::AssetStore;
use screens::welcome::WelcomeScreen;
use screens::build::BuildScreen;

enum Screen {
    Welcome(WelcomeScreen),
    Build(BuildScreen)
}
impl GameComponent for Screen {
    fn draw(&self, assets: &AssetStore) {
        match self {
            Screen::Welcome(w) => w.draw(&assets),
            Screen::Build(b) => b.draw(&assets)
        }
    }
    fn ev_loop(&mut self) -> GameEvent {
        match self {
            Screen::Welcome(w) => w.ev_loop(),
            Screen::Build(b) => b.ev_loop()
        }
    }
}


#[macroquad::main("Little Town")]
async fn main() {
    let assets = AssetStore::init().await;

    let mut screen = Screen::Welcome(WelcomeScreen::new());

    loop {
        clear_background(Color::from_rgba(215, 189, 165, 255));

        screen.draw(&assets);

        match screen.ev_loop() {
            GameEvent::Quit => break,
            GameEvent::ChangeScreen(s) => screen = s,
            _ => ()
        }

        next_frame().await
    }
}

A  => src/screens/build.rs +21 -0
@@ 1,21 @@
use macroquad::prelude::*;
use crate::types::{
    GameComponent,
    GameEvent
};

pub struct BuildScreen {
}
impl BuildScreen {
    pub fn new() -> Self {
        Self {
        }
    }
}
impl GameComponent for BuildScreen {
    fn draw(&self, assets: &crate::textures::AssetStore) {
    }
    fn ev_loop(&mut self) -> GameEvent {
        GameEvent::None
    }
}

A  => src/screens/mod.rs +2 -0
@@ 1,2 @@
pub mod welcome;
pub mod build;

A  => src/screens/welcome.rs +112 -0
@@ 1,112 @@
use macroquad::prelude::*;
use crate::types::{
    GameComponent,
    GameEvent
};
use crate::textures::AssetStore;

fn draw_centered_text(text: &str, x: f32, y: f32, font: Option<Font>, font_size: u16, color: Color) {
    let mut title_params = TextParams {
        font_size,
        color,
        ..Default::default()
    };
    if let Some(font) = font {
        title_params.font = font;
    }
    let title_center = get_text_center(
        text,
        font,
        font_size,
        1.0,
        0.0);
    draw_text_ex(
        text,
        x - title_center.x,
        y - title_center.y,
        title_params);
}
fn draw_wide_button(text: &str, pressed: bool, x: f32, y: f32, assets: &AssetStore) {
    draw_texture(
        if pressed {
            assets.long_button.1
        } else { assets.long_button.0 },
        x - 190.0 / 2.0,
        y,
        WHITE);

    draw_centered_text(text,
                       x, y + 49.0 / 2.0 - 2.0,
                       Some(assets.font), 60, LIGHTGRAY);
}

pub struct WelcomeScreen {
    button_build_down: bool,
    button_exit_down: bool
}
impl WelcomeScreen {
    pub fn new() -> Self {
        Self {
            button_build_down: false,
            button_exit_down: false
        }
    }
}
impl GameComponent for WelcomeScreen {
    fn draw(&self, assets: &AssetStore) {
        draw_centered_text(
            "Welcome",
            screen_width()/2.0, screen_height()/2.0,
            Some(assets.font), 100, WHITE);

        draw_wide_button(
            "Build", self.button_build_down,
            screen_width()/2.0, screen_height()/2.0 + 60.0,
            &assets);

        draw_wide_button(
            "Quit", self.button_exit_down,
            screen_width()/2.0, screen_height()/2.0 + 130.0,
            &assets);
    }
    fn ev_loop(&mut self) -> GameEvent {
        let old_btn_build = self.button_build_down;
        let old_btn_exit = self.button_exit_down;

        self.button_exit_down = false;
        self.button_build_down = false;

        if is_mouse_button_down(MouseButton::Left) {
            let (x,y) = mouse_position();
            let sw_2 = screen_width() / 2.0;
            let sh_2 = screen_height() / 2.0;
            let btn_x_offset = sw_2 - 190.0 / 2.0;
            let btn_height = 49.0;

            if x >= btn_x_offset && x <= btn_x_offset + 190.0 {
                // might be pressing a button
                if y >= sh_2 + 60.0 && y <= sh_2 + 60.0 + btn_height {
                    // pressing first button
                    self.button_build_down = true;
                }
                if y >= sh_2 + 130.0 && y <= sh_2 + 130.0 + btn_height {
                    // pressing second button
                    self.button_exit_down = true;
                }
            }
        }

        if !self.button_build_down && self.button_build_down != old_btn_build {
            // user released key
            // TODO: launch build mode
            return GameEvent::ChangeScreen(crate::Screen::Build(super::build::BuildScreen::new()));
        }
        if !self.button_exit_down && self.button_exit_down != old_btn_exit {
            // user released key
            // exit game
            return GameEvent::Quit;
        }

        GameEvent::None
    }
}

A  => src/textures.rs +46 -0
@@ 1,46 @@
use macroquad::prelude::*;

const ASSET_FOLDER: &str = "assets/";
const ASSET_BASE_FOLDER: &str = "base/";
const ASSET_EXP_FOLDER: &str = "exp/";
const ASSET_UI_FOLDER: &str = "ui/";
const ASSET_FONTS_FOLDER: &str = "fonts/";

fn in_assets_folder(path: &str) -> String {
    format!("{}{}", ASSET_FOLDER, path)
}
fn in_base_folder(path: &str) -> String {
    in_assets_folder(&format!("{}{}", ASSET_BASE_FOLDER, path))
}
fn in_exp_folder(path: &str) -> String {
    in_assets_folder(&format!("{}{}", ASSET_EXP_FOLDER, path))
}
fn in_ui_folder(path: &str) -> String {
    in_assets_folder(&format!("{}{}", ASSET_UI_FOLDER, path))
}
fn in_font_folder(path: &str) -> String {
    in_assets_folder(&format!("{}{}", ASSET_FONTS_FOLDER, path))
}


/// Collection of textures required by game
pub struct AssetStore {
    pub font: Font,
    pub long_button: (Texture2D, Texture2D)
}
impl AssetStore {
    /// loads all the textures
    pub async fn init() -> Self {
        Self {
            font: load_ttf_font(&in_font_folder("Fonts/Kenney Pixel.ttf"))
                .await.expect("Unable to load font"),
            long_button: (
                load_texture(
                    &in_ui_folder("PNG/buttonLong_brown.png"))
                    .await.expect("Unable to load texture"),
                load_texture(
                    &in_ui_folder("PNG/buttonLong_brown_pressed.png"))
                    .await.expect("Unable to load texture"))
        }
    }
}

A  => src/types.rs +29 -0
@@ 1,29 @@
use crate::textures::AssetStore;
use crate::Screen;

/// A basic Game component
/// which can be drawn
/// and has a handler for the event loop
/// NOTE: draw and ev_loop are tehcnically the same,
/// but the serve different purposes
pub trait GameComponent {
    /// Callback used to redraw the component
    fn draw(&self, assets: &AssetStore) {}
    /// Callback used to perform background tasks
    /// e.g. keyboard input
    /// NOTE: this is currently not being run asynchronously
    /// when running large operations, spawn a separate thread
    fn ev_loop(&mut self) -> GameEvent {
        GameEvent::None
    }
}

/// Events send from the event loop
pub enum GameEvent {
    /// Do nothing
    None,
    /// Exit game
    Quit,
    /// Change View
    ChangeScreen(Screen)
}