catsfolly Posted January 29, 2017 Share Posted January 29, 2017 (edited) 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 The inputs just tell you the state of the keys - whether they are pressed or not. To detect that a key has been (newly) pressed, you first have to determine that the key has been "released" by waiting for it the key state to indicate "no key pressed" for several frames in a row. Once you know the key has been released, then the next time a key state changes, you can detect that "a key has been pressed" and use this information to trigger some action. Here is an entirely untested code outline of how this might be implemented: key_released = 0 release_frame_count = 0 const release_frameLimit = 5 new_key = 0 check_for_key: procedure if key_released = 1 then if cont1.key <> 12 then new_key = cont1.key : key_released = 0 : release_frame_count = 0 return end if rem waiting for a number of frames in a row with no keys pressed if cont1.key = 12 then release_frame_count = release_frame_count +1 else release_frame_count = 0 if release_frame_count > release_frame_limit then key_released = 1 end if end rem in the launch routine if new_key <> 0 then gosub launch_disc : new_key = 0 rem in the call back routine if disc_launched AND (new_key <> 0) then gosub callback_disc : new_key = 0 Catsfolly Edited January 29, 2017 by catsfolly Quote Link to comment Share on other sites More sharing options...
+DZ-Jay Posted January 29, 2017 Share Posted January 29, 2017 (edited) I wonder if it would be useful to create an event-driven hand-controller routine for IntyBASIC. Preferably, it would be a library built into the language, but I guess an optimized Assembly Language routine interfaced with macros could do. This routine would periodically test the input and call user-defined event-handlers whenever an input change occurs. This is the way P-Machinery works. The programmer defines a dispatch table with the event-handlers for the events he wants to handle. That is, an undefined event handler will mean that those type of events won't be triggered. ;; ======================================================================== ;; ;; TTL_DISP ;; ;; This is the dispatch table for the "Wait" state. Include pointers ;; ;; to those events you want to handle in your game. Discrete events ;; ;; are dispatched for "Up" (release) and "Down" (pressed) occurrences, ;; ;; per input type, in the following order: ;; ;; ;; ;; Release: ;; ;; DiscUp - Disc released. ;; ;; ActionUp - Action button released. ;; ;; KeyUp - Keypad button released. ;; ;; ;; ;; Pressed: ;; ;; DiscDown - Disc pressed. ;; ;; ActionDown - Action button pressed. ;; ;; KeyDown - Keypad button pressed. ;; ;; ;; ;; Event handlers set to PM.NULL will be ignored. ;; ;; ======================================================================== ;; TTL_DISP PROC DECLE TTL_CTRL.DiscUp DECLE TTL_CTRL.ActUp DECLE TTL_CTRL.KeyUp DECLE TTL_CTRL.DiscDown DECLE TTL_CTRL.ActDown DECLE TTL_CTRL.KeyDown ENDP Then you define procedures for each of the event-handlers. The internal routine will call these procedures whenever the particular event occurs. In the case of P-Machinery, the event includes an appropriate event "data word" which contains information about the hand-controller used and the input event: ;; ======================================================================== ;; ;; TTL_CTRL ;; ;; Event-handler code for the events declared above. ;; ;; ;; ;; An event is dispatched for each of the six event types defined. The ;; ;; Information Payload included with each dispatched event is a 16-bit ;; ;; word in the following general format: ;; ;; Keypad/Disc ;; ;; | ;; ;; ,=====|=====, ;; ;; | | ;; ;; Port | Action | ;; ;; Reserved | | \ | ;; ;; ^ ,=|=, | ,=|=| ;; ;; ,_________|_________, | | | | | ;; ;; / \ v v v v v ;; ;; +---+---+---+---+---+---+---+---+ +---+---+---+---+---+---+---+---+ ;; ;; | x : x : x : x : x : x | n : n | | . : . | . : . | X : X : X : X | ;; ;; +---+---+---+---+---+---+---+---+ +---+---+---+---+---+---+---+---+ ;; ;; F E D C B A 9 8 7 6 5 4 3 2 1 0 ;; ;; \______________,______________/ \______________,______________/ ;; ;; | | ;; ;; v v ;; ;; Event Status Event Data ;; ;; ;; ;; Constants for each controller input type are available as follows: ;; ;; HAND.PORT: ;; ;; PlayerAny ( 0) ;; ;; Player1 ( 0) ;; ;; Player2 ( 1) ;; ;; Player3 ( 2) ;; ;; Player4 ( 3) ;; ;; ;; ;; HAND.KEYPAD: ;; ;; 0 - 9 (0 .. 9) ;; ;; Clear (10) ;; ;; Enter (11) ;; ;; ;; ;; HAND.Action: ;; ;; Top ( 0) ;; ;; BottomLeft ( 1) ;; ;; BottomRight ( 2) ;; ;; ;; ;; HAND.Disc: ;; ;; N ( 0) Disc positions, clockwise: ;; ;; NNE ( 1) ;; ;; NE ( 2) 0 ;; ;; ENE ( 3) F 1 ;; ;; E ( 4) E N 2 ;; ;; ESE ( 5) D ^ 3 ;; ;; SE ( 6) | ;; ;; SSE ( 7) C W<---+--->E 4 ;; ;; S ( | ;; ;; SSW ( 9) B v 5 ;; ;; SW (10) A S 6 ;; ;; WSW (11) 9 7 ;; ;; W (12) 8 ;; ;; WNW (13) ;; ;; NW (14) ;; ;; NNW (15) ;; ;; ======================================================================== ;; I know that a lot of IntyBASIC programmers follow a more procedural approach to their game design, so I wonder if this event-driven approach would be worth exploring. In this case, your program would be reactionary to the input events, updating the game state when they happened. The input decoding routine could be hooked to the internal one, so the main game loop need not be affected. Thoughts? -dZ. UPDATE: All the code to handle the above is available in P-Machinery, although it's built-into the internal kernel and event-driven, process-queue machinery so it may take some work to rip it out and modify it to stand on its own. Absent someone willing to implement this in IntyBASIC, I would be inclined to volunteer to modify my code. However, it is in Assembly Language, so it would have to be an external library hooked into the language. If there is actual interest in this, I could give it a try... Edited January 29, 2017 by DZ-Jay 1 Quote Link to comment Share on other sites More sharing options...
+DZ-Jay Posted January 29, 2017 Share Posted January 29, 2017 (edited) For anybody interested, attached is the pseudo-code algorithms I devised for P-Machinery AGE's hand-controller decoder. It's written in made-up "C" so perhaps it could be easily translated into IntyBASIC. The P-Machinery I/O pipeline has three stages: Scanner, Decoder, Dispatcher: The Scanner is in charge of reading the I/O channels and conditioning the signal by debouncing and filtering obvious glitches. It updates an internal status record with some necessary information. The Decoder is in charge of taking the raw clean signal provided by the Scanner and decoding it into valid event types. It uses a state machine and simple heuristics to determine whether it is in "Keypad" mode or "Disc + Action Button" mode. It then prepares an Event Message Word to be fed to the dispatcher for processing. The Dispatcher takes the Event Message Word produced by the Decoder and dispatches the necessary events accordingly with the appropriate data payload. In P-Machinery, this is done by pushing events into the Task Queue. The actual decoding is done via a linear search of a table of valid values for each input type. In P-Machinery, the internal operating system includes a Task Queue and process chaining primitives, so the above is a natural fit. In IntyBASIC, the Scanner could be assumed to be the internal IntyBASIC hand-controller processor, which returns a valid signal in CONTx. Since IntyBASIC does not have a Task Queue, an implementation of the above Decoder could then call user-defined routines directly as "call-backs" instead of preparing the Event Message Word for a dispatcher. Thoughts? -dZ. io_handctrl_dec.txt <- I/O Decoder Pseudo-Code Algorithm Edited January 29, 2017 by DZ-Jay 2 Quote Link to comment Share on other sites More sharing options...
Vincehood Posted January 30, 2017 Author Share Posted January 30, 2017 Hello, thanks all for the great answers. Catsfolly: I implemented something based on your suggestion and it works, great! Dz-Jay: I personally prefer the asynchronous approach, it is more efficient and intuitive. I guess it is even more true for integrating music and sound which I find quite hard (but this is not the subject of this thread) Vincent 1 Quote Link to comment Share on other sites More sharing options...
+DZ-Jay Posted January 30, 2017 Share Posted January 30, 2017 Hello, thanks all for the great answers. Catsfolly: I implemented something based on your suggestion and it works, great! Dz-Jay: I personally prefer the asynchronous approach, it is more efficient and intuitive. I guess it is even more true for integrating music and sound which I find quite hard (but this is not the subject of this thread) Vincent I'm confused. The event-driven model is an asynchronous one: your program reacts to changes in the game state, which occur outside the critical path asynchronously. dZ. Quote Link to comment Share on other sites More sharing options...
Vincehood Posted January 30, 2017 Author Share Posted January 30, 2017 DZ-Jay: don't be confused, I was just trying to say that I prefer event-driven/asynchronous mechanisms in general and you proposal belongs to this category /V Quote Link to comment Share on other sites More sharing options...
+DZ-Jay Posted January 30, 2017 Share Posted January 30, 2017 DZ-Jay: don't be confused, I was just trying to say that I prefer event-driven/asynchronous mechanisms in general and you proposal belongs to this category /V Ah, gotcha. For a moment I thought you were suggesting that it wasn't. Carry on. By the way, I didn't mean to hijack the thread. I just thought it would be a propos to the topic to suggest an event-driven model, albeit not precisely an implementation. If there is interest, it could be something I could work on. It's high-time that I get immersed deeper into IntyBASIC and contribute more than just concepts and ideas. dZ. 1 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.