I'm working on an open source game for 2 years but I'm very bad at math. The game permits moving a character on an octagonal basis. When the character reaches the border coordinate (colored in yellow), I permit him to travel to another octagon:
The map is a simple 2d array of x, y coordinates. The goal is to know if an x, y tile coordinate is on a "yellow" tile, and which direction it represents (north, northeast, east etc.) depending on map width and height.
I wrote this algorithm many times and in two different language, example with Rust:
pub fn get_corner(width: i16, height: i16, new_row_i: i16, new_col_i: i16) -> Option<CornerEnum> {
let left_col_i_end = width / 3;
let right_col_i_start = (width / 3) * 2;
let top_row_i_end = height / 3;
let bottom_row_i_start = (height / 3) * 2;
let mut more = if new_row_i >= 0 { new_row_i } else { 0 };
#[allow(unused_assignments)]
let mut right_col_i = 0;
#[allow(unused_assignments)]
let mut left_col_i = 0;
if new_row_i < top_row_i_end {
right_col_i = right_col_i_start + more;
left_col_i = left_col_i_end - more;
} else {
if new_row_i >= bottom_row_i_start {
more = (height / 3) - (new_row_i - bottom_row_i_start + 1);
more = if more >= 0 { more } else { 0 };
right_col_i = right_col_i_start + more;
left_col_i = left_col_i_end - more;
} else {
left_col_i = left_col_i_end;
right_col_i = right_col_i_start;
}
}
if new_col_i < left_col_i && new_row_i < top_row_i_end {
return Some(CornerEnum::TopLeft);
}
if new_row_i < 0 && left_col_i <= new_col_i {
return Some(CornerEnum::Top);
}
if new_col_i >= right_col_i && new_row_i < top_row_i_end {
return Some(CornerEnum::TopRight);
}
if new_col_i > width - 1 && top_row_i_end <= new_row_i {
return Some(CornerEnum::Right);
}
if new_col_i >= right_col_i && new_row_i >= bottom_row_i_start {
return Some(CornerEnum::BottomRight);
}
if new_row_i > height - 1 && left_col_i_end <= new_col_i {
return Some(CornerEnum::Bottom);
}
if new_col_i < left_col_i && new_row_i >= bottom_row_i_start {
return Some(CornerEnum::BottomLeft);
}
if new_col_i < 0 && top_row_i_end <= new_row_i {
return Some(CornerEnum::Left);
}
None
}
But it is not working too well: it works only for some borders, but not for others, apparently depending on width/height odd/even... I curse my math. I'm sure it's not that complicated but I've failed for two years. So, I'm here to ask for a solution... which would be greatly appreciated!
