mill_game/src/game.rs

224 lines
7.2 KiB
Rust
Raw Normal View History

2023-05-09 14:39:53 +00:00
use std::sync::{
atomic::{AtomicU32, Ordering::SeqCst},
Arc, Mutex,
};
2023-05-08 18:56:50 +00:00
use anyhow::Result;
2023-05-09 14:39:53 +00:00
use engine::prelude::{cgmath::vec3, *};
2023-05-08 18:56:50 +00:00
2023-05-09 14:39:53 +00:00
use crate::{board::Board, objects::Objects};
2023-05-08 18:56:50 +00:00
pub struct MillGame {
board: Arc<Board>,
2023-05-09 14:39:53 +00:00
white_stones: [Entity; 9],
black_stones: [Entity; 9],
scene: Mutex<SceneHandle>,
camera_controls: Mutex<CameraControl>,
mouse_x: AtomicU32,
mouse_y: AtomicU32,
2023-05-08 18:56:50 +00:00
}
impl MillGame {
2023-05-09 14:39:53 +00:00
pub const OFFSET_TO_BOARD: f32 = 0.01;
2023-05-08 18:56:50 +00:00
pub fn new(engine: Arc<Engine>) -> Result<Arc<Self>> {
let mut scene = SceneHandle::new(&engine)?;
2023-05-09 14:39:53 +00:00
let board = Board::new(&engine, &mut scene)?;
let mut white_stones = None;
let mut black_stones = None;
scene.on_scene(|scene| {
let view = scene.view_mut();
view.camera_mut().set_center(board.center());
view.update_buffer()?;
// add light
let mut sun_light = engine.new_directional_light()?;
sun_light.set_direction(vec3(10.0, -4.0, -20.0))?;
sun_light.set_color(vec3(1.0, 1.0, 1.0))?;
sun_light.set_position(vec3(0.0, 0.0, 100.0))?;
sun_light.set_power(10000000000.0)?;
scene.add_light(sun_light)?;
white_stones = Some(
Self::init_nine_stones(&engine, Color::White)?
.into_iter()
.enumerate()
.map(|(index, mut e)| {
let location = e.get_component_mut::<Location>()?;
location.set_position(board.white_start_slots()[index].extend(0.0));
scene.add_entity(e)
})
.collect::<Result<Vec<Entity>>>()?
.try_into()
.unwrap_or_else(|_: Vec<Entity>| {
unreachable!("create array from vec from an array")
}),
);
black_stones = Some(
Self::init_nine_stones(&engine, Color::Black)?
.into_iter()
.enumerate()
.map(|(index, mut e)| {
let location = e.get_component_mut::<Location>()?;
location.set_position(board.black_start_slots()[index].extend(0.0));
scene.add_entity(e)
})
.collect::<Result<Vec<Entity>>>()?
.try_into()
.unwrap_or_else(|_: Vec<Entity>| {
unreachable!("create array from vec from an array")
}),
);
Ok(())
})?;
let camera_control = CameraControl::new(&mut scene)?;
2023-05-08 18:56:50 +00:00
scene.activate()?;
Ok(Arc::new(Self {
2023-05-09 14:39:53 +00:00
board,
white_stones: white_stones.unwrap(),
black_stones: black_stones.unwrap(),
scene: Mutex::new(scene),
camera_controls: Mutex::new(camera_control),
mouse_x: AtomicU32::new(0),
mouse_y: AtomicU32::new(0),
2023-05-08 18:56:50 +00:00
}))
}
2023-05-09 14:39:53 +00:00
fn init_nine_stones(engine: &Arc<Engine>, color: Color) -> Result<[EntityObject; 9]> {
Ok((0..9)
.map(|_| Self::init_stone(engine, color))
.collect::<Result<Vec<EntityObject>>>()?
.try_into()
.unwrap_or_else(|_: Vec<EntityObject>| {
unreachable!("create array from vec from an array")
}))
}
fn init_stone(engine: &Arc<Engine>, color: Color) -> Result<EntityObject> {
let mut marker = engine.assets().empty_entity();
let draw = Draw::new(vec![{
let mut mesh = AssetMesh::new(
engine.device(),
engine.settings().graphics_info()?.render_type,
)?;
let vertex_buffer = Buffer::builder()
.set_data(&Objects::create_cylinder(1.0, 0.25, 12))
.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,
)?;
mesh
}]);
marker.insert_component(draw);
let location = Location::from_entity(&mut marker);
marker.insert_component(location);
Ok(marker)
}
2023-05-08 18:56:50 +00:00
}
impl EngineObject for MillGame {
fn name(&self) -> &str {
"MillGame"
}
fn update(&self) -> Result<()> {
Ok(())
}
fn event(&self, event: EngineEvent) -> Result<()> {
match event {
2023-05-09 14:39:53 +00:00
EngineEvent::MouseMotion(x, y) => {
self.mouse_x.store(x, SeqCst);
self.mouse_y.store(y, SeqCst);
self.camera_controls.lock().unwrap().mouse_move(
x,
y,
&mut *self.scene.lock().unwrap(),
)?;
}
EngineEvent::MouseButtonDown(button) => match button {
MouseButton::Left => {
self.scene.lock().unwrap().on_scene(|scene| {
if let Some(world_space) = scene.screen_space_to_world(
self.mouse_x.load(SeqCst),
self.mouse_y.load(SeqCst),
)? {
if self.board.close_to_marker(world_space.truncate()) {
println!("close to marker");
} else {
println!("not close to a marker");
}
}
Ok(())
})?;
}
MouseButton::Middle => self.camera_controls.lock().unwrap().hold(),
MouseButton::Right => (),
MouseButton::Forward => (),
MouseButton::Backward => (),
},
EngineEvent::MouseButtonUp(button) => match button {
MouseButton::Left => (),
MouseButton::Middle => self.camera_controls.lock().unwrap().release(),
MouseButton::Right => (),
MouseButton::Forward => (),
MouseButton::Backward => (),
},
EngineEvent::MouseWheel(_x, y, direction) => self
.camera_controls
.lock()
.unwrap()
.scroll_wheel(y, direction, &mut *self.scene.lock().unwrap())?,
2023-05-08 19:24:12 +00:00
EngineEvent::KeyDown(_) => (),
EngineEvent::KeyUp(_) => (),
EngineEvent::ButtonDown(_) => (),
EngineEvent::ButtonUp(_) => (),
EngineEvent::ControllerAxis(_) => (),
EngineEvent::ControllerAdded(_) => (),
EngineEvent::ControllerRemoved(_) => (),
EngineEvent::FileDrop(_) => (),
2023-05-08 18:56:50 +00:00
}
Ok(())
}
}