add level 1
This commit is contained in:
parent
681c53eb80
commit
85f8c710ac
6 changed files with 169 additions and 21 deletions
19
LICENSE
Normal file
19
LICENSE
Normal 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
124
levels/level1.json
Normal 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],
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
|
@ -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 {
|
||||||
|
|
|
@ -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");
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue