• Print

Author Topic: Where to next with QB64 development?  (Read 13740 times)

Galleon

  • Administrator
  • Hero Member
  • *****
  • Posts: 5470
  • QB Forever
Re: Where to next with QB64 development?
« Reply #165 on: June 14, 2011, 05:04:59 am »
I've got no idea why you are jumping up and down about bytes/bits/chomps/etc per pixel, but I agree that pixel formats have always been a bugbear of most 'simple' systems.

Just to get this thread back on track...

I've now finished implementing the devices interface. Despite appearing to have ignored community input if you look closely I did actually make 2 significant changes to the system. I also revised my custom input helper functions to better avoid accidental detection of certain types of input and provide support for wheels(values which can move up/down without limits). Even though you cannot run it (yet) I thought I'd post it anyway. Yes, it doesn't look simple, but this is a lot more than simply using the QB64 devices interface, it's a custom input system, and it does a lot with the code it's got.
1) Simplification of input from all devices into wheel, axis & button movement (the QB64 device interface)
2) Detection of control input
3) Assignment of the control input to an ID string so it can be saved and/or referenced later
4) Combining wheel, button and axis movement in a meaningful/multipurpose way
5) Returning the control input in a simple, easy to check way
Code: [Select]
'Example
'Step 1 - Setup Controls
ignore = _MOUSEMOVEMENTX 'optionally switch QB64 to into relative mouse mode (optional)
FOR i = 1 TO 4
    PRINT "Move/Press control for ";
    IF i = 1 THEN PRINT "UP";
    IF i = 2 THEN PRINT "RIGHT";
    IF i = 3 THEN PRINT "DOWN";
    IF i = 4 THEN PRINT "LEFT";
    DO
        PRINT ".";
        c$ = FindControl$
    LOOP UNTIL LEN(c$)
    PRINT
    IF i = 1 THEN c_up$ = c$
    IF i = 2 THEN c_right$ = c$
    IF i = 3 THEN c_down$ = c$
    IF i = 4 THEN c_left$ = c$
NEXT
'Step 2 - Play Game
SCREEN _NEWIMAGE(640, 400, 256)
x = 320: y = 200
DO
    rx = 0: ry = 0
    DO
        DIM v, rel AS SINGLE
        c$ = GetControl(v, rel)
        IF c$ <> "" THEN
            IF rel THEN
                IF c$ = c_right$ THEN rx = rx + rel
                IF c$ = c_left$ THEN rx = rx - rel
                IF c$ = c_up$ THEN ry = ry - rel
                IF c$ = c_down$ THEN ry = ry + rel
            ELSE
                IF c$ = c_right$ THEN dx1 = v
                IF c$ = c_left$ THEN dx2 = -v
                IF c$ = c_up$ THEN dy1 = -v
                IF c$ = c_down$ THEN dy2 = v
            END IF
        END IF
    LOOP UNTIL c$ = ""
    dx = dx1 + dx2: dy = dy1 + dy2
    IF ABS(dx) < 0.1 THEN dx = 0 'null zone
    IF ABS(dy) < 0.1 THEN dy = 0
    x = x + dx: y = y + dy
    x = x + rx: y = y + ry
    CLS , 1
    PSET (x, y), 40: DRAW "c40u10d20u10l10r20"
    _DISPLAY
    _LIMIT 100
LOOP


'Helper functions

FUNCTION FindControl$
SHARED EnumeratedDevices&
EnumeratedDevices& = _DEVICES 're-enumerate devices (something new may have just been plugged in)
STATIC FindControlCalled&
IF FindControlCalled& = 0 THEN
    FindControlCalled& = 1
    _DELAY 0.5: _MOUSEMOVE _WIDTH \ 2 + 1, _HEIGHT \ 2 + 1: _DELAY 0.1 'centre mouse to avoid accidental detection
END IF
STATIC LastControl$, Continuing&, Repeats&, Repeat$, BlockAxis$
IF Continuing& = 0 THEN
    Continuing& = 1
    DO WHILE _DEVICEINPUT: LOOP
    BlockAxis$ = ""
    FOR d& = 1 TO EnumeratedDevices&
        ignore = _DEVICEINPUT(d&) 'select device d
        FOR i& = 1 TO _LASTAXIS
            v! = _AXIS(i&)
            c$ = ""
            IF v! < -0.75 THEN c$ = "-AXIS"
            IF v! > 0.75 THEN c$ = "+AXIS"
            IF LEN(c$) THEN BlockAxis$ = BlockAxis$ + "[" + "DEVICE" + LTRIM$(STR$(d&)) + "," + c$ + LTRIM$(STR$(i&)) + "]"
        NEXT
    NEXT
