wip: ecs hashtbl; bad
This commit is contained in:
parent
79df19a5fd
commit
764f781289
6 changed files with 103 additions and 101 deletions
16
src/component.ml
Normal file
16
src/component.ml
Normal 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
|
||||||
2
src/dune
2
src/dune
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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 }
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
11
src/map.ml
11
src/map.ml
|
|
@ -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
|
||||||
|
|
|
||||||
115
src/state.ml
115
src/state.ml
|
|
@ -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
|
||||||
|
let x, y =
|
||||||
match dir with
|
match dir with
|
||||||
| Map.Left -> (x - 1, y)
|
| Left -> (x - 1, y)
|
||||||
| Right -> (x + 1, y)
|
| Right -> (x + 1, y)
|
||||||
| Down -> (x, y + 1)
|
| Down -> (x, y + 1)
|
||||||
| Up -> (x, y - 1)
|
| Up -> (x, y - 1)
|
||||||
in
|
in
|
||||||
match Map.get_tile_kind ~x ~y state.map with
|
if not (Map.is_walkable ~x ~y state.map) then Error "invalid terrain"
|
||||||
| Black | Water -> Error "invalid terrain"
|
else if
|
||||||
| Grass ->
|
(* TODO map should know which entity are on which tile *)
|
||||||
if
|
Seq.exists
|
||||||
List.exists
|
(fun (i, j, _d) -> i = x && j = y)
|
||||||
(fun e -> e.Entity.position = state.papy.position)
|
(Hashtbl.to_seq_values state.position_component)
|
||||||
state.entities
|
|
||||||
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
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue