Pour avoir des boutons de jeux il faut des booléens up/down,
Est-ce qu'il suffit de remettre ces booléens à chaque touch event à zero, puis mettre à 1 ceux qui renvoient un test positif point/rectangle, ou la manoeuvre est-elle plus complexe ?
Version imprimable
Pour avoir des boutons de jeux il faut des booléens up/down,
Est-ce qu'il suffit de remettre ces booléens à chaque touch event à zero, puis mettre à 1 ceux qui renvoient un test positif point/rectangle, ou la manoeuvre est-elle plus complexe ?
heu... je n'ai absolument rien compris a la problematique ...
comme on dit : un probleme bien expose est a moitie resolu
Bon je crois qu'il faut que je fasse des tests.
C'est plus compliqué que de gérer la souris et le clavier https://developer.mozilla.org/en-US/...I/Touch_events
Bon donc apparemment comme je le pensais, c'est plus compliqué que ça,
Il faudrait capturer les events stard/end/move/cancel avec toutes les listes d'ellipses,
Ensuite tester les hits d'ellipses contre celles des boutons affichés dans le canvas,
après si je dis pas de bêtises:
- touchstart met les boutons à 1
- touchmove met les boutons à 1 si contact ou 0
- touchend/touchcancel met les boutons à 0
Bon... en fait l'algo va entièrement dépendre du contexte,
Là je pars sur un truc simple, une croix et A B (comme la gameboy)
Si contact avec la croix, il faut faire centreDoigt - centreCroix pour trouver le vecteur directionnel converti en 8 directions,
Pour les boutons tester l'ellipse du pouce suffit, normalement, pour savoir si elle couvre" A, B ou les 2.
Je teste ça et je vous dis si ça marche.
Alors je découvre les subtilités du truc:
1/ Les ellipses sont toutes petites, donc repérer le point central suffit.
2/ Les smartphones d'entrée de gamme ne détectent que deux doigts maximum.
Pour le pouce à droite faudrait donc que j'essaye un rectangle à 3 cases (A, A+B, B) on verra ce que ça donne.
Voilà, je continue mes tests, maintenant je passe aux maths, la difficulté ne réside pas dans les events de touch qui permettent de faire facilement un pseudo-paint, mais dans les calculs géométriques pour simuler une manette.
Il faudrait peut-être que je fasse cet exercice qui consiste à simuler deux curseurs de souris, ça simplifierait la logique dans un premier temps... je ne sais pas je débute en gestion des touch.
je n'ai toujours pas compris ce que tu voulais faire ... mais peut-etre que cette video peu t'aider (en anglais)
https://www.youtube.com/watch?v=MhUC...?v=MhUCYR9Tb9c
- A gauche: une croix à 8 directions. Forme géométrique: un cercle.
- A droite: deux boutons, et si le pouce est entre les deux ça met les deux à true. Forme géométrique: un rectangle.
Côté tests point/cercle/rect je connais les formules de maths, c'est pas là où j'ai une difficulté. Ca pourrait être n'importe quelles autres formes géométriques, peu importe.
La difficulté est de savoir quand les deux pouces entrent et sortent des deux formes. Pour start/end j'ai un event par pouce. Pour move j'ai un event pour deux pouces avec un tableau touch à 2 cases. Y'a rien qui me permet de savoir si c'est le pouce gauche ou droit.
Peut-être bêtement faire un test gauche/droite par rapport au centre du canvas, je vais essayer ça.
Pour l'instant un test simple, je me contente de voir si les doigts sont sur les deux zones.
Çà fonctionne la plupart du temps mais il y a des cas rares où j'arrive à faire planter le truc (la zone droite reste en on alors qu'il n'y a plus de doigt dessus), il faut que je fasse encore des tests.
Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 <!DOCTYPE html> <!-- Click nbfs://nbhost/SystemFileSystem/Templates/Licenses/license-default.txt to change this license Click nbfs://nbhost/SystemFileSystem/Templates/Other/html.html to edit this template --> <html> <head> <title>TODO supply a title</title> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <script src="main.js"></script> </head> <body onLoad="main()"> <div align="center"> <canvas id="draw" width="480" height="320"></canvas> <div id="tracer"></div> </div> </body> </html>
Code:
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 // render context test var CAN = null; var CTX2D = null; // colors const CO = ['#0000FF', '#FF0000']; // left buttons zone: 8-directions cross const CROSS_X = 64; const CROSS_Y = 320 - 64; const CROSS_RAD = 64; var CROSS_ON = 0; // right buttons zone: A B const AB_W = 64 * 3; const AB_X = 480 - AB_W; const AB_H = 64 * 2; const AB_Y = CROSS_Y - AB_H / 2; var AB_ON = 0; // show txt function trace(s) { document.getElementById('tracer').innerHTML += s + '<br/>'; } function main() { //alert("main"); CAN = document.getElementById('draw'); CTX2D = CAN.getContext('2d'); //console.log(CTX2D); CTX2D.strokeStyle = '#FFFFFF'; CTX2D.fillRect(0, 0, 720, 480); // draw button zones CTX2D.fillStyle = CO[0]; CTX2D.arc(CROSS_X, CROSS_Y, CROSS_RAD, 0, Math.PI * 2); CTX2D.fill(); CTX2D.rect(AB_X, AB_Y, AB_W, AB_H); CTX2D.fill(); // touch events CAN.ontouchstart = OnTouchStart; CAN.ontouchend = OnTouchEnd; CAN.ontouchmove = OnTouchMove; } function Touch(e, on) { e.preventDefault(); const tl = e.changedTouches; const r = e.target.getBoundingClientRect(); const halfWidth = (r.right - r.left) / 2; for (let i = 0; i < 2; i++) { const x = tl[i].clientX - r.left; const y = tl[i].clientY - r.top; if ( x < halfWidth ) { // left: test against cross CROSS_ON = 0; if (on) { // test point / circle const dx = x - CROSS_X; const dy = y - CROSS_Y; CROSS_ON = 0 + ( Math.sqrt(dx*dx + dy*dy) <= CROSS_RAD ); } CTX2D.fillStyle = CO[ CROSS_ON ]; CTX2D.beginPath(); CTX2D.arc(CROSS_X, CROSS_Y, CROSS_RAD, 0, Math.PI * 2); CTX2D.fill(); } else { // right: test against AB AB_ON = 0; if (on) { // test point / AABB const dx = x - AB_X; const dy = y - AB_Y; AB_ON = 0 + ( dx >= 0 && dx <= AB_W && dy >= 0 && dy <= AB_H ); } CTX2D.fillStyle = CO[ AB_ON ]; CTX2D.beginPath(); CTX2D.rect(AB_X, AB_Y, AB_W, AB_H); CTX2D.fill(); } } } function OnTouchStart(e) { Touch(e, 1); } function OnTouchEnd(e) { Touch(e, 0); } function OnTouchMove(e) { Touch(e, 1); }
Ca y'est je viens de réussir à identifier le bug.
Quand un "start/move" vire trop vite vers la gauche ou la droite, le programme n'a pas le temps de voir que le doigt a quitté les zones cercle/rect car il retient le dernier move event, donc les booléens restent bloqués sur "on".
Il faut que je réfléchisse comment corriger ça.
Je vais tester une approche plus bête où mes deux zones sont juste des <div>.
Bon donc là je me suis bêtement rabattu sur le comportement par défaut des <div>, je n'ai plus ce bug.
Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 <!DOCTYPE html> <!-- Click nbfs://nbhost/SystemFileSystem/Templates/Licenses/license-default.txt to change this license Click nbfs://nbhost/SystemFileSystem/Templates/Other/html.html to edit this template --> <html> <head> <title>TODO supply a title</title> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <script src="main.js"></script> </head> <body onLoad="main()"> <div align="center"> <div id="container" align="left" style="width:480px;height:320px;background-color:#000000;"> <canvas id="draw" width="480" height="320"></canvas> </div> <div id="tracer"></div> </div> </body> </html>
Code:
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 // div container var CON = null; // render context test var CAN = null; var CTX2D = null; // colors const CO = ['#0000FF', '#FF0000']; // left buttons zone: 8-directions cross var CROSS_DIV = null; // right buttons zone: A B var AB_DIV = null; // show txt function trace(s) { document.getElementById('tracer').innerHTML += s + '<br/>'; } function main() { //alert("main"); CON = document.getElementById('container'); const conR = CON.getBoundingClientRect(); const cost = CON.style; cost.position='relative'; //alert(conR); // drawing canvas CAN = document.getElementById('draw'); CTX2D = CAN.getContext('2d'); // CROSS BUTTONS CROSS_DIV = document.createElement('div'); const cst = CROSS_DIV.style; cst.backgroundColor = '#0000FF'; cst.width = '128px'; cst.height = '128px'; cst.top = (320-128)+'px'; cst.left ='0px'; cst.position = 'absolute'; //cst.zIndex = 2; CON.appendChild(CROSS_DIV); CROSS_DIV.ontouchstart = CrossStart; CROSS_DIV.ontouchend = CrossEnd; // AB BUTTONS AB_DIV = document.createElement('div'); const ast = AB_DIV.style; ast.backgroundColor = '#0000FF'; ast.width = '128px'; ast.height = '128px'; ast.top = (320-128)+'px'; ast.left =(480-128)+'px'; ast.position = 'absolute'; //ast.zIndex = 3; CON.appendChild(AB_DIV); AB_DIV.ontouchstart = ABStart; AB_DIV.ontouchend = ABEnd; } function CrossStart(e) { e.preventDefault(); CROSS_DIV.style.backgroundColor = '#FF0000'; } function CrossEnd(e) { e.preventDefault(); CROSS_DIV.style.backgroundColor = '#0000FF'; } function ABStart(e) { e.preventDefault(); AB_DIV.style.backgroundColor = '#FF0000'; } function ABEnd(e) { e.preventDefault(); AB_DIV.style.backgroundColor = '#0000FF'; }
Bon... faut que je finisse l'exercice jusqu'au bout... je vois que c'est pas si simple et ça pourra servir aux autres.
Faut que j'ajoute là:
- Détection sur onmove quand les doigts sortent/entrent dans les rectangles
- Bouton fullscreen en haut à droite car il faut recalculer la position des boutons
- Dessiner les boutons
- Faire les calculs qui simulent cross & AB
Bonjour,
sans regarder plus avant ton projet, oublie les touchxxxx et passe aux pointerxxxx.
Il te faut factoriser tes fonctions et ne pas en créer une par élément.
Si l'on prend ce code :
seule la cible change donc une seule fonction est nécessaire, par exemple :Code:
1
2
3
4
5
6
7
8
9
10 function CrossStart(e) { e.preventDefault(); CROSS_DIV.style.backgroundColor = '#FF0000'; } function ABStart(e) { e.preventDefault(); AB_DIV.style.backgroundColor = '#FF0000'; }
cela fera pour les deux.Code:
1
2
3
4
5
6 function CrossStart(e) { const target = e.target; e.preventDefault(); target/*CROSS_DIV*/.style.backgroundColor = '#FF0000'; }
Merci, je viens de voir que les events pointer calculent automatiquement over/out, ça va me permettre de simplifier tout ça.
Et oui pour la factorisation de fonction tu as raison j'y pensais hier mais c'était la fin de journée, j'étais fatigué et j'ai un peu bâclé mon test. Il faut que je fasse comme pour le premier, tout condenser sur une fonction PaddleEvent.
bon c'est pas si simple...
onpointerenter/onpointerover fonctionne avec la souris mais pas le touch
les event pointer ne permettent pas d'indifférencier souris et touch, ce sont bien deux input device différents
j'y arrive pas là je crois que je vais me contenter des events touch
Pour l'instant ce petit bout de code a l'air de fonctionner à peu près mais je suis réceptif à vos critiques.
Code:
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 // div container var CON = null; // render context test var CAN = null; var CTX2D = null; // colors const CO = ['#0000FF', '#FF0000']; // left buttons zone: 8-directions cross var CROSS_DIV = null; // right buttons zone: A B var AB_DIV = null; // show txt function trace(s) { document.getElementById('tracer').innerHTML += s + '<br/>'; } function main() { //alert("main"); CON = document.getElementById('container'); const conR = CON.getBoundingClientRect(); const cost = CON.style; cost.position = 'relative'; //alert(conR); // drawing canvas CAN = document.getElementById('draw'); CAN.ontouchmove = function (e) { e.preventDefault(); }; CTX2D = CAN.getContext('2d'); // CROSS BUTTONS CROSS_DIV = document.createElement('div'); const cst = CROSS_DIV.style; cst.backgroundColor = CO[0]; cst.width = '128px'; cst.height = '128px'; cst.top = (320 - 128) + 'px'; cst.left = '0px'; cst.position = 'absolute'; //cst.zIndex = 2; CON.appendChild(CROSS_DIV); CROSS_DIV.ontouchstart = function (e) { PadEvent(e, 1, 0); }; CROSS_DIV.ontouchmove = function (e) { PadEvent(e, 1, 0); }; CROSS_DIV.ontouchend = function (e) { PadEvent(e, 0, 0); }; // AB BUTTONS AB_DIV = document.createElement('div'); const ast = AB_DIV.style; ast.backgroundColor = CO[0]; ast.width = '128px'; ast.height = '128px'; ast.top = (320 - 128) + 'px'; ast.left = (480 - 128) + 'px'; ast.position = 'absolute'; //ast.zIndex = 3; CON.appendChild(AB_DIV); AB_DIV.ontouchstart = function (e) { PadEvent(e, 1, 1); }; AB_DIV.ontouchmove = function (e) { PadEvent(e, 1, 1); }; AB_DIV.ontouchend = function (e) { PadEvent(e, 0, 1); }; } function PadEvent(e, on, zone) { e.preventDefault(); const div = e.target; const st = div.style; const rec = div.getBoundingClientRect(); const touch = e.changedTouches[0]; var pressed = 0; * if (on) { const x = touch.clientX - rec.left; const y = touch.clientY - rec.top; if ( x >=0 && x <= rec.width && y >= 0 && y <= rec.height ) { pressed = 1; } } st.backgroundColor = CO[pressed]; }
Bon... hé bien non, c'est toujours pas bon, quand je touchmove les deux boutons en même temps y'en a un qui fait planter l'autre.
Bon pour le moment avec les <div> je m'en sors pas, je ne trouve pas mes erreurs.
J'ai repris le premier test en réduisant la zone de droite à 128x128 histoire de réduire au max le risque du bug, je n'arrive pas à faire mieux pour le moment.
Bon pour l'instant ça semble fonctionner.
Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 <!DOCTYPE html> <!-- Click nbfs://nbhost/SystemFileSystem/Templates/Licenses/license-default.txt to change this license Click nbfs://nbhost/SystemFileSystem/Templates/Other/html.html to edit this template --> <html> <head> <title>TODO supply a title</title> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <script src="main.js"></script> </head> <body onLoad="main()"> <div align="center"> <div id="container" style="width:480px;height:320px;background-color:#0000FF;" > </div> <div id="tracer"></div> </div> </body> </html>
Code:
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 // canvas dimensions var SW = 480; var SH = 320; // render context test var CONTAINER = null; var CAN = null; var CTX2D = null; // colors const CO = ['#0000FF', '#FF0000']; // left buttons zone: 8-directions cross const CROSS_X = 64; const CROSS_Y = SH - 64; const CROSS_RAD = 64; var CROSS_ON = 0; // right buttons zone: A B const AB_W = 64 * 2; const AB_X = SW - AB_W; const AB_H = 64 * 2; const AB_Y = CROSS_Y - AB_H / 2; var AB_ON = 0; // fullscreen button const FULLSCREEN_RECT = {left: SW - 32, width: 32, top: 0, height: 32}; // show txt function trace(s) { document.getElementById('tracer').innerHTML += s + '<br/>'; } // coordinates relative to canvas function Cx(x) { return x * CAN.width / CONTAINER.offsetWidth; } function Cy(y) { return y * CAN.height / CONTAINER.offsetHeight; } function main() { //alert("main"); CONTAINER = document.getElementById('container'); CAN = document.createElement('canvas'); CAN.width = SW; CAN.height = SH; CAN.style.backgroundColor = '#000000'; CAN.style.width = "100%"; CAN.style.height = "100%"; CONTAINER.appendChild(CAN); CTX2D = CAN.getContext('2d'); //console.log(CTX2D); CTX2D.strokeStyle = '#FFFFFF'; CTX2D.fillRect(0, 0, SW, SH); // draw button zones CTX2D.fillStyle = CO[0]; CTX2D.beginPath(); CTX2D.arc(CROSS_X, CROSS_Y, CROSS_RAD, 0, Math.PI * 2); CTX2D.closePath(); CTX2D.fill(); CTX2D.beginPath(); CTX2D.rect(AB_X, AB_Y, AB_W, AB_H); CTX2D.closePath(); CTX2D.fill(); CTX2D.beginPath(); CTX2D.rect(FULLSCREEN_RECT.left, FULLSCREEN_RECT.top, FULLSCREEN_RECT.width, FULLSCREEN_RECT.height); CTX2D.closePath(); CTX2D.fill(); // touch events CAN.ontouchstart = OnTouchStart; CAN.ontouchend = OnTouchEnd; CAN.ontouchmove = OnTouchMove; } function Touch(e, on) { e.preventDefault(); const tl = e.changedTouches; const r = e.target.getBoundingClientRect(); const halfWidth = Cx((r.right - r.left) / 2); //let inLeft = 0, inRight = 0; for (let i = 0; i < tl.length; i++) { const x = Cx(tl[i].clientX - r.left); const y = Cy(tl[i].clientY - r.top); if (x < halfWidth) { // left: test against cross CROSS_ON = 0; if (on) { //inLeft = 1; // test point / circle const dx = x - CROSS_X; const dy = y - CROSS_Y; CROSS_ON = 0 + (Math.sqrt(dx * dx + dy * dy) <= CROSS_RAD); } } else { // right: test against AB AB_ON = 0; if (on) { //inRight = 1; // test point / AABB const dx = x - AB_X; const dy = y - AB_Y; AB_ON = 0 + (dx >= 0 && dx <= AB_W && dy >= 0 && dy <= AB_H); } } } // colorization test CTX2D.fillStyle = CO[ CROSS_ON ]; CTX2D.beginPath(); CTX2D.arc(CROSS_X, CROSS_Y, CROSS_RAD, 0, Math.PI * 2); CTX2D.closePath(); CTX2D.fill(); CTX2D.fillStyle = CO[ AB_ON ]; CTX2D.beginPath(); CTX2D.rect(AB_X, AB_Y, AB_W, AB_H); CTX2D.closePath(); CTX2D.fill(); } function OnTouchStart(e) { Touch(e, 1); } function OnTouchEnd(e) { Touch(e, 0); OnMouseUp(e); } function OnTouchMove(e) { Touch(e, 1); } function ToggleFullScreen() { if (!document.fullscreen) { CONTAINER.requestFullscreen(); } else { document.exitFullscreen(); } } function OnMouseUp(e) { const rec = e.target.getBoundingClientRect(); const tl = e.changedTouches; const fsr = FULLSCREEN_RECT; for (let i = 0; i < tl.length; i++) { const x = Cx(tl[i].clientX - rec.left); const y = Cy(tl[i].clientY - rec.top); // check fullscreen button const dx = x - fsr.left; const dy = y - fsr.top; //trace(dx + ':' + dy); //console.log(fsr.width+':'+fsr.height); if (dx >= 0 && dx < fsr.width && dy >= 0 && dy < fsr.height) { ToggleFullScreen(); } } }
Je m'aperçois encore de deux petites subtilités de chrome smartphone low-entry:
- Si un objet a des touchevent ça désactive les mouseEvent, donc il faut vraiment tout faire avec le touchevent (je parle dans le cas d'un paddle hein, pas pour des jeux à clics).
- Le paddle doit être affiché dans le canvas, sur les smartphone low-entry ça ne fonctionne pas avec des objets DOM car ils ne gèrent pas deux touchmove sur deux objets différents. (en prime ,afficher des choses par dessus le canvas consomme plus de ressources cpu-gpu, donc l'affichage du paddle doit se faire avec les sprites du jeu). Il faut donc vraiment deux interfaces & affichages différents selon le contexte desktop/smartphone.
- Le bouton fullscreen doit être sur l'event touchEnd, sur touchStart il y'a un bug d'affichage, le canvas est mal dimensionné, je ne sais pas pourquoi.
- Quand le jeu n'est pas en fullscreen les boutons peuvent restés bloqués en "on" quand le doigt quitte le canvas. Il est donc bon d'actionner le fullscreen par défaut dès que le joueur clique "start".
Maintenant la difficulté va être au niveau du design des formes géométriques invisibles sous la croix qui détectent la "collision" avec le centre du pouce. Si je raisonne bêtement avec une grille 3x3 ça n'est pas bon car le pouce va trop facilement taper dans les cases diagonale. Il ne faut pas raisonner avec un joystick croix mais un joystick rond puisque c'est bien ce qui correspond aux x/y renvoyés par les event touch.
A priori je vais tester d'abord comme ça:
- Un cercle extérieur pour définir quand le pouce est sorti de la manette (que je pense faire un peu plus large)
- Un cercle central qui définit la zone morte, le pouce doit d'éloigner du centre pour actionner les directions.
- 4 droites y=2x, y=x/2, y=-x/2, y=-2x, ce qui fait que les zones diagonales sont un peu plus petites que les zones aa.
Bon, mais je ne peux pas dire si mon algo est ergonomique tant que je ne l'ai pas testé avec mon pouce.
Je n'aime pas non plus mon second schéma. Les diagonales sont encore trop faciles d'accès.
Je griffonne d'autres possibilités.
Je sais que pour faire du vrai boulot de pro il faut un "touchpad" spécifique à chaque jeu, mais les jeux web c'est facturé environ 1500€ donc dans ce milieu il faut être productif... Donc sachant qu'on fait plutôt des pacman que des street fighter je ne vais pas trop m'attarder sur les diagonales (dont je risque de ne jamais faire usage, en fait).
Donc pour l'instant je vais tester ça sur mon pad 128x128:
- droites y=x et y=-x pour tester haut/bas/gauche/droite
- un carré de zone morte 16x16 au milieu
- 4 cassés 16x16 dans les coins pour faire les touch diagonale
Je vous montrerai le test si j'ai fini ce soir.
Au lieu de vous faire mal au crâne avec mon charabia de prog graphique c'est mieux de scanner mes dessins.
Pièce jointe 630546
Ca ne me plaît pas il va encore y'avoir des ambiguités sur X/Y.
Je commence à me demander si ça serait pas plus malin de faire un codage de collision standard, avec une grille.
Bon allez, testons des maths crétins,
L = 0001 = 1
R = 0010 = 2
U = 0100 = 4
D = 1000 = 8
LU = 0101 = 5
LD = 1001 = 9
RU = 0110 = 6
RD = 1010 = 10
Le tableau javascript doit donc ressembler à un truc comme ça:
const CROSS = [
5, 5, 4, 4, 4, 4, 6, 6,
5, 5 ,4, 4, 4, 4, 6, 6,
1, 1 ,0, 4, 4, 0, 2, 2,
1, 1, 1, 0, 0, 2, 2, 2,
1, 1, 1, 0, 0, 2, 2, 2,
1, 1 ,0, 8, 8, 0, 2, 2,
9, 9, 8, 8, 8, 8,10,10,
9, 9, 8, 8, 8, 8,10,10
];
Voilà... je teste et je regarde ce que ça donne...
Non en fait mon idée était nulle va encore y'avoir des ambiguités X/Y...
Je vais déjà essayer le truc avec 2 cercles et 4 droites, c'est le plus simple au niveau visuel et maths.
Dès fois j'ai l'impression que développeur est un boulot à peu près aussi chiant que footballeur.
Je remercie les smartphone pour tout le bien qu'ils font à la société avec les cadeaux surprise dans les bateaux (covid, frelons, etc)
De toutes façons Lundi personne a envie de bosser.
bon... la croix m'a l'air de fonctionner... je vous laisse tester.
Code:
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 // canvas dimensions var SW = 240; var SH = 160; // render zone var CONTAINER = null; var CAN = null; var CTX2D = null; // colors const CO = ['#0000FF', '#FF0000']; // left buttons zone: 8-directions cross const CROSS_RAD = 32; const CROSS_X = CROSS_RAD; const CROSS_Y = SH - CROSS_RAD; var CROSS_ON = 0; var LEFT_ON = 0; var RIGHT_ON = 0; var UP_ON = 0; var DOWN_ON = 0; // right buttons zone: A B const AB_W = 32 * 2; const AB_X = SW - AB_W; const AB_H = 32 * 2; const AB_Y = CROSS_Y - AB_H / 2; var AB_ON = 0; // fullscreen button const FULLSCREEN_RECT = {left: SW - 16, width: 16, top: 0, height: 16}; // show txt function trace(s) { document.getElementById('tracer').innerHTML += s + '<br/>'; } // coordinates relative to canvas function Cx(x) { return x * CAN.width / CONTAINER.offsetWidth; } function Cy(y) { return y * CAN.height / CONTAINER.offsetHeight; } function DrawButtons() { // cross CTX2D.fillStyle = CO[ LEFT_ON ]; CTX2D.beginPath(); CTX2D.rect(CROSS_X - CROSS_RAD, CROSS_Y - 8, CROSS_RAD - 8, 16); CTX2D.closePath(); CTX2D.fill(); CTX2D.fillStyle = CO[ RIGHT_ON ]; CTX2D.beginPath(); CTX2D.rect(CROSS_X + 8, CROSS_Y - 8, CROSS_RAD - 8, 16); CTX2D.closePath(); CTX2D.fill(); CTX2D.fillStyle = CO[ UP_ON ]; CTX2D.beginPath(); CTX2D.rect(CROSS_X - 8, CROSS_Y - CROSS_RAD, 16, CROSS_RAD - 8); CTX2D.closePath(); CTX2D.fill(); CTX2D.fillStyle = CO[ DOWN_ON ]; CTX2D.beginPath(); CTX2D.rect(CROSS_X - 8, CROSS_Y + 8, 16, CROSS_RAD - 8); CTX2D.closePath(); CTX2D.fill(); // AB CTX2D.fillStyle = CO[ AB_ON ]; CTX2D.beginPath(); CTX2D.rect(AB_X, AB_Y, AB_W, AB_H); CTX2D.closePath(); CTX2D.fill(); } function main() { //alert("main"); CONTAINER = document.getElementById('container'); CAN = document.createElement('canvas'); CAN.width = SW; CAN.height = SH; CAN.style.backgroundColor = '#000000'; CAN.style.width = "100%"; CAN.style.height = "100%"; CONTAINER.appendChild(CAN); CTX2D = CAN.getContext('2d'); CTX2D.strokeStyle = '#FFFFFF'; CTX2D.fillRect(0, 0, SW, SH); // draw fullscreen button CTX2D.fillStyle = CO[0]; CTX2D.beginPath(); CTX2D.rect(FULLSCREEN_RECT.left, FULLSCREEN_RECT.top, FULLSCREEN_RECT.width, FULLSCREEN_RECT.height); CTX2D.closePath(); CTX2D.fill(); // touch events CAN.ontouchstart = OnTouchStart; CAN.ontouchend = OnTouchEnd; CAN.ontouchmove = OnTouchMove; // start video routine window.requestAnimationFrame(VideoRoutine); } function VideoRoutine(e) { DrawButtons(); window.requestAnimationFrame(VideoRoutine); } function Touch(e, on) { e.preventDefault(); const tl = e.changedTouches; const r = e.target.getBoundingClientRect(); const halfWidth = Cx((r.right - r.left) / 2); //let inLeft = 0, inRight = 0; for (let i = 0; i < tl.length; i++) { const x = Cx(tl[i].clientX - r.left); const y = Cy(tl[i].clientY - r.top); if (x < halfWidth) { // left: test against cross // test point / circle const dx = x - CROSS_X; const dy = y - CROSS_Y; const dist = Math.sqrt(dx * dx + dy * dy); CROSS_ON = 0 + ( dist <= CROSS_RAD && dist >= CROSS_RAD/4); UP_ON = DOWN_ON = LEFT_ON = RIGHT_ON = 0; if ( CROSS_ON && on ) { // test against lines const A = dy >= dx/2; const B = dy >= dx*2; const C = dy >= -dx*2; const D = dy >= -dx/2; DOWN_ON = 0+( A && D ); UP_ON = 0+( !A && !D ); LEFT_ON = 0+( !C && B ); RIGHT_ON = 0+( C && !B ); } } else { // right: test against AB AB_ON = 0; if (on) { // test point / AABB const dx = x - AB_X; const dy = y - AB_Y; AB_ON = 0 + (dx >= 0 && dx <= AB_W && dy >= 0 && dy <= AB_H); } } } } function OnTouchStart(e) { Touch(e, 1); } function OnTouchEnd(e) { Touch(e, 0); OnMouseUp(e); } function OnTouchMove(e) { Touch(e, 1); } function ToggleFullScreen() { if (!document.fullscreen) { CONTAINER.requestFullscreen(); } else { document.exitFullscreen(); } } function OnMouseUp(e) { const rec = e.target.getBoundingClientRect(); const tl = e.changedTouches; const fsr = FULLSCREEN_RECT; for (let i = 0; i < tl.length; i++) { const x = Cx(tl[i].clientX - rec.left); const y = Cy(tl[i].clientY - rec.top); // check fullscreen button const dx = x - fsr.left; const dy = y - fsr.top; if (dx >= 0 && dx < fsr.width && dy >= 0 && dy < fsr.height) { ToggleFullScreen(); } } }
Bon... testé les boutons A B, ça m'a l'air de fonctionner aussi.
Avant de cocher "résolu" il faut que je valide mon script en testant un truc qui bouge, voir si c'est maniable ou si mon calcul est tout pourri.Code:
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 // canvas dimensions var SW = 240; var SH = 160; // render zone var CONTAINER = null; var CAN = null; var CTX2D = null; // colors const CO = ['#0000FF', '#FF0000']; // left buttons zone: 8-directions cross const CROSS_RAD = 32; const CROSS_X = CROSS_RAD; const CROSS_Y = SH - CROSS_RAD; var LEFT_ON = 0; var RIGHT_ON = 0; var UP_ON = 0; var DOWN_ON = 0; // right buttons zone: A B const AB_RAD = CROSS_RAD; const AB_X = SW-AB_RAD; const AB_Y = CROSS_Y; var A_ON = 0; var B_ON = 0; // fullscreen button const FULLSCREEN_RECT = {left: SW - 16, width: 16, top: 0, height: 16}; // show txt function trace(s) { document.getElementById('tracer').innerHTML += s + '<br/>'; } // coordinates relative to canvas function Cx(x) { return x * CAN.width / CONTAINER.offsetWidth; } function Cy(y) { return y * CAN.height / CONTAINER.offsetHeight; } function DrawButtons() { // cross CTX2D.fillStyle = CO[ LEFT_ON ]; CTX2D.beginPath(); CTX2D.rect(CROSS_X - CROSS_RAD, CROSS_Y - 8, CROSS_RAD - 8, 16); CTX2D.closePath(); CTX2D.fill(); CTX2D.fillStyle = CO[ RIGHT_ON ]; CTX2D.beginPath(); CTX2D.rect(CROSS_X + 8, CROSS_Y - 8, CROSS_RAD - 8, 16); CTX2D.closePath(); CTX2D.fill(); CTX2D.fillStyle = CO[ UP_ON ]; CTX2D.beginPath(); CTX2D.rect(CROSS_X - 8, CROSS_Y - CROSS_RAD, 16, CROSS_RAD - 8); CTX2D.closePath(); CTX2D.fill(); CTX2D.fillStyle = CO[ DOWN_ON ]; CTX2D.beginPath(); CTX2D.rect(CROSS_X - 8, CROSS_Y + 8, 16, CROSS_RAD - 8); CTX2D.closePath(); CTX2D.fill(); // AB CTX2D.fillStyle = CO[ A_ON ]; CTX2D.beginPath(); CTX2D.arc(AB_X-AB_RAD/2, AB_Y+AB_RAD/2, AB_RAD/2, 0, Math.PI*2); CTX2D.closePath(); CTX2D.fill(); CTX2D.fillStyle = CO[ B_ON ]; CTX2D.beginPath(); CTX2D.arc(AB_X+AB_RAD/2, AB_Y-AB_RAD/2, AB_RAD/2, 0, Math.PI*2); CTX2D.closePath(); CTX2D.fill(); } function main() { CONTAINER = document.getElementById('container'); CAN = document.createElement('canvas'); CAN.width = SW; CAN.height = SH; CAN.style.backgroundColor = '#000000'; CAN.style.width = "100%"; CAN.style.height = "100%"; CONTAINER.appendChild(CAN); CTX2D = CAN.getContext('2d'); CTX2D.strokeStyle = '#FFFFFF'; CTX2D.fillRect(0, 0, SW, SH); // draw fullscreen button CTX2D.fillStyle = CO[0]; CTX2D.beginPath(); CTX2D.rect(FULLSCREEN_RECT.left, FULLSCREEN_RECT.top, FULLSCREEN_RECT.width, FULLSCREEN_RECT.height); CTX2D.closePath(); CTX2D.fill(); // touch events CAN.ontouchstart = OnTouchStart; CAN.ontouchend = OnTouchEnd; CAN.ontouchmove = OnTouchMove; // start video routine window.requestAnimationFrame(VideoRoutine); } function VideoRoutine(e) { DrawButtons(); window.requestAnimationFrame(VideoRoutine); } function Touch(e, on) { e.preventDefault(); const tl = e.changedTouches; const r = e.target.getBoundingClientRect(); const halfWidth = Cx((r.right - r.left) / 2); for (let i = 0; i < tl.length; i++) { const x = Cx(tl[i].clientX - r.left); const y = Cy(tl[i].clientY - r.top); if (x < halfWidth) { // left: test against cross const dx = x - CROSS_X; const dy = y - CROSS_Y; const dist = Math.sqrt(dx * dx + dy * dy); UP_ON = DOWN_ON = LEFT_ON = RIGHT_ON = 0; // test again circles if ( dist <= CROSS_RAD && dist >= CROSS_RAD/4 && on ) { // test against lines const A = dy >= dx/2; const B = dy >= dx*2; const C = dy >= -dx*2; const D = dy >= -dx/2; DOWN_ON = 0+( A && D ); UP_ON = 0+( !A && !D ); LEFT_ON = 0+( !C && B ); RIGHT_ON = 0+( C && !B ); } } else { // right: test against AB const dx = x - AB_X; const dy = y - AB_Y; A_ON = B_ON = 0; if (on && dx >= -AB_RAD && dx <= AB_RAD && dy >= -AB_RAD && dy <= AB_RAD ) { // test lines A_ON = 0+( dy >= -AB_RAD/2 + dx ); B_ON = 0+( dy <= AB_RAD/2 + dx ); } } } // conversion to key events } function OnTouchStart(e) { Touch(e, 1); } function OnTouchEnd(e) { Touch(e, 0); OnMouseUp(e); } function OnTouchMove(e) { Touch(e, 1); } function ToggleFullScreen() { if (!document.fullscreen) { CONTAINER.requestFullscreen(); } else { document.exitFullscreen(); } } function OnMouseUp(e) { const rec = e.target.getBoundingClientRect(); const tl = e.changedTouches; const fsr = FULLSCREEN_RECT; for (let i = 0; i < tl.length; i++) { const x = Cx(tl[i].clientX - rec.left); const y = Cy(tl[i].clientY - rec.top); // check fullscreen button const dx = x - fsr.left; const dy = y - fsr.top; if (dx >= 0 && dx < fsr.width && dy >= 0 && dy < fsr.height) { ToggleFullScreen(); } } }
La suite .....
Bon j'ai un foirage en non-fullscreen quand les doigts sortent du canvas. Faut que je teste les event touch sur document.
La suite .....
Bon alors si je mets les events sur document ça fait sauter preventDefault()... pff...
Ok j'ai trouvé il faut faire des addEventListener avec {passive:false}
Code:
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 // canvas dimensions var SW = 240; var SH = 160; // render zone var CONTAINER = null; var CAN = null; var CTX2D = null; // colors const CO = ['#0000FF', '#FF0000']; // left buttons zone: 8-directions cross const CROSS_RAD = 32; const CROSS_X = CROSS_RAD; const CROSS_Y = SH - CROSS_RAD; var LEFT_ON = 0; var RIGHT_ON = 0; var UP_ON = 0; var DOWN_ON = 0; // right buttons zone: A B const AB_RAD = CROSS_RAD; const AB_X = SW-AB_RAD; const AB_Y = CROSS_Y; var A_ON = 0; var B_ON = 0; // fullscreen button const FULLSCREEN_RECT = {left: SW - 16, width: 16, top: 0, height: 16}; // show txt function trace(s) { document.getElementById('tracer').innerHTML += s + '<br/>'; } // coordinates relative to canvas function Cx(x) { return x * CAN.width / CONTAINER.offsetWidth; } function Cy(y) { return y * CAN.height / CONTAINER.offsetHeight; } function DrawButtons() { // cross CTX2D.fillStyle = CO[ LEFT_ON ]; CTX2D.beginPath(); CTX2D.rect(CROSS_X - CROSS_RAD, CROSS_Y - 8, CROSS_RAD - 8, 16); CTX2D.closePath(); CTX2D.fill(); CTX2D.fillStyle = CO[ RIGHT_ON ]; CTX2D.beginPath(); CTX2D.rect(CROSS_X + 8, CROSS_Y - 8, CROSS_RAD - 8, 16); CTX2D.closePath(); CTX2D.fill(); CTX2D.fillStyle = CO[ UP_ON ]; CTX2D.beginPath(); CTX2D.rect(CROSS_X - 8, CROSS_Y - CROSS_RAD, 16, CROSS_RAD - 8); CTX2D.closePath(); CTX2D.fill(); CTX2D.fillStyle = CO[ DOWN_ON ]; CTX2D.beginPath(); CTX2D.rect(CROSS_X - 8, CROSS_Y + 8, 16, CROSS_RAD - 8); CTX2D.closePath(); CTX2D.fill(); // AB CTX2D.fillStyle = CO[ A_ON ]; CTX2D.beginPath(); CTX2D.arc(AB_X-AB_RAD/2, AB_Y+AB_RAD/2, AB_RAD/2, 0, Math.PI*2); CTX2D.closePath(); CTX2D.fill(); CTX2D.fillStyle = CO[ B_ON ]; CTX2D.beginPath(); CTX2D.arc(AB_X+AB_RAD/2, AB_Y-AB_RAD/2, AB_RAD/2, 0, Math.PI*2); CTX2D.closePath(); CTX2D.fill(); } function main() { CONTAINER = document.getElementById('container'); CAN = document.createElement('canvas'); CAN.width = SW; CAN.height = SH; CAN.style.backgroundColor = '#000000'; CAN.style.width = "100%"; CAN.style.height = "100%"; CONTAINER.appendChild(CAN); CTX2D = CAN.getContext('2d'); CTX2D.strokeStyle = '#FFFFFF'; CTX2D.fillRect(0, 0, SW, SH); // draw fullscreen button CTX2D.fillStyle = CO[0]; CTX2D.beginPath(); CTX2D.rect(FULLSCREEN_RECT.left, FULLSCREEN_RECT.top, FULLSCREEN_RECT.width, FULLSCREEN_RECT.height); CTX2D.closePath(); CTX2D.fill(); // touch events document.addEventListener('touchstart',OnTouchStart,{passive:false}); document.addEventListener('touchend',OnTouchEnd,{passive:false}); document.addEventListener('touchmove',OnTouchMove,{passive:false}); // start video routine window.requestAnimationFrame(VideoRoutine); } function VideoRoutine(e) { DrawButtons(); window.requestAnimationFrame(VideoRoutine); } function Touch(e, on) { e.preventDefault(); e.stopImmediatePropagation(); const tl = e.changedTouches; const r = CAN.getBoundingClientRect(); const halfWidth = Cx((r.right - r.left) / 2); for (let i = 0; i < tl.length; i++) { const x = Cx(tl[i].clientX - r.left); const y = Cy(tl[i].clientY - r.top); if (x < halfWidth) { // left: test against cross const dx = x - CROSS_X; const dy = y - CROSS_Y; const dist = Math.sqrt(dx * dx + dy * dy); UP_ON = DOWN_ON = LEFT_ON = RIGHT_ON = 0; // test again circles if ( dist <= CROSS_RAD && dist >= CROSS_RAD/4 && on ) { // test against lines const A = dy >= dx/2; const B = dy >= dx*2; const C = dy >= -dx*2; const D = dy >= -dx/2; DOWN_ON = 0+( A && D ); UP_ON = 0+( !A && !D ); LEFT_ON = 0+( !C && B ); RIGHT_ON = 0+( C && !B ); } } else { // right: test against AB const dx = x - AB_X; const dy = y - AB_Y; A_ON = B_ON = 0; if (on && dx >= -AB_RAD && dx <= AB_RAD && dy >= -AB_RAD && dy <= AB_RAD ) { // test lines A_ON = 0+( dy >= -AB_RAD/2 + dx ); B_ON = 0+( dy <= AB_RAD/2 + dx ); } } } // conversion to key events } function OnTouchStart(e) { Touch(e, 1); } function OnTouchEnd(e) { Touch(e, 0); OnMouseUp(e); } function OnTouchMove(e) { Touch(e, 1); } function ToggleFullScreen() { if (!document.fullscreen) { CONTAINER.requestFullscreen(); } else { document.exitFullscreen(); } } function OnMouseUp(e) { const rec = e.target.getBoundingClientRect(); const tl = e.changedTouches; const fsr = FULLSCREEN_RECT; for (let i = 0; i < tl.length; i++) { const x = Cx(tl[i].clientX - rec.left); const y = Cy(tl[i].clientY - rec.top); // check fullscreen button const dx = x - fsr.left; const dy = y - fsr.top; if (dx >= 0 && dx < fsr.width && dy >= 0 && dy < fsr.height) { ToggleFullScreen(); } } }
Bon... maintenant faudrait que je teste le truc avec un bonhomme qui saute et qui donne des coups de poing et des coups de pied.
Pour ça faut que je crée des events pseudo OnKeyDown/OnKeyUp avec un pseudo tableau de touches. Mais là je suis fatigué je crois que je le ferai demain.
Non il suffit de mettre dans le CSS touch-action:none; sur l'élément que tu veux traiter.Citation:
onpointerenter/onpointerover fonctionne avec la souris mais pas le touch
les event pointer ne permettent pas d'indifférencier souris et touch, ce sont bien deux input device différents
j'y arrive pas là je crois que je vais me contenter des events touch
C'est original comme approche ;)Citation:
J'ai repris le premier test en réduisant la zone de droite à 128x128 histoire de réduire au max le risque du bug,
bon j'ai décroché de la lecture de ton suivi ... de plus tu tires souvent de mauvaises conclusions :aie:Citation:
...
oui mais bon ... pas bien compris ... mais j'ai plutôt l'impression que tu pêches dans la vision globale de ce que tu veux faire !Citation:
Ok j'ai trouvé il faut faire des addEventListener avec {passive:false}
Bon courage !!!Citation:
Bon... maintenant faudrait que je teste le truc avec un bonhomme qui saute et qui donne des coups de poing et des coups de pied.
A quoi te servent donc ta « croix » et tes deux « poussoirs » :koi:Citation:
Pour ça faut que je crée des events pseudo OnKeyDown/OnKeyUp avec un pseudo tableau de touches.
Décidément j'ai du mal à suivre ...
Je me suis bêtement inspiré de la gameboy parce qu'il fallait bien que je démarre par quelque chose. Je sais que faire un genre de boussole aurait été mieux adapté qu'une croix pour les jeux smartphone, mais les jeux web doivent aussi être jouables sur desktop avec le clavier donc il faut qu'au final le programme raisonne avec des touches.
Je sais que je débute et que mon code n'est pas un bon exemple. Si tu as des meilleurs exemples de gameboy pad en touch javascript je suis preneur.
Bon, j'ai réussi à faire un rectangle qui marche, qui saute, qui donne des coups de poings et des coups de pied.
Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 <!DOCTYPE html> <!-- Click nbfs://nbhost/SystemFileSystem/Templates/Licenses/license-default.txt to change this license Click nbfs://nbhost/SystemFileSystem/Templates/Other/html.html to edit this template --> <html> <head> <title>TODO supply a title</title> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"> <script src="main.js"></script> <script src="Game.js"></script> </head> <body onLoad="main()"> <div align="center"> <div id="container" style="width:480px;height:320px;background-color:#0000FF;" ></div> <div id="tracer"></div> </div> </body> </html>
Code:
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 // canvas dimensions var SW = 240; var SH = 160; // render zone var CONTAINER = null; var CAN = null; var CTX2D = null; // colors const CO = ['#0000FF', '#FF0000']; // left buttons zone: 8-directions cross const CROSS_RAD = 32; const CROSS_X = CROSS_RAD; const CROSS_Y = SH - CROSS_RAD; var LEFT_ON = 0; var RIGHT_ON = 0; var UP_ON = 0; var DOWN_ON = 0; // right buttons zone: A B const AB_RAD = CROSS_RAD; const AB_X = SW-AB_RAD; const AB_Y = CROSS_Y; var A_ON = 0; var B_ON = 0; // fullscreen button const FULLSCREEN_RECT = {left: SW - 16, width: 16, top: 0, height: 16}; // deprecated keycodes const KEY_CODES = { ArrowUp:38, ArrowDown:40, ArrowLeft:37, ArrowRight:39, d:68, f:70 }; // show txt function trace(s) { document.getElementById('tracer').innerHTML += s + '<br/>'; } // coordinates relative to canvas function Cx(x) { return x * CAN.width / CONTAINER.offsetWidth; } function Cy(y) { return y * CAN.height / CONTAINER.offsetHeight; } function DrawButtons() { // cross CTX2D.fillStyle = CO[ LEFT_ON ]; CTX2D.beginPath(); CTX2D.rect(CROSS_X - CROSS_RAD, CROSS_Y - 8, CROSS_RAD - 8, 16); CTX2D.closePath(); CTX2D.fill(); CTX2D.fillStyle = CO[ RIGHT_ON ]; CTX2D.beginPath(); CTX2D.rect(CROSS_X + 8, CROSS_Y - 8, CROSS_RAD - 8, 16); CTX2D.closePath(); CTX2D.fill(); CTX2D.fillStyle = CO[ UP_ON ]; CTX2D.beginPath(); CTX2D.rect(CROSS_X - 8, CROSS_Y - CROSS_RAD, 16, CROSS_RAD - 8); CTX2D.closePath(); CTX2D.fill(); CTX2D.fillStyle = CO[ DOWN_ON ]; CTX2D.beginPath(); CTX2D.rect(CROSS_X - 8, CROSS_Y + 8, 16, CROSS_RAD - 8); CTX2D.closePath(); CTX2D.fill(); // AB CTX2D.fillStyle = CO[ A_ON ]; CTX2D.beginPath(); CTX2D.arc(AB_X-AB_RAD/2, AB_Y+AB_RAD/2, AB_RAD/2, 0, Math.PI*2); CTX2D.closePath(); CTX2D.fill(); CTX2D.fillStyle = CO[ B_ON ]; CTX2D.beginPath(); CTX2D.arc(AB_X+AB_RAD/2, AB_Y-AB_RAD/2, AB_RAD/2, 0, Math.PI*2); CTX2D.closePath(); CTX2D.fill(); } function DrawRyu() { const ryu = Game.ryu; CTX2D.fillStyle = '#FFFFFF'; CTX2D.beginPath(); // body CTX2D.rect( ryu.x-ryu.hW, ryu.y-ryu.hH, ryu.hW*2, ryu.hH*2); // punch if ( ryu.punchDelay ) { CTX2D.rect( ryu.x+ryu.flipX*32-ryu.hW, ryu.y-24, ryu.hW*2, 16 ); } if ( ryu.kickDelay ) { CTX2D.rect( ryu.x+ryu.flipX*32-ryu.hW, ryu.y+8, ryu.hW*2, 16 ); } CTX2D.closePath(); CTX2D.fill(); // punch } function main() { CONTAINER = document.getElementById('container'); CAN = document.createElement('canvas'); CAN.width = SW; CAN.height = SH; CAN.style.backgroundColor = '#000000'; CAN.style.width = "100%"; CAN.style.height = "100%"; CONTAINER.appendChild(CAN); CTX2D = CAN.getContext('2d'); // touch events document.addEventListener('touchstart',OnTouchStart,{passive:false}); document.addEventListener('touchend',OnTouchEnd,{passive:false}); document.addEventListener('touchmove',OnTouchMove,{passive:false}); //CAN.onmouseup = OnMouseUp; only works in desktop mode, cannot be mixed with touch events Game.init(); // start video routine window.requestAnimationFrame(VideoRoutine); } function VideoRoutine(e) { Game.routine(); // refresh background CTX2D.fillStyle = '#000000'; CTX2D.fillRect(0, 0, SW, SH); // draw fullscreen button CTX2D.fillStyle = CO[0]; CTX2D.beginPath(); CTX2D.rect(FULLSCREEN_RECT.left, FULLSCREEN_RECT.top, FULLSCREEN_RECT.width, FULLSCREEN_RECT.height); CTX2D.closePath(); CTX2D.fill(); // draw Ryu DrawRyu(); // draw paddle buttons DrawButtons(); window.requestAnimationFrame(VideoRoutine); } function Touch(e, on) { e.preventDefault(); e.stopImmediatePropagation(); // prepare key events let lastLeft = LEFT_ON; let lastRight = RIGHT_ON; let lastUp = UP_ON; let lastDown = DOWN_ON; let lastA = A_ON; let lastB = B_ON; // geometry test to update bools const tl = e.changedTouches; const r = CAN.getBoundingClientRect(); const halfWidth = Cx((r.right - r.left) / 2); for (let i = 0; i < tl.length; i++) { const x = Cx(tl[i].clientX - r.left); const y = Cy(tl[i].clientY - r.top); if (x < halfWidth) { // left: test against cross const dx = x - CROSS_X; const dy = y - CROSS_Y; const dist = Math.sqrt(dx * dx + dy * dy); UP_ON = DOWN_ON = LEFT_ON = RIGHT_ON = 0; // test again circles if ( dist <= CROSS_RAD && dist >= CROSS_RAD/4 && on ) { // test against lines const A = dy >= dx/2; const B = dy >= dx*2; const C = dy >= -dx*2; const D = dy >= -dx/2; DOWN_ON = 0+( A && D ); UP_ON = 0+( !A && !D ); LEFT_ON = 0+( !C && B ); RIGHT_ON = 0+( C && !B ); } } else { // right: test against AB const dx = x - AB_X; const dy = y - AB_Y; A_ON = B_ON = 0; if (on && dx >= -AB_RAD && dx <= AB_RAD && dy >= -AB_RAD && dy <= AB_RAD ) { // test lines A_ON = 0+( dy >= -AB_RAD/2 + dx ); B_ON = 0+( dy <= AB_RAD/2 + dx ); } } } // conversion to key events let ke = null; // cross ke = {keyCode:KEY_CODES['ArrowLeft'],key:'ArrowLeft'}; if ( !lastLeft && LEFT_ON ) { OnKeyDown( ke ); } if ( lastLeft && !LEFT_ON ) { OnKeyUp( ke ); } ke = {keyCode:KEY_CODES['ArrowRight'],key:'ArrowRight'}; if ( !lastRight && RIGHT_ON ) { OnKeyDown( ke ); } if ( lastRight && !RIGHT_ON ) { OnKeyUp( ke ); } ke = {keyCode:KEY_CODES['ArrowUp'],key:'ArrowUp'}; if ( !lastUp && UP_ON ) { OnKeyDown( ke ); } if ( lastUp && !UP_ON ) { OnKeyUp( ke ); } ke = {keyCode:KEY_CODES['ArrowDown'],key:'ArrowDown'}; if ( !lastDown && DOWN_ON ) { OnKeyDown( ke ); } if ( lastDown && !DOWN_ON ) { OnKeyUp( ke ); } // AB ke = {keyCode:KEY_CODES['d'],key:'d'}; if ( !lastA && A_ON ) { OnKeyDown( ke ); } if ( lastA && !A_ON ) { OnKeyUp( ke ); } ke = {keyCode:KEY_CODES['f'],key:'f'}; if ( !lastB && B_ON ) { OnKeyDown( ke ); } if ( lastB && !B_ON ) { OnKeyUp( ke ); } } // "key" events function resolveKeyCode( e ) { if ( e.keyCode !== undefined ) { return e.keyCode; } else if ( e.key !== undefined ) { return KEY_CODES[e.key]; } } function OnKeyDown( e ) { Game.onKeyDown( resolveKeyCode(e) ); } function OnKeyUp( e ) { Game.onKeyUp( resolveKeyCode(e) ); OnMouseUp(e); } function OnTouchStart(e) { Touch(e, 1); } function OnTouchEnd(e) { Touch(e, 0); OnMouseUp(e); } function OnTouchMove(e) { Touch(e, 1); } function ToggleFullScreen() { if (!document.fullscreen) { CONTAINER.requestFullscreen(); } else { document.exitFullscreen(); } } function OnMouseUp(e) { const rec = e.target.getBoundingClientRect(); const tl = e.changedTouches; const fsr = FULLSCREEN_RECT; for (let i = 0; i < tl.length; i++) { const x = Cx(tl[i].clientX - rec.left); const y = Cy(tl[i].clientY - rec.top); // check fullscreen button const dx = x - fsr.left; const dy = y - fsr.top; if (dx >= 0 && dx < fsr.width && dy >= 0 && dy < fsr.height) { ToggleFullScreen(); } } }
Code:
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 // static class to simulate a pseudo-game function Game (){} // key table Game.keyBuffer = new ArrayBuffer(256); Game.keyTable = new Uint8Array(Game.keyBuffer); Game.ryu = { x:SW/2, y:SH/2, speedY:0, hW:16, hH:32, flipX:1, onFloor:0, punchDelay:0, kickDelay:0 }; Game.floorY = 140; Game.init = function() { }; Game.routine = function() { const ryu = Game.ryu; // move Ryu along X-Axis const speedX = 2 * ( Game.keyTable[39]-Game.keyTable[37] ); if ( speedX > 0 ) { ryu.flipX = 1; } if ( speedX < 0 ) { ryu.flipX = -1; } ryu.x += speedX ; if ( ryu.x < ryu.hW ) { ryu.x = ryu.hW; } if ( ryu.x > SW-ryu.hW ) { ryu.x = SW-ryu.hW; } // gravity if (!ryu.onFloor) { ryu.speedY ++; ryu.y += ryu.speedY; } if ( ryu.y + ryu.hH >= Game.floorY ) { ryu.y = Game.floorY - ryu.hH; ryu.onFloor = 1; } // punch-kick delays if ( ryu.punchDelay > 0 ) { ryu.punchDelay--; } if ( ryu.kickDelay > 0 ) { ryu.kickDelay--; } }; Game.onKeyDown = function(i) { Game.keyTable[i]=1; const ryu = Game.ryu; // start jump if ( i === 38 ) { ryu.speedY = -12; ryu.onFloor = 0; } // start kick or punch if ( i === 68 ) { ryu.kickDelay = 16; } if ( i === 70 ) { ryu.punchDelay = 16; } }; Game.onKeyUp = function(i) { Game.keyTable[i]=0; };
Maintenant pour finir ce test il faut que je programme l'alternance desktop/smartphone histoire que ça soit également géré par les touches du clavier.
Je vous donne le code du test final, on ne sait jamais, si ça peut intéresser des gens qui cherchent à faire le même genre de trucs. Mon code n'est pas un exemple, c'est vraiment juste une improvisation de tests d'alternance desktop/smartphone, j'ai juste trouvé quelques idées. Mais pour intégrer ça dans un environnement de jeu opérant il faut tout reprogrammer en suivant la structure de votre framework.
Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 <!DOCTYPE html> <html> <head> <title>TODO supply a title</title> <meta charset="UTF-8"> <script src="main.js"></script> <script src="Game.js"></script> </head> <body onLoad="main()"> <div align="center"> <div id="container" style="width:720px;height:480px;background-color:#0000FF;" > <canvas id="screen" width="240" height="160" style="width:100%;height:100%;background-color:#000000"></canvas> </div> <div id="tracer" style="font-size:72px;"></div> </div> </body> </html>
Script main.js:
Code:
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 // detect touch screen var TOUCH = false; // canvas dimensions var SW = 240; var SH = 160; // render zone var CONTAINER = null; var CAN = null; var CTX2D = null; // colors const CO = ['#0000FF', '#FF0000']; // left buttons zone: 8-directions cross const CROSS_RAD = 32; const CROSS_X = CROSS_RAD; const CROSS_Y = SH - CROSS_RAD; var LEFT_ON = 0; var RIGHT_ON = 0; var UP_ON = 0; var DOWN_ON = 0; // right buttons zone: A B const AB_RAD = CROSS_RAD; const AB_X = SW - AB_RAD; const AB_Y = CROSS_Y; var A_ON = 0; var B_ON = 0; // fullscreen button const FULLSCREEN_RECT = {left: SW - 32, width: 32, top: 0, height: 32}; // deprecated keycodes const KEY_CODES = { ArrowUp: 38, ArrowDown: 40, ArrowLeft: 37, ArrowRight: 39, d: 68, f: 70 }; // show txt function trace(s) { document.getElementById('tracer').innerHTML += s + '<br/>'; } // coordinates relative to canvas function Cx(x) { return x * CAN.width / CONTAINER.offsetWidth; } function Cy(y) { return y * CAN.height / CONTAINER.offsetHeight; } function DrawButtons() { // cross CTX2D.fillStyle = CO[ LEFT_ON ]; CTX2D.beginPath(); CTX2D.rect(CROSS_X - CROSS_RAD, CROSS_Y - 8, CROSS_RAD - 8, 16); CTX2D.closePath(); CTX2D.fill(); CTX2D.fillStyle = CO[ RIGHT_ON ]; CTX2D.beginPath(); CTX2D.rect(CROSS_X + 8, CROSS_Y - 8, CROSS_RAD - 8, 16); CTX2D.closePath(); CTX2D.fill(); CTX2D.fillStyle = CO[ UP_ON ]; CTX2D.beginPath(); CTX2D.rect(CROSS_X - 8, CROSS_Y - CROSS_RAD, 16, CROSS_RAD - 8); CTX2D.closePath(); CTX2D.fill(); CTX2D.fillStyle = CO[ DOWN_ON ]; CTX2D.beginPath(); CTX2D.rect(CROSS_X - 8, CROSS_Y + 8, 16, CROSS_RAD - 8); CTX2D.closePath(); CTX2D.fill(); // AB CTX2D.fillStyle = CO[ A_ON ]; CTX2D.beginPath(); CTX2D.arc(AB_X - AB_RAD / 2, AB_Y + AB_RAD / 2, AB_RAD / 2, 0, Math.PI * 2); CTX2D.closePath(); CTX2D.fill(); CTX2D.fillStyle = CO[ B_ON ]; CTX2D.beginPath(); CTX2D.arc(AB_X + AB_RAD / 2, AB_Y - AB_RAD / 2, AB_RAD / 2, 0, Math.PI * 2); CTX2D.closePath(); CTX2D.fill(); } function DrawRyu() { const ryu = Game.ryu; CTX2D.fillStyle = '#FFFFFF'; CTX2D.beginPath(); // body CTX2D.rect(ryu.x - ryu.hW, ryu.y - ryu.hH, ryu.hW * 2, ryu.hH * 2); // punch-kick if (ryu.punchDelay) { CTX2D.rect(ryu.x + ryu.flipX * 32 - ryu.hW, ryu.y - 24, ryu.hW * 2, 16); } if (ryu.kickDelay) { CTX2D.rect(ryu.x + ryu.flipX * 32 - ryu.hW, ryu.y + 8, ryu.hW * 2, 16); } CTX2D.closePath(); CTX2D.fill(); } function main() { TOUCH = ("ontouchmove" in document.documentElement); CONTAINER = document.getElementById('container'); CAN = document.getElementById('screen'); CTX2D = CAN.getContext('2d'); // touch events if (TOUCH) { document.addEventListener('touchstart', OnTouchStart, {passive: false}); document.addEventListener('touchend', OnTouchEnd, {passive: false}); document.addEventListener('touchmove', OnTouchMove, {passive: false}); } else { CAN.onmouseup = OnMouseUp; document.onkeydown = OnKeyDown; document.onkeyup = OnKeyUp; } Game.init(); // start video routine window.requestAnimationFrame(VideoRoutine); } function VideoRoutine(e) { Game.routine(); // refresh background CTX2D.fillStyle = '#000000'; CTX2D.fillRect(0, 0, SW, SH); // draw fullscreen button CTX2D.fillStyle = CO[0]; CTX2D.beginPath(); CTX2D.rect(FULLSCREEN_RECT.left, FULLSCREEN_RECT.top, FULLSCREEN_RECT.width, FULLSCREEN_RECT.height); CTX2D.closePath(); CTX2D.fill(); // draw Ryu DrawRyu(); // draw paddle buttons or keys manual if ( TOUCH ) { DrawButtons(); } else { CTX2D.font = "16px lucida console"; CTX2D.fillStyle ='#0000FF'; CTX2D.fillText(" Move: arrows", 0, SH-48); CTX2D.fillText(" Punch: F", 0, SH-32); CTX2D.fillText(" Kick: D", 0, SH-16); } window.requestAnimationFrame(VideoRoutine); } function Touch(e, on) { e.preventDefault(); e.stopImmediatePropagation(); // prepare key events let lastLeft = LEFT_ON; let lastRight = RIGHT_ON; let lastUp = UP_ON; let lastDown = DOWN_ON; let lastA = A_ON; let lastB = B_ON; // geometry test to update bools const tl = e.changedTouches; const r = CAN.getBoundingClientRect(); const halfWidth = Cx((r.right - r.left) / 2); for (let i = 0; i < tl.length; i++) { const x = Cx(tl[i].clientX - r.left); const y = Cy(tl[i].clientY - r.top); if (x < halfWidth) { // left: test against cross const dx = x - CROSS_X; const dy = y - CROSS_Y; const dist = Math.sqrt(dx * dx + dy * dy); UP_ON = DOWN_ON = LEFT_ON = RIGHT_ON = 0; // test again circles if (dist <= CROSS_RAD && dist >= CROSS_RAD / 4 && on) { // test against lines const A = dy >= dx / 2; const B = dy >= dx * 2; const C = dy >= -dx * 2; const D = dy >= -dx / 2; DOWN_ON = 0 + (A && D); UP_ON = 0 + (!A && !D); LEFT_ON = 0 + (!C && B); RIGHT_ON = 0 + (C && !B); } } else { // right: test against AB const dx = x - AB_X; const dy = y - AB_Y; A_ON = B_ON = 0; if (on && dx >= -AB_RAD && dx <= AB_RAD && dy >= -AB_RAD && dy <= AB_RAD) { // test lines A_ON = 0 + (dy >= -AB_RAD / 2 + dx); B_ON = 0 + (dy <= AB_RAD / 2 + dx); } } } // conversion to key events let ke = null; // cross ke = {keyCode: KEY_CODES['ArrowLeft'], key: 'ArrowLeft'}; if (!lastLeft && LEFT_ON) { KeyDown(ke); } if (lastLeft && !LEFT_ON) { KeyUp(ke); } ke = {keyCode: KEY_CODES['ArrowRight'], key: 'ArrowRight'}; if (!lastRight && RIGHT_ON) { KeyDown(ke); } if (lastRight && !RIGHT_ON) { KeyUp(ke); } ke = {keyCode: KEY_CODES['ArrowUp'], key: 'ArrowUp'}; if (!lastUp && UP_ON) { KeyDown(ke); } if (lastUp && !UP_ON) { KeyUp(ke); } ke = {keyCode: KEY_CODES['ArrowDown'], key: 'ArrowDown'}; if (!lastDown && DOWN_ON) { KeyDown(ke); } if (lastDown && !DOWN_ON) { KeyUp(ke); } // AB ke = {keyCode: KEY_CODES['d'], key: 'd'}; if (!lastA && A_ON) { KeyDown(ke); } if (lastA && !A_ON) { KeyUp(ke); } ke = {keyCode: KEY_CODES['f'], key: 'f'}; if (!lastB && B_ON) { KeyDown(ke); } if (lastB && !B_ON) { KeyUp(ke); } } // "key" events function resolveKeyCode(e) { if (e.keyCode !== undefined) { return e.keyCode; } else if (e.key !== undefined) { return KEY_CODES[e.key]; } } function KeyDown(e) { Game.onKeyDown(resolveKeyCode(e)); } function KeyUp(e) { Game.onKeyUp(resolveKeyCode(e)); } function OnTouchStart(e) { Touch(e, 1); } function OnTouchEnd(e) { Touch(e, 0); TouchFullscreenButton(e); } function OnTouchMove(e) { Touch(e, 1); } function ToggleFullScreen() { if (!document.fullscreen) { CONTAINER.requestFullscreen(); } else { document.exitFullscreen(); } } function TouchFullscreenButton(e) { const rec = e.target.getBoundingClientRect(); const tl = e.changedTouches; const fsr = FULLSCREEN_RECT; for (let i = 0; i < tl.length; i++) { const x = Cx(tl[i].clientX - rec.left); const y = Cy(tl[i].clientY - rec.top); // check fullscreen button const dx = x - fsr.left; const dy = y - fsr.top; if (dx >= 0 && dx < fsr.width && dy >= 0 && dy < fsr.height) { ToggleFullScreen(); } } } function OnMouseUp(e) { const rec = e.target.getBoundingClientRect(); const tl = e.changedTouches; const fsr = FULLSCREEN_RECT; const x = Cx( e.clientX - rec.left ); const y = Cy( e.clientY - rec.top ); // check fullscreen button const dx = x - fsr.left ; const dy = y - fsr.top ; if (dx >= 0 && dx < fsr.width && dy >= 0 && dy < fsr.height) { ToggleFullScreen(); } } function OnKeyDown(e) { e.preventDefault(); e.stopImmediatePropagation(); Game.onKeyDown(resolveKeyCode(e)); } function OnKeyUp(e) { e.preventDefault(); e.stopImmediatePropagation(); Game.onKeyUp(resolveKeyCode(e)); }
Script Game.js
Code:
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 // static class to simulate a pseudo-game function Game (){} // key table Game.keyBuffer = new ArrayBuffer(256); Game.keyTable = new Uint8Array(Game.keyBuffer); Game.ryu = { x:SW/2, y:SH/2, speedY:0, hW:16, hH:32, flipX:1, onFloor:0, punchDelay:0, kickDelay:0 }; Game.floorY = 140; Game.init = function() { }; Game.routine = function() { const ryu = Game.ryu; // move Ryu along X-Axis const speedX = 2 * ( Game.keyTable[39]-Game.keyTable[37] ); if ( speedX > 0 ) { ryu.flipX = 1; } if ( speedX < 0 ) { ryu.flipX = -1; } ryu.x += speedX ; if ( ryu.x < ryu.hW ) { ryu.x = ryu.hW; } if ( ryu.x > SW-ryu.hW ) { ryu.x = SW-ryu.hW; } // gravity if (!ryu.onFloor) { ryu.speedY ++; ryu.y += ryu.speedY; } if ( ryu.y + ryu.hH >= Game.floorY ) { ryu.y = Game.floorY - ryu.hH; ryu.onFloor = 1; } // punch-kick delays if ( ryu.punchDelay > 0 ) { ryu.punchDelay--; } if ( ryu.kickDelay > 0 ) { ryu.kickDelay--; } }; Game.onKeyDown = function(i) { const ryu = Game.ryu; // start jump if ( i === 38 && ryu.onFloor && Game.keyTable[38] === 0 ) { ryu.speedY = -12; ryu.onFloor = 0; } // start kick or punch if ( i === 68 && Game.keyTable[68] === 0 ) { ryu.kickDelay = 16; } if ( i === 70 && Game.keyTable[70] === 0 ) { ryu.punchDelay = 16; } Game.keyTable[i]=1; }; Game.onKeyUp = function(i) { Game.keyTable[i]=0; };
A tester sur vos serveurs FTP et vos smartphones si ça vous intéresse. N'hésitez pas à me signaler les bugs en précisant le navigateur.