-
Notifications
You must be signed in to change notification settings - Fork 2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Feedback #1
base: feedback
Are you sure you want to change the base?
Feedback #1
Changes from 11 commits
8435f5a
a1bee8b
4f42bee
be8350e
8f1dea0
b129124
77f106e
b7d6086
6062c67
969a5c8
fb3e0b2
bc4a368
96ae00e
c852d03
b28c0c0
989bbe2
b44a3f3
5beadf6
c31c446
c8200c6
b647db7
d704378
ca9c16d
02092c2
b7d2e5c
46862ee
b02da3a
742d98c
1a20fb2
de3382e
1e6dc69
f1d3e82
420fe5c
bad074d
08b3b5c
a2c4488
2489769
6086f20
49d702f
f7c0f87
c88f506
1e346ab
c4d618f
154fcdc
9235489
5436742
3d0bbb0
22e0eb5
86e2932
ac53128
285629c
15d88d1
99f2605
0f4762a
2f201d3
6cc72f2
350b543
f913617
e2ad785
71793a8
0438c1c
3941b06
e180d88
3a06087
5569af3
89a9b6b
ebca2f4
9b6e602
c73de5d
cf37120
1fa3970
96b6b70
df7c20e
f271749
7d74257
2e65fe1
b79b719
6d1958d
595c98c
8a23c4a
4aedda0
d34979e
2b40988
a29980f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
.idea | ||
Cargo.lock | ||
/target |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
[package] | ||
name = "mario_mim" | ||
version = "0.1.0" | ||
edition = "2021" | ||
|
||
[dependencies] | ||
bevy = "0.7" | ||
bevy_rapier2d = "0.13.2" | ||
rand = "*" | ||
|
||
[profile.dev.package.bevy_rapier2d] | ||
opt-level = 3 |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,27 +1,60 @@ | ||
# Frobnicator | ||
# Placeholder na chadowy tytuł | ||
|
||
## Autorzy | ||
- Andrzej Głuszak (gr 9, @agluszak na githubie) | ||
- Linus Torvalds (Uniwersytet Helsiński, @torvalds na githubie) | ||
[Katarzyna Kloc](https://github.com/KatKlo) - [email protected]\ | ||
[Patryk Bundyra](https://github.com/PBundyra) - [email protected] | ||
|
||
## Opis | ||
Od zawsze chcieliśmy napisać grę komputerową. | ||
Frobnicator będzie to gra platformowa, w której chodzi o to, żeby... | ||
Odkąd CLion wypluł pierwsze segfaulty chcieliśmy napisać grę komputerową inspirowaną studencką przygodą na MIMie.\ | ||
GigaChadTytuł będzie to gra platformowa, w której chodzi o to, żeby… zdać. Chcemy stworzyć grę inspirowaną Super Mario Bros, ale w mimowskim wydaniu. Student będzie musiał pokonać bugi, wzmonić się pijąc kawę i kto wie, może nawet stawi czoła niektórym prowadzącym... | ||
|
||
Z grubsza będziemy wzorować się na [tym tutorialu](https://dev.to/sbelzile/rust-platformer-part-1-bevy-and-ecs-2pci). | ||
Z grubsza będziemy wzorować się na [tym tutorialu](https://dev.to/sbelzile/rust-platformer-part-1-bevy-and-ecs-2pci) oraz [oficjalnych przykładach uzycia](https://github.com/bevyengine/bevy/tree/latest/examples) | ||
|
||
## Funkcjonalność | ||
- Generowanie map | ||
- Strzelanie | ||
- AI dla wrogów (bardziej rozbudowane niż w tutorialu) | ||
- Możliwość zapisywania i wczytywania stanu gry | ||
- Punktacja | ||
## Funkcjonalności | ||
- generowanie losowych map | ||
- ruch gracza po mapie z przeszkodami | ||
- pokonywanie łatwych przeciwników | ||
- zbieranie wzmocnień (np. szybszy ruch/dalszy skok) | ||
- walka z finałowym bossem | ||
- checkpointy | ||
|
||
## Propozycja podziału na części | ||
W pierwszej części stworzymy grę opartą na tutorialu (z lepszym AI) i jedną zahardcodowaną planszą. | ||
W pierwszej części stworzymy grę opartą na tutorialu z podstawowymi funkcjonalnościami takimi jak: | ||
- generowanie mapy | ||
- generowanie przeciwnikow | ||
- interakcja z przeciwnikami | ||
- wzmocnienia | ||
- menu początowe | ||
|
||
W drugiej części dodamy do tego losowy generator map, zapisywanie/wczytywanie stanu gry oraz system punktacji. | ||
W drugiej części dodamy: | ||
- nowy rodzaj łatwych przeciwników | ||
- finałowego bossa | ||
- podział na poziomu na checkpointy z rosnącym poziomem trudności | ||
- menu końcowe | ||
- efekty dzwiękowe | ||
- zdeployujemy grę używając WebAssembly | ||
- parę easter eggów ;) | ||
|
||
## Biblioteki | ||
- Bevy | ||
- może coś do serializacji danych? (czy mógłby Pan coś polecić?) | ||
|
||
## Update po 1 części | ||
|
||
Robiąc pierwszą część korzystaliśmy głównie z tych tutoriali: | ||
|
||
- https://dev.to/sbelzile/rust-platformer-part-1-bevy-and-ecs-2pci | ||
- https://www.youtube.com/watch?v=j7qHwb7geIM&ab_channel=JeremyChone | ||
- https://www.youtube.com/watch?v=Yb3vInxzKGE&list=PL7r-PXl6ZPcCB_9zZFU0krBoGK3y5f5Vt&index=5&ab_channel=JeremyChone | ||
|
||
oraz z dokumentacji i przykładów do Bevy oraz Rapiera. | ||
|
||
Choć dużą część kodu wzieliśmy z ww. poradników, to używając najnowszej wersji Bevy musieliśmy przekształcić znaczną ilość kodu. Bardzo miło nam przyznać, że wywiązaliśmy się z wszystkich naszych zapowiedzi i zaimplementowaliśmy wszystkie przewidziane feature’y czyli: | ||
- generowanie mapy | ||
- generowanie przeciwnikow | ||
- interakcja z przeciwnikami | ||
- wzmocnienia | ||
- menu początowe | ||
|
||
Widzimy też pole na poprawę i rzeczy które chcemy dodać w kolejnej części projektu. Są to m. in. timery i fizykę wzmocnień (bardzo uciążliwe, bo rapier nie posiada akutalnej dokumentacji), czy dodanie własnych eventów i obsługa pewnych akcji w grze właśnie przez customowe eventy. Duża częśc logiki gry polega na losowaniu. To gdzie zostanie umieszczony przeciwnik, kiedy skoczy, jakie dostaniemy wzmocnienie jest oparte na z góry zadanym prawdopobieństwu. Korzystając z komponentów pogrupowaliśmy odpowiednie struktury, takie jak Enemy, albo Booster, dzięki czemu zapewniliśmy skalowalność rozwiązania i zostawiliśmy sobie furtkę na dodanie kolejnych przeciwników i wzmocnień. Mimo, że żeby zapewnić rozgrywkę na wysokim poziomie potrzeba jeszcze dużo pracy, to gra jest obecnie w niezłym stanie, można w nią sensownie pograć i mieć odrobinę frajdy - gwarantujemy jej zwiększenie w kolejnej części :) | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,138 @@ | ||
use crate::game::{Booster, Coffee, Player, Rust}; | ||
use crate::GameTextures; | ||
use bevy::prelude::*; | ||
use bevy_rapier2d::prelude::*; | ||
use rand::{thread_rng, Rng}; | ||
|
||
const CHANCE_OF_SPAWNING_COFFEE: f64 = 0.1; | ||
const CHANCE_OF_SPAWNING_RUST: f64 = 0.03; | ||
|
||
pub fn insert_coffee_at( | ||
commands: &mut Commands, | ||
player_textures: &Res<GameTextures>, | ||
x: f32, | ||
y: f32, | ||
) { | ||
commands | ||
.spawn_bundle(SpriteBundle { | ||
texture: player_textures.coffee.clone(), | ||
sprite: Sprite { | ||
custom_size: Some(Vec2::new(0.99, 0.99)), | ||
..default() | ||
}, | ||
..default() | ||
}) | ||
.insert(RigidBody::Dynamic) | ||
.insert(Transform::from_xyz(x, y, 10.0)) | ||
.insert(LockedAxes::ROTATION_LOCKED) | ||
.insert(Sleeping::disabled()) | ||
.insert(GravityScale(0.3)) | ||
.insert(Velocity { | ||
linvel: Vec2::new(0.0, 0.0), | ||
..default() | ||
}) | ||
.insert(Ccd::enabled()) | ||
.insert(Collider::round_cuboid(0.05, 0.05, 0.1)) | ||
.insert(ActiveEvents::COLLISION_EVENTS) | ||
.insert(Coffee) | ||
.insert(Booster); | ||
} | ||
|
||
pub fn insert_rust_at( | ||
commands: &mut Commands, | ||
player_textures: &Res<GameTextures>, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Przecież to nie player textures |
||
x: f32, | ||
y: f32, | ||
) { | ||
commands | ||
.spawn_bundle(SpriteBundle { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Potwarza się ten kod, można wyciągnąć do funkcji (i w bevy chyba jaklś da się te bundle robić z parametrami?) |
||
texture: player_textures.rust.clone(), | ||
sprite: Sprite { | ||
custom_size: Some(Vec2::new(0.99, 0.99)), | ||
..default() | ||
}, | ||
..default() | ||
}) | ||
.insert(RigidBody::Dynamic) | ||
.insert(Transform::from_xyz(x, y, 10.0)) | ||
.insert(LockedAxes::ROTATION_LOCKED) | ||
.insert(Sleeping::disabled()) | ||
.insert(GravityScale(0.3)) | ||
.insert(Velocity { | ||
linvel: Vec2::new(0.0, 0.0), | ||
..default() | ||
}) | ||
.insert(Ccd::enabled()) | ||
.insert(Collider::round_cuboid(0.05, 0.05, 0.1)) | ||
.insert(ActiveEvents::COLLISION_EVENTS) | ||
.insert(Rust) | ||
.insert(Booster); | ||
} | ||
|
||
pub fn drink_coffee( | ||
mut commands: Commands, | ||
mut players: Query<(Entity, &mut Player)>, | ||
coffees: Query<Entity, With<Coffee>>, | ||
mut collision_events: EventReader<CollisionEvent>, | ||
) { | ||
for collision_event in collision_events.iter() { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Też się powtarza |
||
if let CollisionEvent::Started(h1, h2, _) = collision_event { | ||
for (player_entity, mut player) in players.iter_mut() { | ||
for coffee in coffees.iter() { | ||
if (*h1 == player_entity && *h2 == coffee) | ||
|| (*h1 == coffee && *h2 == player_entity) | ||
{ | ||
player.increase_speed(); | ||
commands.entity(coffee).despawn_recursive(); | ||
} | ||
} | ||
} | ||
} | ||
} | ||
} | ||
|
||
pub fn learn_rust( | ||
mut commands: Commands, | ||
mut players: Query<(Entity, &mut Player)>, | ||
rusts: Query<Entity, With<Rust>>, | ||
mut collision_events: EventReader<CollisionEvent>, | ||
) { | ||
for collision_event in collision_events.iter() { | ||
if let CollisionEvent::Started(h1, h2, _) = collision_event { | ||
for (player_entity, mut player) in players.iter_mut() { | ||
for rust in rusts.iter() { | ||
if (*h1 == player_entity && *h2 == rust) | ||
|| (*h1 == rust && *h2 == player_entity) | ||
{ | ||
player.powerup_weapon(); | ||
commands.entity(rust).despawn_recursive(); | ||
} | ||
} | ||
} | ||
} | ||
} | ||
} | ||
|
||
pub fn add_boosters(commands: &mut Commands, world: &[usize], player_texture: Res<GameTextures>) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Tutaj też: nie wiem skąd się to player wzięło |
||
world.iter().enumerate().for_each(|(x, height)| { | ||
if should_add_coffee(x) { | ||
insert_coffee_at(commands, &player_texture, x as f32, *height as f32 + 0.25); | ||
} else if should_add_rust(x) { | ||
insert_rust_at(commands, &player_texture, x as f32, *height as f32 + 0.25); | ||
} | ||
}); | ||
} | ||
|
||
fn should_add_coffee(x: usize) -> bool { | ||
if x <= 5 { | ||
return false; | ||
} | ||
thread_rng().gen_bool(CHANCE_OF_SPAWNING_COFFEE) | ||
} | ||
|
||
fn should_add_rust(x: usize) -> bool { | ||
if x <= 15 { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Magiczna stała |
||
return false; | ||
} | ||
thread_rng().gen_bool(CHANCE_OF_SPAWNING_RUST) | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,144 @@ | ||
use bevy::prelude::*; | ||
use bevy_rapier2d::prelude::*; | ||
|
||
use crate::game::{Bullet, Enemy, Player, StrongBullet}; | ||
use crate::GameTextures; | ||
|
||
use super::{GameDirection, WeakBullet}; | ||
|
||
const WEAK_BULLET_SPEED: f32 = 8.25; | ||
const STRONG_BULLET_SPEED: f32 = 18.5; | ||
|
||
#[derive(Copy, Clone)] | ||
pub struct BulletOptions { | ||
pub x: f32, | ||
pub y: f32, | ||
pub direction: GameDirection, | ||
pub player_vex: f32, | ||
} | ||
|
||
pub fn insert_weak_bullet_at( | ||
commands: &mut Commands, | ||
options: BulletOptions, | ||
game_textures: &mut Res<GameTextures>, | ||
) { | ||
let vel_x: f32; | ||
let spawn_x: f32; | ||
match options.direction { | ||
GameDirection::Left => { | ||
vel_x = -WEAK_BULLET_SPEED + options.player_vex * 0.15; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nie rozumiem co to za obliczenia się tu odbywają |
||
spawn_x = -0.75; | ||
} | ||
GameDirection::Right => { | ||
vel_x = WEAK_BULLET_SPEED + options.player_vex * 0.15; | ||
spawn_x = 0.75 | ||
} | ||
} | ||
commands | ||
.spawn_bundle(SpriteBundle { | ||
texture: game_textures.weak_laser.clone(), | ||
sprite: Sprite { | ||
custom_size: Some(Vec2::new(0.5, 0.2)), | ||
..default() | ||
}, | ||
..default() | ||
}) | ||
.insert(RigidBody::Dynamic) | ||
.insert(Transform::from_xyz(options.x + spawn_x, options.y, 10.0)) | ||
.insert(LockedAxes::ROTATION_LOCKED) | ||
.insert(Sleeping::disabled()) | ||
.insert(GravityScale(0.0)) | ||
.insert(Velocity { | ||
linvel: Vec2::new(vel_x, 0.0), | ||
..default() | ||
}) | ||
.insert(Ccd::enabled()) | ||
.insert(Collider::round_cuboid(0.25, 0.05, 0.1)) | ||
.insert(ActiveEvents::COLLISION_EVENTS) | ||
.insert(WeakBullet) | ||
.insert(Bullet); | ||
} | ||
|
||
pub fn insert_strong_bullet_at( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Powtórzony kod |
||
commands: &mut Commands, | ||
options: BulletOptions, | ||
game_textures: &mut Res<GameTextures>, | ||
) { | ||
let vel_x: f32; | ||
let spawn_x: f32; | ||
match options.direction { | ||
GameDirection::Left => { | ||
vel_x = -STRONG_BULLET_SPEED + options.player_vex * 0.15; | ||
spawn_x = -0.75; | ||
} | ||
GameDirection::Right => { | ||
vel_x = STRONG_BULLET_SPEED + options.player_vex * 0.15; | ||
spawn_x = 0.75 | ||
} | ||
} | ||
commands | ||
.spawn_bundle(SpriteBundle { | ||
texture: game_textures.strong_laser.clone(), | ||
sprite: Sprite { | ||
custom_size: Some(Vec2::new(0.5, 0.2)), | ||
..default() | ||
}, | ||
..default() | ||
}) | ||
.insert(RigidBody::Dynamic) | ||
.insert(Transform::from_xyz(options.x + spawn_x, options.y, 10.0)) | ||
.insert(LockedAxes::ROTATION_LOCKED) | ||
.insert(Sleeping::disabled()) | ||
.insert(GravityScale(0.0)) | ||
.insert(Velocity { | ||
linvel: Vec2::new(vel_x, 0.0), | ||
..default() | ||
}) | ||
.insert(Ccd::enabled()) | ||
.insert(Collider::round_cuboid(0.25, 0.05, 0.1)) | ||
.insert(ActiveEvents::COLLISION_EVENTS) | ||
.insert(StrongBullet) | ||
.insert(Bullet); | ||
} | ||
|
||
pub fn destroy_bullet_on_contact( | ||
mut commands: Commands, | ||
bullets: Query<Entity, With<Bullet>>, | ||
mut collision_events: EventReader<CollisionEvent>, | ||
players: Query<Entity, With<Player>>, | ||
) { | ||
for collision_event in collision_events.iter() { | ||
if let CollisionEvent::Started(h1, h2, _) = collision_event { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Czemu h? |
||
for bullet in bullets.iter() { | ||
if (*h1 == bullet | ||
&& !players.iter().any(|b| *h2 == b) | ||
&& !bullets.iter().any(|b| *h2 == b)) | ||
|| (*h2 == bullet | ||
&& !players.iter().any(|b| *h1 == b) | ||
&& !bullets.iter().any(|b| *h1 == b)) | ||
{ | ||
commands.entity(bullet).despawn_recursive(); | ||
} | ||
} | ||
} | ||
} | ||
} | ||
|
||
pub fn killing_enemies( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Niespójność: powinno być kill_enemies |
||
mut commands: Commands, | ||
bullets: Query<Entity, With<Bullet>>, | ||
enemies: Query<Entity, With<Enemy>>, | ||
mut collision_event: EventReader<CollisionEvent>, | ||
) { | ||
for collision_event in collision_event.iter() { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. To też powtórzony kod |
||
if let CollisionEvent::Started(h1, h2, _) = collision_event { | ||
for bullet in bullets.iter() { | ||
for enemy in enemies.iter() { | ||
if (*h1 == bullet && *h2 == enemy) || (*h1 == enemy && *h2 == bullet) { | ||
commands.entity(enemy).despawn_recursive(); | ||
} | ||
} | ||
} | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Lepiej specyfikować major wersję