Virtual joystick

Previous topic - Next topic

GrimSentry

I have been working on this code off and on for a bit over a month, the math gave me many head aches. Its very unpolished and has a lot of optimization that I need to do, along with unused code. Been pretty busy as of late so have not got around to cleaning it up. I did use someones base loop for the tween(not used ATM) and separation of logic and display update, cant remember the name. As soon as I get to a stable connection I will upload the project if anyone wants it. I have my projects Explicit declarations unchecked currently. If you use this posted code before I post a download you will need two images.. the stick 256x256 and back 512x512. Of course you can change this, though not sure how this will work on an idevice.. altered or not.

This will place up to 2 virtual joy sticks on the screen at once any where you touch, both with a background and locked origin to the initial touch reset upon release. Both constrain in a circle. At this point there is nothing defining left vs right joystick. Currently the first touch is stick 0, second is stick 1. Possibly replacing the for loop with if/case statements checking for screen position and running a specific joystick will work, not sure if that's the most efficient. The type is set up to use an array so that it can have up to as many joy sticks as the max touches your device can support. I intend on implementing: Optional snap back, locked origin, velocity %, speed %. Currently the only real usable return is angle 0-359, 0 being up, 180 down, 90 right, 270 left.

I hope some of you can find this useful, and would love any suggestions you may have.

Main Code:

Code (glbasic) Select

// ===================== \\
// Project: Alpha                 
// Start: Monday, July 16, 2012  
// =====================\\

GLOBAL UPDATE_FREQUENCY% = 20 // times per second
GLOBAL update_time# = 1000 / UPDATE_FREQUENCY%
GLOBAL t% , dt% , execution_time% = 0
GLOBAL Main, Second

SETCURRENTDIR("Media") // Set current dir
AUTOPAUSE FALSE
SMOOTHSHADING TRUE
ALPHATESTING 0.5
LOADSPRITE "JoyStick.png", 0
LOADSPRITE "JoyBack.png", 1
SYSTEMPOINTER TRUE

t = GETTIMERALL()
SetDisplay()

// Set up and initialise 2 Joystics
GLOBAL JoySticks[] AS tJoyStick
DIM JoySticks[2]
JoySticks[0].Initialise(0, 0, 2, 2, 0.08, 2, 2, 2, 2)
JoySticks[1].Initialise(1, 0, 2, 2, 0.08, 2, 2, 2, 2)

// =======\\
// Main loop                     
// =======\\

WHILE NOT KEY(1)
dt = GETTIMERALL() - t
t = GETTIMERALL()

execution_time = execution_time + dt

// fixed interval update loop
    WHILE execution_time >= update_time

UpdateLogic()
execution_time = execution_time - update_time

WEND

// calculate the remainder FOR motion interpolation
LOCAL et# = execution_time
LOCAL ut# = update_time
LOCAL tween# = et / ut

Render(tween)
WEND

// ======= \\
// Functions                     
// ======= \\

// ================== Update Logic ================== \\
FUNCTION UpdateLogic:

// Update Logic

ENDFUNCTION

// ================= Render Display ================= \\
FUNCTION Render: tween#

CLEARSCREEN

ALPHAMODE -1

ShowGUI()

SHOWSCREEN

ENDFUNCTION

FUNCTION ShowGUI:

FOR j = 0 TO 1
JoySticks[j].Display()
NEXT

ENDFUNCTION

// =========== Set UP Display based on OS =========== \\
FUNCTION SetDisplay:

LOCAL info$ = PLATFORMINFO$("") // What device is this
LOCAL w%, h%

GETDESKTOPSIZE w,h

SELECT info$

CASE "ANDROID"
SETSCREEN w, h, 1
SETORIENTATION 0
CASE "WIN32"
SETORIENTATION 0
SETSCREEN w, h, 1

CASE "MACOSX"
SETORIENTATION 0

CASE "LINUX"
SETORIENTATION 0

ENDSELECT

ENDFUNCTION


Joy Stick Type and Functions:

Code (glbasic) Select

// ====================== \\
// Project: Alpha - GUI Functions         
// Start: Monday, July 16, 2012  
// ====================== \\

TYPE tJoyStyle

ENDTYPE

TYPE tJoyStick

