Jump to content
Sign in to follow this  
Xandy

SDL Configure Controls, Joystick / Keyboard

Recommended Posts

Xandy

I always knew I'd have to write a configure joystick routine to record and return desired user input to be used for player controls.

This example UDF is mainly to help people just getting started, who have never written a configure joystick routine.

 but it's also a dialog that will setup and load custom controls for as many players as you like.  Just try -12 players for example.

 

Example using Configure Controls to setup controls for Tanks that ride on the desktop.

Damn I broke the jump shadow before the video, ha. I fixed it before the source upload.

http://www.youtube.com/watch?v=I94yrKrDq-E

Having seen plenty of configure joystick functions from a user stand point, I had some criteria.

1. All players controls should be accessible from a single call to the configure function.  Navigating back a dialog just to assign the next player is bullshit.

2. Can handle analog and digital controls, and not become broken b/c the joystick is special.  Testing please let me know!

3. GUI but only Nes joystick GUI at this point.

Todo:

1. I should be able to detect when the GUIHotkey changes and focus the next field. A joystick does this already.

2. After seeing better written UDFs I am still considering better variable names.

3. When you can assign all types of input devices to a single player controls, you allow for multiplayer single player.  B/c of the re-write using both GUIHotkey controls and input fields, I have decided to wait and add this feature latter.  The data is setup to handle it, but the configurecontrols dialog creates all the fields based on the first control type.  Meaning at this point only one input type per player.

 

Note: These scripts require an SDL folder environment!

See download at end of post.

Configure Controls UDF.au3

#include-once
; #INDEX# =======================================================================================================================
; Title .........: Configure Controls
; AutoIt Version : 3.3.10.2 works older versions of AutoIt, unsure how far back
; Description ...: Methods to record user input to a customizable control array
; Author(s) .....: Xandy
; Dll ...........: SDL.dll, SDL_Image.dll
; Functions......:
;                   _configurecontrols($hgui, $screen, $players, $aControlLabelNames= Default) - - - returns $a_control[$controlmax][$g_cc_controldatamax]
;                   _cc_savecontrols($control, $filename, $controlinput)
;                   _cc_loadcontrols($filename, $controlmax, $g_cc_controldatamax)
;                   _cc_updatecontrolinput($control, byref $controlinput)
;                   _cc_nesgui_selectiondefine(byref $nespadbuttonselectsurf, byref $nespadrect)
;                   _cc_surfget($surf, byref $width, byref $height) - - - get the width and height of a SDL_Surface
;                   _cc_controlchanged($control, $player, $g_cc_controldatamax, $controlinput)
;                   _cc_openjoystick(byref $joystick, $joystickid, byref $joystickbuttons, byref $joystickaxes, byref $joystickhats)
;                   _cc_mouseoverrect($mousex, $mousey, $rect, $rect_y= default, $rect_w= default, $rect_h= default)
;                   _cc_deletecontrolinput(byref $controlinput, byref $control)
;                   _cc_createcontrolinput(byref $controlinput, $control, $hgui, $guirect)
;                   _cc_getkeycode($keycode)
;                   _cc_clearcontrols(byref $control)
; ===============================================================================================================================
; AutoIt source script file
#include <Misc.au3>
#include <WindowsConstants.au3>
#include <EditConstants.au3>
#include <GUIConstantsEx.au3>
#include <GuiComboBoxEx.au3>
#include "Include Lib\SDL v14\SDL.au3";created by AdmiralAlkex
#include "Include Lib\SDL v14\SDL_Image.au3";created by AdmiralAlkex
#include "Include Lib\GUIHotkey\GUIHotkey.au3";created by Mat
global $g_cc_controlsavepath= @scriptdir&"\Player Config\"
global $g_cc_controlsavefilename= "Player_"
global $g_cc_controldatamax= 3
global $analog_threshold= 20000
global $buttontypemax= 3
global $buttontype[$buttontypemax][2];min[type][0] and max[type][1] range
global enum $e_button= 0, $e_axis= 1, $e_hat= 2
$buttontype[$e_button][0]= 10
$buttontype[$e_button][1]= 10
$buttontype[$e_axis][0]= 20
$buttontype[$e_axis][1]= 9999
$buttontype[$e_hat][0]= 10000
$buttontype[$e_hat][1]= 19999


