Compare commits

..

2 commits

Author SHA1 Message Date
Michael Huebner
84dbd488b4 Fix some crashes 2025-03-25 15:11:41 +01:00
Michael Huebner
50cc8c2cfe Continue fixing (finish) 2025-03-25 14:59:44 +01:00
4 changed files with 108 additions and 138 deletions

View file

@ -16,7 +16,7 @@ pub struct BoardSlot {
state: BoardSlotState, state: BoardSlotState,
pub position: Vector2<f32>, pub position: Vector2<f32>,
pub slot_marker: Option<Entity>, pub _slot_marker: Option<Entity>,
} }
impl BoardSlot { impl BoardSlot {
@ -40,9 +40,8 @@ impl BoardSlot {
let draw = Draw::new(meshes); let draw = Draw::new(meshes);
marker.insert_component(draw); marker.insert_component(draw);
let mut location = Location::from_entity(&mut marker); let location = Location::new_and_setup(&mut marker)?;
location.set_position(position.extend(MillGame::OFFSET_TO_BOARD)); location.set_position(position.extend(MillGame::OFFSET_TO_BOARD));
marker.insert_component(location);
Ok(Self { Ok(Self {
x, x,
@ -51,7 +50,7 @@ impl BoardSlot {
state: BoardSlotState::default(), state: BoardSlotState::default(),
position, position,
slot_marker: Some(world.add_entity(marker)?), _slot_marker: Some(world.add_entity(marker)?),
}) })
} }
@ -63,7 +62,7 @@ impl BoardSlot {
state: BoardSlotState::Invalid, state: BoardSlotState::Invalid,
position: vec2(0.0, 0.0), position: vec2(0.0, 0.0),
slot_marker: None, _slot_marker: None,
} }
} }
@ -169,9 +168,7 @@ impl Board {
let draw = Draw::new(meshes); let draw = Draw::new(meshes);
board_entity.insert_component(draw); board_entity.insert_component(draw);
Location::new_and_setup(&mut board_entity)?;
let location = Location::from_entity(&mut board_entity);
board_entity.insert_component(location);
let board = world.add_entity(board_entity)?; let board = world.add_entity(board_entity)?;
@ -231,17 +228,17 @@ impl Board {
let distance = 20.0; let distance = 20.0;
let white_start_slots = (16..=16) let white_start_slots = (-16..=16)
.step_by(4) .step_by(4)
.map(|x| vec2(x as f32, distance)) .map(|x| vec2(x as f32, distance))
.collect() .collect::<Vec<_>>()
.try_into() .try_into()
.unwrap(); .unwrap();
let black_start_slots = (16..=16) let black_start_slots = (-16..=16)
.step_by(4) .step_by(4)
.map(|x| vec2(x as f32, -distance)) .map(|x| vec2(x as f32, -distance))
.collect() .collect::<Vec<_>>()
.try_into() .try_into()
.unwrap(); .unwrap();
@ -546,9 +543,8 @@ impl Board {
}]); }]);
lines.insert_component(draw); lines.insert_component(draw);
let mut location = Location::from_entity(&mut lines); let location = Location::new_and_setup(&mut lines)?;
location.set_offset(vec3(0.0, 0.0, MillGame::OFFSET_TO_BOARD)); location.set_offset(vec3(0.0, 0.0, MillGame::OFFSET_TO_BOARD));
lines.insert_component(location);
entities.push(world.add_entity(lines)?); entities.push(world.add_entity(lines)?);

View file