END IF 'Continuing
t! = TIMER
DO UNTIL TIMER > t! + 1 'wait 1 second for a response
    Retry:
    d& = _DEVICEINPUT
    IF d& THEN
        FOR i& = 1 TO _LASTBUTTON
            IF _BUTTONCHANGE(i&) < 0 THEN c$ = "BUTTON": GOTO Found
        NEXT
        FOR i& = 1 TO _LASTAXIS
            v! = _AXIS(i&)
            IF v! < -0.75 THEN c$ = "-AXIS": GOTO Found
            IF v! > 0.75 THEN c$ = "+AXIS": GOTO Found
            IF ABS(v!) < 0.7 THEN 'free a previously blocked axis
                ci& = INSTR(BlockAxis$, "[DEVICE" + LTRIM$(STR$(d&)) + ",-AXIS" + LTRIM$(STR$(i&)) + "]")
                IF ci& THEN BlockAxis$ = LEFT$(BlockAxis$, ci& - 1) + RIGHT$(BlockAxis$, LEN(BlockAxis$) - INSTR(ci&, BlockAxis$, "]"))
                ci& = INSTR(BlockAxis$, "[DEVICE" + LTRIM$(STR$(d&)) + ",+AXIS" + LTRIM$(STR$(i&)) + "]")
                IF ci& THEN BlockAxis$ = LEFT$(BlockAxis$, ci& - 1) + RIGHT$(BlockAxis$, LEN(BlockAxis$) - INSTR(ci&, BlockAxis$, "]"))
            END IF
        NEXT
        w& = 0: wmax! = 0
        FOR i& = 1 TO _LASTWHEEL 'find the wheel which has moved the furthest
            v! = _WHEEL(i&)
            IF ABS(v!) > wmax! THEN w& = i&: wmax! = ABS(v!)
        NEXT
        IF w& THEN
            i& = w&: v! = _WHEEL(i&)
            IF v! < 0 THEN c$ = "-WHEEL": WheelType& = 1: GOTO Found
            IF v! > 0 THEN c$ = "+WHEEL": WheelType& = 1: GOTO Found
        END IF
    END IF
LOOP
EXIT FUNCTION
Found:
c$ = "DEVICE" + LTRIM$(STR$(d&)) + "," + c$ + LTRIM$(STR$(i&))
IF INSTR(BlockAxis$, "[" + c$ + "]") THEN GOTO Retry
IF WheelType& THEN
    WheelType& = 0
    IF Repeats& <= 8 THEN 'avoid accidental detection by requiring repeated movement of a wheel control
        IF Repeats& = 0 THEN Repeat$ = c$
        IF c$ = Repeat$ THEN
            Repeats& = Repeats& + 1
            GOTO Retry
        ELSE
            Repeats& = 0
            GOTO Retry
        END IF
    END IF
END IF
Repeats& = 0
IF c$ = LastControl$ THEN GOTO Retry
LastControl$ = c$: FindControl$ = c$: Continuing& = 0
END FUNCTION

FUNCTION GetControl$ (Value!, RelativeValue!)
RelativeValue! = 0: Value! = 0
SHARED EnumeratedDevices&, EnumeratedTime!
IF EnumeratedDevices& = 0 OR TIMER > EnumeratedTime! + 3 THEN EnumeratedDevices& = _DEVICES: EnumeratedTime! = TIMER 'recover devices every 3 seconds
STATIC CheckingDevice&, CheckingButton&, CheckingAxis&, CheckNegativeAxis&, CheckingWheel&, CheckNegativeWheel&
d& = CheckingDevice&
IF d& = 0 THEN 'check for a new input state
    CheckForNewEvent:
    d& = _DEVICEINPUT
    IF d& = 0 THEN EXIT FUNCTION
    CheckingDevice& = d&
    IF _LASTBUTTON THEN CheckingButton& = 1
    IF _LASTAXIS THEN CheckingAxis& = 1: CheckNegativeAxis& = 0
    IF _LASTWHEEL THEN CheckingWheel& = 1: CheckNegativeWheel& = 0
END IF
IF CheckingButton& THEN
    FOR i& = CheckingButton& TO _LASTBUTTON
        CheckingButton& = i& + 1 'set next button to check
        Change& = _BUTTONCHANGE(i&)
        IF Change& THEN
            IF Change& < 0 THEN Value! = 1 ELSE Value! = 0
            GetControl$ = "DEVICE" + LTRIM$(STR$(d&)) + ",BUTTON" + LTRIM$(STR$(i&))
            EXIT FUNCTION
        END IF
    NEXT
    CheckingButton& = 0 'finished checking all buttons in this state
END IF
IF CheckingAxis& THEN
    i& = CheckingAxis&
    neg& = CheckNegativeAxis&
    IF neg& THEN
        CheckNegativeAxis& = 0
        CheckingAxis& = i& + 1: IF CheckingAxis& > _LASTAXIS THEN CheckingAxis& = 0 'set next axis to check (if any)
        Value! = _AXIS(i&): IF Value! < 0 THEN Value! = -Value! ELSE Value! = 0 'negative movement
        GetControl$ = "DEVICE" + LTRIM$(STR$(d&)) + ",-AXIS" + LTRIM$(STR$(i&))
    ELSE
        CheckNegativeAxis& = 1 'return info about the negative version of this axis next
        Value! = _AXIS(i&): IF Value! < 0 THEN Value! = 0 'positive movement
        GetControl$ = "DEVICE" + LTRIM$(STR$(d&)) + ",+AXIS" + LTRIM$(STR$(i&))
    END IF
    EXIT FUNCTION
END IF
IF CheckingWheel& THEN
    FOR i& = CheckingWheel& TO _LASTWHEEL
        RelativeValue! = _WHEEL(i&)
        CheckNegativeWheel:
        neg& = CheckNegativeWheel&
        IF neg& THEN
            CheckNegativeWheel& = 0: CheckingWheel& = i& + 1: IF CheckingWheel& > _LASTWHEEL THEN CheckingWheel& = 0 'set next wheel to check (if any)
            IF RelativeValue! < 0 THEN
                RelativeValue! = -RelativeValue!
                GetControl$ = "DEVICE" + LTRIM$(STR$(d&)) + ",-WHEEL" + LTRIM$(STR$(i&))
                Value! = 0
                EXIT FUNCTION
            END IF
        ELSE
            CheckNegativeWheel& = 1 'return info about the negative version of this wheel next
            IF RelativeValue! > 0 THEN
                GetControl$ = "DEVICE" + LTRIM$(STR$(d&)) + ",+WHEEL" + LTRIM$(STR$(i&))
                Value! = 0
                EXIT FUNCTION
            END IF
            GOTO CheckNegativeWheel
        END IF
    NEXT
END IF
CheckingDevice& = 0: GOTO CheckForNewEvent
END FUNCTION



Something old... Something new... Something borrowed... Something blue...

Galleon

  • Administrator
  • Hero Member
  • *****
  • Posts: 5470
  • QB Forever
Re: Where to next with QB64 development?
« Reply #166 on: June 14, 2011, 06:45:50 am »
Now I can finally add STICK/STRIG/etc
Something old... Something new... Something borrowed... Something blue...

TerryRitchie

  • Hero Member
  • *****
  • Posts: 2797
  • Press any key to continue or any other key to quit
Re: Where to next with QB64 development?
« Reply #167 on: June 14, 2011, 10:08:50 am »
Whoa ... cool!  8)

Clippy

  • Hero Member
  • *****
  • Posts: 19051
  • I LOVE π = 4 * ATN(1)    Use the QB64 WIKI >>>
    • Pete's Qbasic Site
Re: Where to next with QB64 development?
« Reply #168 on: June 14, 2011, 10:21:47 am »
There's that loop again...

DO WHILE _DEVICEINPUT: LOOP

I gather that is how you get the most recent info.

What happens to the lost information in the loop? :-\
QB64 WIKI: Main Page
Download Q-Basics Code Demo: Q-Basics.zip
Download QB64 BAT, IconAdder and VBS shortcuts: QB64BAT.zip
Download QB64 SDL: QB64v0954-win15.7z

