Day.png);">
Apprendre


Vous êtes
nouveau sur
Oniromancie?

Visite guidée
du site


Découvrir
RPG Maker

RM 95
RM 2000/2003
RM XP
RM VX/VX Ace
RM MV/MZ

Apprendre
RPG Maker

Tutoriels
Guides
Making-of

Dans le
Forum

Section Entraide

Sorties: Star Trek: Glorious Wolf - (...) / Sorties: Dread Mac Farlane - episode 3 / News: Plein d'images cools créées par (...) / Sorties: Star Trek: Glorious Wolf - (...) / Jeux: Final Fantasy 2.0 / Chat

Bienvenue
visiteur !




publicité RPG Maker!

Statistiques

Liste des
membres


Contact

Mentions légales

360 connectés actuellement

29189701 visiteurs
depuis l'ouverture

4752 visiteurs
aujourd'hui



Barre de séparation

Partenaires

Indiexpo

Akademiya RPG Maker

Blog Alioune Fall

Fairy Tail Constellations

Guelnika & E-magination

RPG Maker VX

Lumen

Alex d'Or

Tous nos partenaires

Devenir
partenaire



Input Ultimate 2.3

Gestion clavier, souris et manettes mais aussi vibrations, multijoueur et saisie de texte.

Script pour RPG Maker VX Ace
Ecrit par Zeus81
Publié par zeus81 (lui envoyer un message privé)
Signaler un script cassé

❤ 0

Auteur : Zeus81
Logiciel : RPG Maker XP, VX et VX Ace
Nombre de scripts : 1
Source : http://pastebin.com/LKd9hbDa

Fonctionnalités
Ce script permet de gérer toutes les touches du clavier comme les autres scripts du genre mais en beaucoup mieux et je dis ça sans aucune prétention, en plus d'être au summum de la performance il possède plusieurs fonctionnalités plus ou moins inédites, gestion de la souris avec curseur, sélection, double clic, roulette... gestion des manettes avec boutons analogiques et vibrations, gestion des jeux multijoueurs sur le clavier ou avec plusieurs manettes, outil de saisie de texte au clavier avancé.
Bref y'a plus aucun doute à avoir quant au choix de script de gestion des touches, c'est le meilleur sur tous les plans.

Donc, on peut configurer manuellement les touches du jeu dans le script (je vous laisse lire tout le blabla au début du script), mais le mieux c'est encore de laisser le joueur faire ça via un menu, ce qui demandera quelques notions de programmation bien sûr et peut peut-être être (hihi) compliqué donc si vous avez des questions hésitez quand même avant de les poser parce que j'en ai plein le cul mais j'essaierais d'y répondre.

Conditions d'utilisation
- Vous devez créditer l'auteur (Zeus81)
- Vous ne pouvez pas utiliser ce script pour des projets commerciaux.

Installation
A installer au-dessus de Main.

Utilisation
Tout est dans le script.

Version 2.3

Portion de code : Tout sélectionner

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
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
=begin
  Input Ultimate 2.3 by Zeus81
  Free for non-commercial use
  
  Pour simplement régler les touches sans vouloir en savoir plus, aller ligne 1471.
  
