///|
/// Core gameplay contracts only.
/// Ebiten refs:
/// - run.go (Game, Layout, Draw, Update)
/// - gameforui.go (final screen customization)
///|
pub enum EngineTermination {
RegularTermination
Fatal(String)
} derive(Debug)
///|
pub impl Show for EngineTermination with output(self, logger) {
logger.write_object(to_repr(self))
}
///|
pub struct OutsideSize {
width : Double
height : Double
} derive(Debug)
///|
pub impl Show for OutsideSize with output(self, logger) {
logger.write_object(to_repr(self))
}
///|
pub struct LogicalSize {
width : Int
height : Int
} derive(Debug)
///|
pub impl Show for LogicalSize with output(self, logger) {
logger.write_object(to_repr(self))
}
///|
pub struct FrameBudget {
updates : Int
alpha : Double
tick : Int
} derive(Debug)
///|
pub impl Show for FrameBudget with output(self, logger) {
logger.write_object(to_repr(self))
}
///|
pub struct InputSnapshot {
cursor_x : Double
cursor_y : Double
wheel_x : Double
wheel_y : Double
pressed_keys : Array[Int]
pressed_mouse_buttons : Array[Int]
touches : Array[TouchPoint]
gamepads : Array[GamepadSnapshot]
} derive(Debug)
///|
pub impl Show for InputSnapshot with output(self, logger) {
logger.write_object(to_repr(self))
}
///|
pub enum TouchSource {
Direct
Indirect
Mouse
Unknown
} derive(Debug)
///|
pub impl Show for TouchSource with output(self, logger) {
logger.write_object(to_repr(self))
}
///|
pub fn touch_source_to_int(source : TouchSource) -> Int {
match source {
TouchSource::Direct => 0
TouchSource::Indirect => 1
TouchSource::Mouse => 2
TouchSource::Unknown => 3
}
}
///|
pub fn touch_source_from_int(source : Int) -> TouchSource {
match source {
0 => TouchSource::Direct
1 => TouchSource::Indirect
2 => TouchSource::Mouse
_ => TouchSource::Unknown
}
}
///|
pub struct TouchPoint {
id : Int
x : Double
y : Double
source : TouchSource
} derive(Debug)
///|
pub impl Show for TouchPoint with output(self, logger) {
logger.write_object(to_repr(self))
}
///|
pub struct GamepadSnapshot {
id : Int
axes : Array[Double]
pressed_buttons : Array[Int]
} derive(Debug)
///|
pub impl Show for GamepadSnapshot with output(self, logger) {
logger.write_object(to_repr(self))
}
///|
pub struct RunOptions {
init_unfocused : Bool
screen_transparent : Bool
screen_cleared_every_frame : Bool
} derive(Debug)
///|
pub impl Show for RunOptions with output(self, logger) {
logger.write_object(to_repr(self))
}
///|
pub fn new_outside_size(width : Double, height : Double) -> OutsideSize {
{ width, height }
}
///|
pub fn new_frame_budget(
updates : Int,
alpha : Double,
tick : Int,
) -> FrameBudget {
{ updates, alpha, tick }
}
///|
pub fn new_touch_point(id : Int, x : Double, y : Double) -> TouchPoint {
{ id, x, y, source: TouchSource::Unknown }
}
///|
pub fn new_touch_point_with_source(
id : Int,
x : Double,
y : Double,
source : TouchSource,
) -> TouchPoint {
{ id, x, y, source }
}
///|
pub fn new_gamepad_snapshot(
id : Int,
axes : Array[Double],
pressed_buttons : Array[Int],
) -> GamepadSnapshot {
{ id, axes, pressed_buttons }
}
///|
pub fn new_input_snapshot_full(
cursor_x : Double,
cursor_y : Double,
wheel_x : Double,
wheel_y : Double,
pressed_keys : Array[Int],
pressed_mouse_buttons : Array[Int],
touches : Array[TouchPoint],
gamepads : Array[GamepadSnapshot],
) -> InputSnapshot {
{
cursor_x,
cursor_y,
wheel_x,
wheel_y,
pressed_keys,
pressed_mouse_buttons,
touches,
gamepads,
}
}
///|
pub fn new_input_snapshot(
cursor_x : Double,
cursor_y : Double,
wheel_x : Double,
wheel_y : Double,
pressed_keys : Array[Int],
) -> InputSnapshot {
new_input_snapshot_full(
cursor_x,
cursor_y,
wheel_x,
wheel_y,
pressed_keys,
[],
[],
[],
)
}
///|
pub fn empty_input_snapshot() -> InputSnapshot {
new_input_snapshot(0.0, 0.0, 0.0, 0.0, [])
}
///|
pub enum TouchPhase {
Began
Moved
Stationary
Ended
Cancelled
} derive(Debug)
///|
pub impl Show for TouchPhase with output(self, logger) {
logger.write_object(to_repr(self))
}
///|
pub fn touch_phase_to_int(phase : TouchPhase) -> Int {
match phase {
TouchPhase::Began => 0
TouchPhase::Moved => 1
TouchPhase::Stationary => 2
TouchPhase::Ended => 3
TouchPhase::Cancelled => 4
}
}
///|
pub fn touch_phase_from_int(phase : Int) -> TouchPhase {
match phase {
0 => TouchPhase::Began
1 => TouchPhase::Moved
2 => TouchPhase::Stationary
3 => TouchPhase::Ended
4 => TouchPhase::Cancelled
_ => TouchPhase::Began
}
}
///|
pub struct TouchPointEx {
id : Int
x : Double
y : Double
phase : TouchPhase
pressure : Double
delta_x : Double
delta_y : Double
} derive(Debug)
///|
pub impl Show for TouchPointEx with output(self, logger) {
logger.write_object(to_repr(self))
}
///|
pub fn new_touch_point_ex(
id : Int,
x : Double,
y : Double,
phase : TouchPhase,
) -> TouchPointEx {
{ id, x, y, phase, pressure: 1.0, delta_x: 0.0, delta_y: 0.0 }
}
///|
pub fn new_touch_point_ex_full(
id : Int,
x : Double,
y : Double,
phase : TouchPhase,
pressure : Double,
delta_x : Double,
delta_y : Double,
) -> TouchPointEx {
{ id, x, y, phase, pressure, delta_x, delta_y }
}
///|
pub fn touch_point_from_ex(ex : TouchPointEx) -> TouchPoint {
{ id: ex.id, x: ex.x, y: ex.y, source: TouchSource::Unknown }
}
///|
pub trait Game {
/// Ebiten ref: Game.Layout in run.go
layout(Self, outside : OutsideSize) -> LogicalSize
/// Ebiten ref: Game.Update in run.go
update(Self, input : InputSnapshot) -> EngineTermination?
/// Ebiten ref: Game.Draw in run.go
draw(Self, frame : FrameBudget) -> Unit
}
///|
pub trait FinalScreenDrawer {
/// Ebiten ref: FinalScreenDrawer.DrawFinalScreen in run.go/gameforui.go
draw_final_screen(Self, frame : FrameBudget) -> Unit
}
///|
pub struct NoopGame {
logical_width : Int
logical_height : Int
}
///|
pub fn new_noop_game(width : Int, height : Int) -> NoopGame {
{ logical_width: width, logical_height: height }
}
///|
pub impl Game for NoopGame with layout(self, _outside) {
{ width: self.logical_width, height: self.logical_height }
}
///|
pub impl Game for NoopGame with update(_self, _input) {
None
}
///|
pub impl Game for NoopGame with draw(_self, _frame) {
()
}
///|
pub fn default_run_options() -> RunOptions {
new_run_options()
}
///|
pub fn new_run_options(
init_unfocused? : Bool = false,
screen_transparent? : Bool = false,
screen_cleared_every_frame? : Bool = true,
) -> RunOptions {
{ init_unfocused, screen_transparent, screen_cleared_every_frame }
}
///|
pub fn[T : Game] run_game(game : T, options : RunOptions) -> Unit {
let _ = options
let outside = new_outside_size(640.0, 480.0)
let logical = game.layout(outside)
let _ = logical
let _ = game.update(empty_input_snapshot())
game.draw(new_frame_budget(0, 0.0, 0))
}