Basic basic game
This commit is contained in:
parent
b020d0564c
commit
ce070ce4be
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
/target
|
3159
Cargo.lock
generated
Normal file
3159
Cargo.lock
generated
Normal file
File diff suppressed because it is too large
Load Diff
16
Cargo.toml
Normal file
16
Cargo.toml
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
[package]
|
||||||
|
name = "arnold-survivors"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[profile.dev]
|
||||||
|
opt-level = 1
|
||||||
|
|
||||||
|
[profile.dev.package."*"]
|
||||||
|
opt-level = 3
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
bevy = "0.6.1"
|
||||||
|
rand = "0.8.5"
|
BIN
assets/arno.jpg
Normal file
BIN
assets/arno.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 44 KiB |
BIN
assets/arno.png
Normal file
BIN
assets/arno.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 21 KiB |
BIN
assets/knife.png
Normal file
BIN
assets/knife.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.0 KiB |
BIN
assets/knife.webp
Normal file
BIN
assets/knife.webp
Normal file
Binary file not shown.
After Width: | Height: | Size: 39 KiB |
BIN
assets/monster.jpg
Normal file
BIN
assets/monster.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 46 KiB |
BIN
assets/monster.png
Normal file
BIN
assets/monster.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 21 KiB |
295
src/main.rs
Normal file
295
src/main.rs
Normal file
@ -0,0 +1,295 @@
|
|||||||
|
use std::f32::consts::PI;
|
||||||
|
|
||||||
|
use bevy::core::{FixedTimestep, Time, Timer};
|
||||||
|
use bevy::input::system::exit_on_esc_system;
|
||||||
|
use bevy::input::Input;
|
||||||
|
use bevy::math::Vec3;
|
||||||
|
use bevy::prelude::{
|
||||||
|
App, AssetServer, Commands, Component, Entity, KeyCode, OrthographicCameraBundle, Query, Res,
|
||||||
|
SystemSet, Transform, Without,
|
||||||
|
};
|
||||||
|
use bevy::sprite::{Sprite, SpriteBundle};
|
||||||
|
use bevy::window::Windows;
|
||||||
|
use bevy::DefaultPlugins;
|
||||||
|
use rand::Rng;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
App::new()
|
||||||
|
.add_plugins(DefaultPlugins)
|
||||||
|
.add_startup_system(setup)
|
||||||
|
.add_system_set(
|
||||||
|
SystemSet::new()
|
||||||
|
.with_run_criteria(FixedTimestep::step(1.0 / 60.0))
|
||||||
|
.with_system(projectile_collide_system)
|
||||||
|
.with_system(arnold_movement_system)
|
||||||
|
.with_system(arnold_attack_system)
|
||||||
|
.with_system(linear_movement_system)
|
||||||
|
.with_system(expiration_date_system)
|
||||||
|
.with_system(follow_arnold_system)
|
||||||
|
.with_system(enemy_spawner_system),
|
||||||
|
)
|
||||||
|
.add_system(exit_on_esc_system)
|
||||||
|
.run();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn setup(mut commands: Commands, assets: Res<AssetServer>) {
|
||||||
|
let arnold_sh = assets.load("arno.png");
|
||||||
|
|
||||||
|
commands.spawn_bundle(OrthographicCameraBundle::new_2d());
|
||||||
|
commands
|
||||||
|
.spawn_bundle(SpriteBundle {
|
||||||
|
texture: arnold_sh,
|
||||||
|
..Default::default()
|
||||||
|
})
|
||||||
|
.insert(EnemySpawner::new(Timer::from_seconds(3.0, true)))
|
||||||
|
.insert(Arnold::new())
|
||||||
|
.insert(Transform {
|
||||||
|
translation: Vec3::new(0.0, 0.0, 0.0),
|
||||||
|
..Default::default()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Component)]
|
||||||
|
struct Projectile {
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Projectile {
|
||||||
|
fn new() -> Self {
|
||||||
|
Self {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Component)]
|
||||||
|
struct Hitpoints {
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Hitpoints {
|
||||||
|
fn new() -> Self {
|
||||||
|
Self {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn projectile_collide_system(
|
||||||
|
mut commands: Commands,
|
||||||
|
projectile_query: Query<(&Projectile, &Transform)>,
|
||||||
|
target_query: Query<(Entity, &Hitpoints, &Transform)>
|
||||||
|
) {
|
||||||
|
for (entity, _hp, target_transform) in target_query.iter() {
|
||||||
|
let mut has_been_hit = false;
|
||||||
|
for (_projectile, projectile_transform) in projectile_query.iter() {
|
||||||
|
if target_transform.translation.distance(projectile_transform.translation) < 32.0 {
|
||||||
|
has_been_hit = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if has_been_hit {
|
||||||
|
commands.entity(entity).despawn();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(PartialEq)]
|
||||||
|
enum Facing {
|
||||||
|
Left,
|
||||||
|
Right,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Component)]
|
||||||
|
struct Arnold {
|
||||||
|
facing: Facing,
|
||||||
|
attack_timer: Timer,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Arnold {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
facing: Facing::Left,
|
||||||
|
attack_timer: Timer::from_seconds(1.0, true),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Component)]
|
||||||
|
struct Knife {}
|
||||||
|
|
||||||
|
impl Knife {
|
||||||
|
fn new() -> Self {
|
||||||
|
Self {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Component)]
|
||||||
|
struct LinearMovement {
|
||||||
|
direction: Vec3,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl LinearMovement {
|
||||||
|
fn new(direction: Vec3) -> Self {
|
||||||
|
Self { direction }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn linear_movement_system(mut query: Query<(&LinearMovement, &mut Transform)>) {
|
||||||
|
for (lin_movement, mut transform) in query.iter_mut() {
|
||||||
|
transform.translation += lin_movement.direction;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Component)]
|
||||||
|
struct ExpirationDate {
|
||||||
|
countdown: Timer,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ExpirationDate {
|
||||||
|
fn new(countdown: Timer) -> Self {
|
||||||
|
Self { countdown }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn expiration_date_system(
|
||||||
|
mut commands: Commands,
|
||||||
|
time: Res<Time>,
|
||||||
|
mut query: Query<(Entity, &mut ExpirationDate)>,
|
||||||
|
) {
|
||||||
|
for (entity, mut exp_date) in query.iter_mut() {
|
||||||
|
if exp_date.countdown.tick(time.delta()).just_finished() {
|
||||||
|
commands.entity(entity).despawn();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn arnold_movement_system(
|
||||||
|
keyboard_input: Res<Input<KeyCode>>,
|
||||||
|
mut query: Query<(&mut Arnold, &mut Sprite, &mut Transform)>,
|
||||||
|
) {
|
||||||
|
let (mut arnold, mut sprite, mut transform) = query.single_mut();
|
||||||
|
|
||||||
|
let mut velocity = Vec3::new(0.0, 0.0, 0.0);
|
||||||
|
if keyboard_input.pressed(KeyCode::A) {
|
||||||
|
velocity.x -= 1.0;
|
||||||
|
}
|
||||||
|
if keyboard_input.pressed(KeyCode::D) {
|
||||||
|
velocity.x += 1.0;
|
||||||
|
}
|
||||||
|
if keyboard_input.pressed(KeyCode::S) {
|
||||||
|
velocity.y -= 1.0;
|
||||||
|
}
|
||||||
|
if keyboard_input.pressed(KeyCode::W) {
|
||||||
|
velocity.y += 1.0;
|
||||||
|
}
|
||||||
|
velocity *= 1.5;
|
||||||
|
|
||||||
|
if keyboard_input.just_pressed(KeyCode::A) {
|
||||||
|
sprite.flip_x = false;
|
||||||
|
arnold.facing = Facing::Left;
|
||||||
|
}
|
||||||
|
if keyboard_input.just_pressed(KeyCode::D) {
|
||||||
|
sprite.flip_x = true;
|
||||||
|
arnold.facing = Facing::Right;
|
||||||
|
}
|
||||||
|
|
||||||
|
transform.translation += velocity;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn arnold_attack_system(
|
||||||
|
assets: Res<AssetServer>,
|
||||||
|
mut commands: Commands,
|
||||||
|
time: Res<Time>,
|
||||||
|
mut query: Query<(&mut Arnold, &Transform)>,
|
||||||
|
) {
|
||||||
|
let (mut arnold, arnold_transform) = query.single_mut();
|
||||||
|
|
||||||
|
if arnold.attack_timer.tick(time.delta()).just_finished() {
|
||||||
|
let knife_velocity = match arnold.facing {
|
||||||
|
Facing::Left => Vec3::new(-1.0, 0.0, 0.0),
|
||||||
|
Facing::Right => Vec3::new(1.0, 0.0, 0.0),
|
||||||
|
} * 4.0;
|
||||||
|
|
||||||
|
commands
|
||||||
|
.spawn_bundle(SpriteBundle {
|
||||||
|
texture: assets.load("knife.png"),
|
||||||
|
sprite: Sprite {
|
||||||
|
flip_x: arnold.facing == Facing::Left,
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
..Default::default()
|
||||||
|
})
|
||||||
|
.insert(Knife::new())
|
||||||
|
.insert(Transform {
|
||||||
|
translation: arnold_transform.translation
|
||||||
|
+ Vec3::new(0.0, 0.0, 10.0)
|
||||||
|
+ knife_velocity,
|
||||||
|
..Default::default()
|
||||||
|
})
|
||||||
|
.insert(LinearMovement::new(knife_velocity))
|
||||||
|
.insert(ExpirationDate::new(Timer::from_seconds(5.0, false)))
|
||||||
|
.insert(Projectile::new());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Component)]
|
||||||
|
struct EnemySpawner {
|
||||||
|
timer: Timer,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl EnemySpawner {
|
||||||
|
fn new(timer: Timer) -> Self {
|
||||||
|
Self { timer }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn enemy_spawner_system(
|
||||||
|
mut commands: Commands,
|
||||||
|
assets: Res<AssetServer>,
|
||||||
|
windows: Res<Windows>,
|
||||||
|
time: Res<Time>,
|
||||||
|
mut query: Query<&mut EnemySpawner>,
|
||||||
|
) {
|
||||||
|
let mut enemy_spawner = query.single_mut();
|
||||||
|
|
||||||
|
if !enemy_spawner.timer.tick(time.delta()).just_finished() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let window = windows.get_primary().unwrap();
|
||||||
|
let spawn_distance = f32::max(window.width(), window.height()) / 2.0;
|
||||||
|
|
||||||
|
let mut rng = rand::thread_rng();
|
||||||
|
let phi = rng.gen_range(0.0..2.0 * PI);
|
||||||
|
|
||||||
|
commands
|
||||||
|
.spawn_bundle(SpriteBundle {
|
||||||
|
texture: assets.load("monster.png"),
|
||||||
|
transform: Transform {
|
||||||
|
translation: Vec3::new(phi.cos() * spawn_distance, phi.sin() * spawn_distance, 0.0),
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
..Default::default()
|
||||||
|
})
|
||||||
|
.insert(FollowArnold::new(1.0))
|
||||||
|
.insert(Hitpoints::new());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Component)]
|
||||||
|
struct FollowArnold {
|
||||||
|
speed: f32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FollowArnold {
|
||||||
|
fn new(speed: f32) -> Self {
|
||||||
|
Self { speed }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn follow_arnold_system(
|
||||||
|
mut follow_query: Query<(&FollowArnold, &mut Transform), Without<Arnold>>,
|
||||||
|
arnold_query: Query<(&Arnold, &Transform)>,
|
||||||
|
) {
|
||||||
|
let (_, arnold_transform) = arnold_query.single();
|
||||||
|
|
||||||
|
for (follow, mut follow_transform) in follow_query.iter_mut() {
|
||||||
|
let velocity = (arnold_transform.translation - follow_transform.translation).normalize()
|
||||||
|
* follow.speed;
|
||||||
|
follow_transform.translation += velocity;
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user