39
loading...
This website collects cookies to deliver better user experience
opam install drom
drom new my_program --skeleton program
drom project
drom run
module Position = struct
type s = {
x: int;
y: int
}
include(val (Component.create ()): Component.Sig with type t = s)
end;;
module Sprite = struct
type s = Raylib.Texture2D.t' Raylib.ctyp
let load path = (
let tex = Raylib.load_texture path in
Gc.finalise Raylib.unload_texture tex;
tex
)
include(val (Component.create ()): Component.Sig with type t = s)
end;;
module type Sig = sig
type t
val set: t -> key -> key
val s: t -> key -> key
val fold: (key -> t -> 'a -> 'a) -> 'a -> 'a
val iter: (key -> t -> unit) -> unit
val get: key -> t
val get_opt: key -> t option
val remove: key-> unit
end;;
module Rendering = struct
let on_process _key (pos: Position.t) spr =
Raylib.draw_texture spr pos.x pos.y Raylib.Color.white
include (val (System2R.create on_process Position.iter Sprite.get_opt))
end;;
module Commands = struct
type command =
| GoUp
| GoDown
| GoLeft
| GoRight
| Attack
end;;
module Input = InputFrom(Commands)
module InputHandling = struct
let on_input cmd (pos: Position.t) =
let x_size = 128 in
let y_size = 60 in
match cmd with
| Commands.GoDown -> {pos with y=(Stdlib.min (pos.y + y_size) ((2 * y_size)))}
| Commands.GoUp -> {pos with y=(Stdlib.max (pos.y - y_size) 0)}
| Commands.GoLeft -> {pos with x=(Stdlib.max (pos.x - x_size) 32)}
| Commands.GoRight -> {pos with x=(Stdlib.min (pos.x + x_size) ((2 * x_size)+32)) }
| Attack -> let key = Entity.by_name "Enemy" in Health.set ( (Health.get key) - 1 ) key|> ignore; pos
let on_process key pos inp =
Array.iter (
fun (kb_key, cmd) ->
if Raylib.is_key_pressed kb_key then
Position.set (on_input cmd pos) key |> ignore
else ()
)
inp
include (val (System2R.create on_process Position.iter Input.get_opt ))
end;;
Entity.by_name "Player"
|> Position.s {x=32;y=0}
|> Sprite.s (Sprite.load "assets/player.png")
|> Health.s 100
|> Script.s (can_die)
|> Input.s [|
(Raylib.Key.Up, Commands.GoUp);
(Raylib.Key.Down, Commands.GoDown);
(Raylib.Key.Left, Commands.GoLeft);
(Raylib.Key.Right, Commands.GoRight);
(Raylib.Key.Space, Commands.Attack);
|] |> ignore;
Input.s
is an array of tuples with a key and what command does it execute. About the rest of the syntax we'll talk more about it in a minute.InputHandling
system we could say the we needed another component which registered this entity as a player, for example).Entity.by_name "Enemy"
|> Position.s {x=32+384;y=0}
|> Sprite.s (Sprite.load "assets/enemy.png")
|> Health.s 10
|> Enemy.s ()
|> Script.s (can_die)
|> ignore;
Component.s
is nothing more than a shortcut to set and that it returns the ID to be used again later (that's why we need the ignore) the Script
part may be weird to you.Script
a Component
which will trigger a function each frame (most probably it can improved and filtered for performance) but for the time being it proved a great addition (which was even better thanks to OCaml partial application).engine.ml
the whole project needed to be recompiled so that the new definitions were available to marlin for main.ml
, not just that but at first it seems that drom kinda mixed versions and got a nasty error saying that I was using OCaml "4.10" while the version the tools expected was "4.11", I had to clear all caches and packages storages so and upgrade to "4.11" in the project files (just upgrading the version in the files wasn't enough). This is isn't my first time dabbling with OCaml either, and everytime I come seems like something new pops up (either that I have forgotten the kinda complicated set of instructions that I need to do).;;
and sometimes it seems it is not needed, though that is good, actually).Component
and a System
just for that, at that time I understood that trying to shove everything inside the ECS is going to make your code verbose as hell and you may end with several times the number of lines you might had otherwise.Script
Component as an escape hatch, and honestly it felt 😀️ good. OCaml's partially applied functions really helped too. Honestly, I can see this design getting some sugar and being used more.Input
, while still verbose feels pretty good, the Command
idea taken from FRP and Elm is a great way of abstracting input hardware.World
and passing that down on all functions for them to do wathever they feel like, something like what the Nu game engine does.39