huge refactor
This commit is contained in:
parent
e9c8cdbf48
commit
b0ef20ff8b
11 changed files with 278 additions and 139 deletions
|
@ -17,8 +17,8 @@
|
|||
"position": [1, 3],
|
||||
"color": [255, 10, 100],
|
||||
"segments": [
|
||||
[0, 0, 0, 0],
|
||||
[1, 0, 4, 0],
|
||||
[1, 3, 0, 0],
|
||||
[2, 3, 4, 0],
|
||||
],
|
||||
},
|
||||
{
|
||||
|
@ -27,8 +27,8 @@
|
|||
"position": [2, 4],
|
||||
"color": [105, 210, 50],
|
||||
"segments": [
|
||||
[0, 0, 2, 0],
|
||||
[0, 1, 0, 0],
|
||||
[2, 4, 2, 0],
|
||||
[2, 5, 0, 0],
|
||||
],
|
||||
},
|
||||
{
|
||||
|
@ -37,8 +37,8 @@
|
|||
"position": [0, 4],
|
||||
"color": [35, 150, 100],
|
||||
"segments": [
|
||||
[0, 0, 1, 1],
|
||||
[0, 1, 0, 1],
|
||||
[0, 4, 1, 1],
|
||||
[0, 5, 0, 1],
|
||||
],
|
||||
},
|
||||
{
|
||||
|
@ -47,8 +47,8 @@
|
|||
"position": [0, 3],
|
||||
"color": [25, 120, 10],
|
||||
"segments": [
|
||||
[0, 0, 3, 1],
|
||||
[1, 0, 0, 1],
|
||||
[0, 3, 3, 1],
|
||||
[1, 3, 0, 1],
|
||||
],
|
||||
},
|
||||
{
|
||||
|
@ -57,7 +57,7 @@
|
|||
"position": [0, 2],
|
||||
"color": [15, 15, 15],
|
||||
"segments": [
|
||||
[0, 0, 0, 0],
|
||||
[0, 2, 0, 0],
|
||||
],
|
||||
},
|
||||
{
|
||||
|
@ -66,7 +66,7 @@
|
|||
"position": [2, 2],
|
||||
"color": [15, 15, 15],
|
||||
"segments": [
|
||||
[0, 0, 0, 1],
|
||||
[2, 2, 0, 1],
|
||||
],
|
||||
},
|
||||
]
|
||||
|
|
14
src/color.rs
Normal file
14
src/color.rs
Normal file
|
@ -0,0 +1,14 @@
|
|||
#[derive(Copy, Clone, Debug)]
|
||||
pub struct Color(pub f32, pub f32, pub f32, pub f32);
|
||||
|
||||
impl Color {
|
||||
pub fn from_rgb_u32(r: u32, g: u32, b: u32) -> Self {
|
||||
Color(r as f32 / 256.0, g as f32 / 256.0, b as f32 / 256.0, 1.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<(u32, u32, u32)> for Color {
|
||||
fn from(tuple: (u32, u32, u32)) -> Self {
|
||||
Color::from_rgb_u32(tuple.0, tuple.1, tuple.2)
|
||||
}
|
||||
}
|
|
@ -1,15 +1,15 @@
|
|||
#[derive(Debug, Deserialize)]
|
||||
pub struct PlayerData {
|
||||
pub position: [i32; 2],
|
||||
pub color: [u32; 3],
|
||||
pub position: (i32, i32),
|
||||
pub color: (u32, u32, u32),
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
pub struct BlockData {
|
||||
pub movable: bool,
|
||||
pub orientation: u32,
|
||||
pub position: [i32; 2],
|
||||
pub color: [u32; 3],
|
||||
pub position: (i32, i32),
|
||||
pub color: (u32, u32, u32),
|
||||
pub segments: Vec<[i32; 4]>,
|
||||
}
|
||||
|
||||
|
|
18
src/enums.rs
18
src/enums.rs
|
@ -1,6 +1,6 @@
|
|||
use std::ops::Add;
|
||||
|
||||
#[derive(Eq, PartialEq, Hash, PartialOrd, Copy, Clone)]
|
||||
#[derive(Debug, Eq, PartialEq, Hash, PartialOrd, Copy, Clone)]
|
||||
pub enum Board {
|
||||
Left = 0,
|
||||
Right = 1,
|
||||
|
@ -18,9 +18,10 @@ impl From<i32> for Board {
|
|||
|
||||
#[derive(Copy, Clone)]
|
||||
pub enum Orientation {
|
||||
Both = 0,
|
||||
None = 0,
|
||||
Horizontal = 1,
|
||||
Vertical = 2,
|
||||
Both = 3,
|
||||
}
|
||||
|
||||
impl From<u32> for Orientation {
|
||||
|
@ -62,7 +63,7 @@ impl Add<PushDir> for (i32, i32, Board) {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, PartialOrd, PartialEq)]
|
||||
#[derive(Copy, Clone, Debug, PartialOrd, PartialEq)]
|
||||
pub enum Shape {
|
||||
Full = 0,
|
||||
TopRight = 1,
|
||||
|
@ -85,6 +86,17 @@ impl From<i32> for Shape {
|
|||
}
|
||||
|
||||
impl Shape {
|
||||
pub fn opposite(&self) -> Shape {
|
||||
use Shape::*;
|
||||
match self {
|
||||
TopRight => BottomLeft,
|
||||
BottomLeft => TopRight,
|
||||
TopLeft => BottomRight,
|
||||
BottomRight => TopLeft,
|
||||
Full => Full,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_opposite(&self, other: &Shape) -> bool {
|
||||
use Shape::*;
|
||||
match (self, other) {
|
||||
|
|
|
@ -92,7 +92,7 @@ impl<'a> Game<'a> {
|
|||
macro_rules! shit {
|
||||
($key:expr, $player:expr, $movement:expr) => {
|
||||
if self.is_pressed(&$key) {
|
||||
let mut level = self.get_current_level_mut();
|
||||
let level = self.get_current_level_mut();
|
||||
level.handle_movement($player, $movement);
|
||||
self.keymap.insert($key, false);
|
||||
}
|
||||
|
|
63
src/level/block.rs
Normal file
63
src/level/block.rs
Normal file
|
@ -0,0 +1,63 @@
|
|||
use crate::color::Color;
|
||||
use crate::data::BlockData;
|
||||
use crate::enums::Orientation;
|
||||
use crate::level::Segment;
|
||||
|
||||
pub trait Blockish {
|
||||
fn get_color(&self) -> Color;
|
||||
fn get_orientation(&self) -> Orientation;
|
||||
|
||||
// TODO: don't alloc/clone here?
|
||||
fn get_segments(&self) -> Vec<Segment>;
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Block {
|
||||
movable: bool,
|
||||
position: (i32, i32),
|
||||
color: Color,
|
||||
orientation: Orientation,
|
||||
segments: Vec<Segment>,
|
||||
}
|
||||
|
||||
impl Block {
|
||||
pub fn from_data(index: usize, data: &BlockData) -> Self {
|
||||
let movable = data.movable;
|
||||
let position = (data.position.0, data.position.1);
|
||||
let segments = data
|
||||
.segments
|
||||
.iter()
|
||||
.map(|segment| {
|
||||
let seg = Segment {
|
||||
position: (segment[0], segment[1]),
|
||||
shape: segment[2].into(),
|
||||
board: segment[3].into(),
|
||||
};
|
||||
seg
|
||||
})
|
||||
.collect();
|
||||
let orientation = data.orientation.into();
|
||||
let color = Color::from_rgb_u32(data.color.0, data.color.1, data.color.2);
|
||||
Block {
|
||||
movable,
|
||||
position,
|
||||
color,
|
||||
segments,
|
||||
orientation,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Blockish for Block {
|
||||
fn get_color(&self) -> Color {
|
||||
self.color
|
||||
}
|
||||
|
||||
fn get_orientation(&self) -> Orientation {
|
||||
self.orientation
|
||||
}
|
||||
|
||||
fn get_segments(&self) -> Vec<Segment> {
|
||||
self.segments.clone()
|
||||
}
|
||||
}
|
72
src/level/cell_map.rs
Normal file
72
src/level/cell_map.rs
Normal file
|
@ -0,0 +1,72 @@
|
|||
use std::collections::HashMap;
|
||||
|
||||
use crate::enums::Board;
|
||||
use crate::level::Segment;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct CellMap(HashMap<(i32, i32, Board), CellContents>);
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub enum CellContents {
|
||||
Empty,
|
||||
Player,
|
||||
Single((usize, Segment)),
|
||||
|
||||
// invariant: .0 < .1
|
||||
Double((usize, Segment), (usize, Segment)),
|
||||
}
|
||||
|
||||
impl CellMap {
|
||||
pub fn new() -> Self {
|
||||
CellMap(HashMap::new())
|
||||
}
|
||||
|
||||
pub fn get(&self, loc: (i32, i32, Board)) -> CellContents {
|
||||
self.0
|
||||
.get(&loc)
|
||||
.cloned()
|
||||
.unwrap_or_else(|| CellContents::Empty)
|
||||
}
|
||||
|
||||
pub fn clear(&mut self, loc: (i32, i32, Board)) {
|
||||
self.0.remove(&loc);
|
||||
}
|
||||
|
||||
pub fn add_player(&mut self, loc: (i32, i32, Board)) -> bool {
|
||||
let contents = self.get(loc).clone();
|
||||
match contents {
|
||||
CellContents::Empty => {
|
||||
self.0.insert(loc, CellContents::Player);
|
||||
true
|
||||
}
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add(&mut self, loc: (i32, i32, Board), index: usize, segment: &Segment) -> bool {
|
||||
let contents = self.get(loc).clone();
|
||||
match contents {
|
||||
CellContents::Empty => {
|
||||
// just add it like normal
|
||||
self.0.insert(loc, CellContents::Single((index, *segment)));
|
||||
true
|
||||
}
|
||||
CellContents::Single((index0, existing)) => {
|
||||
if existing.shape.is_opposite(&segment.shape) {
|
||||
self.0.insert(
|
||||
loc,
|
||||
if *segment < existing {
|
||||
CellContents::Double((index, *segment), (index0, existing))
|
||||
} else {
|
||||
CellContents::Double((index0, existing), (index, *segment))
|
||||
},
|
||||
);
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
CellContents::Player | CellContents::Double(_, _) => false,
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,9 +1,18 @@
|
|||
mod block;
|
||||
mod cell_map;
|
||||
mod player;
|
||||
|
||||
use std::collections::{HashMap, VecDeque};
|
||||
|
||||
use crate::color::Color;
|
||||
use crate::data::LevelData;
|
||||
use crate::enums::{Board, Orientation, PushDir, Shape};
|
||||
use crate::renderer::Renderer;
|
||||
|
||||
use self::block::{Block, Blockish};
|
||||
use self::cell_map::{CellContents, CellMap};
|
||||
use self::player::Player;
|
||||
|
||||
pub struct Level {
|
||||
dimensions: (u32, u32),
|
||||
move_stack: VecDeque<()>,
|
||||
|
@ -13,22 +22,11 @@ pub struct Level {
|
|||
player2: Player,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Block {
|
||||
movable: bool,
|
||||
#[derive(Copy, Clone, Debug, PartialOrd, PartialEq)]
|
||||
pub struct Segment {
|
||||
position: (i32, i32),
|
||||
color: (f32, f32, f32),
|
||||
orientation: Orientation,
|
||||
segments: Vec<Segment>,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, PartialOrd, PartialEq)]
|
||||
pub struct Segment(i32, i32, Shape, Board);
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct Player {
|
||||
pub position: [i32; 2],
|
||||
pub color: [u32; 3],
|
||||
shape: Shape,
|
||||
board: Board,
|
||||
}
|
||||
|
||||
impl Level {
|
||||
|
@ -36,48 +34,48 @@ impl Level {
|
|||
let data: LevelData = json5::from_str(data.as_ref()).unwrap();
|
||||
println!("{:?}", data);
|
||||
|
||||
let mut cell_map = CellMap::new();
|
||||
|
||||
let blocks = data
|
||||
.blocks
|
||||
.iter()
|
||||
.map(|block| {
|
||||
let movable = block.movable;
|
||||
let position = (block.position[0], block.position[1]);
|
||||
let segments = block
|
||||
.segments
|
||||
.iter()
|
||||
.map(|segment| {
|
||||
Segment(segment[0], segment[1], segment[2].into(), segment[3].into())
|
||||
})
|
||||
.collect();
|
||||
let orientation = block.orientation.into();
|
||||
let color = (
|
||||
block.color[0] as f32 / 256.0,
|
||||
block.color[1] as f32 / 256.0,
|
||||
block.color[2] as f32 / 256.0,
|
||||
);
|
||||
Block {
|
||||
movable,
|
||||
position,
|
||||
color,
|
||||
segments,
|
||||
orientation,
|
||||
.enumerate()
|
||||
.map(|(i, block)| {
|
||||
let block = Block::from_data(i, block);
|
||||
for segment in block.get_segments() {
|
||||
cell_map.add(
|
||||
(segment.position.0, segment.position.1, segment.board),
|
||||
i,
|
||||
&segment,
|
||||
);
|
||||
}
|
||||
block
|
||||
})
|
||||
.collect();
|
||||
|
||||
let player1 = Player {
|
||||
position: data.player1.position,
|
||||
color: data.player1.color,
|
||||
color: data.player1.color.into(),
|
||||
};
|
||||
let player2 = Player {
|
||||
position: data.player2.position,
|
||||
color: data.player2.color,
|
||||
color: data.player2.color.into(),
|
||||
};
|
||||
cell_map.add_player((
|
||||
data.player1.position.0,
|
||||
data.player1.position.1,
|
||||
Board::Left,
|
||||
));
|
||||
cell_map.add_player((
|
||||
data.player2.position.0,
|
||||
data.player2.position.1,
|
||||
Board::Right,
|
||||
));
|
||||
|
||||
Level {
|
||||
dimensions: (data.dimensions[0], data.dimensions[1]),
|
||||
move_stack: VecDeque::new(),
|
||||
cell_map: CellMap::new(),
|
||||
cell_map,
|
||||
blocks,
|
||||
player1,
|
||||
player2,
|
||||
|
@ -87,7 +85,7 @@ impl Level {
|
|||
// player1: true -> player1, false -> player2
|
||||
// TODO: don't use a boolean here
|
||||
pub fn handle_movement(&mut self, player1: bool, direction: PushDir) -> bool {
|
||||
let mut player = if player1 {
|
||||
let player = if player1 {
|
||||
&self.player1
|
||||
} else {
|
||||
&self.player2
|
||||
|
@ -95,8 +93,8 @@ impl Level {
|
|||
|
||||
// TODO: check out of bounds
|
||||
let movement = direction.as_pair();
|
||||
let x = player.position[0] + movement.0;
|
||||
let y = player.position[1] + movement.1;
|
||||
let x = player.position.0 + movement.0;
|
||||
let y = player.position.1 + movement.1;
|
||||
|
||||
let result = self.can_move(player1, direction).clone();
|
||||
let mut player = if player1 {
|
||||
|
@ -106,21 +104,25 @@ impl Level {
|
|||
};
|
||||
|
||||
if let Some(_) = result {
|
||||
player.position[0] = x;
|
||||
player.position[1] = y;
|
||||
player.position.0 = x;
|
||||
player.position.1 = y;
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
pub fn try_move(&self) {}
|
||||
|
||||
// TODO: don't use a boolean here
|
||||
pub fn can_move(&self, player1: bool, direction: PushDir) -> Option<()> {
|
||||
// an absolute segment (as opposed to relative to a block)
|
||||
#[derive(Copy, Clone, PartialOrd, PartialEq)]
|
||||
struct ASegment(i32, i32, Shape, Board);
|
||||
|
||||
fn can_push(src: Segment, dst: Segment) -> bool {
|
||||
struct PushMap(CellMap);
|
||||
|
||||
fn can_push_segment(src: ASegment, dst: ASegment) -> bool {
|
||||
if src.3 != dst.3 {
|
||||
return false;
|
||||
}
|
||||
|
@ -130,14 +132,14 @@ impl Level {
|
|||
|
||||
let player = if player1 {
|
||||
(
|
||||
self.player1.position[0],
|
||||
self.player1.position[1],
|
||||
self.player1.position.0,
|
||||
self.player1.position.1,
|
||||
Board::Left,
|
||||
)
|
||||
} else {
|
||||
(
|
||||
self.player2.position[0],
|
||||
self.player2.position[1],
|
||||
self.player2.position.0,
|
||||
self.player2.position.1,
|
||||
Board::Right,
|
||||
)
|
||||
};
|
||||
|
@ -153,7 +155,9 @@ impl Level {
|
|||
}
|
||||
|
||||
// check if we're sharing a triangle cell
|
||||
if let CellContents::Double(a, b) = self.cell_map.get(player) {}
|
||||
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?
|
||||
|
@ -204,14 +208,22 @@ impl Level {
|
|||
|
||||
// render blocks
|
||||
for block in self.blocks.iter() {
|
||||
for segment in block.segments.iter() {
|
||||
let offset = match &segment.3 {
|
||||
for segment in block.get_segments().iter() {
|
||||
let offset = match &segment.board {
|
||||
Board::Left => left_off,
|
||||
Board::Right => right_off,
|
||||
};
|
||||
let coord = (segment.0 + block.position.0, segment.1 + block.position.1);
|
||||
let location = (offset.0 + coord.0 * scale, offset.1 + coord.1 * scale);
|
||||
renderer.render_segment(location, scale, block.color, block.orientation, segment.2);
|
||||
let location = (
|
||||
offset.0 + segment.position.0 * scale,
|
||||
offset.1 + segment.position.1 * scale,
|
||||
);
|
||||
renderer.render_segment(
|
||||
location,
|
||||
scale,
|
||||
block.get_color(),
|
||||
block.get_orientation(),
|
||||
segment.shape,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -228,75 +240,15 @@ impl Level {
|
|||
offset: (i32, i32),
|
||||
) {
|
||||
let location = (
|
||||
offset.0 + player.position[0] * scale + 4,
|
||||
offset.1 + player.position[1] * scale + 4,
|
||||
offset.0 + player.position.0 * scale + 4,
|
||||
offset.1 + player.position.1 * scale + 4,
|
||||
);
|
||||
renderer.render_segment(
|
||||
location,
|
||||
(scale - 8),
|
||||
(
|
||||
player.color[0] as f32,
|
||||
player.color[1] as f32,
|
||||
player.color[2] as f32,
|
||||
),
|
||||
player.color,
|
||||
Orientation::Both,
|
||||
Shape::Full,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
struct CellMap(HashMap<(i32, i32, Board), CellContents>);
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
enum CellContents {
|
||||
Empty,
|
||||
Player,
|
||||
Single(Segment),
|
||||
|
||||
// invariant: .0 < .1
|
||||
Double(Segment, Segment),
|
||||
}
|
||||
|
||||
impl CellMap {
|
||||
pub fn new() -> Self {
|
||||
CellMap(HashMap::new())
|
||||
}
|
||||
|
||||
pub fn get(&self, loc: (i32, i32, Board)) -> CellContents {
|
||||
self.0
|
||||
.get(&loc)
|
||||
.cloned()
|
||||
.unwrap_or_else(|| CellContents::Empty)
|
||||
}
|
||||
|
||||
pub fn clear(&mut self, loc: (i32, i32, Board)) {
|
||||
self.0.remove(&loc);
|
||||
}
|
||||
|
||||
pub fn add(&mut self, loc: (i32, i32, Board), segment: &Segment) -> bool {
|
||||
let contents = self.get(loc).clone();
|
||||
match contents {
|
||||
CellContents::Empty => {
|
||||
// just add it like normal
|
||||
self.0.insert(loc, CellContents::Single(*segment));
|
||||
true
|
||||
}
|
||||
CellContents::Single(existing) => {
|
||||
if existing.2.is_opposite(&segment.2) {
|
||||
self.0.insert(
|
||||
loc,
|
||||
if *segment < existing {
|
||||
CellContents::Double(*segment, existing)
|
||||
} else {
|
||||
CellContents::Double(existing, *segment)
|
||||
},
|
||||
);
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
CellContents::Player | CellContents::Double(_, _) => false,
|
||||
}
|
||||
}
|
||||
}
|
23
src/level/player.rs
Normal file
23
src/level/player.rs
Normal file
|
@ -0,0 +1,23 @@
|
|||
use crate::color::Color;
|
||||
use crate::enums::Orientation;
|
||||
use crate::level::{Blockish, Segment};
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct Player {
|
||||
pub position: (i32, i32),
|
||||
pub color: Color,
|
||||
}
|
||||
|
||||
impl Blockish for Player {
|
||||
fn get_color(&self) -> Color {
|
||||
self.color
|
||||
}
|
||||
|
||||
fn get_orientation(&self) -> Orientation {
|
||||
Orientation::None
|
||||
}
|
||||
|
||||
fn get_segments(&self) -> Vec<Segment> {
|
||||
vec![]
|
||||
}
|
||||
}
|
|
@ -4,6 +4,7 @@ extern crate nalgebra_glm as glm;
|
|||
#[macro_use]
|
||||
extern crate serde_derive;
|
||||
|
||||
mod color;
|
||||
mod data;
|
||||
mod enums;
|
||||
mod game;
|
||||
|
|
|
@ -3,6 +3,7 @@ use glium::index::{NoIndices, PrimitiveType};
|
|||
use glium::{Display, Frame, Program, Surface, Texture2d, VertexBuffer};
|
||||
use nalgebra::{Matrix4, Vector4};
|
||||
|
||||
use crate::color::Color;
|
||||
use crate::enums::{Orientation, Shape};
|
||||
use crate::game::Game;
|
||||
|
||||
|
@ -85,7 +86,7 @@ impl<'a, 'b> Renderer<'a, 'b> {
|
|||
&mut self,
|
||||
location: (i32, i32),
|
||||
scale: i32,
|
||||
color: (f32, f32, f32),
|
||||
color: Color,
|
||||
orientation: Orientation,
|
||||
shape: Shape,
|
||||
) {
|
||||
|
@ -199,6 +200,7 @@ impl<'a, 'b> Renderer<'a, 'b> {
|
|||
|
||||
let rotate_texture = match orientation {
|
||||
Orientation::Both => false,
|
||||
Orientation::None => false,
|
||||
Orientation::Vertical => true,
|
||||
Orientation::Horizontal => false,
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue