Vincehood Posted January 23, 2017 Share Posted January 23, 2017 Hello, I have been looking in other threads and in the SDK examples (like the controller one) and I am still not fully sure about the best way to handle keypad buttons. I am trying to achieve the following: 1) the MOB moves based on disc direction 2) something happens when a key (1 to 9) on keypad is pressed (both when direction / no direction is pressed on disc) For 1), I am using CONT1.UP, CONT1.DOWN testing and it is working fine. For 2) I am using the result of the cont command which I compare to KEYPAD_1, KEYPAD_2, ... I realized recently that the values KEYPAD_1 to KEYPAD_9 are the values returned when no direction is pressed on disc.This means my code was not testing the situation where the both a key and the disc are pressed. As an example, the following values are returned by cont when key 5 is pressed: 66 (disc not pressed, defined as KEYPAD_5 in constants.bas), 74 (E), 64 (W), 70 (N), 67 (S), NW (94)... I noticed also that CONT1.KEY remains constantly equal to 12. So what is the best way to handle that? - Should I persist in using cont and handle the different key values I have observed in my tests like this: keypad=cont IF keypad=KEYPAD_5 or keypad=74 or keypad=64 or keypad=70 or keypad=67 or keypad=94 ... THEN END IF IF keypad=KEYPAD_1 or keypad=xx or keypad=xx or keypad=xx or keypad=xx or keypad=xx ... THEN END IF .... - is there any good reason for using both CONT1.x and cont? should I handle the MOV move with cont instead (assuming I need to use it anyway for the keys) - I am also wondering what is the default control mapping of the SDK to a computer keyboard? Are both controller 1 & 2 mapped? Is it documented somewhere? Thanks for your help /Vincent Quote Link to comment Share on other sites More sharing options...
+DZ-Jay Posted January 23, 2017 Share Posted January 23, 2017 Unfortunately, there is no way to accurately detect keypad and disc at the same time. The Intellivision hand-controller was designed with two use-cases in mind: either "keyboard entry" (keypad only), or "run and shoot" (disc and action buttons). If you think about it, the controller hardware interface provides only 8-bits of data, yet there are 32 different states (12 keys, 3 buttons, 16 disc directions, and idle). This was accomplished through a clever application of grey codes to accurately tell each input apart from the others. Consequently, most control input signals overlap across input types, meaning that disc input may look exactly like keypad input, but with an extra bit. The accuracy problem is exacerbated by the flaky and noisy analog signal and cheap plastic buttons. Clever use of heuristics and a state machine can help to condition the signal for better accuracy, but they still won't solve the issue of keypad signals overlapping disc signals. In my opinion, game mechanics are more accurate and pleasant to use when programmers embrace this design intent of the Intellivision hand-controller: use keypad for key input and use disc and action buttons for movement and actions; and keep the two separated. In my own P-Machinery framework, I use a state machine with simple heuristics to treat the input as either "keypad" or "disc+action" modes, and ignore invalid signals within the context of the active mode. The mode switches when a valid signal is received following a full and sustained release of the hand-controller input. Note that this is separate from "debouncing" and signal conditioning. dZ. Quote Link to comment Share on other sites More sharing options...
Vincehood Posted January 23, 2017 Author Share Posted January 23, 2017 Thanks DZ-Jay for the great explanation. I definitely want to embrace the design intent of the Intellivision controllers. I might have been mistaken by wrong memories of the Tron Deadly Dics game. I thought you could throw the disc while running (controller disc pressed) and pressing the keytab. I can no longer verify that myself on real hardware but a quick look at the few Youtube videos around confirms clearly what you say above. So I am just fine with that! Thanks Quote Link to comment Share on other sites More sharing options...
catsfolly Posted January 23, 2017 Share Posted January 23, 2017 Some players play Deadly Disks by using the Disc on one controller, and the keypad on the other. 1 Quote Link to comment Share on other sites More sharing options...
Vincehood Posted January 24, 2017 Author Share Posted January 24, 2017 Hello again, I am just wondering about the last part of my question: " what is the default control mapping of the SDK to a computer keyboard? Are both controller 1 & 2 mapped? Is it documented somewhere?" Since I am currently only testing on a PC, I need to make sure that what I observe is correct. Is the Inty Basic SDK relying on some defaults jzintv emulator settings? Which ones? Thanks /Vincent Quote Link to comment Share on other sites More sharing options...
Vincehood Posted January 24, 2017 Author Share Posted January 24, 2017 I kind of found the answer myself in the jzintv documentation (see further down). However I am still a bit puzzled. What if I want to differentiate controller 1 keypad and controller 2 keypad in IntyBasic? Aren't the KEYPAD_x constants differentiating them then? Also I do not have a numeric keypad on my laptop. Does it means I need to reconfigure jzintv if I should test both controller keypads? Thanks /V Numeric Keypad, maps 0 and 1 1-9 Left controller 1 - 9 0 Left controller Clear . Left controller 0 Enter Left controller Enter Main Keyboard, map 0. (Map 1 just moves right controller mappings to left.) 0-9 Right controller 0 - 9 - Right controller Clear = Right controller Enter Left Shift Right controller top action buttons Left Alt Right controller lower left action button Left Control Right controller lower right action button Right Shift Left controller top action buttons Right Alt Left controller lower left action button Right Control Left controller lower right action button Up Arrow Left controller disc up Down Arrow Left controller disc down Left Arrow Left controller disc left Right Arrow Left controller disc right Quote Link to comment Share on other sites More sharing options...
GroovyBee Posted January 24, 2017 Share Posted January 24, 2017 If you want to detect the controllers separately, then use either cont1 or cont2 instead of cont. The KEYPAD_XXX mappings are the same for either one. 1 Quote Link to comment Share on other sites More sharing options...
carlsson Posted January 24, 2017 Share Posted January 24, 2017 Regarding the second question, often you have a Func key or similar on your laptop that will enable a numeric keypad in the middle of the regular keyboard. Quote Link to comment Share on other sites More sharing options...
+DZ-Jay Posted January 24, 2017 Share Posted January 24, 2017 Just to clarify your understanding, the constants KEYPAD_X represent the value of the controller signal for each input. That is, when the key "1" is pressed on the keypad, the variable CONT will contain the value represented by the constant "KEYPAD_1". This is why, like GroovyBee said, the constant applies for either controller. Also like GroovyBee said, IntyBASIC provides access to both hand-controllers individually via the variables CONT1 (controller 1, or left) and CONT2 (controller 2, or right). CONT (with no number) is an amalgamation of both controller input signals, allowing a player to choose which controller they wish to use. This is very useful for single-player games where a single controller is employed, but the game remains indifferent to which one the player uses. dZ. Quote Link to comment Share on other sites More sharing options...
Vincehood Posted January 24, 2017 Author Share Posted January 24, 2017 (edited) OK thanks to you three. Here is what I observe with my keyboard: - cont captures key strokes corresponding to KEYPAD_XXX on number 0 to 9 (I was expecting this) - cont1 does not capture key strokes corresponding to KEYPAD_XXX on number 0 to 9 (I was not expecting this) - cont2 captures key strokes corresponding to KEYPAD_XXX - key strokes on number 0 to 9 are influencing the values of CONT2.x (I was not expecting this) As a result, in the code I am writing, when I press the keys 0-9, it impacts two different sprites which is not what I want (I don't want player 2 to move when player 1 is performing an action with the keypad!). This makes me wondering: - do I need to change the keymap in jzintv? I need one suitable for a 2 player game (see keymap list further down). Is the default one the right one then? - do I need to change something in my keyboard configuration (like enabling a keypad as suggested by carlsson and once I have figure how!) /Vincent Edited January 24, 2017 by Vincehood Quote Link to comment Share on other sites More sharing options...
+DZ-Jay Posted January 24, 2017 Share Posted January 24, 2017 As far as I know, the default keymap in jzIntv is fine for 2 players. Controller 1 is mapped to the left side of the Keyboard (ASDF, etc. and the number row on top), and Controller 2 is mapped to the left side of the keyboard (JKL;, etc. and the numerical keypad). You can obviously change this yourself. For more information on how to remap the controllers, see the jzIntv documentation included with the SDK. As for having having individual control over each hand-controller, then avoid CONT completely and only use CONT1 and CONT2. dZ. Quote Link to comment Share on other sites More sharing options...
carlsson Posted January 24, 2017 Share Posted January 24, 2017 Which model laptop do you have? There really ought to be a key you can press to get the numeric keyboard function. And yes, with a regular full sized PC keyboard the two keypads map to different locations so you can read both individually, I just tested. Quote Link to comment Share on other sites More sharing options...
+DZ-Jay Posted January 24, 2017 Share Posted January 24, 2017 By the way, in case it was not clear from my comment above, the reason you shouldn't use CONT for your purposes is that, CONT = CONT1 XOR CONT2 It actually means: "merge both hand-controller signals so that we treat the input of either one as a single controller." Obviously, this only works if the player uses one or the other. If he tries to press the keypad of both controllers simultaneously, the value of CONT is not reliable. As I said before, CONT is only useful for single-player games where the program doesn't care which controller the player is using, as long as he picks only one of them. This is a very common use case, and in fact the way that a lot of old games worked. dZ. 1 Quote Link to comment Share on other sites More sharing options...
Vincehood Posted January 24, 2017 Author Share Posted January 24, 2017 Hello, yes I do not use CONT any longer. My laptop is an old Clevo M767TU with a Swedish keyboard (see layout in attached picture) Fn + NumLK activates some keypad support: M:0 J:1 K:2 L:3 U:4 I:5 O:6 7:7 8:8 9:9 I enabled the keypad but it does not seem to help much The regular numbers are still influencing both CONT1.XXX and cont2 evaluation. /Vincent Quote Link to comment Share on other sites More sharing options...
Vincehood Posted January 24, 2017 Author Share Posted January 24, 2017 I have a spared USB keyboard with a separate numeric keypad. Will test with this one and come back! /V 1 Quote Link to comment Share on other sites More sharing options...
Vincehood Posted January 24, 2017 Author Share Posted January 24, 2017 (edited) OK, things look better now that I have connected an external USB keyboard with a numeric keypad. The numeric keypad is mapped on cont1 and the arrows on CONT1.xxxxx I still observe however that the main keyboard 0-9 keys are mapped onto CONT2.xxxx. Isn't it strange? In other words, a sprite (which is associated to CONT2 values) is moving when pressing 0-9 on the main keyboard which is not according to the jzintv documentation. E, D,S and X keys are also working for movement but this according to the jzintv doc. /V Edited January 24, 2017 by Vincehood Quote Link to comment Share on other sites More sharing options...
+DZ-Jay Posted January 24, 2017 Share Posted January 24, 2017 I guess it is actually the reverse of what I said: controller 1 (left) is mapped to the right side of the keyboard, while controller 2 (right) is mapped to the left side. This would make sense since the most common control surfaces are the numerical keypad and the arrow keys, so they are mapped by default to controller 1. Sorry for the confusion. Quote Link to comment Share on other sites More sharing options...
+nanochess Posted January 24, 2017 Share Posted January 24, 2017 If you don't want your player to move while pressing keypad, you should add this code in your IntyBASIC programs. x = CONT AND $E0 IF (x=$80)+(x=$40)+(x=$20) THEN ' Ignore as this is a keypad pressing. ELSE ' Continue processing disc and side buttons. END IF Also if you use CONT.KEY, CONT1.KEY or CONT2.KEY you should follow the IntyBASIC manual, these return the current number pressed (0-9), 10 and 11 for special keys and 12 for not pressed. The constants included in constants.bas are for decoding by yourself the keypad. Quote Link to comment Share on other sites More sharing options...
Vincehood Posted January 24, 2017 Author Share Posted January 24, 2017 Hello OK, I am now using only CONT1.KEY and CONT2.KEY and compare the results with values 0-12. It works fine for the sprite controlled with CONT1.KEY but I have still have the same issue reported earlier. I have not yet integrated your code above. Do you mean that this code would avoid that pressing the left keypad affects the right controller? /Vincent Quote Link to comment Share on other sites More sharing options...
Vincehood Posted January 24, 2017 Author Share Posted January 24, 2017 Hello, I think it is best that I share my code so you can have a look if you wish to. I would really appreciate expert advices. This is an attempt for a 2 players Tron alike game with discs bouncing on walls. Given the problems I experienced, I duplicated some procedure per player but it did not make any difference (the code was shorter initially). The issues I experience are the following ones: 1) for player 1, pressing numeric keypad triggers both move and throwing disc* (it should only trigger the latter) 2) for player 2. pressing numbers on main keyboard triggers both move and throwing disc* (it should only trigger the latter) 3) player 2 keypad based control for throwing disc is not working at all and I am not sure if I miss something obvious or if I did something really wrong for handling controls in a 2 player game Thanks Tron3.bas Quote Link to comment Share on other sites More sharing options...
+DZ-Jay Posted January 24, 2017 Share Posted January 24, 2017 Hello OK, I am now using only CONT1.KEY and CONT2.KEY and compare the results with values 0-12. It works fine for the sprite controlled with CONT1.KEY but I have still have the same issue reported earlier. I have not yet integrated your code above. Do you mean that this code would avoid that pressing the left keypad affects the right controller? /Vincent I think I have added some confusion here because I wasn't very familiar with the way IntyBASIC handles the controllers. I apologize for this. The CONT1 and CONT2 variables return the raw hand-controller input signal. These are a series of bits that must be decoded in order to know which actual signal was returned. As nanochess said, the constants in "Constant.bas" are intended to represent the raw codes for each individual input. If you plan on using these variables and constants, then your program will have to do the decoding itself. This means knowing not only testing for the input you want, but making sure it does not overlap another signal. This is the example that nanochess provided. The same applies to the CONT variable, since it is just "CONT1 AND CONT2" to merge both signals. IntyBASIC provides some facilities to decode the hand-controller signal for you, but this requires additional CPU processing. This is not a big deal, since it is presumably work that your program would have to do anyway. In order to take advantage of this, you can use the following variables: ' Both controllers merged CONT.UP Non-zero if any controller pointing up CONT.DOWN Non-zero if any controller pointing down CONT.LEFT Non-zero if any controller pointing left CONT.RIGHT Non-zero if any controller pointing right CONT.BUTTON Non-zero if any controller button pressed. CONT.B0 Non-zero if any controller top buttons pressed (left/right) CONT.B1 Non-zero if any controller bottom left button pressed. CONT.B2 Non-zero if any controller bottom right button pressed. CONT.KEY Current pressed key (0-9 for numbers, 10-Clear, 11-Enter, 12-Not pressed) ' Controller 1 (left) CONT1.UP Non-zero if controller pointing up CONT1.DOWN Non-zero if controller pointing down CONT1.LEFT Non-zero if controller pointing left CONT1.RIGHT Non-zero if controller pointing right CONT1.BUTTON Non-zero if controller button pressed. CONT1.B0 Non-zero if any of top controller buttons pressed (left/right) CONT1.B1 Non-zero if bottom left button pressed CONT1.B2 Non-zero if bottom right button pressed CONT1.KEY Current pressed key (0-9 for numbers, 10-Clear, 11-Enter, 12-Not pressed) ' Controller 2 (right) CONT2.UP Non-zero if controller pointing up CONT2.DOWN Non-zero if controller pointing down CONT2.LEFT Non-zero if controller pointing left CONT2.RIGHT Non-zero if controller pointing right CONT2.BUTTON Non-zero if controller button pressed. CONT2.B0 Non-zero if any of top controller buttons pressed (left/right) CONT2.B1 Non-zero if bottom left button pressed CONT2.B2 Non-zero if bottom right button pressed CONT2.KEY Current pressed key (0-9 for numbers, 10-Clear, 11-Enter, 12-Not pressed) Does this make sense? -dZ. Quote Link to comment Share on other sites More sharing options...
carlsson Posted January 24, 2017 Share Posted January 24, 2017 (edited) First I made a solution using the bit patterns as described in constants.bas and by DZ-Jay below. Then I reread Nanochess' post and realized he had a better solution, so I changed my code to what he suggested. It means the following changes: * In CheckControllers, I store the value of CONT1 AND $E0 into a temporary variable and in case that is zero, it means the disc is pressed. * In DisplayDiscs, you simply had a typo which referenced Dy(0) instead of Dy(Disc). Tron3.bas Edited January 24, 2017 by carlsson 1 Quote Link to comment Share on other sites More sharing options...
+DZ-Jay Posted January 24, 2017 Share Posted January 24, 2017 Here's the low-down on the hand-controller signals: KeyPad: ------- ------- -------- Input Code Signal ------- ------- -------- 1 0x81 10000001 2 0x41 01000001 3 0x21 00100001 4 0x82 10000010 5 0x42 01000010 6 0x22 00100010 7 0x84 10000100 8 0x44 01000100 9 0x24 00100100 Clear 0x88 10001000 0 0x48 01001000 Enter 0x28 00101000 ------- ------- -------- Action: ------- ------- -------- Input Code Signal ------- ------- -------- 0 0xA0 10100000 1 0x60 01100000 2 0xC0 11000000 ------- ------- -------- Disc: ------- ------- -------- Input Code Signal ------- ------- -------- 0 0x04 00000100 1 0x14 00010100 2 0x16 00010110 3 0x06 00000110 4 0x02 00000010 5 0x12 00010010 6 0x13 00010011 7 0x03 00000011 8 0x01 00000001 9 0x11 00010001 10 0x19 00011001 11 0x09 00001001 12 0x08 00001000 13 0x18 00011000 14 0x1C 00011100 15 0x0C 00001100 ------- ------- -------- ; SORTED BIT PATTERN 00000001 DISC-8 0x01 00000010 DISC-4 0x02 00000011 DISC-7 0x03 00000100 DISC-0 0x04 00000110 DISC-3 0x06 00001000 DISC-12 0x08 00001001 DISC-11 0x09 00001100 DISC-15 0x0C 00010001 DISC-9 0x11 00010010 DISC-5 0x12 00010011 DISC-6 0x13 00010100 DISC-1 0x14 00010110 DISC-2 0x16 00011000 DISC-13 0x18 00011001 DISC-10 0x19 00011100 DISC-14 0x1C 00100001 KEY-3 0x21 00100010 KEY-6 0x22 00100100 KEY-9 0x24 00101000 KEY-Enter 0x28 01000001 KEY-2 0x41 01000010 KEY-5 0x42 01000100 KEY-8 0x44 01001000 KEY-0 0x48 10000001 KEY-1 0x81 10000010 KEY-4 0x82 10000100 KEY-7 0x84 10001000 KEY-Clear 0x88 01100000 BTN-1 0x60 10100000 BTN-0 0xA0 11000000 BTN-2 0xC0 And here is a diagram showing the disc bits matrix: The core heuristics I use to decode are: If it matches exactly one of the keypad entries, it's a keypad key. Done. If it doesn't match a keypad entry exactly: Test the low-order 5 bits to see if we have a valid disc entry. Test the high-order 3 bits to see if we have an action button entry. If we have a valid disc entry, test bit 4 to see if we have a disc perfect diagonal. If no match found, it's glitchy noise, ignore. By the way, that's only when I want to use the entire hand-controller. If I only want to read the disc, I look for exact matches of the first 5 bits against the disc codes, and ignore the rest. Quote Link to comment Share on other sites More sharing options...
Vincehood Posted January 25, 2017 Author Share Posted January 25, 2017 I am really graceful, thanks for all the explanations and the code correction. I think it is much clearer now. Thanks Carlsson for the debugging, this typo was driving me nuts and I obviosly missed it! /Vincent Quote Link to comment Share on other sites More sharing options...
Vincehood Posted January 29, 2017 Author Share Posted January 29, 2017 Hello again, another question on the same theme. I am trying to change my code so keys 1-9 (except 5) can be used for 2 purposes: throwing the disc and getting back the disc. I have however noticed that a single key press seems to be interpreted as several ones by the code which results in unwanted behavior. What would the best practice to avoid this issue? Thanks /Vincent Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.