Home Game – Virtual Joystick With QML

Game – Virtual Joystick With QML


Recently out of curiosity I tried to created virtual joystick, which nowadayx s used quite frequently touch based games.
Well my implementation still required some improvement to provide real feel of joystick but its still quite useful. Here is output.


To test my joystick, I also created a sprite which moves in almost all direction.
Here is my QML code for joystick. I basically used two circle and checking inner circle position with outer circle and deciding direction. I am not describing code, but tried to put necessary comment in code.

import QtQuick 1.0

Item {
id:joyStick;
property int offset:30;
signal dirChanged(string direction);
signal pressed();
signal released();
Rectangle {
id:totalArea
color:”gray”
radius: parent.width/2
opacity: 0.5
width:parent.width;height:parent.height
}
Rectangle{
id:stick
width:totalArea.width/2; height: width
radius: width/2
x: totalArea.width/2 – radius;
y: totalArea.height/2 – radius;
color:”black”
}
MouseArea{
id:mouseArea
anchors.fill: parent
onPressed: {
joyStick.pressed();
}
onMousePositionChanged: {
//(x-center_x)^2 + (y – center_y)^2 < radius^2
//if stick need to remain inside larger circle
//var rad = (totalArea.radius – stick.radius);
//if stick can go outside larger circle
var rad = totalArea.radius;
rad = rad * rad;
// calculate distance in x direction
var xDist = mouseX – (totalArea.x + totalArea.radius);
xDist = xDist * xDist;
// calculate distance in y direction
var yDist = mouseY – (totalArea.y + totalArea.radius);
yDist = yDist * yDist;
//total distance for inner circle
var dist = xDist + yDist;
//if distance if less then radius then inner circle is inside larger circle
if( rad < dist) { return; } //center of larger circle var oldX = stick.x; var oldY = stick.y; stick.x = mouseX – stick.radius; stick.y = mouseY – stick.radius; //using L R U D LU RU LD RD for describe direction var dir=””; //check if Right or left direction, //by checking if inner circle’s y is near center of larger circle if( stick.y >= totalArea.radius – stick.radius – joyStick.offset
&& stick.y+stick.height <= totalArea.radius + stick.radius + joyStick.offset) { if( stick.x + stick.radius > totalArea.x + totalArea.radius) {
dir = “R”;
} else if( stick.x < totalArea.x + totalArea.radius) { dir = “L”; } } //check if Up or Down direction, //by checking if inner circle’s x is near center of larger circle else if( stick.x >= totalArea.radius – stick.radius – joyStick.offset
&& stick.x + stick.width <= totalArea.radius + stick.radius + joyStick.offset) { if( stick.y + stick.radius > totalArea.y + totalArea.radius) {
dir = “D”;
} else if( stick.y < totalArea.y + totalArea.radius) {
dir = “U”;
}
}
//check if Up Left or Up Right direction,
//by checking if inner circle is near one of top corner of larger circle
else if( stick.y < totalArea.radius – stick.radius ) { if( stick.x + stick.radius > totalArea.x + totalArea.radius) {
dir = “R”;
} else if( stick.x < totalArea.x + totalArea.radius) { dir = “L”; } dir = dir +”U”; } //check if Down Left or Down Right direction, //by checking if inner circle is near one of bottom corner of larger circle else if ( stick.y + stick.radius >= totalArea.radius + stick.radius ) {
if( stick.x + stick.radius > totalArea.x + totalArea.radius) {
dir = “R”;
} else if( stick.x < totalArea.x + totalArea.radius) {
dir = “L”;
}
dir = dir +”D”;
}
joyStick.dirChanged(dir);
}
onReleased: {
//snap to center
stick.x = totalArea.width /2 – stick.radius;
stick.y = totalArea.height/2 – stick.radius;
joyStick.released();
}
}
}
Follwing my code for sprite used in above video.

import QtQuick 1.0

Item {
id:sprite
width: 50; height: 50
clip:true
property alias running: timer.running;
property int frameCount: 5
property int frame:0
property int row:0
property int xDir:0;
property int yDir:0;
Image{
id:image
source:”man.png”
x:-sprite.width * sprite.frame;
y:-sprite.height * sprite.row;
}
function changeDirection(direction) {
if( direction === “L”) {
sprite.row=6;
sprite.xDir = -1;
sprite.yDir = 0;
} else if( direction === “R”) {
sprite.row=2;
sprite.xDir = 1;
sprite.yDir = 0;
} else if( direction === “U”) {
sprite.row=4;
sprite.xDir = 0;
sprite.yDir = -1;
} else if( direction === “D”) {
sprite.row=0;
sprite.xDir = 0;
sprite.yDir = 1;
} else if( direction === “RU”) {
sprite.row = 3;
sprite.xDir = 1;
sprite.yDir = -1;
} else if( direction === “LU”) {
sprite.row = 5;
sprite.xDir = -1;
sprite.yDir = -1;
} else if( direction === “RD”) {
sprite.row = 1;
sprite.xDir = 1;
sprite.yDir = 1;
} else if( direction === “LD”) {
sprite.row = 7;
sprite.xDir = -1;
sprite.yDir = 1;
}
}
function nextFrame() {
sprite.frame = ++sprite.frame % sprite.frameCount
sprite.x = sprite.x + 5* sprite.xDir;
sprite.y = sprite.y + 5* sprite.yDir;
}
Timer {
id:timer
interval: 150; running: false; repeat: true
onTriggered: {
nextFrame();
}
}
}
Finally, main qml file which include both joystick and sprite.

import QtQuick 1.0

Image {
width: 854 ; height:480
source:”grass.jpg”
fillMode: Image.Tile
Sprite{
id:man
x:parent.width/2 ; y: parent.height/2;
}
Connections {
target: joyStick
onDirChanged:{
man.changeDirection(direction)
}
onPressed:{
man.running=true;
}
onReleased:{
man.running=false;
}
}
Joystick{
id:joyStick
anchors.bottom: parent.bottom
anchors.left: parent.left
anchors.bottomMargin: 10
anchors.leftMargin: 10
width:150;height:150
}
}
 
Source Kunalmaemo Blogspot

About ReadWrite’s Editorial Process

The ReadWrite Editorial policy involves closely monitoring the tech industry for major developments, new product launches, AI breakthroughs, video game releases and other newsworthy events. Editors assign relevant stories to staff writers or freelance contributors with expertise in each particular topic area. Before publication, articles go through a rigorous round of editing for accuracy, clarity, and to ensure adherence to ReadWrite's style guidelines.

Get the biggest tech headlines of the day delivered to your inbox

    By signing up, you agree to our Terms and Privacy Policy. Unsubscribe anytime.

    Tech News

    Explore the latest in tech with our Tech News. We cut through the noise for concise, relevant updates, keeping you informed about the rapidly evolving tech landscape with curated content that separates signal from noise.

    In-Depth Tech Stories

    Explore tech impact in In-Depth Stories. Narrative data journalism offers comprehensive analyses, revealing stories behind data. Understand industry trends for a deeper perspective on tech's intricate relationships with society.

    Expert Reviews

    Empower decisions with Expert Reviews, merging industry expertise and insightful analysis. Delve into tech intricacies, get the best deals, and stay ahead with our trustworthy guide to navigating the ever-changing tech market.