REFERENCES
  Input :
    Constantes :
      REPEAT : Permet de régler la façon dont la méthode repeat? fonctionne, ligne 1417.
      PLAYERS_MAX : Le nombre de joueurs gérés par le script, à configurer ligne 1424.
      KEYS_MAX : Définit une limite pour optimiser la mémoire, ligne 1425.
      Players : La liste des contrôles joueurs.
      Gamepads : La liste des manettes détectées.
    Méthodes :
      Input.update : A appeler une fois par frame pour tout mettre à jour.
      Input.refresh : Détecte les manettes connectées au PC.
      Input[i] : Retourne le contrôle du joueur i (commence à 0).
                 Le premier Player est fusionné avec le module Input
                 Faire Input.trigger?(k) équivaut à faire Input[0].trigger?(k)
      
  Device :
      Base commune à Player, Gamepad, Keyboard et Mouse
    Propriétés :
      enabled : Permet d'activer ou désactiver un contrôle.
                Par exemple si on fait un jeu multijoueur mais qu'on joue en solo
                on peut désactiver les autres joueurs pour optimiser les perfs.
                Par défaut tous les contrôles sont activés sauf la souris et les
                manettes non utilisées.
      ntrigger_max : Option de la fonction ntrigger? décrite plus en dessous.
                     C'est ce qui est utilisé pour les doubles clics de la souris.
                     Par défaut cette option est désactivée (égale à 0) sauf
                     pour la souris où elle est égale à 3 (pour les triples clic).
                     Cette limite sert à faire boucler les clics, par exemple là
                     si je fais 5 clics ça sera considéré comme un triple clic
                     suivi d'un double clic.
      ntrigger_time : Temps en nombre de frames pouvant s'écouler entre deux
                      clics pour être considérés comme une série de clics.
                      Si on met 0 ce temps sera le même que dans Windows. (Défaut)
    Méthodes :
      press?(*a) : Retourne true si la touche est pressée sinon false.
                   La fonction peut être utilisée de plusieurs façons :
                    Input.press?(Input::C)
                    Input.press?(:C)
                    Input.press?('C')
                    Input.press?(13)
                    Input::C.press?
                   Tout ceci revient au même, cela dit en terme de performance
                    Input::C.press? est deux fois plus rapide que les autres.
                   On peut aussi mettre plusieurs touches à la fois :
                    Input.press?(:A, :B, :C) = :A or :B or :C
                   En regroupant des touches dans un tableaux on inverse or/and :
                    Input.press?([:A, :B, :C]) = :A and :B and :C
                   On peut mélanger les deux :
                    Input.press?(:A, [:B, :C]) = :A or (:B and :C)
                   Et mettre plusieurs niveaux de tableaux :
                    Input.press?([:A, [:B, :C]]) = :A and (:B or :C)
                   En plus des tableaux on peut aussi utiliser des Range :
                    Input.press?(:A..:C) = Input.press?([:A, :B, :C])
                    Input.press?(*:A..:C) = Input.press?(:A, :B, :C)
                   Oui je sais, tout ça ne servira absolument à rien.
      trigger?(*a) : Retourne true si la touche vient d'être pressée.
                     Pour les arguments fonctionne comme press?
      release?(*a) : Retourne true si la touche vient d'être relâchée.
                     Pour les arguments fonctionne comme press?
      repeat?(*a) : Retourne true ou false selon le schéma de REPEAT
                    Pour les arguments fonctionne comme press?
      ntrigger?(n,*a) : Retourne true si la touche vient d'être pressée comme
                        trigger? mais en comptant le nombre de fois.
                        Mouse.ntrigger?(2, :Left) retournera true uniquement si
                        on fait un double clic, si ensuite on fait un troisième
                        clic seul Mouse.ntrigger?(3, :Left) retournera true.
                        n doit être inférieur ou égal à ntrigger_max
                        Pour les arguments fonctionne comme press?
      count(k) : Retourne le temps en nombre de frames depuis quand la touche k
                 est pressée, 0 si elle n'est pas pressée.
                 Comme pour le reste k peut être égal à Input::C, :C, 'C', 13.
                 Et on peut aussi écrire Input::C.count
      key(i) : Retourne la touche Key ayant pour id i.
               Ici aussi i peut être un symbole, string, nombre (:C, 'C', 13).
      capture_key(*exclude) : Si jamais vous faites un menu pour configurer les
                              touches utilisez cette fonction pour attendre
                              que le joueur appuie comme ceci :
                                until key = Keyboard.capture_key || Input.gamepad.capture_key
                                  Graphics.update
                                  Input.update
                                end
                              key sera un Keyboard_Key ou Gamepad_Key, vous pouvez
                              bien entendu les séparer si vous ne voulez que l'un
                              ou l'autre.
                              Protip, avant d'appeler cette méthode utilisez un
                              release? plutôt qu'un trigger? pour éviter que la
                              touche soit capturée. De même il vaut mieux
                              ensuite attendre que la touche capturée soit
                              relâchée avant de continuer, ce qui donne :
                                if Input::C.release?
                                  until key = Keyboard.capture_key || Input.gamepad.capture_key
                                    Graphics.update
                                    Input.update
                                  end
                                  while key and key.push?
                                    Graphics.update
                                    Input.update
                                  end
                                end
                              Vous pouvez aussi mettre en arguments des touches
                              que vous désirez ignorer.
      
  Player < Device :
      Pour les jeux multijoueur on y accède en utilisant Input[i]
      Pour simplifier les jeux solo le premier Player est fusionné avec Input :
        Input.trigger?(*a) = Input[0].trigger?(*a)
    Constantes :
      A, B, C, etc... : Les touches du jeu virtuelles (à ne pas confondre avec
                        les touches du clavier), à configurer ligne 1433.
                        Ce ne sont pas des nombres mais des objets de type Player_Key
                        ce qui permet de faire des chose comme : Input::C.press?
                        Pour les jeux multijoueurs on peut aussi faire :
                          Input::C[i].press? où i est l'id du joueur.
    Propriétés :
      id : Id du joueur. (lecture seule)
      gamepad_id : Id du gamepad, par défaut égal à l'id du joueur.
                   Pour que le joueur n'ai pas de gamepad, mettre la valeur -1.
      gamepad : Contrôleur Gamepad associé au joueur. (lecture seule)
    Méthodes :
      setup(h) : Configure la relation entre les touches virtuelles du jeu et
                 les touches réelles des clavier/manettes.
                 Nécessite un format particulier, voir ligne 1471.
      dir4() : Retourne la direction pressée, format 4 directions.
      dir8() : Retourne la direction pressée, format 8 directions.
      dir360() : Retourne la direction pressée sous forme d'un angle et une
                 pression (pourcentage entre 0 et 1).
                  angle, power = Input.dir360
                 A la base créé pour les joysticks analogiques comme la fonction
                 analog? celle-ci retourne des valeurs aux extrémités si utilisé
                 sans manette analogique.
      dirXY() : Retourne la direction pressée sous forme de deux axes entre -1 et 1.
                  x, y = Input.dirXY
                Si le stick est orienté vers la gauche x = -1, vers la droite x = 1.
                Si le stick est orienté vers le bas y = -1, vers le haut y = 1.
                Par contre attention, la portée d'un joystick n'est pas carrée
                (ni ronde d'ailleurs, c'est plus un carré aux bords arrondis)
                de ce fait si on oriente le stick vers bas gauche par exemple
                on aura pas x, y = -1, -1 mais plus x, y = -0.8, -0.8
      
  Gamepad < Device :
      Il y a trois types de gamepad, Multimedia_Gamepad pour les manettes
      standard, XBox360_Gamepad spécialement pour les manettes Xbox et
      No_Gamepad quand on a aucune manette, toutes ont les mêmes fonctions.
      La classe No_Gamepad est là juste pour qu'on ait pas à se soucier de savoir
      si un pad est branché ou pas avant d'utiliser ses fonctions.
      Par exemple si on veut utiliser la fonction vibrate! on l'utilise, si une
      manette xbox est branchée ça vibrera sinon ça fera rien, pas d'erreur.
    Constantes :
      AXIS_PUSH : Les joysticks analogiques ont une valeur de pression entre
                  0 et 32768 par direction.
                  Cette variable contient la valeur au delà de laquelle ces
                  touches seront considérés comme pressés si on utilise la
                  fonction press? par exemple.
                  Par défaut 16384 (soit 50%), à configurer ligne 679.
      AXIS_DEADZONE : La position de repos d'un joystick analogique (au milieu)
                      n'est pas très stable, par conséquent si on utilise la
                      fonction analog? on obtient jamais 0, une zone morte est
                      établie au centre du joystick pour pallier à ça.
                      Par défaut 6666 (soit 10%), à configurer ligne 679.
      TRIGGER_PUSH : Les gâchettes LT et RT des manettes XBox360 ont une valeur
                     de pression entre 0 et 255.
                     Cette variable contient la valeur au delà de laquelle ces
                     touches seront considérés comme pressés si on utilise la
                     fonction press? par exemple.
                     Par défaut 0, à configurer ligne 679.
      Button1, Button2, etc.. : Les touches standard des manettes, liste ligne 681.
                                On les utilise uniquement lors du setup des Player.
                                  Gamepad::Button1
      LB, RB, etc... : Les touches des manettes xbox, liste ligne 689.
                       On les utilise uniquement lors du setup des Player.
                        XBox360_Gamepad::A
                       Ça revient au même que d'utiliser les touches standard
                       c'est juste l'écriture qui change, utilisez celle que
                       vous préférez.
      
    Propriétés :
      unplugged : Retourne true si la manette est débranchée. (lecture seule)
                  Ça peut être utilisé pour détecter une perte de manette soudaine.
                  Si on a pas de manette depuis le départ ce n'est pas considéré
                  comme une manette débranchée mais comme une manette de type
                  No_Gamepad avec unplugged = false
      vibration : Permet d'activer ou pas les vibrations.
    Méthodes :
      analog?(*a) : Retourne un pourcentage entre 0 et 1 si la touche pressée est
                    analogique (sticks des manettes et gâchettes LT RT pour les
                    pads xbox) sinon retourne 0 ou 1.
                    Cette fonction est là pour les manettes cela dit on écrira
                    jamais : Input.gamepad.analog?(XBox360_Gamepad::AxisLY_0)
                    Mais plutôt : Input.analog?(Input::DOWN)
                    Les touches de la manette étant liées au setup du Player.
                    Pour les arguments fonctionne comme press?.
      vibrate!(id, speed, fade_in, duration, fade_out) :
                  Fait vibrer la manette, ne fait rien si les vibrations
                  sont désactivées ou que ce n'est pas une manette XBox360.
                  id = 0 ou 1, pour les moteurs gauche ou droite.
                       Ou sinon 2 pour les deux en même temps.
                  speed = pourcentage entre 0 et 1
                  fade_in = durée de la transition entre le niveau de vibration
                            en cours et celui désiré.
                  duration = durée de la vibration.
                  fade_out = durée de la transition vers 0 à la fin du temps.
                  Exemple :
                    Input.gamepad.vibrate!(2, 0.5, 50, 200, 50)
                  Les deux moteurs vibreront à 50% sur en tout 300 frames.
                  
  Keyboard < Device :
      Attention normalement vous ne devriez jamais utiliser le clavier directement.
      Pour créer des jeux il est préférable d'utiliser des touches virtuelles
      qui peuvent correspondre à plusieurs touches du clavier + des manettes en
      même temps et éventuellement être configurable par le joueur,
      donc utilisation directe du clavier à éviter.
      Pour ce qui est de la saisie de texte la classe Text_Entry_Box est là.
    Constantes :
      Escape, Enter, etc... : Les touches du clavier, voir la liste ligne 862.
                              Ce ne sont pas des nombres mais des objets de type
                              Keyboard_Key ce qui permet de faire des chose comme :
                                Keyboard::Enter.push?
    Méthodes :
      setup(*a) : Si toutefois vous étiez amené pour une raison ou une autre à
                  devoir malgré tout utiliser directement le clavier, il faudra
                  d'abord lui dire quelles touches mettre à jour.
                  Par défaut aucune n'est mise à jour parce que ça prendrait du
                  temps pour rien.
                  Comme pour le reste plusieurs écritures sont supportées :
                    Keyboard.setup(Keyboard::Enter, :Escape, 'A'..'Z', 1)
                  Pour désactiver la mise à jour des touches :
                    Keyboard.setup()
                  A chaque setup toutes les touches envoyées remplacent les
                  anciennes, elles ne s'ajoutent pas.
                  Cependant vous n'avez besoin de faire ça que si vous désirez
                  utiliser les fonctions press?, trigger?, release?, repeat?,
                  ntrigger? et count, les fonctions push?, toggle?, push!, release!
                  et toggle! si dessous peuvent être utilisées sur n'importe
                  quelle touche en permanence.
      push?(*a) : Fonctionne exactement comme la fonction press? mais en regardant
                  directement l'état du matériel donc un peu plus lentement.
                  A n'utiliser que dans le cas cité précédemment, si vous voulez
                  l'état press d'une touche du clavier sans vouloir passer par
                  le setup, sinon il est préférable d'utiliser press?
                  Vous pouvez aussi l'utiliser sur les constantes Key du clavier :
                    Keyboard::Escape.push?
      toggle?(*a) : Retourne true si la touche est verrouillée sinon false.
                    Le vérouillage est ce qui est utilisé pour les touches
                    Verr. Num, Verr. Maj et Verr. Défil pour savoir si elles
                    sont sur On ou Off, mais vous pouvez l'utiliser sur n'importe
                    quelle touche en fait.
                    Comme push? cette fonction regarde directement l'état du
                    matériel et peut être utilisée sans setup.
                    Vous pouvez aussi l'utiliser sur les constantes Key du clavier :
                      Keyboard::CapsLock.toggle?
                    Pour les arguments fonctionne comme press?
      push!(*a) : Appuie sur les touches du clavier à la place du joueur.
                  Les signaux sont envoyés directement à Windows donc attention.
                  Vous pouvez par exemple forcer le passage en plein écran :
                    Keyboard.push!(:Alt, :Enter)
                  Vous pouvez aussi l'utiliser sur les constantes Key du clavier :
                    Keyboard::Space.push!
                  Pour les arguments fonctionne comme press?
      release!(*a) : Relâche les touches du clavier.
                     Après avoir appeler push! il faut appeler release! pour que
                     le système comprenne qu'elle n'est pas appuyée en permanence.
                     Ce n'est pas automatique !
                     Donc pour finaliser le passage en mode plein écran il faut faire :
                      Keyboard.push!(:Alt, :Enter)
                      Keyboard.release!(:Alt, :Enter)
                     Vous pouvez aussi l'utiliser sur les constantes Key du clavier :
                      Keyboard::Space.release!
                     Pour les arguments fonctionne comme press?
      toggle!(*a) : Change l'état de verrouillage d'une touche.
                    Vous pouvez aussi l'utiliser sur les constantes Key du clavier :
                      Keyboard::Space.release!
                    Pour les arguments fonctionne comme press?
      key_name(k) : Retourne le nom de la touche dans la langue du système.
                    Comme pour press?, k peut être égal à Keyboard::W, :W, 'W', 87.
                    Par exemple : Keyboard.key_name(:Escape) # => "ECHAP"
                    Cependant les noms de toutes les touches ne sont pas forcément
                    bienvenus donc il est peut être préférable de s'organiser
                    soi-même une liste de noms manuellement.
                    Vous pouvez aussi l'utiliser sur les constantes Key du clavier :
                      Keyboard::Escape.name
      
  Mouse < Device :
      Par défaut la souris est désactivée, pour l'activer faites :
        Mouse.enabled = true
    Constantes :
      Left, Middle, Right, X1, X2, WheelUp, WheelDown :
        Les touches de la souris, j'ai tout mis inutile d'aller voir la liste ligne 990.
        Ce ne sont pas des nombres mais des objets de type Mouse_Key ce qui
        permet de faire des chose comme : Mouse::Left.click?
        Left, Middle, Right sont les clics gauche, milieu, droit.
        X1 et X2 sont les boutons sur les côtés de la souris (si y'en a).
        WheelUp et WheelDown pour la roulette ne répondent malheureusement pas
        parfaitement, à éviter dans un jeu du coup, d'ailleurs pour que ça marche
        un tant soit peu il faut mettre le Input.update avant le Graphics.update
    Propriétés :
      click_max : alias de ntrigger_max
                  Contrairement aux autres contrôles le click_max/ntrigger_max
                  de la souris est par défaut égal à 3.
      click_time : alias de ntrigger_time
      cursor : Le curseur de la souris, c'est un Sprite classique donc vous
               pouvez utiliser toutes les fonctions des sprites.
               Pour modifier le curseur par défaut voir ligne 1024.
      x : Raccourci de cursor.x pour la lecture.
          Vous pouvez aussi modifier manuellement la position de la souris.
            Mouse.x = 123
          Attention Mouse.cursor.x = 123 ne fonctionne pas.
      y : Raccourci de cursor.y pour la lecture.
          Vous pouvez aussi modifier manuellement la position de la souris.
            Mouse.y = 456
          Attention Mouse.cursor.y = 456 ne fonctionne pas.
      drag : Le rectangle de sélection utilise aussi un Sprite mais a un
             fonctionnement particulier.
             Il apparait automatiquement quand on maintient un clic gauche et
             déplace la souris, cependant par défaut il est désactivé.
             Si vous désirez changer l'apparence du rectangle de sélection sachez
             que c'est un Bitmap de 1x1 pixels, par défaut il est bleu transparent
             voir ligne 1032, mais on peut le changer à tout moment :
              Mouse.drag.bitmap.set_pixel(0, 0, Color.new(255, 0, 0, 128))
      drag_enabled = Permet d'activer/désactiver la sélection, par défaut désactivée.
                     Pour l'activer : Mouse.drag_enabled = true
      drag_x : Raccourci de drag.x (Lecture seule)
      drag_y : Raccourci de drag.y (Lecture seule)
      drag_width : Largeur de la sélection, équivalent de drag.zoom_x.to_i (Lecture seule)
      drag_height : Hauteur de la sélection, équivalent de drag.zoom_y.to_i (Lecture seule)
      drag_rect : Retourne Rect.new(drag_x, drag_y, drag_width, drag_height) (Lecture seule)
      drag_auto_clear : Si activé la sélection s'effacera automatiquement
                        dès lors qu'on relâche le clic gauche.
      drag_start_size : Nombre de pixels dont on doit déplacer la souris pour
                        faire apparaître le rectangle de sélection, par défaut 10.
    Méthodes :
      icon(s=nil, ox=0, oy=0) : Permet de changer l'apparence du curseur,
                                l'image doit se trouver dans le dossier picture,
                                l'extension est facultative.
                                  Mouse.icon("croix")
                                On peut éventuellement préciser un décalage vers
                                le centre du curseur si nécessaire, en comptant
                                à partir du coin haut gauche de l'image.
                                  Mouse.icon("croix", 4, 4)
                                Si on veut remettre le curseur par défaut :
                                  Mouse.icon()
      clip(*a) : Définit la zone dans laquelle la souris est libre de se mouvoir.
                 Il y a quatre façons d'utiliser cette fonction :
                  Mouse.clip(i) : Si i = 0, aucune limitation, la souris peut
                                  voguer librement sur tout l'écran. (Défaut)
                                  Si i = 1, la souris est bloquée dans la fenêtre
                                  du jeu, càd surface de jeu + barre de titre.
                                  Si i = 2, la souris est bloquée dans la surface
                                  de jeu, on ne peut plus aller sur la barre de titre.
                                  Déconseillé vu qu'on ne peut plus réduire/fermer
                                  le jeu ce qui peut vite devenir pénible.
                  Mouse.clip() : Idem que Mouse.clip(0).
                  Mouse.clip(x, y, w, h) : Définit une zone manuellement,
                                           le point 0, 0 correspond au coin
                                           haut gauche de la surface de jeu.
                  Mouse.clip(rect) : Idem mais avec un objet de type Rect.
      on?(*a) : Retourne true si la souris est dans la zone demandée.
                Il y a cinq façons d'utiliser cette fonction :
                  Mouse.on?() : vérifie si le curseur est dans la surface de jeu.
                  Mouse.on?(x, y) : vérifie si le curseur est sur le point x y.
                  Mouse.on?(x, y, r) : vérifie si le curseur est dans le cercle
                                       de centre x y et de rayon r.
                  Mouse.on?(x, y, w, h) : vérifie si le curseur est dans le
                                          rectangle aux coordonnées spécifiées.
                  Mouse.on?(rect) : Idem mais avec un objet de type Rect.
      drag_on?(*a) : Retourne true si la sélection est en contact avec la zone donnée.
                     Il y a quatre façons d'utiliser cette fonction :
                      Mouse.drag_on?(x, y) : vérifie si le point x y est compris
                                             dans la sélection.
                      Mouse.drag_on?(x, y, r) : vérifie si le cercle de centre x y
                                                et de rayon r entre en contact
                                                avec la sélection.
                      Mouse.drag_on?(x, y, w, h) : vérifie si le rectangle entre
                                                   en contact avec la sélection.
                      Mouse.drag_on?(rect) : Idem mais avec un objet de type Rect.
      drag_clear() : Efface la sélection.
      dragging?() : Retourne true si une sélection est en cours.
      swap_button(b) : Si b = true, inverse les clics gauches et droits,
                       si b = false, les remet à la normale.
      click?(k=Left) : Simple clic, équivalent de ntrigger?(1, k).
                       L'argument est facultatif et est le clic gauche par défaut.
                       La différence entre click? et trigger? est que si on fait
                       un double clic par exemple lors du deuxième clic trigger?
                       renverra true alors que click? false (et dclick? true).
                       Vous pouvez aussi l'utiliser sur les constantes Key de la souris :
                        Mouse::Left.click?
      dclick?(k=Left) : Double clic, équivalent de ntrigger?(2, k).
                        Vous pouvez aussi l'utiliser sur les constantes Key de la souris :
                          Mouse::Left.dclick?
      tclick?(k=Left) : Triple clic, équivalent de ntrigger?(3, k).
                        Vous pouvez aussi l'utiliser sur les constantes Key de la souris :
                          Mouse::Left.tclick?
      
  Key :
      Il y en a quatre types : Player_Key, Gamepad_Key, Keyboard_Key et Mouse_Key
      Certaines possèdent des fonctions en plus.
    Méthodes :
      to_s() : Retourne le nom de la constante.
                Input::DOWN.to_s # => "DOWN"
      to_i() : Retourne l'id de la touche.
                Input::DOWN.to_i # => 2
      push?(), toggle?(), press?(), trigger?(), release?(), repeat?(), analog?(),
      ntrigger?(n), count() : Toutes les fonctions décrites précédemment sont
                              utilisables directement sur les touches pour plus
                              d'efficacité :
                                Input::DOWN.press?
                              Cependant inutile d'appeler ces fonctions sur les
                              touches Gamepad_Key, ça ne marchera pas.
      name(), push!(), release!(), toggle!() : Fonctions supplémentaires des Keyboard_Key
      click?(), dclick?(), tclick?() : Fonctions supplémentaires des Mouse_Key
      [i] : Fonction supplémentaire des Player_Key pour le jeu multijoueur :
              Input::DOWN[0].trigger? # joueur 1
              Input::DOWN[1].trigger? # joueur 2
      
  Text_Entry_Box < Sprite
      Cette classe permet de saisir du texte au clavier, la souris est aussi
      supportée pour la sélection de texte.
      Text_Entry_Box est dérivée de Sprite et son affichage est automatisé.
      Vous pouvez utiliser toutes les fonctions de Sprite cependant les fonctions
      zoom, angle, mirror, src_rect ne seront pas compatibles avec la souris.
      Si la souris est activée et survole une boite de texte, l’icône changera
      automatiquement, vous pouvez modifier son apparence ligne 1180.
    Propriétés :
      enabled : Permet d'activer ou désactiver une boite de texte.
                Une boite désactivée ne peut plus avoir le focus.
      focus : L'état de focus actuel, une seule boite peut l'avoir à la fois.
      text : Permet de récupérer le texte entré.
      back_color : La couleur du fond, valeur par défaut ligne 1195.
                   Elle peut être modifiée à tout moment mais il faut ensuite
                   appeler refresh() pour mettre à jour le bitmap.
                    text_entry_box.back_color = Color.new(255, 0, 0)
      select_color : Couleur de la sélection, idem que back_color.
      allow_c : Liste des caractères autorisés sous forme de string.
                  text_entry_box.allow_c = "abcABC123"
                Si la liste est vide tous les caractères sont autorisés. (Défaut)
      select : Permet d'activer ou désactiver les sélections que ce soit avec la
               souris ou en maintenant la touche Maj.
               Activé par défaut, pour le désactiver : text_entry_box.select = false
      mouse : Permet d'activer ou désactiver les fonctionnalités de la souris.
              Activé par défaut, pour le désactiver : text_entry_box.mouse = false
              Il faut aussi que la souris elle même soit activée sinon ça sert à rien.
      case : Casse de caractère :
              text_entry_box.case = 0 # normal, sensible à la casse (Défaut)
              text_entry_box.case = 1 # downcase, les majuscules deviennent minuscules.
              text_entry_box.case = 2 # upcase, les minuscules deviennent majuscules.
      size : Le nombre de caractères actuel. (lecture seule)
      size_max : Le nombre de caractères maximum autorisé.
                 Si 0, pas de limite.
      width : Raccourci pour text_entry_box.bitmap.width (lecture seule)
      width_max : La taille maximum autorisée en pixels.
                  Si 0, pas de limite.
      height : Raccourci pour text_entry_box.bitmap.height (lecture seule)
      font : Raccourci pour text_entry_box.bitmap.font
    Méthodes :
      Text_Entry_Box.new(width, height, viewport=nil) :
          Crée une nouvelle instance de Text_Entry_Box
          On est obligé de préciser width et height qui sont utilisés pour créer
          le bitmap, viewport est facultatif.
            text_entry_box = Text_Entry_Box.new(100, 20)
            
      dispose : Supprime le sprite et le bitmap.
      update : A appeler une fois par frame pour mettre à jour la saisie de texte.
      refresh : A appeler après avoir modifié les propriétés ou le font du bitmap
                pour forcer la mise à jour.
      hover? : Retourne true si la souris survole la boite texte.
      focus! : Donne le focus à la boite texte, une seule boite peut avoir le
               focus à la fois, il est automatiquement retiré des autres.
               Cette fonction est automatiquement appelée quand on clique sur la
               boite texte, si la souris est activée bien sûr.
=end
 
class Object
  remove_const(:Input)
  def singleton_attach_methods(o) class << self; self end.attach_methods(o) end
  def self.attach_methods(o)
    @attached_methods ||= []
    for m in o.public_methods-(instance_methods-@attached_methods)
      define_method(m, &o.method(m))
      @attached_methods << m unless @attached_methods.include?(m)
    end
  end
end
 
class String; alias getbyte [] end if RUBY_VERSION == '1.8.1'
 
module Input
  class Key
    include Comparable
    attr_reader :o, :i, :s, :hash, :to_sym
    alias to_i i
    alias to_s s
    def initialize(i,o)
      @o, self.i, self.s = o, i, "#{self.class.name.split('::')[-1]}_#{i}"
    end
    def o=(o) @o, @hash = o, @i.hash^o.hash  end
    def i=(i) @i, @hash = i, i.hash^@o.hash  end
    def s=(s) @s, @to_sym = s, s.to_sym      end
    def <=>(o)       @i <=> o.to_i           end
    def succ()       self.class.new(@i+1,@o) end
    def count()      @o.get_count(@i)        end
    def push?()      @o.get_push(@i)         end
    def toggle?()    @o.get_toggle(@i)       end
    def press?()     @o.get_press(@i)        end
    def trigger?()   @o.get_trigger(@i)      end
    def release?()   @o.get_release(@i)      end
    def repeat?()    @o.get_repeat(@i)       end
    def ntrigger?(n) @o.get_ntrigger(n,@i)   end
    def analog?()    @o.get_analog(@i)       end
  end
  class Gamepad_Key < Key
    def initialize(i,o=Gamepad) super        end
  end
  class Keyboard_Key < Key
    def initialize(i,o=Keyboard) super       end
    def name()       @o.get_key_name(@i)     end
    def push!()      @o.push!(@i)            end
    def release!()   @o.release!(@i)         end
    def toggle!()    @o.toggle!(@i)          end
  end
  class Mouse_Key < Key
    def initialize(i,o=Mouse) super          end
    def click?()     ntrigger?(1)            end
    def dclick?()    ntrigger?(2)            end
    def tclick?()    ntrigger?(3)            end
  end
  class Player_Key < Key
    def [](i)        @players_keys[i]        end
    def initialize(i,o=Players[0])
      super
      @players_keys = Players.map {|p| k = dup; k.o = p; k}
    end
  end
  
  class Device
    GetDoubleClickTime = Win32API.new('user32', 'GetDoubleClickTime', '', 'i')
    attr_accessor :enabled, :ntrigger_max, :ntrigger_time
    def initialize(max)
      @enabled, @count, @release, @keys = true, Array.new(max,0), [], []
      @ntrigger_count, @ntrigger_last, @ntrigger_max = @count.dup, @count.dup, 0
      self.ntrigger_time = 0
    end
    def update
      return unless @enabled
      update_keys
      update_ntrigger if @ntrigger_max != 0
    end
    def update_keys
      @release.clear
      for i in @keys
        if    get_push(i)   ; @count[i] += 1
        elsif @count[i] != 0; @count[i]  = 0; @release << i
        end
      end
    end
    def update_ntrigger
      f = Graphics.frame_count
      for i in @keys
        if @count[i] == 1
          @ntrigger_count[i] %= @ntrigger_max
          @ntrigger_count[i] += 1
          @ntrigger_last[i] = f + @ntrigger_time
        elsif @ntrigger_last[i] == f
          @ntrigger_count[i] = 0
        end
      end
    end
    def capture_key(*exclude)
      exclude = keyarrayize(*exclude) unless exclude.empty?
      (@count.size-1).downto(0) {|i| return key(i) if !exclude.include?(i) and get_push(i)}
      nil
    end
    def get_count(i)      @count[i]                                                            end
    def get_push(i)       false                                                                end
    def get_toggle(i)     false                                                                end
    def get_press(i)      @count[i] != 0                                                       end
    def get_trigger(i)    @count[i] == 1                                                       end
    def get_release(i)    @release.include?(i)                                                 end
    def get_repeat(i)     (j=@count[i])>0 and REPEAT.any? {|w,f| break(f>0 && j%f==0) if j>=w} end
    def get_ntrigger(n,i) get_trigger(i) and @ntrigger_count[i] == n                           end
    def get_analog(i)     get_push(i) ? 1.0 : 0.0                                              end
    def count(k)          get_count(k2i(k))                                                           end
    def push?(*a)         a.any?{|i| enum?(i) ? i.all?{|j| push?(*j)}       : get_push(k2i(i))}       end
    def toggle?(*a)       a.any?{|i| enum?(i) ? i.all?{|j| toggle?(*j)}     : get_toggle(k2i(i))}     end
    def press?(*a)        a.any?{|i| enum?(i) ? i.all?{|j| press?(*j)}      : get_press(k2i(i))}      end
    def trigger?(*a)      a.any?{|i| enum?(i) ? i.all?{|j| trigger?(*j)}    : get_trigger(k2i(i))}    end
    def release?(*a)      a.any?{|i| enum?(i) ? i.all?{|j| release?(*j)}    : get_release(k2i(i))}    end
    def repeat?(*a)       a.any?{|i| enum?(i) ? i.all?{|j| repeat?(*j)}     : get_repeat(k2i(i))}     end
    def ntrigger?(n,*a)   a.any?{|i| enum?(i) ? i.all?{|j| ntrigger?(n,*j)} : get_ntrigger(n,k2i(i))} end
    def analog?(*a)
      a.each do |i|
        d = if enum?(i)
          sum = size = 0
          i.each {|j| sum, size = sum+analog?(*j), size+1}
          sum == 0 ? 0 : sum / size
        else get_analog(k2i(i))
        end
        return d if d != 0
      end
      0.0
    end
    def ntrigger_time=(i) @ntrigger_time = (i==0 ? GetDoubleClickTime.call *
                          Graphics.frame_rate / 1000 : i)  end
    def key(o)            self.class.key(o)                end
    def k2i(o)            self.class.k2i(o)                end
  private
    def enum?(o)          o.is_a?(Array) or o.is_a?(Range) end
    def keyarrayize(*a)
      a.flatten!
      a.map! {|o| o.is_a?(Range) ? o.to_a : o}.flatten!
      a.compact!
      a.map! {|k| k2i(k)}.uniq!
      a
    end
    def self.key(o) o.is_a?(Key) || o.is_a?(Integer) ? const_get(:Keys)[o.to_i] : const_get(o) end
    def self.k2i(o) o.is_a?(Key) ? o.i : o.is_a?(Integer) ? o : const_get(o).i                 end
  end
  
  class Player < Device
    attr_reader :id, :gamepad, :gamepad_id
    def initialize(id)
      super(KEYS_MAX)
      @id, @gamepad_id, @gamepad, @map = id, id, No_Gamepad.new, @count.map{[]}
    end
    def setup(h)
      @keys.clear
      @count.fill(0)
      @map.fill([])
      for i,a in h
        a=@map[i=k2i(i)] = a[0].map {|j| Gamepad.key(j).dup} + a[1].map {|j| Keyboard.key(j)}
        @keys << i unless a.empty?
      end
      self.gamepad_id += 0
    end
    def gamepad_id=(i)
      vibration, @gamepad.enabled = @gamepad.vibration, false
      @gamepad = (@gamepad_id = i) >= 0 && Gamepads[i] || No_Gamepad.new
      @gamepad.vibration = vibration
      Players.each {|p| p.gamepad.enabled = true}
      @map.each {|a| a.each {|k| k.o = @gamepad if k.is_a?(Gamepad_Key)}}
    end
    def get_push(i)   @map[i].any? {|k| k.push?}                              end
    def get_toggle(i) @map[i].any? {|k| k.toggle?}                            end
    def get_analog(i) @map[i].each {|k| d=k.analog?; return d if d != 0}; 0.0 end
    def dirXY
      return 0.0, 0.0 unless @enabled
      return RIGHT.analog?-LEFT.analog?, UP.analog?-DOWN.analog?
    end
    def dir360
      x, y = *dirXY
      return 0.0, 0.0 if x == 0 and y == 0
      return Math.atan2(y,x)*180/Math::PI, (w=Math.hypot(x,y))>1 ? 1.0 : w
    end
    def dir8
      d = 5
      d -= 3 if DOWN.press?
      d -= 1 if LEFT.press?
      d += 1 if RIGHT.press?
      d += 3 if UP.press?
      d == 5 ? 0 : d
    end
    def dir4
      case d = dir8
      when 1; DOWN.trigger? == (@last_dir==2) ? 2 : 4
      when 3; DOWN.trigger? == (@last_dir==2) ? 2 : 6
      when 7; UP.trigger?   == (@last_dir==8) ? 8 : 4
      when 9; UP.trigger?   == (@last_dir==8) ? 8 : 6
      else    @last_dir = d
      end
    end
  end
  
  class Gamepad < Device
    ::Gamepad = self
    AXIS_PUSH, AXIS_DEADZONE, TRIGGER_PUSH = 16384, 6666, 0
    Keys = Array.new(48) {|i| Gamepad_Key.new(i)}
    Button1 , Button2 , Button3 , Button4 , Button5 , Button6 , Button7 ,
    Button8 , Button9 , Button10, Button11, Button12, Button13, Button14,
    Button15, Button16, Button17, Button18, Button19, Button20, Button21,
    Button22, Button23, Button24, Button25, Button26, Button27, Button28,
    Button29, Button30, Button31, Button32, Axis1_0 , Axis1_1 , Axis2_0 ,
    Axis2_1 , Axis3_0 , Axis3_1 , Axis4_0 , Axis4_1 , Axis5_0 , Axis5_1 ,
    Axis6_0 , Axis6_1 , PovUp   , PovRight, PovDown , PovLeft = *Keys
    XKeys = Array.new(48) {|i| Gamepad_Key.new(i)}
    A, B, X, Y, LB, RB, LT, RT, BACK, START, LS, RS,
    n, n, n, n, n, n, n, n, n, n, n, n, n, n, n, n, n, n, n, n,
    AxisLX_0, AxisLX_1, AxisLY_1, AxisLY_0, AxisRX_0, AxisRX_1, AxisRY_1, AxisRY_0,
    n, n, n, n, DPadUp, DPadRight, DPadDown, DPadLeft = *XKeys
    constants.each {|s| k = const_get(s);  k.s = s.to_s if k.is_a?(Key)}
    
    attr_accessor :vibration
    attr_reader   :unplugged
    def initialize(id=nil)
      super(48)
      @id, @unplugged, @map, @vibration = id, false, @count.map{[]}, true
    end
    def get_push(i)
      return false unless @enabled and !@unplugged
      j, k = *@map[i]
      case j
      when :button ; button(k)
      when :pov    ; k.include?(pov)
      when :axis_0 ; axis_raw(k) < -AXIS_PUSH
      when :axis_1 ; axis_raw(k) > AXIS_PUSH-1
      when :trigger; trig_raw(k) > TRIGGER_PUSH
      else           false
      end
    end
    def get_analog(i)
      return 0.0 unless @enabled and !@unplugged
      j, k = *@map[i]
      case j
      when :button, :pov; super
      when :axis_0 ; (k=axis_pct(k)) < 0 ? -k : 0.0
      when :axis_1 ; (k=axis_pct(k)) > 0 ?  k : 0.0
      when :trigger; trig_pct(k)
      else           0.0
      end
    end
    def vibrate!(id, speed, fade_in, duration, fade_out) end
  private
    def axis_pct(i)
      (i=axis_raw(i)).abs <= AXIS_DEADZONE ? 0.0 :
      (i<0 ? i+AXIS_DEADZONE : i-AXIS_DEADZONE+1) / (32768.0-AXIS_DEADZONE)
    end
    def trig_pct(i) trig_raw(i) / 255.0 end
    def axis_raw(i) 0                   end
    def trig_raw(i) 0                   end
    def pov()       0                   end
    def button(i)   false               end
      
    singleton_attach_methods(@o = new)
    
    class No_Gamepad < Gamepad
      ::No_Gamepad = Input::No_Gamepad = self
      def get_push(i)   false end
      def get_analog(i) 0.0   end
    end
    
    class Multimedia_Gamepad < Gamepad
      ::Multimedia_Gamepad = Input::Multimedia_Gamepad = self
      JoyGetDevCaps = Win32API.new('winmm', 'joyGetDevCaps', 'ipi', 'i')
      JoyGetPosEx   = Win32API.new('winmm', 'joyGetPosEx'  , 'ip' , 'i')
      def initialize(id)
        super
        JoyGetDevCaps.call(id, devcaps="\0"*404, 404)
        @caps = Array.new(7) {|i| i<2 or devcaps.getbyte(96)[i-2]==1}
        @buffer = [52,255,0,0,0,0,0,0,0,0,0,0,0].pack('L13')
        @state = @buffer.unpack('L13')
        for k,v in {            Button1 =>[:button, 0], Button2 =>[:button, 1],
        Button3 =>[:button, 2], Button4 =>[:button, 3], Button5 =>[:button, 4],
        Button6 =>[:button, 5], Button7 =>[:button, 6], Button8 =>[:button, 7],
        Button9 =>[:button, 8], Button10=>[:button, 9], Button11=>[:button,10],
        Button12=>[:button,11], Button13=>[:button,12], Button14=>[:button,13],
        Button15=>[:button,14], Button16=>[:button,15], Button17=>[:button,16],
        Button18=>[:button,17], Button19=>[:button,18], Button20=>[:button,19],
        Button21=>[:button,20], Button22=>[:button,21], Button23=>[:button,22],
        Button24=>[:button,23], Button25=>[:button,24], Button26=>[:button,25],
        Button27=>[:button,26], Button28=>[:button,27], Button29=>[:button,28],
        Button30=>[:button,29], Button31=>[:button,30], Button32=>[:button,31],
        Axis1_0 =>[:axis_0, 0], Axis1_1 =>[:axis_1, 0], Axis2_0 =>[:axis_0, 1],
        Axis2_1 =>[:axis_1, 1], Axis3_0 =>[:axis_0, 2], Axis3_1 =>[:axis_1, 2],
        Axis4_0 =>[:axis_0, 3], Axis4_1 =>[:axis_1, 3], Axis5_0 =>[:axis_0, 4],
        Axis5_1 =>[:axis_1, 4], Axis6_0 =>[:axis_0, 5], Axis6_1 =>[:axis_1, 5],
        PovUp   =>[:pov,[31500,    0, 4500]], PovRight=>[:pov,[ 4500, 9000,13500]],
        PovDown =>[:pov,[13500,18000,22500]], PovLeft =>[:pov,[22500,27000,31500]]}
          @map[k.i] = v
        end
        update
      end
      def update
        return unless @enabled and !@unplugged = JoyGetPosEx.call(@id, @buffer) != 0
        @state.replace(@buffer.unpack('L13'))
        super
      end
    private
      def button(i)   @state[8][i] == 1                end
      def pov()       @caps[6] ? @state[10] : 0        end
      def axis_raw(i) @caps[i] ? @state[2+i]-32768 : 0 end
    end
    
    class XBox360_Gamepad < Gamepad
      ::XBox360_Gamepad = Input::XBox360_Gamepad = self
      Keys = XKeys
      XInputGetState = (Win32API.new(DLL='xinput1_3'  , 'XInputGetState', 'ip', 'i') rescue
                        Win32API.new(DLL='xinput1_2'  , 'XInputGetState', 'ip', 'i') rescue
                        Win32API.new(DLL='xinput1_1'  , 'XInputGetState', 'ip', 'i') rescue
                        Win32API.new(DLL='xinput9_1_0', 'XInputGetState', 'ip', 'i') rescue
                        DLL=nil)
      XInputSetState =  Win32API.new(DLL              , 'XInputSetState', 'ip', 'i') if DLL
      def initialize(id)
        super
        @buffer = "\0"*16
        @state = @buffer.unpack('LSC2s4')
        @vibration_state = Array.new(2) {[0,0,0,0,0,false]}
        for k,v in {
        A        =>[:button,12], B       =>[:button,13], X       =>[:button,14],
        Y        =>[:button,15], LB      =>[:button, 8], RB      =>[:button, 9],
        LT       =>[:trigger,0], RT      =>[:trigger,1], BACK    =>[:button, 5],
        START    =>[:button, 4], LS      =>[:button, 6], RS      =>[:button, 7],
        AxisLX_0 =>[:axis_0, 0], AxisLX_1=>[:axis_1, 0], AxisLY_1=>[:axis_1, 1],
        AxisLY_0 =>[:axis_0, 1], AxisRX_0=>[:axis_0, 2], AxisRX_1=>[:axis_1, 2],
        AxisRY_1 =>[:axis_1, 3], AxisRY_0=>[:axis_0, 3], DPadUp  =>[:button, 0],
        DPadRight=>[:button, 3], DPadDown=>[:button, 1], DPadLeft=>[:button, 2]}
          @map[k.i] = v
        end
        update
      end
      def update
        return unless @enabled and !@unplugged = XInputGetState.call(@id, @buffer) != 0
        @state.replace(@buffer.unpack('LSC2s4'))
        super
        update_vibration if @vibration
      end
      def update_vibration
        vibrate = false
        @vibration_state.each do |v|
          next unless v[5]
          last_v0 = v[0]
          if    v[2]>0; v[0] = (v[0]*(v[2]-=1)+v[1]) / (v[2]+1.0)
          elsif v[3]>0; v[0], v[3] = v[1], v[3]-1
          elsif v[4]>0; v[0] = v[0]*(v[4]-=1) / (v[4]+1.0)
          else          v[0], v[5] = 0, false
          end
          vibrate = true if last_v0 != v[0]
        end
        set_vibration if vibrate
      end
      def vibration=(b) vibrate!(2,0,0,0,0); super end
      def vibrate!(id, speed, fade_in, duration, fade_out)
        case id
        when 0, 1; @vibration_state[id][1,5] = [speed, fade_in, duration, fade_out, true]
        when 2   ; 2.times {|i| vibrate!(i, speed, fade_in, duration, fade_out)}
        end
      end
    private
      def button(i)   @state[1][i] == 1 end
      def axis_raw(i) @state[4+i]       end
      def trig_raw(i) @state[2+i]       end
      def set_vibration
        return unless @enabled and @vibration and !@unplugged
        XInputSetState.call(@id, [@vibration_state[0][0]*0xFFFF,
                                  @vibration_state[1][0]*0xFFFF].pack('S2'))
      end
    end
    
  end
  
  class Keyboard < Device
    ::Keyboard = self
    GetKeyboardState    = Win32API.new('user32'  , 'GetKeyboardState'   , 'p'       , 'i')
    getKeyNameText      = Win32API.new('user32'  , 'GetKeyNameTextW'    , 'ipi'     , 'i')
    mapVirtualKey       = Win32API.new('user32'  , 'MapVirtualKey'      , 'ii'      , 'i')
    SendInput           = Win32API.new('user32'  , 'SendInput'          , 'ipi'     , 'i')
    ToUnicode           = Win32API.new('user32'  , 'ToUnicode'          , 'iippii'  , 'i')
    WideCharToMultiByte = Win32API.new('kernel32', 'WideCharToMultiByte', 'iipipipp', 'i')
  
    Keys = Array.new(256) {|i| Keyboard_Key.new(i)}
    None, MouseL, MouseR, Cancel, MouseM, MouseX1, MouseX2, n, Back, Tab,
    LineFeed, n, Clear, Enter, n, n, Shift, Control, Alt, Pause, CapsLock,
    KanaMode, n, JunjaMode, FinalMode, KanjiMode, n, Escape, IMEConvert,
    IMENonConvert, IMEAccept, IMEModeChange, Space, PageUp, PageDown, End, Home,
    Left, Up, Right, Down, Select, Print, Execute, PrintScreen, Insert, Delete,
    Help, D0, D1, D2, D3, D4, D5, D6, D7, D8, D9, n, n, n, n, n, n, n, A, B, C,
    D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, LWin,
    RWin, Apps, n, Sleep, NumPad0, NumPad1, NumPad2, NumPad3, NumPad4, NumPad5,
    NumPad6, NumPad7, NumPad8, NumPad9, Multiply, Add, Separator, Subtract,
    Decimal, Divide, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, F13,
    F14, F15, F16, F17, F18, F19, F20, F21, F22, F23, F24, n, n, n, n, n, n, n,
    n, NumLock, Scroll, n, n, n, n, n, n, n, n, n, n, n, n, n, n, LShift,
    RShift, LControl, RControl, LAlt, RAlt, BrowserBack, BrowserForward,
    BrowserRefresh, BrowserStop, BrowserSearch, BrowserFavorites, BrowserHome,
    VolumeMute, VolumeDown, VolumeUp, MediaNextTrack, MediaPreviousTrack,
    MediaStop, MediaPlayPause, LaunchMail, SelectMedia, LaunchApplication1,
    LaunchApplication2, n, n, OemSemicolon, OemPlus, OemComma, OemMinus,
    OemPeriod, OemQuestion, OemTilde, n, n, n, n, n, n, n, n, n, n, n, n, n, n,
    n, n, n, n, n, n, n, n, n, n, n, n, OemOpenBrackets, OemPipe,
    OemCloseBrackets, OemQuotes, Oem8, n, n, OemBackslash, n, n, ProcessKey,
    n, Packet, n, n, n, n, n, n, n, n, n, n, n, n, n, n, Attn, Crsel, Exsel,
    EraseEof, Play, Zoom, NoName, Pa1, OemClear, Unknown = *Keys
    constants.each {|s| k = const_get(s);  k.s = s.to_s if k.is_a?(Key)}
    
    SCAN_CODE = Array.new(256) {|i| mapVirtualKey.call(i, 0)}
    (BrowserBack..LaunchApplication2).each {|k| SCAN_CODE[k.i] = 0}
    for k,code in  {Pause  =>0x0045, PageUp     =>0x0149, PageDown=>0x0151,
    End   =>0x014F, Home   =>0x0147, Left       =>0x014B, Up      =>0x0148,
    Right =>0x014D, Down   =>0x0150, PrintScreen=>0x0137, Insert  =>0x0152,
    Delete=>0x0153, LWin   =>0x015B, RWin       =>0x015C, Apps    =>0x015D,
    Divide=>0x0135, NumLock=>0x0145, RControl   =>0x011D, RAlt    =>0x0138}
      SCAN_CODE[k.i] = code
    end
    
    KEYS_NAME = Array.new(256) do |i|
      if getKeyNameText.call(SCAN_CODE[i]<<16, utf16="\0"*256, 256) > 0
        WideCharToMultiByte.call(65001, 0, utf16, -1, utf8="\0"*256, 256, 0, 0)
        utf8.delete("\0")
      else Keys[i].to_s
      end
    end
    
    TEXT_KEYS = [Space.i] + (D0.i..D9.i).to_a + (A.i..Z.i).to_a +
                (NumPad0.i..Divide.i).to_a + (146..150).to_a +
                (OemSemicolon.i..OemTilde.i).to_a + (OemOpenBrackets.i..245).to_a
    
    TEXT_ENTRY_KEYS = TEXT_KEYS + [Back.i,Left.i,Up.i,Right.i,Down.i,Delete.i]
    
    DEAD_KEYS = {
        '`' => {'a'=>'à', 'e'=>'è', 'i'=>'ì', 'o'=>'ò', 'u'=>'ù',
      ' '=>'`', 'A'=>'À', 'E'=>'È', 'I'=>'Ì', 'O'=>'Ò', 'U'=>'Ù'},
      
        '´' => {'a'=>'á', 'e'=>'é', 'i'=>'í', 'o'=>'ó', 'u'=>'ú', 'y'=>'ý',
      ' '=>'´', 'A'=>'Á', 'E'=>'É', 'I'=>'Í', 'O'=>'Ó', 'U'=>'Ú', 'Y'=>'Ý'},
      
        '^' => {'a'=>'â', 'e'=>'ê', 'i'=>'î', 'o'=>'ô', 'u'=>'û',
      ' '=>'^', 'A'=>'Â', 'E'=>'Ê', 'I'=>'Î', 'O'=>'Ô', 'U'=>'Û'},
      
        '¨' => {'a'=>'ä', 'e'=>'ë', 'i'=>'ï', 'o'=>'ö', 'u'=>'ü', 'y'=>'ÿ',
      ' '=>'¨', 'A'=>'Ä', 'E'=>'Ë', 'I'=>'Ï', 'O'=>'Ö', 'U'=>'Ü', 'y'=>'Ÿ'},
      
        '~' => {'a'=>'ã', 'o'=>'õ', 'n'=>'ñ',
      ' '=>'~', 'A'=>'Ã', 'O'=>'Õ', 'N'=>'Ñ'},
    }
    
    def initialize()         super(256); @buffer = "\0"*256                        end
    def get_push(i)          @enabled and @buffer.getbyte(i)[7] == 1               end
    def get_toggle(i)        @enabled and @buffer.getbyte(i)[0] == 1               end
    def get_key_name(i)      i.between?(0, 255) ? KEYS_NAME[i].dup : ''            end
    def key_name(k)          get_key_name(k2i(k))                                  end
    def push!(*a)            set_state(a, true)                                    end
    def release!(*a)         set_state(a, false)                                   end
    def toggle!(*a)          set_state(a, true); set_state(a, false)               end
    def text_entry()         start_text_entry unless @text_entry; @text_entry.dup  end
    def start_text_entry()   (@text_entry = ''; setup(@keys)) unless @text_entry   end
    def stop_text_entry()    (@text_entry = nil; setup(@user_keys)) if @text_entry end
    def swap_mouse_button(b) MouseL.i, MouseR.i = b ? 2 : 1, b ? 1 : 2             end
    def setup(*a)
      @count.fill(0)
      @keys = keyarrayize(@text_entry ? [@user_keys=a, TEXT_ENTRY_KEYS] : a)
    end
    def update
      return unless @enabled
      GetKeyboardState.call(@buffer)
      super
      update_text_entry if @text_entry
    end
    def update_text_entry
      @text_entry = ''
      for i in TEXT_KEYS
        next if !get_repeat(i) or ToUnicode.call(i, 0, @buffer, utf16="\0"*16, 8, 0)==0
        j = ToUnicode.call(i, 0, @buffer, utf16, 8, 0)
        WideCharToMultiByte.call(65001, 0, utf16, 1, utf8="\0"*4, 4, 0, 0)
        utf8.delete!("\0")
        if @dead_key
          a = DEAD_KEYS[@dead_key]
          @text_entry, @dead_key = (a && a[utf8]) || (@dead_key + utf8)
        else j == -1 ? @dead_key=utf8 : @text_entry=utf8
        end
        return
      end
    end
  private
    def set_state(keys, state)
      keys, inputs = keyarrayize(keys), ''
      keys.each {|i| inputs << [1,i,0,state ? 0 : 2,0,0].pack('LSSLLLx8')}
      SendInput.call(keys.size, inputs, 28)
    end
    
    singleton_attach_methods(@o = new)
    Keys.each {|k| k.o = @o}
    def self.o() @o end
  end
  
  class Mouse < Device
    ::Mouse = self
    ClipCursor      = Win32API.new('user32', 'ClipCursor'     , 'p'      , 'i')
    createCursor    = Win32API.new('user32', 'CreateCursor'   , 'iiiiipp', 'i')
    findWindow      = Win32API.new('user32', 'FindWindow'     , 'pp'     , 'i')
    GetClientRect   = Win32API.new('user32', 'GetClientRect'  , 'ip'     , 'i')
    GetCursorPos    = Win32API.new('user32', 'GetCursorPos'   , 'p'      , 'i')
    GetWindowRect   = Win32API.new('user32', 'GetWindowRect'  , 'ip'     , 'i')
    MapWindowPoints = Win32API.new('user32', 'MapWindowPoints', 'iipi'   , 'i')
    PeekMessage     = Win32API.new('user32', 'PeekMessage'    , 'piiii'  , 'i')
    SetClassLong    = Win32API.new('user32', 'SetClassLong'   , 'iii'    , 'i')
    SetCursorPos    = Win32API.new('user32', 'SetCursorPos'   , 'ii'     , 'i')
    
    Keys = Array.new(7) {|i| Mouse_Key.new(i)}
    Left, Middle, Right, X1, X2, WheelUp, WheelDown = *Keys
    constants.each {|s| k = const_get(s);  k.s = s.to_s if k.is_a?(Key)}
    
    HWND = findWindow.call('RGSS Player', 0)
    BlankCursor = createCursor.call(0, 0, 0, 1, 1, "\xFF", "\x00")
    Cache = (defined? RPG::Cache) ? RPG::Cache : ::Cache
    
    alias click_max   ntrigger_max
    alias click_max=  ntrigger_max=
    alias click_time  ntrigger_time
    alias click_time= ntrigger_time=
    attr_accessor :drag_enabled, :drag_auto_clear, :drag_start_size
    attr_reader   :cursor, :drag
    def initialize
      super(7)
      @map = @count.map{[]}
      for k,v in {Left    => [:button, Keyboard::MouseL],
                  Middle  => [:button, Keyboard::MouseM],
                  Right   => [:button, Keyboard::MouseR],
                  X1      => [:button, Keyboard::MouseX1],
                  X2      => [:button, Keyboard::MouseX2],
                  WheelUp => [:wheel, 1], WheelDown => [:wheel, -1]}
        @map[k.i] = v
      end
      @enabled, @ntrigger_max, @buffer, @keys = false, 3, "\0"*28, (0...7).to_a
      @drag_enabled, @drag_auto_clear, @drag_start_size = false, false, 10
      clip
      initialize_sprites
    end
    def initialize_sprites
      return if @cursor and !@cursor.disposed?
      @cursor, @drag = Sprite.new, Sprite.new
      @cursor.z = @drag.z = 0x7FFFFFFF
      @cursor.visible, @drag.visible = @enabled, @enabled && @drag_enabled
      @cursor.bitmap = @default_icon = Bitmap.new(8,8)
      @cursor.bitmap.fill_rect(0, 0, 3, 7, c=Color.new(0,0,0))
      @cursor.bitmap.fill_rect(0, 0, 7, 3, c)
      @cursor.bitmap.fill_rect(5, 5, 3, 3, c)
      @cursor.bitmap.fill_rect(1, 1, 1, 5, c.set(255,255,255))
      @cursor.bitmap.fill_rect(1, 1, 5, 1, c)
      @cursor.bitmap.fill_rect(6, 6, 1, 1, c)
      @drag.bitmap = Bitmap.new(1,1)
      @drag.bitmap.set_pixel(0, 0, c.set(0,0,255,128))
      drag_clear
    end
    def enabled=(enabled)
      initialize_sprites
      drag_clear unless @enabled = enabled
      SetClassLong.call(HWND, -12, @enabled ? BlankCursor : 0)
      @cursor.visible, @drag.visible = @enabled, @enabled && @drag_enabled
    end
    def drag_enabled=(drag_enabled)
      initialize_sprites
      drag_clear unless @drag_enabled = drag_enabled
      @drag.visible = @enabled && @drag_enabled
    end
    def update
      return unless @enabled
      super
      initialize_sprites
      update_cursor
      update_drag
      update_clip
      update_wheel
    end
    def update_cursor
      GetCursorPos.call(@buffer)
      MapWindowPoints.call(0, HWND, @buffer, 1)
      @cursor.update
      @cursor.x, @cursor.y = *@buffer.unpack('ll')
    end
    def update_drag
      return unless @drag_enabled
      @drag.update
      if Left.trigger?
        drag_clear
        @drag_start_point = [@cursor.x, @cursor.y]
      elsif @drag_start_point and Left.press?
        x, y = *@drag_start_point
        w, h = @cursor.x-x, @cursor.y-y
        if w == 0 then w = 1 elsif w < 0 then x -= w *= -1 end
        if h == 0 then h = 1 elsif h < 0 then y -= h *= -1 end
        if dragging? or w > @drag_start_size or h > @drag_start_size
          @drag.x, @drag.y, @drag.zoom_x, @drag.zoom_y = x, y, w, h
        end
      elsif @drag_auto_clear and Left.release?
        drag_clear
      end
    end
    def update_clip
      ClipCursor.call(@buffer) if case @clip
      when String; MapWindowPoints.call(HWND, 0, @buffer.replace(@clip), 2)
      when      1; GetWindowRect.call(HWND, @buffer)
      when      2; GetClientRect.call(HWND, @buffer)
                   MapWindowPoints.call(HWND, 0, @buffer, 2)
      end
    end
    def update_wheel
      @wheel_state = PeekMessage.call(@buffer,HWND,0x020A,0x020A,0)>0 ?
                     @buffer.getbyte(11)==0 ? 1 : -1 : 0
    end
    def on?(x=nil, y=nil, w=nil, h=nil)
      if !@enabled; false
      elsif h; @cursor.x.between?(x, x+w) and @cursor.y.between?(y, y+h)
      elsif w; Math.hypot(x-@cursor.x, y-@cursor.y) <= w
      elsif y; @cursor.x == x and @cursor.y == y
      elsif x; on?(x.x, x.y, x.width, x.height)
      else     GetClientRect.call(HWND, @buffer); on?(*@buffer.unpack('l4'))
      end
    end
    def drag_on?(x, y=nil, w=nil, h=nil)
      if !@enabled or !@drag_enabled; false
      elsif h
        x < @drag.x+drag_width  and @drag.x < x+w and
        y < @drag.y+drag_height and @drag.y < y+h
      elsif w
        sw, sh = drag_width/2, drag_height/2
        x, y = (x-@drag.x-sw).abs, (y-@drag.y-sh).abs
        x<=sw+w and y<=sh+w and (x<=sw or y<=sh or Math.hypot(x-sw,y-sh)<=w)
      elsif y
        x.between?(@drag.x, @drag.x+drag_width) and
        y.between?(@drag.y, @drag.y+drag_height)
      else drag_on?(x.x, x.y, x.width, x.height)
      end
    end
    def icon(s=nil, ox=0, oy=0) @cursor.bitmap, @cursor.ox, @cursor.oy =
                                s ? Cache.picture(s) : @default_icon, ox, oy end
    def clip(x=0, y=nil, w=0, h=0)
      ClipCursor.call(0)
      if x.is_a?(Rect); clip(x.x, x.y, x.width, x.height)
      else @clip = y ? [x, y, w+x, h+y].pack('l4x12') : x
      end
    end
    def click?(k=Left)  get_ntrigger(1, k2i(k))                           end
    def dclick?(k=Left) get_ntrigger(2, k2i(k))                           end
    def tclick?(k=Left) get_ntrigger(3, k2i(k))                           end
    def swap_button(b)  Keyboard.swap_mouse_button(b)                     end
    def x()             @cursor.x                                         end
    def x=(x)           set_pos(x, y)                                     end
    def y()             @cursor.y                                         end
    def y=(y)           set_pos(x, y)                                     end
    def dragging?()     @drag.zoom_x != 0                                 end
    def drag_x()        @drag.x                                           end
    def drag_y()        @drag.y                                           end
    def drag_width()    @drag.zoom_x.to_i                                 end
    def drag_height()   @drag.zoom_y.to_i                                 end
    def drag_rect()     Rect.new(drag_x, drag_y, drag_width, drag_height) end
    def drag_clear
      @drag_start_point = nil
      @drag.x = @drag.y = @drag.zoom_x = @drag.zoom_y = 0
    end
    def get_push(i)
      return false unless @enabled
      j, k = *@map[i]
      case j
      when :button; k.push?
      when :wheel ; k == @wheel_state
      else          false
      end
    end
    def get_toggle(i)
      return false unless @enabled
      j, k = *@map[i]
      case j
      when :button; k.toggle?
      else          false
      end
    end
  private
    def set_pos(x, y)
      @cursor.x, @cursor.y = x, y
      MapWindowPoints.call(HWND, 0, s=[x,y].pack('ll'), 1)
      SetCursorPos.call(*s.unpack('ll'))
    end
    
    singleton_attach_methods(@o = new)
    Keys.each {|k| k.o = @o}
    def self.o() @o end
  end
  
  class Text_Entry_Box < Sprite
    ::Text_Entry_Box = self
    SPECIAL_CHARS_CASE = {
      'à'=>'À', 'è'=>'È', 'ì'=>'Ì', 'ò'=>'Ò', 'ù'=>'Ù',
      'á'=>'Á', 'é'=>'É', 'í'=>'Í', 'ó'=>'Ó', 'ú'=>'Ú', 'ý'=>'Ý',
      'â'=>'Â', 'ê'=>'Ê', 'î'=>'Î', 'ô'=>'Ô', 'û'=>'Û',
      'ä'=>'Ä', 'ë'=>'Ë', 'ï'=>'Ï', 'ö'=>'Ö', 'ü'=>'Ü', 'ÿ'=>'Ÿ',
      'ã'=>'Ã',                     'õ'=>'Õ',                     'ñ'=>'Ñ',
    }
    def self.initialize
      @@boxes, @@last_icon = [], nil
      @@icon = [Bitmap.new(9,20), 4, 0] # [bmp, ox, oy]
      @@icon[0].fill_rect(0,  0, 9,  3, c=Color.new(0,0,0))
      @@icon[0].fill_rect(0, 17, 9,  3, c)
      @@icon[0].fill_rect(3,  3, 3, 14, c)
      @@icon[0].fill_rect(1,  1, 3,  1, c.set(255,255,255))
      @@icon[0].fill_rect(5,  1, 3,  1, c)
      @@icon[0].fill_rect(1, 18, 3,  1, c)
      @@icon[0].fill_rect(5, 18, 3,  1, c)
      @@icon[0].fill_rect(4,  2, 1, 16, c)
    end
    initialize
    attr_accessor :enabled, :mouse, :focus, :back_color, :select_color,
                  :text, :allow_c, :select, :case, :size_max, :width_max
    def initialize(width, height, viewport=nil)
      super(viewport)
      @back_color, @select_color = Color.new(0,0,0,0), Color.new(0,0,255,128)
      @text, @text_width, @allow_c = '', [], ''
      @enabled = @mouse = @select = true
      @case = @size_max = @width_max = @pos = @sel = @off = 0
      @text_chars = [] if RUBY_VERSION == '1.8.1'
      width = 640 if width > 640 and RUBY_VERSION == '1.9.2'
      self.bitmap = Bitmap.new(width, height)
      self.class.initialize if @@icon[0].disposed?
      @@boxes.delete_if {|s| s.disposed?}
      @focus = @@boxes.empty?
      @@boxes << self
    end
    def width()  bitmap.width                                      end
    def height() bitmap.height                                     end
    def font()   bitmap.font                                       end
    def font=(f) bitmap.font = f                                   end
    def hover?() Mouse.on?(x-ox, y-oy, width, height)              end
    def focus!() @@boxes.each {|s| s.focus = false}; @focus = true end
    def dispose
      super
      @@boxes.delete_if {|s| s.disposed?}
      Keyboard.stop_text_entry
      bitmap.dispose
    end
    def update
      super
      return unless @enabled
      update_mouse if @mouse
      return unless @focus
      if update_text_entry
        refresh
      elsif @mouse and (Mouse::WheelDown.press? or Mouse::WheelUp.press?)
        @off = Mouse::WheelDown.press? ? [@off-16, 0].max :
               [@off+16, text_width(0, size)+1-width].min
        draw_text_box
      elsif Graphics.frame_count % 20 == 0
        draw_cursor(Graphics.frame_count % 40 == 0)
      end
    end
    def refresh
      tag = "#{font.name}#{font.size}#{font.bold}#{font.italic}"
      self.text, @last_font = @text, tag if @last_font != tag
      min = [text_width(0,@pos)+16-width, text_width(0,size)+1-width].min
      max = [text_width(0,@pos)-16, 0].max
      @off = [min, [@off, max].min].max
      @sel = 0 unless @select
      draw_text_box
    end
  private
    def update_mouse
      if hover = hover? and !@@last_icon
        @@last_icon = [Mouse.cursor.bitmap, Mouse.cursor.ox, Mouse.cursor.oy]
        Mouse.cursor.bitmap, Mouse.cursor.ox, Mouse.cursor.oy = *@@icon
      elsif @last_hover != hover and !@last_hover = hover and @@last_icon
        Mouse.cursor.bitmap, Mouse.cursor.ox, Mouse.cursor.oy = *@@last_icon
        @@last_icon = nil
      end
      if @mouse_select
        @sel, @mouse_select = @sel+@pos, Mouse::Left.press?
        @sel -= @pos = get_pos(Mouse.x-x+ox+@off, true)
      elsif Mouse::Left.trigger? and hover
        @pos, @sel, @mouse_select = get_pos(Mouse.x-x+ox+@off, true), 0, true
        Mouse.drag_clear
        focus!
      end
    end
    def update_text_entry
      if @mouse_select
        return false if @last_pos == @pos and @last_sel == @sel
        @last_pos, @last_sel = @pos, @sel
      elsif @sel != 0 and (Keyboard::Back.trigger? or Keyboard::Delete.trigger?)
        @pos -= @sel *= -1 if @sel < 0
        self[@pos, @sel], @sel = '', 0
      elsif @pos != 0 and Keyboard::Back.repeat?
        self[@pos -= 1, 1] = ''
      elsif @pos != size and Keyboard::Delete.repeat?
        self[@pos, 1] = ''
      elsif @pos != 0 and Keyboard::Up.trigger?
        @sel, @pos = @select && Keyboard::Shift.push? ? @sel+@pos : 0, 0
      elsif @pos != size and Keyboard::Down.trigger?
        @sel, @pos = @select && Keyboard::Shift.push? ? @sel+@pos-size : 0, size
      elsif @pos != 0 and Keyboard::Left.repeat?
        @pos, @sel = @pos-1, @select && Keyboard::Shift.push? ? @sel+1 : 0
      elsif @pos != size and Keyboard::Right.repeat?
        @pos, @sel = @pos+1, @select && Keyboard::Shift.push? ? @sel-1 : 0
      elsif !Keyboard.text_entry.empty?
        need_refresh, allowed_chars = false,
          @case==1 ? downcase(@allow_c) : @case==2 ? upcase(@allow_c) : @allow_c
        for c in Keyboard.text_entry.split(//)
          break if @size_max != 0 and @size_max <= size
          c = @case==1 ? downcase(c) : @case==2 ? upcase(c) : c
          next unless allowed_chars.empty? or allowed_chars.include?(c)
          _text, _pos, _sel = @text.dup, @pos, @sel if @width_max != 0
          @pos -= @sel *= -1 if @sel < 0
          self[@pos, @sel], @pos, @sel = c, @pos+1, 0
          if @width_max != 0 and text_width(0, size) > @width_max
            self.text, @pos, @sel = _text, _pos, _sel
            break
          end
          need_refresh = true
        end
        return need_refresh
      else return false
      end
      return true
    end
    def draw_text_box
      bitmap.fill_rect(bitmap.rect, @back_color)
      draw_selection if @sel != 0
      draw_text_entry
      draw_cursor(true)
    end
    def draw_selection
      pos, sel = @sel < 0 ? @pos+@sel : @pos, @sel.abs
      x, w, h = text_width(0,pos)-@off, text_width(pos,sel), font.size+2
      bitmap.fill_rect(x, (height-h)/2, w, h, @select_color)
    end
    def draw_cursor(blink)
      color = blink ? font.color : @back_color
      x, h = text_width(0, @pos)-@off, font.size+2
      bitmap.fill_rect(x, (height-h)/2, 1, h, color)
    end
    def draw_text_entry()
      bitmap.draw_text(-@off, 0, 0xFFFF, height, @text)
    end
    def downcase(str)
      str = str.downcase
      SPECIAL_CHARS_CASE.each {|d,u| str.gsub!(u, d)}
      str
    end
    def upcase(str)
      str = str.upcase
      SPECIAL_CHARS_CASE.each {|d,u| str.gsub!(d, u)}
      str
    end
    def text_width(i, j)
      @text_width[i] ||= bitmap.text_size(self[0, i]).width
      @text_width[i+j] ||= bitmap.text_size(self[0, i+j]).width
      @text_width[i+j] - @text_width[i]
    end
    def get_pos(x, round=false)
      return 0 if x <= 0
      return size if x >= text_width(0, size)
      size.times do |i|
        if (w = text_width(0,i+1)) > x
          return i unless round
          w -= text_width(i,1) / 2
          return w > x ? i : i+1
        end
      end
    end
    if RUBY_VERSION == '1.9.2'
      alias normal_draw_text_entry draw_text_entry
      def draw_text_entry
        if text_width(0, size) > 640
          a, b = get_pos(@off), get_pos(@off+width)
          b += 1 if b != size and text_width(a, b+1-a) <= 640
          a += 1 if text_width(a, b-a) > 640
          x = text_width(0,a)-@off
          bitmap.draw_text(x, 0, 0xFFFF, height, self[a, b-a])
        else normal_draw_text_entry
        end
      end
      def [](i, j) @text[i, j] end
      def []=(i, j, str)
        @text[i, j] = str
        @text_width[i, @text_width.size-i] = Array.new(size-i)
      end
    public
      def size()   @text.size  end
      def text=(str)
        str = @case==1 ? downcase(str) : @case==2 ? upcase(str) : str
        @text_width = Array.new(str.size)
        @text = str
      end
    else
      def [](i, j) @text_chars[i, j].join('') end
      def []=(i, j, str)
        @text_chars[i, j] = str.empty? ? nil : str
        @text_width[i, @text_width.size-i] = Array.new(size-i)
        @text.replace(@text_chars.join(''))
      end
    public
      def size()   @text_chars.size           end
      def text=(str)
        str = @case==1 ? downcase(str) : @case==2 ? upcase(str) : str
        @text_chars.replace(str.split(//))
        @text_width = Array.new(@text_chars.size)
        @text = str
      end
    end
  end
  
  def self.[](i) Players[i] end
  def self.update
    Keyboard.update
    Mouse.update
    Gamepads.each {|g| g.update}
    Players.each {|p| p.update}
  end
  def self.refresh
    Gamepads.clear
    x360_pads = XBox360_Gamepad::DLL ? Array.new(4) {|i| XBox360_Gamepad.new(i)} : []
    x360_pads.sort! {|a,b| (a.unplugged ? 1 : 0) <=> (b.unplugged ? 1 : 0)}
    devcaps = "\0"*404
    16.times do |i|
      Multimedia_Gamepad::JoyGetDevCaps.call(i, devcaps, 404)
      mid = devcaps.unpack('S')[0]
      if mid == 1118 and !x360_pads.empty?
        Gamepads << x360_pads.shift
      elsif mid != 0
        Gamepads << Multimedia_Gamepad.new(i)
      end
    end
    Gamepads.sort! {|a,b| (a.unplugged ? 1 : 0) <=> (b.unplugged ? 1 : 0)}
    Gamepads.each {|g| g.enabled = false}
    Players.each {|p| p.gamepad_id += 0}
  end
  
  # Le rythme de la fonction repeat? quand on maintient une touche appuyée.
  # La fonction repeat? est utilisée dans les menus pour bouger le curseur par exemple.
  f = Graphics.frame_rate
  REPEAT = [ # (se lit de bas en haut)
    #[f*4, 1],           # Après 4 secondes retourne toujours true.
    #[f*2, f*0.05],    # Après 2 secondes retourne true toutes les 0.05 secondes.
    [f*0.4, f*0.1], # Après 0.4 secondes retourne true toutes les 0.1 secondes.
    [2, 0],       # ...puis retourne false (à partir de la 2ème frame).
    [1, 1]      # Retourne true quand on vient d'appuyer (la 1ère frame)...
  ]
  PLAYERS_MAX = 1 # Le nombre de joueurs pour les jeux multijoueurs.
  KEYS_MAX = 30 # Nombre de touches, on peut mettre un très grand nombre si on
                # veut mais le limiter au minimum sert à optimiser la mémoire.
  
  Gamepads, Players = [], Array.new(PLAYERS_MAX) {|i| Player.new(i)}
  singleton_attach_methods(Players[0])
  class Player
    Keys = Array.new(KEYS_MAX) {|i| Player_Key.new(i)}
    # Les différentes touches du jeu (id entre 0 et KEYS_MAX-1).
    DOWN  = Keys[2]
    LEFT  = Keys[4]
    RIGHT = Keys[6]
    UP    = Keys[8]
    A     = Keys[11]
    B     = Keys[12]
    C     = Keys[13]
    X     = Keys[14]
    Y     = Keys[15]
    Z     = Keys[16]
    L     = Keys[17]
    R     = Keys[18]
    SHIFT = Keys[21]
    CTRL  = Keys[22]
    ALT   = Keys[23]
    F5    = Keys[25]
    F6    = Keys[26]
    F7    = Keys[27]
    F8    = Keys[28]
    F9    = Keys[29]
    
    constants.each {|s| Input.const_set(s,k=const_get(s)); k.s = s.to_s if k.is_a?(Key)}
  end
  
  # La config par défaut des touches.
  # En cas de jeu multijoueur il en faut une différente pour chaque joueur.
  # Liste des touches du clavier ligne 862.
  # Liste des touches XBox360 ligne 689, pour manette random ligne 681.
  # Mais inutile de mettre les deux, par exemple :A et :Button1 sont la même
  # touche, si moi j'utilise celles d'XBox c'est juste parce que ça me semble
  # plus logique de régler les touches par rapport à une config connue.
  # Le mieux étant de faire un menu où le joueur peut configurer lui même tout ça.
  # Le format est très simple, à gauche les touches virtuelles du jeu, à droite
  # un tableau des touches correspondantes séparé en deux, 1ère colonne les
  # touches de la manette, 2ème colonne les touches du clavier.
  # Pour les jeux multijoueurs la config des manettes se fait pareillement pour
  # tous, la différenciation des manettes se fait en interne.
  # Config du joueur 1 :
  Players[0].setup(
    :DOWN  => [ [:AxisLY_0, :DPadDown] , [:Down]                 ],
    :LEFT  => [ [:AxisLX_0, :DPadLeft] , [:Left]                 ],
    :RIGHT => [ [:AxisLX_1, :DPadRight], [:Right]                ],
    :UP    => [ [:AxisLY_1, :DPadUp]   , [:Up]                   ],
    :A     => [ [:X]                   , [:Z, :Shift]            ],
    :B     => [ [:Y]                   , [:X, :NumPad0, :Escape] ],
    :C     => [ [:A]                   , [:C, :Enter, :Space]    ],
    :X     => [ [:B]                   , [:A]                    ],
    :Y     => [ [:LT]                  , [:S]                    ],
    :Z     => [ [:RT]                  , [:D]                    ],
    :L     => [ [:LB]                  , [:Q, :PageUp]           ],
    :R     => [ [:RB]                  , [:W, :PageDown]         ],
    :SHIFT => [ []                     , [:Shift]                ],
    :CTRL  => [ []                     , [:Control]              ],
    :ALT   => [ []                     , [:Alt]                  ],
    :F5    => [ []                     , [:F5]                   ],
    :F6    => [ []                     , [:F6]                   ],
    :F7    => [ []                     , [:F7]                   ],
    :F8    => [ []                     , [:F8]                   ],
    :F9    => [ []                     , [:F9]                   ])
  
  refresh
  update
  Keyboard.release!(0...256) if Keyboard.push?(*0...256)
end




Mis à jour le 4/7/2020.






Joueur1 - posté le 20/03/2012 à 20:43:28 (981 messages postés)

❤ 0

Hum ?

Gestion de la souris ? Ouais ! on va pouvoir faire des point and clic ! :grossourire

"Il y avait bien une lumière au bout du tunnel... et c'était un lance-flammes" (Terry Pratchett)


fenryo - posté le 27/03/2012 à 21:51:16 (153 messages postés)

❤ 0

Mi-Loup, Mi-homme je parcours le monde à la recherche de ma meute: Ceux qui savent...

THAAAAAAAAANNNNNNKS A LOOOOT G attendu ce script depuis des siècles et des siècles lool

-------- Le réalisme c'est trouver un moyen rationnel d'atteindre un but magnifique ----------------- Kiro'o Tale: Aurion, jeu d'un nouveau genre !! ==> Pour faire des formulaire sur RMXP:


paradoxII - posté le 10/04/2012 à 01:44:27 (259 messages postés)

❤ 0

NYA

Merci beaucoup, enfin un truc vraiment utile et pas coder avec les pieds !

NYA


fenryo - posté le 22/06/2012 à 12:17:30 (153 messages postés)

❤ 0

Mi-Loup, Mi-homme je parcours le monde à la recherche de ma meute: Ceux qui savent...

Bon j'ai un bug avec le script pour une manette 360 tout les boutons LB, RB, RT LT par défaut sont reconnus mais pas le reste donc là j'ai inséré le script dans un jeu cobaye (neuf quoi) et ça ne reconnait pas les touches Y,X, B, A de la manette xbox360 quand elles sont appuyés dumoins la reconnaissance avec les touches virtuelles j'ai raté quelque chose?

Quand ça fait Input.trigger?(Input::C) ça ne réagit pas si j'appuie sur A de la manette xbox.:F

-------- Le réalisme c'est trouver un moyen rationnel d'atteindre un but magnifique ----------------- Kiro'o Tale: Aurion, jeu d'un nouveau genre !! ==> Pour faire des formulaire sur RMXP:


Zeus81 - posté le 22/06/2012 à 14:26:18 (11071 messages postés)

❤ 0

Putain de bug de Ruby de merde, tu fais chier ! :fache2
Tu peux rajouter ce fix en attendant que je fasse une nouvelle version mieuxe :

Portion de code : Tout sélectionner

1
2
3
  class XBox360_Gamepad
    Gamepad.constants.each {|n| k=Gamepad.const_get(n); const_set(n, k) if k.is_a?(Key)}
  end



Edit : Bon voilà t'as qu'à télécharger la dernière version, j'ai réparé le bug d'une superbe manière. :F
http://pastebin.com/LKd9hbDa


fenryo - posté le 22/06/2012 à 20:39:33 (153 messages postés)

❤ 0

Mi-Loup, Mi-homme je parcours le monde à la recherche de ma meute: Ceux qui savent...

LOOOOOOL ok boss merci :bob

[edit] : Bon j'ai un gros problème je potache depuis 2h là je me retrouve pas. Je fais une fenêtre pour que les joeurs puissent choisirs leur config eux même. J'ai donc les 2 pbs suivants :

1 - J'ai vu le setup par défaut du player 0 à la ligne 1473 et aussi ton script pour aider à capturer les touches. Mais comment j'affiche alors les touches associées aux touches virtuelles? je veux dire si je veux récupérer les noms des touches reçues dans ton setup par défaut pour la touche C, je fais comment ? j'ai tenté Input::C.to_s ça me renvoie "C" :oO

2- Ensuite je voudrais que chaque partie sauvegardée conserve sa config j'ai donc mon fichier de sauvegarde du jeu ou j'empile les objets à la sauvegarde et dépile pour le chargement mais là je sais pas quel objet empiler? Player[0] ?

Si tu peux m'aider avec des prototypes de script stp à genoux :grossourire

-------- Le réalisme c'est trouver un moyen rationnel d'atteindre un but magnifique ----------------- Kiro'o Tale: Aurion, jeu d'un nouveau genre !! ==> Pour faire des formulaire sur RMXP:


Zeus81 - posté le 23/06/2012 à 16:12:38 (11071 messages postés)

❤ 0

Je comprends, j'ai vraiment pas fait simple pour le coup et l'aide est pas documentée là dessus. :F
En fait pour configurer les touches faut envoyer un tableau au bon format au setup : Input.setup(liste)
Mais c'est à sens unique, on ne peut pas récupérer la liste, c'est à toi de la conserver avant de l'envoyer.
Par exemple tu peux créer un tableau dans Game_System :

Portion de code : Tout sélectionner

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
class Game_System
  attr_reader :inputs
  alias inputs_initialize initialize
  def initialize
    inputs_initialize 
    @inputs = { # On met notre config par défaut
      :DOWN  => [ [Gamepad::AxisLY_0.to_i], [Keyboard::Down.to_i]     ],
      :LEFT  => [ [Gamepad::AxisLX_0.to_i], [Keyboard::Left.to_i]     ],
      :RIGHT => [ [Gamepad::AxisLX_1.to_i], [Keyboard::Right.to_i]    ],
      :UP    => [ [Gamepad::AxisLY_1.to_i], [Keyboard::Up.to_i]       ],
      :A     => [ [Gamepad::X.to_i]       , [Keyboard::Shift.to_i]    ],
      :B     => [ [Gamepad::Y.to_i]       , [Keyboard::NumPad0.to_i]  ],
      :C     => [ [Gamepad::A.to_i]       , [Keyboard::Enter.to_i]    ],
      :X     => [ [Gamepad::B.to_i]       , [Keyboard::A.to_i]        ],
      :Y     => [ [Gamepad::LT.to_i]      , [Keyboard::S.to_i]        ],
      :Z     => [ [Gamepad::RT.to_i]      , [Keyboard::D.to_i]        ],
      :L     => [ [Gamepad::LB.to_i]      , [Keyboard::PageUp.to_i]   ],
      :R     => [ [Gamepad::RB.to_i]      , [Keyboard::PageDown.to_i] ],
      :SHIFT => [ []                      , [Keyboard::Shift.to_i]    ],
      :CTRL  => [ []                      , [Keyboard::Control.to_i]  ],
      :ALT   => [ []                      , [Keyboard::Alt.to_i]      ],
      :F5    => [ []                      , [Keyboard::F5.to_i]       ],
      :F6    => [ []                      , [Keyboard::F6.to_i]       ],
      :F7    => [ []                      , [Keyboard::F7.to_i]       ],
      :F8    => [ []                      , [Keyboard::F8.to_i]       ],
      :F9    => [ []                      , [Keyboard::F9.to_i]       ]}
    Input.setup(@inputs)
  end
end


Ensuite dans ton menu pour configurer les touches, tu modifies ce tableau, bon y'a plusieurs façons de le faire ça dépend de comment tu comptes faire ton menu, si tu comptes séparer la config manette et clavier, si tu veux pouvoir supporter plusieurs touches sur le même bouton...
M'enfin voici un exemple simple ou on configure le bouton C, manette et clavier confondus et avec une seule touche par bouton :

Portion de code : Tout sélectionner

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
  # on capture la touche
  until key = Keyboard.capture_key || Input.gamepad.capture_key
    Graphics.update
    Input.update
  end
  
  if key
    key_i = key.to_i # dans notre tableau on garde les touches sous forme d'entier
    key_type = key.is_a?(Input::Keyboard_Key) ? 1 : 0 # dans notre tableau les touches
                                                      # du clavier sont rangées dans la
                                                      # colonne 1 celles des manettes
                                                      # dans la colonne 0.
    
    # on retire la touche qu'on vient d'entrer de tous les autres boutons
    # si une même touche correspondait à deux boutons ça le ferait moyen
    $game_system.inputs.each_value do |v|
      v[key_type].delete(key_i)
    end
    
    $game_system.inputs[:C] = [[], []] unless $game_system.inputs.has_key?(:C)
    $game_system.inputs[:C][key_type] = [key_i] # si on veut pouvoir garder plusieurs
                                                # touches sur le même bouton il faudra
                                                # gérer cette étape différemment
    
    # on attend que la touche soit relâchée avant de continuer au cas où.
    while key.push?
      Graphics.update
      Input.update
    end
  end


Quand tu veux valider ton nouveau tableau de touches tu fais : Input.setup($game_system.inputs)
Idem quand tu charges ta partie pour reprendre la config sauvegardée.

Enfin pour l'affichage dans ton menu toujours, tu regardes encore le tableau, par exemple pour le bouton C, en considérant qu'on a qu'une touche par bouton :

Portion de code : Tout sélectionner

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
keyboard_key_i = $game_system.inputs[:C][1][0]
if keyboard_key_i == nil
  # si la touche n'est pas configurée
  keyboard_key_str = "vide"
else
  # si la touche est configurée on a plusieurs choix :
  # - si on veut tout simplement le nom de la constante
  keyboard_key_str = Keyboard.key(keyboard_key_i).to_s
  # - si on veut le nom de la touche dans la langue du système
  keyboard_key_str = Keyboard.key_name(keyboard_key_i)
  # - si on veut le nom de la touche par rapport à son id et un tableau personnel
  keyboard_key_str = monTableau[keyboard_key_i]
end
 
gamepad_key_i = $game_system.inputs[:C][0][0]
if gamepad_key_i == nil
  # si la touche n'est pas configurée
  gamepad_key_str = "vide"
else
  # si la touche est configurée on a plusieurs choix :
  # - si on veut tout simplement le nom de la constante
  gamepad_key_str = Input.gamepad.key(gamepad_key_i).to_s
  # - si on veut le nom de la touche par rapport à son id et un tableau personnel
  gamepad_key_str = monTableau[gamepad_key_i]
end




fenryo - posté le 23/06/2012 à 16:39:05 (153 messages postés)

❤ 0

Mi-Loup, Mi-homme je parcours le monde à la recherche de ma meute: Ceux qui savent...

Ok merci d'avoir répondu c'est pas très évident mais je vais me battre à partir de là !! :biere

[EDIT]c'est l'édo tensei ce code loooool mais bon g réussi déjà à lire et sauvegarder les touches ça devrait aller merci encore !! :joint

[EDIT 2h plus tard] c bon g décodé la matrice lool purée ct pas léger ça. Input Ultimate 2.3 fully plugged into my game !!

-------- Le réalisme c'est trouver un moyen rationnel d'atteindre un but magnifique ----------------- Kiro'o Tale: Aurion, jeu d'un nouveau genre !! ==> Pour faire des formulaire sur RMXP:


Zeus81 - posté le 23/06/2012 à 23:41:26 (11071 messages postés)

❤ 0

Cool comme ça y'aura au moins une personne qui l'utilise. :)


saebakiller - posté le 02/02/2013 à 13:23:50 (1 messages postés)

❤ 0

salut a tous euhm Zeus81 ça ne fonctionne pas !?
il me met

unexpected '='
=begin

:sriden


Zeus81 - posté le 02/02/2013 à 13:58:52 (11071 messages postés)

❤ 0

T'as dû rajouter un espace avant, vire le.


Champinoir - posté le 23/02/2013 à 16:10:06 (1 messages postés)

❤ 0

Bonjour, j'ai deux problèmes avec ce script :
Quand je lance le jeu sans ma manette, la souris ne fait pas bouger le personnage.
Quand je lance le jeu avec ma manette, le personnage va vers le haut sans arrêt (non, ce n'est pas un problème de manette :) )
C'est une manette PS3 :p

Edit : En enlevant " :DPadUp " à la ligne 1477, la manette marche impeccablement bien...


Zeus81 - posté le 23/02/2013 à 16:34:36 (11071 messages postés)

❤ 0

Ce script n'a pas pour but de déplacer le personnage avec la souris, il te donne entre autre la position de la souris mais c'est à toi d'en faire ce que tu veux et tout gérer.
Pour la manette t'as qu'à vérifier que le stick analogique est bien centré, sinon je vois pas.


the_bored_gamer - posté le 08/04/2013 à 22:05:21 (3 messages postés)

❤ 0

Salut! Je patauge en ce moment avec la souris... Elle semble reconnaître environ 2 fois sur 5 quand je clique.

J'ignore à quel endroit mettre Input.update . Je l'avais mis à la fin de mon event, mais aucune amélioration. Si je la met au début, rien n'est détecté du tout!

Condition 1) Mouse::Left.click?
condition 2) Mouse.on?(13, 13, 228, 44)

Qu'est-ce que je fais de mal?

:help


Zeus81 - posté le 08/04/2013 à 23:35:58 (11071 messages postés)

❤ 0

T'as pas besoin de mettre de Input.update normalement si tu bosses en event.
Le reste a l'air bon, après faut qu'auparavant t'ais activé la souris : Mouse.enabled = true


the_bored_gamer - posté le 09/04/2013 à 02:26:19 (3 messages postés)

❤ 0

Zeus81 a dit:


T'as pas besoin de mettre de Input.update normalement si tu bosses en event.
Le reste a l'air bon, après faut qu'auparavant t'ais activé la souris : Mouse.enabled = true



Non, ça va pour ça, ma souris est activée. J'ai créé ma propre icône. Nickel.

Je ne mettais pas le Input.update au départ dans mon event, mais comme ça clochait, je croyais que c'était ça le problème...

J'ai fait le tour de ta documentation (chapeau, d'ailleurs) et je ne cerne pas le bobo. Même après plusieurs tests.

Pour tester, quand on clique dans la zone je me suis mis un:
puts "détecté"
Ca fonctionne, mais pas toujours. Environ deux fois sur cinq.
Et c'est bien ce "pas toujours" qui me chicote...
Ma scène est vide. C'est pas comme si j'avais pleins de processus qui travaillaient en parallèle.
C'est forcément un update qui ne se fait pas à quelque part...

Merci beaucoup de ton support


Zeus81 - posté le 10/04/2013 à 03:25:26 (11071 messages postés)

❤ 0

Ah ok je vois, en fait c'est vx ace qui a un bug avec ses processus parallèles, si tu veux qu'ils fonctionnent comme ils le devraient, il faut englober tout le code de ton event dans une boucle avec un attendre 1 frame à la fin :
<boucle>
__<commandes random ...>
__<attendre 1 frame>
<fin boucle>

Sinon tu peux rajouter ce fix :

Portion de code : Tout sélectionner

1
2
3
4
5
6
7
8
9
10
class Game_Event
  alias zeus_update update
  def update
    zeus_update
    if @interpreter and !@interpreter.running?
      @interpreter.setup(@list, @event.id)
      @interpreter.update
    end
  end
end




the_bored_gamer - posté le 10/04/2013 à 04:11:13 (3 messages postés)

❤ 0

Incroyable ! :wouah

C'est maintenant fonctionnel à 100% !!!

Zeus81, je m'incline devant ton talent! :lei


vannseed - posté le 22/01/2014 à 20:30:49 (3 messages postés)

❤ 0

j’adore ton script mais je ne comprend pas bien comment mettre mes propre touche , j'ai essayer de suivre le petit tuto que tu donne a fenryo, mai j'arrive pas a configurer ma windows et ma scene...
je suis sous vxace si ça peut changer quelque chose


merci


zeus81 - posté le 23/01/2014 à 17:26:16 (11071 messages postés)

❤ 0

Dit comme ça je vois pas ce que je peux faire de plus.


Sofreack - posté le 29/05/2014 à 13:10:57 (938 messages postés)

❤ 0

J'ai dix doigts et une main.

Salut Zeus81,
je viens à toi Dieu de l'olympe car j'utilise ton script dont je n'ai rien touché et qui fonctionnait très bien jusque là par default avec ma manette filaire Xbox360.
Mais (y en a toujours un ), je n'ai plus cette manette elle m'a lâché j'utilise donc maintenant ma Razer Onza, qui est aussi un pad xbox360, reconnu en tant que tel, mais voilà:
-la touche assignée dans ton script à RT se retrouve assignée à START et la touche assignée à LT à BACK.
Quand je test ma manette, BACK et START sont respectivement le bouton 9 et 10 et LT et RT sont reconnu sur un même Axe Z, dont la valeur augmente si j'appuis sur RT et diminue si j'appuis sur LT.

J'ai bien lu dans ton script que ces deux touches étaient reconnues par la pression exercée sur les touches donc j'ai cherché à voir si j'arriverais à comprendre, et si j'ai bien compris si sa valeur est égale à 0 c'est LT si 1 ou plus c'est RT, me trompe-je?

Quoi qu'il en soit je ne vois pas comment faire, elle est reconnue en tant que pad Xbox 360, toute les autres touches configurées fonctionnent et j'ai essayé de voir pour la configurer par rapport à un Gamepad quelconque avec les "Button:" au lieux de "A","X" etc mais ça reviens au même en fait les boutons START et BACK sont les boutton: 4 et 5 dans ton script alors qu'ils correspondent aux 9 et 10 quand je test et le 10 je le vois pas dans le script, bref je m'embrouille dans la config alors que je suis persuadé que tout est bon si je rebranche un pad 360 filaire officiel.

Donc question est-ce que ça peu que venir de ma manette ? Est-ce normal que les gâchettes soient reconnues sur un axe Z et si oui alors pourquoi elles sont transférées sur START et BACK ? Y a t'il un moyen de faire passer les bouttons 9 et 10 sur LT et RT ?

Valjean Story


skyprost - posté le 19/08/2014 à 23:53:39 (1 messages postés)

❤ 0

Désoler de paraitre débile mais a quel endroit il faut mettre Mouse.enabled = true
:-/


CapNot - posté le 02/12/2015 à 09:16:30 (6 messages postés)

❤ 0

Salut à tous,
après moult années d'absence (pour cause de faisage d'autres chose), je me remet doucement au making.
J'ai acheté VX ace hier et le codage n'a jamais été mon fort ...
Ce script me fait bien envie mais je ne parviens pas à le faire fonctionner, j'ai toujours le message suivant :
unexpected '='
=begin

