709 lines
22 KiB
OCaml
709 lines
22 KiB
OCaml
open Graphics ;;
|
|
|
|
Random.self_init () ;;
|
|
|
|
(* use Ctrl+F with 'WALUIGI_TIME' to look for sections *)
|
|
|
|
(* ------------------------------------------------------------------------------------- *)
|
|
(* ------------------------------------------------------------------------------------- *)
|
|
(* WALUIGI_TIME Types + Constants *)
|
|
|
|
exception ReturnBool of bool ;;
|
|
exception ReturnInt of int ;;
|
|
exception HasEnded ;;
|
|
|
|
type pt_2d = {
|
|
mutable x : float ;
|
|
mutable y : float ;
|
|
} ;;
|
|
|
|
type polygon = {
|
|
vertexes : pt_2d array ;
|
|
rgb : int ;
|
|
xmin : float ;
|
|
xmax : float ;
|
|
ymin : float ;
|
|
ymax : float ;
|
|
mutable restitution : float ;
|
|
score : int ;
|
|
} ;;
|
|
|
|
type sphere = {
|
|
center : pt_2d ;
|
|
radius : float ;
|
|
rgb : int ;
|
|
xmin : float ;
|
|
xmax : float ;
|
|
ymin : float ;
|
|
ymax : float ;
|
|
mutable restitution : float ;
|
|
score : int ;
|
|
} ;;
|
|
|
|
type ball = {
|
|
radius : float ;
|
|
mass : float ;
|
|
rgb : int ;
|
|
xy : pt_2d ;
|
|
v : pt_2d ;
|
|
a : pt_2d ;
|
|
fres : pt_2d ;
|
|
} ;;
|
|
|
|
(* --- *)
|
|
|
|
let default_polygon = {
|
|
vertexes = [||] ;
|
|
rgb = 0 ;
|
|
xmin = 1. ;
|
|
xmax = -. 1. ;
|
|
ymin = 1. ;
|
|
ymax = -. 1. ;
|
|
restitution = 0. ;
|
|
score = 0 ;
|
|
} ;;
|
|
|
|
let default_sphere = {
|
|
center = {x = 0. ; y = 0.} ;
|
|
rgb = 0 ;
|
|
radius = -. 1. ;
|
|
xmin = 1. ;
|
|
xmax = -. 1. ;
|
|
ymin = 1. ;
|
|
ymax = -. 1. ;
|
|
restitution = 0. ;
|
|
score = 0 ;
|
|
} ;;
|
|
|
|
let univ_g = 750.0 ;;
|
|
let pi = 3.14159265358979343 ;;
|
|
|
|
let winBL = {
|
|
x = 0. ;
|
|
y = 0. ;
|
|
} ;;
|
|
|
|
let winTR = {
|
|
x = 1200. ;
|
|
y = 800. ;
|
|
}
|
|
|
|
let winball = {
|
|
x = 750. ;
|
|
y = 500. ;
|
|
}
|
|
|
|
let gforce = {x = 0. ; y = -. univ_g} ;;
|
|
|
|
let score = ref 0 ;;
|
|
|
|
(* ------------------------------------------------------------------------------------- *)
|
|
(* ------------------------------------------------------------------------------------- *)
|
|
(* WALUIGI_TIME Threads *)
|
|
|
|
let n_threads = 8 ;;
|
|
|
|
let beep_boop = Array.make n_threads false ;;
|
|
let beep_id = ref 0 ;;
|
|
|
|
let playbeep id =
|
|
while true do
|
|
if beep_boop.(id) then begin
|
|
beep_boop.(id) <- false ;
|
|
ignore (Unix.system "./sound wah/scored_hit.wav") ;
|
|
end;
|
|
Unix.sleepf 0.005 ;
|
|
done;;
|
|
|
|
let beep_list = Array.init n_threads (fun k -> Thread.create playbeep k) ;;
|
|
|
|
(**)
|
|
|
|
let play_music () =
|
|
while true do
|
|
ignore (Unix.system "./sound wah/wah_metal.wav") ;
|
|
ignore (Unix.system "./sound wah/wah_eurobeat.wav") ;
|
|
ignore (Unix.system "./sound wah/wah_hardcore.wav") ;
|
|
done;;
|
|
|
|
let theme_thr = Thread.create play_music () ;;
|
|
|
|
(* ------------------------------------------------------------------------------------- *)
|
|
(* ------------------------------------------------------------------------------------- *)
|
|
(* WALUIGI_TIME Arithmetical operations *)
|
|
|
|
let rec pw x n = match n with
|
|
| 0 -> 1
|
|
| 1 -> x
|
|
| k when k mod 2 = 0 -> pw (x*x) (n/2)
|
|
| k -> x * (pw (x*x) (n/2)) ;;
|
|
|
|
let rec pwf x n = match n with
|
|
| 0 -> 1.
|
|
| 1 -> x
|
|
| k when k mod 2 = 0 -> pwf (x *. x) (n/2)
|
|
| k -> x *. (pwf (x *. x) (n/2)) ;;
|
|
|
|
let rec ln10 n = match n with
|
|
| k when k < 0 -> failwith "Are you sure about that ?"
|
|
| k when k < 10 -> 0
|
|
| k -> 1 + ln10 (k/10) ;;
|
|
|
|
let convexf x y theta =
|
|
(1.0 -. theta) *. x +. theta *. y ;;
|
|
|
|
let absf = function
|
|
| x when x < 0.0 -> -. x
|
|
| x -> x ;;
|
|
|
|
let rec expand_fl = function
|
|
| k when float_of_int (int_of_float k) = k -> int_of_float k
|
|
| k -> expand_fl (10.0 *. k) ;;
|
|
|
|
let incree = function
|
|
| k when k < 10 -> 0
|
|
| _ -> 1 ;;
|
|
|
|
let round x n =
|
|
float_of_int (int_of_float (x *. pwf 10. n)) /. (pwf 10. n);;
|
|
|
|
(* ------------------------------------------------------------------------------------- *)
|
|
(* ------------------------------------------------------------------------------------- *)
|
|
(* WALUIGI_TIME Dynamic Arrays *)
|
|
|
|
type 'a dynamic = {
|
|
mutable len : int ;
|
|
mutable memlen : int ;
|
|
mutable tab : 'a array
|
|
} ;;
|
|
|
|
let dyn_create (elt : 'a) =
|
|
{
|
|
len = 0 ;
|
|
memlen = 16 ;
|
|
tab = Array.make 16 elt
|
|
} ;;
|
|
|
|
let dyn_add (dyn : 'a dynamic) (elt : 'a) =
|
|
if dyn.len = dyn.memlen then begin
|
|
let _new = Array.make (2 * dyn.memlen) dyn.tab.(0) in
|
|
for i = 0 to dyn.memlen -1 do
|
|
_new.(i) <- dyn.tab.(i)
|
|
done;
|
|
dyn.tab <- _new ;
|
|
dyn.memlen <- dyn.memlen * 2 ;
|
|
end;
|
|
dyn.tab.(dyn.len) <- elt ;
|
|
dyn.len <- dyn.len +1 ;;
|
|
|
|
let dyn_remove (dyn : 'a dynamic) (elt : 'a) =
|
|
try
|
|
for i = 0 to dyn.len -1 do
|
|
if dyn.tab.(i) = elt then
|
|
raise (ReturnInt i)
|
|
done;
|
|
raise (ReturnInt (-1))
|
|
with
|
|
| ReturnInt (-1) -> ()
|
|
| ReturnInt k ->
|
|
for i = k to dyn.len -2 do
|
|
dyn.tab.(i) <- dyn.tab.(i+1)
|
|
done;
|
|
dyn.len <- dyn.len -1 ;
|
|
if (dyn.memlen >= 32) && (dyn.len * 4 <= dyn.memlen) then begin
|
|
let _new = Array.make (dyn.memlen/2) dyn.tab.(0) in
|
|
for i = 0 to dyn.len -1 do
|
|
_new.(i) <- dyn.tab.(i)
|
|
done;
|
|
dyn.tab <- _new ;
|
|
dyn.memlen <- dyn.memlen/2 ;
|
|
end ;;
|
|
|
|
let dyn_fold_left (f : 'b -> 'a -> 'b) (acc0 : 'b) (dyn : 'a dynamic) =
|
|
let acc = ref acc0 in
|
|
for i = 0 to dyn.len -1 do
|
|
acc := f !acc dyn.tab.(i)
|
|
done;
|
|
!acc ;;
|
|
|
|
(* ------------------------------------------------------------------------------------- *)
|
|
(* ------------------------------------------------------------------------------------- *)
|
|
(* WALUIGI_TIME Arithmetical operations *)
|
|
|
|
let vect_convexf (px : pt_2d) (py : pt_2d) theta =
|
|
{
|
|
x = convexf px.x py.x theta ;
|
|
y = convexf px.y py.y theta ;
|
|
} ;;
|
|
|
|
|
|
let vect_sum_2D (p1 : pt_2d) (p2 : pt_2d) =
|
|
{
|
|
x = p1.x +. p2.x ;
|
|
y = p1.y +. p2.y ;
|
|
} ;;
|
|
|
|
let vect_diff_2D (p1 : pt_2d) (p2 : pt_2d) =
|
|
{
|
|
x = p1.x -. p2.x ;
|
|
y = p1.y -. p2.y ;
|
|
} ;;
|
|
|
|
let vect_mult_2D (p1 : pt_2d) (lambda : float) =
|
|
{
|
|
x = p1.x *. lambda ;
|
|
y = p1.y *. lambda ;
|
|
} ;;
|
|
|
|
let vect_midpoint_2D (p1 : pt_2d) (p2 : pt_2d) =
|
|
{
|
|
x = (p1.x +. p2.x) /. 2.0 ;
|
|
y = (p1.y +. p2.y) /. 2.0 ;
|
|
} ;;
|
|
|
|
let vect_normal_2D (p1 : pt_2d) (p2 : pt_2d) =
|
|
{
|
|
x = -. (p2.y -. p1.y) ;
|
|
y = (p2.x -. p1.x) ;
|
|
} ;;
|
|
|
|
let return_proj_of_point (m : pt_2d) (spt : pt_2d) (ept : pt_2d) =
|
|
match (-. ((ept.x -. spt.x) *. (spt.x -. m.x) +. (ept.y -. spt.y) *. (spt.y -. m.y)) /. ((ept.x -. spt.x) *. (ept.x -. spt.x) +. (ept.y -. spt.y) *. (ept.y -. spt.y))) with
|
|
| k when k >= 0. && k <= 1. -> (vect_convexf spt ept k)
|
|
| k when k < 0. -> spt
|
|
| k -> ept ;;
|
|
|
|
let return_proj_of_point_D (m : pt_2d) (spt : pt_2d) (ept : pt_2d) =
|
|
let theta = (-. ((ept.x -. spt.x) *. (spt.x -. m.x) +. (ept.y -. spt.y) *. (spt.y -. m.y)) /. ((ept.x -. spt.x) *. (ept.x -. spt.x) +. (ept.y -. spt.y) *. (ept.y -. spt.y))) in
|
|
(vect_convexf spt ept theta) ;;
|
|
|
|
let vect_dot_product_2D (p1 : pt_2d) (p2 : pt_2d) =
|
|
p1.x *. p2.x +. p1.y *. p2.y ;;
|
|
|
|
let vect_norm_2D (p1 : pt_2d) =
|
|
Float.sqrt (vect_dot_product_2D p1 p1) ;;
|
|
|
|
let vect_dist_2D (p1 : pt_2d) (p2 : pt_2d) =
|
|
vect_norm_2D (vect_diff_2D p1 p2) ;;
|
|
|
|
let vect_scale_2D (v1 : pt_2d) (v2 : pt_2d) =
|
|
vect_mult_2D v1 ((vect_norm_2D v2) /. (vect_norm_2D v1)) ;;
|
|
|
|
let vect_normalize_2D (v1 : pt_2d) =
|
|
vect_mult_2D v1 (1.0 /. (vect_norm_2D v1)) ;;
|
|
|
|
let vect_symmetry (m : pt_2d) (p1 : pt_2d) (p2 : pt_2d) =
|
|
let proj = return_proj_of_point_D m p1 p2 in
|
|
let ortho = vect_diff_2D proj m in
|
|
vect_sum_2D (vect_sum_2D ortho ortho) m ;;
|
|
|
|
(* ------------------------------------------------------------------------------------- *)
|
|
(* ------------------------------------------------------------------------------------- *)
|
|
(* WALUIGI_TIME Physics functions *)
|
|
|
|
let step_one_ball (b : ball) (dt : float) =
|
|
{
|
|
x = b.xy.x +. b.v.x *. dt ;
|
|
y = b.xy.y +. b.v.y *. dt ;
|
|
} ;;
|
|
|
|
let is_in_bounding_box_p (b : ball) (poly : polygon) =
|
|
(b.xy.x +. b.radius >= poly.xmin) && (b.xy.x -. b.radius <= poly.xmax) &&
|
|
(b.xy.y +. b.radius >= poly.ymin) && (b.xy.y -. b.radius <= poly.ymax) ;;
|
|
|
|
let is_in_bounding_box_s (b : ball) (s : sphere) =
|
|
(b.xy.x +. b.radius >= s.xmin) && (b.xy.x -. b.radius <= s.xmax) &&
|
|
(b.xy.y +. b.radius >= s.ymin) && (b.xy.y -. b.radius <= s.ymax) ;;
|
|
|
|
let distance_line_segment (m : pt_2d) (spt : pt_2d) (ept : pt_2d) =
|
|
match (-. ((ept.x -. spt.x) *. (spt.x -. m.x) +. (ept.y -. spt.y) *. (spt.y -. m.y)) /. ((ept.x -. spt.x) *. (ept.x -. spt.x) +. (ept.y -. spt.y) *. (ept.y -. spt.y))) with
|
|
| k when k >= 0. && k <= 1. -> vect_dist_2D (vect_convexf spt ept k) m
|
|
| k when k < 0. -> vect_dist_2D spt m
|
|
| k -> vect_dist_2D ept m ;;
|
|
|
|
let is_collision_p (b : ball) (poly : polygon) (dt : float) =
|
|
(* returns the 1st point of the closest line that the ball collides with *)
|
|
if not (is_in_bounding_box_p b poly) then
|
|
(-1)
|
|
else begin
|
|
try
|
|
let mind = ref b.radius
|
|
and minidx = ref (-1) in
|
|
for i = 0 to Array.length poly.vertexes - 1 do
|
|
let dst = (distance_line_segment (step_one_ball b dt) poly.vertexes.(i) poly.vertexes.((i+1) mod Array.length poly.vertexes)) in
|
|
if dst <= !mind then begin
|
|
mind := dst ;
|
|
minidx := i ;
|
|
end
|
|
done;
|
|
raise (ReturnInt (!minidx))
|
|
with
|
|
| ReturnInt b -> b
|
|
end ;;
|
|
|
|
let playbeep () =
|
|
beep_boop.(!beep_id) <- true ;
|
|
beep_id := (!beep_id+1) mod n_threads ;;
|
|
|
|
let is_collision_s (b : ball) (s : sphere) (dt : float) =
|
|
if not (is_in_bounding_box_s b s) then
|
|
false
|
|
else
|
|
vect_dist_2D (step_one_ball b dt) (s.center) <= (s.radius +. b.radius) ;;
|
|
|
|
let update_ball_data (b : ball) (polys : polygon array) (spheres : sphere array) (dt : float) =
|
|
b.fres.x <- 0. ;
|
|
b.fres.y <- 0. ;
|
|
|
|
for p = 0 to (Array.length polys -1) do
|
|
let hit = (is_collision_p b polys.(p) dt) in
|
|
if hit <> -1 then begin
|
|
score := !score + polys.(p).score ;
|
|
|
|
if polys.(p).score > 0 then
|
|
playbeep () ;
|
|
|
|
(* apply normal reaction force *)
|
|
let hit2 = (hit +1) mod (Array.length polys.(p).vertexes) in
|
|
let proj = return_proj_of_point b.xy polys.(p).vertexes.(hit) polys.(p).vertexes.(hit2) in
|
|
let proj_n = vect_normalize_2D (vect_diff_2D b.xy proj) in
|
|
let reaction_force_2 = vect_mult_2D proj_n (univ_g *. b.mass *. (vect_dot_product_2D (vect_normalize_2D gforce) proj_n)) in
|
|
|
|
b.fres.x <- b.fres.x +. reaction_force_2.x *. polys.(p).restitution ;
|
|
b.fres.y <- b.fres.y +. reaction_force_2.y *. polys.(p).restitution ;
|
|
|
|
(* change velocity according to angle *)
|
|
let director = vect_diff_2D polys.(p).vertexes.(hit2) polys.(p).vertexes.(hit) in
|
|
let symmetric = vect_symmetry b.v {x = 0. ; y = 0.} director in
|
|
|
|
b.v.x <- symmetric.x ;
|
|
b.v.y <- symmetric.y ;
|
|
end
|
|
done ;
|
|
|
|
for s = 0 to (Array.length spheres -1) do
|
|
if is_collision_s b spheres.(s) dt then begin
|
|
score := !score + spheres.(s).score ;
|
|
|
|
if spheres.(s).score > 0 then
|
|
playbeep () ;
|
|
|
|
(* apply normal reaction force *)
|
|
let proj_n = vect_normalize_2D (vect_diff_2D b.xy spheres.(s).center) in
|
|
let reaction_force_2 = vect_mult_2D proj_n (univ_g *. b.mass *. (vect_dot_product_2D (vect_normalize_2D gforce) proj_n)) in
|
|
|
|
b.fres.x <- b.fres.x +. reaction_force_2.x *. spheres.(s).restitution ;
|
|
b.fres.y <- b.fres.y +. reaction_force_2.y *. spheres.(s).restitution ;
|
|
|
|
(* change velocity according to angle *)
|
|
let theta = b.radius /. (vect_norm_2D (vect_diff_2D b.xy spheres.(s).center)) in
|
|
let intersection = (vect_convexf b.xy spheres.(s).center theta) in
|
|
let director = vect_normal_2D intersection (vect_sum_2D intersection proj_n) in
|
|
let symmetric = vect_symmetry b.v {x = 0. ; y = 0.} director in
|
|
|
|
b.v.x <- symmetric.x ;
|
|
b.v.y <- symmetric.y ;
|
|
end
|
|
done ;
|
|
|
|
(* P = mg *)
|
|
b.fres.y <- b.fres.y -. univ_g *. b.mass ;
|
|
|
|
(* PFD : ma = sum(F) *)
|
|
b.a.x <- b.fres.x /. b.mass ;
|
|
b.a.y <- b.fres.y /. b.mass ;
|
|
|
|
b.v.x <- b.v.x +. b.a.x *. dt ;
|
|
b.v.y <- b.v.y +. b.a.y *. dt ;
|
|
|
|
b.xy.x <- b.xy.x +. b.v.x *. dt ;
|
|
b.xy.y <- b.xy.y +. b.v.y *. dt ;;
|
|
|
|
let update_balls (bl : ball array) (polys : polygon array) (spheres : sphere array) (dt : float) =
|
|
for b = 0 to Array.length bl -1 do
|
|
update_ball_data bl.(b) polys spheres dt
|
|
done ;;
|
|
|
|
(* ------------------------------------------------------------------------------------- *)
|
|
(* ------------------------------------------------------------------------------------- *)
|
|
(* WALUIGI_TIME Graphics fcts *)
|
|
|
|
let draw_integer x0 y n0 r =
|
|
(* 7-seg display *)
|
|
let n = ref n0 in
|
|
let size = ln10 n0 in
|
|
let len = r/3 in
|
|
let offset = size*(len*11/7)/2 in
|
|
for i = 0 to size do
|
|
let x = x0 + offset - i*(len*11/7) in
|
|
if Array.mem (!n mod 10) [|0; 4; 5; 6; 7; 8; 9|] then
|
|
draw_poly_line [|(x-len/2, y+len); (x-len/2, y)|];
|
|
|
|
if Array.mem (!n mod 10) [|0; 2; 3; 5; 6; 7; 8; 9|] then
|
|
draw_poly_line [|(x-len/2, y+len); (x+len/2, y+len)|];
|
|
|
|
if Array.mem (!n mod 10) [|0; 1; 2; 3; 4; 7; 8; 9|] then
|
|
draw_poly_line [|(x+len/2, y+len); (x+len/2, y)|];
|
|
|
|
if Array.mem (!n mod 10) [|2; 3; 4; 5; 6; 8; 9|] then
|
|
draw_poly_line [|(x-len/2, y); (x+len/2, y)|];
|
|
|
|
if Array.mem (!n mod 10) [|0; 1; 3; 4; 5; 6; 7; 8; 9|] then
|
|
draw_poly_line [|(x+len/2, y-len); (x+len/2, y)|];
|
|
|
|
if Array.mem (!n mod 10) [|0; 2; 3; 5; 6; 8; 9|] then
|
|
draw_poly_line [|(x-len/2, y-len); (x+len/2, y-len)|];
|
|
|
|
if Array.mem (!n mod 10) [|0; 2; 6; 8|] then
|
|
draw_poly_line [|(x-len/2, y-len); (x-len/2, y)|];
|
|
|
|
n := !n/10;
|
|
done ;;
|
|
|
|
let draw_integer_alignedleft x0 y n0 len =
|
|
(* 7-seg display 2 *)
|
|
set_line_width (max 1 (len/4));
|
|
let n = ref n0 in
|
|
let size = ln10 (abs n0) in
|
|
|
|
let cur_x = ref (x0 + size*(len*11/7)) in
|
|
|
|
if !n < 0 then begin
|
|
n := !n * (-1);
|
|
draw_poly_line [|(x0, y); (x0+len, y)|];
|
|
cur_x := !cur_x + (len*11/7)
|
|
end;
|
|
|
|
for i = 0 to size do
|
|
let x = !cur_x in
|
|
if Array.mem (!n mod 10) [|0; 4; 5; 6; 7; 8; 9|] then
|
|
draw_poly_line [|(x, y+len); (x, y)|];
|
|
|
|
if Array.mem (!n mod 10) [|0; 2; 3; 5; 6; 7; 8; 9|] then
|
|
draw_poly_line [|(x, y+len); (x+len, y+len)|];
|
|
|
|
if Array.mem (!n mod 10) [|0; 1; 2; 3; 4; 7; 8; 9|] then
|
|
draw_poly_line [|(x+len, y+len); (x+len, y)|];
|
|
|
|
if Array.mem (!n mod 10) [|2; 3; 4; 5; 6; 8; 9|] then
|
|
draw_poly_line [|(x, y); (x+len, y)|];
|
|
|
|
if Array.mem (!n mod 10) [|0; 1; 3; 4; 5; 6; 7; 8; 9|] then
|
|
draw_poly_line [|(x+len, y-len); (x+len, y)|];
|
|
|
|
if Array.mem (!n mod 10) [|0; 2; 3; 5; 6; 8; 9|] then
|
|
draw_poly_line [|(x, y-len); (x+len, y-len)|];
|
|
|
|
if Array.mem (!n mod 10) [|0; 2; 6; 8|] then
|
|
draw_poly_line [|(x, y-len); (x, y)|];
|
|
|
|
n := !n/10;
|
|
cur_x := !cur_x - (len*11/7);
|
|
done ;;
|
|
|
|
let draw_float x y n0 r =
|
|
let n = absf n0 in
|
|
let ent = int_of_float n in
|
|
let frac = expand_fl (n -. float_of_int ent) in
|
|
draw_integer_alignedleft x y ent r ;
|
|
fill_circle (x + (ln10 ent) * r * 11/7 + 3*r/2) (y - r) 3 ;
|
|
draw_integer_alignedleft (x + 3*r/5 + (ln10 ent + 1)*r*11/7) y ((100 * frac) / (pw 10 (1+ ln10 frac))) r ;;
|
|
|
|
let draw_polygon (poly : polygon) =
|
|
set_color (rgb (poly.rgb mod 256) ((poly.rgb / 256) mod 256) ((poly.rgb / (256*256)) mod 256)) ;
|
|
fill_poly (Array.init (Array.length poly.vertexes) (fun i -> (int_of_float poly.vertexes.(i).x, int_of_float poly.vertexes.(i).y))) ;;
|
|
|
|
let draw_sphere (s : sphere) =
|
|
set_color (rgb (s.rgb mod 256) ((s.rgb / 256) mod 256) ((s.rgb / (256*256)) mod 256)) ;
|
|
fill_circle (int_of_float s.center.x) (int_of_float s.center.y) (int_of_float s.radius) ;;
|
|
|
|
let draw_ball (b : ball) =
|
|
set_color (rgb (b.rgb mod 256) ((b.rgb / 256) mod 256) ((b.rgb / (256*256)) mod 256)) ;
|
|
fill_circle (int_of_float b.xy.x) (int_of_float b.xy.y) (int_of_float b.radius) ;
|
|
set_line_width 4 ;
|
|
draw_circle (int_of_float b.xy.x) (int_of_float b.xy.y) (int_of_float b.radius) ;;
|
|
|
|
let draw_all_balls (bs : ball array) =
|
|
for k = 0 to Array.length bs -1 do
|
|
draw_ball bs.(k)
|
|
done ;;
|
|
|
|
(* ------------------------------------------------------------------------------------- *)
|
|
(* ------------------------------------------------------------------------------------- *)
|
|
(* WALUIGI_TIME Misc fcts *)
|
|
|
|
let get1char_plus () =
|
|
if key_pressed () then
|
|
read_key ()
|
|
else
|
|
'@' ;;
|
|
|
|
let create_ball (r : float) (x0 : int) (y0 : int) (m : float) (red : int) (green : int) (blue : int) =
|
|
{
|
|
radius = r ;
|
|
rgb = red + 256 * green + 256 * 256 * blue ;
|
|
mass = m;
|
|
xy = {x = float_of_int x0 +. (Random.float 10.0 -. 5.0); y = float_of_int y0 +. (Random.float 10.0 -. 5.0)} ;
|
|
v = {x = 0. ; y = 0.} ;
|
|
a = {x = 0. ; y = 0.} ;
|
|
fres = {x = 0. ; y = 0.} ;
|
|
} ;;
|
|
|
|
let create_polygon (arr : (int * int) array) (rest : float) (pts : int) (red : int) (green : int) (blue : int) =
|
|
{
|
|
vertexes = Array.init (Array.length arr) (fun k -> {x = float_of_int (fst arr.(k)); y = float_of_int (snd arr.(k))}) ;
|
|
rgb = red + 256 * green + 256 * 256 * blue ;
|
|
xmin = float_of_int (Array.fold_left (fun acc k -> min acc (fst k)) 99999 arr) ;
|
|
xmax = float_of_int (Array.fold_left (fun acc k -> max acc (fst k)) (-99999) arr) ;
|
|
ymin = float_of_int (Array.fold_left (fun acc k -> min acc (snd k)) 99999 arr) ;
|
|
ymax = float_of_int (Array.fold_left (fun acc k -> max acc (snd k)) (-99999) arr) ;
|
|
restitution = rest ;
|
|
score = pts ;
|
|
} ;;
|
|
|
|
let create_sphere (x00 : int) (y00 : int) (rd : float) (rest : float) (pts : int) (red : int) (green : int) (blue : int) =
|
|
let x0 = float_of_int x00 and y0 = float_of_int y00 in
|
|
{
|
|
center = {x = x0 ; y = y0};
|
|
rgb = red + 256 * green + 256 * 256 * blue ;
|
|
radius = rd ;
|
|
xmin = x0 -. rd ;
|
|
xmax = x0 +. rd ;
|
|
ymin = y0 -. rd ;
|
|
ymax = y0 +. rd ;
|
|
restitution = rest ;
|
|
score = pts ;
|
|
} ;;
|
|
|
|
let generate_pinballs (count : int) (r : float) (x0 : int) (y0 : int) (m : float) (red : int) (green : int) (blue : int) =
|
|
Array.init count (fun k -> create_ball r x0 y0 m red green blue) ;;
|
|
|
|
(* ------------------------------------------------------------------------------------- *)
|
|
(* ------------------------------------------------------------------------------------- *)
|
|
(* WALUIGI_TIME Edition functions *)
|
|
|
|
let customize lvl_name =
|
|
open_graph " 1200x800" ;
|
|
set_window_title "WAH" ;
|
|
|
|
let (res : polygon dynamic) = dyn_create default_polygon in
|
|
let stopped = ref false in
|
|
let refresh = ref true in
|
|
|
|
let (cpoly : pt_2d dynamic) = dyn_create {x = 0. ; y = 0.} in
|
|
|
|
while not !stopped do
|
|
Unix.sleepf 0.005 ;
|
|
|
|
if !refresh then begin
|
|
auto_synchronize false ;
|
|
clear_graph () ;
|
|
refresh := false ;
|
|
for p = 0 to res.len -1 do
|
|
draw_polygon res.tab.(p)
|
|
done;
|
|
auto_synchronize true ;
|
|
end;
|
|
|
|
match (get1char_plus ()) with
|
|
| 'a' -> (* add current polygon *)
|
|
(*Printf.printf "+polygon\n" ;*)
|
|
if cpoly.len >= 2 then begin
|
|
refresh := true ;
|
|
let newVTX = Array.init cpoly.len (fun k -> cpoly.tab.(k)) in
|
|
dyn_add res {
|
|
vertexes = newVTX ;
|
|
rgb = 128 + 255*128 + 255*255*128 ;
|
|
xmin = Array.fold_left (fun acc k -> min acc k.x) (999999.) newVTX ;
|
|
xmax = Array.fold_left (fun acc k -> max acc k.x) (-.999999.) newVTX ;
|
|
ymin = Array.fold_left (fun acc k -> min acc k.y) (999999.) newVTX ;
|
|
ymax = Array.fold_left (fun acc k -> max acc k.y) (-.999999.) newVTX ;
|
|
restitution = 1. ;
|
|
score = 0 ;
|
|
} ;
|
|
cpoly.len <- 0 ;
|
|
end
|
|
| 'v' -> (* add a vertex *)
|
|
(*Printf.printf "+vertex\n" ;*)
|
|
let (mx, my) = mouse_pos () in
|
|
dyn_add cpoly {x = float_of_int mx ; y = float_of_int my} ;
|
|
| 'c' -> (* clear current polygon *)
|
|
(*Printf.printf "cleared\n" ;*)
|
|
cpoly.len <- 0 ;
|
|
| 'h' ->
|
|
stopped := true ;
|
|
| _ -> ()
|
|
done;
|
|
close_graph ();
|
|
res ;;
|
|
|
|
(* ------------------------------------------------------------------------------------- *)
|
|
(* ------------------------------------------------------------------------------------- *)
|
|
(* WALUIGI_TIME Main *)
|
|
|
|
let simulate (data : polygon dynamic) (dats : sphere dynamic) =
|
|
open_graph " 1200x800" ;
|
|
set_window_title "WAH" ;
|
|
|
|
let pinballs = generate_pinballs 3 20.0 600 700 0.15 255 255 0 in
|
|
let stime = Unix.gettimeofday () in
|
|
let ctime = ref (Unix.gettimeofday ()) in
|
|
|
|
while true do
|
|
let __start = Unix.gettimeofday () in
|
|
auto_synchronize false ;
|
|
clear_graph () ;
|
|
|
|
set_line_width 1 ;
|
|
for d = 0 to data.len -1 do
|
|
draw_polygon data.tab.(d)
|
|
done;
|
|
for d = 0 to dats.len -1 do
|
|
draw_sphere dats.tab.(d)
|
|
done;
|
|
draw_all_balls pinballs ;
|
|
|
|
set_color (rgb 128 128 32) ;
|
|
draw_float 25 770 (round (!ctime -. stime) 3) 25 ;
|
|
|
|
set_color black ;
|
|
set_line_width 4 ;
|
|
draw_integer 600 770 !score 50 ;
|
|
|
|
auto_synchronize true ;
|
|
Unix.sleepf 0.005 ;
|
|
|
|
let __end = Unix.gettimeofday () in
|
|
ctime := !ctime +. (__end -. __start) ;
|
|
update_balls pinballs data.tab dats.tab (__end -. __start) ;
|
|
done;
|
|
|
|
close_graph () ;;
|
|
|
|
(*let polygons = customize () ;;*)
|
|
let polygons = dyn_create default_polygon ;;
|
|
dyn_add polygons (create_polygon [|(0, 0); (50, 0); (50, 775); (0, 775)|] 1.0 0 32 32 255) ;;
|
|
dyn_add polygons (create_polygon [|(1150, 0); (1200, 0); (1200, 775); (1150, 775)|] 1.0 0 32 32 255) ;;
|
|
dyn_add polygons (create_polygon [|(50, 0); (50, 200); (500, 25); (500, 0)|] 1.0 0 32 32 255) ;;
|
|
dyn_add polygons (create_polygon [|(1150, 0); (1150, 200); (700, 25); (700, 0)|] 1.0 0 32 32 255) ;;
|
|
dyn_add polygons (create_polygon [|(500, 0); (700, 0); (700, 25); (500, 25)|] 1.0 (-10) 192 64 64) ;;
|
|
dyn_add polygons (create_polygon [|(0, 750); (1200, 750); (1200, 800); (0, 800)|] 1.0 25 64 192 64) ;;
|
|
|
|
let spheres = dyn_create default_sphere ;;
|
|
dyn_add spheres (create_sphere 200 400 20. 1. 5 220 32 220) ;;
|
|
dyn_add spheres (create_sphere 300 200 20. 1. 3 192 0 192) ;;
|
|
dyn_add spheres (create_sphere 400 450 20. 1. 3 192 0 192) ;;
|
|
dyn_add spheres (create_sphere 600 350 20. 1. 10 255 64 255) ;;
|
|
dyn_add spheres (create_sphere 800 450 20. 1. 3 192 0 192) ;;
|
|
dyn_add spheres (create_sphere 900 200 20. 1. 3 192 0 192) ;;
|
|
dyn_add spheres (create_sphere 1000 400 20. 1. 5 220 32 220) ;;
|
|
dyn_add spheres (create_sphere 50 200 15. 1. 20 255 255 32) ;;
|
|
dyn_add spheres (create_sphere 1150 200 15. 1. 20 255 255 32) ;;
|
|
|
|
simulate polygons spheres ;;
|
|
(*
|
|
let create_polygon (arr : (int * int) array) (rest : float) (pts : int) (red : int) (green : int) (blue : int)
|
|
let create_sphere (x00 : int) (y00 : int) (radius : float) (rest : float) (pts : int)
|
|
*)
|
|
|
|
(* ocamlfind ocamlopt -linkpkg -package unix -linkpkg -package graphics -thread -package threads -linkpkg main.ml *) |