I created a PWA with Phaser 2, following this tutorial (this one is made with Phaser 3).
I face a problem with how the game scales on mobile. In my game I use these Phaser 2 methods for scaling:
game.scale.scaleMode = Phaser.ScaleManager.SHOW_ALL;
game.scale.pageAlignHorizontally = true;
game.scale.pageAlignVertically = true;
When I click the localhost link in my mobile, the game appears way too big, I have to scroll down to see it. When I 'download' it to act like an app, it gets shaky at first, scaling up and down until it settles to the correct size. The game dimensions are 1280x720 and looked very nice before I converted it to a PWA, both on web and on mobile.
I did an audit for a PWA in Chrome's dev tools and it showed this notification:
The viewport size is 1280px, whereas the window size is 412px.
I tried solutions from here and here but that did not help. It must be something else.
Do you have any idea what could be causing this?
This is something I usually do for Phaser 3, but even though you're using Phaser 2 you could try resizing the canvas outside of Phaser 2's functionality.
From Emanuele Feronato's How to scale your HTML5 games if your framework does not feature a scale manager – or if you do not use any framework:
/**
* From https://www.emanueleferonato.com/2018/02/16/how-to-scale-your-html5-games-if-your-framework-does-not-feature-a-scale-manager-or-if-you-do-not-use-any-framework/
*/
function resize() {
const canvas = document.querySelector("canvas");
const width = window.innerWidth;
const height = window.innerHeight;
const wratio = width / height;
const ratio = Number(gameConfig.width) / Number(gameConfig.height);
if (wratio < ratio) {
canvas.style.width = width + "px";
canvas.style.height = (width / ratio) + "px";
} else {
canvas.style.width = (height * ratio) + "px";
canvas.style.height = height + "px";
}
}
window.onload = function(){
// setup your game here
resize();
window.addEventListener("resize", resize, false);
}
Related
I implemented a signature pad using https://github.com/ramsatt/Angular9SignaturePad/tree/master/src/app/_componets/signature-pad and it works fine on smaller devices but on iPad or bigger devices like 7" upwards, it doesn't work properly.
When drawing on the screen, the resulting line has an offset from where the user touched (Signature drawn doesn't appear directly under the pen as user draws).
please how can I fix this.
So I fixed it by adding the below code and calling it in ngOnInit
resizeCanvas() {
var width = this.signaturePadElement.nativeElement.width;
var height = this.signaturePadElement.nativeElement.height;
var ratio = Math.max(window.devicePixelRatio || 1, 1);
if (ratio <= 2) {
this.signaturePadElement.nativeElement.width = width * ratio;
this.signaturePadElement.nativeElement.height = height * ratio;
this.signaturePadElement.nativeElement
.getContext("2d")
.scale(ratio, ratio);
}
then do
ngOnInit(){
this.resizeCanvas()
}
this.signaturePadElement is your Element gotten using ViewChild()
I have a mobile game with a BAR on the top of the screen. The bar and it's game objects are in canvas with "Screen Space - Overlay" mode plus a Canvas Scaler with scale mode of "Scale with Screen Size" and match equals "Match width or height".
I am animating a game object to the position of an object inside of this and the object is going completely of the screen (really far way).
I am trying to get the position of the object using code below.
Even so, the position being returned is complete of the screen. Any idea what I am doing wrong?
public Vector3 getObjectPosition()
{
// Getting my CANVAS
Camera cam = Camera.main;
GameObject canvasOverlayObject = GameObject.Find("CanvasOverlay");
Canvas canvas = canvasOverlayObject.GetComponent<Canvas>();
//Manual scalling the CANVAS
float canvasScaleX = Screen.width / canvasOverlayObject.GetComponent<CanvasScaler>().referenceResolution.x;
float canvasScaleY = Screen.height / canvasOverlayObject.GetComponent<CanvasScaler>().referenceResolution.y;
return Camera.main.ScreenToWorldPoint(new Vector3(transform.position.x / canvas.scaleFactor, transform.position.y / canvas.scaleFactor, 0));
}
No scaling was needed even using the scaled canvas, just passed the gameobject.tranform.position as the parameter.
public Vector3 getPosition()
{
Camera cam = Camera.main;
GameObject canvasOverlayObject = GameObject.Find("CanvasOverlay");
Canvas canvas = canvasOverlayObject.GetComponent<Canvas>();
Vector3 rawPosition = Camera.main.ScreenToWorldPoint(gameObject.transform.position);
return rawPosition;
}
I want to display UI logo images in their aspect ratio but in proper size that fit within its container. Already all logo images as per aspect ratio but few are too big or small compare to requirements.
At present this kind of thing happening:
Here is the code that I am using:
private void ShowGamePlayLogoViewed ()
{
for (int i = 0; i < DataCollection.companyDetailsList.Count; i++) {
Company company = DataCollection.companyDetailsList [i];
if (company.ViewedCounter > 0) {
GameObject companyItemObj = Instantiate (companyItemPref, gridViewContainer) as GameObject;
CompanyItem companyItem = companyItemObj.GetComponent<CompanyItem> ();
companyItem.companyId = company.CompanyId;
companyItem.UpdateCompanyLogo (company.CompanyLogo);
companyItem.UpdateCompanyName (company.CompanyName);
}
}
}
public void UpdateCompanyLogo (Sprite logoSprite)
{
logoImage.sprite = logoSprite;
logoImage.SetNativeSize ();
}
As you are seeing, logos overlapping the container. I want to display properly them in their respective containers also in aspect ratio too.
Let me clarify one more thing: all logos loaded from web server and they all are dynamic at a time, based on server data it will appear in mobile screen.
I have found solution through Unity Forum and I want to say thanks to #Hosnkobf for reply.
Here is the exact reply that worked for me properly:
adjust the image game object inside unity so that it has the height you are looking for. also adjust the anchors so that it scales with different resolutions properly.
Add an "AspectRatioFitter" component to the object. Make it "Height controls width".
Instead of logoImage.SetNativeSize (); do the following:
float aspectRatio = logoSprite.rect.width / logoSprite.rect.height;
var fitter = logoImage.GetComponent<UnityEngine.UI.AspectRatioFitter>();
fitter.aspectRatio = aspectRatio;
I hope this become useful to other members :)
While in editor, everything's working fine, but when I build the game to my phone, the background seems to be short on top and bottom side.
This is a screenshot from the phone build.
This is a screenshot from Unity.
I checked all sizes and they were all the same - 800x1280. I think the problem started to happen when I made the cloudy background infinitely move with a quad.
Checked everywhere, can't seem to pin-point the problem.
You should resize the background according to screen size. You can do that through code. If you are using Sprite Renderer, you can follow this link to do so. Here's the main codes needed to resize a sprite according to the above link.
void Awake() {
SpriteRenderer spriteRenderer = GetComponent<SpriteRenderer>();
float cameraHeight = Camera.main.orthographicSize * 2;
Vector2 cameraSize = new Vector2(Camera.main.aspect * cameraHeight, cameraHeight);
Vector2 spriteSize = spriteRenderer.sprite.bounds.size;
Vector2 scale = transform.localScale;
if (cameraSize.x >= cameraSize.y) { // Landscape (or equal)
scale *= cameraSize.x / spriteSize.x;
} else { // Portrait
scale *= cameraSize.y / spriteSize.y;
}
}
Or if you are using a UI Panel under Canvas to draw the background, you can set the anchors on the edge points and set the Canvas's UI Scale Mode to Scale With Screen Size
I've implented an app that only works in portrait mode. The app have a compass, we know that compass in samsungs tablets (e.g: samsung galaxy tab 2) and mobile devices works different, ones have NORTH (0º) in landscape an others in portrait.
We need to have all in portrait mode, in other words, we want that the NORTH (0º) in PORTRAIT. Anyone have a solution for that ?
I had the same issue with a Galaxy Note and followed advice on how to determine tablet or phone. This was in another posting but can't remember the link. The code looks like this:
DisplayMetrics metrics = this.getResources().getDisplayMetrics();
int screenWidth = metrics.widthPixels;
int screenHeight = metrics.heightPixels;
double inches = Math.sqrt((metrics.widthPixels * metrics.widthPixels)
+ (metrics.heightPixels * metrics.heightPixels))
/ metrics.densityDpi;
// tablets typically larger than 6"" diagonally
// this is attempt to orient both player and magnetic sensors
if (inches > 6) {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
} else
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
After doing this, I translated the azimuth setting in the sensorlistener code:
public void onSensorChanged(SensorEvent event) {
// Note: Not all sensor events will supply both accelerometer and
// mag-field
int s = event.sensor.getType();
switch (s) {
case Sensor.TYPE_ACCELEROMETER:
aValues = lowPass(event.values.clone(), aValues);
break;
case Sensor.TYPE_MAGNETIC_FIELD:
mValues = lowPass(event.values.clone(), mValues);
break;
}
float[] R = new float[16]; // Rotation Matrix result goes here
float[] I = new float[9]; // Inclination Matrix result goes here
float[] oValues = new float[3]; // used for new orientation
boolean success = SensorManager.getRotationMatrix(R, I, aValues,
mValues);
// if both aValues and mValues are not null success will be true
// Also returns the Inclination Matrix
if (success) {
// Now get the device's orientation from the Rotation and
// Inclination Matrices
SensorManager.getOrientation(R, oValues);
// Change Radians to Degrees
oValues[0] = (360 + (float) Math.toDegrees(oValues[0])) % 360;
oValues[1] = (float) Math.toDegrees(oValues[1]);
oValues[2] = (float) Math.toDegrees(oValues[2]);
azimuth = oValues[0];//
y_az = oValues[1];// orientationValues[1];
z_az = oValues[2];// =
// test portrait or landscape (different on Tablets)
int test = getResources().getConfiguration().orientation;
// if necessary, azimuth = azimuth+270f or + 90f %360
heading.setText("X:" + Math.round(azimuth) + " Y:"
+ Math.round(y_az) + " Z: " + Math.round(z_az)
+ " degrees");
}
}
I ended up letting the tablet stay in landscape mode since most users would orient it that way and North is at the top of the landscape. I hope my rookie code (with plenty of help from others) can help you.