Cant quite nail scaling the game on mobile. Its not showing all of the game but only part of the game - phaser-framework

this.scale.scaleMode = Phaser.ScaleManager.SHOW_ALL;
this.scale.pageAlignHorizontally = true;
this.scale.pageAlignVertically = true;
this.scale.refresh();
Its a tiny game code which I have uploaded on http://scaleissue.site44.com/ so pls use browser dev tools to have a look.
As you will notice when u go to dev tools and choose mobile emulation (iphone 4, 5, 6 - landscape orientation only), the screen only shows the top-left corner of the actual game with scroll bars when in fact it should have scaled the game such that all of the game was being shown on the screen since I used
this.scale.scaleMode = Phaser.ScaleManager.SHOW_ALL;
(you might have to reload page to notice this issue when in dev tools). I tried the game on real mobile and still the same issue.
All relevant scaling code is under boot.js
Please help as I cant quite nail the issue having tried several scaling modes.

You can try to resize the canvas:
var width=window.innerWidth,
height=window.innerHeight,
dpr=window.devicePixelRatio || 1;
var game = window.game[NAMESPACE].game = new Phaser.Game(1024, 480, Phaser.AUTO, 'gameDiv');
var mainState = {
preload : function () {
game.scale.scaleMode = Phaser.ScaleManager.RESIZE ;
//game.canvas.style.width=width+'px';
game.canvas.style.height=height+'px';
},
create : function () {
this.stage.backgroundColor = '#0000db';
},
update : function () {}
};
//initialising Phaser
game.state.add('main', mainState);
game.state.start('main');
The rationale behind this code: The canvas.width value (which is a number) sets the size of the game, while the canvas.style.width value (which is a string) sets the size of the canvas element. To avoid deformations you should maintain the same ratio (in your case, the ratio is 1024/480) in both values. If you set the ScaleManager as RESIZE then this ratio is maintained automatically, that's the reason why I'm only setting the height.

Related

WKWebView: window.innerWidth reporting wrong value

I'm hosting some 3rd-party content in a WKWebView, and their content doesn't resize correctly on orientation change. It does resize correctly in Safari though.
window.onresize = function() { console.log(window.innerWidth) }
This prints the same width every time (768), regardless of orientation, but when I evaluate window.innerWidth on the console after the rotation has completed, it prints the correct width.
Is this a known issue? Are there any workarounds?
UPDATE:
What I ended up doing is re-firing the resize event after a delay. It's ugly but it solves my use case.
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
super.viewWillTransition(to: size, with: coordinator)
coordinator.animate(alongsideTransition: nil) { _ in
// Orientation change triggers the `resize` event, but `window.innerWidth` is
// wrong *during that time*. By calling resize a second time, we let content resize itself
// according to the correct dimensions.
// There's more! Sometimes the dimensions are still wrong after the rotation has completed,
// so we have to wait. The minimum reliable delay varies widely across devices.
DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(750)) {
self.webView?.evaluateJavaScript("window.dispatchEvent(new Event('resize'));", completionHandler: nil)
}
}
}
Yeah I had the same issue. You should use document.body.offsetWidth instead of window.innerWidth, because window.innerWidth can take additional 500ms until it updates itself after the window resize event. This is true at least for WKWebView in iOS.

cocos2d js - Touch on overlay sprites that move up together

I used latest version cocos2d-js to create my game. On the game screen, I added multiple sprites overlay in a row, like this
Overlay sprites
I added an event listener to move up a sprite on y-axis when it was clicked. However, when I clicked on the point that any two sprites contain, the two sprites moved up together.
This is my event listener code
var listener = cc.EventListener.create({
event: cc.EventListener.TOUCH_ONE_BY_ONE,
swallowTouches: true,
onTouchBegan: function (touch, event) {
var target = event.getCurrentTarget();
var location = target.convertToNodeSpace(touch.getLocation());
var targetSize = target.getContentSize();
var targetRectangle = cc.rect(0, 0, targetSize.width, targetSize.height);
if (cc.rectContainsPoint(targetRectangle, location)){
target.setPositionY(50);
}
}
});
How can I prevent to move them up together and move only one sprite?
Thanks.
onTouchBegan must returns boolean value as result, if returns true it's means touch was handled and event cycle will be stopped. Try to return true, if rect contains point.
Hope this helps. And sorry for my English.

