ForgeableSum Posted April 30, 2015 Share Posted April 30, 2015 Anyone have examples of how to do a mini map in phaser? One way I thought of doing it was to create a separate canvas element and copy the scaled down contents of the game world into it. Problem with this approach is there's no way (that I know of) to copy an entire canvas including the non-visible parts (non-visible to the window). So if the game is larger than the window size, you run into trouble. Thoughts? Appreciate any advice. Link to comment Share on other sites More sharing options...
MichaelD Posted April 30, 2015 Share Posted April 30, 2015 I would think that you could scale down the image/sprite to achieve the reduced view of the map, then you can treat it as a separate object and place items inside. Or if you create a group and place items exactly where you want them and then scale the whole group the items will remain in their exact locations. Link to comment Share on other sites More sharing options...
CtlAltDel Posted April 30, 2015 Share Posted April 30, 2015 Phaser is not very good at seperation of game objects and display objects. Most of the time they are the same. What you need to do is separate your game objects from display objects and then you can just have 2 display objects for the same game object. Both display objects can be sprites with a different texture and thus you can make a minimap of sorts. Link to comment Share on other sites More sharing options...
sanojian Posted April 30, 2015 Share Posted April 30, 2015 Is it a tile-based game? I am doing it by assigning a color for each tile and drawing the minimap onto a BitmapData object. In create():// the static mapvar miniMapBmd = this.game.add.bitmapData(g_game.tileMap.width*g_game.miniMapSize, g_game.tileMap.height*g_game.miniMapSize);// g_game.miniMapSize is the pixel size in the minimap// iterate my map layersfor (l=0; l<g_game.tileMap.layers.length; l++) { for (y = 0; y < g_game.tileMap.height; y++) { for (x = 0; x < g_game.tileMap.width; x++) { var tile = g_game.tileMap.getTile(x, y, l); if (tile && g_game.tileMap.layers[l].name == 'Ground') { // fill a pixel in the minimap miniMapBmd.ctx.fillStyle = '#bc8d6b'; miniMapBmd.ctx.fillRect(x * g_game.miniMapSize, y * g_game.miniMapSize, g_game.miniMapSize, g_game.miniMapSize); } else if ... other types of tiles } }}g_game.miniMap = this.game.add.sprite(x, y, miniMapBmd);// dynamic bmd where I draw mobile stuff like friends and enemies g_game.miniMapOverlay = this.game.add.bitmapData(g_game.tileMap.width*g_game.miniMapSize, g_game.tileMap.height*g_game.miniMapSize);this.game.add.sprite(g_game.miniMap.x, g_game.miniMap.y, g_game.miniMapOverlay);And then I draw dynamic stuff on the minimap in update()g_game.miniMapOverlay.context.clearRect(0, 0, g_game.miniMapOverlay.width, g_game.miniMapOverlay.height);g_game.soldiers.forEach(function(soldier) { g_game.miniMapOverlay.rect(Math.floor(soldier.x / TILE_SIZE) * g_game.miniMapSize, Math.floor(soldier.y / TILE_SIZE) * g_game.miniMapSize, g_game.miniMapSize, g_game.miniMapSize, color);});g_game.miniMapOverlay.dirty = true; Working pretty well so far for Super Combat Squadron: ForgeableSum, stauzs, MichaelD and 2 others 5 Link to comment Share on other sites More sharing options...
ForgeableSum Posted April 30, 2015 Author Share Posted April 30, 2015 Sanjin, I actually had this idea. Problem is my tiles can't really be represented by a single hex. They have complicated color schemes. See screenshot: Aside from that, they are not tiles. There is a grid system for placing static game objects (e.g. trees). However, there are also game objects which move off the grid (namely, units). Walkable terrain (e.g. roads, grass, leaves) does not conform to any grid system. Because of this, I'm thinking copying the entire canvas, scaled down, is my best (and perhaps only) option. If anyone has examples/implementations of this for a game world which doesn't fit inside the window, I'd love to see them. Link to comment Share on other sites More sharing options...
theoutlander Posted November 16, 2015 Share Posted November 16, 2015 How was this accomplished finally in Feudal Wars? Link to comment Share on other sites More sharing options...
ForgeableSum Posted November 21, 2015 Author Share Posted November 21, 2015 How was this accomplished finally in Feudal Wars?I accomplished it with a render texture which represents the game world. I use a graphic to update units and game objects and the terrain layer is rendered every 300 milli or so. Normally you wouldn't have to update the terrain layer, because most maps are static. But my map changes in the map editor so I constantly re-render it. Works like a charm. function createMiniMap() { miniMapContainer = game.add.group(); resolution = 2 / gameSize; if (game.world.width > 8000) { var renderWH = 8000; } else { var renderWH = game.world.width; } renderTexture = game.add.renderTexture(renderWH, renderWH); renderTexture.resolution = resolution; var cropRect = new Phaser.Rectangle(0, 0, 200, 200); renderTexture.crop = cropRect; var miniMapY = game.camera.view.height - (game.world.height * resolution); var miniMapUI = game.add.image(0, 0, 'mini_map'); renderTexture.trueWidth = renderTexture.resolution * game.world.width; renderTexture.trueHeight = renderTexture.resolution * game.world.height; var cropRect = new Phaser.Rectangle(0, 0, renderTexture.trueWidth, renderTexture.trueHeight); renderTexture.crop = cropRect; var miniWidth = .075 * renderTexture.trueWidth; var miniHeight = miniMapY - (.06 * renderTexture.trueHeight); miniMap = game.add.sprite(miniWidth, miniHeight, renderTexture); var padding = .241 * renderTexture.trueHeight; miniMapUI.width = (renderTexture.trueWidth + padding); miniMapUI.height = (renderTexture.trueHeight + padding); miniMapUI.y = game.camera.view.height - miniMapUI.height; miniMapUI.fixedToCamera = true; miniMap.fixedToCamera = true; viewRect = game.add.graphics(0, 0); viewRect.lineStyle(1, 0xFFFFFF); viewRect.drawRect(miniMap.x, miniMap.y, game.camera.view.width * resolution, game.camera.view.height * resolution); unitDots = game.add.graphics(miniMap.x, miniMap.y); unitDots.fixedToCamera = true; var bg = game.add.graphics(0, 0); bg.beginFill(0x000000, 1); bg.drawRect(0, miniMapUI.y + (miniMapUI.height * .1), miniMapUI.width * .95, miniMapUI.height * .9); bg.fixedToCamera = true; var children = [bg, miniMap, unitDots, viewRect, miniMapUI]; miniMapContainer.addMultiple(children);}function updateUnitDots() { unitDots.clear(); gameObjects.forEach(function(object) { var unitMiniX = object.x * renderTexture.resolution; var unitMiniY = object.y * renderTexture.resolution; var objectType = object.objectType; if (objectType == 'unit' || objectType == 'building' || objectType == 'wall') { if (playerColors[object.player - 2] == undefined) { // player 1 var color = '0x1331a1'; } else { var color = playerColors[object.player - 2].color; } unitDots.beginFill(color); if (objectType == 'building') { unitDots.drawRect(unitMiniX, unitMiniY, 5, 5); } else { unitDots.drawEllipse(unitMiniX, unitMiniY, 1.5, 1.5); } } else if (objectType == 'plant') { // tree unitDots.beginFill(0x2A4B17); unitDots.drawEllipse(unitMiniX, unitMiniY, 2, 2); } else { var color = '0x666666'; // gray unitDots.beginFill(color); unitDots.drawRect(unitMiniX, unitMiniY, 5, 5); } });} You can catch a glimpse of the mini map working in the game trailer. drhayes, samme and amuseum 3 Link to comment Share on other sites More sharing options...
billmo Posted December 6, 2016 Share Posted December 6, 2016 On 21/11/2015 at 3:49 AM, feudalwars said: I accomplished it with a render texture which represents the game world. I use a graphic to update units and game objects and the terrain layer is rendered every 300 milli or so. Normally you wouldn't have to update the terrain layer, because most maps are static. But my map changes in the map editor so I constantly re-render it. Works like a charm. function createMiniMap() { miniMapContainer = game.add.group(); resolution = 2 / gameSize; if (game.world.width > 8000) { var renderWH = 8000; } else { var renderWH = game.world.width; } renderTexture = game.add.renderTexture(renderWH, renderWH); renderTexture.resolution = resolution; var cropRect = new Phaser.Rectangle(0, 0, 200, 200); renderTexture.crop = cropRect; var miniMapY = game.camera.view.height - (game.world.height * resolution); var miniMapUI = game.add.image(0, 0, 'mini_map'); renderTexture.trueWidth = renderTexture.resolution * game.world.width; renderTexture.trueHeight = renderTexture.resolution * game.world.height; var cropRect = new Phaser.Rectangle(0, 0, renderTexture.trueWidth, renderTexture.trueHeight); renderTexture.crop = cropRect; var miniWidth = .075 * renderTexture.trueWidth; var miniHeight = miniMapY - (.06 * renderTexture.trueHeight); miniMap = game.add.sprite(miniWidth, miniHeight, renderTexture); var padding = .241 * renderTexture.trueHeight; miniMapUI.width = (renderTexture.trueWidth + padding); miniMapUI.height = (renderTexture.trueHeight + padding); miniMapUI.y = game.camera.view.height - miniMapUI.height; miniMapUI.fixedToCamera = true; miniMap.fixedToCamera = true; viewRect = game.add.graphics(0, 0); viewRect.lineStyle(1, 0xFFFFFF); viewRect.drawRect(miniMap.x, miniMap.y, game.camera.view.width * resolution, game.camera.view.height * resolution); unitDots = game.add.graphics(miniMap.x, miniMap.y); unitDots.fixedToCamera = true; var bg = game.add.graphics(0, 0); bg.beginFill(0x000000, 1); bg.drawRect(0, miniMapUI.y + (miniMapUI.height * .1), miniMapUI.width * .95, miniMapUI.height * .9); bg.fixedToCamera = true; var children = [bg, miniMap, unitDots, viewRect, miniMapUI]; miniMapContainer.addMultiple(children);}function updateUnitDots() { unitDots.clear(); gameObjects.forEach(function(object) { var unitMiniX = object.x * renderTexture.resolution; var unitMiniY = object.y * renderTexture.resolution; var objectType = object.objectType; if (objectType == 'unit' || objectType == 'building' || objectType == 'wall') { if (playerColors[object.player - 2] == undefined) { // player 1 var color = '0x1331a1'; } else { var color = playerColors[object.player - 2].color; } unitDots.beginFill(color); if (objectType == 'building') { unitDots.drawRect(unitMiniX, unitMiniY, 5, 5); } else { unitDots.drawEllipse(unitMiniX, unitMiniY, 1.5, 1.5); } } else if (objectType == 'plant') { // tree unitDots.beginFill(0x2A4B17); unitDots.drawEllipse(unitMiniX, unitMiniY, 2, 2); } else { var color = '0x666666'; // gray unitDots.beginFill(color); unitDots.drawRect(unitMiniX, unitMiniY, 5, 5); } });} You can catch a glimpse of the mini map working in the game trailer. I know this is old, but what does gameSize refer to when setting the value to the resolution variable? Link to comment Share on other sites More sharing options...
ForgeableSum Posted December 6, 2016 Author Share Posted December 6, 2016 4 hours ago, billmo said: I know this is old, but what does gameSize refer to when setting the value to the resolution variable? It's the game world width/height divided by 100 (game.world.width / 100); I should note that my techniques for rendering a mini map have since evolved from the time of my post. I no longer render the entire terrain layer to the map every x number of milliseconds. I do that for units (anything that moves), but for the terrain, I have a simple render texture the exact size of the mini map and render the tiles (transformed to fit the scaled position and resolution/scale of the mini map) whenever a tile changes. However, for the purposes of most simple games, my old technique should do fine. Sky Alpha and Alexalten 2 Link to comment Share on other sites More sharing options...
billmo Posted December 12, 2016 Share Posted December 12, 2016 Thanks Feudalwars! Link to comment Share on other sites More sharing options...
Recommended Posts