All lock delay modes implemented

This commit is contained in:
dan63047 2023-11-15 00:10:01 +03:00
parent 95987c5526
commit da41c6e030
3 changed files with 196 additions and 103 deletions

View File

@ -140,6 +140,7 @@ pub struct Engine {
pub lock_delay_left: u8, pub lock_delay_left: u8,
pub lock_delay_resets: u8, pub lock_delay_resets: u8,
pub lock_delay_resets_left: u8, pub lock_delay_resets_left: u8,
pub lock_delay_active: bool,
pub need_to_lock: bool, // when lock resets ended pub need_to_lock: bool, // when lock resets ended
} }
@ -160,6 +161,7 @@ impl Default for Engine {
lock_delay_left: 30, lock_delay_left: 30,
lock_delay_resets: 15, lock_delay_resets: 15,
lock_delay_resets_left: 15, lock_delay_resets_left: 15,
lock_delay_active: false,
need_to_lock: false, need_to_lock: false,
randomizer: Box::new(Bag{}), randomizer: Box::new(Bag{}),
} }
@ -244,20 +246,15 @@ impl Engine {
y y
} }
fn lock_delay_check(&mut self, shift: (i8, i8)){ fn reset_lock_delay(&mut self, shift: (i8, i8)){
match self.rotation_system.lock_delay_mode { match self.rotation_system.lock_delay_mode {
LockDelayMode::Disabled => {}, LockDelayMode::Disabled => {},
LockDelayMode::Gravity => {}, LockDelayMode::Gravity => {
LockDelayMode::ResetOnYChange => { if self.position_is_valid((self.current_piece.as_ref().unwrap().position.0, self.current_piece.as_ref().unwrap().position.1-1), self.current_piece.as_ref().unwrap().rotation) {
if shift.1 < 0 { self.lock_delay_active = false;
self.lock_delay_left = self.lock_delay;
if self.lock_delay_resets_left == 0{
self.need_to_lock = true;
}else{
self.lock_delay_resets_left -= 1;
}
} }
}, },
LockDelayMode::ResetOnYChange => {},
LockDelayMode::ResetOnMovementLimited => { LockDelayMode::ResetOnMovementLimited => {
if !self.position_is_valid((self.current_piece.as_ref().unwrap().position.0, self.current_piece.as_ref().unwrap().position.1-1), self.current_piece.as_ref().unwrap().rotation){ if !self.position_is_valid((self.current_piece.as_ref().unwrap().position.0, self.current_piece.as_ref().unwrap().position.1-1), self.current_piece.as_ref().unwrap().rotation){
self.lock_delay_left = self.lock_delay; self.lock_delay_left = self.lock_delay;
@ -265,12 +262,14 @@ impl Engine {
self.need_to_lock = true; self.need_to_lock = true;
}else{ }else{
self.lock_delay_resets_left -= 1; self.lock_delay_resets_left -= 1;
self.lock_delay_active = false;
} }
} }
}, },
LockDelayMode::ResetOnMovement => { LockDelayMode::ResetOnMovement => {
if !self.position_is_valid((self.current_piece.as_ref().unwrap().position.0, self.current_piece.as_ref().unwrap().position.1-1), self.current_piece.as_ref().unwrap().rotation){ if !self.position_is_valid((self.current_piece.as_ref().unwrap().position.0, self.current_piece.as_ref().unwrap().position.1-1), self.current_piece.as_ref().unwrap().rotation){
self.lock_delay_left = self.lock_delay; self.lock_delay_left = self.lock_delay;
self.lock_delay_active = false;
} }
}, },
} }
@ -286,7 +285,7 @@ impl Engine {
}else{ }else{
1 1
}; };
self.lock_delay_check((0, 0)); self.reset_lock_delay((0, 0));
for test in &self.rotation_system.kicks[self.current_piece.as_ref().unwrap().id][self.current_piece.as_ref().unwrap().rotation][id_for_kicks]{ for test in &self.rotation_system.kicks[self.current_piece.as_ref().unwrap().id][self.current_piece.as_ref().unwrap().rotation][id_for_kicks]{
let future_position = (self.current_piece.as_ref().unwrap().position.0 + test.0 as isize, self.current_piece.as_ref().unwrap().position.1 + test.1 as isize); let future_position = (self.current_piece.as_ref().unwrap().position.0 + test.0 as isize, self.current_piece.as_ref().unwrap().position.1 + test.1 as isize);
if self.position_is_valid(future_position, future_rotation) { if self.position_is_valid(future_position, future_rotation) {
@ -307,7 +306,7 @@ impl Engine {
self.current_piece.as_ref().unwrap().position.1 + shift.1 as isize // future Y self.current_piece.as_ref().unwrap().position.1 + shift.1 as isize // future Y
); );
if self.position_is_valid(future_position, self.current_piece.as_ref().unwrap().rotation) { if self.position_is_valid(future_position, self.current_piece.as_ref().unwrap().rotation) {
if shift.0 != 0 {self.lock_delay_check(shift);} if shift.0 != 0 {self.reset_lock_delay(shift);}
self.current_piece.as_mut().unwrap().position = future_position; self.current_piece.as_mut().unwrap().position = future_position;
true true
}else { }else {

View File

@ -1,6 +1,6 @@
use bevy::{prelude::*, sprite::MaterialMesh2dBundle}; use super::{resources::Engine, rotation_systems::LockDelayMode, GameStates, GameloopStates};
use crate::engine::components::*; use crate::engine::components::*;
use super::{resources::Engine, GameloopStates, GameStates}; use bevy::{prelude::*, sprite::MaterialMesh2dBundle};
const MINO_SIZE: f32 = 20.0; const MINO_SIZE: f32 = 20.0;
@ -10,15 +10,23 @@ pub fn init_engine(
mut materials: ResMut<Assets<ColorMaterial>>, mut materials: ResMut<Assets<ColorMaterial>>,
mut engine: ResMut<Engine>, mut engine: ResMut<Engine>,
mut next_state: ResMut<NextState<GameloopStates>>, mut next_state: ResMut<NextState<GameloopStates>>,
){ ) {
commands.spawn(( commands.spawn((
MaterialMesh2dBundle { MaterialMesh2dBundle {
mesh: meshes.add(Mesh::from(shape::Quad{ size: Vec2 { x: engine.board.width as f32 * MINO_SIZE, y: engine.board.height as f32 * MINO_SIZE }, flip: false })).into(), mesh: meshes
.add(Mesh::from(shape::Quad {
size: Vec2 {
x: engine.board.width as f32 * MINO_SIZE,
y: engine.board.height as f32 * MINO_SIZE,
},
flip: false,
}))
.into(),
material: materials.add(ColorMaterial::from(Color::PURPLE)), material: materials.add(ColorMaterial::from(Color::PURPLE)),
transform: Transform::from_xyz(0.0, 0.0, -1.0), transform: Transform::from_xyz(0.0, 0.0, -1.0),
..default() ..default()
}, },
BoardVisual{} BoardVisual {},
)); ));
engine.init("SRS"); engine.init("SRS");
next_state.set(GameloopStates::Falling); next_state.set(GameloopStates::Falling);
@ -28,8 +36,8 @@ pub fn draw_board(
mut commands: Commands, mut commands: Commands,
engine: Res<Engine>, engine: Res<Engine>,
all_minos: Query<Entity, With<Mino>>, all_minos: Query<Entity, With<Mino>>,
asset_server: Res<AssetServer> asset_server: Res<AssetServer>,
){ ) {
for mino in all_minos.iter() { for mino in all_minos.iter() {
commands.entity(mino).despawn(); commands.entity(mino).despawn();
} }
@ -44,14 +52,19 @@ pub fn draw_board(
commands.spawn(( commands.spawn((
SpriteBundle { SpriteBundle {
transform: Transform::from_xyz( transform: Transform::from_xyz(
x*MINO_SIZE-(engine.board.width as f32)/2.0*MINO_SIZE+MINO_SIZE/2.0, x * MINO_SIZE - (engine.board.width as f32) / 2.0 * MINO_SIZE
y*MINO_SIZE-(engine.board.height as f32)/2.0*MINO_SIZE+MINO_SIZE/2.0, + MINO_SIZE / 2.0,
0.0 y * MINO_SIZE - (engine.board.height as f32) / 2.0 * MINO_SIZE
+ MINO_SIZE / 2.0,
0.0,
), ),
texture: asset_server.load("default_mino.png"), texture: asset_server.load("default_mino.png"),
sprite: Sprite { sprite: Sprite {
color: mino.color, color: mino.color,
custom_size: Some(Vec2 {x: MINO_SIZE, y: MINO_SIZE}), custom_size: Some(Vec2 {
x: MINO_SIZE,
y: MINO_SIZE,
}),
..default() ..default()
}, },
..default() ..default()
@ -59,7 +72,7 @@ pub fn draw_board(
*mino, *mino,
)); ));
} }
None => {}, None => {}
}; };
x += 1.0; x += 1.0;
} }
@ -72,50 +85,68 @@ pub fn draw_board(
Some(piece) => { Some(piece) => {
x = piece.position.0 as f32; x = piece.position.0 as f32;
y = piece.position.1 as f32; y = piece.position.1 as f32;
for mino in &engine.rotation_system.pieces[piece.id][piece.rotation]{ for mino in &engine.rotation_system.pieces[piece.id][piece.rotation] {
commands.spawn(( commands.spawn((
SpriteBundle { SpriteBundle {
transform: Transform::from_xyz( transform: Transform::from_xyz(
x*MINO_SIZE - (engine.board.width as f32)/2.0*MINO_SIZE + MINO_SIZE/2.0 + mino.0 as f32 * MINO_SIZE, x * MINO_SIZE - (engine.board.width as f32) / 2.0 * MINO_SIZE
y*MINO_SIZE - (engine.board.height as f32)/2.0*MINO_SIZE + MINO_SIZE/2.0 + mino.1 as f32 * MINO_SIZE, + MINO_SIZE / 2.0
1.0 + mino.0 as f32 * MINO_SIZE,
y * MINO_SIZE - (engine.board.height as f32) / 2.0 * MINO_SIZE
+ MINO_SIZE / 2.0
+ mino.1 as f32 * MINO_SIZE,
1.0,
), ),
texture: asset_server.load("default_mino.png"), texture: asset_server.load("default_mino.png"),
sprite: Sprite { sprite: Sprite {
color: engine.rotation_system.colours[piece.id], color: engine.rotation_system.colours[piece.id],
custom_size: Some(Vec2 {x: MINO_SIZE, y: MINO_SIZE}), custom_size: Some(Vec2 {
x: MINO_SIZE,
y: MINO_SIZE,
}),
..default() ..default()
}, },
..default() ..default()
}, },
Mino{color: engine.rotation_system.colours[piece.id]}, Mino {
color: engine.rotation_system.colours[piece.id],
},
)); ));
} }
}, }
None => {}, None => {}
} }
// draw next queue // draw next queue
if engine.board.show_next > 0 { if engine.board.show_next > 0 {
y = 8.0; y = 8.0;
for i in 0..engine.board.show_next as usize{ for i in 0..engine.board.show_next as usize {
for mino in &engine.rotation_system.pieces[engine.next_queue[i].id][engine.next_queue[i].rotation]{ for mino in &engine.rotation_system.pieces[engine.next_queue[i].id]
[engine.next_queue[i].rotation]
{
commands.spawn(( commands.spawn((
SpriteBundle { SpriteBundle {
transform: Transform::from_xyz( transform: Transform::from_xyz(
11.0*MINO_SIZE - (engine.board.width as f32)/2.0*MINO_SIZE + MINO_SIZE/2.0 + mino.0 as f32 * MINO_SIZE, 11.0 * MINO_SIZE - (engine.board.width as f32) / 2.0 * MINO_SIZE
y* MINO_SIZE + MINO_SIZE/2.0 + mino.1 as f32 * MINO_SIZE, + MINO_SIZE / 2.0
0.0 + mino.0 as f32 * MINO_SIZE,
y * MINO_SIZE + MINO_SIZE / 2.0 + mino.1 as f32 * MINO_SIZE,
0.0,
), ),
texture: asset_server.load("default_mino.png"), texture: asset_server.load("default_mino.png"),
sprite: Sprite { sprite: Sprite {
color: engine.rotation_system.colours[engine.next_queue[i].id], color: engine.rotation_system.colours[engine.next_queue[i].id],
custom_size: Some(Vec2 {x: MINO_SIZE, y: MINO_SIZE}), custom_size: Some(Vec2 {
x: MINO_SIZE,
y: MINO_SIZE,
}),
..default() ..default()
}, },
..default() ..default()
}, },
Mino{color: engine.rotation_system.colours[engine.next_queue[i].id]}, Mino {
color: engine.rotation_system.colours[engine.next_queue[i].id],
},
)); ));
} }
y -= 4.0; y -= 4.0;
@ -125,27 +156,35 @@ pub fn draw_board(
// draw hold // draw hold
match engine.hold.as_ref() { match engine.hold.as_ref() {
Some(piece) => { Some(piece) => {
for mino in &engine.rotation_system.pieces[piece.id][piece.rotation]{ for mino in &engine.rotation_system.pieces[piece.id][piece.rotation] {
commands.spawn(( commands.spawn((
SpriteBundle { SpriteBundle {
transform: Transform::from_xyz( transform: Transform::from_xyz(
-5.0*MINO_SIZE - (engine.board.width as f32)/2.0*MINO_SIZE + MINO_SIZE/2.0 + mino.0 as f32 * MINO_SIZE, -5.0 * MINO_SIZE - (engine.board.width as f32) / 2.0 * MINO_SIZE
-2.0*MINO_SIZE + (engine.board.height as f32)/2.0*MINO_SIZE + MINO_SIZE/2.0 + mino.1 as f32 * MINO_SIZE, + MINO_SIZE / 2.0
0.0 + mino.0 as f32 * MINO_SIZE,
-2.0 * MINO_SIZE
+ (engine.board.height as f32) / 2.0 * MINO_SIZE
+ MINO_SIZE / 2.0
+ mino.1 as f32 * MINO_SIZE,
0.0,
), ),
texture: asset_server.load("default_mino.png"), texture: asset_server.load("default_mino.png"),
sprite: Sprite { sprite: Sprite {
color: piece.color, color: piece.color,
custom_size: Some(Vec2 {x: MINO_SIZE, y: MINO_SIZE}), custom_size: Some(Vec2 {
x: MINO_SIZE,
y: MINO_SIZE,
}),
..default() ..default()
}, },
..default() ..default()
}, },
Mino{color: piece.color}, Mino { color: piece.color },
)); ));
} }
}, }
None => {}, None => {}
} }
// draw shadow // draw shadow
@ -154,27 +193,41 @@ pub fn draw_board(
Some(piece) => { Some(piece) => {
x = piece.position.0 as f32; x = piece.position.0 as f32;
y = engine.lowest_point_under_current_piece() as f32; y = engine.lowest_point_under_current_piece() as f32;
for mino in &engine.rotation_system.pieces[piece.id][piece.rotation]{ for mino in &engine.rotation_system.pieces[piece.id][piece.rotation] {
commands.spawn(( commands.spawn((
SpriteBundle { SpriteBundle {
transform: Transform::from_xyz( transform: Transform::from_xyz(
x*MINO_SIZE - (engine.board.width as f32)/2.0*MINO_SIZE + MINO_SIZE/2.0 + mino.0 as f32 * MINO_SIZE, x * MINO_SIZE - (engine.board.width as f32) / 2.0 * MINO_SIZE
y*MINO_SIZE - (engine.board.height as f32)/2.0*MINO_SIZE + MINO_SIZE/2.0 + mino.1 as f32 * MINO_SIZE, + MINO_SIZE / 2.0
0.0 + mino.0 as f32 * MINO_SIZE,
y * MINO_SIZE - (engine.board.height as f32) / 2.0 * MINO_SIZE
+ MINO_SIZE / 2.0
+ mino.1 as f32 * MINO_SIZE,
0.0,
), ),
texture: asset_server.load("default_mino.png"), texture: asset_server.load("default_mino.png"),
sprite: Sprite { sprite: Sprite {
color: Color::Rgba { red: 1.0, green: 1.0, blue: 1.0, alpha: 0.1 }, color: Color::Rgba {
custom_size: Some(Vec2 {x: MINO_SIZE, y: MINO_SIZE}), red: 1.0,
green: 1.0,
blue: 1.0,
alpha: 0.1,
},
custom_size: Some(Vec2 {
x: MINO_SIZE,
y: MINO_SIZE,
}),
..default() ..default()
}, },
..default() ..default()
}, },
Mino{color: engine.rotation_system.colours[piece.id]}, Mino {
color: engine.rotation_system.colours[piece.id],
},
)); ));
} }
}, }
None => {}, None => {}
} }
} }
} }
@ -184,8 +237,10 @@ pub fn receive_input(
mut engine: ResMut<Engine>, mut engine: ResMut<Engine>,
state: Res<State<GameloopStates>>, state: Res<State<GameloopStates>>,
mut next_state: ResMut<NextState<GameloopStates>>, mut next_state: ResMut<NextState<GameloopStates>>,
){ ) {
if keyboard_input.any_just_pressed([KeyCode::Up, KeyCode::X]) && state.get() == &GameloopStates::Falling { if keyboard_input.any_just_pressed([KeyCode::Up, KeyCode::X])
&& state.get() == &GameloopStates::Falling
{
engine.rotate_current_piece(1); engine.rotate_current_piece(1);
} }
if keyboard_input.just_pressed(KeyCode::Z) && state.get() == &GameloopStates::Falling { if keyboard_input.just_pressed(KeyCode::Z) && state.get() == &GameloopStates::Falling {
@ -225,13 +280,9 @@ pub fn receive_input(
} }
} }
pub fn das_and_arr( pub fn das_and_arr(mut engine: ResMut<Engine>, time: Res<Time>, state: Res<State<GameloopStates>>) {
mut engine: ResMut<Engine>, let direction = engine.handling.movement_tick(time.delta_seconds() * 1000.0);
time: Res<Time>, if state.get() == &GameloopStates::Falling {
state: Res<State<GameloopStates>>,
){
let direction = engine.handling.movement_tick(time.delta_seconds()*1000.0);
if state.get() == &GameloopStates::Falling{
engine.move_current_piece((direction, 0)); engine.move_current_piece((direction, 0));
} }
} }
@ -245,59 +296,99 @@ pub fn gameloop(
//info!("{:?}", clocks); //info!("{:?}", clocks);
match engine.current_piece { match engine.current_piece {
Some(piece) => { Some(piece) => {
if engine.handling.sdf_active {
engine.g_bucket += engine.g * engine.handling.sdf;
} else {
engine.g_bucket += engine.g; engine.g_bucket += engine.g;
if engine.handling.sdf_active {engine.g_bucket += engine.g * engine.handling.sdf} }
let mut gravity_tick_happend = false;
while engine.g_bucket >= 1.0 { while engine.g_bucket >= 1.0 {
engine.move_current_piece((0, -1)); engine.move_current_piece((0, -1));
engine.g_bucket -= 1.0; engine.g_bucket -= 1.0;
gravity_tick_happend = true;
} }
if !engine.position_is_valid((piece.position.0, piece.position.1-1), piece.rotation){ let previos_lock_delay_active = engine.lock_delay_active;
engine.lock_delay_active =
!engine.position_is_valid((piece.position.0, piece.position.1 - 1), piece.rotation);
if engine.lock_delay_active {
match engine.rotation_system.lock_delay_mode { match engine.rotation_system.lock_delay_mode {
super::rotation_systems::LockDelayMode::Disabled => { LockDelayMode::Disabled => {
engine.lock_current_piece(); engine.need_to_lock = true;
next_state.set(GameloopStates::AfterLocking);
return;
},
super::rotation_systems::LockDelayMode::Gravity => {engine.need_to_lock = true;},
super::rotation_systems::LockDelayMode::ResetOnYChange => {},
super::rotation_systems::LockDelayMode::ResetOnMovementLimited => {engine.lock_delay_left -= 1;},
super::rotation_systems::LockDelayMode::ResetOnMovement => {engine.lock_delay_left -= 1;}
} }
}else{ LockDelayMode::Gravity => {
if gravity_tick_happend && previos_lock_delay_active {
engine.need_to_lock = true;
}
}
LockDelayMode::ResetOnYChange => {
engine.lock_delay_left -= 1;
}
LockDelayMode::ResetOnMovementLimited => {
engine.lock_delay_left -= 1;
}
LockDelayMode::ResetOnMovement => {
engine.lock_delay_left -= 1;
}
}
} else {
if previos_lock_delay_active {
match engine.rotation_system.lock_delay_mode {
LockDelayMode::Disabled => {}
LockDelayMode::Gravity => {}
LockDelayMode::ResetOnYChange => {
engine.lock_delay_left = engine.lock_delay;
if engine.lock_delay_resets == 0 {
engine.need_to_lock = true;
} else {
engine.lock_delay_resets_left -= 1;
}
}
LockDelayMode::ResetOnMovementLimited => {
engine.lock_delay_left = engine.lock_delay; engine.lock_delay_left = engine.lock_delay;
} }
if (engine.lock_delay_left < 1 || engine.need_to_lock) && !engine.position_is_valid((piece.position.0, piece.position.1-1), piece.rotation){ LockDelayMode::ResetOnMovement => {
engine.lock_delay_left = engine.lock_delay;
}
}
}
}
if (engine.lock_delay_left < 1 || engine.need_to_lock)
&& !engine
.position_is_valid((piece.position.0, piece.position.1 - 1), piece.rotation)
{
engine.lock_current_piece(); engine.lock_current_piece();
next_state.set(GameloopStates::AfterLocking); next_state.set(GameloopStates::AfterLocking);
} }
}, }
None => { None => {}
},
} }
for mut text in lock_delay_text.iter_mut() { for mut text in lock_delay_text.iter_mut() {
text.sections[0].value = format!("{}; {}", engine.lock_delay_resets_left, engine.lock_delay_left); text.sections[0].value = format!(
"{}; {}",
engine.lock_delay_resets_left, engine.lock_delay_left
);
} }
} }
pub fn after_locking_routine( pub fn after_locking_routine(
mut engine: ResMut<Engine>, mut engine: ResMut<Engine>,
mut next_state: ResMut<NextState<GameloopStates>>, mut next_state: ResMut<NextState<GameloopStates>>,
){ ) {
engine.board.clear_full_lines(); engine.board.clear_full_lines();
engine.lock_delay_left = engine.lock_delay; engine.lock_delay_left = engine.lock_delay;
engine.lock_delay_resets_left = engine.lock_delay_resets; engine.lock_delay_resets_left = engine.lock_delay_resets;
engine.lock_delay_active = false;
next_state.set(GameloopStates::Spawn); next_state.set(GameloopStates::Spawn);
} }
pub fn spawn_routine( pub fn spawn_routine(
mut engine: ResMut<Engine>, mut engine: ResMut<Engine>,
mut next_state: ResMut<NextState<GameloopStates>>, mut next_state: ResMut<NextState<GameloopStates>>,
mut game_next_state: ResMut<NextState<GameStates>> mut game_next_state: ResMut<NextState<GameStates>>,
){ ) {
if engine.spawn_sequence(){ if engine.spawn_sequence() {
next_state.set(GameloopStates::Falling); next_state.set(GameloopStates::Falling);
}else{ } else {
game_next_state.set(GameStates::GameOver); game_next_state.set(GameStates::GameOver);
} }
} }

View File

@ -11,9 +11,11 @@ pub fn build_hud(commands: &mut Commands, asset_server: &Res<AssetServer>) -> En
NodeBundle { NodeBundle {
style: Style { style: Style {
display: Display::Flex, display: Display::Flex,
flex_direction: FlexDirection::Column, flex_direction: FlexDirection::Row,
justify_items: JustifyItems::Center, justify_content: JustifyContent::SpaceBetween,
align_items: AlignItems::Center, align_items: AlignItems::Center,
width: Val::Vw(100.0),
height: Val::Vh(100.0),
..default() ..default()
}, },
..default() ..default()
@ -25,9 +27,10 @@ pub fn build_hud(commands: &mut Commands, asset_server: &Res<AssetServer>) -> En
parent.spawn(( parent.spawn((
TextBundle { TextBundle {
style: Style { style: Style {
// position_type: PositionType::Absolute, position_type: PositionType::Absolute,
// top: Val::Percent(50.0), top: Val::Px(550.0),
// left: Val::Percent(50.0), left: Val::Percent(45.0),
align_self: AlignSelf::Center,
..default() ..default()
}, },
text: Text { text: Text {