House radius (12ft diameter -> 6ft radius), button (6in -> 0.5ft), four-ft, eight-ft, twelve-ft radii now computed at compile time from FEET_TO_METERS = 0.3048. Ultraworked + Co-authored-by
124 lines
3.0 KiB
Rust
124 lines
3.0 KiB
Rust
use serde::{Deserialize, Serialize};
|
|
use std::fmt;
|
|
|
|
pub const TICK_RATE_HZ: u16 = 120;
|
|
pub const SAMPLE_RATE_HZ: u16 = 40;
|
|
pub const PHYSICS_DT: f32 = 1.0 / TICK_RATE_HZ as f32;
|
|
pub const FEET_TO_METERS: f32 = 0.3048;
|
|
|
|
pub const STONES_PER_TEAM: u8 = 8;
|
|
pub const ENDS: u8 = 10;
|
|
|
|
// World coordinates in meters, y along sheet toward house.
|
|
pub const SHEET_WIDTH: f32 = 5.0;
|
|
pub const SHEET_LENGTH: f32 = 45.0;
|
|
pub const HOUSE_CENTER: (f32, f32) = (0.0, 38.5);
|
|
pub const HOUSE_RADIUS: f32 = 6.0 * FEET_TO_METERS; // 12 ft diameter → 6 ft radius
|
|
pub const HOG_LINE_Y: f32 = 21.0;
|
|
pub const BACK_LINE_Y: f32 = 42.0;
|
|
pub const HACK_Y: f32 = 2.0;
|
|
|
|
// Stone physical properties
|
|
pub const STONE_RADIUS: f32 = 0.15;
|
|
pub const STONE_MASS: f32 = 20.0;
|
|
pub const STONE_FRICTION: f32 = 0.015;
|
|
pub const STONE_RESTITUTION: f32 = 0.05;
|
|
pub const MIN_SPEED: f32 = 3.0;
|
|
pub const MAX_SPEED: f32 = 6.45;
|
|
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Hash, Default)]
|
|
#[serde(rename_all = "snake_case")]
|
|
pub enum Team {
|
|
#[default]
|
|
Red,
|
|
Yellow,
|
|
}
|
|
|
|
impl Team {
|
|
pub fn other(self) -> Self {
|
|
match self {
|
|
Team::Red => Team::Yellow,
|
|
Team::Yellow => Team::Red,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl fmt::Display for Team {
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
match self {
|
|
Team::Red => write!(f, "red"),
|
|
Team::Yellow => write!(f, "yellow"),
|
|
}
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
#[serde(tag = "type", rename_all = "snake_case")]
|
|
pub enum ClientMessage {
|
|
Throw {
|
|
team: Team,
|
|
broom_x: f32,
|
|
broom_y: f32,
|
|
weight: u8,
|
|
#[serde(default = "default_curl")]
|
|
curl: i8,
|
|
#[serde(default = "default_friction")]
|
|
friction: f32,
|
|
},
|
|
}
|
|
|
|
fn default_curl() -> i8 { 1 }
|
|
fn default_friction() -> f32 { 1.0 }
|
|
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
#[serde(tag = "type", rename_all = "snake_case")]
|
|
pub enum ServerMessage {
|
|
Joined { room: String },
|
|
Waiting { message: String },
|
|
GameState {
|
|
end: u8,
|
|
scores: [i32; 2], // red, yellow
|
|
hammer: Team,
|
|
turn_team: Team,
|
|
stones: Vec<StoneState>,
|
|
phase: Phase,
|
|
},
|
|
Trajectory {
|
|
paths: Vec<StoneTrajectory>,
|
|
},
|
|
EndScored { end: u8, points: i32, scoring_team: Option<Team> },
|
|
GameOver {
|
|
scores: [i32; 2],
|
|
winner: Option<Team>,
|
|
},
|
|
Error { message: String },
|
|
}
|
|
|
|
#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq, Eq)]
|
|
#[serde(rename_all = "snake_case")]
|
|
pub enum Phase {
|
|
#[default]
|
|
Waiting,
|
|
Playing,
|
|
Simulating,
|
|
Scoring,
|
|
EndComplete,
|
|
GameComplete,
|
|
}
|
|
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
pub struct StoneTrajectory {
|
|
pub stone_id: u32,
|
|
pub path: Vec<(f32, f32, f32)>,
|
|
}
|
|
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
pub struct StoneState {
|
|
pub id: u32,
|
|
pub team: Team,
|
|
pub x: f32,
|
|
pub y: f32,
|
|
pub rotation: f32,
|
|
pub active: bool,
|
|
}
|