mIndex // The # of the mouse
mX // Current mouse x
mY // Current mouse y
mB1 // Current mouse button1 state
mB2 // Current mouse button1 state
mOriginX // X possision of mouse on first press
mOriginY // Y possision of mouse on first press
FirstPress // Track first press
Distance // Distance between 2 x, y coordinates
Delay // Prevents first frame from rendering JoyStick to avoid bounce/flicker
jRadius // Raidius of the Stick
jStick // Stick image
jBase // Base image
jStickAlpha // Transparancy of Stick
jBaseAlpha // Transparancy of Base
jBoundry // How far from origin the stick can move
sLimit // How far from origin can mouse(finger) more before snaping back to center
jLimitX // Limit x of Stick based on boundry
jLimitY // Limit y of Stick based on boundry
jStaticX // Static x possision of JoyStick, if greater then 0 this will take effect.
jStaticY // Static y possision of JoyStick
bRadius // Base radius

FUNCTION Initialise%: mIndex, sLimit, jStaticX, jStaticY, jSize, jStick, jBase, jStickAlpha, jBaseAlpha

LOCAL w, h
GETDESKTOPSIZE w,h

// Mouse State Variables
self.mIndex = mIndex
self.FirstPress = FALSE

// Joystick Visuals
self.jRadius = jSize * h
self.jStick = jStick
self.jBase = jBase
self.jStickAlpha = jStickAlpha
self.jBaseAlpha = jBaseAlpha
self.jBoundry = jRadius
self.sLimit = sLimit
self.jStaticX = jStaticX
self.jStaticY = jStaticY
self.bRadius = jRadius * 2

ENDFUNCTION


FUNCTION GetAngle:

DistanceX = mOriginX - mX
DistanceY = mOriginY - mY

res% = ATAN( DistanceX, DistanceY)

// Change from -/+ 180 to 0 - 359 ( 360 Degrees)
IF res = 0
res = 0
ELSEIF res > 0
res = ABS(res - 360)
ELSEIF res < 0
res = ABS(res)
ENDIF

RETURN res

ENDFUNCTION


FUNCTION GetVelocity:
// To be done - % based
ENDFUNCTION


FUNCTION GetSpeed:
// To be done - % based
ENDFUNCTION


FUNCTION GetDistance:
Distance = SQR(POW((mX-mOriginX),2) + POW((mY-mOriginY),2))
RETURN Distance
ENDFUNCTION


FUNCTION Limit:
vx# = mOriginX - mX;
vy# = mOriginY - mY;

// Length
mag# = SQR(vx*vx + vy*vy);

// Normalize

vx = vx / mag;
vy = vy / mag;

//calculate the new vector

jLimitX = (mX + vx * (mag + (-jBoundry)));
jLimitY = (mY + vy * (mag + (-jBoundry)));

ENDFUNCTION


FUNCTION Display:

Distance = GetDistance()
SETACTIVEMOUSE mIndex
MOUSESTATE mX, mY, mB1, mB2

IF mB1

IF FirstPress = FALSE
FirstPress = TRUE
Delay = TRUE // Prevents first frame from rendering JoyStick to avoid bounce/flicker
mOriginX = mX
mOriginY = mY
ENDIF

//Draw base here

IF Distance > jBoundry AND Delay = FALSE

STARTPOLY 1 // Bitmap = No.0
POLYVECTOR   mOriginX - bRadius,   mOriginY - bRadius,    0,    0, RGB(255, 255, 255)
POLYVECTOR   mOriginX - bRadius,   mOriginY + bRadius,    0,  512, RGB(255, 255, 255)
POLYVECTOR   mOriginX + bRadius,   mOriginY + bRadius,  512,  512, RGB(255, 255, 255)
POLYVECTOR mOriginX + bRadius,   mOriginY - bRadius,  512,    0, RGB(255, 255, 255)
ENDPOLY

// Display Joystick at limited possision
STARTPOLY 0 // Bitmap = No.0
POLYVECTOR   jLimitX - jRadius,   jLimitY - jRadius,    0,    0, RGB(255, 255, 255)
POLYVECTOR   jLimitX - jRadius,   jLimitY + jRadius,    0,  256, RGB(255, 255, 255)
POLYVECTOR   jLimitX + jRadius,   jLimitY + jRadius,  256,  256, RGB(255, 255, 255)
POLYVECTOR jLimitX + jRadius,   jLimitY - jRadius,  256,    0, RGB(255, 255, 255)
ENDPOLY