; #FUNCTION# ;===============================================================================
;
; Name...........: _configurecontrols
; Description ...: Saves player control files for keyboard or joystick
;                   Saves one file per player, but only if the data changes without 'cancel'
; Syntax.........: _configurecontrols($hgui, $screen, $players, $controlmax)
; Parameters ....: $hgui       - GUI handle, probably should be the one with $screen attached
;                  $screen     - SDL_Video Surface attached to $hgui
;                  $players    - How many possiable player config files to create or modify
;                  $aControlNames - An array that has the names of player controls.  If Default 8 Nespad controls will be used.
func _configurecontrols(byref $hgui, byref $screen, $players, $aControlNames= default)
    local $controlmax= 8

    if $aControlNames= default then
        local $controllabel[$controlmax]= ["Up", "Down", "Left", "Right", "Select", "Start", "B", "A"]
    else
        $controlmax= ubound($aControlNames)
        local $controllabel[$controlmax]
        for $i= 0 to $controlmax-1
            $controllabel[$i]= $aControlNames[$i]
        next
    endif
    local $a_winrect= wingetpos($hgui)
    local $joysticks= _SDL_NumJoysticks()
    local $player= 0
    local $joystickbuttons= -1, $joystickaxes= -1, $joystickhats= -1
    local $disableaxes= 0
    local $guirect= _SDL_Rect_Create(0, 40, $a_winrect[2]-1, 129);
    local $joystick= 0
    local $colorblack= 0
    local $control= _cc_loadcontrols($g_cc_controlsavepath&$g_cc_controlsavefilename&$player&".txt", $controlmax, $g_cc_controldatamax)
    local $joystickid= $control[0][0]
    local $confirm= 0
    ;Prepare screen surface
    _SDL_FillRect($screen, 0, _SDL_MapRGB($screen, 152, 152, 152));whole screen grey
    $drect= _SDL_Rect_Create(0, $guirect.y+$guirect.h, $a_winrect[2]-200, $a_winrect-$guirect.h);rect to fill with black
    _SDL_FillRect($screen, $drect, $colorblack);fill black area
    _SDL_Flip($screen)
    ;All GUI controls
    local $controlinput[$controlmax][2]
    local $filemenu= guictrlcreatemenu("File")
    local $filesaveconfig= guictrlcreatemenuitem("Save a backup copy", $filemenu)
    local $fileloadconfig= guictrlcreatemenuitem("Load a backup config", $filemenu)
    local $fileexit= guictrlcreatemenuitem("Exit", $filemenu)
    ;populate input controls and labels
    for $i= 0 to $controlmax-1;create gui button controls for nespad
        $controlinput[$i][0]= guictrlcreatelabel($controllabel[$i], $a_winrect[2]-200, $guirect.h+1+($i*25), 75, 25);controlinput
        guictrlsetfont(-1, 12, 1200)
    next
    _cc_createcontrolinput($controlinput, $control, $hgui, $guirect)
    ;Setup Cancel and Ok button
    $buttoncancel= guictrlcreatebutton("Cancel", $a_winrect[2]-170, $guirect.h+($controlmax*25)+20, 75, 20)
    guictrlsetfont($buttoncancel, 14, 400)
    $buttonok= guictrlcreatebutton("Ok", $a_winrect[2]-80, $guirect.h+($controlmax*25)+20, 55, 20)
    guictrlsetfont($buttonok, 14, 400)
    ;Player Number: label and combobox
    $playerlabel= guictrlcreatelabel("Player Number:", 45, 17, 175, 22)
    guictrlsetfont($playerlabel, 18, 400)
    $playercombo= guictrlcreatecombo("1", 45, 40, 55, 30)
    guictrlsetfont($playercombo, 16, 400)
    for $i= 1 to $players
        guictrlsetdata($playercombo, $i)
    next
    ;Setup Joystick Name: label and combobox
    $joysticklabel= guictrlcreatelabel(" Joystick Name: ", 45, 80, 175, 22)
    guictrlsetfont($joysticklabel, 18, 400)
    $joysticknamecombo= guictrlcreatecombo("Keyboard", 45, 103, 550, 20, $CBS_DROPDOWNLIST)
    guictrlsetfont($joysticknamecombo, 14, 400)
    for $i= 0 to $joysticks-1
        guictrlsetdata($joysticknamecombo, _SDL_JoystickName($i)&"|")
    next
    _guictrlcombobox_setcursel($joysticknamecombo, $control[0][0])
    ;Disable Axes checkbox
    $disableaxescheckbox= guictrlcreatecheckbox("Disable Axes", 245, 80, 95)
    guictrlsetfont($disableaxescheckbox, 9, 400)
    ;Setup Max Axes: label and input
    $axesmaxlabel= guictrlcreatelabel("Max Axes:", 370, 58, 85)
    guictrlsetfont($axesmaxlabel, 14, 400)
    guictrlsettip($axesmaxlabel, "Use when a joystick reports axises incorrectly, but still needs some axis")
    $axesmaxinput= guictrlcreateinput("", 370, 80, 45, 21, $ES_NUMBER)
    ;Setup Threshold: label and input
    $analog_thresholdlabel= guictrlcreatelabel("Threshold:", 485, 58, 90)
    guictrlsetfont($analog_thresholdlabel, 14, 400)
    $analog_thresholdinput= guictrlcreateinput($analog_threshold, 485, 80, 55, 21, $ES_NUMBER)
    _cc_updatecontrolinput($control, $controlinput)
    guisetstate()
    local $w= 0, $h= 0
    local $nespadsurf= _IMG_Load(@scriptdir&"\..\Graphics\Nespad\nes-pad.png")
    _cc_surfget($nespadsurf, $w, $h)
    local $nespadrect= _SDL_Rect_Create(10, $guirect.y+$guirect.h+1-10, $w, $h)
    local $highlightbutton= -1
    local $nespadbuttonselectsurf[$controlmax][4];[$control][0]surf, [1]rect, [2]possiable surf, [3]possiable rect
    local $mousex= 0, $mousey= 0;to detect graphic control under mouse
    ; Define GUI button selection graphic placement
    _cc_nesgui_selectiondefine($nespadbuttonselectsurf, $nespadrect);defines area to blit controls to gui
    local $rx= 0, $ry= 0, $rw= 0, $rh= 0
    local $rect_a= 0
    local $redraw= 1
    local $newbutton= "do nothing"
    local $oldhighlightbutton= -1
    ;local $msg= $joysticknamecombo
    local $msg= 0
    if $joystickid> 0 then;joystick
        $joystick= _cc_openjoystick($joystick, $joystickid, $joystickbuttons, $joystickaxes, $joystickhats)
    endif;joystickid> 0
    guictrlsetdata($axesmaxinput, $joystickaxes)
    $drect= _SDL_Rect_Create($nespadrect.x, $nespadrect.y, $nespadrect.w, $nespadrect.h);nes pad rect
    do
        if winactive($hgui) then
            switch $msg
                case $joysticknamecombo;joystick selection
                    _cc_deletecontrolinput($controlinput, $control)
                    _cc_clearcontrols($control)
                    $joystickid= _guictrlcombobox_getcursel($joysticknamecombo)
                    $control[0][0]= $joystickid
                    $joystick= _cc_openjoystick($joystick, $joystickid, $joystickbuttons, $joystickaxes, $joystickhats)
                    _cc_createcontrolinput($controlinput, $control, $hgui, $guirect)
                    _cc_updatecontrolinput($control, $controlinput)
                    guictrlsetdata($axesmaxinput, $joystickaxes)
                case $playercombo
                    if _cc_controlchanged($control, $player, $g_cc_controldatamax, $controlinput) then _cc_savecontrols($control, $g_cc_controlsavepath&$g_cc_controlsavefilename&$player&".txt", $controlinput)
                    _cc_deletecontrolinput($controlinput, $control)
                    $player= _guictrlcombobox_getcursel($playercombo)
                    $control= _cc_loadcontrols($g_cc_controlsavepath&$g_cc_controlsavefilename&$player&".txt", $controlmax, $g_cc_controldatamax)
                    _guictrlcombobox_setcursel($joysticknamecombo, $control[0][0]);use the first control type as combo selection
                    $joystickid= $control[0][0]
                    $joystick= _cc_openjoystick($joystick, $joystickid, $joystickbuttons,   $joystickaxes, $joystickhats)
                    _cc_createcontrolinput($controlinput, $control, $hgui, $guirect)
                    _cc_updatecontrolinput($control, $controlinput)
                    guictrlsetdata($axesmaxinput, $joystickaxes)
                case $disableaxescheckbox
                    $disableaxes= guictrlread($disableaxescheckbox)
                case $analog_thresholdinput
                    $analog_threshold= int(guictrlread($analog_thresholdinput))
                case $buttoncancel
                    exitloop
                case $fileexit
                    exitloop
                case $buttonok
                    $confirm= 1
                    exitloop
                case $fileloadconfig
                    $loadpath= fileopendialog("Load Control File", $g_cc_controlsavepath, "txt(*.txt)")
                    if @error= 0 then
                        $control= _cc_loadcontrols($loadpath, $controlmax, $g_cc_controldatamax)
                        $joystickid= $control[0][0];use the first control type as combo selection
                        _guictrlcombobox_setcursel($joysticknamecombo, $joystickid)
                        _cc_deletecontrolinput($controlinput, $control)
                        _cc_createcontrolinput($controlinput, $control, $hgui, $guirect)
                        $joystick= _cc_openjoystick($joystick, $joystickid, $joystickbuttons,   $joystickaxes, $joystickhats)
                        _cc_updatecontrolinput($control, $controlinput)
                    endif
                case $filesaveconfig
                    $savepath= filesavedialog("Save Config File", $g_cc_controlsavepath, "txt(*.txt)")
                    if @error= 0 then
                        $temp= stringmid($savepath, stringlen($savepath)-3);test file name extention
                        if $temp<> ".txt" then $savepath= $savepath&".txt";if no .txt ext add one
                        _cc_savecontrols($control, $savepath, $controlinput)
                    endif
                case $axesmaxinput
                    $joystickaxes= int(guictrlread($axesmaxinput))
            endswitch;msg
            $msg= guigetmsg()
            ;Enables image click for control selection
            if _ispressed(1) then;left mouse button down
                _SDL_GetMouseState($mousex, $mousey)
                for $i= 0 to 7;$controlmax-1 ; this example only has 8 nespad rects
                    $rect_a= $nespadbuttonselectsurf[$i][1]
                    if _cc_mouseoverrect($mousex, $mousey, $nespadbuttonselectsurf[$i][1].x-9, $nespadbuttonselectsurf[$i][1].y-9, $nespadbuttonselectsurf[$i][1].w+9, $nespadbuttonselectsurf[$i][1].h+9) then
                        $oldhighlightbutton= $highlightbutton
                        $highlightbutton= $i
                        guictrlsetstate($controlinput[$highlightbutton][1], $gui_focus)
                        exitloop
                    endif
                    if $nespadbuttonselectsurf[$i][2]<> 0 then
                        $rect_a= $nespadbuttonselectsurf[$i][3]
                        if _cc_mouseoverrect($mousex, $mousey, $nespadbuttonselectsurf[$i][3]) then
                            $oldhighlightbutton= $highlightbutton
                            $highlightbutton= $i
                            guictrlsetstate($controlinput[$highlightbutton][1], $gui_focus)
                            exitloop
                        endif
                    endif
                next
            endif;_ispressed(1) image clicking
            if $highlightbutton> -1 then;capture user input
                if int($joystickid)> 0 then;detect joystick
                    _SDL_JoystickUpdate($joystick)
                    ;joystick buttons
                    for $i= 0 to $joystickbuttons;check all the joystick buttons to find button pressed
                        if _SDL_JoystickGetButton($joystick, $i) > 0 then
                            $control[$highlightbutton][0]= $joystickid;keyboard or joystickid
                            $control[$highlightbutton][1]= 10;type: 10button
                            $newbutton= $i
                            $control[$highlightbutton][2]= $newbutton;button or state
                        endif
                    next;button
                    ;joystick axes
                    if $disableaxes<> 1 then;if axes not disabled
                        for $i= 0 to $joystickaxes-1;check the axi
                            $axisintensity= _SDL_JoystickGetAxis($joystick, $i)
                            if $axisintensity < -$analog_threshold then
                                $control[$highlightbutton][1]= $buttontype[$e_axis][0]+$i;type: > 19 to 9999 axis
                                $newbutton= "axis "&$i&" "&$axisintensity
                                $control[$highlightbutton][2]= $axisintensity+1
                            else
                                if $axisintensity > $analog_threshold then
                                    $control[$highlightbutton][1]= $buttontype[$e_axis][0]+$i;type: > 19 to 9999 axis
                                    $newbutton= "axis "&$i&" "&$axisintensity
                                    $control[$highlightbutton][2]= $axisintensity-1;button or state
                                endif
                            endif
                        next;axis
                    endif;disableaxis
                    ;joystick hats
                    for $i= 0 to $joystickhats
                        $hat= _SDL_JoystickGetHat($joystick, $i)
                        if $hat<> 0 then
                            $control[$highlightbutton][1]= $buttontype[$e_hat][0]+$i
                            $control[$highlightbutton][2]= $hat;button or state
                            $newbutton= "hat "&$i&" "&$hat
                        endif
                    next;hat
                endif;joystickid> 0
                if $newbutton== "do nothing" then
                    ;do nothing
                else;update the control input fields with user input
                    $control[$highlightbutton][0]= $joystickid;keyboard or joystickid
                    guictrlsetdata($controlinput[$highlightbutton][1], "J"&$joystickid&" "&$newbutton)
                    if $highlightbutton+1> $controlmax-1 then
                        $highlightbutton= -1
                        guictrlsetstate($buttonok, $gui_focus);last control set, select buttonok
                    else;select next input button to set
                        guictrlsetstate($controlinput[$highlightbutton+1][1], $gui_focus)
                    endif;select next control
                    sleep(400);easy way to prevent spam assignment
                    $newbutton= "do nothing"
                endif;newbutton
            else
                if _ispressed("1B") then exitloop;when no control is highlighted, ESC cancels out of configurejoystick()
            endif;highlightbutton> -1
            if $oldhighlightbutton<> $highlightbutton then $redraw= 1
            if $redraw= 1 then
                $redraw= 0
                _SDL_BlitSurface($nespadsurf, 0, $screen, $drect);draw nes pad
                ;draw button highlight
                if $highlightbutton> -1 and $highlightbutton< $controlmax then
                    _SDL_BlitSurface($nespadbuttonselectsurf[$highlightbutton][0], 0, $screen, $nespadbuttonselectsurf[$highlightbutton][1]);draw button selected rect1
                    if $nespadbuttonselectsurf[$highlightbutton][2]<> 0 then
                        _SDL_BlitSurface($nespadbuttonselectsurf[$highlightbutton][2], 0, $screen, $nespadbuttonselectsurf[$highlightbutton][3]);draw button selected rect2
                    endif
                endif;highlightbutton control range
                _SDL_UpdateRect($screen, $nespadrect.x, $nespadrect.y, $nespadrect.w, $nespadrect.h)
            endif;redraw
            ;find target button focus if any
            if $control[0][0]= 0 then
                $focus_s= controlgetfocus($hgui)
                for $i= 0 to $controlmax-1
                    if $focus_s= "msctls_hotkey32"&$i+1 then
                        $oldhighlightbutton= $highlightbutton
                        $highlightbutton= $i
                        exitloop
                    endif
                next
            else
                $focush= ControlGetHandle ($hgui, "", ControlGetFocus($hgui));find the windows control focus
                $focusid= _WinAPI_GetDlgCtrlID ($focush);find the focus controlid
                for $i= 0 to $controlmax-1
                    if $focusid= $controlinput[$i][1] then
                        $oldhighlightbutton= $highlightbutton
                        $highlightbutton= $i
                    endif;a= buttoninput[i][1]
                next
            endif
        endif;winactive(hgui)
    until $msg= $gui_event_close
    if $confirm= 1 then _cc_savecontrols($control, $g_cc_controlsavepath&$g_cc_controlsavefilename&$player&".txt", $controlinput)
    for $i= 0 to $controlmax-1
        _SDL_FreeSurface($nespadbuttonselectsurf[$i][0])
    next
    guictrldelete($filemenu)
    guictrldelete($playerlabel)
    guictrldelete($playercombo)
    guictrldelete($joysticknamecombo)
    guictrldelete($joysticklabel)
    guictrldelete($disableaxescheckbox)
    guictrldelete($axesmaxlabel)
    guictrldelete($axesmaxinput)
    guictrldelete($analog_thresholdlabel)
    guictrldelete($analog_thresholdinput)
    guictrldelete($buttoncancel)
    guictrldelete($buttonok)
    for $i= 0 to $controlmax-1
        guictrldelete($controlinput[$i][0]);delete label
        if $control[0][0]= 0 then
            _GUICtrlHotkey_Delete($controlinput[$i][1]);delete hotkey control
        else
            guictrldelete($controlinput[$i][1]);delete gui input control
        endif
    next
    _SDL_FreeSurface($nespadsurf)
    _SDL_FillRect($screen, 0, $colorblack)
    _SDL_Flip($screen)
    sleep(100)
    return $confirm