Phaser.io - Load objects from Tiled

I'm new to phaser, and for the past few days I've been trying to make a really simple game, platformer-style, where the player must navigate to certain areas before being able to exit the level.
I have the basics running, but now I can't seem to figure out how to check if the player is in those areas.
The relevant part of the code so far is as follows:
var game = new Phaser.Game(800, 600, Phaser.AUTO, "mygame", {
preload: preload,
create: create,
update: update,
render: render
});
function preload() {
game.load.tilemap("questMap", "assets/quest.json", null, Phaser.Tilemap.TILED_JSON);
game.load.image("tilesheet", "assets/tilesheet.png");
game.load.image("npc", "assets/npc.png");
game.load.spritesheet("player", "assets/player.png", 64, 64);
}
var map;
var tileset;
var groundBg;
var props;
var houses;
var houseProps;
var npc;
var ground;
var areas;
var player;
function create() {
game.physics.startSystem(Phaser.Physics.ARCADE);
game.stage.backgroundColor = "#A8DBFF";
map = game.add.tilemap("questMap");
map.addTilesetImage("tilesheet");
map.addTilesetImage("npc");
ground = map.createLayer("ground");
groundBg = map.createLayer("groundbg");
props = map.createLayer("props");
houses = map.createLayer("houses");
houseProps = map.createLayer("houseprops");
npc = map.createLayer("npc");
map.setCollisionBetween(1, 5000);
ground.resizeWorld();
Not too pretty, I know.
I've created the map with tiled and there are a lot of small props and decorative tiles, hence the multiple "map.createLayer()" calls. The only one with collision is the ground layer.
Now, on my Tiled file, I've created an Object layer and drawn small rectangles on the areas I want to check if the player is in. I thought this was going to be an easy process but I can't seem to figure out how to load those areas into Phaser, and then check if the player is within bounds.
Googling has given me some results, but none seem to fit, as they usually cover how to add a sprite to an object, which in this case does not apply.
I simply need that small area to exist and check if the player is there. I've also given names to each of those rectangles in Tiled, via the custom properties tab.
I would try using a transparent image as the area you wish to check if your sprite is over and use
if(sprite1.overlap(transparentImage)){
//do something
}

How to implement auto-hide navigation?

I'm not sure where to post this question, so please excuse me if I am violating any policies.
To clarify my question, I want to achieve the same navigation bar as Teehan + Lax's.
Here is their website: http://www.teehanlax.com/tools/
If you notice, the navigation auto hides itself when you scroll down, however when you scroll up it would show it self again.
So my question is, how did they achieve this? Is it through only CSS or do I need JavaScript to do this? Whatever way it is, can someone also point towards the right direction on how I can find the information to implement this?
Thank you
It's not possible to change position from fixed to absolute in pure CSS like you want, so I used some javascript to do so. Demo
function followTo(elem, pos) {
var element = document.getElementById(elem);
window.onscroll = function(e){
var disFromTop = document.all? iebody.scrollTop : pageYOffset;
if (disFromTop > pos) {
element.style.position = 'absolute';
element.style.top = pos + 'px';
} else {
element.style.position = 'fixed';
element.style.top = 0;
}
};
};
followTo("nav", 100);
It even includes an IE fix pulled from this SO post to get the correct scroll position
Here is the jQuery version, taken from this SO post
EDIT
As pointed out by zanona, I did not include the feature where the navigation appears if you scroll up from a place further down in the page. As a result, I create a new technique that uses a setInterval
var last = 0, // The last read top value
delay = 150, // The delay for the setInterval
threshold = 30; // The max scroll distance before showing/hiding the nav
//I always set a variable to my setIntervals in case I want to stop them later on
var navMovement = setInterval(function() {
var nav = document.getElementById('nav'), // Gets nav object
pageVertOffset = document.all? iebody.scrollTop : pageYOffset;
// Happens if the difference in scroll is below the negative threshold
if(pageVertOffset - last < -threshold) {
nav.style.top = "0px"; // Put the nav at the top of the window
}
// Happens if the difference in scroll is above the threshold
else if(pageVertOffset - last > threshold){
nav.style.top = - nav.offsetHeight + "px"; // Hides the navigation
}
last = pageVertOffset; // Updates the previous scroll value
}, delay); // Runs every `delay` amount
Javascript version, or if you prefer, jQuery version
I thought I recreated the site pretty well (but it's better because mine has a kitten, haha)

Titanium handling different resoutions

Simple question, which is the best way to make sure that the app works on different screen resolutions without looking crap? I can't use static values, then it want adjust according to the resolution. Right now i am using relative measurements (percentage of screen) but wonder if that's really the best way to handle it!?
Another/additional option we have been successful with is a small set of functions which use the screen density value to compute display sizes... this is of course only an approximation, as there are only the four densities, but we have found this to be very helpful.
//=============================================================================
// inch
//
// compute approximate number of pixels for the specified physical on-screen
// size based on the density reported by the OS
//=============================================================================
function inch(size)
{
// default to 160 dpi if unavailable
var height = size * 160.0;
try
{
// compute header height based on screen density ... target .25" height
height = size * Ti.Platform.displayCaps.dpi;
}
catch(e) { warn("Error accessing display caps for screen density calculation: " + e); }
return height;
}
So if you want something to be 3/4 inch high on the screen....
Ti.UI.createThing({ height: inch(.75)});
...or if you want to scale things by point size, one could make some constants...
const g_12pt = inch(12/72); //0.166667
const g_10pt = inch(10/72); //0.138889
const g_8pt = inch(8/72); //0.111111
const g_6pt = inch(6/72); //0.083333
...
...font:{fontSize: g_10pt, fontWeight:"bold"},...
We also created a couple of functions to get the screen height and width, so if we wanted a better layout on a tablet or something tiny we could better understand what we were dealing with.
//=============================================================================
// screenWidth - return screen width in inches
//=============================================================================
function screenWidth()
{
return Titanium.Platform.displayCaps.platformWidth / Titanium.Platform.displayCaps.dpi;
}
//=============================================================================
// screenHeight - return screen height in inches
//=============================================================================
function screenHeight()
{
return Titanium.Platform.displayCaps.platformHeight / Titanium.Platform.displayCaps.dpi;
}
You can go on and on from there... but this really helped us nail down how we laid out our screens on the different densities and platforms. The inch function has exception handling only because we use it early in the app, and sometimes the Ti.Platform is still undefined. By the time we are laying out our reports Ti.Platform is available and so the screen functions do not have the exception handling. If you need to query earlier you may need exception handling in those as well.
Hope this helps!
You'll want to modify your tiapp.xml - in the android section you add a manifest record like so:
<android xmlns:android="http://schemas.android.com/apk/res/android">
<manifest>
<supports-screens android:anyDensity="false"/>
</manifest>
</android>
That will make the app default to the same style that the older versions of titanium used, where it basically scales them according to the device in use. More details on the change can be found here: http://developer.appcelerator.com/blog/2011/06/new-defaults-for-android-layouts-in-1-7.html
well, as far as I googled, the solution is :
1.detect the specific screen resolution:
// app/alloy.js
Alloy.Globals.isIos7Plus = (OS_IOS && parseInt(Ti.Platform.version.split(".")[0]) >= 7);
Alloy.Globals.iPhoneTall = (OS_IOS && Ti.Platform.osname == "iphone" && Ti.Platform.displayCaps.platformHeight == 568);
2.write query style tss:
// Query styles
"#info[if=Alloy.Globals.isIos7Plus]" : {
font : { textStyle : Ti.UI.TEXT_STYLE_FOOTNOTE }
},
"#title[if=Alloy.Globals.isIos7Plus]" : {
top: '25dp', // compensate for the status bar on iOS 7
font : { textStyle : Ti.UI.TEXT_STYLE_HEADLINE }
},
"#content[if=Alloy.Globals.isIos7Plus]" : {
font : { textStyle : Ti.UI.TEXT_STYLE_CAPTION1 }
},
"ScrollView[if=Alloy.Globals.iPhoneTall]" : {
height : '500dp'
}
refer to: http://docs.appcelerator.com/titanium/3.0/#!/guide/Alloy_Styles_and_Themes-section-35621526_AlloyStylesandThemes-Platform-SpecificStyles

Resources