add level 1

This commit is contained in:
Michael Zhang 2020-06-08 03:25:00 -05:00
parent 681c53eb80
commit 85f8c710ac
Signed by: michael
GPG key ID: BDA47A31A3C8EE6B
6 changed files with 169 additions and 21 deletions

19
LICENSE Normal file
View file

@ -0,0 +1,19 @@
Copyright (c) Michael Zhang
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

124
levels/level1.json Normal file
View file

@ -0,0 +1,124 @@
{
"dimensions": [8, 8],
"player1": {
"position": [5, 5],
"color": [66, 134, 244],
},
"player2": {
"position": [5, 5],
"color": [244, 83, 65],
},
"goal1": [0, 0],
"goal2": [0, 0],
"blocks": [
{
"movable": true,
"orientation": 2,
"color": [255, 10, 100],
"segments": [
[6, 4, 2, 0],
[6, 5, 0, 0],
],
},
{
"movable": true,
"orientation": 1,
"color": [0, 255, 100],
"segments": [
[4, 3, 2, 0],
[5, 3, 0, 0],
[6, 3, 4, 0],
[4, 3, 2, 1],
[5, 3, 0, 1],
[6, 3, 4, 1],
],
},
{
"movable": true,
"orientation": 2,
"color": [20, 25, 100],
"segments": [
[6, 2, 4, 0],
[6, 1, 0, 0],
[6, 2, 4, 1],
[6, 1, 0, 1],
],
},
{
"movable": true,
"orientation": 1,
"color": [110, 30, 230],
"segments": [
[3, 5, 4, 0],
[2, 5, 0, 0],
[1, 5, 0, 0],
[3, 5, 4, 1],
[2, 5, 0, 1],
[1, 5, 0, 1],
],
},
{
"movable": true,
"orientation": 2,
"color": [240, 50, 60],
"segments": [
[3, 5, 2, 0],
[3, 6, 0, 0],
],
},
{
"movable": true,
"orientation": 2,
"color": [120, 220, 20],
"segments": [
[3, 3, 4, 1],
[3, 2, 0, 1],
],
},
{
"movable": false,
"orientation": 0,
"color": [0, 0, 0],
"segments": [
[2, 0, 0, 0],
[2, 1, 0, 0],
[2, 2, 0, 0],
[2, 3, 0, 0],
[2, 0, 0, 1],
[2, 1, 0, 1],
[2, 2, 0, 1],
[2, 3, 0, 1],
],
},
{
"movable": false,
"orientation": 0,
"color": [0, 0, 0],
"segments": [
[4, 4, 0, 0],
[4, 5, 0, 0],
[4, 6, 0, 0],
[4, 7, 0, 0],
[4, 4, 0, 1],
[4, 5, 0, 1],
[4, 6, 0, 1],
[4, 7, 0, 1],
],
},
{
"movable": false,
"orientation": 0,
"color": [0, 0, 0],
"segments": [
[7, 4, 0, 0],
[7, 5, 0, 0],
[7, 6, 0, 0],
[7, 7, 0, 0],
[7, 4, 0, 1],
[7, 5, 0, 1],
[7, 6, 0, 1],
[7, 7, 0, 1],
],
},
],
}

View file

