I use the script below to get the position of the player on the screen.
On my laptop i get the good result, but on my mobile not.
What do i have to change?
var FollowWorldTarget = pc.createScript('followWorldTarget');
FollowWorldTarget.attributes.add('target', {type: "entity"});
FollowWorldTarget.attributes.add('camera', {type: "entity"});
// initialize code called once per entity
FollowWorldTarget.prototype.initialize = function() {
};
// update code called every frame
FollowWorldTarget.prototype.update = function(dt) {
// world space position of target
var worldPos = this.target.getPosition();
var screenPos = new pc.Vec3();
// get screen space co-ord
this.camera.camera.worldToScreen(worldPos, screenPos);
// convert to screen component co-ordinates
var screenEntity = this.entity.element.screen;
var scale = screenEntity.screen.scale;
var device = this.app.graphicsDevice;
this.entity.setLocalPosition(screenPos.x / scale, (device.height - screenPos.y) / scale, 0);
};
I think in displays with a pixel ratio > 1 you need to multiply the device width/height (or your screen coords) with that to get it to center:
var pixelRatio = window.devicePixelRatio;
Try playing with that value in your equation and most likely that it the reason.
No idea how to insert your solution but I realize the player is always in the center of the screen. So maybe for now it’s easier to get an answer on the question, how do I calculate the center of the screen?
Of course i can do that in the editor without any scripting, so problem solved i think.
If you are using 2D Screen elements, you can easily do that by selecting

If you are using world positioned entities you can add it as a child to the camera and just offset its local z position (push it away from the camera):
Yes, both solutions can be implemented in code.
On how to calculate the center of the screen, that depends on the point of reference:
- For 2D coordinates, that would always be …
new pc.Vec2(screenWidth / 2, screenHeight/2)
- For 3D coordinates, there isn’t really a screen center in world units, since the camera is an object inside the world. Here your best bet is to add the object as a child to the camera, as in my previous post. That object will be centered on screen.
Oke, i have the 2D element in the center of the screen, and i don’t use the script above anymore, but now i can’t get the y position of the element in my script. The result stays 0. If i enable the script above then i get a result. What do i missing?
I want to know if my mouse is above or under the element.
In the script below the playerScreenPosition is the element in the centre of the screen.
I need that position.
// Climbing
Player.prototype.updateClimbing = function (dt) {
if (playerIsClimbing) {
playerHeightBeforeFalling = this.entity.getPosition().y;
console.log(inputScreenPosition.y + " " + playerScreenPosition.getLocalPosition().y);
// If mouse is above player
if (inputScreenPosition.y < playerScreenPosition.getLocalPosition().y) {
playerIsClimbingUp = true;
playerIsClimbingDown = false;
}
// If mouse is under player
if (inputScreenPosition.y > playerScreenPosition.getLocalPosition().y) {
playerIsClimbingDown = true;
playerIsClimbingUp = false;
}
if (playerIsClimbingUp && playerIsMoving && !playerIsOnTop) {
player.translateLocal(0,0.025,0); // move up
}
if (playerIsClimbingDown && playerIsMoving && !playerIsOnBottom) {
player.translateLocal(0,-0.025,0); // move down
}
}
};
I think Y stays 0 because it counts from the element’s anchor point, which is the center of the screen element. That’s correct.
If you would like to check when the cursor is over the element, enable input on the element component and then check for the mouseenter and mouseleave events.
Here is an example that implements that, script btn-states.js:
https://playcanvas.com/editor/scene/547900
Reading your post again, when you say above or under your element, you mean I now think on the upper or lower part of your screen.
To do that you can use something like this:
var Mouse = pc.createScript('mouse');
// initialize code called once per entity
Mouse.prototype.initialize = function() {
this.app.mouse.on(pc.EVENT_MOUSEMOVE, this.onMouseMove, this);
};
Mouse.prototype.onMouseMove = function (event) {
if( event.y < this.app.graphicsDevice.height / 2 ){
console.log('above');
}else{
console.log('below');
}
};
Hello @Leonidas, your last solution is working on my laptop but not working on a mobile device.
(With using this.onTouchMove).
By not working, you mean being off-center then try multiplying with the devicePixelRatio, as we said above (I think that would be the case if you have device pixel ratio disabled in your project settings, not 100% sure though).
Update the check to:
if( event.y < (this.app.graphicsDevice.height * window.devicePixelRatio) / 2 ){
If the issue is something different, it’s better to post a sample project to take a look.
Hi @Albertos,
The reason it fails on mobile is event.y being undefined there. Touch events hold an array of touches which you should access to get the event info.
Here is your updated method:
Input.prototype.onTouchMove = function (event) {
if (event.touches[0].y < this.app.graphicsDevice.height / 2){
alert('above');
} else{
alert('below');
}
};
Without using device pixel ratio everything is working. But i use device pixel ratio and then it does’t work on mobile. Also not with using (this.app.graphicsDevice.height * window.devicePixelRatio) / 2. I have updated the sample project with the issue.
What’s not working, could you be more specific?
I’ve created a test project with the code I shared above:
https://playcanvas.com/editor/scene/896908
And it’s working on both Android and iOS:
- Samsung Galaxy S10
- iPhone 10XR
Above/below messages fire with the correct center.
Please enable device pixel ratio in the project settings and you see that you dont’t get the right result anymore.
Ok, if you are using Device Pixel Ratio in your project, then update the code to use the window.innerHeight when doing comparisons when event coordinates. Like this:
Input.prototype.onMouseMove = function (event) {
if (event.y < window.innerHeight / 2){
console.log('above');
} else{
console.log('below');
}
};
Input.prototype.onTouchMove = function (event) {
if (event.touches[0].y < window.innerHeight / 2){
alert('above '+event.touches[0].y);
} else{
alert('below '+event.touches[0].y);
}
};
1 Like
Yes, this is working! Thanks again! 
1 Like