wip: ecs hashtbl; bad

This commit is contained in:
Swrup 2022-12-30 22:21:59 +01:00
parent 79df19a5fd
commit 764f781289
6 changed files with 103 additions and 101 deletions

16
src/component.ml Normal file
View file

@ -0,0 +1,16 @@
type dir =
| Left
| Right
| Down
| Up
type mana = int
type position = int * int * dir
type image = Entity.archetype
type t =
| Image of image
| Position of position
| Mana of mana

View file

@ -45,7 +45,7 @@
(library (library
(name shared) (name shared)
(modules entity map network state) (modules component entity map network state)
(libraries uuidm)) (libraries uuidm))
(rule (rule

View file

@ -1,24 +1,13 @@
type kind = type archetype =
| Papy | Papy
| Tree0 | Tree0
| Tree1 | Tree1
| Wheat | Wheat
type dir = (*
| Left TODO
| Right type 'archetype t = Uuidm.t
| Down *)
| Up
type position = int * int * dir (* TODO just use int ?*)
type t = Uuidm.t
type t =
{ kind : kind
; id : Uuidm.t
; position : position
; mana : int
}
let set_pos v e = { e with position = v }
let set_mana v e = { e with mana = v }

View file

@ -57,25 +57,6 @@ let tree1 = C2d.image_src_of_el (get_el "tree1")
let wheat = C2d.image_src_of_el (get_el "wheat") let wheat = C2d.image_src_of_el (get_el "wheat")
(* TODO FIX *)
let draw_entity context entity =
let e_x, e_y, e_dir = entity.Entity.position in
let tile_x = float_of_int ((e_x * tile_size) + orig_x) in
let tile_y = float_of_int ((e_y * tile_size) + orig_y) in
let img =
match entity.kind with
| Papy -> (
match e_dir with
| Left -> papy_left
| Right -> papy_right
| Down -> papy_down
| Up -> papy_up )
| Tree0 -> tree0
| Tree1 -> tree1
| Wheat -> wheat
in
C2d.draw_image context img ~x:tile_x ~y:tile_y
let draw = let draw =
let papy_x = float_of_int (width - tile_size) /. 2. in let papy_x = float_of_int (width - tile_size) /. 2. in
let papy_y = (float_of_int height /. 2.) -. (float_of_int tile_size *. 1.5) in let papy_y = (float_of_int height /. 2.) -. (float_of_int tile_size *. 1.5) in

View file

@ -1,11 +1,3 @@
type dir = Entity.dir =
| Left
| Right
| Down
| Up
type position = int * int * dir
type background = type background =
| Grass | Grass
| Water | Water
@ -29,3 +21,6 @@ let init () =
let get_tile_kind ~x ~y map = let get_tile_kind ~x ~y map =
try map.tiles.(x).(y) with Invalid_argument _ -> Black try map.tiles.(x).(y) with Invalid_argument _ -> Black
let is_walkable ~x ~y map =
match get_tile_kind ~x ~y map with Water | Black -> false | Grass -> true

View file

@ -1,83 +1,104 @@
type t =
{ map : Map.t
; papy : Entity.t
; entities : Entity.t list
}
let random_state = Random.State.make_self_init () let random_state = Random.State.make_self_init ()
type t =
{ map : Map.t
; mana_component : (Entity.t, Component.mana) Hashtbl.t
; position_component : (Entity.t, Component.position) Hashtbl.t
; image_component : (Entity.t, Component.image) Hashtbl.t
; papy : Entity.t
}
let add_component state entity components =
match components with
| Component.Image image -> Hashtbl.replace state.image_component entity image
| Position position ->
Hashtbl.replace state.position_component entity position
| Mana mana -> Hashtbl.replace state.mana_component entity mana
let make_entity state components =
let entity = Uuidm.v4_gen random_state () in
List.iter (add_component state entity) components;
entity
let init () = let init () =
let map = Map.init () in let state =
let papy = { map = Map.init ()
Entity. ; mana_component = Hashtbl.create 1
{ kind = Papy ; position_component = Hashtbl.create 1
; id = Uuidm.v4_gen random_state () ; image_component = Hashtbl.create 1
; position = (20, 3, Down) ; papy = Uuidm.v4_gen random_state ()
; mana = 0 }
}
in in
(* finish papy *)
List.iter
(add_component state state.papy)
Component.[ Position (20, 3, Down); Mana 13; Image Entity.Papy ];
(* add trees *) (* add trees *)
let tree_kind = if Random.bool () then Entity.Tree0 else Entity.Tree1 in let tree_kind = if Random.bool () then Entity.Tree0 else Entity.Tree1 in
let entities = let n = 5 * (state.map.width * state.map.height / 100) in
let n = 5 * (map.width * map.height / 100) in let xs = List.init n (fun _i -> Random.int state.map.width) in
let ws = List.init n (fun _i -> Random.int map.width) in let ys = List.init n (fun _i -> Random.int state.map.height) in
let hs = List.init n (fun _i -> Random.int map.height) in let _entities : Entity.t list =
List.combine ws hs List.combine xs ys
|> List.filter (fun (x, y) -> |> List.filter (fun (x, y) -> Map.is_walkable ~x ~y state.map)
match Map.get_tile_kind ~x ~y map with
| Water | Black -> false
| Grass -> true )
|> List.map (fun (x, y) -> |> List.map (fun (x, y) ->
Entity. make_entity state
{ kind = tree_kind Component.[ Position (x, y, Up); Mana 0; Image tree_kind ] )
; id = Uuidm.v4_gen random_state ()
; position = (x, y, Up)
; mana = 0
} )
in in
{ map; papy; entities } state
type action = type action =
| Meditate | Meditate
(* TODO some action do not needs to be checked by server *) (* TODO some action do not needs to be checked by server *)
| Move of Map.dir | Move of Component.dir
(* type for result of action send to the client by the server *) (* type for result of action send to the client by the server *)
type action' = type action' =
| Add_mana of int | Add_mana of Entity.t * int
| Set_player_position of Map.position | Set_player_position of Component.position
let check_papy_move state dir = let check_papy_move state dir =
let x, y, current_dir = state.papy.position in match Hashtbl.find_opt state.position_component state.papy with
let x, y = | None -> failwith "couldn't find position component for papy"
if current_dir <> dir then (x, y) | Some (x, y, current_dir) ->
if current_dir <> dir then Ok (x, y, dir)
else else
match dir with let x, y =
| Map.Left -> (x - 1, y) match dir with
| Right -> (x + 1, y) | Left -> (x - 1, y)
| Down -> (x, y + 1) | Right -> (x + 1, y)
| Up -> (x, y - 1) | Down -> (x, y + 1)
in | Up -> (x, y - 1)
match Map.get_tile_kind ~x ~y state.map with in
| Black | Water -> Error "invalid terrain" if not (Map.is_walkable ~x ~y state.map) then Error "invalid terrain"
| Grass -> else if
if (* TODO map should know which entity are on which tile *)
List.exists Seq.exists
(fun e -> e.Entity.position = state.papy.position) (fun (i, j, _d) -> i = x && j = y)
state.entities (Hashtbl.to_seq_values state.position_component)
then Error "invalid move, space is occupied" then Error "invalid move, space is occupied"
else Ok (x, y, dir) else Ok (x, y, dir)
let check_action state = function let check_action state = function
| Meditate -> | Meditate ->
if state.papy.mana < 99 then Ok (Add_mana 1) else Error "maximum mana" let mana =
match Hashtbl.find_opt state.mana_component state.papy with
| None -> failwith "no mana component for papy"
| Some mana -> mana
in
if mana < 99 then Ok (Add_mana (state.papy, 1)) else Error "maximum mana"
| Move dir -> ( | Move dir -> (
match check_papy_move state dir with match check_papy_move state dir with
| Error _e as error -> error | Error _e as error -> error
| Ok pos -> Ok (Set_player_position pos) ) | Ok pos -> Ok (Set_player_position pos) )
let perform_action state = function let perform_action state = function
| Add_mana n -> | Add_mana (entity, n) ->
{ state with papy = Entity.set_mana (state.papy.mana + n) state.papy } let mana =
match Hashtbl.find_opt state.mana_component state.papy with
| None -> failwith "no mana component for entity"
| Some mana -> mana
in
Hashtbl.replace state.mana_component entity (mana + n)
| Set_player_position pos -> | Set_player_position pos ->
{ state with papy = Entity.set_pos pos state.papy } Hashtbl.replace state.position_component state.papy pos