EndFunc;_configurecontrols($players, $controlmax)

; Save controls to disk
func _cc_savecontrols($control, $filename, $controlinput)
    dircreate($g_cc_controlsavepath)
    $file= fileopen($filename, 2)
    if $file<> -1 then
        for $i= 0 to ubound($control)-1
            if $control[0][0]= 0 then
                $control[$i][0]= 0
                $control[$i][1]= 10
                $control[$i][2]= _GUICtrlhotkey_GetHotkeyCode($controlinput[$i][1])
            endif
            for $ii= 0 to $g_cc_controldatamax-1
                filewriteline($file, $control[$i][$ii])
            next
        next
    else
        msgbox(0, "Save Error", "Player controls could NOT be Saved to:"&@CRLF&$filename)
    endif
    fileclose($file)
EndFunc;_cc_savecontrols($control, $filename, $controlinput)

; Load controls from disk, return control[controlmax][controldatamax]
func _cc_loadcontrols($filename, $controlmax, $g_cc_controldatamax)
    local $control[$controlmax][$g_cc_controldatamax]
    $file= fileopen($filename)
    if $file<> -1 then
        for $i= 0 to $controlmax-1
            for $ii= 0 to $g_cc_controldatamax-1
                $control[$i][$ii]= int(filereadline($file))
            next
        next
        fileclose($file)
    else
        msgbox(0, "Load Error", "Player controls could NOT be Loaded", 2000)
    endif;file<> -1
    return $control
EndFunc;_cc_loadcontrols($filename, $controlmax, $g_cc_controldatamax)()

; updates the control input fields
func _cc_updatecontrolinput($control, byref $controlinput)
    local $newbutton= ""
    for $i= 0 to ubound($control)-1
        if $control[0][0]= 0 then
            _GUICtrlHotkey_SetHotkeyCode($controlinput[$i][1], $control[$i][2])
        else
            switch $control[$i][1]
                case $buttontype[$e_button][0] to $buttontype[$e_button][1]
                    $newbutton= $control[$i][2]
                case $buttontype[$e_axis][0] to $buttontype[$e_axis][1];axis
                    $newbutton= "axis "&$control[$i][1]-20&" "&$control[$i][2]
                case $buttontype[$e_hat][0] to $buttontype[$e_hat][1];hat
                    $newbutton= "hat "&$control[$i][1]-10000&" "&$control[$i][2]
                case else;to prevent a J1, J0..controlmax spam on blank controls
                    $newbutton= Null
            endswitch
            if $newbutton<> Null then $newbutton= "J"&$control[$i][0]&" "&$newbutton
            guictrlsetdata($controlinput[$i][1], $newbutton)
        endif
    next
EndFunc;_cc_updatecontrolinput($control, byref $controlinput)

; Sets the positions and images of selected buttons on the nespad gui
func _cc_nesgui_selectiondefine(byref $nespadbuttonselectsurf, byref $nespadrect)
    local $graphicpath= @scriptdir&"\..\Graphics\Nespad"
    $nespadbuttonselectsurf[0][0]= _IMG_Load($graphicpath&"\nes-select-up 95 105 28 26.png");up
    $nespadbuttonselectsurf[0][1]= _SDL_Rect_Create($nespadrect.x+95, $nespadrect.y+105, 28, 26)
    $nespadbuttonselectsurf[1][0]= _IMG_Load($graphicpath&"\nes-select-down 95 177 28 26.png");down
    $nespadbuttonselectsurf[1][1]= _SDL_Rect_Create($nespadrect.x+95, $nespadrect.y+177, 28, 26)
    $nespadbuttonselectsurf[2][0]= _IMG_Load($graphicpath&"\nes-select-left 58 140 25 29.png");left
    $nespadbuttonselectsurf[2][1]= _SDL_Rect_Create($nespadrect.x+58, $nespadrect.y+140, 25, 29)
    $nespadbuttonselectsurf[3][0]= _IMG_Load($graphicpath&"\nes-select-right 133 141 26 26.png");right
    $nespadbuttonselectsurf[3][1]= _SDL_Rect_Create($nespadrect.x+133, $nespadrect.y+141, 26, 26)
    $nespadbuttonselectsurf[4][0]= _IMG_Load($graphicpath&"\nes-select-select 228 178 30 12.png");select button highlight
    $nespadbuttonselectsurf[4][1]= _SDL_Rect_Create($nespadrect.x+228, $nespadrect.y+178, 30, 12)
    $nespadbuttonselectsurf[4][2]= _IMG_Load($graphicpath&"\nes-select-label 205 125 73 13.png");select text label
    $nespadbuttonselectsurf[4][3]= _SDL_Rect_Create($nespadrect.x+205, $nespadrect.y+125, 73, 13)
    $nespadbuttonselectsurf[5][0]= _IMG_Load($graphicpath&"\nes-select-select 228 178 30 12.png");start button highlight
    $nespadbuttonselectsurf[5][1]= _SDL_Rect_Create($nespadrect.x+306, $nespadrect.y+178, 30, 12)
    $nespadbuttonselectsurf[5][2]= _IMG_Load($graphicpath&"\nes-select-start-label 295 125 61 13.png");start text label
    $nespadbuttonselectsurf[5][3]= _SDL_Rect_Create($nespadrect.x+289, $nespadrect.y+125, 61, 13)
    $nespadbuttonselectsurf[6][0]= _IMG_Load($graphicpath&"\nes-select-B.png");button B
    $nespadbuttonselectsurf[6][1]= _SDL_Rect_Create($nespadrect.x+413, $nespadrect.y+170, 25, 24)
    $nespadbuttonselectsurf[6][2]= _IMG_Load($graphicpath&"\nes-select-B-label 447 224 15 14.png");B text label
    $nespadbuttonselectsurf[6][3]= _SDL_Rect_Create($nespadrect.x+447, $nespadrect.y+223, 15, 14)
    $nespadbuttonselectsurf[7][0]= _IMG_Load($graphicpath&"\nes-select-B.png");A button highlight
    $nespadbuttonselectsurf[7][1]= _SDL_Rect_Create($nespadrect.x+491, $nespadrect.y+170, 25, 24)
    $nespadbuttonselectsurf[7][2]= _IMG_Load($graphicpath&"\nes-select-A-label 524 223 15 15.png");A text label
    $nespadbuttonselectsurf[7][3]= _SDL_Rect_Create($nespadrect.x+524, $nespadrect.y+223, 15, 15)
