mill_game/src/board.rs

478 lines
16 KiB
Rust
Raw Normal View History

2023-05-08 18:56:50 +00:00
use std::sync::Arc;
use anyhow::Result;
use engine::prelude::{
2023-05-09 14:39:53 +00:00
cgmath::{vec2, vec3, Vector2, Vector3},
2023-05-08 18:56:50 +00:00
*,
};
2023-05-09 14:39:53 +00:00
use crate::{game::MillGame, objects::Objects};
#[derive(Debug, PartialEq, Clone, Copy)]
pub struct BoardSlot {
pub state: BoardSlotState,
pub position: Vector2<f32>,
pub slot_marker: Option<Entity>,
}
impl BoardSlot {
pub const SLOT_MARKER_SIZE: f32 = 1.5;
pub fn new(position: Vector2<f32>, scene: &mut Scene) -> Result<Self> {
let mut marker = scene.engine().assets().empty_entity();
let meshes = vec![Self::create_mesh(&scene.engine(), Color::Black)?];
let draw = Draw::new(meshes);
marker.insert_component(draw);
let mut location = Location::from_entity(&mut marker);
location.set_position(position.extend(MillGame::OFFSET_TO_BOARD));
marker.insert_component(location);
Ok(Self {
state: BoardSlotState::default(),
position,
slot_marker: Some(scene.add_entity(marker)?),
})
}
pub fn invalid() -> Self {
Self {
state: BoardSlotState::Invalid,
position: vec2(0.0, 0.0),
slot_marker: None,
}
}
fn create_mesh(engine: &Arc<Engine>, color: Color) -> Result<AssetMesh> {
let mut mesh = AssetMesh::new(
engine.device(),
engine.settings().graphics_info()?.render_type,
)?;
let vertex_buffer = Buffer::builder()
.set_data(&Objects::create_flat_quad([
vec2(-Self::SLOT_MARKER_SIZE * 0.5, -Self::SLOT_MARKER_SIZE * 0.5),
vec2(Self::SLOT_MARKER_SIZE * 0.5, -Self::SLOT_MARKER_SIZE * 0.5),
vec2(Self::SLOT_MARKER_SIZE * 0.5, Self::SLOT_MARKER_SIZE * 0.5),
vec2(-Self::SLOT_MARKER_SIZE * 0.5, Self::SLOT_MARKER_SIZE * 0.5),
]))
.set_usage(VK_BUFFER_USAGE_VERTEX_BUFFER_BIT)
.set_memory_usage(MemoryUsage::CpuOnly)
.build(engine.device().clone())?;
let a: [f32; 3] = color.into();
mesh.add_primitive(
vertex_buffer,
None,
None,
PrimitiveMaterial {
color: [a[0], a[1], a[2], 1.0],
metallic_factor: 0.2,
emissive_factor: [0.2, 0.2, 0.2],
roughness_factor: 0.8,
alpha_mode: AlphaMode::Opaque,
alpha_cut_off: 0.5,
},
true,
)?;
Ok(mesh)
}
}
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum BoardSlotState {
Invalid,
Empty,
Black(Entity),
White(Entity),
}
impl Default for BoardSlotState {
fn default() -> Self {
Self::Empty
}
}
2023-05-08 18:56:50 +00:00
pub struct Board {
2023-05-09 16:58:07 +00:00
_board: Entity,
2023-05-09 14:39:53 +00:00
center: Vector3<f32>,
2023-05-09 16:58:07 +00:00
_connection_lines: Vec<Entity>,
2023-05-09 14:39:53 +00:00
slots: [[[BoardSlot; 3]; 3]; 3],
white_start_slots: [Vector2<f32>; 9],
black_start_slots: [Vector2<f32>; 9],
2023-05-08 18:56:50 +00:00
}
impl Board {
2023-05-09 16:58:07 +00:00
pub fn new(engine: &Arc<Engine>, scene: &mut SceneHandle) -> Result<Self> {
2023-05-08 18:56:50 +00:00
let mut board_entity = engine.assets().empty_entity();
let meshes = vec![Self::create_board_base(&engine)?];
let draw = Draw::new(meshes);
board_entity.insert_component(draw);
let location = Location::from_entity(&mut board_entity);
board_entity.insert_component(location);
let mut board = None;
2023-05-09 14:39:53 +00:00
let mut slots = None;
2023-05-08 18:56:50 +00:00
scene.on_scene(|scene| {
board = Some(scene.add_entity(board_entity)?);
2023-05-09 14:39:53 +00:00
slots = Some([
[
[
BoardSlot::new(vec2(-15.0, -15.0), scene)?, // 0 0 0
BoardSlot::new(vec2(-10.0, -10.0), scene)?, // 0 0 1
BoardSlot::new(vec2(-5.0, -5.0), scene)?, // 0 0 2
],
[
BoardSlot::new(vec2(-15.0, 0.0), scene)?, // 0 1 0
BoardSlot::new(vec2(-10.0, 0.0), scene)?, // 0 1 1
BoardSlot::new(vec2(-5.0, 0.0), scene)?, // 0 1 2
],
[
BoardSlot::new(vec2(-15.0, 15.0), scene)?, // 0 2 0
BoardSlot::new(vec2(-10.0, 10.0), scene)?, // 0 2 1
BoardSlot::new(vec2(-5.0, 5.0), scene)?, // 0 2 2
],
],
[
[
BoardSlot::new(vec2(0.0, -15.0), scene)?, // 1 0 0
BoardSlot::new(vec2(0.0, -10.0), scene)?, // 1 0 1
BoardSlot::new(vec2(0.0, -5.0), scene)?, // 1 0 2
],
[
BoardSlot::invalid(), // 1 1 0
BoardSlot::invalid(), // 1 1 1
BoardSlot::invalid(), // 1 1 2
],
[
BoardSlot::new(vec2(0.0, 15.0), scene)?, // 1 2 0
BoardSlot::new(vec2(0.0, 10.0), scene)?, // 1 2 1
BoardSlot::new(vec2(0.0, 5.0), scene)?, // 1 2 2
],
],
[
[
BoardSlot::new(vec2(15.0, -15.0), scene)?, // 2 0 0
BoardSlot::new(vec2(10.0, -10.0), scene)?, // 2 0 1
BoardSlot::new(vec2(5.0, -5.0), scene)?, // 2 0 2
],
[
BoardSlot::new(vec2(15.0, 0.0), scene)?, // 2 1 0
BoardSlot::new(vec2(10.0, 0.0), scene)?, // 2 1 1
BoardSlot::new(vec2(5.0, 0.0), scene)?, // 2 1 2
],
[
BoardSlot::new(vec2(15.0, 15.0), scene)?, // 2 2 0
BoardSlot::new(vec2(10.0, 10.0), scene)?, // 2 2 1
BoardSlot::new(vec2(5.0, 5.0), scene)?, // 2 2 2
],
],
]);
2023-05-08 18:56:50 +00:00
Ok(())
})?;
2023-05-09 14:39:53 +00:00
let distance = 20.0;
let white_start_slots = [
vec2(-16.0, distance),
vec2(-12.0, distance),
vec2(-8.0, distance),
vec2(-4.0, distance),
vec2(0.0, distance),
vec2(4.0, distance),
vec2(8.0, distance),
vec2(12.0, distance),
vec2(16.0, distance),
];
let black_start_slots = [
vec2(-16.0, -distance),
vec2(-12.0, -distance),
vec2(-8.0, -distance),
vec2(-4.0, -distance),
vec2(0.0, -distance),
vec2(4.0, -distance),
vec2(8.0, -distance),
vec2(12.0, -distance),
vec2(16.0, -distance),
];
2023-05-09 16:58:07 +00:00
Ok(Self {
_board: board.unwrap(),
2023-05-09 14:39:53 +00:00
center: vec3(0.0, 0.0, 0.0),
2023-05-09 16:58:07 +00:00
_connection_lines: Self::create_connection_lines(scene, Color::Black)?,
2023-05-09 14:39:53 +00:00
slots: slots.unwrap(),
white_start_slots,
black_start_slots,
2023-05-09 16:58:07 +00:00
})
2023-05-08 18:56:50 +00:00
}
2023-05-09 14:39:53 +00:00
pub fn center(&self) -> Vector3<f32> {
self.center
}
pub fn white_start_slots(&self) -> &[Vector2<f32>; 9] {
&self.white_start_slots
}
pub fn black_start_slots(&self) -> &[Vector2<f32>; 9] {
&self.black_start_slots
}
2023-05-09 16:58:07 +00:00
pub fn slots(&mut self) -> &mut [[[BoardSlot; 3]; 3]; 3] {
&mut self.slots
}
pub fn close_to_marker(&mut self, position: Vector2<f32>) -> Option<&mut BoardSlot> {
2023-05-09 14:39:53 +00:00
const DISTANCE: f32 = 1.25;
2023-05-09 16:58:07 +00:00
for outer in self.slots.iter_mut() {
for inner in outer.iter_mut() {
for slot in inner.iter_mut() {
2023-05-09 14:39:53 +00:00
if slot.state != BoardSlotState::Invalid {
if (slot.position - position).magnitude() <= DISTANCE {
2023-05-09 16:58:07 +00:00
return Some(slot);
2023-05-09 14:39:53 +00:00
}
}
}
}
}
2023-05-09 16:58:07 +00:00
None
2023-05-09 14:39:53 +00:00
}
}
impl Board {
2023-05-08 18:56:50 +00:00
fn create_board_base(engine: &Arc<Engine>) -> Result<AssetMesh> {
let mut board_base = AssetMesh::new(
engine.device(),
engine.settings().graphics_info()?.render_type,
)?;
let vertex_buffer = Buffer::builder()
2023-05-09 14:39:53 +00:00
.set_data(&Objects::create_cuboid(
vec3(-22.5, -25.0, -2.0),
vec3(45.0, 50.0, 2.0),
2023-05-08 18:56:50 +00:00
))
.set_usage(VK_BUFFER_USAGE_VERTEX_BUFFER_BIT)
.set_memory_usage(MemoryUsage::CpuOnly)
.build(engine.device().clone())?;
let color = Color::try_from("#b77b2b")?;
let a: [f32; 3] = color.into();
board_base.add_primitive(
vertex_buffer,
None,
None,
PrimitiveMaterial {
color: [a[0], a[1], a[2], 1.0],
metallic_factor: 0.2,
2023-05-09 14:39:53 +00:00
emissive_factor: [0.5, 0.5, 0.5],
2023-05-08 18:56:50 +00:00
roughness_factor: 0.8,
alpha_mode: AlphaMode::Opaque,
alpha_cut_off: 0.5,
},
true,
)?;
Ok(board_base)
}
2023-05-09 14:39:53 +00:00
fn create_connection_lines(scene: &mut SceneHandle, color: Color) -> Result<Vec<Entity>> {
let mut entities = Vec::new();
scene.on_scene(|scene| {
let mut lines = scene.engine().assets().empty_entity();
let draw = Draw::new(vec![{
let mut mesh = AssetMesh::new(
scene.engine().device(),
scene.engine().settings().graphics_info()?.render_type,
)?;
let vertex_buffer = Buffer::builder()
.set_data(
&[
Objects::create_flat_quad([
vec2(-15.25, -15.25),
vec2(15.25, -15.25),
vec2(15.25, -14.75),
vec2(-15.25, -14.75),
]),
Objects::create_flat_quad([
vec2(-10.25, -10.25),
vec2(10.25, -10.25),
vec2(10.25, -9.75),
vec2(-10.25, -9.75),
]),
Objects::create_flat_quad([
vec2(-5.25, -5.25),
vec2(5.25, -5.25),
vec2(5.25, -4.75),
vec2(-5.25, -4.75),
]),
Objects::create_flat_quad([
vec2(-15.25, 14.75),
vec2(15.25, 14.75),
vec2(15.25, 15.25),
vec2(-15.25, 15.25),
]),
Objects::create_flat_quad([
vec2(-10.25, 9.75),
vec2(10.25, 9.75),
vec2(10.25, 10.25),
vec2(-10.25, 10.25),
]),
Objects::create_flat_quad([
vec2(-5.25, 4.75),
vec2(5.25, 4.75),
vec2(5.25, 5.25),
vec2(-5.25, 5.25),
]),
Objects::create_flat_quad([
vec2(-14.75, -15.25),
vec2(-14.75, 15.25),
vec2(-15.25, 15.25),
vec2(-15.25, -15.25),
]),
Objects::create_flat_quad([
vec2(-9.75, -10.25),
vec2(-9.75, 10.25),
vec2(-10.25, 10.25),
vec2(-10.25, -10.25),
]),
Objects::create_flat_quad([
vec2(-4.75, -5.25),
vec2(-4.75, 5.25),
vec2(-5.25, 5.25),
vec2(-5.25, -5.25),
]),
Objects::create_flat_quad([
vec2(15.25, -15.25),
vec2(15.25, 15.25),
vec2(14.75, 15.25),
vec2(14.75, -15.25),
]),
Objects::create_flat_quad([
vec2(10.25, -10.25),
vec2(10.25, 10.25),
vec2(9.75, 10.25),
vec2(9.75, -10.25),
]),
Objects::create_flat_quad([
vec2(5.25, -5.25),
vec2(5.25, 5.25),
vec2(4.75, 5.25),
vec2(4.75, -5.25),
]),
Objects::create_flat_quad([
vec2(0.25, -15.25),
vec2(0.25, -4.75),
vec2(-0.25, -4.75),
vec2(-0.25, -15.25),
]),
Objects::create_flat_quad([
vec2(-0.25, 15.25),
vec2(-0.25, 4.75),
vec2(0.25, 4.75),
vec2(0.25, 15.25),
]),
Objects::create_flat_quad([
vec2(-15.25, -0.25),
vec2(-4.75, -0.25),
vec2(-4.75, 0.25),
vec2(-15.25, 0.25),
]),
Objects::create_flat_quad([
vec2(15.25, 0.25),
vec2(4.75, 0.25),
vec2(4.75, -0.25),
vec2(15.25, -0.25),
]),
]
.concat(),
)
.set_usage(VK_BUFFER_USAGE_VERTEX_BUFFER_BIT)
.set_memory_usage(MemoryUsage::CpuOnly)
.build(scene.engine().device().clone())?;
let a: [f32; 3] = color.into();
mesh.add_primitive(
vertex_buffer,
None,
None,
PrimitiveMaterial {
color: [a[0], a[1], a[2], 1.0],
metallic_factor: 0.2,
emissive_factor: [0.2, 0.2, 0.2],
roughness_factor: 0.8,
alpha_mode: AlphaMode::Opaque,
alpha_cut_off: 0.5,
},
true,
)?;
mesh
}]);
lines.insert_component(draw);
let mut location = Location::from_entity(&mut lines);
location.set_offset(vec3(0.0, 0.0, MillGame::OFFSET_TO_BOARD));
lines.insert_component(location);
entities.push(scene.add_entity(lines)?);
Ok(())
})?;
Ok(entities)
2023-05-08 18:56:50 +00:00
}
}
impl Map for Board {
fn name(&self) -> &str {
"MillBoard"
}
fn check_walkability(
&self,
_position: cgmath::Vector2<f32>,
_direction: cgmath::Vector2<f32>,
_radius: f32,
) -> Result<bool> {
Ok(true)
}
fn get_height(&self, _x: f32, _y: f32) -> Result<f32> {
Ok(0.0)
}
fn spawn_positions(&self) -> Result<Vec<cgmath::Vector3<f32>>> {
Ok(vec![])
}
fn leave_markers(&self) -> Result<Vec<Entity>> {
Ok(vec![])
}
2023-05-09 14:39:53 +00:00
fn disable(&self, _scene: &mut Scene) -> Result<()> {
unreachable!()
2023-05-08 18:56:50 +00:00
}
}