Last active
November 5, 2019 20:10
-
-
Save SeijiEmery/c75b5cb5b9db9ee696bf7b06927f184a to your computer and use it in GitHub Desktop.
Ideas for a high level game lang
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
num is pub type where | |
// static properties (ie. <numtype>.zero, etc) | |
zero: pub value num | |
one: pub value num | |
min: pub value option<num> | |
max: pub value option<num> | |
inf: optional pub value option<num> | |
nan: optional pub value | |
// operator overloads (using one potential syntax: 'op <bin|un> <symbol>') | |
op bin +: pub func (a: Self, b: Self) -> Self | |
op bin -: pub func (a: Self, b: Self) -> Self | |
op bin *: optional pub func (a: Self, b: Self) -> Self | |
op bin /: optional pub func (a: Self, b: Self) -> Self | |
op un -: pub func (a: Self) -> Self | |
// ternary comparison operator (actually num should just be derived from Cmp/Ord..) | |
op cmp: pub func (a: Self, b: Self) -> Cmp | |
// methods... | |
signof: pub method (@self) -> num | |
// type constraints: enforce semantics for all number impls | |
// theoretically could be used on the builtin `num` type to enable compiler optimizations | |
// on numeric operations for user defined numeric types (as this guarantees that the following | |
// are / should be equivalent) | |
requires | |
0 <==> Self.zero | |
1 <==> Self.one | |
2 <==> 1 + 1 | |
_1 <==> 0 - 1 | |
inf <==> Self.inf || Self.nan | |
// trivial axioms | |
0 + 0 == 0 | |
0 + 1 == 1 | |
_1 * 1 == _1 | |
_1 * _1 == 1 | |
// nontrivial axioms | |
forall (a: Self, b: Self) | |
a + b == b + a | |
a + 0 == a | |
a * 1 == a | |
a / 1 == a | |
a / 0 == inf * a.signof | |
if a < 0 then | |
a.signof == _1 | |
else | |
a.signof == 1 | |
if a == 0 or b == 0 then | |
a * b == 0 | |
elif (a < 0 and b < 0) or (a > 0 and b > 0) then | |
a * b > 0 | |
else | |
a * b < 0 | |
// vec3 impl. Notably: | |
// - vec3 is a number | |
// - vec3 takes a type parameter that is a number | |
// | |
vec3 is pub type <T: num = float> deriving num where | |
x: pub rw T | |
y: pub rw T | |
z: pub rw T | |
// define partial properties for num | |
// type parameter T is implicitely available since it was defined above | |
// and is part of any vec3 type instance's type signature | |
vec3.zero is value vec3(0, 0, 0) | |
vec3.one is value vec3(1, 1, 1) | |
vec3.min is value T.min * vec3.one | |
vec3.max is value T.max * vec3.one | |
// more vector properties | |
vec3.fwd is value vec3(1, 0, 0) | |
vec3.back is value vec3.fwd * -1 | |
// alt syntax 1 for defining operators | |
// uses explicit types, stating that a has the same type as b... | |
operator + is pub func <T: num> (a: vec3<T>, b: vec3<T>) -> vec3<T> where | |
vec3(a.x + b.x, a.y + b.y, a.z + b.z) | |
// alt syntax 2 for defining operators | |
// type parameters are implicit, ie assume that | |
// a.typeof == b.typeof == vec3<T> | |
// ie. a.typeof.T == b.typeof.T | |
// | |
vec3.__add__ is func (a: vec3, b: vec3) where | |
vec3(a.x + b.x, a.y + b.y, a.z + b.z) | |
// define a `+=` operator using the above syntax | |
// @self denotes that a parameter 'self' exists and is this method's object instance | |
// returning a parameter (@self) instead of a type signature denotes that | |
// returns a value with that type signature | |
// should literally return that parameter | |
// (hence this has an -implicit- `return self` line at the end of this method) | |
vec3.__adda__ is method (@self: rw vec3, other: vec3) -> @self where | |
self.x += other.x | |
self.y += other.y | |
self.z += other.z | |
// states that MouseEvent is an event, and that it's a union of other events | |
// more or less equivalent to saying that | |
// newtype MouseEvent = MouseMoveEvent | MousePressEvent | MouseScrollEvent | |
// in other languages | |
// written using only whitespace b/c | |
// - we can just define a new language block (ie. `event type`) w/ its own syntax + semantics | |
// - whitespace only is a lot cleaner | |
// | |
MouseEvent is event type of | |
MouseMoveEvent | |
MousePressEvent | |
MouseScrollEvent | |
MouseKeyboardInputEvent is event type of | |
MouseEvent | |
KeyboardEvent | |
WindowManagerEvent is event type of | |
MouseKeyboardInputEvent | |
GamepadInputEvent | |
GamepadConnectionEvent | |
WindowMoveEvent | |
WindowChangeEvent | |
// events are normally defined concretely like this (note the type of this is just `event`) | |
MouseMoveEvent is event where | |
pos: vec2 | |
delta: vec2 | |
MouseButton is enum type of | |
Left | |
Right | |
Middle | |
MousePressEvent is event where | |
button: MouseButton | |
// ECS implementation!!!! :D | |
// (this is the real reason to have a custom language) | |
PositionComponent is component of vec3 | |
VelocityComponent is component of vec3 | |
PlayerInputComponent is component where | |
state: PlayerInputState where | |
move: vec2 | |
jump: bool | |
movespeed: num | |
jumpspeed: num | |
GravityComponent is component where | |
gravity: num = GravityInstance.gravity | |
gravityDir: rot = GravityInstance.gravityDir | |
terminalVel: num = GravityInstance.terminalVel | |
TimeInstance is dataparam where | |
time: Time | |
dt: Time | |
MovementSystem is systemtype (exclusive) | |
PhysicsAffector is systemtype | |
requires | |
runafter MovementSystem | |
runbefore PhysicsSystem | |
PhysicsSystem is systemtype (exclusive) | |
PlayerMovementSystem is system deriving MovementSystem of | |
player: readonly PlayerInputComponent | |
velocity: rw VelocityComponent | |
time: read TimeInstance | |
with | |
dt = time.dt.seconds | |
where | |
velocity.x += dt * player.state.move.x * player.movespeed | |
if player.state.jump | |
velocity.y = player.jumpspeed | |
GravitySystem is system deriving PhysicsAffector of | |
gravity: GravityComponent | |
velocity: rw VelocityComponent | |
time: TimeInstance | |
where | |
// split into two vector components: | |
// vcomponent = vector component along gravityDir | |
// vortho = vector component perpendicular / orthogonal to gravityDir | |
// we have a high level language so obviously we can just write a high level fcn on vec3 to express this | |
let vcomponent, vortho = velocity.splitcomponents(gravity.gravityDir) | |
let speed = vcomponent.magnitude | |
speed += Time.dt.seconds * gravity.gravity | |
speed = min(speed, gravity.terminalVel) | |
vcomponent = gravity.gravityDir * speed | |
velocity = vcomponent + vortho | |
requires | |
runafter MovementSystem |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment