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:
// ===================== \\
// 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:
// ====================== \\
// 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:
<?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>
MrTaToad did something like this last year. Could be very useful to some.
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.
Is there some .PNGs for your code?
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 (http://www.mediafire.com/?34p6xyehd6kdgcn)
~Grim S.
P.S. Not sure about iDevices, but works on my HTC EVO LTE
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:
Indeed (I tried it on Windows too).
:)