Je me doute que le problème vient de moi, néanmoins j'aimerais le résoudre.
Si quelqu'un aurait la gentillesse de me venir en aide, il aurait mon éternelle gratitude.

Merci d'avance.


zeus81 - posté le 02/12/2015 à 16:25:08 (11071 messages postés)

❤ 0

C'est parce que tu dois avoir des espaces avant le =begin, il faut qu'il soit collé à gauche.


CapNot - posté le 06/12/2015 à 23:03:28 (6 messages postés)

❤ 0

Merci beaucoup Zeus81,
mais maintenant mon projet ne veut même plus se lancer ...
Message d'erreur :
line 1499 SyntaxError occured

embedded document meets end of file.

Je crois qu'il va vraiment falloir que je me mette au ruby ...
Ou rester à jouer au clavier.


zeus81 - posté le 07/12/2015 à 03:18:46 (11071 messages postés)

❤ 0

Je sais pas, peut-être que t'as mal copié le script et qu'un caractère chelou s'est ajouté à la fin qui fait tout planter.


Alien25Gaming - posté le 26/05/2018 à 13:41:18 (3 messages postés)

❤ 0

il est possible de ne récupérer que la partie Manette de ce script s'il vous plaît ? (si oui et qu'il faut que je le fasse moi-même comment ?)

