Jump to content
IGNORED

Efficient control handling with Intybasic


Vincehood

Recommended Posts

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 by catsfolly
Link to comment
Share on other sites

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 by DZ-Jay
  • Like 1
Link to comment
Share on other sites

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 by DZ-Jay
  • Like 2
Link to comment
Share on other sites

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

  • Like 1
Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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.

  • Like 1
Link to comment
Share on other sites

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.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...