@ -1,4 +1,4 @@
use std::collections::HashMap; use std::collections::{HashSet, HashMap};
use std::time::Duration; use std::time::Duration;
use crate::enums::Board; use crate::enums::Board;
@ -8,7 +8,7 @@ pub type MoveResult = Result<ChangeSet, FailSet>;
pub type BlockOffsets = HashMap<Entity, (f32, f32)>; pub type BlockOffsets = HashMap<Entity, (f32, f32)>;
// TODO: don't yeet around a HashMap all the time // TODO: don't yeet around a HashMap all the time
pub type AnimationFn = Box<Fn(MoveResult, BlockOffsets, f32) -> BlockOffsets>; pub type AnimationFn = Box<dyn Fn(MoveResult, BlockOffsets, f32) -> BlockOffsets>;
// in seconds // in seconds
const ANIMATION_DURATION: f32 = 1.0 / 6.0; const ANIMATION_DURATION: f32 = 1.0 / 6.0;
@ -19,6 +19,7 @@ pub struct AnimationState {
pub last_move_result: Option<MoveResult>, pub last_move_result: Option<MoveResult>,
pub progress: f32, pub progress: f32,
pub block_offsets: BlockOffsets, pub block_offsets: BlockOffsets,
pub immovable_blocks: HashSet<usize>,
progress_function: Option<AnimationFn>, progress_function: Option<AnimationFn>,
} }
@ -29,6 +30,7 @@ impl AnimationState {
last_move_result: None, last_move_result: None,
progress: 0.0, progress: 0.0,
block_offsets: BlockOffsets::new(), block_offsets: BlockOffsets::new(),
immovable_blocks: HashSet::new(),
progress_function: None, progress_function: None,
} }
} }
@ -38,6 +40,7 @@ impl AnimationState {
self.last_move_result = Some(result); self.last_move_result = Some(result);
self.is_animating = true; self.is_animating = true;
self.progress = 0.0; self.progress = 0.0;
let func = |last_move_result: MoveResult, mut offsets: BlockOffsets, progress: f32| { let func = |last_move_result: MoveResult, mut offsets: BlockOffsets, progress: f32| {
use std::f32::consts::PI; use std::f32::consts::PI;
match last_move_result { match last_move_result {
@ -52,6 +55,7 @@ impl AnimationState {
offsets.insert(entity, offset); offsets.insert(entity, offset);
} }
} }
// vibrate all blocking pieces // vibrate all blocking pieces
Err(fail_set) => { Err(fail_set) => {
for index in fail_set { for index in fail_set {

View file

@ -1,16 +1,12 @@
use std::collections::HashMap;
use std::time::Duration; use std::time::Duration;
use glium::glutin::{ElementState, Event, VirtualKeyCode, WindowEvent}; use glium::glutin::{ElementState, Event, WindowEvent};
use glium::{Display, Frame}; use glium::{Display, Frame};
use crate::animations::AnimationState;
use crate::enums::{Board, PushDir};
use crate::keymap::Keymap; use crate::keymap::Keymap;
use crate::level::Level;
use crate::renderer::Renderer; use crate::renderer::Renderer;
use crate::resources::Resources; use crate::resources::Resources;
use crate::screens::{MenuScreen, Screen, ScreenStack}; use crate::screens::{MenuScreen, ScreenStack};
const SEGMENT_VERT: &str = include_str!("../shaders/segment.vert"); const SEGMENT_VERT: &str = include_str!("../shaders/segment.vert");
const SEGMENT_FRAG: &str = include_str!("../shaders/segment.frag"); const SEGMENT_FRAG: &str = include_str!("../shaders/segment.frag");

View file

@ -1,7 +1,6 @@
mod menu; mod menu;
mod play; mod play;
use std::sync::Arc;
use std::time::Duration; use std::time::Duration;
use crate::keymap::Keymap; use crate::keymap::Keymap;
@ -27,7 +26,7 @@ pub struct ScreenStack(Vec<Box<dyn Screen>>);
impl ScreenStack { impl ScreenStack {
pub fn with<S: 'static + Screen>(screen: S) -> Self { pub fn with<S: 'static + Screen>(screen: S) -> Self {
let mut stack = Vec::<Box<Screen>>::new(); let mut stack = Vec::<Box<dyn Screen>>::new();
stack.push(Box::new(screen)); stack.push(Box::new(screen));
ScreenStack(stack) ScreenStack(stack)
} }
@ -56,7 +55,7 @@ impl ScreenStack {
} }
pub fn render(&self, renderer: &mut Renderer) { pub fn render(&self, renderer: &mut Renderer) {
let mut screen = self.top(); let screen = self.top();
let screen = screen.as_ref(); let screen = screen.as_ref();
screen.render(renderer) screen.render(renderer)
} }

View file

@ -11,6 +11,7 @@ use crate::screens::{Screen, ScreenAction};
const LEVEL_TUTORIAL: &str = include_str!("../../levels/tutorial.json"); const LEVEL_TUTORIAL: &str = include_str!("../../levels/tutorial.json");
const LEVEL_TUTORIAL2: &str = include_str!("../../levels/tutorial2.json"); const LEVEL_TUTORIAL2: &str = include_str!("../../levels/tutorial2.json");
const LEVEL_1: &str = include_str!("../../levels/level1.json");
pub struct PlayScreen { pub struct PlayScreen {
animations: AnimationState, animations: AnimationState,
@ -20,7 +21,7 @@ pub struct PlayScreen {
impl Screen for PlayScreen { impl Screen for PlayScreen {
fn update(&mut self, delta: Duration, keymap: &Keymap) -> ScreenAction { fn update(&mut self, delta: Duration, keymap: &Keymap) -> ScreenAction {
macro_rules! shit { macro_rules! btn_handler {
($key:expr, $board:expr, $direction:expr) => { ($key:expr, $board:expr, $direction:expr) => {
if keymap.is_pressed($key) { if keymap.is_pressed($key) {
println!("pushed: {:?}", $key); println!("pushed: {:?}", $key);
@ -51,15 +52,15 @@ impl Screen for PlayScreen {
} }
} }
} else { } else {
shit!(VirtualKeyCode::W, Board::Left, PushDir::Up); btn_handler!(VirtualKeyCode::W, Board::Left, PushDir::Up);
shit!(VirtualKeyCode::A, Board::Left, PushDir::Left); btn_handler!(VirtualKeyCode::A, Board::Left, PushDir::Left);
shit!(VirtualKeyCode::S, Board::Left, PushDir::Down); btn_handler!(VirtualKeyCode::S, Board::Left, PushDir::Down);
shit!(VirtualKeyCode::D, Board::Left, PushDir::Right); btn_handler!(VirtualKeyCode::D, Board::Left, PushDir::Right);
shit!(VirtualKeyCode::I, Board::Right, PushDir::Up); btn_handler!(VirtualKeyCode::I, Board::Right, PushDir::Up);
shit!(VirtualKeyCode::J, Board::Right, PushDir::Left); btn_handler!(VirtualKeyCode::J, Board::Right, PushDir::Left);
shit!(VirtualKeyCode::K, Board::Right, PushDir::Down); btn_handler!(VirtualKeyCode::K, Board::Right, PushDir::Down);
shit!(VirtualKeyCode::L, Board::Right, PushDir::Right); btn_handler!(VirtualKeyCode::L, Board::Right, PushDir::Right);
} }
ScreenAction::None ScreenAction::None
@ -82,6 +83,7 @@ impl PlayScreen {
pub fn new() -> PlayScreen { pub fn new() -> PlayScreen {
let levels = vec![ let levels = vec![
Level::from_json(&LEVEL_1),
Level::from_json(&LEVEL_TUTORIAL), Level::from_json(&LEVEL_TUTORIAL),
Level::from_json(&LEVEL_TUTORIAL2), Level::from_json(&LEVEL_TUTORIAL2),
]; ];
@ -93,11 +95,15 @@ impl PlayScreen {
} }
} }
fn go_to_next_level(&mut self) {
self.current_level += 1;
}
fn check_win_condition(&mut self) { fn check_win_condition(&mut self) {
let level = self.get_current_level(); let level = self.get_current_level();
if level.check_win_condition() { if level.check_win_condition() {
// go on to the next level // go on to the next level
self.current_level += 1; self.go_to_next_level();
} }
} }
} }