TerryRitchie

  • Hero Member
  • *****
  • Posts: 2797
  • Press any key to continue or any other key to quit
Re: Where to next with QB64 development?
« Reply #169 on: June 14, 2011, 10:37:45 am »
I would assume that while inside the loop you could gather previous information in an array, with the last element being the most recent movement/action.  ???

unseenmachine

  • Hero Member
  • *****
  • Posts: 3542
  • Make the Game not the ENGINE!!!
Re: Where to next with QB64 development?
« Reply #170 on: June 14, 2011, 10:41:25 am »
ARRAY!!! You wish! Though M$ has a method of providing the last 64 known mouse positions...
UnseenGDK Download : http://dl.dropbox.com/u/8822351/UnseenGDK.bm
GDK Tutorial : http://dl.dropbox.com/u/8822351/UnseenGDK_Tutorial.doc
VQB02 : https://www.dropbox.com/s/zz5ve8e75gcie8z/VQB02.bm?dl=0

Clippy

  • Hero Member
  • *****
  • Posts: 19051
  • I LOVE π = 4 * ATN(1)    Use the QB64 WIKI >>>
    • Pete's Qbasic Site
Re: Where to next with QB64 development?
« Reply #171 on: June 14, 2011, 11:29:48 am »
Well any delays between reads guarantees that information WILL be lost.

I can see using that when you want to start anew, but once you start reading, you COULD miss stuff if the loop runs more than once. That is what was happening when I tried to read a button down mouse event after the program went to a SUB procedure.

I gather that we will HAVE to read the event before we can read ANY of the other information...
QB64 WIKI: Main Page
Download Q-Basics Code Demo: Q-Basics.zip
Download QB64 BAT, IconAdder and VBS shortcuts: QB64BAT.zip
Download QB64 SDL: QB64v0954-win15.7z

Galleon

  • Administrator
  • Hero Member
  • *****
  • Posts: 5470
  • QB Forever
Re: Where to next with QB64 development?
« Reply #172 on: June 14, 2011, 01:04:05 pm »
Quote
I gather that is how you get the most recent info.
Actually I'm doing the equivalent of:
Code: [Select]
DO: LOOP UNTIL INKEY$=""Because I want to flush the input buffer there.
Something old... Something new... Something borrowed... Something blue...

Clippy

  • Hero Member
  • *****
  • Posts: 19051
  • I LOVE π = 4 * ATN(1)    Use the QB64 WIKI >>>
    • Pete's Qbasic Site
Re: Where to next with QB64 development?
« Reply #173 on: June 14, 2011, 01:24:56 pm »
OK so you use a STATIC variable to tell it when to flush the buffer. After that it doesn't flush it. I see...
QB64 WIKI: Main Page
Download Q-Basics Code Demo: Q-Basics.zip
Download QB64 BAT, IconAdder and VBS shortcuts: QB64BAT.zip
Download QB64 SDL: QB64v0954-win15.7z

Galleon

  • Administrator
  • Hero Member
  • *****
  • Posts: 5470
  • QB Forever
Re: Where to next with QB64 development?
« Reply #174 on: June 15, 2011, 05:19:41 am »
I just read the help on the QBASIC STICK (actually QB4.5) function. The example was hilarious as always, so it needed to be shared here.
Code: [Select]
' Do not attempt to run this program unless a joystick is installed
TEMP = STICK(0)
PRINT STICK(2), STICK(3)
Something old... Something new... Something borrowed... Something blue...

Galleon

  • Administrator
  • Hero Member
  • *****
  • Posts: 5470
  • QB Forever
Re: Where to next with QB64 development?
« Reply #175 on: June 17, 2011, 07:31:15 am »
Here's some code snippits of STICK & STRIG being implemented. I've extended these commands to allow for more than 2 joysticks and more then 2 buttons/axes. The original indexing systems didn't really suit being able to index more than 2 anythings, but I've tried to imagine what upgrading an existing QBASIC program containing STICK/STRIG might be like and make the extension options follow on from the QBASIC indexing system.