ELSEIF Distance < jBoundry AND Delay = FALSE

STARTPOLY 1 // Bitmap = No.0
POLYVECTOR   mOriginX - bRadius,   mOriginY - bRadius,    0,    0, RGB(255, 255, 255)
POLYVECTOR   mOriginX - bRadius,   mOriginY + bRadius,    0,  512, RGB(255, 255, 255)
POLYVECTOR   mOriginX + bRadius,   mOriginY + bRadius,  512,  512, RGB(255, 255, 255)
POLYVECTOR mOriginX + bRadius,   mOriginY - bRadius,  512,    0, RGB(255, 255, 255)
ENDPOLY


// Display Joystick at mouse possision
STARTPOLY 0 // Bitmap = No.0
POLYVECTOR   mX - jRadius,   mY - jRadius,    0,    0, RGB(255, 255, 255)
POLYVECTOR   mX - jRadius,   mY + jRadius,    0,  256, RGB(255, 255, 255)
POLYVECTOR   mX + jRadius,   mY + jRadius,  256,  256, RGB(255, 255, 255)
POLYVECTOR mX + jRadius,   mY - jRadius,  256,    0, RGB(255, 255, 255)
ENDPOLY

ENDIF

Delay = FALSE // After first pass through allow rendering
Limit()

ELSEIF mB1 = FALSE
FirstPress = FALSE
ENDIF


ENDFUNCTION

FUNCTION CleanUp:

// REDIM - Remove Images

ENDFUNCTION

ENDTYPE


I don't remember all the modifications I made to the AndroidManifest.xml so:

Code (glbasic) Select

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="com.yourcompany.alpha"
      android:installLocation="preferExternal"
      android:versionCode="1"
      android:versionName="0.001">
    <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="14" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.BATTERY_STATS" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<supports-screens android:resizeable="false"
  android:smallScreens="true"
  android:normalScreens="true"
  android:largeScreens="true"
  android:anyDensity="true" />
    <application android:label="@string/app_name" android:icon="@drawable/icon" android:debuggable="false">
        <activity android:name="org.libsdl.app.SDLActivity"
android:label="@string/app_name"
android:screenOrientation="landscape"
>
<!-- android:configChanges="orientation|keyboardHidden" -->
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
</manifest>


Ian Price

MrTaToad did something like this last year. Could be very useful to some.
I came. I saw. I played.

GrimSentry

Very true, and its a great piece of code. I have read over the code quite a few times. Unfortunately it constrains the stick to a square and as is only returns values for left right up and down, it just wasnt quite what i was looking for.

I needed/wanted:
up down left right
Velocity/Acceleration - how fast the player is moving the joystick
Speed - percentage return, based on min distance from origin to max limit, to allow for speed control
Angle - Allowing for easier orientation of objects and sprites
More Joysticks - Currently tested up to 8 on screen - large tablet + 4 kids great potential

Not all of these features are currently implemented, slowly chipping away at it when i have some time to code. Would love any suggestions.

~Grim S.

bigsofty

Is there some .PNGs for your code?
Cheers,

Ian.

"It is practically impossible to teach good programming style to students that have had prior exposure to BASIC.  As potential programmers, they are mentally mutilated beyond hope of regeneration."
(E. W. Dijkstra)

GrimSentry

Yes, here is the entire project - Slightly updated to display up to 8 joysticks. Windows/Linux/Mac will only display 1.

http://www.mediafire.com/?34p6xyehd6kdgcn

~Grim S.

P.S. Not sure about iDevices, but works on my HTC EVO LTE

bigsofty

I had a quick look on windows and I was impressed, it looks really nice, very much like the virtual joysticks you see in most games, well done! :good:
Cheers,

Ian.

"It is practically impossible to teach good programming style to students that have had prior exposure to BASIC.  As potential programmers, they are mentally mutilated beyond hope of regeneration."
(E. W. Dijkstra)

Ian Price

Indeed (I tried it on Windows too).

:)
I came. I saw. I played.