Issues with running on apple devices and screen size



I have noticed problems with running on iphones in the past, and for my latest game, I received this comment "The game didn't run past the start screen on my iPad (iOS 7.1)".


Do you have to do something different with apple devices or have you seen this problem ?

If you go to my site and try sector 7 with an apple device, I would be interested in what you see.


I think foxcode has played it on an android device and he said everything worked ok, but I don't know if he has tried it lately.


On a related note, what should I set the screen size to so the game plays on the widest number of devices.


Lately I have been using 608 x 920 like I have seen in some of your source stuff. Is that a standard size or is there some other size I should be using ?


thanks for any help




All 8 Comments

Hi Shri


The fact that the start screen loads and the rest doesn't, makes me think it's a problem with something you're loading after the start screen - maybe sound?


For apple devices you need your sounds in aac/mp4 format. They need to be called the same as your .ogg files, just a different extension. In code, you keep using playAudio('myAudio.ogg'), but on iOS Safari (that doesn't support .ogg), WADE will look for the aac version.


Regarding screen sizes, it's tricky. It depends on which device(s) you think your game is going to be played on most of the time. It's difficult to know beforehand. Using the developer tools in Chrome (F12) there is a little phone icon in the top-left corner. It shows some common screen sizes when you click it.


608 x 920 is something we came up with for portrait-mode games when the browser bar is visible and takes some of the vertical space. But really it's better to use a flexible layout setting minScreenSize and maxScreenSize to different values, to be sure it look the best on all devices regardless of aspect ratio.




I've actually had this problem for quite some time on apple devices, so I must be doing something fundamentally wrong.

I've just never had a good reason to dig around and figure out what the problem was. Anyway...


All the sound files are up there in aac and ogg format.


I checked it out on my sons iphone.

Here's what happens:

  • Loading screen loads and then finishes.
  • Intro music starts playing.
  • Intro screen loads  first image, and then fades out to show the second intro image
  • Then you can't start the game by clicking the start button on the intro screen


here are the snippets I use to hand off and return control from various "Scenes"

the game scene loader in the main app

this.gameSceneLoader = function(sceneName) {		console.log('load game scene ' + sceneName);		currentScene = null;		var params = { sceneParameters: {			app: self,			layer: self.SCENE_LAYER,			width:,			height:,			levelNumber: levelNumber || 0		}};				mySoundManager.playLoop(self.SOUND_MUSIC_INTRO);		switch (sceneName) {			case 'IntroScene':				currentScene = new SceneObject(0, IntroScene, 0, 0);				break;			case 'HelpScene':				currentScene = new SceneObject(0, HelpScene, 0, 0);				break;			case 'SplashScene':				currentScene = new SceneObject(0, SplashScene, 0, 0);				break;			case 'LevelScene':				currentScene = new SceneObject(0, LevelScene, 0, 0);				break;			case 'CreditScene':				currentScene = new SceneObject(0, CreditScene, 0, 0);				break;			default:				break;		};	// end switch		wade.addSceneObject(currentScene,false,params);	};	// end gameSceneLoader

and the game scene manager in the main app

this.gameSceneManager = function(sceneName,sceneState) {        console.log('game scene manager ' + sceneName + ' ' + sceneState + ' ' + gameState.current);        mySoundManager.stopAll();        switch(gameState.current) {            case gameState.INTRO:                console.log('intro callback from ' + sceneName + ' ' + sceneState);                wade.removeSceneObject(currentScene);                if (sceneState == 'loadHelp') { self.gameSceneLoader('HelpScene'); }                else {                    gameState.current = gameState.LOAD_LEVEL;                    self.gameSceneLoader('LevelScene',levelNumber);                }                break;            case gameState.LOAD_LEVEL:                console.log('load level callback from ' + sceneName + ' ' + sceneState);                wade.removeSceneObject(currentScene);                self.loadLevel();                gameState.current = gameState.PLAYING;                self.startGame();                break;            case gameState.PAUSED:                console.log('callback from paused state' + sceneName + ' ' + sceneState);                wade.removeSceneObject(currentScene);                gameState.current = gameState.PLAYING;                self.gameUnpause();                break;            case gameState.OVER:                wade.clearScene();                levelNumber = 1;                gameState.current = gameState.INTRO;                self.loadIntro();                break;            default:                break;        };    // end switch    };    // end gameSceneManager

here is my introScreen.js file

IntroScene = function() {	var self = this;	var name = "IntroScene";	var mainApp;	var state = 'intro1Clicked';	var params;	var clickCount = 0;		this.onAddToScene = function(eventData) {		console.log(name + ' added to scene');		params = eventData.sceneParameters;		mainApp =;		var sp0 = new Sprite('./images/introScreen2.jpg',params.layer);		sp0.setSize(params.width,params.height);		self.owner.addSprite(sp0);		var sp1 = new Sprite('./images/introScreen.jpg',params.layer);		self.owner.addSprite(sp1);		sp1.setDrawFunction(wade.drawFunctions.fadeOpacity_(1,0,2,sp1.draw,self.titleFadeComplete));	};	// end onAddToScene		this.titleFadeComplete = function() {		console.log('title fade complete');		state = 'act1Complete';		wade.addEventListener(self.owner,'onClick');		return true;	};	// end titleFadeComplete		this.onClick = function(eventData) {		var sToW = wade.screenPositionToWorld(params.layer,eventData.screenPosition);		var choice = sToW.x;		if (choice < 0) { state = 'loadLevel'; }		else { state = 'loadHelp'; }		mainApp.gameSceneManager(name,state);		return true;	};	// end onClick		this.onRemoveFromScene = function() {		console.log(name + ' removed from scene');	};	// end onRemoveFromScene	};	// end IntroScene

When I do this -- wade.addEventListener(self.owner,'onClick'); am I adding it to the wrong place ?

Should it instead be (self,'onClick') ?

But then why does it work on everything but the apple ?


As usual, thanks for the help.





What you are doing with self.owner looks alright.


I don't have an iDevice handy for the weekend, but I can give this a go on Monday.


In the meantime, here's what I'd suggest if you can use an iPhone, as a quick and dirty debugging technique:


1) alert something in IntroScene.onClick so you know whether it's actually getting there or failing to register the click

2) depending on that, move the alert around so you can at least see where it is failing exactly


But anyway, I'll try to test it on Monday. Your code seems fine (though I'm missing quite a few pieces), so it may be that whatever you are legitimately doing is triggering a bug in WADE, and I do want to understand what happens.


While I'm here I'll also suggest this wonderful resource for when you don't have access to a particular type of device and want to debug on it:




For monday or whenever, I have attached the zip of all the sources minus wade 2.0.







I was trying to see what I could do to figure out my safari (apple) problem.

I'm testing with my Rift Runner game locally (it is smaller and less complicated).

I'm using wade 2.1 with Safari 5.1.7.


I have commented out sounds after seeing what a mess it is in Safari 517.

So now, when I run, I get the following on game startup


ReferenceError: Can't find variable: FileReader. wade_2.1.js:43


So I looked a little for this error and if you try and load fonts, in the assetLoader,

in the loadFont method line 751.

If there is no FileReader(), then there is no fallback.


So, I commented out fonts and got the rift runner game to run locally (yea !!)


Then I tried setting the user agent to IOS 4.3.3 (iphone or ipad)

And I ran into yet another problem (boo !!).

I kept getting errors related to anything I was using via wade.preloadScript()


This would jive with what I am seeing on the iphone when I try to run games from my website.

  • The app loads with the loading bar
  • The sound starts to play.
  • The intro screen images load and do their thing,
  • The game appears to hang - if you click start or help nothing happens


The way I have structured the code is that the game framework is made up of different "scenes".

Each scene has an associated behavior file. (ex: introScene.js, levelScene.js, etc).


The code that handles what to do when a user clicks a given scene is located in the behavior file.

So, if this behavior file is not loading, then the game would just appear to hang.


Anyway, hope this helps





Hey Shri


That's very interesting, thanks for looking into it - I just haven't had time recently. It's something I want to investigate further.


Regarding FileReader - there probably should be a fallback, although it's now very well supported (see here) so I didn't think it was a problem. But we're definitely adding a fallback for the next version (most likely this will just be ignoring fonts if FileReader is not supported, as it should be a very rare occurrence)


iOS 4 is also quite ancient and I'll have a hard time finding a device that runs it, but I'll see if I can find one (I believe even my old first-generation iPad is on iOS 5.1).


I'm honestly very confused as to why preloadScript wouldn't work on that version of iOS though, considering that loadScript works (or your game wouldn't work at all). The thing is, loadScript and preloadScript share exactly the same code, so it's really weird.


As an aside - wouldn't it be simpler to use the built-in scene system? So you can use preloadScene, loadScene etc. and that would simplify all your scene management logic.




Hopefully, I'm not just crying wolf ?


filereader - yes, I think the best thing would be to simply ignore the font, I just mentioned the fallback because I'm not sure how you would want to handle it.


IOS 4 - unfortunately, I still use an old machine (XP) and so can't run the latest version of safari. But the reviewer who couldn't get my game to run

was using 7.1 on a tablet. Also, I think the iphone 5c runs 4.3.3 ? Anyway, the point is the problem seems to exist with newer machines as

well, so you should be able to replicate it with a newer mac device.


Aside - I would prefer to go farther than what the engine offers with the load scene stuff. Please refer to my game state demo.






OK, I've finally found some time to take a good look. There are a few problems:


1) FileReader is indeed NOT supported by Safari iOS version 5.1 and lower. This is about 0.04% of devices (iPhone 5c's run version 7 or higher, not 4), so it is not a real problem, but one that we're fixing anyway in the next version of WADE. Basically if FileReader is not supported, we don't load fonts dynamically. Thanks for bringing this issue to my attention.


2) Don't use wade.preloadScript()  in your load function. The thing with preloadScript is that it loads scripts asynchronously in the background and it doesn't wait for the loading to finish before going on. So your app's init() function may be called before all the scripts are loaded. This can happen on any platform, but due to browsers handling async stuff differently, it may be more likely on some platforms than on some others. It appears to be very likely on iOS Safari. If you need your scripts to be loaded before App.init() is called, in App.load() use wade.loadScript() instead.


3) In older versions of iOS where WebAudio is not supported, you can't load audio whenever you like - it has to happen on user  input, so in an onClick or onMouseUp function for example. This is a ridiculous restriction that Apple used to enforce, but with WebAudio (in iOS 6) things got sensible again. To ensure compatibility with old Apple devices (say about 4-5 year old ones), you either check if WebAudio is supported before calling wade.loadAudio(), or use wade.preloadAudio(). With preloadAudio, wade doesn't wait for the audio to load before calling App.init(), and that's a good thing because on these old devices it may fail to load, so you don't want to be sitting there forever waiting for it to load, if it just doesn't. This is what you were doing in your code, so that's all fine. But if you do that, when you want to play audio (in your SoundManager.js file), use wade.playAudioIfAvailable() instead of wade.playAudio() or WADE will try to play a file that it can't load, and will crash.


Having changed these things, I got it to run on my 1st-generation iPad, and it's surprisingly quite fast :)


Aside -  I think you could do the same with much less code using the scene system, but I don't want to force you to use it :) Our development philosophy has always been to give you the tools, and the option not to use them if you prefer a different solution that, for whatever reason, works better for you.

Post a reply
Add Attachment
Submit Reply
Login to Reply