wip
This commit is contained in:
parent
ada9131dfb
commit
77b263576c
4 changed files with 168 additions and 119 deletions
|
@ -1,9 +1,13 @@
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
pub type BlockOffsets = HashMap<usize, (u32, u32)>;
|
pub type BlockOffsets = HashMap<usize, (i32, i32)>;
|
||||||
|
|
||||||
|
// TODO: don't yeet around a HashMap all the time
|
||||||
pub type AnimationFn = Box<Fn(BlockOffsets, f32) -> BlockOffsets>;
|
pub type AnimationFn = Box<Fn(BlockOffsets, f32) -> BlockOffsets>;
|
||||||
|
|
||||||
|
const ANIMATION_DURATION: f32 = 1.0 / 6.0;
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct AnimationState {
|
pub struct AnimationState {
|
||||||
pub is_animating: bool,
|
pub is_animating: bool,
|
||||||
|
@ -21,9 +25,27 @@ impl AnimationState {
|
||||||
self.progress_function = Some(f);
|
self.progress_function = Some(f);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn make_progress(&mut self, delta: Duration) {}
|
pub fn make_progress(&mut self, delta: Duration) {
|
||||||
|
let progress = self.progress + delta.as_millis() as f32 / 1000.0;
|
||||||
|
let block_offsets = if let Some(f) = &self.progress_function {
|
||||||
|
Some(f(self.block_offsets.clone(), progress))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
if let Some(block_offsets) = block_offsets {
|
||||||
|
self.block_offsets = block_offsets;
|
||||||
|
self.progress = progress;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn is_done(&self) -> bool {
|
pub fn is_done(&self) -> bool {
|
||||||
self.progress > 1.0
|
self.progress > 1.0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_offset(&self, index: usize) -> (i32, i32) {
|
||||||
|
self.block_offsets
|
||||||
|
.get(&index)
|
||||||
|
.cloned()
|
||||||
|
.unwrap_or_else(|| (0, 0))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
24
src/game.rs
24
src/game.rs
|
@ -5,7 +5,7 @@ use glium::glutin::{ElementState, Event, VirtualKeyCode, WindowEvent};
|
||||||
use glium::{Display, Frame};
|
use glium::{Display, Frame};
|
||||||
|
|
||||||
use crate::animations::AnimationState;
|
use crate::animations::AnimationState;
|
||||||
use crate::enums::PushDir;
|
use crate::enums::{Board, PushDir};
|
||||||
use crate::level::Level;
|
use crate::level::Level;
|
||||||
use crate::renderer::Renderer;
|
use crate::renderer::Renderer;
|
||||||
use crate::resources::Resources;
|
use crate::resources::Resources;
|
||||||
|
@ -95,10 +95,10 @@ impl<'a> Game<'a> {
|
||||||
|
|
||||||
pub fn update(&mut self, delta: Duration) {
|
pub fn update(&mut self, delta: Duration) {
|
||||||
macro_rules! shit {
|
macro_rules! shit {
|
||||||
($key:expr, $player:expr, $movement:expr) => {
|
($key:expr, $board:expr, $direction:expr) => {
|
||||||
if self.is_pressed(&$key) {
|
if self.is_pressed(&$key) {
|
||||||
let level = self.get_current_level_mut();
|
let level = self.get_current_level_mut();
|
||||||
let result = level.handle_movement($player, $movement);
|
let result = level.try_move($board, $direction);
|
||||||
self.keymap.insert($key, false);
|
self.keymap.insert($key, false);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -112,15 +112,15 @@ impl<'a> Game<'a> {
|
||||||
} else {
|
} else {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
shit!(VirtualKeyCode::W, true, PushDir::Up);
|
shit!(VirtualKeyCode::W, Board::Left, PushDir::Up);
|
||||||
shit!(VirtualKeyCode::A, true, PushDir::Left);
|
shit!(VirtualKeyCode::A, Board::Left, PushDir::Left);
|
||||||
shit!(VirtualKeyCode::S, true, PushDir::Down);
|
shit!(VirtualKeyCode::S, Board::Left, PushDir::Down);
|
||||||
shit!(VirtualKeyCode::D, true, PushDir::Right);
|
shit!(VirtualKeyCode::D, Board::Left, PushDir::Right);
|
||||||
|
|
||||||
shit!(VirtualKeyCode::I, false, PushDir::Up);
|
shit!(VirtualKeyCode::I, Board::Right, PushDir::Up);
|
||||||
shit!(VirtualKeyCode::J, false, PushDir::Left);
|
shit!(VirtualKeyCode::J, Board::Right, PushDir::Left);
|
||||||
shit!(VirtualKeyCode::K, false, PushDir::Down);
|
shit!(VirtualKeyCode::K, Board::Right, PushDir::Down);
|
||||||
shit!(VirtualKeyCode::L, false, PushDir::Right);
|
shit!(VirtualKeyCode::L, Board::Right, PushDir::Right);
|
||||||
|
|
||||||
// failed a move
|
// failed a move
|
||||||
if !self.animations.last_move_success {
|
if !self.animations.last_move_success {
|
||||||
|
@ -135,6 +135,6 @@ impl<'a> Game<'a> {
|
||||||
|
|
||||||
pub fn render(&self, renderer: &mut Renderer) {
|
pub fn render(&self, renderer: &mut Renderer) {
|
||||||
let level = self.get_current_level();
|
let level = self.get_current_level();
|
||||||
level.render(renderer, &self.animations.block_offsets);
|
level.render(renderer, &self.animations);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,7 @@ pub trait Blockish {
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct Block {
|
pub struct Block {
|
||||||
index: usize,
|
index: usize,
|
||||||
movable: bool,
|
pub movable: bool,
|
||||||
position: (i32, i32),
|
position: (i32, i32),
|
||||||
color: Color,
|
color: Color,
|
||||||
orientation: Orientation,
|
orientation: Orientation,
|
||||||
|
|
235
src/level/mod.rs
235
src/level/mod.rs
|
@ -4,7 +4,7 @@ mod player;
|
||||||
|
|
||||||
use std::collections::{HashMap, VecDeque};
|
use std::collections::{HashMap, VecDeque};
|
||||||
|
|
||||||
use crate::animations::BlockOffsets;
|
use crate::animations::AnimationState;
|
||||||
use crate::color::Color;
|
use crate::color::Color;
|
||||||
use crate::data::LevelData;
|
use crate::data::LevelData;
|
||||||
use crate::enums::{Board, Orientation, PushDir, Shape};
|
use crate::enums::{Board, Orientation, PushDir, Shape};
|
||||||
|
@ -83,122 +83,146 @@ impl Level {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// player1: true -> player1, false -> player2
|
// pub fn handle_movement(&mut self, board: Board, direction: PushDir) -> bool {
|
||||||
// TODO: don't use a boolean here
|
// let player = match board {
|
||||||
pub fn handle_movement(&mut self, player1: bool, direction: PushDir) -> bool {
|
// Board::Left => &self.player1,
|
||||||
let player = if player1 {
|
// Board::Right => &self.player2
|
||||||
&self.player1
|
// };
|
||||||
} else {
|
|
||||||
&self.player2
|
|
||||||
};
|
|
||||||
|
|
||||||
// TODO: check out of bounds
|
// // TODO: check out of bounds
|
||||||
let movement = direction.as_pair();
|
// let movement = direction.as_pair();
|
||||||
let x = player.position.0 + movement.0;
|
// let x = player.position.0 + movement.0;
|
||||||
let y = player.position.1 + movement.1;
|
// let y = player.position.1 + movement.1;
|
||||||
|
|
||||||
let result = self.can_move(player1, direction).clone();
|
// let result = self.can_move(player1, direction).clone();
|
||||||
let mut player = if player1 {
|
// let player = match board {
|
||||||
&mut self.player1
|
// Board::Left => &mut self.player1,
|
||||||
} else {
|
// Board::Right => &mut self.player2
|
||||||
&mut self.player2
|
// };
|
||||||
};
|
|
||||||
|
|
||||||
if let Some(_) = result {
|
// if let Some(_) = result {
|
||||||
player.position.0 = x;
|
// player.position.0 = x;
|
||||||
player.position.1 = y;
|
// player.position.1 = y;
|
||||||
true
|
// true
|
||||||
} else {
|
// } else {
|
||||||
false
|
// false
|
||||||
}
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
pub fn try_move(&self, board: Board, direction: PushDir) {
|
||||||
|
let result = self.player_can_move(board, direction);
|
||||||
|
println!("result: {:?}", result);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn try_move(&self) {}
|
fn player_can_move(&self, board: Board, direction: PushDir) {}
|
||||||
|
|
||||||
fn block_can_move(&self, block: impl Blockish) {
|
fn block_can_move(&self, index: usize, direction: PushDir) -> Option<()> {
|
||||||
for segment in block.get_segments() {}
|
let block = match self.blocks.get(index) {
|
||||||
}
|
Some(block) => block,
|
||||||
|
None => return None,
|
||||||
|
};
|
||||||
|
|
||||||
fn segment_can_move(&self, block: Block, segment: Segment, direction: PushDir) -> Option<()> {
|
// is the block even movable?
|
||||||
let triple = (segment.position.0, segment.position.1, segment.board);
|
if !block.movable {
|
||||||
let target = triple + direction;
|
|
||||||
|
|
||||||
// is the target in the map?
|
|
||||||
if target.0 < 0
|
|
||||||
|| target.0 >= self.dimensions.0 as i32
|
|
||||||
|| target.1 < 0
|
|
||||||
|| target.1 >= self.dimensions.1 as i32
|
|
||||||
{
|
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
// check if we're sharing a triangle cell
|
for segment in block.get_segments() {
|
||||||
if let CellContents::Double((ind1, block1), (ind2, block2)) = self.cell_map.get(triple) {
|
let result = self.segment_can_move(Some(index), segment, direction);
|
||||||
// figure out which one is the other block
|
|
||||||
|
|
||||||
// check that we're pushing in the direction of the other block
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Some(())
|
Some(())
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: don't use a boolean here
|
fn segment_can_move(
|
||||||
pub fn can_move(&self, player1: bool, direction: PushDir) -> Option<()> {
|
&self,
|
||||||
// an absolute segment (as opposed to relative to a block)
|
block_index: Option<usize>,
|
||||||
#[derive(Copy, Clone, PartialOrd, PartialEq)]
|
segment: Segment,
|
||||||
struct ASegment(i32, i32, Shape, Board);
|
direction: PushDir,
|
||||||
|
) -> Option<()> {
|
||||||
struct PushMap(CellMap);
|
let segment_loc = (segment.position.0, segment.position.1, segment.board);
|
||||||
|
let target = segment_loc + direction;
|
||||||
fn can_push_segment(src: ASegment, dst: ASegment) -> bool {
|
|
||||||
if src.3 != dst.3 {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
true
|
|
||||||
}
|
|
||||||
|
|
||||||
let player = if player1 {
|
|
||||||
(
|
|
||||||
self.player1.position.0,
|
|
||||||
self.player1.position.1,
|
|
||||||
Board::Left,
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
(
|
|
||||||
self.player2.position.0,
|
|
||||||
self.player2.position.1,
|
|
||||||
Board::Right,
|
|
||||||
)
|
|
||||||
};
|
|
||||||
|
|
||||||
// check to make sure that the player isn't trying to go out of bounds
|
|
||||||
let target = player + direction;
|
|
||||||
if target.0 < 0
|
|
||||||
|| target.0 >= self.dimensions.0 as i32
|
|
||||||
|| target.1 < 0
|
|
||||||
|| target.1 >= self.dimensions.1 as i32
|
|
||||||
{
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
// check if we're sharing a triangle cell
|
|
||||||
if let CellContents::Double(a, b) = self.cell_map.get(player) {
|
|
||||||
// get the shape of the other block
|
|
||||||
}
|
|
||||||
|
|
||||||
// 08/06 pickup
|
|
||||||
// need to determine whether or not segment should hold a reference back to block or not?
|
|
||||||
// either way, segment in the cellmap should hold block information
|
|
||||||
// maybe cellmap should just carry a block index? seems hacky
|
|
||||||
// using refs to manage the whole thing is messy and probably doesn't work
|
|
||||||
// ???
|
|
||||||
|
|
||||||
Some(())
|
Some(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn render(&self, renderer: &mut Renderer, block_offsets: &BlockOffsets) {
|
// fn segment_can_move(&self, block: Block, segment: Segment, direction: PushDir) -> Option<()> {
|
||||||
|
// let triple = (segment.position.0, segment.position.1, segment.board);
|
||||||
|
// let target = triple + direction;
|
||||||
|
|
||||||
|
// // is the target in the map?
|
||||||
|
// if target.0 < 0
|
||||||
|
// || target.0 >= self.dimensions.0 as i32
|
||||||
|
// || target.1 < 0
|
||||||
|
// || target.1 >= self.dimensions.1 as i32
|
||||||
|
// {
|
||||||
|
// return None;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // check if we're sharing a triangle cell
|
||||||
|
// if let CellContents::Double((ind1, block1), (ind2, block2)) = self.cell_map.get(triple) {
|
||||||
|
// // figure out which one is the other block
|
||||||
|
|
||||||
|
// // check that we're pushing in the direction of the other block
|
||||||
|
|
||||||
|
// }
|
||||||
|
|
||||||
|
// Some(())
|
||||||
|
// }
|
||||||
|
|
||||||
|
// pub fn can_move(&self, board: Board, direction: PushDir) -> Option<()> {
|
||||||
|
// // an absolute segment (as opposed to relative to a block)
|
||||||
|
// #[derive(Copy, Clone, PartialOrd, PartialEq)]
|
||||||
|
// struct ASegment(i32, i32, Shape, Board);
|
||||||
|
|
||||||
|
// struct PushMap(CellMap);
|
||||||
|
|
||||||
|
// fn can_push_segment(src: ASegment, dst: ASegment) -> bool {
|
||||||
|
// if src.3 != dst.3 {
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// true
|
||||||
|
// }
|
||||||
|
|
||||||
|
// let player = if player1 {
|
||||||
|
// (
|
||||||
|
// self.player1.position.0,
|
||||||
|
// self.player1.position.1,
|
||||||
|
// Board::Left,
|
||||||
|
// )
|
||||||
|
// } else {
|
||||||
|
// (
|
||||||
|
// self.player2.position.0,
|
||||||
|
// self.player2.position.1,
|
||||||
|
// Board::Right,
|
||||||
|
// )
|
||||||
|
// };
|
||||||
|
|
||||||
|
// // check to make sure that the player isn't trying to go out of bounds
|
||||||
|
// let target = player + direction;
|
||||||
|
// if target.0 < 0
|
||||||
|
// || target.0 >= self.dimensions.0 as i32
|
||||||
|
// || target.1 < 0
|
||||||
|
// || target.1 >= self.dimensions.1 as i32
|
||||||
|
// {
|
||||||
|
// return None;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // check if we're sharing a triangle cell
|
||||||
|
// if let CellContents::Double(a, b) = self.cell_map.get(player) {
|
||||||
|
// // get the shape of the other block
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // 08/06 pickup
|
||||||
|
// // need to determine whether or not segment should hold a reference back to block or not?
|
||||||
|
// // either way, segment in the cellmap should hold block information
|
||||||
|
// // maybe cellmap should just carry a block index? seems hacky
|
||||||
|
// // using refs to manage the whole thing is messy and probably doesn't work
|
||||||
|
// // ???
|
||||||
|
|
||||||
|
// Some(())
|
||||||
|
// }
|
||||||
|
|
||||||
|
pub fn render(&self, renderer: &mut Renderer, animations: &AnimationState) {
|
||||||
// board positioning calculations
|
// board positioning calculations
|
||||||
let playfield_ratio = (2 * self.dimensions.0 + 6) as f32 / (self.dimensions.1 + 4) as f32;
|
let playfield_ratio = (2 * self.dimensions.0 + 6) as f32 / (self.dimensions.1 + 4) as f32;
|
||||||
let screen_ratio = renderer.window.0 / renderer.window.1;
|
let screen_ratio = renderer.window.0 / renderer.window.1;
|
||||||
|
@ -216,7 +240,7 @@ impl Level {
|
||||||
(scale, xoff, 0)
|
(scale, xoff, 0)
|
||||||
};
|
};
|
||||||
|
|
||||||
self.render_boards(renderer, scale, (xoff, yoff), block_offsets);
|
self.render_boards(renderer, scale, (xoff, yoff), animations);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render_boards(
|
fn render_boards(
|
||||||
|
@ -224,7 +248,7 @@ impl Level {
|
||||||
renderer: &mut Renderer,
|
renderer: &mut Renderer,
|
||||||
scale: i32,
|
scale: i32,
|
||||||
offset: (i32, i32),
|
offset: (i32, i32),
|
||||||
block_offsets: &BlockOffsets,
|
animations: &AnimationState,
|
||||||
) {
|
) {
|
||||||
let left_off = (offset.0 + 2 * scale, offset.1 + 2 * scale);
|
let left_off = (offset.0 + 2 * scale, offset.1 + 2 * scale);
|
||||||
let right_off = (
|
let right_off = (
|
||||||
|
@ -242,16 +266,19 @@ impl Level {
|
||||||
}
|
}
|
||||||
|
|
||||||
// render blocks
|
// render blocks
|
||||||
for block in self.blocks.iter() {
|
for (i, block) in self.blocks.iter().enumerate() {
|
||||||
for segment in block.get_segments().iter() {
|
for segment in block.get_segments().iter() {
|
||||||
let offset = match &segment.board {
|
let offset = match &segment.board {
|
||||||
Board::Left => left_off,
|
Board::Left => left_off,
|
||||||
Board::Right => right_off,
|
Board::Right => right_off,
|
||||||
};
|
};
|
||||||
let location = (
|
let mut location = (
|
||||||
offset.0 + segment.position.0 * scale,
|
offset.0 + segment.position.0 * scale,
|
||||||
offset.1 + segment.position.1 * scale,
|
offset.1 + segment.position.1 * scale,
|
||||||
);
|
);
|
||||||
|
let animation_offset = animations.get_offset(i);
|
||||||
|
location.0 += animation_offset.0;
|
||||||
|
location.1 += animation_offset.1;
|
||||||
renderer.render_segment(
|
renderer.render_segment(
|
||||||
location,
|
location,
|
||||||
scale,
|
scale,
|
||||||
|
|
Loading…
Reference in a new issue