{"id":168,"date":"2017-04-24T10:35:57","date_gmt":"2017-04-24T10:35:57","guid":{"rendered":"http:\/\/www.netexl.com\/blog\/?p=168"},"modified":"2017-11-11T19:05:10","modified_gmt":"2017-11-11T19:05:10","slug":"handling-moving-tweens-in-a-responsive-game-in-phaser","status":"publish","type":"post","link":"https:\/\/www.netexl.com\/blog\/handling-moving-tweens-in-a-responsive-game-in-phaser\/","title":{"rendered":"Handling of Moving Tweens in a Responsive Game in Phaser"},"content":{"rendered":"<p>If you went\u00a0through previous <a href=\"https:\/\/www.netexl.com\/blog\/making-of-a-responsive-game-in-phaser-part-1\/\" target=\"_blank\">articles<\/a>\u00a0on making of a responsive game in Phaser, we handled scaling and placement of individual elements according to the available width and height for the game. I moved on to writing next responsive game in Phaser and came across another scenario which requires additional handling. In <a href=\"http:\/\/www.netexl.com\/games\/numberspread\/\" target=\"_blank\">Number Spread<\/a> game we did not use any tween to move elements between two points. In my next game I planned to create a domino game where effects like dealing domino tiles to the players were required to be handled. While aligning and scaling of the elements were done exactly how it was done in <a href=\"http:\/\/www.netexl.com\/games\/numberspread\/\" target=\"_blank\">Number Spread<\/a> game, additional scenario which I needed to handle was managing the tweens which were used to deal domino tiles to the players.<\/p>\n<div style=\"height:250px;\"><script async src=\"\/\/pagead2.googlesyndication.com\/pagead\/js\/adsbygoogle.js\"><\/script>\r\n<ins class=\"adsbygoogle\"\r\n     style=\"display:inline-block;width:300px;height:250px\"\r\n     data-ad-client=\"ca-pub-0810934084049672\"\r\n     data-ad-slot=\"8927903874\"><\/ins>\r\n<script>\r\n(adsbygoogle = window.adsbygoogle || []).push({});\r\n<\/script><\/div>\n<p>Consider the scenario where I made a chained tweens set to deal domino tiles to the players. I resized my game\u00a0halfway through the dealing of tiles. At this point my <strong>RESIZE\u00a0<\/strong>method was called and I could\u00a0now handle whatever was\u00a0required to be done and I had additional work to do since the tweens set I created for dealing the tiles had not yet finished and their target positions (x,y co-ordinates)\u00a0were calculated according to the previous available width and height. Now I needed to handle two things here; <em>First<\/em>, Move and\u00a0scale tiles which are already dealt; <em>Second<\/em>, scale and modify the tiles which are\u00a0yet not dealt.\u00a0We know from\u00a0Number Spread game articles how to take care of the first. The second one needs handling of two things\u00a0&#8211; Scaling\u00a0of\u00a0tiles as well as\u00a0modification of the target position of those tiles in the tweens itself so that tweens know how to deliver the remaining tiles to the correct new positions. For that purpose we would need to keep a temporary reference of current running tweens in our game. In <strong>RESIZE\u00a0<\/strong>method we will pause the running tweens, change their target positions and then resume the tweens again.<\/p>\n<p>As we did in the previous game, we will first divide\u00a0game screen into various parts to place\u00a0different elements. We are going to again use different layout for portrait and landscape orientations. See below for the layout I decided for the game (layout is posted just to give you\u00a0a better understanding of various elements&#8217; positioning when you are going through the code)<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-171 size-full\" src=\"https:\/\/www.netexl.com\/blog\/wp-content\/uploads\/2017\/04\/DominoGame1.png\" alt=\"\" width=\"655\" height=\"482\" srcset=\"https:\/\/www.netexl.com\/blog\/wp-content\/uploads\/2017\/04\/DominoGame1.png 655w, https:\/\/www.netexl.com\/blog\/wp-content\/uploads\/2017\/04\/DominoGame1-300x221.png 300w, https:\/\/www.netexl.com\/blog\/wp-content\/uploads\/2017\/04\/DominoGame1-280x206.png 280w\" sizes=\"auto, (max-width: 655px) 100vw, 655px\" \/><\/p>\n<p>First I am going to create some classes for handling dominoes and decks in my game.\u00a0These classes would be used and extended later on in the game. Currently it is the bare minimum code to handle a deck of dominoes.<\/p>\n<pre class=\"lang:default decode:true\">\/\/ ---------------Domino---------------------\r\nfunction Domino(rank1, rank2, frame, counter) {\r\n    \/\/ rank2 is always equal to or greater than rank1\r\n    this.rank1 = rank1;\r\n    this.rank2 = rank2;\r\n    this.frame = frame;\r\n    this.counter = counter;\r\n};\r\n\/\/ ---------------Deck---------------------\r\nfunction Deck(noOfDecks, game, left, top, properties) {\r\n    this.dominoes = [];\r\n    this.game = game;\r\n    this.dominoSpacerX = 0;\r\n    this.dominoSpacerY = 0;\r\n    this.left = left;\r\n    this.top = top;\r\n    this.noOfDecks = noOfDecks ? noOfDecks : 0;\r\n    this.display = false;\r\n\r\n    if (properties) {\r\n        this.properties = properties;\r\n        if (this.properties.anchor)\r\n            this.anchor = { x: this.properties.anchor.x, y: this.properties.anchor.y };\r\n\r\n        if (this.properties.frame)\r\n            this.frame = this.properties.frame;\r\n    }\r\n\r\n    if (this.noOfDecks &gt; 0)\r\n        this.initDominoes();\r\n};\r\n\r\nDeck.prototype.initDominoes = function () {\r\n    var counter = 0;\r\n    for (var i = 0; i &lt; this.noOfDecks; i++) {\r\n        for (var rank1 = 0; rank1 &lt;= 6; rank1++) {\r\n            for (var rank2 = rank1; rank2 &lt;= 6; rank2++) {\r\n                counter++;\r\n                this.dominoes.push(new Domino(rank1, rank2, (counter - 1), counter));\r\n            }\r\n        }\r\n    }\r\n};\r\n\r\nDeck.prototype.shuffle = function (count) {\r\n    for (var i = 0; i &lt; count; i++) {\r\n        shuffle(this.dominoes);\r\n    }\r\n};\r\n\r\nDeck.prototype.draw = function (toDeck, count) {\r\n    for (var i = 0; i &lt; count; i++) {\r\n        var domino = this.dominoes.pop();\r\n        toDeck.addDomino(domino);\r\n    }\r\n};\r\n\r\nDeck.prototype.addDomino = function (domino) {\r\n    this.dominoes.push(domino);\r\n};\r\n\r\nDeck.prototype.getPositionX = function (index, leftMargin, tileScale, tileMargin) {\r\n    var scale = tileScale ? tileScale: 1;\r\n    var localMargin = (leftMargin &amp;&amp; this.dominoSpacerX &gt; 0) ? leftMargin : 0;\r\n    var localTileMargin = (tileMargin &amp;&amp; this.dominoSpacerX &gt; 0) ? tileMargin : 0;\r\n\treturn (this.left + index * this.dominoSpacerX * scale - localMargin + index * localTileMargin + this.dominoSpacerX * scale \/ 2);\r\n};\r\n\r\nDeck.prototype.getPositionY = function (index) {\r\n    return (this.top + index * this.dominoSpacerY);\r\n};\r\n\r\nfunction shuffle(array) {\r\n    var i = 0\r\n      , j = 0\r\n      , temp = null;\r\n\r\n    for (i = array.length - 1; i &gt; 0; i -= 1) {\r\n        j = Math.floor(Math.random() * (i + 1));\r\n        temp = array[i];\r\n        array[i] = array[j];\r\n        array[j] = temp;\r\n    }\r\n}\r\n<\/pre>\n<p>Now let us look at the game code<\/p>\n<pre class=\"lang:default mark:106-115,118-124,180-199 decode:true \">var TheGame = {\r\n};\r\n\r\nTheGame.Params = {\r\n\tbaseWidth: 1920,\r\n\tbaseHeight: 1080,\r\n\tmarginMultiplier: 0.9,\r\n\twidthMultiplerPortrait: 0.9,\r\n    widthMultiplerLandScape: 0.8,\r\n    maxTiles: 7,\r\n\tminPadding: 50,\r\n\tbackFrame: 29,\r\n    blankFrame: 28,\r\n\ttileSize: {\r\n\t\twidth: 50,\r\n\t\theight: 98\r\n\t}\r\n};\r\n\r\nTheGame.Boot = function (game) { };\r\n\r\nTheGame.Boot.prototype =  {\r\n    init: function () {\r\n        this.scale.scaleMode = Phaser.ScaleManager.RESIZE;\r\n    },\r\n    preload: function () {\r\n        this.load.image(\"loading\", \"loadingback.png\");\r\n    },\r\n    create: function () {\r\n        this.state.start(\"Loading\");\r\n    }\t\r\n};\r\n\r\nTheGame.Loading = function (game) {\r\n};\r\n\r\nTheGame.Loading.prototype = {\r\n    init: function () {\r\n    },\r\n    preload: function () {\r\n        var loadingBar = this.add.sprite(this.world.centerX, this.world.centerY, \"loading\");\r\n        loadingBar.anchor.setTo(0.5);\r\n        this.load.setPreloadSprite(loadingBar);\r\n\r\n        this.load.spritesheet(\"dominoes\", \"dominoes_2.png\", 50, 98);\r\n        this.load.image(\"reload\", \"reload.png\");\r\n\r\n    },\r\n    create: function () {\r\n       this.state.start(\"TheGame\");\r\n    }\r\n};\r\n\r\n\r\nTheGame.MyGame = function (game) {\r\n};\r\n\r\nTheGame.MyGame.prototype = {\r\n    preload: function () {\r\n    },\r\n    create: function () {\r\n        this.isMoving = false;\r\n        this.group = this.game.add.group();\r\n        this.dominoesMap = {};\r\n \r\n\t\t\/\/ Dealer Deck\r\n        this.dealer = new Deck(1, this.game, -200, -200, { anchor: { x: 0.5, y: 0.5 } });\r\n        this.dealer.shuffle(5);\r\n\r\n        \/\/ Player 1 Deck\r\n        this.player1Deck = new Deck(0, -200, -200, { anchor: { x: 0.5, y: 0.5 } });\r\n        this.player1Deck.dominoSpacerX = TheGame.Params.tileSize.width;\r\n        this.player1Deck.display = true;\r\n\r\n        \/\/ Player 2 Deck\r\n        this.player2Deck = new Deck(0, -200, -200, { anchor: { x: 0.5, y: 0.5 } });\r\n        this.player2Deck.frame = TheGame.Params.blankFrame;\r\n        this.player2Deck.dominoSpacerX = TheGame.Params.tileSize.width;\r\n        this.player2Deck.display = false;\r\n\r\n        this.reloadButton = this.game.add.button(-200, -200, \"reload\", this.reload, this);\r\n        this.reloadButton.anchor.setTo(0.5);\r\n        this.reloadButton.visible = false;\r\n\r\n        this.initDominoControls(this.dealer); \/\/ Initialize Domino Controls\r\n\r\n        this.positionControls(this.game.width, this.game.height);\r\n\t\t\r\n\t    \/\/ Wait before dealing domino tiles\r\n        this.game.time.events.add(1000, this.actuateRowDecks, this);\r\n    },\r\n    initDominoControls: function (deck) {\r\n        var dominoes = deck.dominoes;\r\n        var count = dominoes.length;\r\n        for (var i = 0; i &lt; count; i++) {\r\n            var control = this.game.add.sprite(this.dealer.left, this.dealer.top, \"dominoes\");\r\n            control.frame = TheGame.Params.backFrame;\r\n            control.domino = dominoes[i];\r\n            this.game.physics.arcade.enable(control);\r\n            control.anchor.setTo(0.5, 0.5);\r\n            this.applyScale(control, this.tilesScale);\r\n            this.group.add(control);\r\n            this.dominoesMap[dominoes[i].counter] = control;\r\n        }\r\n    },\r\n    updateTweenXY: function (tween, targetObject, startPosition, endPosition) {\r\n        \/\/begin at current tween position\r\n        tween.timeline[0].vStart = { x: startPosition.x, y: startPosition.y };\r\n        \/\/update the duration of the tween so that it will not overrun.\r\n        tween.timeline[0].duration = tween.timeline[0].duration - tween.timeline[0].dt;\r\n        \/\/set the new tween condition\r\n        tween.timeline[0].vEnd = { x: endPosition.x, y: endPosition.y };\r\n        \/\/reset the dt, if you reset dt it is the same as rewinding your tween to the beginning\r\n        tween.timeline[0].dt = 0;\r\n    },\r\n    positionControls: function (width, height) {\r\n        \/\/ pause all running tweens which are moving a sprite\r\n        if (this.currentTweens) {\r\n            for (var i = 0, count = this.currentTweens.length; i &lt; count; i++) {\r\n                if (!this.currentTweens[i].isMoveComplete) {\r\n                    this.currentTweens[i].pause();\r\n                }\r\n            }\r\n        }\r\n        \/\/ We would consider landscape orientation if height to width ratio is less than 1.0.\r\n        \/\/ Pick any value you like or a preference for landscape or portrait orientation\r\n        var isLandscape = this.isLandscapeOrientation(width, height);\r\n        this.calculateOverallScale(width, height);\r\n\r\n        if (isLandscape) {\r\n            \/\/ 1x 4x 1x\r\n            \/\/ Dealer Deck\r\n            this.dealer.left = width - width * 0.125; \/\/ 25% Space\r\n            this.dealer.top = height \/ 12; \/\/ 1x Top \r\n\r\n            \/\/ Player 1 Deck\r\n            this.player1Deck.left = this.world.centerX;\r\n            this.player1Deck.top = height - height \/ 12; \/\/ 1x Bottom\r\n\r\n            \/\/ Player 2 Deck\r\n            this.player2Deck.left = this.world.centerX;\r\n            this.player2Deck.top = height \/ 12; \/\/ 1x Top\r\n\r\n            this.scaleSprite(this.reloadButton, width * 0.2, height \/ 6, 10, 0.5, true);\r\n            this.reloadButton.x = width - width * 0.125;\r\n            this.reloadButton.y = height - height \/ 12;\r\n\r\n            this.positionPlayerDominoes();\r\n            \r\n        } else {\r\n            \/\/ 1x 1x 6x 1x 1x\r\n            \/\/ Dealer Deck\r\n            this.dealer.left = width * 0.2 \/ 2;\r\n            this.dealer.top = height \/ 20;\r\n\r\n            \/\/ Player 1 Deck\r\n            this.player1Deck.left = this.world.centerX;\r\n            this.player1Deck.top = height - height \/ 10 - height \/ 20;\r\n\r\n            \/\/ Player 2 Deck\r\n            this.player2Deck.left = this.world.centerX;\r\n            this.player2Deck.top = height \/ 10 + height \/ 20;\r\n\r\n            this.scaleSprite(this.reloadButton, width * 0.2, height \/ 10, 10, 0.8, true);\r\n            this.reloadButton.x = width - width * 0.2 \/ 2;\r\n            this.reloadButton.y = height \/ 20;\r\n\r\n            this.positionPlayerDominoes();\r\n        }\r\n    },\r\n    positionPlayerDominoes: function () {\r\n        for (var i = 0, dealerCount = this.dealer.dominoes.length; i &lt; dealerCount; i++) {\r\n            var control = this.getControlAt(this.dealer, i);\r\n            this.applyScale(control, this.tilesScale);\r\n            var positionX = this.dealer.getPositionX(i, 0, this.tilesScale, this.calculatedTileMargin);\r\n            var positionY = this.dealer.getPositionY(i);\r\n            this.setControlPosition(control, positionX, positionY);\r\n        }\r\n\r\n        if (this.currentTweens) {\r\n            for (var i = 0, count = this.currentTweens.length; i &lt; count; i++) {\r\n                var deck = this.currentTweens[i].deck;\r\n                var index = this.currentTweens[i].index;\r\n                var margin = this.calculatedTileWidth * deck.dominoes.length \/ 2 + deck.dominoes.length * this.calculatedTileMargin \/ 2;\r\n                var control = this.getControlAt(deck, index);\r\n                this.applyScale(control, this.tilesScale);\r\n                var positionX = deck.getPositionX(index, margin, this.tilesScale, this.calculatedTileMargin);\r\n                var positionY = deck.getPositionY(index);\r\n\r\n                if (this.currentTweens[i].isMoveComplete) {\r\n                    this.setControlPosition(control, positionX, positionY);\r\n                } else {\r\n                    if (!this.currentTweens[i].isRunning)\r\n                        this.setControlPosition(control, this.dealer.left, this.dealer.top);\r\n                    this.updateTweenXY(this.currentTweens[i], control, {x: this.dealer.left, y: this.dealer.top}, { x: positionX, y: positionY });\r\n                    this.currentTweens[i].resume();\r\n                }\r\n            }\r\n        } \r\n        else {\r\n            var player1Count = this.player1Deck.dominoes.length;\r\n            var player1Margin = this.calculatedTileWidth * player1Count \/ 2 + player1Count * this.calculatedTileMargin \/ 2;\r\n            for (var i = 0; i &lt; player1Count; i++) {\r\n                var control = this.getControlAt(this.player1Deck, i);\r\n                this.applyScale(control, this.tilesScale);\r\n                var positionX = this.player1Deck.getPositionX(i, player1Margin, this.tilesScale, this.calculatedTileMargin);\r\n                var positionY = this.player1Deck.getPositionY(i);\r\n                this.setControlPosition(control, positionX, positionY);\r\n            }\r\n\r\n            var player2Count = this.player2Deck.dominoes.length;\r\n            var player2Margin = this.calculatedTileWidth * player2Count \/ 2 + player2Count * this.calculatedTileMargin \/ 2;\r\n            for (var i = 0; i &lt; this.player2Deck.dominoes.length; i++) {\r\n                var control = this.getControlAt(this.player2Deck, i);\r\n                this.applyScale(control, this.tilesScale);\r\n                var positionX = this.player2Deck.getPositionX(i, player2Margin, this.tilesScale, this.calculatedTileMargin);\r\n                var positionY = this.player2Deck.getPositionY(i);\r\n                this.setControlPosition(control, positionX, positionY);\r\n            }\r\n        }\r\n    },\r\n    actuateRowDecks: function () {\r\n        this.isMoving = true;\r\n        var tweens = [];\r\n        var tilesCount = 7;\r\n        var margin = tilesCount * this.calculatedTileWidth \/ 2 + tilesCount * this.calculatedTileMargin \/ 2;\r\n        for (var i = 0; i &lt; tilesCount; i++) {\r\n            this.dealer.draw(this.player1Deck, 1);\r\n            var tween1 = this.addTweenForLastControlMove(this.player1Deck, 30, 300, margin, this.tilesScale);\r\n            tween1.deck = this.player1Deck;\r\n            tween1.index = i;\r\n            tweens.push(tween1);\r\n\r\n            this.dealer.draw(this.player2Deck, 1);\r\n            var tween2 = this.addTweenForLastControlMove(this.player2Deck, 30, 300, margin, this.tilesScale);\r\n            tween2.deck = this.player2Deck;\r\n            tween2.index = i;\r\n            tweens.push(tween2);\r\n        }\r\n\r\n        var tweensCount = tweens.length;\r\n        if (tweensCount &gt; 1) {\r\n            var tween = tweens[0];\r\n            for (var i = 1; i &lt; tweensCount; i++) {\r\n                tween.chain(tweens[i]);\r\n                tween = tweens[i];\r\n            }\r\n        }\r\n\r\n        this.currentTweens = tweens;\r\n\r\n        tweens[tweens.length - 1].onComplete.addOnce(function () {\r\n            this.currentTweens = null;\r\n\t\t\t\/\/ TODO - Processing after dealing the tiles\r\n            this.reloadButton.visible = true;\r\n\r\n            this.isMoving = false;\r\n        }, this);\r\n        tweens[0].start();\r\n    },\r\n\tcalculateOverallScale: function (width, height) {\r\n\t    var isLandscape = this.isLandscapeOrientation(width, height);\r\n\t\tif(isLandscape){\r\n\t\t\t\/\/ In landscape mode height = 4x for play area + 1x for player + 1x for bot \r\n\t\t    var availableHeightPerDomino = (height \/ 6) * TheGame.Params.marginMultiplier; \/\/\r\n\t\t    var availableWidthPerDomino = (width * 0.5 \/ TheGame.Params.maxTiles) * TheGame.Params.marginMultiplier; \/\/ 50%\r\n\r\n\t\t\tvar baseAspectRatio = TheGame.Params.baseWidth \/ TheGame.Params.baseHeight;\r\n\t\t\tvar currentAspectRatio = width \/ height;\r\n\t\t\t\r\n\t\t\tif(currentAspectRatio &gt; baseAspectRatio){\r\n\t\t\t    this.overallScale = height \/ TheGame.Params.baseHeight;\r\n\t\t\t} else {\r\n\t\t\t    this.overallScale = width \/ TheGame.Params.baseWidth;\r\n\t\t\t}\r\n\t\t\tthis.tilesScale = this.getSpriteScale(TheGame.Params.tileSize.width, TheGame.Params.tileSize.height, availableWidthPerDomino, availableHeightPerDomino, 0, false);\r\n\t\t\tthis.calculatedTileWidth = (TheGame.Params.tileSize.width) * this.tilesScale;\r\n\t\t\tthis.calculatedTileHeight = (TheGame.Params.tileSize.height) * this.tilesScale;\r\n\t\t\tthis.calculatedTileMargin = (1 - TheGame.Params.marginMultiplier) * width \/ TheGame.Params.maxTiles;\r\n\t\t} else {\r\n\r\n\t\t    \/\/ In portrait mode height = 1x for score tile + 1x for player domino + 6x for play area + 1x for bot domino + 1x for bot score \r\n\r\n\t\t\tvar availableHeightPerDomino = (height \/ 10) * TheGame.Params.marginMultiplier; \/\/\r\n\t\t\tvar availableWidthPerDomino = (width \/ TheGame.Params.maxTiles) * TheGame.Params.marginMultiplier; \/\/ 100% of width\r\n\t\t\tvar baseAspectRatio = TheGame.Params.baseWidth \/ TheGame.Params.baseHeight; \/\/ For portrait width and height is switched\r\n\t\t\tvar currentAspectRatio = height \/ width;\r\n\t\t\t\r\n\t\t\tif(currentAspectRatio &gt; baseAspectRatio){\r\n\t\t\t\tthis.overallScale = width \/ TheGame.Params.baseWidth;\r\n\t\t\t} else {\r\n\t\t\t\tthis.overallScale = height \/ TheGame.Params.baseHeight;\r\n\t\t\t}\r\n\t\t\tthis.tilesScale = this.getSpriteScale(TheGame.Params.tileSize.width, TheGame.Params.tileSize.height, availableWidthPerDomino, availableHeightPerDomino, 0, true);\r\n\t\t\tthis.calculatedTileWidth = (TheGame.Params.tileSize.width) * this.tilesScale;\r\n\t\t\tthis.calculatedTileHeight = (TheGame.Params.tileSize.height) * this.tilesScale;\r\n\t\t\tthis.calculatedTileMargin = (1 - TheGame.Params.marginMultiplier) * width \/ TheGame.Params.maxTiles;\r\n\t\t}\r\n\t},\r\n\tisLandscapeOrientation: function (width, height) {\r\n\t    return height \/ width &lt; 1.0 ? true : false;\r\n\t},\r\n    applyScale: function (sprite, scale) {\r\n        sprite.scale.x = scale;\r\n        sprite.scale.y = scale;\r\n    },\r\n    scaleSprite: function (sprite, availableSpaceWidth, availableSpaceHeight, padding, scaleMultiplier, isFullScale) {\r\n        var scale = this.getSpriteScale(sprite._frame.width, sprite._frame.height, availableSpaceWidth, availableSpaceHeight, padding, isFullScale);\r\n        sprite.scale.x = scale * scaleMultiplier;\r\n        sprite.scale.y = scale * scaleMultiplier;\r\n    },\r\n    getSpriteScale: function (spriteWidth, spriteHeight, availableSpaceWidth, availableSpaceHeight, minPadding, isFullScale) {\r\n        var ratio = 1;\r\n        var currentDevicePixelRatio = window.devicePixelRatio;\r\n        \/\/ Sprite needs to fit in either width or height\r\n        var widthRatio = (spriteWidth * currentDevicePixelRatio + 2 * minPadding) \/ availableSpaceWidth;\r\n        var heightRatio = (spriteHeight * currentDevicePixelRatio + 2 * minPadding) \/ availableSpaceHeight;\r\n        if (widthRatio &gt; 1 || heightRatio &gt; 1) {\r\n            ratio = 1 \/ Math.max(widthRatio, heightRatio);\r\n        } else {\r\n            if (isFullScale)\r\n                ratio = 1 \/ Math.max(widthRatio, heightRatio);\r\n        }\r\n        return ratio * currentDevicePixelRatio;\r\n    },\r\n    setControlPosition: function (control, positionX, positionY) {\r\n        control.x = positionX;\r\n        control.y = positionY;\r\n    },\r\n    addTweenForMove: function (control, deck, index, delay, duration, margin, scale) {\r\n        var positionX = deck.getPositionX(index, margin, this.tilesScale, this.calculatedTileMargin);\r\n        var positionY = deck.getPositionY(index);\r\n        var period = 300;\r\n        if (duration)\r\n            period = duration;\r\n        var tween = this.game.add.tween(control);\r\n        tween.isMoveComplete = false;\r\n        tween.to({ x: positionX, y: positionY }, period, Phaser.Easing.Linear.None, false, delay);\r\n        tween.onStart.addOnce(function (sprite, tween) {\r\n            sprite.bringToTop(mygame.group);\r\n            if (tween.deck.display)\r\n                sprite.frame = sprite.domino.frame;\r\n            else\r\n                sprite.frame = TheGame.Params.blankFrame;\r\n\r\n        }, this);\r\n        tween.onComplete.addOnce(function (sprite, tween) {\r\n            tween.isMoveComplete = true;\r\n        }, this);\r\n        return tween;\r\n    },\r\n    addTweenForLastControlMove: function (deck, delay, duration, margin, scale) {\r\n        var index = deck.dominoes.length - 1;\r\n        var control = this.getControlAt(deck, index);\r\n        return this.addTweenForMove(control, deck, index, delay, duration, margin, scale);\r\n    },\r\n    getControlAt: function (deck, index) {\r\n        return this.dominoesMap[deck.dominoes[index].counter];\r\n    },\r\n    getControl: function (domino) {\r\n        return this.dominoesMap[domino.counter];\r\n    },\r\n\tresize: function (width, height) {\r\n\t\tthis.positionControls(width, height);\r\n\t},\r\n\treload: function () {\r\n\t    this.state.start(\"TheGame\");\r\n\t}\r\n};\r\n\r\nvar mygame;\r\nwindow.onload = function () {\r\n\tmygame = new Phaser.Game(TheGame.Params.baseWidth, TheGame.Params.baseHeight, Phaser.AUTO);\t\r\n\tmygame.state.add(\"Boot\", TheGame.Boot);\r\n\tmygame.state.add(\"Loading\", TheGame.Loading);\r\n\tmygame.state.add(\"TheGame\", TheGame.MyGame);\r\n\tmygame.state.start(\"Boot\");\r\n}\r\n<\/pre>\n<p>The code used to handle tweens on resize is\u00a0highlighted above. Rest of the resize code is similar to how it was done in the previous Number Spread game article.<\/p>\n<p>Resize the screen when checking\u00a0the code below or open the demo link\u00a0on your device by clicking <a href=\"https:\/\/www.netexl.com\/blog\/demo\/7\/index.html\" target=\"_blank\">here<\/a><\/p>\n\n<!-- iframe plugin v.5.2 wordpress.org\/plugins\/iframe\/ -->\n<iframe loading=\"lazy\" src=\"https:\/\/www.netexl.com\/blog\/demo\/7\/index.html\" width=\"100%\" height=\"400px\" scrolling=\"yes\" class=\"iframe-class\" frameborder=\"0\"><\/iframe>\n\n<p><strong>UPDATE &#8211;\u00a0<\/strong>I finished whole game which can be played <a href=\"http:\/\/www.netexl.com\/games\/blockdominoes\/\" target=\"_blank\">here<\/a>. Check out the game on your device.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>If you went\u00a0through previous articles\u00a0on making of a responsive game in Phaser, we handled scaling and placement of individual elements according to the available width and height for the game. I moved on to writing next responsive game in Phaser and came across another scenario which requires additional handling. In Number Spread game we did not use any tween to move elements between two points. In my next game I planned to create a domino game where effects like dealing domino tiles to the players were required to be handled. While aligning and scaling of the elements were done exactly how it was done in Number Spread game, additional scenario which I needed to handle was managing the tweens which were used to deal domino tiles to the players. Consider the scenario where I made a chained tweens set to deal domino tiles to the players. I resized my game\u00a0halfway[&#8230;]<\/p>\n","protected":false},"author":5,"featured_media":85,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[5,3,4],"tags":[],"class_list":["post-168","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-framework","category-html5","category-phaser"],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/www.netexl.com\/blog\/wp-json\/wp\/v2\/posts\/168","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.netexl.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.netexl.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.netexl.com\/blog\/wp-json\/wp\/v2\/users\/5"}],"replies":[{"embeddable":true,"href":"https:\/\/www.netexl.com\/blog\/wp-json\/wp\/v2\/comments?post=168"}],"version-history":[{"count":4,"href":"https:\/\/www.netexl.com\/blog\/wp-json\/wp\/v2\/posts\/168\/revisions"}],"predecessor-version":[{"id":610,"href":"https:\/\/www.netexl.com\/blog\/wp-json\/wp\/v2\/posts\/168\/revisions\/610"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.netexl.com\/blog\/wp-json\/wp\/v2\/media\/85"}],"wp:attachment":[{"href":"https:\/\/www.netexl.com\/blog\/wp-json\/wp\/v2\/media?parent=168"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.netexl.com\/blog\/wp-json\/wp\/v2\/categories?post=168"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.netexl.com\/blog\/wp-json\/wp\/v2\/tags?post=168"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}