Tom Atom

  • Content Count

  • Joined

  • Last visited

  • Days Won


Tom Atom last won the day on December 28 2019

Tom Atom had the most liked content!


About Tom Atom

  • Rank
    Advanced Member

Contact Methods

  • Website URL
  • Twitter

Profile Information

  • Gender

Recent Profile Visitors

5082 profile views
  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.