This commit is contained in:
Michael Zhang 2019-08-09 21:50:10 -05:00
parent ada9131dfb
commit 77b263576c
No known key found for this signature in database
GPG key ID: 5BAEFE5D04F0CE6C
4 changed files with 168 additions and 119 deletions

View file

@ -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))
}
} }

View file

@ -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);
} }
} }

View file

@ -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,

View file

@ -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,