Code: [Select]
int32 func_stick(int32 i,int32 axis_group,int32 passed){
//note: range: 1-254 (127=neutral), top-left to bottom-right positive
//             128 returned for unattached devices
//QB64 extension: 'i' allows for joystick selection 0,1->JoyA, 2,3->JoyB, 4,5->JoyC, etc
//                'axis_group' selects the pair of axes to read from, 1 is the default
...

Code: [Select]
int32 func_strig(int32 i,int32 controller,int32 passed){
//note: returns 0 or -1(true)
//QB64 extension: 'i' refers to a button (b1,b1,b1,b1,b2,b2,b2,b2,b3,b3,b3,b3,b4,...)
//                'controller' overrides the controller implied by 'i', 1 is the default
if (device_last==0) func__devices();//init device interface (if not already setup)
...
Something old... Something new... Something borrowed... Something blue...

Galleon

  • Administrator
  • Hero Member
  • *****
  • Posts: 5470
  • QB Forever
Re: Where to next with QB64 development?
« Reply #176 on: June 18, 2011, 02:26:00 am »
Ok, I've now finished coding the support for the STICK and STRIG functions.
Code: [Select]
DO
    LOCATE 1, 1
    PRINT "JOY1: STICK"; STICK(0); STICK(1); STICK(0, 2); STICK(1, 2); "STRIG"; STRIG(0); STRIG(1); STRIG(4); STRIG(5); STRIG(8); STRIG(9)
    PRINT "JOY2: STICK"; STICK(2); STICK(3); STICK(2, 2); STICK(3, 2); "STRIG"; STRIG(2); STRIG(3); STRIG(6); STRIG(7); STRIG(10); STRIG(11)
    PRINT "JOY3: STICK"; STICK(4); STICK(5); STICK(4, 2); STICK(5, 2); "STRIG"; STRIG(0, 3); STRIG(1, 3); STRIG(4, 3); STRIG(5, 3); STRIG(8, 3); STRIG(9, 3)
    _LIMIT 10
LOOP
Here's some code to display the input from 3 joysticks, all with dual sticks and 3 buttons. Notice the extra (QB64 only) parameters used to cater for the 2nd stick and the buttons of the 3rd joystick. If this looks a bit confusing I highly recommend looking up help if you choose to use these commands. I'll be adding support for ON STRIG next.

That's 2 less QBASIC commands which QB64 will be incompatible with! ;D
Something old... Something new... Something borrowed... Something blue...

Galleon

  • Administrator
  • Hero Member
  • *****
  • Posts: 5470
  • QB Forever
Re: Where to next with QB64 development?
« Reply #177 on: June 19, 2011, 04:25:40 am »
I'm very proud to announce that I have achieved the implementation of ON STRIG in a single day. It was nothing really, I just took the implementation of ON KEY, duplicated (most of) it then changed it until it was an implementation of ON STRIG.

Here's a very QBASICy example:
Code: [Select]
ON STRIG(0) GOSUB 10
STRIG (0)ON

DO
    PRINT ".";
    _LIMIT 30
LOOP UNTIL INKEY$ <> ""
END

10
a$ = "[STRIG 0 EVENT]"
FOR x = 1 TO LEN(a$)
    PRINT MID$(a$, x, 1);
    _DELAY 0.02
NEXT
RETURN

And here's an example using QBASIC's ON STRIG with some of the extended features available in QB64:
Code: [Select]
FOR j = 1 TO 256
    FOR b = 1 TO 256
        ON STRIG((b - 1) * 4, j) jb (j - 1) * 256 + b - 1
    NEXT
NEXT
STRIG ON

DO
    PRINT ".";
    _LIMIT 30
LOOP UNTIL INKEY$ <> ""
END

SUB jb (x AS LONG)
PRINT "Joystick #"; x \ 256 + 1; "button #"; (x AND 255) + 1; "pressed!"
END SUB
Something old... Something new... Something borrowed... Something blue...

Cyperium

  • Hero Member
  • *****
  • Posts: 3654
  • Knowledge is good, but understanding is better
    • Cyperium
Re: Where to next with QB64 development?
« Reply #178 on: June 19, 2011, 04:36:09 am »
Nice Galleon! Approaching 100% QB compatible!
Venture - New Prototype, QB64 Editor v1.97, SDL dll files

OlDosLover

  • Moderator
  • Hero Member
  • *****
  • Posts: 5315
  • OlDosLover
Re: Where to next with QB64 development?
« Reply #179 on: June 19, 2011, 04:51:50 am »
Hi all,
    Congrats Galleon and thank you. Another one bites the dust!
OlDosLover.

  • Print