EndFunc;_cc_nesgui_selectiondefine(byref $nespadbuttonselectsurf, byref $nespadrect)(

; Get width and Height from a SDL Surface
func _cc_surfget($surf, byref $w, byref $h)
    $struct= DllStructCreate($tagSDL_SURFACE, $surf)
    $w= DllStructGetData($struct, "w")
    $h= DllStructGetData($struct, "h")
    $struct= 0
EndFunc;_cc_surfget($surf, byref $w, byref $h)

; _cc_controlchanged() compairs the current controls to the user control file on disk
func _cc_controlchanged($control, $player, $g_cc_controldatamax, $controlinput)
    local $controlmax= ubound($control)
    local $control_temp= _cc_loadcontrols($g_cc_controlsavepath&$g_cc_controlsavefilename&$player&".txt", $controlmax, $g_cc_controldatamax)
    for $i= 0 to $controlmax-1
        for $ii= 0 to $g_cc_controldatamax-1
            if $control[$i][0]= 0 then
                if _GUICtrlHotkey_GetHotkeyCode($controlinput[$i][1])<> $control_temp[$i][$ii] then return 1
            else
                if $control[$i][$ii]<> $control_temp[$i][$ii] then return 1
            endif
        next;$ii
    next;$i
    return 0
EndFunc;_cc_controlchanged($control, $player, $g_cc_controldatamax)

; returns a joystick object
func _cc_openjoystick(byref $joystick, $joystickid, byref $joystickbuttons, byref $joystickaxes, byref $joystickhats)
    _SDL_JoystickClose($joystick)
    $joystick= 0
    $joystickbuttons= -1
    $joystickaxes= -1
    $joystickhats= -1
    if $joystickid> 0 then;joystick
        $joystick= _SDL_JoystickOpen($joystickid-1);b/c joystickid is 1 greater to allow for keyboard in the combobox
        $joystickbuttons= _SDL_JoystickNumButtons($joystick)
        $joystickaxes= _SDL_JoystickNumAxes($joystick)
        $joystickhats= _SDL_JoystickNumHats($joystick)
    endif
    return $joystick
EndFunc;_cc_openjoystick($joystickid, byref $joystickbuttons, byref $joystickaxes, byref $joystickhats)

; $rect is for a SDL_Rect, however if $rect_y<> default then $rect is treated as $rect_x
func _cc_mouseoverrect($mousex, $mousey, $rect, $rect_y= default, $rect_w= default, $rect_h= default)
    if $rect_y= default then
        if $mousex> $rect.x-1 and $mousex< $rect.x+$rect.w+1 then
            if $mousey> $rect.y-1 and $mousey< $rect.y+$rect.h+1 then
                return 1
            endif
        endif
    else
        if $mousex> $rect-1 and $mousex< $rect+$rect_w+1 then
            if $mousey> $rect_y-1 and $mousey< $rect_y+$rect_h+1 then
                return 1
            endif
        endif
    endif
    return 0
EndFunc;_cc_mouseoverrect($x, $y, $w, $h)

func _cc_deletecontrolinput(byref $controlinput, byref $control)
    ;if $control[0][0]= 0 then
        for $i= 0 to ubound($control)-1
            _GUICtrlHotkey_Delete($controlinput[$i][1])
        next
    ;endif
EndFunc;_cc_deletecontrolinput(byref $controlinput, byref $control)

; uses the first control type to determine guihotkey controls or input fields
func _cc_createcontrolinput(byref $controlinput, $control, $hgui, $guirect)
    if $control[0][0]= 0 then;hotkey controls
        for $i= 0 to ubound($controlinput)-1
            guictrldelete($controlinput[$i][1])
            $controlinput[$i][1]= _GUICtrlHotkey_Create($hgui, $guirect.w-124, $guirect.h+($i*25), 121, 25)
        next
    else;input fields for joystick controls
        for $i= 0 to ubound($controlinput)-1
            guictrldelete($controlinput[$i][1]);delete input field
            $controlinput[$i][1]= guictrlcreateinput("", $guirect.w-124, $guirect.h+($i*25), 121, 25)
            guictrlsendmsg(-1, $EM_SETREADONLY, 1, 0);read-only
        next
    endif
EndFunc;_cc_createcontrolinput(byref $controlinput, $control, $hgui, $guirect)

; First time I've done this so I might be explaining wrong!
; Adapted from Mat's GUIHotkey.au3 to produce a _ispressed() hex keycode
; $keycode : keycode > 255 will have it's key modifier attributes removed
; returns a single _ispressed() keycode
func _cc_getkeycode($keycode)
    Local $iLoByte= $keycode
    if $keycode> 255 then
        Local $iHiByte = BitShift($keycode, 8)
        $iLoByte = BitAND($keycode, 0xFF)
    endif
    return hex($iLoByte)
EndFunc;_cc_getkeycode($keycode)

; clear the control object
func _cc_clearcontrols(byref $control)
    for $i= 0 to ubound($control)-1
        for $ii= 0 to $g_cc_controldatamax-1
            $control[$i][$ii]= 0
        next
    next
EndFunc;_cc_clearcontrols(byref $control)
Simple Example

#include "configure controls udf.au3"
global $debug= 0

test_main()
func test_main()
    local $players= 3
    local $controlmax= 8, $controldatamax= 3
    local $player[$players][3];control, x, y
    ;AutoIt options
    opt("GUICloseOnESC", 0);disable escape closing AutoIt dialog
    opt("GUIResizeMode", $GUI_DOCKALL);force consistent control spacing of gui controls
    ;Windows GUI with SDL
    $hgui= guicreate(@scriptname, 850, 600, default, default, bitor($WS_MAXIMIZEBOX, $WS_MINIMIZEBOX));$WS_SIZEBOX
    if $debug= 0 then EnvSet("SDL_WINDOWID", $hgui);remark this to create AutoIt window and recieve error messages from AutoIt
    guisetstate();show screen hgui, screen window
    ;init SDL
    _SDL_Init_image()
    _SDL_Init($_SDL_INIT_EVERYTHING)
    ;SDL Video Surface $screen
    $screen= _SDL_SetVideoMode(850, 600, 0, $_SDL_SWSURFACE);bitor($_SDL_SWSURFACE, $_SDL_RESIZABLE)
    local $joysticks= _SDL_NumJoysticks();
    local $joystickobj[$joysticks]
    if _configurecontrols($hgui, $screen, $players)= 1 then
        for $i= 0 to $players-1
            $player[$i][0]= _cc_loadcontrols($g_cc_controlsavepath&$g_cc_controlsavefilename&$i&".txt", $controlmax, $controldatamax)
            $control= $player[0][0]
            if $control[0][0]> 0 then
                $joystickobj[$control[0][0]-1]= _SDL_JoystickOpen($control[0][0]-1)
            else;keyboard convert saved keypresses to _ispressed hex codes
                for $ii= 0 to $controlmax-1
                    $control[$ii][2]= _cc_getkeycode($control[$ii][2])
                next
                $player[0][0]= $control
            endif
        next

        local $label= guictrlcreatelabel("Press the control assigned to 'Up', to exit", 15, 15)
        do
            if $control[0][0]= 0 then
                if _ispressed($control[0][2]) then exitloop
            else
                _SDL_JoystickUpdate($joystickobj[$control[0][0]-1]);update the joystick in question
                switch $control[0][1]
                case $buttontype[$e_button][0] to $buttontype[$e_button][1]
                    if _SDL_JoystickGetButton($joystickobj[$control[0][0]-1], $control[0][2])> 0 then exitloop
                case $buttontype[$e_axis][0] to $buttontype[$e_axis][1];axis
                    $axis= _SDL_JoystickGetAxis($joystickobj[$control[0][0]-1], $control[0][1]-$buttontype[$e_axis][0])
                    if $control[0][2]< 0 then
                        if $axis< $control[0][2] - 1 then exitloop
                    else
                        if $axis> $control[0][2] - 1 then exitloop
                    endif
                case $buttontype[$e_hat][0] to $buttontype[$e_hat][1];hat
                    $hat= _SDL_JoystickGetHat($joystickobj[$control[0]-1], $control[0][1]-$buttontype[$e_hat][0])
                    if $hat= $control[0][2] then exitloop
                endswitch
            endif
        until guigetmsg()= $gui_event_close
    endif
    ;close systems
    If $__SDL_DLL <> -1 Then _SDL_Quit();"Once upon a time... You saw me ;)"
    If $__SDL_DLL_image <> -1 Then _SDL_Shutdown_image()
EndFunc;main()
Tank Player Example:

Tank.au3

#include <Array.au3>;_arraydisplay()
#include "configure controls udf.au3"
#include "tank.h.au3"
global $debug= 0
; AutoIt options
opt("GUICloseOnESC", 0);disable escape closing AutoIt dialog
main()
func main()
    makeconsole(); create a console gui
    ;then make transpartent gui main dialog
    local $hgui = GUICreate("Tank", @DesktopWidth, @DesktopHeight, 0, 0, $WS_POPUP, $WS_EX_LAYERED)
    _WinAPI_SetLayeredWindowAttributes($hgui, 0x000000, 255);transparency of main screen $hgui, black, 100%transparent
    if $debug= 0 then EnvSet("SDL_WINDOWID", $hgui);Attaches the next call to _SDL_SetVideoMode() surface to $hgui, idk really
    ; $debug turns off the attachment to the SDL Video Surface, and then gives us 2 windows 1 for the $hgui and 1 for the SDL Video Surface (I think).  This will allow SciTE or whatever to pin point the errors and return them rather then just hang the script.
    ; Now $debug is a useful variable b/c if you ever need to detect window active in say a nested function environment then you can also check against $debug to toggle the check of active b/c in debug mode you'll have 2
    ; windows, $hgui might not be the window you need it to be, when debuging whatever problem you are debuging.  $debug can be used to easily avoid this problem.  if(winactive($hgui) or $debug= 1)
    _SDL_Startup_sge()
    _SDL_Init_image()
    _SDL_Init($_SDL_INIT_EVERYTHING)
    local $screen = _SDL_SetVideoMode(@DesktopWidth, @DesktopHeight, 32, $_SDL_HWSURFACE);$screen is now the SDL Video Surface
    _AutoItObject_Startup(0)
    for $i= 0 to $players-1
        $otank[$i]= tankobject()
    next
    local $tank_controlnames[]= ["Forward", "Reverse", "Left", "Right", "Nitro", "Jump", "Drill", "a"]
    loadplayercontrols()
    maketrig()
    loadpics()
    $redraw= 1
    guisetstate();main screen turn on
    while 1
        switch guigetmsg()
            case $gui_event_close
                exitloop
            case $fileexit
                exitloop
            case $fileconfigurecontrols
                winsetstate($hguiconsole, "", @sw_hide);the console doesn't work in the next dialog
                _WinAPI_SetLayeredWindowAttributes($hgui, 0x000001, 255);transparency to color not in configure controls dialog
                _configurecontrols($hgui, $screen, $players, $tank_controlnames);dialog for players to setup controls
                loadplayercontrols();reload the player control files
                _WinAPI_SetLayeredWindowAttributes($hgui, 0x000000, 255);transparency back to colorblack
                winsetstate($hguiconsole, "", @sw_show);
        endswitch
        _SDL_FillRect($screen, 0, $colorblack);clear the screen surface
        for $i= 0 to $players-1
            $control= $a_tankcontrol[$i]
            tankcontrols($otank[$i], $i)
            $otank[$i].loopactions()
            $otank[$i].draw($screen, $i)
        next
        _SDL_Flip($screen);update the screen surface
    wend;main loop
    _SDL_Quit()
    _SDL_Shutdown_image()
    _SDL_Shutdown_sge()
EndFunc;main()

func loadplayercontrols()
    for $i= 0 to $players-1
        $control= _cc_loadcontrols($g_cc_controlsavepath & $g_cc_controlsavefilename & $i & ".txt", $controlmax, $controldatamax)
        for $ii= 0 to $controlmax-1
            if $control[$ii][0]> 0 then
                $joystickobj[$i]= _SDL_JoystickOpen($control[$ii][0]-1)
                consolewrite("Joystick "&$control[$i][0]-1& "opened")
                exitloop
            else;convert keystrokes
                $control[$ii][2]= _cc_getkeycode($control[$ii][2])
            endif
        next
        $a_tankcontrol[$i]= $control
    next
EndFunc;loadplayercontrols()

func makeconsole($startup_output= "Hello world.")
    $hguiconsole= guicreate("Tank", $consolew, $consoleh)
    $filemenu= guictrlcreatemenu("File")
    $fileexit= guictrlcreatemenuitem("Exit", $filemenu)
    $g_consoleedit= guictrlcreateedit($startup_output, 10, 20, 300, 80)
    $fileconfigurecontrols= guictrlcreatemenuitem("Configure Controls", $filemenu)
    guictrlsendmsg($g_consoleedit, $EM_SETREADONLY, 1, 0);read-only
    guisetstate()
EndFunc;makeconsole()
Tank.h.au3

#include-once
#include "tank.global.au3"
#include "configure controls udf.au3"
func consoleout($output)
    ; insert new line at end of edit control
    $iEnd = StringLen(GUICtrlRead($g_consoleedit));Melba23 ref: http://www.autoitscript.com/forum/topic/110948-add-text-to-edit-box-and-scroll-it-down/#entry778671
    _GUICtrlEdit_SetSel($g_consoleedit, $iEnd, $iEnd)
    _GUICtrlEdit_Scroll($g_consoleedit, $SB_SCROLLCARET)
    guictrlsetdata($g_consoleedit, @crlf & $output, 1)
EndFunc;consoleout($output)

func loadpics()
    $path= @scriptdir & "\..\graphics\"
    consoleout("Load graphics from: " & $path&@crlf)
    local $w= 0, $h= 0
    for $a= 0 to 180-1
        for $i= 0 to $tank_tredframemax-1
            $tank_tredl[$a][$i]= _SDL_LoadBMP($path & "lefttred\"&$a&"_"&$i&".bmp")
            _SDL_SetColorKey($tank_tredl[$a][$i], $_SDL_SRCCOLORKEY, _SDL_MapRGB($tank_tredl[$a][$i], 0x00, 0x00, 0x00))
            $tank_tredr[$a][$i]= _SDL_LoadBMP($path & "righttred\"&$a&"_"&$i&".bmp")
            _SDL_SetColorKey($tank_tredr[$a][$i], $_SDL_SRCCOLORKEY, _SDL_MapRGB($tank_tredl[$a][$i], 0x00, 0x00, 0x00))
        next;tred frame
        $tank_body[$a]= _SDL_LoadBMP($path & "body\"&$a&".bmp")
        _SDL_SetColorKey($tank_body[$a], $_SDL_SRCCOLORKEY, _SDL_MapRGB($tank_body[$a], 0x00, 0x00, 0x00))
        for $i= 0 to $tank_drillframemax-1
            $tank_drill[$a][$i]= _SDL_LoadBMP($path & "drill\"&$a&"_"&$i&".bmp")
            _SDL_SetColorKey($tank_drill[$a][$i], $_SDL_SRCCOLORKEY, _SDL_MapRGB($tank_drill[$a][$i], 0x00, 0x00, 0x00))
        next;drill frame
    next;angle
    for $i= 0 to $tank_personmax-1
        $tank_person[0][$i]= _SDL_LoadBMP($path & "person\"&$i&".bmp")
        _SDL_SetColorKey($tank_person[0][$i], $_SDL_SRCCOLORKEY, _SDL_MapRGB($tank_person[0][$i], 0x00, 0x00, 0x00))
    next
    _cc_surfget($tank_person[0][0], $w, $h)
    if $players> 1 then
        for $i= 1 to $players-1
            $colormask= $i*25
            if $colormask> 255 then
                while $colormask> 255
                    $colormask-= 255
                wend
            endif
            for $ii= 0 to $tank_personmax-1
                $tank_person[$i][$ii]= _SDL_CreateRGBSurface($_SDL_HWSURFACE, $w, $h, 32, $colormask, $colormask, $colormask, 255)
                _SDL_BlitSurface($tank_person[0][$ii], 0, $tank_person[$i][$ii], 0)
            next
        next
    endif
    consoleout("Graphics Loaded")
EndFunc;end loadpics()

func fixa($a)
    if $a>= 359.9 then $a-= 360;
    if $a< 0 then $a+= 359.9;
    return $a
EndFunc;end fixa($a)

func maketrig()
    for $a= 0 to 359
        $mycos[$a]= cos($a*3.1416/180)
        $mysin[$a]= sin($a*3.1416/180)
    next
EndFunc;end maketrig()

func tankcontrols(byref $tankobj, $player)
    local $action= -1
    local $control= $a_tankcontrol[$player]
    _SDL_JoystickUpdate($joystickobj[$player])
    for $i= 0 to $controlmax-1
        $action= -1
        if $control[$i][0]> 0 then;joystick
            ;_SDL_JoystickUpdate($joystickobj[$player])
            ;joystick axis
            switch $control[$i][1];button type
            case $buttontype[$e_button][0] to $buttontype[$e_button][1];gamepad button
                if _SDL_JoystickGetButton($joystickobj[$player], $control[$i][2])> 0 then
                    $action= $i
                endif
            case $buttontype[$e_axis][0] to $buttontype[$e_axis][1];axis
                $axis= _SDL_JoystickGetAxis($joystickobj[$player], $control[$i][1]-$buttontype[$e_axis][0])
                if $control[$i][2]< 0 then
                    if $axis< $control[$i][2] - 1 then $action= $i
                else
                    if $axis> $control[$i][2] - 1 then $action= $i
                endif
            case $buttontype[$e_hat][0] to $buttontype[$e_hat][1];hat
                $hat= _SDL_JoystickGetHat($joystickobj[$player], $control[$i][1]-$buttontype[$e_hat][0])
                if $hat= $control[$i][2] then $action= $i
            endswitch
        else;keyboard
            if _ispressed($control[$i][2], $hdll) then
                $action= $i
            endif
        endif;joystick or keyboard

        if $action> -1 then
            if $action= $e_tankctrl_forward then
                $tankobj.control_forward= 1
            endif
            if $action= $e_tankctrl_backward then
                $tankobj.control_backward= 1
            endif
            if $action= $e_tankctrl_left then
                $tankobj.control_left= 1
            endif
            if $action= $e_tankctrl_right then
                $tankobj.control_right= 1
            endif
            if $action= $e_tankctrl_nitro then
                $tankobj.control_nitro= 1
            endif
            if $action= $e_tankctrl_jump then
                $tankobj.control_jump= 1
            endif
            if $action= $e_tankctrl_drill then
                $tankobj.control_drill= 1
            endif
        endif
    next;control
EndFunc;end tankobjectcontrols()
Tankclass.au3

#include-once
#include "tank.global.au3"
#include "configure controls udf.au3"
func tankobject($iStartup = False)
    local $oObj = _AutoItObject_Create()
    _AutoItObject_AddMethod($oObj, "draw", "tankobjectdraw")
    _AutoItObject_AddMethod($oObj, "loopactions", "tankobjectloopactions")
    _AutoItObject_AddProperty($oObj, "x", $ELSCOPE_Public, random(32, @DesktopWidth-32, @DesktopHeight-32))
    _AutoItObject_AddProperty($oObj, "y", $ELSCOPE_Public, random(32, 359))
    _AutoItObject_AddProperty($oObj, "drillframe", $ELSCOPE_Public, 0)
    _AutoItObject_AddProperty($oObj, "angle", $ELSCOPE_Public, random(0, 359))
    _AutoItObject_AddProperty($oObj, "acc", $ELSCOPE_Public, 0)
    _AutoItObject_AddProperty($oObj, "v", $ELSCOPE_Public, 0)
    _AutoItObject_AddProperty($oObj, "anglev", $ELSCOPE_Public, 0)
    _AutoItObject_AddProperty($oObj, "surf", $ELSCOPE_Public, 0)
    _AutoItObject_AddProperty($oObj, "tredframel", $ELSCOPE_Public, 0)
    _AutoItObject_AddProperty($oObj, "tredframer", $ELSCOPE_Public, 0)
    _AutoItObject_AddProperty($oObj, "distancetraveled", $ELSCOPE_Public, 100000)
    _AutoItObject_AddProperty($oObj, "distancetraveledl", $ELSCOPE_Public, 100000)
    _AutoItObject_AddProperty($oObj, "distancetraveledr", $ELSCOPE_Public, 100000)
    _AutoItObject_AddProperty($oObj, "nitroup", $ELSCOPE_Public, 0)
    _AutoItObject_AddProperty($oObj, "jumpy", $ELSCOPE_Public, 0)
    _AutoItObject_AddProperty($oObj, "jumpa", $ELSCOPE_Public, 0)
    _AutoItObject_AddProperty($oObj, "jumpv", $ELSCOPE_Public, 0)
    _AutoItObject_AddProperty($oObj, "updown", $ELSCOPE_Public, 0)
    ;controls
    local $a_control[$controlmax][$controldatamax]
    _AutoItObject_AddProperty($oObj, "a_control", $ELSCOPE_Public, $a_control)
    _AutoItObject_AddProperty($oObj, "control_forward")
    _AutoItObject_AddProperty($oObj, "control_backward")
    _AutoItObject_AddProperty($oObj, "control_left")
    _AutoItObject_AddProperty($oObj, "control_right")
    _AutoItObject_AddProperty($oObj, "control_drill")
    _AutoItObject_AddProperty($oObj, "control_jump")
    _AutoItObject_AddProperty($oObj, "control_nitro")
    $path= @scriptdir & "\..\graphics\"
    $oObj.surf= _SDL_LoadBMP($path & "drill\"&0&"_"&0&".bmp");create a tank surface to construct the tank on
    _SDL_SetColorKey($oObj.surf, $_SDL_SRCCOLORKEY, _SDL_MapRGB($oObj.surf, 0x00, 0x00, 0x00))
    if $iStartup then $oObj.Startup
    return $oObj
EndFunc;end tankobject

func tankobjectdraw($oself, $screen, $player)
    _SDL_FillRect($oself.surf, 0, $colorblack);clear the tank surface
    $angleint= int($oself.angle/2)
    _SDL_BlitSurface($tank_tredl[$angleint][$oself.tredframel], 0, $oself.surf, 0);left tred
    _SDL_BlitSurface($tank_tredr[$angleint][$oself.tredframer], 0, $oself.surf, 0);right tred
    _SDL_BlitSurface($tank_body[$angleint], 0, $oself.surf, 0)
    _SDL_BlitSurface($tank_drill[$angleint][$oself.drillframe], 0, $oself.surf, 0)
    $personframe= int($oself.angle/360*$tank_personmax)
    _SDL_BlitSurface($tank_person[$player][$personframe], 0, $oself.surf, 0);draw person rider
    if $oself.jumpy< 0 then;surf,x,y,r,c,al
        _sge_FilledCircleAlpha($screen, $oself.x+32, $oself.y+48, 10+($oself.jumpy/6), _SDL_MapRGB($screen, 10, 10, 10), 100-($oself.jumpy));
        _SDL_BlitSurface($oself.surf, 0, $screen, _SDL_Rect_Create($oself.x, $oself.y+$oself.jumpy, 64, 64));draw the tank surface
    else
        _SDL_BlitSurface($oself.surf, 0, $screen, _SDL_Rect_Create($oself.x, $oself.y, 64, 64));draw the tank surface
    endif;endif jumpy< 0
EndFunc;end draw()

func tankobjectloopactions($oself)
    $oself.distancetraveledl= $oself.distancetraveledl+$oself.v+(17*$oself.anglev*3.1416/180)
    $oself.distancetraveledr= $oself.distancetraveledr+$oself.v+(-17*$oself.anglev*3.1416/180)
    $oself.distancetraveled= $oself.distancetraveled+$oself.v
    if $oself.jumpy> -1 then
        if $oself.control_forward= 1 then;26 up arrow
            $oself.acc= $oself.acc+.0009
            $oself.v= $oself.v+$oself.acc
        else
            $oself.v= $oself.v*.9
            if $oself.acc> 0 then $oself.acc= $oself.acc*.0005
        endif
        if $oself.control_backward= 1 then;28 down arrow
            ;$oself.x-= $mysin[$tank_angle]
            $oself.x= $oself.x- $mysin[$oself.angle]
            $oself.y= $oself.y+ $mycos[$oself.angle]
            $oself.distancetraveledl= $oself.distancetraveledl-1
            $oself.distancetraveledr= $oself.distancetraveledr-1
        endif
        if $oself.control_left= 1 then;25 left arrow
            if $oself.anglev> 0 then $oself.anglev= 0
            $oself.anglev= $oself.anglev-.1
            $oself.angle= $oself.angle+$oself.anglev
        endif
        if $oself.control_right= 1 then;27 right arrow
            if $oself.anglev< 0 then $oself.anglev= 0
            $oself.anglev= $oself.anglev+.1
            $oself.angle= $oself.angle+$oself.anglev
        endif
        if $oself.control_drill= 1 then;44 'd'
            $oself.drillframe= $oself.drillframe+1
            if $oself.drillframe> $tank_drillframemax-1 then $oself.drillframe= $oself.drillframe-$tank_drillframemax
        endif
        if $oself.control_nitro= 1 then;0x4E 'n'
            if $oself.nitroup= 0 then
                $oself.nitroup= 5
            endif
        endif
        if $oself.control_jump= 1 then
            $oself.control_jump= 0
            if $oself.jumpy> -1 and $oself.updown= 0 then
                $oself.jumpy= -45
            endif
        endif
    else
        $oself.jumpy= $oself.jumpy+2
    endif;jumpy= 0
    if $oself.nitroup> 0 then
        $oself.control_nitro= 0
        $oself.v= $oself.v*1.2
        $oself.nitroup= $oself.nitroup-1
    endif;endif $nitroup> 50

    if $oself.x< -31 then $oself.x= $oself.x+@DesktopWidth
    if $oself.x> @DesktopWidth then $oself.x= $oself.x-@DesktopWidth
    if $oself.y< -31 then $oself.y= $oself.y+@DesktopHeight
    if $oself.y> @DesktopHeight+31 then $oself.y= $oself.y-@DesktopHeight
    if $oself.distancetraveled< 0 then $oself.distancetraveled= $oself.distancetraveled+100000
    if $oself.distancetraveledl< 0 then $oself.distancetraveledl= $oself.distancetraveledl+100000
    if $oself.distancetraveledr< 0 then $oself.distancetraveledr= $oself.distancetraveledr+100000
    $oself.tredframel= $tank_tredframemax-1-mod(int($oself.distancetraveledl/$tank_tredframemax), $tank_tredframemax)
    $oself.tredframer= $tank_tredframemax-1-mod(int($oself.distancetraveledr/$tank_tredframemax), $tank_tredframemax)
    if $oself.control_left= 0 and $oself.control_right= 0 then $oself.anglev= 0
    $oself.control_forward= 0
    $oself.control_backward= 0
    $oself.control_left= 0
    $oself.control_right= 0
    $oself.control_drill= 0
    $oself.control_jump= 0
    while $oself.angle>= 359.9
        $oself.angle= $oself.angle-360;
    wend
    while $oself.angle< 0
        $oself.angle= $oself.angle+359.9;
    wend
    if $oself.acc> 0 then;friction
        $oself.acc= $oself.acc-.01
    else
        $oself.acc= 0
    endif;end friction
    $oself.x= $oself.x- ($mysin[int($oself.angle)])*($oself.v)
    $oself.y= $oself.y+ ($mycos[int($oself.angle)])*($oself.v)
EndFunc;end tankloopactions()
Tank.global.au3

#include-once
#Include "Include Lib\SDL v14\SDL.au3"
#include "Include Lib\AutoItObject\AutoitObject.au3"
#Include "Include Lib\SDL v14\SDL_sge.au3"
#include <GUIConstantsEx.au3>
#Include <WinAPI.au3>
#include <WindowsConstants.au3>
#Include <Color.au3>
#Include <misc.au3>
#include <GUIConstantsEx.au3>
#include <EditConstants.au3>
#Include <GUIEdit.au3>
#Include <ScrollBarConstants.au3>
global $hgui= 0
global $players= 3
global $otank[$players]
global $a_tankcontrol[$players]
global $joystickobj[$players]
global $controlmax= 8, $controldatamax= 3
global $colorblack= 0
global $tank_tredframemax= 8, $tank_drillframemax= 3
global $tank_tredl[180][8], $tank_tredr[180][8], $tank_body[180], $tank_drill[180][3]
global $tank_personmax= 32
global $tank_person[$players][$tank_personmax]

global enum $e_tankctrl_forward= 0, $e_tankctrl_backward= 1, $e_tankctrl_left= 2, $e_tankctrl_right= 3, $e_tankctrl_nitro= 4, $e_tankctrl_jump= 5, $e_tankctrl_drill= 6

global $mycos[361], $mysin[361]

global $tank_control_forward= 0
global $tank_control_backward= 0
global $tank_control_left= 0
global $tank_control_right= 0
global $tank_control_drill= 0
global $tank_control_jump= 0
global $hdll= dllopen("user32.dll")

;console window for tank
global $consolew= 320, $consoleh= 200
global $hguiconsole= 0
global $filemenu= 0
global $fileexit= 0
global $g_consoleedit= 0
global $fileconfigurecontrols= 0
#include "tankclass.au3"
Both tank and configure controls have a graphics pack. It's best to just download the Source Folder.

If you like this idea, I encourage you to say something. It's a good way to keep me working on this.

I think I dropped this tank project for at least a year.

Edited by Xandy

Share this post


Link to post
Share on other sites
Xandy

fixed, thank you.

Player Control file syntax, 3 numbers per control.

int: type of control: 0keyboard 0 < joystickid

int: button type: 10button, 20..9999axis, 10000..19999hat

int: action state such as keyid, buttonid, axis intensity, hat state

example:

1 // joystick 0

10 // joystick button

7 // joystick button id 7

2 // joystick 1

20 // 20 axis 0

-20000 // axis 0 less then -19999

Note if you have a joystick just spamming some axis, lower the axis max until the problem stops, through the configure control dialog

Edited by Xandy

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

  • Similar Content

    • WoodGrain
      By WoodGrain
      Hi All,
      I've bought a Ergodox EZ programmable keyboard with layers of key maps (eg, layer 0 = dvorak, layer 1 = numberpad & nav, layer 2 = qwerty, etc), I've also got a small USB screen that can pull information from the registry. What I would like to determine is a way to pull the value of each current key from the keyboard, I can then write the values to the registry and pull them into my USB screen so I can see the keyboard key layout.
      I'm stuck with retrieving the key values, I've looked at _IsPressed(), _WinAPI_GetKeyState(), _WinAPI_GetKeyboardState(), _WinAPI_GetKeyboardType(), _WinAPI_GetKeyNameText(), but none of them appear to be able to pull the keyboard key values without user interaction.
      The idea being, in pseudo code, bear in mind no error checking etc in this code, "GetKeyValue()" is what I'm needing help with and is a made up function, as is "HardwareKey1" etc:
      $keyOnePrev = "" $numOfKeys = 76 While 1 $keyOneCurrent = GetKeyValue(HardwareKey1) If $keyOneCurrent <> $keyOnePrev Then For $key = 1 To $numOfKeys $keyToWrite = GetKeyValue(HardwareKey & $key) RegWrite("HKEY_CURRENT_USER\Software\myKeyboard", "key" & $key, "REG_SZ", $keyToWrite) Next EndIf $keyOnePrev = $keyOneCurrent Sleep(5000) WEnd Thanks guys!
    • Bilgus
      By Bilgus
      Example of Subclassing listviews using setwindowSubclass in order to intercept WM_KEYUP events
      Also pops context menu on  Shift + F10
      #include <Misc.au3> #include <ListViewConstants.au3> #include <GUIConstants.au3> #include <GuiMenu.au3> #include <WinAPIShellEx.au3> Global $g_hCB, $g_pCB, $g_ahProc[2][2] ;Stores the Data for subclassing listview Global $g_LVKEYUP = 0xFE00, $g_LVKEYDN = 0xFD00 ;Our Own Custom messages (Key Up/Dn) Global $g_iDummyData Global $g_hGui = GUICreate("test") Global $g_hList1 = GUICtrlCreateListView("#|x|y", 5, 24, 161, 70, $LVS_SHOWSELALWAYS Or $LVS_SINGLESEL) GUICtrlCreateListViewItem("text", $g_hList1) Global $g_hList1_LVN = GUICtrlCreateDummy() ;Recieves Messages from the callback Global $g_hContext1 = GUICtrlCreateContextMenu($g_hList1) GUICtrlCreateMenuItem("1", $g_hContext1) GUICtrlCreateMenuItem("2", $g_hContext1) Global $g_hList2 = GUICtrlCreateListView("#|x|y", 5, 100, 161, 70, $LVS_SHOWSELALWAYS Or $LVS_SINGLESEL) GUICtrlCreateListViewItem("text", $g_hList2) Global $g_hList2_LVN = GUICtrlCreateDummy() ;Recieves Messages from the callback Global $g_hContext2 = GUICtrlCreateContextMenu($g_hList2) GUICtrlCreateMenuItem("3", $g_hContext2) GUICtrlCreateMenuItem("4", $g_hContext2) GUISetState(@SW_SHOW) SubClassListView() ;Creates our subclass Func SubClassListView() OnAutoItExitRegister("Cleanup") ;to remove our subclass $g_hCB = DllCallbackRegister('_SubclassProc', 'lresult', 'hwnd;uint;wparam;lparam;uint_ptr;dword_ptr') $g_pCB = DllCallbackGetPtr($g_hCB) $g_ahProc[0][0] = $g_hList1 ;Add the Ids of the controls we'd like to subclass $g_ahProc[1][0] = $g_hList2 ;Set up the subclass _WinAPI_SetWindowSubclass ( $hWnd, $pSubclassProc, $idSubClass [, $pData = 0] ) $g_ahProc[0][1] = _WinAPI_SetWindowSubclass(GUICtrlGetHandle($g_ahProc[0][0]), $g_pCB, $g_ahProc[0][0], $g_hList1_LVN) $g_ahProc[1][1] = _WinAPI_SetWindowSubclass(GUICtrlGetHandle($g_ahProc[1][0]), $g_pCB, $g_ahProc[1][0], $g_hList2_LVN) EndFunc ;==>SubClassListView Func _SubclassProc($hWnd, $iMsg, $wParam, $lParam, $iID, $pData) #forceref $iID Local $iRtnMsg = 0 ;Events we'd like to intercept If $iMsg = $WM_KEYUP Or $iMsg = $WM_SYSKEYUP Then $iRtnMsg = $g_LVKEYUP ElseIf $iMsg = $WM_KEYDOWN Or $iMsg = $WM_SYSKEYDOWN Then $iRtnMsg = $g_LVKEYDN EndIf ;We Recieve the Id of the dummy through $pData and pass our RtnMsg to the dummy control If $iRtnMsg Then GUICtrlSendToDummy($pData, BitOR($iRtnMsg, $wParam)) ;Pass messages on to the default handler Return _WinAPI_DefSubclassProc($hWnd, $iMsg, $wParam, $lParam) EndFunc ;==>_SubclassProc Func Cleanup() For $i = 0 To UBound($g_ahProc) - 1 ;Remove Our Subclass' by setting it back to the original proc _WinAPI_RemoveWindowSubclass(GUICtrlGetHandle($g_ahProc[$i][0]), DllCallbackGetPtr($g_ahProc[$i][1]), $g_ahProc[$i][0]) Next DllCallbackFree($g_hCB) EndFunc ;==>Cleanup While 1 Switch GUIGetMsg() Case $GUI_EVENT_CLOSE Exit Case $g_hList1_LVN ;This is just a dummy it only recieves events ConsoleWrite("LV1 EVENT 0x" & Hex($g_iDummyData, 4) & @CRLF) $g_iDummyData = GUICtrlRead($g_hList1_LVN) ;Retrieve the code that was sent Switch BitAND($g_iDummyData, 0xFF00) ;Get the keyup/dn status Case $g_LVKEYDN If BitAND($g_iDummyData, 0x00FF) = 0x79 And (_IsPressed("A0") Or _IsPressed("A1")) Then ;Right/ Left Shift & F10 ShowMenu($g_hGui, $g_hList1, $g_hContext1) Else ConsoleWrite("Lv1 KeyDn Vk: 0x" & Hex(BitAND($g_iDummyData, 0x00FF), 2) & @CRLF) ;Get the Virtual keycode EndIf Case $g_LVKEYUP ConsoleWrite("Lv1 KeyUp Vk: 0x" & Hex(BitAND($g_iDummyData, 0x00FF), 2) & @CRLF) ;Get the Virtual keycode EndSwitch Case $g_hList2_LVN $g_iDummyData = GUICtrlRead($g_hList2_LVN) ;Retrieve the code that was sent ConsoleWrite("LV2 EVENT 0x" & Hex($g_iDummyData, 4) & @CRLF) Switch BitAND($g_iDummyData, 0xFF00) ;Get the keyup/dn status Case $g_LVKEYDN ConsoleWrite("Lv2 KeyDn Vk: 0x" & Hex(BitAND($g_iDummyData, 0x00FF), 2) & @CRLF) ;Get the Virtual keycode Case $g_LVKEYUP ConsoleWrite("Lv2 KeyUp Vk: 0x" & Hex(BitAND($g_iDummyData, 0x00FF), 2) & @CRLF) ;Get the Virtual keycode EndSwitch EndSwitch WEnd Func ShowMenu($hWnd, $idCtrl, $idContext) Local $aPos, $iX, $iY Local $hMenu = GUICtrlGetHandle($idContext) $aPos = ControlGetPos($hWnd, "", $idCtrl) $iX = $aPos[0] $iY = $aPos[1] + $aPos[3] ClientToScreen($hWnd, $iX, $iY) ; Show at the given coordinates (x, y) the popup menu (hMenu) which belongs to a given GUI window (hWnd) _GUICtrlMenu_TrackPopupMenu($hMenu, $hWnd, $iX, $iY) EndFunc ;==>ShowMenu ; Convert the client (GUI) coordinates to screen (desktop) coordinates Func ClientToScreen($hWnd, ByRef $iX, ByRef $iY) Local $tPoint = DllStructCreate("int;int") DllStructSetData($tPoint, 1, $iX) DllStructSetData($tPoint, 2, $iY) DllCall("user32.dll", "int", "ClientToScreen", "hwnd", $hWnd, "struct*", $tPoint) $iX = DllStructGetData($tPoint, 1) $iY = DllStructGetData($tPoint, 2) ; release Struct not really needed as it is a local $tPoint = 0 EndFunc ;==>ClientToScreen  
      Old Code Using setWindowLong
       
    • Xandy
      By Xandy
      I am currently developing NPCs they cannot yet be added.  Items only exist in database.  Enemies only in sprite.
      This project has been on the shelf a couple years.  I decided to learn DLLStruct at the beginning of this project.  I'm not sure if using them was a good idea or not.  I'm open to converting them to pure array and Enum.
      Developing multiplayer system UDP clients / server.  I'm looking for some advice on how to setup the packets.
      I was thinking the best way was to convert packets to Hex and convert back at the destination.  That's probably the way I have it setup.  Anyhow they all talk to each other, clients and server.  Where the avatars appear on screens doesn't work.
      My Enums are used for data members of arrays.  I exclude the 'g' even though they are all Global.  I put the array names they describe in the Enum: ePlayer_x.  In some cases I abbreviate the array name; aWorld_info probably has: aWorld_info[eWi_layers]
      Most gaming things are done better with a nice engine: GameMaker, Unity, Unreal.
      My buddy made a time machine in BASIC.  I know you can make a better time machine in other languages, but there is something to be said for doing it in BASIC.
      Many things are ugly with this, just broken, or extraneous blocks of code I threw together for some one-off task.
      I put this here to see if it generates interest.  I'm happy to change this thing around.  I do many things in favor of speed, but I know some of it's crap.
      Package contains a Server and a Map Editor.  The Map Editor is meant to be able to add and edit:
      World Files, worlds have 2 layers. 
      0.txt background 1.txt forground. The files are formatted with a header: width, height, and the largest tile number.  The largest tile number is used to pad the world files.  So that the world files could be edited by hand.
      WorldN Tile X_Y.txt (a subset cord of tile to specify frame):  World Tile X_Y is stored in a separate file per layer so that the world layer files remain pretty.
      World Directory Structure: Example: World_1_Overworld.
       
      In folder above we can notice only layer 1 has a Tile_X_Y file.  This is because atm only trees use the system and trees are foreground.
      Areas: areas are to subdivide worlds in effort to section the worlds and divide lists for: hotspots, NPCs, Items, and area properties such as: Out-of-Bounds: Destination and Repeat Tile, enemy encounters, etc..
      Areas have: Global Enum $eArea_x, $eArea_y, $eArea_w, $eArea_h, _                        ; Area World Bound Rect         $eArea_ob_tile, $eArea_ob_world, $eArea_ob_x, $eArea_ob_y, _     ; Out of Bounds Repeat Tile and World Destination if Out of Bounds         $eArea_hotspots, $eArea_items, $eArea_NPCs ; Total Hotspots per Area, Items and People Hotspots: hotspots are locations on the board that relocate the player
      Global Enum $eHotspot_x, $eHotspot_y, _; the spot in world that moves player $eHotspot_dest_world, $eHotspot_dest_x, $eHotspot_dest_y; the destination world and position Board: A rectangle of world tiles is pre-drawn on aBoard[layer_max] centered on player, you can change the size to consume less RAM but requires drawing world to board more often.
       
      Animated Background: Before anything is drawn a moving BG image is drawn.  Creating beautiful water AI.  So if no tiles are drawn from world, BG water animation is shown.
       
      Map Editor should be able to test all of the systems of the game: Player, Worlds, Areas, Hotspots, NPCs, Items, Shops, Battles, Netplay, etc..
      (Not all systems exist yet)

      Download site: http://songersoft.com/programming/dw3_remake/dw3_remake_about.phtml
      It's going to say that the files might be malicious.  Probably b/c of the DLLs and I hosted an unmoderated forum from the site years ago were people posted malicious links.  Let me know if it's malicious!
      PS: I tried posting the source but I keep getting errors.  I think the source might be too large to post. 6308 lines.  Idk.
    • Xandy
      By Xandy
      I have a bunch of SDL_Surfaces loaded into memory.  I want to list them in a ComboBox.
      Using this code, I can load images to the combobox from file but not from existing SDL_Surface memory
      CODE ISN"T MEANT TO RUN
      ; Create combobox pic list example $aControl[$iControl_id][$eControl_data] = _GUICtrlComboBoxEx_Create($gui, $data_value, $data_x, $data_y, $data_w, $data_h, $CBS_DROPDOWNLIST) ; Image List for ComboboxEx Local $hImage = _GUIImageList_Create($gTile_w, $gTile_h, 6) ; Fill hImage with SDL_Surfaces stored in memory: aNPC_surf[scale][type][way][frame] For $i = 0 To 1 ; This works but only from file: ;_GUIImageList_AddBitmap($hImage, $gFolder_graphics & $gaWorld_info[$player.iWorld_cur][$eWi_filename] & "Tiles\" & $i & ".bmp") ; I've broken up a sprite sheet and want to insert into combobox from memory ;_GUIImageList_Add($hImage, $aNPC_surf[1][1][1][$i]) _GUIImageList_Add($hImage, _GDIPlus_BitmapCreateFromMemory($aNPC_surf[1][1][1][$i]), True) ;_GDIPlus_BitmapCreateFromMemory($aNPC_surf[1][1][1][$i]) ; Add the index number to combobox item _GUICtrlComboBoxEx_AddString($aControl[$eNPC_iPic_type][$eControl_data], $i, $i, $i) Next ; Set hImage list to combobox control _GUICtrlComboBoxEx_SetImageList($aControl[$eNPC_iPic_type][$eControl_data], $hImage) Anyone know if I can convert from SDL_Surface to hBitmap?  Maybe I'm doing something else wrong.
       
      I've seen hBitmap converted to SDL_Surface but I don't really understand it yet: 
       
      My full script can be found here:
       
    • Tarakesh
      By Tarakesh
      I have a situation where the desktop is designed in java swings. The nodes JTree is not allowing me to do checkbox selection using "spacebar". I am able to navigate through the nodes using up, down arrow and a tab. When I reach to the desire node selection, mouse left click is not working due a flaw a JTree core. However since it is selected, if mouse cursor auto moved to the position of the selection and send a "click"  then it should be solved. Any ideas much appreciated. 
      the problem with having fixed coordinates are the main windows is divided to 2panels where right panel containing this JTree can be expanded or shrink-ed.

×