-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathjsapp.ml
167 lines (149 loc) · 4.79 KB
/
jsapp.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
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
open Bulletml.Syntax
open Bulletml.Interp
open Bulletml.Interp_types
let stop = ref false
let bml = ref ((*{{{*)
BulletML (Some Horizontal, [EAction ("top", [Repeat (Num 20.,Direct ([Fire (Direct ((Some (DirAim (((Num 0. -@ Num 60.) +@ (Rand *@ Num 120.)))), None, Indirect ("hmgLsr", [])))); Repeat (Num 8.,Direct ([Wait (Num 1.); Fire (Direct ((Some (DirSeq (Num 0.)), None, Indirect ("hmgLsr", []))))])); Wait (Num 10.)])); Wait (Num 60.)]); EBullet ("hmgLsr",Bullet (None,Some (SpdAbs (Num 2.)),[Direct ([ChangeSpeed (SpdAbs (Num 0.3),Num 30.); Wait (Num 100.); ChangeSpeed (SpdAbs (Num 5.),Num 100.)]); Direct ([Repeat (Num 12.,Direct ([ChangeDirection (DirAim (Num 0.),(Num 45. -@ (Rank *@ Num 30.))); Wait (Num 5.)]))])]))]))
(*}}}*)
let screen_w = 400
let screen_h = 300
let enemy_pos = (200., 100.)
let ship_pos = ref (200., 250.)
let params =
{ p_screen_w = screen_w
; p_screen_h = screen_h
; p_enemy = enemy_pos
; p_ship = !ship_pos
; p_rank = 0.5
}
let mouse_handler c e =
let get_hard z = Js.Optdef.get z (fun () -> assert false) in
let px = get_hard (e##.pageX) in
let py = get_hard (e##.pageY) in
let x = px - c##.offsetLeft in
let y = py - c##.offsetTop in
ship_pos := (float x, float y);
Js._true
let create_canvas () =
let c = Dom_html.createCanvas Dom_html.document in
c##.width := screen_w;
c##.height := screen_h;
c##.onmousemove := Dom_html.handler (mouse_handler c);
c
let draw_px ~color ctx data i j =
let (r, g, b) = color in
let p = 4 * (j * screen_w + i) in
Dom_html.pixel_set data (p+0) r;
Dom_html.pixel_set data (p+1) g;
Dom_html.pixel_set data (p+2) b;
Dom_html.pixel_set data (p+3) 255;
()
(* A clearRect would be better but it does not work *)
let clear (ctx, img) =
let data = img##.data in
let color = (0xff, 0xff, 0xff) in
for i = 0 to screen_w do
for j = 0 to screen_h do
draw_px ~color ctx data i j
done
done
let in_bounds x y =
0 <= x && x < screen_w && 0 <= y && y < screen_h
let draw_bullet ?(color=(0xfa, 0x69, 0x00)) ctx img x y =
let data = img##.data in
let i0 = int_of_float x in
let j0 = int_of_float y in
let pix =
[ -2, 0 ; -2, 1 ; -2, 2 ; -2, -1
; -1, 0 ; -1, 1 ; -1, 2 ; -1, 3
; -1, -1 ; -1, -2 ; 0, 0 ; 0, 1
; 0, 2 ; 0, 3 ; 0, -1 ; 0, -2
; 1, 0 ; 1, 1 ; 1, 2 ; 1, 3
; 1, -1 ; 1, -2 ; 2, 0 ; 2, 1
; 2, 2 ; 2, 3 ; 2, -1 ; 2, -2
; 3, 0 ; 3, 1 ; 3, 2 ; 3, -1
]
in
List.iter (fun (i, j) ->
let x = i0 + i in
let y = j0 + j in
if in_bounds x y then
draw_px ~color ctx data x y
) pix
let draw (ctx, img) root =
let objs =
List.filter
(fun o -> not o.vanished)
(collect_obj root)
in
let r = ref 0 in
List.iter (fun o -> let (x, y) = o.pos in draw_bullet ctx img x y;incr r) objs;
!r
let draw_ship (ctx, img) =
let color = (0x69, 0xD2, 0xE7) in
let (x, y) = !ship_pos in
draw_bullet ~color ctx img x y
let draw_msg ctx msg =
ctx##fillText (Js.string msg) 0. 10.
let reload elem =
let s = Js.to_string elem##.value in
bml := Bulletml.Parser.parse_pat_string s;
stop := true
let setup_textarea elem =
elem##.onkeyup := Dom_html.handler (fun e ->
let cb = Js.wrap_callback (fun () -> reload elem) in
let _ = Dom_html.window##setTimeout cb 10. in
Js._true
)
let iter_nl f nl =
let n = nl##.length in
for i = 0 to n - 1 do
Js.Opt.iter (nl##item(i)) f
done
let setup_demos ta =
let demos = Dom_html.document##querySelectorAll(Js.string".demo") in
iter_nl (fun e ->
e##.onclick := Dom_html.handler (fun _ ->
let cont = e##.innerHTML in
ta##.innerHTML := cont;
reload ta;
Js._true
)
) demos
let _ =
let open Lwt in
let canvas = create_canvas () in
let doc = Dom_html.document in
let textarea = Dom_html.createTextarea doc in
Js.Opt.iter (doc##querySelector(Js.string"#shmup")) (fun e ->
Dom.appendChild e canvas;
Dom.appendChild e textarea;
);
setup_textarea textarea;
setup_demos textarea;
let (global_env, obj0, _top) = prepare (!bml) params () in
canvas##.onclick := Dom_html.handler (fun e -> stop := true ; Js._true);
let rec go frame obj () =
let env =
{ global_env with
frame = frame
; ship_pos = !ship_pos
}
in
let ctx = canvas##getContext (Dom_html._2d_) in
let img = ctx##getImageData 0. 0. (float screen_w) (float screen_h) in
clear (ctx, img);
let perf = draw (ctx, img) obj in
draw_ship (ctx, img);
ctx##putImageData img 0. 0.;
draw_msg ctx (string_of_int perf ^ " bullets");
let k = if !stop then begin
stop := false;
let (_, o, _) = prepare (!bml) params () in
go 1 o
end else
go (frame + 1) (animate env obj)
in
Lwt_js.yield () >>= k
in
go 1 obj0 ()