Skip to content

Commit

Permalink
added enemy and projectile
Browse files Browse the repository at this point in the history
  • Loading branch information
tsukinoko-kun committed Jul 7, 2024
1 parent 937a5e6 commit 7328034
Show file tree
Hide file tree
Showing 10 changed files with 291 additions and 31 deletions.
Binary file added assets/sprites/projectile.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/sprites/skeleton.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
10 changes: 9 additions & 1 deletion src/anim.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ impl AnimationIndices {
}
}

#[derive(Component, Deref, DerefMut)]
#[derive(Component, Deref, DerefMut, Debug)]
pub struct AnimationTimer(pub Timer);

fn animate_sprite(
Expand All @@ -51,6 +51,14 @@ fn animate_sprite(
}
}

#[derive(Bundle, Debug)]
pub struct AnimatedSpriteBundle {
pub sprite: SpriteBundle,
pub indices: AnimationIndices,
pub timer: AnimationTimer,
pub atlas: TextureAtlas,
}

pub struct AnimPlugin;

impl Plugin for AnimPlugin {
Expand Down
32 changes: 15 additions & 17 deletions src/cat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@

use bevy::prelude::*;

use crate::anim::{AnimationIndices, AnimationTimer};
use crate::anim::{AnimatedSpriteBundle, AnimationIndices, AnimationTimer};
use crate::movement::*;
use crate::player::Player;

Expand All @@ -43,23 +43,21 @@ fn spawn_cat(

commands.spawn((
Cat,
SpriteBundle {
texture,
transform: Transform::from_scale(Vec3::splat(2.0)).with_translation(Vec3::new(
CAT_THRESHOLD,
CAT_THRESHOLD,
0.0,
)),
..default()
AnimatedSpriteBundle {
sprite: SpriteBundle {
texture,
transform: Transform::from_scale(Vec3::splat(2.0)),
..default()
},
atlas: TextureAtlas {
layout: texture_atlas_layout,
index: animation_indices.first,
},
indices: animation_indices,
timer: AnimationTimer(Timer::from_seconds(0.25, TimerMode::Repeating)),
},
TextureAtlas {
layout: texture_atlas_layout,
index: animation_indices.first,
},
animation_indices,
AnimationTimer(Timer::from_seconds(0.25, TimerMode::Repeating)),
MovingObjectBundle {
velocity: Velocity::new(Vec3::new(0.0, 0.0, 0.0), CAT_SPEED),
velocity: Velocity::from_vec3(Vec3::new(0.0, 0.0, 0.0), CAT_SPEED),
},
));
}
Expand All @@ -68,7 +66,7 @@ fn update_position(
mut cats: Query<(&Cat, &Transform, &mut Velocity)>,
players: Query<(&Player, &Transform)>,
) {
if let Some((_, player_transform)) = players.iter().next() {
if let Ok((_, player_transform)) = players.get_single() {
for (_, cat_transform, mut cat_vel) in &mut cats.iter_mut() {
// calc direction from cat to player
let direction = player_transform.translation - cat_transform.translation;
Expand Down
106 changes: 106 additions & 0 deletions src/enemy.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
/*
* Mageanoid - A computer game
* Copyright (C) 2024 Frank Mayer
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/

use bevy::prelude::*;

use crate::anim::{AnimationIndices, AnimationTimer};
use crate::movement::*;
use crate::player::Player;

const ENEMY_SPEED: f32 = 40.0;
const ENEMY_THRESHOLD: f32 = ENEMY_SPEED;

pub struct EnemyPlugin;

#[derive(Component, Debug)]
pub struct Enemy;

fn spawn_enemy(
mut commands: Commands,
asset_server: Res<AssetServer>,
mut texture_atlas_layouts: ResMut<Assets<TextureAtlasLayout>>,
// players: Query<(&Player, &Transform)>,
) {
// if let Ok((_, player_transform)) = players.get_single() {}

let texture = asset_server.load("sprites/skeleton.png");
let layout = TextureAtlasLayout::from_grid(UVec2::new(64, 64), 4, 3, None, None);
let texture_atlas_layout = texture_atlas_layouts.add(layout);

let animation_indices = AnimationIndices::new(0, 0);

commands.spawn((
Enemy,
SpriteBundle {
texture,
transform: Transform::from_scale(Vec3::splat(2.0)).with_translation(Vec3::new(
0.0,
0.0,
0.0,
)),
..default()
},
TextureAtlas {
layout: texture_atlas_layout,
index: animation_indices.first,
},
animation_indices,
AnimationTimer(Timer::from_seconds(0.25, TimerMode::Repeating)),
MovingObjectBundle {
velocity: Velocity::from_vec3(Vec3::new(0.0, 0.0, 0.0), ENEMY_SPEED),
},
));
}

fn update_position(
mut enemies: Query<(&Enemy, &Transform, &mut Velocity)>,
players: Query<(&Player, &Transform)>,
) {
if let Ok((_, player_transform)) = players.get_single() {
for (_, enemy_transform, mut enemy_vel) in &mut enemies.iter_mut() {
let direction = player_transform.translation - enemy_transform.translation;
if direction.length() > ENEMY_THRESHOLD {
enemy_vel.direction = direction.normalize();
} else {
enemy_vel.direction = Vec3::ZERO;
}
}
}
}

fn update_animation(mut cats: Query<(&Enemy, &Velocity, &mut AnimationIndices)>) {
for (_, velocity, mut indices) in &mut cats {
if velocity.direction.x < 0.0 {
indices.first = 0;
indices.last = 1;
} else if velocity.direction.x > 0.0 {
indices.first = 2;
indices.last = 3;
} else {
indices.last = indices.first;
}
}
}

impl Plugin for EnemyPlugin {
fn build(&self, app: &mut App) {
app.add_systems(Startup, spawn_enemy)
.add_systems(Update, update_position)
.add_systems(Update, update_animation);
}
}
8 changes: 7 additions & 1 deletion src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,11 @@ use bevy::prelude::*;
mod anim;
mod cam;
mod cat;
mod enemy;
mod movement;
mod overlap;
mod player;
mod projectile;

fn main() {
let mut app = App::new();
Expand All @@ -31,8 +34,11 @@ fn main() {
.add_plugins(anim::AnimPlugin)
.add_plugins(cam::CamPlugin)
.add_plugins(cat::CatPlugin)
.add_plugins(enemy::EnemyPlugin)
.add_plugins(movement::MovementPlugin)
.add_plugins(player::PlayerPlugin);
.add_plugins(overlap::OverlapPlugin)
.add_plugins(player::PlayerPlugin)
.add_plugins(projectile::ProjectilePlugin);

app.run();
}
9 changes: 6 additions & 3 deletions src/movement.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,16 @@ pub struct Velocity {
}

impl Velocity {
pub fn new(direction: Vec3, speed: f32) -> Self {
pub fn from_vec3(direction: Vec3, speed: f32) -> Self {
Self { direction, speed }
}

pub fn from_vec2(direction: Vec2, speed: f32) -> Self {
Self { direction: Vec3::new(direction.x, direction.y, 0.0), speed }
}
}

#[derive(Bundle)]
#[derive(Bundle, Debug)]
pub struct MovingObjectBundle {
pub velocity: Velocity,
}
Expand All @@ -41,7 +45,6 @@ fn update_position(mut query: Query<(&Velocity, &mut Transform)>, time: Res<Time
trans.translation += vel.direction.normalize_or_zero()
* f32::min(vel.speed, vel.direction.length() * vel.speed)
* time.delta_seconds();
trans.translation.z = -trans.translation.y;
}
}

Expand Down
33 changes: 33 additions & 0 deletions src/overlap.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*
* Mageanoid - A computer game
* Copyright (C) 2024 Frank Mayer
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/

use bevy::prelude::*;

fn overlap(mut query: Query<&mut Transform>) {
for mut transform in &mut query.iter_mut() {
transform.translation.z = -transform.translation.y;
}
}

pub struct OverlapPlugin;

impl Plugin for OverlapPlugin {
fn build(&self, app: &mut App) {
app.add_systems(Update, overlap);
}
}
51 changes: 42 additions & 9 deletions src/player.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,12 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/

use bevy::input::mouse::MouseButtonInput;
use bevy::prelude::*;

use crate::anim::*;
use crate::movement::*;
use crate::projectile::ProjectileBundle;

const PLAYER_MOVE_SPEED: f32 = 150.0;

Expand Down Expand Up @@ -53,31 +55,61 @@ fn spawn_player(
animation_indices,
AnimationTimer(Timer::from_seconds(0.25, TimerMode::Repeating)),
MovingObjectBundle {
velocity: Velocity::new(Vec3::new(0.0, 0.0, 0.0), PLAYER_MOVE_SPEED),
velocity: Velocity::from_vec3(Vec3::new(0.0, 0.0, 0.0), PLAYER_MOVE_SPEED),
},
));
}

fn player_input(
mut player_entity: Query<(&Player, &mut Velocity, &mut AnimationIndices)>,
fn player_projectile(
players: Query<(&Player, &GlobalTransform)>,
mut mousebtn_evr: EventReader<MouseButtonInput>,
mut commands: Commands,
asset_server: Res<AssetServer>,
texture_atlas_layouts: ResMut<Assets<TextureAtlasLayout>>,

// cursor click
windows: Query<&Window>,
camera_q: Query<(&Camera, &GlobalTransform)>,
) {
for (_, transform) in &mut players.iter() {
for ev in mousebtn_evr.read() {
if ev.state.is_pressed() && ev.button == MouseButton::Left {
let window = windows.single();
let (camera, camera_transform) = camera_q.single();

if let Some(world_position) = window
.cursor_position()
.and_then(|cursor| camera.viewport_to_world_2d(camera_transform, cursor))
{
let direction = (world_position - transform.translation().xy()).normalize();
commands.spawn(ProjectileBundle::new(asset_server, texture_atlas_layouts, transform.translation(), direction));
return;
}
}
}
}
}

fn player_movement(
mut players: Query<(&Player, &mut Velocity, &mut AnimationIndices)>,
keys: Res<ButtonInput<KeyCode>>,
gamepads: Res<Gamepads>,
axes: Res<Axis<GamepadAxis>>,
) {
for (_, mut velocity, mut indices) in &mut player_entity.iter_mut() {
for (_, mut velocity, mut indices) in &mut players.iter_mut() {
// keyboard x
if keys.pressed(KeyCode::ArrowLeft) || keys.pressed(KeyCode::KeyA) {
if keys.any_pressed([KeyCode::ArrowLeft, KeyCode::KeyA]) {
velocity.direction.x = -1.0;
} else if keys.pressed(KeyCode::ArrowRight) || keys.pressed(KeyCode::KeyD) {
} else if keys.any_pressed([KeyCode::ArrowRight, KeyCode::KeyD]) {
velocity.direction.x = 1.0;
} else {
velocity.direction.x = 0.0;
}

// keyboard y
if keys.pressed(KeyCode::ArrowUp) || keys.pressed(KeyCode::KeyW) {
if keys.any_pressed([KeyCode::ArrowUp, KeyCode::KeyW]) {
velocity.direction.y = 1.0;
} else if keys.pressed(KeyCode::ArrowDown) || keys.pressed(KeyCode::KeyS) {
} else if keys.any_pressed([KeyCode::ArrowDown, KeyCode::KeyS]) {
velocity.direction.y = -1.0;
} else {
velocity.direction.y = 0.0;
Expand Down Expand Up @@ -118,6 +150,7 @@ fn player_input(
impl Plugin for PlayerPlugin {
fn build(&self, app: &mut App) {
app.add_systems(Startup, spawn_player)
.add_systems(Update, player_input);
.add_systems(Update, player_movement)
.add_systems(Update, player_projectile);
}
}
Loading

0 comments on commit 7328034

Please sign in to comment.