-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmain.rs
More file actions
200 lines (164 loc) · 5.84 KB
/
main.rs
File metadata and controls
200 lines (164 loc) · 5.84 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
use bevy::math::bounding::Aabb2d;
use bevy::math::bounding::IntersectsVolume;
use bevy::prelude::*;
use bevy::window::PrimaryWindow;
use crate::enemy::Enemy;
use crate::enemy::EnemyPlugin;
use crate::player::Player;
use crate::player::PlayerPlugin;
mod enemy;
mod player;
// region: Game Constants
const BASE_SPEED: f32 = 5.;
const PLAYER_MAX: u8 = 1;
const ENEMY_MAX: u8 = 5;
// endregion: Game Constants
// region: Resource
#[derive(Resource)]
pub struct WinSize {
pub w: f32,
pub h: f32,
}
#[derive(Resource)]
struct PlayerCount(u8);
#[derive(Resource)]
struct EnemyCount(u8);
// endregion: Resource
// region: Components
#[derive(Component)]
struct Velocity {
pub x: f32,
pub y: f32,
}
#[derive(Component)]
pub struct Movable {
pub auto_despawn: bool,
}
#[derive(Component)]
pub struct Laser;
#[derive(Component)]
pub struct SpriteSize(pub Vec2);
impl From<(f32, f32)> for SpriteSize {
fn from(val: (f32, f32)) -> Self {
SpriteSize(Vec2::new(val.0, val.1))
}
}
#[derive(Component)]
pub struct FromPlayer;
#[derive(Component)]
pub struct FromEnemy;
// endregion: Components
fn main() {
App::new()
// アプリケーションの背景色を指定します。
.insert_resource(ClearColor(Color::srgb(0.04, 0.04, 0.04)))
// ウィンドウのタイトルと解像度を指定します。
.add_plugins(DefaultPlugins.set(WindowPlugin {
primary_window: Some(Window {
title: "Invaders".into(),
resolution: (600, 800).into(),
..Default::default()
}),
..Default::default()
}))
.add_plugins(EnemyPlugin)
.add_plugins(PlayerPlugin)
.add_systems(Startup, setup)
.add_systems(Update, movable_system)
.add_systems(Update, player_laser_hit_enemy_system)
.add_systems(Update, enemy_laser_hit_player_system)
.run();
}
fn setup(mut commands: Commands, query: Query<&Window, With<PrimaryWindow>>) {
// 2D カメラを設置
commands.spawn(Camera2d);
// ウィンドウのサイズを取得
let Ok(primary) = query.single() else {
return;
};
let (win_w, win_h) = (primary.width(), primary.height());
// ウィンドウのサイズをリソースとして保存
let win_size = WinSize { w: win_w, h: win_h };
commands.insert_resource(win_size);
// プレイヤーとエネミーのカウントをリソースとして保存
commands.insert_resource(PlayerCount(0));
commands.insert_resource(EnemyCount(0));
}
fn movable_system(
mut commands: Commands,
win_size: Res<WinSize>,
mut query: Query<(Entity, &Velocity, &mut Transform, &Movable)>,
) {
for (entity, velocity, mut transform, movable) in query.iter_mut() {
let translation = &mut transform.translation;
translation.x += velocity.x * BASE_SPEED;
translation.y += velocity.y * BASE_SPEED;
if movable.auto_despawn {
const MARGIN: f32 = 200.;
if translation.y > win_size.h / 2. + MARGIN
|| translation.y < -win_size.h / 2. - MARGIN
|| translation.x > win_size.w / 2. + MARGIN
|| translation.x < -win_size.w / 2. - MARGIN
{
// println!("Despawned an entity {:?}", entity);
commands.entity(entity).despawn();
}
}
}
}
fn player_laser_hit_enemy_system(
mut commands: Commands,
mut enemy_count: ResMut<EnemyCount>,
mut laser_query: Query<(Entity, &Transform, &SpriteSize), (With<Laser>, With<FromPlayer>)>,
mut enemy_query: Query<(Entity, &Transform, &SpriteSize), With<Enemy>>,
) {
for (laser_entity, laser_transform, laser_size) in laser_query.iter_mut() {
let laser_pos = laser_transform.translation;
let laser_scale = laser_transform.scale.xy();
for (enemy_entity, enemy_transform, enemy_size) in enemy_query.iter_mut() {
let enemy_pos = enemy_transform.translation;
let enemy_scale = enemy_transform.scale.xy();
// determine if collision
let collision =
Aabb2d::new(laser_pos.truncate(), (laser_size.0 * laser_scale) / 2.).intersects(
&Aabb2d::new(enemy_pos.truncate(), (enemy_size.0 * enemy_scale) / 2.),
);
// perform collision
if collision {
// remove the enemy
commands.entity(enemy_entity).despawn();
enemy_count.0 -= 1;
// remove the laser
commands.entity(laser_entity).despawn();
}
}
}
}
fn enemy_laser_hit_player_system(
mut commands: Commands,
mut player_count: ResMut<PlayerCount>,
mut laser_query: Query<(Entity, &Transform, &SpriteSize), (With<Laser>, With<FromEnemy>)>,
mut player_query: Query<(Entity, &Transform, &SpriteSize), With<Player>>,
) {
if let Ok((player_entity, player_transform, player_size)) = player_query.single_mut() {
let player_pos = player_transform.translation;
let player_scale = player_transform.scale.xy();
for (laser_entity, laser_transform, laser_size) in laser_query.iter_mut() {
let laser_pos = laser_transform.translation;
let laser_scale = laser_transform.scale.xy();
// determine if collision
let collision =
Aabb2d::new(laser_pos.truncate(), (laser_size.0 * laser_scale) / 2.).intersects(
&Aabb2d::new(player_pos.truncate(), (player_size.0 * player_scale) / 2.),
);
// perform collision
if collision {
// remove the player
commands.entity(player_entity).despawn();
player_count.0 -= 1;
// remove the laser
commands.entity(laser_entity).despawn();
}
}
}
}