-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathroom.ml
141 lines (128 loc) · 5.15 KB
/
room.ml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
open Player
open Enemy
open Item
open Vector
type tile =
| Floor of Animations.image
| Wall of Animations.image
| Exit of Animations.image
| Boundary
type t =
{
seed: int;
player: Player.t;
enemies: Enemy.t list;
items: Item.t list;
tiles: tile array array;
}
type collision = CItem of Item.t | CEnemy of Enemy.t
| CWall of tile | CExit of tile | CPlayer of Player.t
let draw_tile (win : Window.window) (rm : t) (x : int) (y : int) =
let position = (x,y) |> Vector.from_int in
let (x_draw,y_draw) = Vector.center rm.player.e.pos position in
match rm.tiles.(y).(x) with
| Floor (im)
| Wall (im)
| Exit (im) -> Window.draw_image win im x_draw y_draw
| Boundary -> ()
let draw_room (win : Window.window) (rm : t) =
Array.iteri
(fun y row -> Array.iteri (fun x tile -> draw_tile win rm x y) row)
rm.tiles;
ignore
(List.map (fun item -> match item.pos with
|Position _ -> Item.draw win rm.player.e.pos item
|_ -> ()) rm.items);
ignore
(List.map (fun enemy -> Enemy.draw win rm.player.e.pos enemy) rm.enemies);
Array.iteri (fun y row -> Array.iteri (fun x tile ->
match tile with
| Floor _ -> ()
| _ -> draw_tile win rm x y) row) rm.tiles;
Player.draw win rm.player.e.pos rm.player
let get_unused_inventory (rm : t) : int option =
let rec create_list length = function
| t when List.length t < length ->
(create_list (length - 1) []) @ [length - 1]
| t -> t in
let idxs = create_list GameVars.inventory_size [] in
let inventory = List.map (fun i -> match i.pos with
| Inventory {index = idx} -> idx
| _ -> (-1))
rm.items |> List.filter ((<=) 0) in
let unused = List.filter (fun i -> List.mem i inventory |> not) idxs in
let lowest_unused = List.fold_left (fun acc idx -> min acc idx)
(GameVars.inventory_size) unused in
if lowest_unused < GameVars.inventory_size &&
lowest_unused >= 0 then Some lowest_unused
else None
let get_inventory (rm : t) : Item.t list =
List.filter (fun i -> match i.pos with |Inventory _ -> true |_ -> false)
rm.items
|> List.sort (fun i1 i2 ->
match i1.pos with
| Inventory {index = t1 } ->
begin
match i1.pos with
| Inventory {index = t2} ->
t1 - t2
| _ -> failwith "Trying to access non-inventory inventory item"
end
| _ -> failwith "Trying to access non-inventory inventory item"
)
let get_item_slot (rm : t) idx : Item.t option =
List.find_opt (fun i -> match i.pos with
|Inventory {index} when index = idx -> true
| _ -> false) rm.items
(**[scale_pos_pix pos] returns [pos] scaled to units of pixels. *)
let scale_pos_pix pos = pos |> Vector.scale_vec 16. |> Vector.to_int
(** [check_e_collisions e1 e2] is [true] if [e1] and [e2] are colliding and
[false] otherwise.*)
let check_e_collisions (e1: Entity.e) (e2: Entity.e) =
Window.collision
(Vector.add_ints (scale_pos_pix e1.pos) e1.bounding_box_pos) e1.bounding_box
(Vector.add_ints (scale_pos_pix e2.pos) e2.bounding_box_pos) e2.bounding_box
(** [check_wall_collisions e tile,(y,x)] is [true] if [e] and [tile] are
colliding and [false] otherwise.
Requires: (x,y) represents the position of tile [tile].*)
let check_wall_collisions (e:Entity.e) (tile,(y,x)) =
(match tile with
| Floor _-> false
| _-> true ) &&
Window.collision
(16*x + 2,16*y + 2) (12,12)
(Vector.add_ints (scale_pos_pix e.pos) e.bounding_box_pos)
e.bounding_box
(**[generate_tile_with_cords rm lst] returns a list of tuples of the
form [tile, pos] where [tile] is a tile in room [rm] at position
[pos], where [pos] is the corresponding element of [lst].*)
let rec generate_tile_with_cords rm lst = match lst with
| (y,x)::t -> let ar = try rm.tiles.(y).(x),(y,x) with e -> Boundary, (y,x)
in ar :: generate_tile_with_cords rm t
| [] -> []
(** [floor f] is the integer formed by flooring [f]*)
let floor f = Float.floor f |> int_of_float
(** [ciel f] is the integer formed by rounding [f] up*)
let ciel f = Float.ceil f |> int_of_float
let collisions_with_entity rm (e:Entity.e) (ignore : Entity.e) =
let players = List.filter
(fun (player:Player.t) -> check_e_collisions e player.e &&
player.e.pos <> ignore.pos) [rm.player] in
let enemies = List.filter
(fun (enemy:Enemy.t) -> check_e_collisions e enemy.e &&
enemy.e.pos <> ignore.pos) (rm.enemies) in
let items =
List.filter
(fun item -> match item.pos with
| Inventory _ -> false
| _ -> check_e_collisions e item.e && item.e.pos <> ignore.pos)
(rm.items) in
let (x,y) = e.pos in
let tile_array = [(floor y, floor x);(floor y, ciel x); (ciel y, ciel x);
(ciel y, floor x)] |> generate_tile_with_cords rm in
let tiles = List.filter (check_wall_collisions e) tile_array in
(List.map (fun item -> CItem item) items)@
(List.map (fun (tile,(a,b)) ->
match tile with | Exit _ -> CExit tile | _ -> CWall tile) tiles) @
(List.map (fun enemy -> CEnemy enemy) enemies) @
(List.map (fun player -> CPlayer player) players)