I’m trying to use the physical pixels instead of CSS pixels for a better resolution. I can do this by calling melonjs.video.renderer.resize(document.clientWidthwindow.devicePixelRatio,document.clientHeightwindow.devicePixelRatio). However, this screws up the mouse events triggering on the entities on screen. I’m currently using a kludge where I have a handler in the game state that calls this adjustPixels function at the end of the pointer event handler functions. However, it doesn’t always work (especially for pointermove), besides being very hacky. How can I fix this?
adjustPointer(pointer:melonjs.Pointer){
//fix problem with device pixel ratio
pointer.gameScreenX*=window.devicePixelRatio;
pointer.gameScreenY*=window.devicePixelRatio;
let local=melonjs.input.globalToLocal(pointer.gameScreenX,pointer.gameScreenY);
pointer.gameLocalX=local.x;
pointer.gameLocalY=local.y;
let world=(melonjs.game.viewport as melonjs.Camera2d).localToWorld(local.x,local.y);
pointer.gameWorldX=world.x as number;
pointer.gameWorldY=world.y as number;
}
Why don’t you use Pointer.client[X/Y] (melonJS: Pointer) those are the mouse/pointer coordinates sent by the browser/system event ? this should be what you are looking for ?
Else normally the whole Pointer implementation is made so that you don’t have to worry about scaled resolution vs internal resolution and all corresponding pixel “transformation”. What is your use case where this is not accurate enough for you ? (just our of curiosity)
Actually the main problem that I’m facing is that the pointer events don’t get fired on the sprites unless I do that hackery. Seems to be because the pointer coordinates are in CSS pixels and the location of sprites on screen are in canvas (physical) pixels. Even with the hackery sometimes pointermove is not called.
Or am I doing it wrong? Is there some other proper way to increase the resolution to 1:1 with physical pixels other than calling melonjs.video.renderer.resize?
Have you tried playing with the scaling options to scale the display right away ? or do you need to change the resolution (canvas size, or aspect ratio) during the game ?
I’m using flex scale mode. Basically I just want the screen to display as much of the map as the physical pixels allow with no scaling.
The problem that happens when I resize it to multiply the dimensions by the devicePixelRatio is that the pointer events on the sprites stop working. My way of trying to solve this was to handle pointer events globally and call my adjustPointer function at the end of the event handler. However, that only works inconsistently some of the time (notably, pointermove sometimes doesn’t get called on the sprites), besides the fact that it’s obviously a kludge.
Is there some way to have the pointer events translated between CSS pixels and physical pixels, when the canvas size is resized to be based on physical pixels instead of CSS pixels, so that the event handlers of the sprites (which have screen coordinates based on canvas pixels) get called?
No, it didn’t help because flex still doesn’t make the resolution according to physical pixels (let’s say devicePixelRatio is 3, the CSS pixel width is 100, then the canvas width should be resized to 300 but in flex, the canvas width is still 100).
I’ve temporarily solved the events firing by making my minimap floating and setting the width and height to the entire screen (then I calculate the coordinates manually in the event handler). And I’m still using the adjustPixels function. Also not a very good solution.
I think the problem is in dispatchEvent because it doesn’t seem to allow for a canvas width / height that is different from its width and height in CSS pixels.