chore: squash commits
This commit is contained in:
parent
7d6044c9cf
commit
61cf4b9f74
1153
Cargo.lock
generated
1153
Cargo.lock
generated
File diff suppressed because it is too large
Load diff
|
@ -2,6 +2,9 @@
|
||||||
name = "ambition"
|
name = "ambition"
|
||||||
version = "0.4.0"
|
version = "0.4.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
authors = ["Muhammad Nauman Raza <devraza.hazard643@slmail.me>"]
|
||||||
|
description = "A fast-paced 2D MMORPG."
|
||||||
|
readme = "README.md"
|
||||||
|
|
||||||
# Squeeze out more performance for `release` builds - very slow compile times
|
# Squeeze out more performance for `release` builds - very slow compile times
|
||||||
[profile.release]
|
[profile.release]
|
||||||
|
@ -15,7 +18,7 @@ opt-level = 1
|
||||||
opt-level = 3
|
opt-level = 3
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
bevy = { version = "0.13.0" }
|
bevy = { version = "0.13.2", features = ["wayland"] }
|
||||||
bevy_egui = "0.25.0"
|
bevy_egui = "0.27.1"
|
||||||
bevy_hanabi = "0.10.0"
|
bevy_hanabi = "0.11.0"
|
||||||
lazy_static = "1.4.0"
|
lazy_static = "1.4.0"
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
*Go forth and realise your...*
|
*Go forth and realise your...*
|
||||||
|
|
||||||
# Ambition
|
# Ambition
|
||||||
A fast-paced, textual 2D multiplayer role-playing game written in Rust.
|
A fast-paced 2D multiplayer role-playing game written in Rust.
|
||||||
|
|
||||||
## Credits
|
## Credits
|
||||||
- [Muhammad Nauman Raza](https://github.com/devraza) - Project manager/founder, producer, and programmer
|
- [Muhammad Nauman Raza](https://github.com/devraza) - Project manager/founder, producer, and programmer
|
||||||
|
|
12
flake.lock
12
flake.lock
|
@ -21,11 +21,11 @@
|
||||||
"nixpkgs": "nixpkgs"
|
"nixpkgs": "nixpkgs"
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1710868679,
|
"lastModified": 1713543440,
|
||||||
"narHash": "sha256-V1o2bCZdeYKP/0zgVp4EN0KUjMItAMk6J7SvCXUI5IU=",
|
"narHash": "sha256-lnzZQYG0+EXl/6NkGpyIz+FEOc/DSEG57AP1VsdeNrM=",
|
||||||
"owner": "guibou",
|
"owner": "guibou",
|
||||||
"repo": "nixGL",
|
"repo": "nixGL",
|
||||||
"rev": "d709a8abcde5b01db76ca794280745a43c8662be",
|
"rev": "310f8e49a149e4c9ea52f1adf70cdc768ec53f8a",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
@ -51,11 +51,11 @@
|
||||||
},
|
},
|
||||||
"nixpkgs-unstable": {
|
"nixpkgs-unstable": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1711163522,
|
"lastModified": 1716509168,
|
||||||
"narHash": "sha256-YN/Ciidm+A0fmJPWlHBGvVkcarYWSC+s3NTPk/P+q3c=",
|
"narHash": "sha256-4zSIhSRRIoEBwjbPm3YiGtbd8HDWzFxJjw5DYSDy1n8=",
|
||||||
"owner": "nixos",
|
"owner": "nixos",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "44d0940ea560dee511026a53f0e2e2cde489b4d4",
|
"rev": "bfb7a882678e518398ce9a31a881538679f6f092",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
|
12
flake.nix
12
flake.nix
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
description = "Rust development environment for Ambition using fenix";
|
description = "Rust development environment for Ambition";
|
||||||
|
|
||||||
inputs = {
|
inputs = {
|
||||||
utils.url = "github:numtide/flake-utils";
|
utils.url = "github:numtide/flake-utils";
|
||||||
|
@ -41,16 +41,14 @@
|
||||||
pkgs.udev
|
pkgs.udev
|
||||||
pkgs.alsa-lib
|
pkgs.alsa-lib
|
||||||
pkgs.libxkbcommon
|
pkgs.libxkbcommon
|
||||||
|
pkgs.wayland
|
||||||
]}"'';
|
]}"'';
|
||||||
buildInputs = with pkgs; [
|
buildInputs = with pkgs; [
|
||||||
xorg.libX11 xorg.libXcursor xorg.libXi xorg.libXrandr # To use the x11 feature
|
xorg.libX11 xorg.libXcursor xorg.libXi xorg.libXrandr # To use the x11 feature
|
||||||
libxkbcommon # To use the wayland feature
|
libxkbcommon wayland # To use the wayland feature
|
||||||
udev alsa-lib vulkan-loader
|
udev alsa-lib vulkan-loader
|
||||||
pkgs.nixgl.nixVulkanIntel
|
|
||||||
mold
|
pkgs.nixgl.nixVulkanIntel mold clang pkg-config tokei
|
||||||
clang
|
|
||||||
pkg-config
|
|
||||||
tokei
|
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
2
justfile
2
justfile
|
@ -4,4 +4,4 @@ timestamp := `date +"%Y-%m-%d\ %H:%M"`
|
||||||
|
|
||||||
# Backup assets
|
# Backup assets
|
||||||
backup:
|
backup:
|
||||||
ouch compress assets/player assets/logo assets/attacks ~/NAS/Documents/Ambition/{{timestamp}}.tar.gz
|
ouch compress assets/player assets/logo assets/attacks ~/NAS/Documents/Ambition/Assets/{{timestamp}}.tar.gz
|
||||||
|
|
62
src/enemy.rs
Normal file
62
src/enemy.rs
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
use bevy::prelude::*;
|
||||||
|
use std::f32::consts::PI;
|
||||||
|
|
||||||
|
use crate::player::*;
|
||||||
|
|
||||||
|
// Define the enemy component
|
||||||
|
#[derive(Component)]
|
||||||
|
pub struct Enemy {
|
||||||
|
pub name: String,
|
||||||
|
pub movement_speed: f32,
|
||||||
|
/*
|
||||||
|
pub rotation_speed: f32,
|
||||||
|
|
||||||
|
pub health: f32,
|
||||||
|
pub health_max: f32,
|
||||||
|
pub stamina: f32,
|
||||||
|
pub stamina_max: f32,
|
||||||
|
pub mana: f32,
|
||||||
|
pub mana_max: f32,
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
// Define the enemy movement system
|
||||||
|
#[allow(clippy::type_complexity)]
|
||||||
|
pub fn enemy_movement(
|
||||||
|
time: Res<Time>,
|
||||||
|
mut set: ParamSet<(
|
||||||
|
Query<&Transform, With<Player>>,
|
||||||
|
Query<&mut Transform, With<Enemy>>,
|
||||||
|
)>,
|
||||||
|
mut enemy_query: Query<&Enemy>,
|
||||||
|
) {
|
||||||
|
let enemy = enemy_query.single_mut();
|
||||||
|
|
||||||
|
// Bring the player translation into scope
|
||||||
|
let mut player_translation = Vec3::ZERO;
|
||||||
|
for player_transform in set.p0().iter_mut() {
|
||||||
|
player_translation = player_transform.translation;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the enemy's movement distance (based on movement speed)
|
||||||
|
let movement_distance = enemy.movement_speed * time.delta_seconds();
|
||||||
|
|
||||||
|
for mut enemy_transform in set.p1().iter_mut() {
|
||||||
|
// Calculate the angle from the enemy to the player's position
|
||||||
|
let difference = player_translation - enemy_transform.translation;
|
||||||
|
let angle = difference.y.atan2(difference.x) - PI / 2.; // Subtract PI/2. to orient the enemy correctly
|
||||||
|
|
||||||
|
// Return a Quat for the enemy's movement direction based on the angle
|
||||||
|
let movement_direction = Quat::from_axis_angle(Vec3::new(0., 0., 1.), angle);
|
||||||
|
|
||||||
|
// Update the rotation and translation of the enemy
|
||||||
|
enemy_transform.rotation = movement_direction;
|
||||||
|
enemy_transform.translation += movement_direction * Vec3::Y * movement_distance;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn change_enemy_color(mut query: Query<&mut Sprite, With<Enemy>>) {
|
||||||
|
for mut sprite in query.iter_mut() {
|
||||||
|
sprite.color = Color::rgb(0.5, 1.0, 0.5);
|
||||||
|
}
|
||||||
|
}
|
39
src/main.rs
39
src/main.rs
|
@ -13,12 +13,14 @@ mod player;
|
||||||
use crate::player::*;
|
use crate::player::*;
|
||||||
mod ui;
|
mod ui;
|
||||||
use crate::ui::*;
|
use crate::ui::*;
|
||||||
|
mod enemy;
|
||||||
|
use crate::enemy::*;
|
||||||
|
|
||||||
// Version information
|
// Version information
|
||||||
const VERSION: &str = env!("CARGO_PKG_VERSION");
|
const VERSION: &str = env!("CARGO_PKG_VERSION");
|
||||||
const PKGNAME: &str = env!("CARGO_PKG_NAME");
|
const PKGNAME: &str = env!("CARGO_PKG_NAME");
|
||||||
|
|
||||||
// Create a map of the Hypernova colorscheme
|
// Create a map of the kagayaki colorscheme
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
static ref KAGAYAKI: HashMap<&'static str, (u8, u8, u8)> = vec![
|
static ref KAGAYAKI: HashMap<&'static str, (u8, u8, u8)> = vec![
|
||||||
("BLACK", (13, 13, 15)),
|
("BLACK", (13, 13, 15)),
|
||||||
|
@ -59,7 +61,15 @@ fn main() {
|
||||||
.add_systems(Startup, (setup, setup_ui))
|
.add_systems(Startup, (setup, setup_ui))
|
||||||
.add_systems(
|
.add_systems(
|
||||||
Update,
|
Update,
|
||||||
(render_ui, movement, camera_follow, player_regen, attack),
|
(
|
||||||
|
render_ui,
|
||||||
|
player_movement,
|
||||||
|
player_regen,
|
||||||
|
player_attack,
|
||||||
|
attack_movement,
|
||||||
|
enemy_movement,
|
||||||
|
change_enemy_color,
|
||||||
|
),
|
||||||
)
|
)
|
||||||
.run();
|
.run();
|
||||||
}
|
}
|
||||||
|
@ -97,4 +107,29 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
||||||
mana: 100.,
|
mana: 100.,
|
||||||
mana_max: 100.,
|
mana_max: 100.,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Spawn an enemy
|
||||||
|
commands
|
||||||
|
.spawn(SpriteBundle {
|
||||||
|
texture: asset_server.load("player/player-4x.png"),
|
||||||
|
transform: Transform {
|
||||||
|
scale: Vec3::splat(0.2),
|
||||||
|
..default()
|
||||||
|
},
|
||||||
|
..default()
|
||||||
|
})
|
||||||
|
.insert(Enemy {
|
||||||
|
name: "Goblin".to_string(),
|
||||||
|
movement_speed: 256.,
|
||||||
|
/*
|
||||||
|
rotation_speed: f32::to_radians(360.),
|
||||||
|
|
||||||
|
health: 10.,
|
||||||
|
health_max: 10.,
|
||||||
|
stamina: 10.,
|
||||||
|
stamina_max: 10.,
|
||||||
|
mana: 100.,
|
||||||
|
mana_max: 100.,
|
||||||
|
*/
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,10 +22,11 @@ pub struct Attack {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Define the player movement system
|
// Define the player movement system
|
||||||
pub fn movement(
|
pub fn player_movement(
|
||||||
time: Res<Time>,
|
time: Res<Time>,
|
||||||
keys: Res<ButtonInput<KeyCode>>,
|
keys: Res<ButtonInput<KeyCode>>,
|
||||||
mut player_query: Query<(&mut Player, &mut Transform), With<Player>>,
|
mut player_query: Query<(&mut Player, &mut Transform), With<Player>>,
|
||||||
|
camera_query: Query<&mut Transform, (Without<Player>, With<Camera>)>,
|
||||||
) {
|
) {
|
||||||
let (mut player, mut transform) = player_query.single_mut();
|
let (mut player, mut transform) = player_query.single_mut();
|
||||||
|
|
||||||
|
@ -66,62 +67,63 @@ pub fn movement(
|
||||||
|
|
||||||
// Update the player translation with the translation
|
// Update the player translation with the translation
|
||||||
transform.translation += movement_direction * movement_distance;
|
transform.translation += movement_direction * movement_distance;
|
||||||
|
|
||||||
|
camera_follow(
|
||||||
|
camera_query,
|
||||||
|
transform.translation.x,
|
||||||
|
transform.translation.y,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn attack(
|
#[allow(clippy::type_complexity)]
|
||||||
|
pub fn player_attack(
|
||||||
keys: Res<ButtonInput<KeyCode>>,
|
keys: Res<ButtonInput<KeyCode>>,
|
||||||
mut set: ParamSet<(
|
mut player_query: Query<(&Transform, &mut Player), With<Player>>,
|
||||||
Query<&mut Transform, With<Attack>>,
|
|
||||||
Query<&Transform, With<Player>>,
|
|
||||||
)>,
|
|
||||||
mut player_query: Query<&mut Player>,
|
|
||||||
mut commands: Commands,
|
mut commands: Commands,
|
||||||
asset_server: Res<AssetServer>,
|
asset_server: Res<AssetServer>,
|
||||||
) {
|
) {
|
||||||
let mut player = player_query.single_mut();
|
let (transform, mut player) = player_query.single_mut();
|
||||||
|
let attack_position = transform.translation + (transform.rotation * Vec3::Y * 100.);
|
||||||
|
|
||||||
for player_transform in set.p1().iter_mut() {
|
if keys.just_pressed(KeyCode::Enter) {
|
||||||
let attack_position =
|
commands
|
||||||
player_transform.translation + ((player_transform.rotation * Vec3::Y) * 100.);
|
.spawn(SpriteBundle {
|
||||||
|
texture: asset_server.load("attacks/stone_cannon.png"),
|
||||||
|
transform: Transform {
|
||||||
|
scale: Vec3::splat(0.3),
|
||||||
|
translation: attack_position,
|
||||||
|
rotation: transform.rotation,
|
||||||
|
},
|
||||||
|
..default()
|
||||||
|
})
|
||||||
|
.insert(Attack {
|
||||||
|
velocity: 20.,
|
||||||
|
damage: 20.,
|
||||||
|
});
|
||||||
|
|
||||||
if keys.just_pressed(KeyCode::Enter) {
|
player.mana -= 1.;
|
||||||
commands
|
|
||||||
.spawn(SpriteBundle {
|
|
||||||
texture: asset_server.load("attacks/stone_cannon.png"),
|
|
||||||
transform: Transform {
|
|
||||||
scale: Vec3::splat(0.3),
|
|
||||||
translation: attack_position,
|
|
||||||
rotation: player_transform.rotation,
|
|
||||||
},
|
|
||||||
..default()
|
|
||||||
})
|
|
||||||
.insert(Attack {
|
|
||||||
velocity: 10.,
|
|
||||||
damage: 20.,
|
|
||||||
});
|
|
||||||
|
|
||||||
player.mana -= 1.;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for mut attack_transform in set.p0().iter_mut() {
|
pub fn attack_movement(mut attack_query: Query<(&mut Transform, Option<&Attack>), With<Attack>>) {
|
||||||
let direction = attack_transform.rotation * Vec3::Y;
|
for (mut transform, attack) in attack_query.iter_mut() {
|
||||||
attack_transform.translation += direction * 20.;
|
if let Some(attack) = attack {
|
||||||
|
let direction = transform.rotation * Vec3::Y;
|
||||||
|
transform.translation += direction * attack.velocity;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Function to make the camera follow the plaeyr
|
// Function to make the camera follow the plaeyr
|
||||||
pub fn camera_follow(
|
fn camera_follow(
|
||||||
mut player: Query<(&Player, &mut Transform)>,
|
mut camera_query: Query<&mut Transform, (Without<Player>, With<Camera>)>,
|
||||||
mut cameras: Query<&mut Transform, (With<Camera>, Without<Player>)>,
|
player_x: f32,
|
||||||
|
player_y: f32,
|
||||||
) {
|
) {
|
||||||
let (_, transform) = player.single_mut();
|
let mut camera_transform = camera_query.single_mut();
|
||||||
let pos = transform.translation;
|
|
||||||
|
|
||||||
for mut camera_transform in &mut cameras {
|
camera_transform.translation.x = player_x;
|
||||||
camera_transform.translation.x = pos.x;
|
camera_transform.translation.y = player_y;
|
||||||
camera_transform.translation.y = pos.y;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn player_regen(mut player_query: Query<&mut Player, With<Player>>, time: Res<Time>) {
|
pub fn player_regen(mut player_query: Query<&mut Player, With<Player>>, time: Res<Time>) {
|
||||||
|
|
|
@ -105,7 +105,7 @@ pub fn render_ui(
|
||||||
egui::CentralPanel::default()
|
egui::CentralPanel::default()
|
||||||
.frame(egui::containers::Frame {
|
.frame(egui::containers::Frame {
|
||||||
fill: egui::Color32::TRANSPARENT,
|
fill: egui::Color32::TRANSPARENT,
|
||||||
inner_margin: egui::style::Margin::same(10.),
|
inner_margin: crate::ui::egui::Margin::same(10.),
|
||||||
..default()
|
..default()
|
||||||
})
|
})
|
||||||
.show(ctx, |ui| {
|
.show(ctx, |ui| {
|
||||||
|
@ -116,8 +116,9 @@ pub fn render_ui(
|
||||||
egui::Grid::new("Stats")
|
egui::Grid::new("Stats")
|
||||||
.spacing(egui::Vec2::new(20., 10.))
|
.spacing(egui::Vec2::new(20., 10.))
|
||||||
.show(ui, |ui| {
|
.show(ui, |ui| {
|
||||||
let health_bar = egui::widgets::ProgressBar::new(player.health)
|
let health_bar =
|
||||||
.desired_width(window_width / 10.);
|
egui::widgets::ProgressBar::new(player.health / player.health_max)
|
||||||
|
.desired_width(window_width / 10.);
|
||||||
let mut stamina_bar =
|
let mut stamina_bar =
|
||||||
egui::widgets::ProgressBar::new(player.stamina / player.stamina_max)
|
egui::widgets::ProgressBar::new(player.stamina / player.stamina_max)
|
||||||
.desired_width(window_width / 10.);
|
.desired_width(window_width / 10.);
|
||||||
|
|
Reference in a new issue