@ -325,8 +325,7 @@ impl MillGame {
me.state = GameState::Placing; me.state = GameState::Placing;
me.current_player = PlayerColor::Black; me.current_player = PlayerColor::Black;
me.finish_turn(world); me.finish_turn(now);
me.last_turn_timing = now;
Ok(()) Ok(())
} }
@ -365,13 +364,13 @@ impl MillGame {
Ok(()) Ok(())
} }
pub fn finish_turn(&mut self, world: &World) { pub fn finish_turn(&mut self, now: Duration) {
Self::log( Self::log(
&format!("{:?} finished turn", self.current_player), &format!("{:?} finished turn", self.current_player),
LogSeverity::Debug, LogSeverity::Debug,
); );
self.last_turn_timing = world.now(); self.last_turn_timing = now;
self.turn_finished = true; self.turn_finished = true;
self.selected_field = None; self.selected_field = None;
} }
@ -406,7 +405,7 @@ impl MillGame {
Ok(()) Ok(())
} }
fn next_game_step(&mut self, world: &World) -> Result<()> { fn next_game_step(&mut self, world: &mut World) -> Result<()> {
Self::log( Self::log(
&format!( &format!(
" =========================== NEW TURN ({:?}) ===========================", " =========================== NEW TURN ({:?}) ===========================",
@ -492,7 +491,7 @@ impl MillGame {
LogSeverity::Debug, LogSeverity::Debug,
); );
let mut resources = world.resources.multi_mut(); let mut resources = unsafe { remove_life_time_mut(world) }.resources.multi_mut();
let gui_handler = resources.get::<GuiHandler>(); let gui_handler = resources.get::<GuiHandler>();
let simple_ai = resources.get::<SimpleAI>(); let simple_ai = resources.get::<SimpleAI>();
@ -515,13 +514,13 @@ impl MillGame {
Self::log("current player is AI", LogSeverity::Debug); Self::log("current player is AI", LogSeverity::Debug);
simple_ai.step( simple_ai.step(
&mut self.stones(simple_ai.player_color), unsafe { remove_life_time_mut(self.stones_mut(simple_ai.player_color)) },
self.board.slots_mut(), unsafe { remove_life_time_mut(self.board.slots_mut()) },
&mut *self.scene.lock().unwrap(), world,
&mut self.state, &mut self.state,
)?; )?;
self.finish_turn(world); self.finish_turn(world.now());
} }
Self::log("leave next_game_step", LogSeverity::Debug); Self::log("leave next_game_step", LogSeverity::Debug);
@ -529,10 +528,10 @@ impl MillGame {
Ok(()) Ok(())
} }
fn stones(&self, player_color: PlayerColor) -> &[Stone; 9] { fn stones_mut(&mut self, player_color: PlayerColor) -> &mut [Stone; 9] {
match player_color { match player_color {
PlayerColor::White => &self.white_stones, PlayerColor::White => &mut self.white_stones,
PlayerColor::Black => &self.black_stones, PlayerColor::Black => &mut self.black_stones,
} }
} }
@ -586,8 +585,7 @@ impl MillGame {
}]); }]);
marker.insert_component(draw); marker.insert_component(draw);
let location = Location::from_entity(&mut marker); Location::new_and_setup(&mut marker)?;
marker.insert_component(location);
Ok(marker) Ok(marker)
} }
@ -664,7 +662,7 @@ impl MillGame {
LogSeverity::Debug, LogSeverity::Debug,
); );
let slot = &mut board[x][y][z]; let slot = unsafe { remove_life_time_mut(&mut board[x][y][z]) };
let neighbour = &mut board[tx][ty][tz]; let neighbour = &mut board[tx][ty][tz];
if neighbour.state() != BoardSlotState::Empty if neighbour.state() != BoardSlotState::Empty
@ -829,15 +827,20 @@ impl MillGame {
fn check_mouse_click<F>(&mut self, scene: &Scene, f: F) -> Result<()> fn check_mouse_click<F>(&mut self, scene: &Scene, f: F) -> Result<()>
where where
F: FnOnce(&Self, (usize, usize, usize), &mut [[[BoardSlot; 3]; 3]; 3]) -> Result<()>, F: FnOnce(&mut Self, (usize, usize, usize), &mut [[[BoardSlot; 3]; 3]; 3]) -> Result<()>,
{ {
Self::log("check_mouse_click", LogSeverity::Debug); Self::log("check_mouse_click", LogSeverity::Debug);
if let Some(world_space) = scene.screen_space_to_world(self.mouse_x, self.mouse_y)? { if let Some(world_space) = scene.screen_space_to_world(self.mouse_x, self.mouse_y)? {
if let Some(slot) = self.board.close_to_marker(world_space.truncate()) { if let Some(slot) = unsafe { remove_life_time(self) }
.board
.close_to_marker(world_space.truncate())
{
Self::log("click is close to marker", LogSeverity::Debug); Self::log("click is close to marker", LogSeverity::Debug);
f(self, (slot.x, slot.y, slot.z), self.board.slots_mut())?; let slots = unsafe { remove_life_time_mut(self.board.slots_mut()) };
f(self, (slot.x, slot.y, slot.z), slots)?;
} }
} }
@ -886,7 +889,7 @@ impl MillGame {
pub fn update(world: &mut World) -> Result<bool> { pub fn update(world: &mut World) -> Result<bool> {
let now = world.now(); let now = world.now();
let me = world.resources.get_mut::<Self>(); let me = world.resources.get_mut_unchecked::<Self>();
if me.turn_finished { if me.turn_finished {
if (me.last_turn_timing + Self::TURN_WAIT_TIME) < now { if (me.last_turn_timing + Self::TURN_WAIT_TIME) < now {
@ -921,13 +924,12 @@ impl EventConsumer for MillGame {
match self.state { match self.state {
GameState::Placing => { GameState::Placing => {
let mut resources = world.resources.multi_mut();
self.check_mouse_click( self.check_mouse_click(
resources.get::<Scene>(), world.resources.get_unchecked::<Scene>(),
|me, (x, y, z), board| { |me, (x, y, z), board| {
if let Some(placable) = me if let Some(placable) = unsafe {
.stones(me.current_player) remove_life_time_mut(me.stones_mut(me.current_player))
}
.iter_mut() .iter_mut()
.find(|stone| stone.state == StoneState::ReadyToBePlaced) .find(|stone| stone.state == StoneState::ReadyToBePlaced)
{ {
@ -938,10 +940,10 @@ impl EventConsumer for MillGame {
board, board,
me.current_player, me.current_player,
world, world,
&mut self.state, &mut me.state,
)? == MillState::None )? == MillState::None
{ {
me.finish_turn(world); me.finish_turn(world.now());
} }
} else { } else {
Self::log( Self::log(
@ -960,10 +962,8 @@ impl EventConsumer for MillGame {
)?; )?;
} }
GameState::Removing => { GameState::Removing => {
let mut resources = world.resources.multi_mut();
self.check_mouse_click( self.check_mouse_click(
resources.get::<Scene>(), world.resources.get_unchecked::<Scene>(),
|me, (x, y, z), board| { |me, (x, y, z), board| {
let slot = &mut board[x][y][z]; let slot = &mut board[x][y][z];
@ -981,9 +981,8 @@ impl EventConsumer for MillGame {
(BoardSlotState::White(_), PlayerColor::Black) => true, (BoardSlotState::White(_), PlayerColor::Black) => true,
_ => false, _ => false,
} { } {
let mut stones = self.stones(me.current_player.other()); let stone = me
.stones_mut(me.current_player.other())
let stone = stones
.iter_mut() .iter_mut()
.find(|s| { .find(|s| {
s.stone s.stone
@ -997,7 +996,7 @@ impl EventConsumer for MillGame {
Self::remove_stone(stone, slot, world)?; Self::remove_stone(stone, slot, world)?;
me.finish_turn(world); me.finish_turn(world.now());
} }
Ok(()) Ok(())
@ -1005,17 +1004,15 @@ impl EventConsumer for MillGame {
)?; )?;
} }
GameState::Main => { GameState::Main => {
let mut resources = world.resources.multi_mut(); self.check_mouse_click(world.resources.get_unchecked::<Scene>() , |me, (tx, ty, tz), board| {
self.check_mouse_click(resources.get::<Scene>() , |me, (tx, ty, tz), board| {
match me.selected_field { match me.selected_field {
Some((x, y, z)) => { Some((x, y, z)) => {
if Self::is_neighbour((x, y, z), (tx, ty, tz)) { if Self::is_neighbour((x, y, z), (tx, ty, tz)) {
if let Some(millstate) if let Some(millstate)
= Self::move_stone((x,y,z), (tx,ty,tz), world, board, &mut self.state)? { = Self::move_stone((x,y,z), (tx,ty,tz), world, board, &mut me.state)? {
if let MillState::None = millstate { if let MillState::None = millstate {
me.selected_field = None; me.selected_field = None;
self.finish_turn(world); me.finish_turn(world.now());
} }
} }
} }

View file

@ -4,7 +4,6 @@ mod objects;
mod simple_ai; mod simple_ai;
use anyhow::Result; use anyhow::Result;
use assetpath::AssetPath;
use engine::prelude::*; use engine::prelude::*;
use game::MillGame; use game::MillGame;
@ -14,7 +13,10 @@ fn main() -> Result<()> {
create_engine(&mut world_builder)?; create_engine(&mut world_builder)?;
world_builder.add_system(MillGame::update); world_builder.add_system(MillGame::update);
world_builder.build().run() let mut world = world_builder.build();
MillGame::new(&mut world)?;
world.run()
} }
fn create_engine(world_builder: &mut WorldBuilder) -> Result<()> { fn create_engine(world_builder: &mut WorldBuilder) -> Result<()> {
@ -22,10 +24,6 @@ fn create_engine(world_builder: &mut WorldBuilder) -> Result<()> {
create_info.resource_base_path = "resources".to_string(); create_info.resource_base_path = "resources".to_string();
create_info.gui_info.font = Font::Path(AssetPath::from(("resources", "ExportedFont.png")));
create_info.gui_info.resource_directory =
AssetPath::from((create_info.resource_base_path.as_str(), "")).into();
create_info.graphics_info.render_scale = 1.0; create_info.graphics_info.render_scale = 1.0;
create_info.graphics_info.vsync = true; create_info.graphics_info.vsync = true;
create_info.graphics_info.sample_count = VK_SAMPLE_COUNT_4_BIT; create_info.graphics_info.sample_count = VK_SAMPLE_COUNT_4_BIT;
@ -39,7 +37,5 @@ fn create_engine(world_builder: &mut WorldBuilder) -> Result<()> {
create_info.enable_keyboard = true; create_info.enable_keyboard = true;
create_info.enable_mouse = true; create_info.enable_mouse = true;
let engine = Engine::new::<MillGame>(create_info, world_builder)?; Engine::new::<MillGame>(create_info, world_builder)
Ok(())
} }

View file

@ -47,21 +47,17 @@ impl SimpleAI {
(slot.x, slot.y, slot.z) (slot.x, slot.y, slot.z)
}; };
scene.on_scene(|scene| {
if MillGame::place_stone( if MillGame::place_stone(
placable, placable,
(x, y, z), (x, y, z),
board, board,
self.player_color, self.player_color,
scene, world,
state, state,
)? != MillState::None )? != MillState::None
{ {
found_a_mill = true; found_a_mill = true;
} }
Ok(())
})?;
} }
} }
GameState::Removing => { GameState::Removing => {
@ -95,15 +91,9 @@ impl SimpleAI {
MillGame::log("[AI] remove stone", LogSeverity::Debug); MillGame::log("[AI] remove stone", LogSeverity::Debug);
scene.on_scene(|scene| { MillGame::remove_stone(stone, slot, world)?;
MillGame::remove_stone(stone, slot, scene)?;
Ok(())
})?;
} }
GameState::Main => { GameState::Main => loop {
scene.on_scene(|scene| {
loop {
let same_color: Vec<&BoardSlot> = board let same_color: Vec<&BoardSlot> = board
.iter() .iter()
.flatten() .flatten()
@ -124,8 +114,7 @@ impl SimpleAI {
.collect(); .collect();
if !neighbours.is_empty() { if !neighbours.is_empty() {
let neighbour = let neighbour = &neighbours[Random::range(0, neighbours.len() as u32) as usize];
&neighbours[Random::range(0, neighbours.len() as u32) as usize];
if neighbour.state() == BoardSlotState::Empty { if neighbour.state() == BoardSlotState::Empty {
let (x, y, z) = (slot.x, slot.y, slot.z); let (x, y, z) = (slot.x, slot.y, slot.z);
@ -135,13 +124,9 @@ impl SimpleAI {
MillGame::log("[AI] going to make a move", LogSeverity::Debug); MillGame::log("[AI] going to make a move", LogSeverity::Debug);
if let Some(millstate) = MillGame::move_stone( if let Some(millstate) =
(x, y, z), MillGame::move_stone((x, y, z), (tx, ty, tz), world, board, state)?
(tx, ty, tz), {
scene,
board,
state,
)? {
MillGame::log("[AI] successful move", LogSeverity::Debug); MillGame::log("[AI] successful move", LogSeverity::Debug);
if MillState::None != millstate { if MillState::None != millstate {
@ -160,17 +145,13 @@ impl SimpleAI {
} }
} }
} }
} },
Ok(())
})?;
}
GameState::Waiting => unreachable!(), GameState::Waiting => unreachable!(),
GameState::Won(_) => (), GameState::Won(_) => (),
} }
if found_a_mill { if found_a_mill {
self.step(stones, board, scene, state)?; self.step(stones, board, world, state)?;
} }
MillGame::log("finish AI", LogSeverity::Debug); MillGame::log("finish AI", LogSeverity::Debug);