Hey,
I am currently working to create an AR paper toss clone. I am able to swipe to launch an orange towards a basket. But the impulse force right now is predefined and hence works the same every time, regardless of my swipe distance/time. This does not make for a fun game. I need help in figuring out how to convert my swipe input into an impulse force, so that every time I swipe, based on my swipe the force applied to the object changes.
This is the link to my project.
https://playcanvas.com/project/673559/overview/orangetoss
This is the link to my published build for testing. Please open this link on your phone
This is the link to the hiro marker. Please open this link on your laptop/desktop so you can test from your phone.
Instruction - Swipe up to toss an orange.
Hi @Nishant_Fernandez and welcome!
You can take a look at the Model Viewer template (available when creating a new project) how it calculates a panning or zooming distance when you touch and drag. You can do something similar on touch end:
TouchInput.prototype.getPinchDistance = function (pointA, pointB) {
// Return the distance between the two points
var dx = pointA.x - pointB.x;
var dy = pointA.y - pointB.y;
return Math.sqrt((dx * dx) + (dy * dy));
};
TouchInput.prototype.onTouchMove = function(event) {
// ...
if (touches.length == 2) {
// Calculate the difference in pinch distance since the last event
var currentPinchDistance = this.getPinchDistance(touches[0], touches[1]);
var diffInPinchDistance = currentPinchDistance - this.lastPinchDistance;
this.lastPinchDistance = currentPinchDistance;
}
};
You can then use that pinch distance to create and scale a force to push your object to a direction:
// example force facing upwards scaled to match the swipe distance
var force = new pc.Vec3();
var baseStrength = 100;
force.set(0, 1, 0).scale(diffInPinchDistance * baseStrength);
coinEntity.rigidbody.applyForce(force);
1 Like
Hey @Leonidas,
Thanks for this, will try to implement this logic using swipe instead of pinch and get back to you on how I do.
1 Like
For anyone else who might struggle with this, here is the way I used touch Input to calculate the power generated by a swipe to apply to a ball(orange in my use case).
Test.prototype.initialize = function ()
{
var touch = this.app.touch;
if(touch)
{
touch.on(pc.EVENT_TOUCHSTART, this.onTouchStart, this);
touch.on(pc.EVENT_TOUCHMOVE, this.onTouchMove, this);
touch.on(pc.EVENT_TOUCHEND, this.onTouchEnd, this);
}
//Define the Variables required
this.velocity = new pc.Vec3(0,0,0);
this.direction = new pc.Vec3();
this.distance = 0;
this.power = 0;
this.StartWorldPos = new pc.Vec3(0,0,0);
this.EndWorldPos = new pc.Vec3(0,0,0);
this.touchStarted = false;
this.touchEnded = false;
this.startPos = new pc.Vec2(0,0);
this.EndPos = new pc.Vec2(0,0);
this.time = 0;
this.duration = 0;
this.startX = 0;
this.startY = 0;
this.endX = 0;
this.endY = 0;
this.canThrow = false;
}
Test.prototype.onTouchStart = function (event)
{
this.time = 0;
this.duration = 0 ;
this.touchStarted = true;
this.touchEnded = false;
//Get touch start position
var touch = event.touches[0];
this.startPos.set(touch.x,touch.y);
this.startX = touch.x;
this.startY = touch.y;
//reset the power.
this.power = 0;
//console.log("startPos = " + this.startPos);
};
Test.prototype.onTouchEnd = function (event)
{
this.touchStarted = false;
this.touchEnded = true;
this.CameraEntity.camera.screenToWorld(this.startX,this.startY,0.1,this.StartWorldPos);
this.CameraEntity.camera.screenToWorld(this.endX,this.endY,0.1,this.EndWorldPos);
};
Test.prototype.onTouchMove = function (event)
{
//Get touch end position
var touch = event.touches[0];
this.EndPos.set(touch.x,touch.y);
this.canThrow = true;
this.endX = touch.x;
this.endY = touch.y;
};
Test.prototype.update = function (event)
{
if(this.touchStarted){
this.time += dt;
}else
{
this.duration = this.time;
}
if(this.touchEnded)
{
//Calculate direction by subtracting startPos from endPos
this.direction.sub2(this.EndWorldPos,this.StartWorldPos);
this.distance = this.direction.length();
//Calculate the power.
this.power = this.distance / this.duration;
//apply the power to the object
var y = this.power * 10 * 2;
var z = this.power * 10 * 2;
this.orange.rigidbody.applyImpulse(0,y,-z);
}
}
3 Likes
Thanks for sharing @Nishant_Fernandez!