Tom Atom

  • Content Count

  • Joined

  • Last visited

  • Days Won


Everything posted by Tom Atom

  1. Dots & Boxes is web version of classic pencil and paper game for two players ( You can play either against your friend or against computer AI. Rules are simple: connect dots with lines to form boxes. Player closing up box gets extra move. Game was created for Coolmath Games. You can play it here.
  2. setting preserveDrawingBuffer to true works, but it has impact on performance on some devices - see this thread: It looks like flickering is related to specifis GPUs. So, you can make test for GPU in your game and set preserveDrawingBuffer accordingly. This is snippet from one of our games: public static getRenderer(): number { let badGPUList = [ /.*Mali.400.*/i, /.*Mali.450.*/i, /.*Mediatek.MT6582.*/i ]; // from: let canvas = document.createElement('canvas'); let gl: WebGLRenderingContext; let debugInfo; let renderer: string; try { gl = canvas.getContext('webgl') || canvas.getContext('experimental-webgl'); } catch (e) { return Phaser.AUTO; } if (!gl) { return Phaser.AUTO; } debugInfo = gl.getExtension('WEBGL_debug_renderer_info'); if (!debugInfo) { return Phaser.AUTO; } renderer = gl.getParameter(debugInfo.UNMASKED_RENDERER_WEBGL); console.log("renderer: " + renderer); for (let i = 0; i < badGPUList.length; i++) { let badGPURegEx = badGPUList[i]; if (badGPURegEx.test(renderer)) { console.log("In bad GPUs list => render to CANVAS"); return Phaser.CANVAS; } } return Phaser.AUTO; }
  3. @farhan selling / publishing is not covered in book. In fact, implementing sponsor APIs is usually very easy (despite the fact, every sponsor has different API). The hard part is to find sponsor interested in publishing your game and it is about writing emails... Also publishing on Google Play or Apple Appstore is easy - I used Cordova for this for some of our games and for ads I used Heyzap mediation (mediation between Heyzap, Chartboost, AdMob, Unity Ads). While sponsor implementation is easy, hard part is to keep single codebase for many different sponsors. I am writing small series about making maintainable games with Phaser 3. Currently it has 5 parts: @Matty77 not sure, why... Some slightly adjusted versions of game were published by sponsors, who made deep testing. But, no matter how deep testing is, there is always at least one device, that does not work! Sounds like some kind of game development law 🙂
  4. In Phaser Newsletter 123 was announced new type of GameObject - DOM Element. Here are some exmaples here: objects/dom element/ ,but it currently is not working with Phaser 3.12-beta 3 (there is quite fresh remark on GitHub, that "DOM Elements moved behind experimental flag for now"). Before that I tried wild things, like displaying rotating YouTube iframed video inside Phaser Game and it worked 🙂
  5. @Fractal Games look here: There is how to add tinto to BitmapText. If you take some additional work, you can try to replicate Phaser 2 behavior into Phaser 3.
  6. @Ahmed Khalifa Unfortunatelly, I also needed tint for BitmapText. Not beacuse I like it, but because sponsors still want to support old devices and for some of them, running in canvas is only solution. Finally, I wrote article on how to add this functionality to Phaser 3: It works for static BitmapText, but will not for DynamicBitmapText. Whole magic behind tint in Phaser 2 / PIXI is, that it creates small canvas for tinted sprite and renders tinted version into it. It rerenders it when sprite frame changes, etc. It than takes this prerendered canvas to display it on screen instead of frame from atlas. In Phaser 2 BitmapText is tinted character by character. In my solution whole tinted text is prerendered - this is reason, why it will not work with dynamic text.
  7. @pingu it is ok in this case, because that part of update is called only once. Why not call it in the end of create()? Because there still may be music/sound decoding process ongoing. During update you are regularly checking if audio is ready and then, before you change state to Manu/Play or whatever "real" game state, you start FB too. So, when real game is entered, everything is ready. (Of course, there is possibility to do it in create and set some flag. Then in update check if sounds are ready and FB game started too - this will run in parallel instead one after each other as in my case).
  8. Your solution is OK, but you should generalize it like this: if (player.x - enemy.x > 0) { enemy.scale.x = 1; } else { enemy.scale.x = -1; } ... so you are not dependent on fixed (340) position of enemy.
  9. @pingu - for load progress, see this Phaser 3 example: it is now about events, - regarding FB IG: I am using first this: // ------------------------------------------------------------------------- window.onload = () => { if (App.Global.FBINSTANT) { // check if FB Instant is present if (FBInstant == null) { App.Global.FBINSTANT = false; startGame(); return; } // FB Instant console.log("FB initializeAsync called"); FBInstant.initializeAsync().then(function () { console.log("FB initializeAsync completed"); startGame(); }).catch(function (e) { // FBInstant failed to initialize - switch off FBINSTANT setting and start standard game console.log("FB initializeAsync failed - fallback to standard game. Error: " + e.code + ": " + e.message); App.Global.FBINSTANT = false; startGame(); }); } else { // Standard game startGame(); } }; // ------------------------------------------------------------------------- function startGame(): Phaser.Game { let game = new Ninja2.Game(); = game; return game; } it initializes FB API and creates Phaser game. Game runs through states until it gets into Preloader. When preloader finishes its job, I do this in preloader update: // ------------------------------------------------------------------------- update() { // run only once - once the music is decoded do some tween animation if (!this._ready && this.cache.isSoundDecoded("Music")) { this._ready = true; let fbUtils = FBInstantUtils.FBInstantUtils.instance; let self = this; if (App.Global.FBINSTANT) { console.log("FB startGameAsync called"); FBInstant.startGameAsync().then(function () { console.log("FB startGameAsync completed"); fbUtils.onGameStart(); fbUtils.getPlayers(function () { // load saved data console.log("FB getDataAsync called"); FBInstant.player.getDataAsync(["saveData"]).then(function (data: any) { // stats if (data["saveData"] != null) { console.log("FB data loaded: " + JSON.stringify(data["saveData"])); App.Global.saveData = data["saveData"]; } else { console.log("No FB save data"); } App.Global.adsSupported = fbUtils.isAPISupported("getRewardedVideoAsync"); if (App.Global.adsSupported) { console.log("Ads supported"); } else { console.log("Ads not supported"); } // start game self.setPlayState(); }); }, self); }).catch(function (e) { console.log("FB startGameAsync failed. Error: " + e.code + ": " + e.message); }); } else { this.setPlayState(); } } } // ------------------------------------------------------------------------- private setPlayState(): void {"Play"); } Just remove / skip calls to fbUtils. They are my utils to build DB of profile photos, so it is not necessary to download it every time and to get players in context. So, in the end of preloader I start FB game (this is needed only once) and then I load saved data from FB and check some features, like whether rewarded video ads are available. After all these check I move to game - this game is small, so there is immediatelly Play state. But for larger game I would move to Menu.
  10. You have to send loading progress to FB from your game - create & use loadUpdate(). Do not set it to 100 in preload(). In preload() you only prepare list of assets for loading - it is not actual loading. Actual loading is started by Phaser when preload() exits. loadUpdate() { if (App.Global.FBINSTANT) { console.log("FB setLoadingProgress called " + this.load.progress); FBInstant.setLoadingProgress(this.load.progress); } }
  11. Try this: if (cursors.up.isDown) { //this.physics.velocityFromRotation(ship.rotation, 600, ship.body.acceleration); ship.setVelocity(Math.cos(ship.rotation) * 600, Math.sin(ship.rotation) * 600); // 1 } else { ship.setAcceleration(0); ship.setVelocity(0,0); // 2 } In physics, you use acceleration to calculate new velocity and velocity to get new position. If you are driving car and accelerating for some time, your velocity increases. When you yake the foot out of the gas, your acceleration is 0, it does not increase velocity and your velocity is constant (unless there is inplemented something like friction or drag, which will slow you down). What you need is immediate change in velocity - it is commented as // 1. You can also add line // 2 to immediately stop ship if not holding up key... but it looks ugly (it is like you not only put foot out of gas, but stomped on break in the same time) Alternatively, you can change original line to this: this.physics.velocityFromRotation(ship.rotation, 600, ship.body.velocity);
  12. No, there is no such time - your game is running in single thread and you are in risk, that browser will say your game is not responsive. If you do not want to split your long running task into smaller steps, then you have to use Web Workers as @stupot suggested - it will start separate thread. Look at here: Unfortunatelly, Web Workers are not supported in old browsers (not a big problem), you have to have its task in separate file and you have to take care of communication between your game and Worker - postMessage / onmessage.
  13. I was just solving this recently - AI thinking / computer generating in 2 games. for computer generating I had long time running loop. I changed it, that I record some variables, that allow me to re-enter method and continue where it ended last time. Then in my update() method I am calling it as long as it is generating. Something like bellow. Every frame I do as many steps as time "lastDelta * 0.9" allows me. Making only one step per frame would be bad - if you needed 10000 steps then it would take 166 seconds with 60 FPS: private _computerIsGenerating: boolean; // ------------------------------------------------------------------------- public update(): void { if (this._computerIsGenerating) { if (this.generate()) { this._computerIsGenerating = false; } } } // ------------------------------------------------------------------------- private generate(): boolean { let enterTime = this.time.time; let lastDelta = this.time.elapsed; do { // step generator let ready = this._generator.generateStep(); // found new puzzle if (ready) { return true; } } while ( - enterTime < lastDelta * 0.9); return false; } for AI thinking in another game, AI was doing lot of different things like board analysis, looking for some possible moves, etc. in one big loop. I broke it into states and whenever state is changed, I return and next frame I continue again with last state.
  14. Hi, you can load assets outside preload method. Look at this example:\loader\loader%20events\start%20loader%20manually.js
  15. Hi, do you mean this: If yes, I was about to make Phaser 3 version with some changes (like removing support for special binary format, that no one uses). But I decided to wait some time, as there is still lot of changes in engine with every new release.
  16. @PixelPicoSean hmmm... it is Mali-400 ( Let us know, about results!
  17. Problem is connected with this bug: If I run, for example, this example: objects/particle emitter/angled emitter.js in Canvas, it hits problematic line in ParticleManagerCanvasRenderer.js (
  18. You can look at this topic: Setting preserveDrawingBuffer worked well, but for some devices, as I was reported by friends, it means big slowdown. Flickering is not caused by browser, but appears on devices with certain GPU. Here is list: Mali-400, Mali-450, Mediatek MT6582 List probably is not complete, so It would be good to add next GPUs if discovered. You can detect GPU on device like this: - I did not test it yet, but I am about to, as I have to make changes into one of our games. If you detected "bad" GPU, solution for Phaser 2 was to start game in Canvas rendering. Unfortunately Phaser 3 (3.11.0) is not ready for this yet. There are some fatures currently not supported in Canvas (tint - I added issue on GitHub with solution to support it at least for BitmapText - or at blog: and some are not working (RenderTexture - issue from yesterday - again with solution: So, you have two options: - use preserveDrawingBuffer and some devices may be really slow, - switch to canvas for some devices. If you do not need tint or render textures, you are happy and can switch without fixes. Otherwise, you may apply fixes and make your build.
  19. @pingu found the problem... it is related to Phaser texture creating. See method createTextureFromSource() ( It sets wrap mode to CLAMP_TO_EDGE by default, which would be OK and no bleeding would be shown. But... if texture dimensions are power of two (which is your case), then it changes wrap mode to REPEAT. You can encounter imprecisions in GPU calculations, so your texture is drawn and small part is repeated - it is that bleeding. Your current sprite scale is 0.406, if you set it to 0.5, then calculations are little different and bleeding is not shown. If you animated scale, then bleeding would probably blink - sometimes shown, sometimes not. So, solutions are: - add extra padding around your shape as @bossikkk suggested. If you want to preserve texture size 512x512, then draw your shape 510x510 and leave 1px empty on all sides, - simply change dimensions of your texture to not be power of 2 - like add 1 empty line and column to make it 513x513 texture (this is OK for development, but I do not like this solution - not sure, but I have somewhere back in my mind, that some GPUs are adding extra space for non POT textures to force them to nearest POT - in your case it would be 1024x1024 with lot of memory eaten.)
  20. Hi, I am using Typescript and this works for me: export class Preloader extends SceneBase { // ------------------------------------------------------------------------- public constructor() { // list of files to load as scene payload let files = []; // general config files.push({ type: "json", key: "Config", url: "assets/config.json" }); // sponsor specific config if exists if (Sponsor.isFeatureOn("hasConfig")) { let sponsorConfigUrl = `assets/sponsor/config_${Sponsor.features().name}.json`; files.push({ type: "json", key: "SponsorConfig", url: sponsorConfigUrl }); } // preload assets - like loading bar, etc. super({ key: "Preloader", pack: { files: files } }); } : : : I am loading game configs during constructor and I plan to load loading bar graphics too. I think, your problem is, you defined pack, but are not passing it to super class constructor - you are passing only "key" for scene name. See my super call in the end.
  21. Is your image part of atlas? If yes, did you add padding between sprites?
  22. You will never handle this with single game object. You have to build your own complex game object with other game objects. Split it into atomic objects that are present in Phaser. Then build up. For example, Phaser has Sprite and BitmapText - these are atomic for you. Create new class extending Phaser Container, put Sprite and BitmapText into it and you have new game object element "Sprite with text" ... so you can, for example, make: "* 3500" Then create buttons and any other elements you need and finally create WinDialog (again extending Phaser Container) and compose it from your basic elements. You can then tween whole dialog (like pop) or tween any individual elements. BTW, dialog like this is lot of work. Do not expect single function or game object to do all the work for you...On the other hand, if you make your elements good, then you can reuse it for other dialogs (and even outside of dialogs) in game - like "Sprite with text" in game HUD
  23. One thing that helps me a lot, especially in scenes like menu, splash, etc., is to place world coordinates 0,0 into center of screen. Then many things can be placed relative to it and on resize you do not have to reposition it. Of course, it does not work with things that should be stuck to screen borders.
  24. I did not try, but: Container has method sort(property) ( So, it should work to call it manually with any property. If still setting/getting depth on images in Container, it will probably fire depth sort on scene objects (
  25. Hi, Scenes have property game (Phaser.Game), but it seems to be undefined all the time (in preload, create or update methods of scene). Doc says: "This property will only be available if defined in the Scene Injection Map." and I can see it in default injection map ... but still undefined. On the other side, there is sys property (object) with game property in it. I can get game reference like instead of Is it correct to use Why is not working? Is it some leftover from older version?