Suite à de nombreux abus, le post en invités a été désactivé. Veuillez vous inscrire si vous souhaitez participer à la conversation.

Haut de page

Merci de ne pas reproduire le contenu de ce site sans autorisation.
Contacter l'équipe - Mentions légales

Plan du site

Communauté: Accueil | Forum | Chat | Commentaires | News | Flash-news | Screen de la semaine | Sorties | Tests | Gaming-Live | Interviews | Galerie | OST | Blogs | Recherche
Apprendre: Visite guidée | RPG Maker 95 | RPG Maker 2003 | RPG Maker XP | RPG Maker VX | RPG Maker MV | Tutoriels | Guides | Making-of
Télécharger: Programmes | Scripts/Plugins | Ressources graphiques / sonores | Packs de ressources | Midis | Eléments séparés | Sprites
Jeux: Au hasard | Notre sélection | Sélection des membres | Tous les jeux | Jeux complets | Le cimetière | RPG Maker 95 | RPG Maker 2000 | RPG Maker 2003 | RPG Maker XP | RPG Maker VX | RPG Maker VX Ace | RPG Maker MV | Autres | Proposer
Ressources RPG Maker 2000/2003: Chipsets | Charsets | Panoramas | Backdrops | Facesets | Battle anims | Battle charsets | Monstres | Systems | Templates
Ressources RPG Maker XP: Tilesets | Autotiles | Characters | Battlers | Window skins | Icônes | Transitions | Fogs | Templates
Ressources RPG Maker VX: Tilesets | Charsets | Facesets | Systèmes
Ressources RPG Maker MV: Tilesets | Characters | Faces | Systèmes | Title | Battlebacks | Animations | SV/Ennemis
Archives: Palmarès | L'Annuaire | Livre d'or | Le Wiki | Divers