This repository has been archived by the owner on Sep 18, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcamlbrick.ml
1107 lines (932 loc) · 31.6 KB
/
camlbrick.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
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
(**
Ce module CamlBrick représente le noyau fonctionnel du jeu de casse-brique.
Le noyau fonctionnel consiste à réaliser l'ensemble des structures et autres fonctions capables d'être utilisées par une interface graphique.
Par conséquent, dans ce module il n'y a aucun aspect visuel.
Vous pouvez cependant utiliser le mode console.
Le principe du jeu de casse-brique consiste à faire disparaître toutes les briques d'un niveau en utilisant les rebonds d'une balle depuis une raquette contrôlée par l'utilisateur.
@author Max Charrier
@author Paul Ourliac
@author Matéo Abrane
@author Axel De Les Champs--Vieira
@version 1
*)
(**
Compteur utilisé en interne pour afficher le numéro de la frame du jeu vidéo.
A utiliser uniquement en lecture.
NE PAS MODIFIER SA VALEUR !
@deprecated Ne pas modifier cette valuer !
*)
let frames = ref 0;;
(**
Attributs globaux pour paramétrer le casse-brique
<b>Attention:</b> Il doit y avoir des cohérences entre les différents paramètres:
<ul>
<li>la hauteur totale de la fenêtre est égale à la somme des hauteurs de la zone de briques du monde et de la hauteur de la zone libre.</li>
<li>la hauteur de la zone des briques du monde est un multiple de la hauteur d'une seule brique.</li>
<li>la largeur du monde est un multiple de la largeur d'une seule brique.</li>
<li>initialement la largeur de la raquette doit correspondre à la taille moyenne.</li>
<li>la hauteur initiale de la raquette doit être raisonnable et ne pas toucher un bord de la fenêtre.</li>
<li>La variable <u>time_speed</u> doit être strictement positive, elle représente l'écoulement du temps.</li>
</ul>
*)
type t_camlbrick_param = {
world_width : int; (** largeur de la zone de dessin des briques *)
world_bricks_height : int; (** hauteur de la zone de dessin des briques *)
world_empty_height : int; (** hauteur de la zone vide pour que la bille puisse évoluer un petit peu *)
brick_width : int; (** largeur d'une brique *)
brick_height : int; (** hauteur d'une brique *)
paddle_init_width : int; (** largeur initiale de la raquette *)
paddle_init_height : int; (** hauteur initiale de la raquette *)
time_speed : int ref; (** indique l'écoulement du temps en millisecondes (c'est une durée approximative) *)
};;
(**
Représentation des différents états du jeu.
Les trois états de base sont :
<ul>
<li>[GAMEOVER]: qui indique si une partie est finie typiquement lors du lancement du jeu</li>
<li>[PLAYING]: qui indique qu'une partie est en cours d'exécution</li>
<li>[PAUSING]: indique qu'une partie en cours d'exécution est actuellement en pause</li>
</ul>
Dans le cadre des extensions, possibilité de modifier ce type pour adopter d'autres états du jeu selon le besoin.
*)
type t_gamestate = GAMEOVER | PLAYING | PAUSING;;
(**
Représentation des différentes couleurs prise en charge par notre moteur de jeu.
NE PAS MODIFIER CE TYPE !
@deprecated Ne pas modifier ce type !
*)
type t_camlbrick_color = WHITE | BLACK | GRAY | LIGHTGRAY | DARKGRAY | BLUE | RED | GREEN | YELLOW | CYAN | MAGENTA | ORANGE | LIME | PURPLE;;
(**
Représentation des différents types de briques.
NE PAS MODIFIER CE TYPE !
@deprecated Ne pas modifier ce type !
*)
type t_brick_kind = BK_empty | BK_simple | BK_double | BK_block | BK_bonus;;
(**
Retourne le type de brique pour représenter les briques de vide.
C'est à dire, l'information qui encode l'absence de brique à un emplacement sur la grille du monde.
@return Renvoie le type correspondant à la notion de vide.
@deprecated Cette fonction est utilisé en interne.
*)
let make_empty_brick () : t_brick_kind =
BK_empty
;;
(**
Représeantion des différentes tailles des billes.
La taille par défaut d'une bille est [BS_MEDIUM].
Possibilité d'ajouter d'autres valeurs sans modifier les valeurs existantes.
*)
type t_ball_size = BS_SMALL | BS_MEDIUM | BS_BIG;;
(**
Représenation des différentes taille de la raquette.
La taille par défaut d'une raquette est [PS_SMALL].
Possibilité d'ajouter d'autres valeurs sans modifier les valeurs existantes.
*)
type t_paddle_size = PS_SMALL | PS_MEDIUM | PS_BIG;;
(**
Définition des composantes d'un vecteur.
*)
type t_vec2 = {
x : int;
y : int
};;
(**
Création un vecteur 2D à partir de deux entiers.
Les entiers représentent la composante en X et en Y du vecteur.
@author Paul Ourliac
@param x première composante du vecteur
@param y seconde composante du vecteur
@return vecteur dont les composantes sont (x,y).
*)
let make_vec2 (x, y : int * int) : t_vec2 =
{
x = x;
y = y
}
;;
(**
Somme des composantes de deux vecteurs.
@author Paul Ourliac
@param a premier vecteur
@param b second vecteur
@return vecteur égale à la somme des vecteurs.
*)
let vec2_add (a, b : t_vec2 * t_vec2) : t_vec2 =
{
x = a.x + b.x;
y = a.y + b.y
}
;;
(**
Somme des composantes d'un vecteur et d'un vecteur construit à partir de (x,y).
Il s'agit d'une optimisation du code suivant :
{[
let vec2_add_scalar (a, x, y : t_vec2 * int * int) : t_vec2 =
vec2_add (a, make_vec2 (x, y))
;;
]}
@author Paul Ourliac
@param a premier vecteur
@param x composante en x du second vecteur
@param y composante en y du second vecteur
@return vecteur égale à la somme du vecteur et du vecteur construit.
*)
let vec2_add_scalar (a, x, y : t_vec2 * int * int) : t_vec2 =
{
x = a.x + x;
y = a.y + y
}
;;
(**
Multiplication des composantes de deux vecteurs.
@author Max Charrier
@param a premier vecteur
@param b second vecteur
@return vecteur égale à la multiplication des vecteurs.
*)
let vec2_mult (a, b : t_vec2 * t_vec2) : t_vec2 =
{
x = a.x * b.x;
y = a.y * b.y
}
;;
(**
Multiplication des composantes d'un vecteur et d'un vecteur construit à partir de (x,y).
Il s'agit d'une optimisation du code suivant :
{[
let vec2_mult_scalar (a, x, y : t_vec2 * int * int) : t_vec2 =
vec2_mult (a, make_vec2 (x, y))
;;
]}
@author Max Charrier
@param a premier vecteur
@param x composante en x du second vecteur
@param y composante en y du second vecteur
@return vecteur égale à la multiplication du vecteur et du vecteur construit.
*)
let vec2_mult_scalar (a, x, y : t_vec2 * int * int) : t_vec2 =
{
x = a.x * x;
y = a.y * y
}
;;
(**
Définition de la balle par sa position, son vecteur vitesse et sa taille.
D'un point de vue de l'affichage, une balle se représente par un cercle.
*)
type t_ball =
{
position : t_vec2 ref;
speed : t_vec2 ref;
size : t_ball_size
}
;;
(**
Définition de la raquette par sa taille et sa position en mouvement sur l'axe X.
*)
type t_paddle =
{
position : (int ref) * int;
size : t_paddle_size ref
}
;;
(**
Représentation du jeu de manière fonctionnel, avec tout les composants affichés à l'écran.
*)
type t_camlbrick =
{
param: t_camlbrick_param;
matrix : t_brick_kind array array;
paddle : t_paddle;
balls : t_ball list;
speed : int ref
}
;;
(**
Paramètres du casse-brique via des informations personnalisables selon les contraintes du sujet.
Aucune vérification n'est réalisé, s'assurer que les valeurs données en argument soient cohérentes.
@return paramétrage de jeu par défaut.
*)
let make_camlbrick_param () : t_camlbrick_param = {
world_width = 800;
world_bricks_height = 600;
world_empty_height = 200;
brick_width = 40;
brick_height = 20;
paddle_init_width = 100;
paddle_init_height = 20;
time_speed = ref 20;
};;
(**
Extraction des paramètres du casse-brique à partir de la partie du jeu.
@param game partie en cours d'exécution
@return paramétrage actuel.
*)
let param_get (game : t_camlbrick) : t_camlbrick_param =
make_camlbrick_param ()
;;
(**
Création d'une nouvelle structure qui initialise le monde avec aucune brique visible, une raquette et une balle par défaut dans la zone libre.
@author Max Charrier
@author Paul Ourliac
@return partie correctement initialisé.
*)
let make_camlbrick () : t_camlbrick =
{
param = make_camlbrick_param ();
matrix = Array.make_matrix 20 30 BK_empty;
paddle = {
size = ref PS_MEDIUM;
position = (ref 0, 0)
};
balls = [{
position = ref (make_vec2 (400, 750));
speed = ref (make_vec2 (-1, -3));
size = BS_MEDIUM
}];
speed = ref 5
}
;;
(**
Création d'une raquette par défaut au milieu de l'écran et de taille normal.
@author Paul Ourliac
@deprecated Cette fonction est là juste pour le debug ou pour débuter certains traitements de test.
*)
let make_paddle () : t_paddle =
{
size = ref PS_MEDIUM;
position = (ref 0, 0)
}
;;
(**
Création d'un balle par défaut.
@author Max Charrier
@param x position en abscisse
@param y position en ordonnée
@param size taille de la balle
@return balle initialisée.
*)
let make_ball (x, y, size : int * int * int) : t_ball =
if size = 5 then
{
position = ref (make_vec2 (x, y));
speed = ref (make_vec2 (0, 0));
size = BS_SMALL
}
else if size = 10 then
{
position = ref (make_vec2 (x, y));
speed = ref (make_vec2 (0, 0));
size = BS_MEDIUM
}
else
{
position = ref (make_vec2 (x, y));
speed = ref (make_vec2 (0, 0));
size = BS_BIG
}
;;
(**
Traduction de l'état du jeu sous la forme d'une chaîne de caractère.
Cette fonction est appelée à chaque frame, et est affichée directement dans l'interface graphique.
TODO : modifier cette fonction.
@author Max Charrier
@param game la partie en cours d'exécution.
@return chaîne de caractère représentant l'état de la partie.
*)
let string_of_gamestate (game : t_camlbrick) : string =
(* Itération 1,2,3 et 4 *)
"INCONNU"
;;
(**
Renvoie le type de la brique en fonction des coordonnées.
@author Paul Ourliac
@param game partie en cours d'exécution
@param i partie horizontal de la matrice de brique
@param j partie vertical de la matrice de brique
@return type d'une brique.
*)
let brick_get (game, i, j : t_camlbrick * int * int) : t_brick_kind =
game.matrix.(i).(j)
;;
(**
Retrace grâce au coordonnées de i et j le type dans la matrice de brique et
change son type en fonction de son type précedemment.
@author Axel De Les Champs--Vieira
@author Max Charrier
@param game partie en cours d'exécution
@param i partie horizontal de la matrice de brique
@param j partie vertical de la matrice de brique
@return type de brique
*)
let brick_hit (game, i, j : t_camlbrick * int * int) : t_brick_kind =
let brick : t_brick_kind = brick_get (game, i, j) in
if brick = BK_simple then
BK_empty
else if brick = BK_double then
BK_simple
else if brick = BK_bonus then
BK_empty
else if brick = BK_block then
BK_block
else
BK_empty
;;
(**
Renvoie la couleur de la brique en fonction des coordonnées.
@author Paul Ourliac
@param game partie en cours d'exécution
@param i partie horizontal de la matrice de brique
@param j partie vertical de la matrice de brique
@return couleur d'une brique.
*)
let brick_color (game, i, j : t_camlbrick * int * int) : t_camlbrick_color =
let brick : t_brick_kind = brick_get (game, i, j) in
if brick = BK_empty then
BLACK
else if brick = BK_simple then
GREEN
else if brick = BK_double then
RED
else if brick = BK_block then
ORANGE
else
BLUE
;;
(**
Renvoie la position selon l'axe horizontale de la raquette.
@author Paul Ourliac
@author Max Charrier
@param game partie en cours d'exécution
@return position en abscisse de la raquette.
*)
let paddle_x (game : t_camlbrick) : int =
!(fst game.paddle.position)
;;
(**
Renvoie la taille en pixel de la raquette.
@author Paul Ourliac
@param game partie en cours d'exécution
@return taille en pixel de la raquette.
*)
let paddle_size_pixel (game : t_camlbrick) : int =
let param : t_camlbrick_param = param_get game in
if !(game.paddle.size) = PS_SMALL then
param.paddle_init_width
else if !(game.paddle.size) = PS_MEDIUM then
param.paddle_init_width * 2
else
param.paddle_init_width * 4
;;
(**
Déplace la raquette vers la gauche.
@author Paul Ourliac
@param game partie en cours d'exécution
*)
let paddle_move_left (game : t_camlbrick) : unit =
if
paddle_x game > (paddle_size_pixel game) / 4 - game.param.world_width / 2
then
fst game.paddle.position := !(fst game.paddle.position) - 10
else
()
;;
(**
Déplace la raquette vers la droite.
@author Paul Ourliac
@param game partie en cours d'exécution
*)
let paddle_move_right (game : t_camlbrick) : unit =
let param : t_camlbrick_param = param_get game in
if
paddle_x game < (param.world_width / 2) - (paddle_size_pixel game) / 4
then
fst game.paddle.position := !(fst game.paddle.position) + 10
else
()
;;
(**
Indique si la partie en cours possèdes des balles.
@author Axel De Les Champs--Vieira
@author Max Charrier
@param game partie en cours d'exécution
@return s'il y a une balle ou non dans la partie.
*)
let has_ball (game : t_camlbrick) : bool =
game.balls <> []
;;
(**
Renvoie le nombre de balle présente dans une partie.
@author Axel De Les Champs--Vieira
@author Max Charrier
@param game partie en cours d'exécution
@return nombre de balle dans la partie.
*)
let balls_count (game : t_camlbrick) : int =
if game.balls = [] then
0
else
List.length game.balls
;;
(**
Récupérer la liste de toutes les balles de la partie en cours.
@author Axel De Les Champs--Vieira
@param game partie en cours d'exécution
@return liste des balles de la partie.
*)
let balls_get (game : t_camlbrick) : t_ball list =
game.balls
;;
(**
Récupère la i-ième balle d'une partie, i compris entre 0 et n, avec n le nombre de balles.
@author Axel De Les Champs--Vieira
@author Max Charrier
@param game partie en cours d'exécution
@param i partie horizontal de la matrice de brique
@return paramètres de la balle.
*)
let ball_get (game, i : t_camlbrick * int) : t_ball =
(*
Il s'agit d'une optimisation du code suivant :
{[
let eol : t_ball list ref = ref game.ball in
let incr : int ref = ref 0 in
while !incr != i do
eol := List.tl !eol;
incr := !incr + 1
done;
List.hd !eol
]}
*)
List.nth game.balls i
;;
(**
Renvoie l'abscisse du centre d'une balle.
@author Axel De Les Champs--Vieira
@author Max Charrier
@param game partie en cours d'exécution
@param ball balle
@return position en abscisse de la balle
*)
let ball_x (game, ball : t_camlbrick * t_ball) : int =
!(ball.position).x
;;
(**
Renvoie l'ordonnée du centre d'une balle.
@author Axel De Les Champs--Vieira
@author Max Charrier
@param game partie en cours d'exécution
@param ball balle
@return position en ordonnée de la balle
*)
let ball_y (game, ball : t_camlbrick * t_ball) : int =
!(ball.position).y
;;
(**
Indique le diamètre du cercle représentant la balle en fonction de sa taille.
@author Axel De Les Champs--Vieira
@author Max Charrier
@param game partie en cours d'exécution
@param ball balle
@return taille de la balle
*)
let ball_size_pixel (game, ball : t_camlbrick * t_ball) : int =
if ball.size = BS_SMALL then
5
else if ball.size = BS_MEDIUM then
10
else
15
;;
(**
Donne une couleur différentes pour chaque taille de balle.
@author Axel De Les Champs--Vieira
@param game partie en cours d'exécution
@param ball balle
@return couleur de la balle
*)
let ball_color (game, ball : t_camlbrick * t_ball) : t_camlbrick_color =
if ball.size = BS_SMALL then
LIME
else if ball.size = BS_MEDIUM then
LIGHTGRAY
else
GRAY
;;
(**
Modifie la vitesse d'une balle par accumulation avec un vecteur.
On peut alors augmenter ou diminuer la vitesse de la balle.
@author Max Charrier
@param game partie en cours d'exécution
@param ball balle
@param dv vecteur
*)
let ball_modif_speed (game, ball, dv : t_camlbrick * t_ball * t_vec2) : unit =
ball.speed := vec2_add (!(ball.speed), dv)
;;
(**
Modifie la vitesse d'une balle par multiplication avec un vecteur.
On peut alors augmenter ou diminuer la vitesse de la balle.
@author Max Charrier
@param game partie en cours d'exécution
@param ball balle
@param sv vecteur
*)
let ball_modif_speed_sign (game, ball, sv : t_camlbrick * t_ball * t_vec2) : unit =
ball.speed := vec2_mult (!(ball.speed), sv)
;;
(**
Détecte si un point (x,y) se trouve à l'intérieur d'un disque de centre (cx,cy) et de rayon rad.
@author Matéo Abrane
@author Max Charrier
@param cx centre du disque en abscisse
@param cy centre du disque en ordonnée
@param rad rayon du cercle
@param x point en abscisse
@param y point en ordonnée
@return si le point est dans le cercle
*)
let is_inside_circle (cx, cy, rad, x, y : int * int * int * int * int) : bool =
let fst_point : float = float_of_int (x - cx) ** 2. in
let snd_point : float = float_of_int (y - cy) ** 2. in
Float.sqrt (fst_point +. snd_point) < (float_of_int rad)
;;
(**
Détecte si un point (x,y) se trouve à l'intérieur d'un rectangle formé.
@author Matéo Abrane
@param x1 coordonnée (0, 0) du rectangle
@param y1 coordonnée (0, 1) du rectangle
@param x2 coordonnée (1, 0) du rectangle
@param y2 coordonnée (1, 1) du rectangle
@param x point en abscisse
@param y point en ordonnée
@return si le point est dans le rectangle
*)
let is_inside_quad (x1, y1, x2, y2, x, y : int * int * int * int * int * int) : bool =
x >= x1 && x <= x2 && y >= y1 && y <= y2
;;
(**
Renvoie une nouvelle liste sans les balles qui dépassent la zone de rebond.
@author Max Charrier
@author Paul Ourliac
@param game partie en cours
@param balls balle de la partie
@return balle restante
*)
let ball_remove_out_of_border (game, balls : t_camlbrick * t_ball list ) : t_ball list =
let param : t_camlbrick_param = param_get game in
let aux (ball : t_ball) : bool =
!(ball.position).y < param.world_width
in
List.filter aux balls
;;
(**
Rebondit si une balle touche la raquette.
@author Paul Ourliac
@author Max Charrier
@param game partie en cours
@param ball balle courante
@param paddle la raquette
@return si touché ou non
*)
let ball_hit_paddle (game, ball, paddle : t_camlbrick * t_ball * t_paddle) : unit =
let param : t_camlbrick_param = param_get game in
let ball_position : t_vec2 = !(ball.position) in
let ball_speed : t_vec2 = !(ball.speed) in
let paddle_x1 : int =
paddle_x game - (paddle_size_pixel game) / 4
and paddle_x2 : int =
(paddle_x game - (paddle_size_pixel game) / 4) + param.paddle_init_width
and paddle_y1 : int =
param.world_bricks_height + param.world_empty_height - param.paddle_init_height - 10
and paddle_y2 : int =
param.world_bricks_height + param.world_empty_height - 10
in
if
is_inside_quad (paddle_x1, paddle_y1, paddle_x2 - 4 * 20 , paddle_y2, ball_position.x - (param.world_width / 2), ball_position.y)
then begin
ball_modif_speed_sign (game, ball, make_vec2 (0, 0));
ball_modif_speed (game, ball, make_vec2 (-2, - ball_speed.y))
end else if
is_inside_quad (paddle_x1 + 1 * 20, paddle_y1, paddle_x2 - 3 * 20, paddle_y2, ball_position.x - (param.world_width / 2), ball_position.y)
then begin
ball_modif_speed_sign (game, ball, make_vec2 (0, 0));
ball_modif_speed (game, ball, make_vec2 (-1, - ball_speed.y))
end else if
is_inside_quad (paddle_x1 + 2 * 20, paddle_y1, paddle_x2 - 2 * 20, paddle_y2, ball_position.x - (param.world_width / 2), ball_position.y)
then begin
ball_modif_speed_sign (game, ball, make_vec2 (0, 0));
ball_modif_speed (game, ball, make_vec2 (0, - ball_speed.y))
end else if
is_inside_quad (paddle_x1 + 3 * 20, paddle_y1, paddle_x2 - 1 * 20, paddle_y2, ball_position.x - (param.world_width / 2), ball_position.y)
then begin
ball_modif_speed_sign (game, ball, make_vec2 (0, 0));
ball_modif_speed(game, ball, make_vec2 (1, - ball_speed.y))
end else if
is_inside_quad (paddle_x1 + 4 * 20, paddle_y1, paddle_x2 , paddle_y2, ball_position.x - (param.world_width / 2), ball_position.y)
then begin
ball_modif_speed_sign (game, ball, make_vec2 (0, 0));
ball_modif_speed (game, ball, make_vec2 (2, - ball_speed.y))
end
;;
(**
Vérifie si une balle touche un des sommets des briques.
@author Max Charrier
@author Paul Ourliac
@param game partie en cours
@param ball balle courante
@param i partie horizontal de la matrice de brique
@param j partie vertical de la matrice de brique
@return si touché ou non
*)
let ball_hit_corner_brick (game, ball, i, j : t_camlbrick * t_ball * int * int) : bool =
let param : t_camlbrick_param = param_get game in
let ball_position = !(ball.position) in
let ball_radius = ball_size_pixel (game, ball) in
let (pos_x, pos_y) : int * int =
(i * param.brick_width, j * param.brick_height)
in
is_inside_circle (ball_position.x, ball_position.y, ball_radius, pos_x, pos_y)
|| is_inside_circle (ball_position.x, ball_position.y, ball_radius, pos_x + param.brick_width, pos_y)
|| is_inside_circle (ball_position.x, ball_position.y, ball_radius, pos_x, pos_y + param.brick_height)
|| is_inside_circle (ball_position.x, ball_position.y, ball_radius, pos_x + param.brick_width, pos_y + param.brick_height)
;;
(**
Vérifie si une balle touche une des arrêtes des briques.
@author Max Charrier
@author Paul Ourliac
@param game partie en cours
@param ball balle courante
@param i partie horizontal de la matrice de brique
@param j partie vertical de la matrice de brique
@return si touché ou non
*)
let ball_hit_side_brick (game, ball, i, j : t_camlbrick * t_ball * int * int) : bool =
let param : t_camlbrick_param = param_get game in
let ball_position = !(ball.position) in
let ball_radius = ball_size_pixel (game, ball) in
let (pos_x, pos_y) : int * int =
(i * param.brick_width, j * param.brick_height)
in
is_inside_circle (ball_position.x, ball_position.y, ball_radius, pos_x + (param.brick_width / 2), pos_y)
|| is_inside_circle (ball_position.x, ball_position.y, ball_radius, pos_x + param.brick_width, pos_y + param.brick_height)
|| is_inside_circle (ball_position.x, ball_position.y, ball_radius, pos_x, pos_y + (param.brick_height / 2))
|| is_inside_circle (ball_position.x, ball_position.y, ball_radius, pos_x + param.brick_width, pos_y + (param.brick_height / 2))
;;
(**
Gère les collisions des balles.
TODO : découper `animate_action` pour le mettre ici.
@author ...
@param game partie en cours
@param balls liste des balles en jeu
*)
let game_test_hit_balls (game, balls : t_camlbrick * t_ball list) : unit =
(* Itération 3 *)
()
;;
(**
Appelée par l'interface graphique avec le jeu en argument et la position de
la souris dans la fenêtre lorsqu'elle se déplace.
Vous pouvez réaliser des traitements spécifiques, mais comprenez bien que
cela aura un impact sur les performances si vous dosez mal les temps de
calcul.
@param game la partie en cours
@param x l'abscisse de la position de la souris
@param y l'ordonnée de la position de la souris
*)
let canvas_mouse_move (game, x, y : t_camlbrick * int * int) : unit =
()
;;
(**
Appelée par l'interface graphique avec le jeu en argument et la position
de la souris dans la fenêtre lorsqu'un bouton est enfoncé.
Vous pouvez réaliser des traitements spécifiques, mais comprenez bien que
cela aura un impact sur les performances si vous dosez mal les temps de
calcul.
@param game la partie en cours
@param button numero du bouton de la souris enfoncé
@param x l'abscisse de la position de la souris
@param y l'ordonnée de la position de la souris
*)
let canvas_mouse_click_press (game, button, x, y : t_camlbrick * int * int * int) : unit =
let param : t_camlbrick_param = param_get game in
let canvas_height : int =
param.world_empty_height + param.world_bricks_height
in
let pos_x : int =
if x > param.world_width / 2 then
if x / 2 >= param.world_width / 2 - paddle_size_pixel game / 4 then
param.world_width / 2 - paddle_size_pixel game / 4
else
x - param.world_width / 2
else
-1 * (-(x + param.world_width / 2) + param.world_width)
in
if y >= canvas_height - param.paddle_init_height - 10 && y < canvas_height then begin
print_string "pos init=";
print_int (paddle_x game);
print_string " new pos=";
print_int pos_x;
print_newline ();
fst game.paddle.position := pos_x
end else
()
;;
(**
Appelée par l'interface graphique avec le jeu en argument et la position
de la souris dans la fenêtre lorsqu'un bouton est relaché.
Vous pouvez réaliser des traitements spécifiques, mais comprenez bien que
cela aura un impact sur les performances si vous dosez mal les temps de
calcul.
@param game la partie en cours
@param button numero du bouton de la souris relaché
@param x l'abscisse de la position du relachement
@param y l'ordonnée de la position du relachement
*)
let canvas_mouse_click_release (game, button, x, y : t_camlbrick * int * int * int) : unit =
()
;;
(**
Appelée par l'interface graphique lorsqu'une touche du clavier est appuyée.
Les arguments sont le jeu en cours, la touche enfoncé sous la forme d'une
chaine et sous forme d'un code spécifique à labltk.
Le code fourni initialement permet juste d'afficher les touches appuyées au
clavier afin de pouvoir les identifiées facilement dans nos traitements.
Vous pouvez réaliser des traitements spécifiques, mais comprenez bien que
cela aura un impact sur les performances si vous dosez mal les temps de
calcul.
@param game la partie en cours
@param keyString nom de la touche appuyée
@param keyCode code entier de la touche appuyée
*)
let canvas_keypressed (game, key_string, key_code : t_camlbrick * string * int) : unit =
let left_key_code : int = 65361 in
let q_key_code : int = 113 in
let right_key_code : int = 65363 in
let d_right_code : int = 100 in
if key_code = left_key_code || key_code = q_key_code then
paddle_move_left game
else if key_code = right_key_code || key_code = d_right_code then
paddle_move_right game
else
()
;;
(**
Appelée par l'interface graphique lorsqu'une touche du clavier est relachée.
Les arguments sont le jeu en cours, la touche relachée sous la forme d'une
chaine et sous forme d'un code spécifique à labltk.
Le code fourni initialement permet juste d'afficher les touches appuyées au
clavier afin de pouvoir les identifiées facilement dans nos traitements.
Vous pouvez réaliser des traitements spécifiques, mais comprenez bien que
cela aura un impact sur les performances si vous dosez mal les temps de
calcul.
@param game la partie en cours
@param keyString nom de la touche relachée
@param keyCode code entier de la touche relachée
*)
let canvas_keyreleased (game, key_string, key_code : t_camlbrick * string * int) : unit =
()
;;
(**
Cette fonction est utilisée par l'interface graphique pour connaitre
l'information à afficher dans la zone Custom1 de la zone du menu.
*)
let custom1_text () : string =
(* Iteration 4 *)
"<Rien1>"
;;
(**
Cette fonction est utilisée par l'interface graphique pour connaitre
l'information à afficher dans la zone Custom2 de la zone du menu.
*)
let custom2_text () : string =
(* Iteration 4 *)
"<Rien2>"
;;
(**
Cette fonction est appelée par l'interface graphique lorsqu'on clique sur le
bouton de la zone de menu et que ce bouton affiche "Start".
Vous pouvez réaliser des traitements spécifiques, mais comprenez bien que
cela aura un impact sur les performances si vous dosez mal les temps de
calcul.
@author Max Charrier
@param game la partie en cours
*)
let start_onclick (game : t_camlbrick) : unit =
()
;;
(**
Appelée par l'interface graphique lorsqu'on clique sur le bouton
de la zone de menu et que ce bouton affiche "Stop".
Vous pouvez réaliser des traitements spécifiques, mais comprenez bien que
cela aura un impact sur les performances si vous dosez mal les temps de
calcul.
@param game la partie en cours
*)
let stop_onclick (game : t_camlbrick) : unit =
let balls : t_ball list ref = ref game.balls in
(* Supprimer toutes les balles *)
balls := []
;;
(**
Appelée par l'interface graphique pour connaitre la valeur
du slider Speed dans la zone du menu.
Vous pouvez donc renvoyer une valeur selon votre désir afin d'offrir la
possibilité d'interagir avec le joueur.
@param game partie en cours d'exécution
@return vitesse du slider speed dans le menu contextuel.
*)
let speed_get (game : t_camlbrick) : int =
!(game.speed)
;;