Are you relocating the tiles every frame or something? Your specs seem perfectly reasonable to me.
Tilemap performance is lacking? [SOLVED AS HELL]
Well, they are only made once and that’s it… They are made in the gameworld…
Gameworld:
package game_handling
{
import assets.hp_globe.HpGlobe;
import assets.hp_globe.HpGlobe_HP;
import assets.stamina_bar.StaminaBarGraphic;
import assets.stamina_bar.StaminaGraphic;
import assets.xp_bar.XpBarGraphic;
import assets.xp_bar.XpGraphic;
import blocks.*;
import blocks.chests.Chest_Wooden;
import enemies.Goblin_Thief;
import events.Change_Room;
import flash.display.Bitmap;
import flash.geom.Point;
import hero.*;
import levels.level1.*;
import lit.Light;
import lit.Lighting;
import net.flashpunk.Entity;
import net.flashpunk.FP;
import net.flashpunk.graphics.Graphiclist;
import net.flashpunk.graphics.Image;
import net.flashpunk.graphics.Stamp;
import net.flashpunk.graphics.Tilemap;
import net.flashpunk.masks.Grid;
import net.flashpunk.World;
import talents.*;
public class GameWorld extends World
{
[Embed(source="../assets/circle_gradient2.png")]
public static const SPR_LIGHT_CIRCLE_GRADIENT:Class;
private var stats:HeroStats = new HeroStats();
private var xpbar:XpBarGraphic = new XpBarGraphic(470, 1040);
private var xpbar_xp:XpGraphic = new XpGraphic(470, 1040);
private var hpglobe:HpGlobe = new HpGlobe(30, 30);
private var hpglobe_hp:HpGlobe_HP = new HpGlobe_HP(30, 30);
private var staminabar:StaminaBarGraphic = new StaminaBarGraphic(250, 30);
private var staminabar_stamina:StaminaGraphic = new StaminaGraphic(250, 30);
private var gui:HUD = new HUD();
private var sounds:Sounds = new Sounds();
public var lighting:Lighting;
public var mouseLight:Light;
private var _map_Ground_Accessories_2:Tilemap;
private var _map_Ground_Accessories:Tilemap;
private var _map_Ground:Tilemap;
private var _map_BG_Accessories_2:Tilemap;
private var _map_BG_Accessories:Tilemap;
private var _map_BG:Tilemap;
public var collisionData:Grid;
public static var currentLevelIsScrollable:Boolean = false;
public static var currentLevel:int = 0;
private var _rawMapData:Class;
private var _scrollable:Boolean;
private var _tileset:Class;
public function GameWorld(map:Class, tileset:Class, isScrollable:Boolean)
{
_rawMapData = map
_tileset = tileset
_scrollable = isScrollable
}
override public function begin():void
{
super.begin();
//Hero stats
add(stats);
//Hp and xp graphics
add(hpglobe);
add(hpglobe_hp);
add(xpbar);
add(xpbar_xp);
add(staminabar);
add(staminabar_stamina);
//HUD
add(gui);
add(sounds);
loadLevel(_rawMapData, _tileset, _scrollable);
}
override public function update():void
{
super.update();
}
public function setNewMap(map:Class, tileset:Class, isScrollable:Boolean):void
{
_rawMapData = map;
loadLevel(_rawMapData, _tileset, _scrollable);
}
public function loadLevel(levelNumber:Class, tileset:Class, scrollable:Boolean):void
{
currentLevelIsScrollable = scrollable;
var tileSet:Class = tileset
var mapXML:XML = FP.getXML(levelNumber);
var mapWidth:uint = uint(mapXML.@width);
var mapHeight:uint = uint(mapXML.@height);
var tileX:uint = 0;
var tileY:uint = 0;
collisionData = new Grid(mapWidth * 128, mapHeight * 128, 128, 128);
_map_Ground_Accessories_2 = new Tilemap(tileSet, mapWidth * 128, mapHeight * 128, 128, 128);
_map_Ground_Accessories = new Tilemap(tileSet, mapWidth * 128, mapHeight * 128, 128, 128);
_map_Ground = new Tilemap(tileSet, mapWidth * 128, mapHeight * 128, 128, 128);
_map_BG_Accessories_2 = new Tilemap(tileSet, mapWidth * 128, mapHeight * 128, 128, 128);
_map_BG_Accessories = new Tilemap(tileSet, mapWidth * 128, mapHeight * 128, 128, 128);
_map_BG = new Tilemap(tileSet, mapWidth * 128, mapHeight * 128, 128, 128);
var amountOfTiles:int = 0;
for each (var layer:XML in mapXML.layer)
{
var XMLlayers:String = layer.attribute("name");
switch (XMLlayers)
{
case "Ground_Accessories_2":
tileX = 0;
tileY = 0;
for each (var tile:XML in layer.data.tile)
{
if (tileX >= mapWidth)
{
tileX = 0;
tileY++;
}
if (tile.@gid != 0)
{
_map_Ground_Accessories_2.setTile(tileX, tileY, uint(tile.@gid - 1));
}
tileX++;
}
break;
case "Ground_Accessories":
tileX = 0;
tileY = 0;
for each ( tile in layer.data.tile)
{
if (tileX >= mapWidth)
{
tileX = 0;
tileY++;
}
if (tile.@gid != 0)
{
_map_Ground_Accessories.setTile(tileX, tileY, uint(tile.@gid - 1));
}
tileX++;
}
break;
case "Ground":
tileX = 0;
tileY = 0;
for each (tile in layer.data.tile)
{
if (tileX >= mapWidth)
{
tileX = 0;
tileY++;
}
if (tile.@gid != 0)
{
collisionData.setTile(tileX, tileY, true);
}
if (tile.@gid != 0)
{
_map_Ground.setTile(tileX, tileY, uint(tile.@gid - 1));
}
tileX++;
}
break;
case "BG_Accessories_2":
tileX = 0;
tileY = 0;
for each (tile in layer.data.tile)
{
if (tileX >= mapWidth)
{
tileX = 0;
tileY++;
}
if (tile.@gid != 0)
{
_map_BG_Accessories_2.setTile(tileX, tileY, uint(tile.@gid - 1));
}
tileX++;
}
break;
case "BG_Accessories":
tileX = 0;
tileY = 0;
for each (tile in layer.data.tile)
{
if (tileX >= mapWidth)
{
tileX = 0;
tileY++;
}
if (tile.@gid != 0)
{
_map_BG_Accessories.setTile(tileX, tileY, uint(tile.@gid - 1));
}
tileX++;
}
break;
case "BG":
tileX = 0;
tileY = 0;
for each (tile in layer.data.tile)
{
if (tileX >= mapWidth)
{
tileX = 0;
tileY++;
}
if (tile.@gid != 0)
{
_map_BG.setTile(tileX, tileY, uint(tile.@gid - 1));
}
tileX++;
}
break;
}
}
trace(amountOfTiles)
for each (var objectgroup:XML in mapXML.objectgroup)
{
var groupname:String = objectgroup.attribute("name");
switch (groupname)
{
case "Spawn":
for each (var object:XML in objectgroup.object)
{
var spawnname:String = object.attribute("name");
switch (spawnname)
{
case "Hero":
FP.world.add(new Hero(new Point(int(object.@x * 8), int(object.@y * 8))));
break;
case "Goblin_Thief":
FP.world.add(new Goblin_Thief(new Point(int(object.@x * 8), int(object.@y * 8))));
break;
}
}
case "Chests":
for each (object in objectgroup.object)
{
var chestname:String = object.attribute("name");
switch (chestname)
{
case "Wooden":
FP.world.add(new Chest_Wooden(new Point(int(object.@x * 8), int(object.@y * 8))));
break;
}
}
case "Events":
for each (object in objectgroup.object)
{
var eventname:String = object.attribute("name");
switch (eventname)
{
case "Change_Room":
FP.world.add(new Change_Room(new Point(int(object.@x * 8), int(object.@y * 8))));
break;
}
}
}
}
//_map_BG.scrollX = 0.2;
//addGraphic(_map_Ground)
addGraphic(_map_BG, 1);
addGraphic(_map_BG_Accessories);
addGraphic(_map_BG_Accessories_2);
addGraphic(_map_Ground_Accessories, -2)
addGraphic(_map_Ground_Accessories_2, -3)
updateCollision();
}
public function updateCollision():void
{
var collision_:Collision = FP.world.getInstance("collision");
if (collision_ == null)
FP.world.add(new Collision(0, 0, _map_Ground, collisionData))
else
{
FP.world.remove(collision_)
trace("updating collision")
}
}
//End
}
}
The XML:
<map version="1.0" orientation="orthogonal" width="15" height="9" tilewidth="16" tileheight="16">
<tileset firstgid="1" name="Dungeon_1" tilewidth="16" tileheight="16">
<image source="../output/Dungeon_1.png" trans="ffffff" width="96" height="96"/>
</tileset>
<layer name="BG" width="15" height="9">
<data>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="10"/>
<tile gid="10"/>
<tile gid="10"/>
<tile gid="10"/>
<tile gid="10"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="10"/>
<tile gid="11"/>
<tile gid="10"/>
<tile gid="10"/>
<tile gid="10"/>
<tile gid="10"/>
<tile gid="10"/>
<tile gid="10"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="10"/>
<tile gid="10"/>
<tile gid="10"/>
<tile gid="10"/>
<tile gid="10"/>
<tile gid="10"/>
<tile gid="10"/>
<tile gid="10"/>
<tile gid="10"/>
<tile gid="10"/>
<tile gid="10"/>
<tile gid="10"/>
<tile gid="11"/>
<tile gid="10"/>
<tile gid="10"/>
<tile gid="10"/>
<tile gid="10"/>
<tile gid="10"/>
<tile gid="10"/>
<tile gid="10"/>
<tile gid="10"/>
<tile gid="10"/>
<tile gid="10"/>
<tile gid="10"/>
<tile gid="10"/>
<tile gid="10"/>
<tile gid="11"/>
<tile gid="10"/>
<tile gid="10"/>
<tile gid="10"/>
<tile gid="10"/>
<tile gid="10"/>
<tile gid="10"/>
<tile gid="10"/>
<tile gid="10"/>
<tile gid="10"/>
<tile gid="10"/>
<tile gid="10"/>
<tile gid="10"/>
<tile gid="10"/>
<tile gid="10"/>
<tile gid="10"/>
<tile gid="10"/>
<tile gid="10"/>
<tile gid="10"/>
<tile gid="10"/>
<tile gid="10"/>
<tile gid="10"/>
<tile gid="10"/>
<tile gid="10"/>
<tile gid="11"/>
<tile gid="10"/>
<tile gid="10"/>
<tile gid="10"/>
<tile gid="11"/>
<tile gid="10"/>
<tile gid="10"/>
<tile gid="10"/>
<tile gid="10"/>
<tile gid="10"/>
<tile gid="10"/>
<tile gid="10"/>
<tile gid="11"/>
<tile gid="10"/>
<tile gid="10"/>
<tile gid="10"/>
<tile gid="10"/>
<tile gid="10"/>
<tile gid="10"/>
<tile gid="10"/>
<tile gid="10"/>
<tile gid="10"/>
<tile gid="10"/>
<tile gid="10"/>
<tile gid="10"/>
<tile gid="10"/>
<tile gid="10"/>
<tile gid="10"/>
<tile gid="10"/>
<tile gid="10"/>
<tile gid="10"/>
<tile gid="10"/>
<tile gid="10"/>
<tile gid="10"/>
<tile gid="10"/>
<tile gid="10"/>
<tile gid="10"/>
<tile gid="10"/>
<tile gid="10"/>
<tile gid="10"/>
<tile gid="10"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
</data>
</layer>
<layer name="BG_Accessories" width="15" height="9">
<data>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="23"/>
<tile gid="24"/>
<tile gid="25"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="26"/>
<tile gid="27"/>
<tile gid="28"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="23"/>
<tile gid="24"/>
<tile gid="25"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="29"/>
<tile gid="30"/>
<tile gid="31"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="26"/>
<tile gid="27"/>
<tile gid="28"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="29"/>
<tile gid="30"/>
<tile gid="31"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
</data>
</layer>
<layer name="Ground" width="15" height="9">
<data>
<tile gid="5"/>
<tile gid="5"/>
<tile gid="5"/>
<tile gid="5"/>
<tile gid="7"/>
<tile gid="5"/>
<tile gid="5"/>
<tile gid="5"/>
<tile gid="7"/>
<tile gid="7"/>
<tile gid="7"/>
<tile gid="7"/>
<tile gid="7"/>
<tile gid="7"/>
<tile gid="7"/>
<tile gid="5"/>
<tile gid="7"/>
<tile gid="7"/>
<tile gid="7"/>
<tile gid="5"/>
<tile gid="5"/>
<tile gid="13"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="3"/>
<tile gid="6"/>
<tile gid="5"/>
<tile gid="5"/>
<tile gid="7"/>
<tile gid="12"/>
<tile gid="13"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="1"/>
<tile gid="5"/>
<tile gid="5"/>
<tile gid="5"/>
<tile gid="13"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="3"/>
<tile gid="12"/>
<tile gid="12"/>
<tile gid="13"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="1"/>
<tile gid="3"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="3"/>
<tile gid="1"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="6"/>
<tile gid="16"/>
<tile gid="17"/>
<tile gid="17"/>
<tile gid="18"/>
<tile gid="17"/>
<tile gid="3"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="4"/>
<tile gid="5"/>
<tile gid="5"/>
<tile gid="5"/>
<tile gid="5"/>
<tile gid="5"/>
<tile gid="5"/>
<tile gid="5"/>
<tile gid="14"/>
<tile gid="15"/>
<tile gid="5"/>
<tile gid="5"/>
<tile gid="5"/>
<tile gid="5"/>
<tile gid="5"/>
<tile gid="5"/>
<tile gid="5"/>
<tile gid="5"/>
<tile gid="5"/>
<tile gid="5"/>
<tile gid="5"/>
<tile gid="5"/>
<tile gid="5"/>
</data>
</layer>
<layer name="Ground_Accessories" width="15" height="9">
<data>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="8"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="21"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="22"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="9"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="20"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="2"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="8"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
</data>
</layer>
<objectgroup name="Chests" width="15" height="9">
<object name="Wooden" x="160" y="80" width="16" height="16"/>
</objectgroup>
<objectgroup name="Spawn" width="15" height="9">
<object name="Hero" x="32" y="96" width="16" height="16"/>
</objectgroup>
<objectgroup name="Events" width="15" height="9">
<object name="Change_Room" x="192" y="64" width="16" height="16"/>
</objectgroup>
</map>
The tileset used for level 1 is 12kb, 768 x 768… I’m sorry for including all of the code, but I figured that every line can be crucial to performance?
I know I have a history of asking unnecessary questions and kind of expected code to be written to me (I read your PM jacob, but I haven’t had time to respond properly. It was a really nice PM and I don’t want to respond with a one-liner… I’m very busy IRL also, I will respond ASAP).
But in this issue, I seriously think something is wrong here. I agree, there shouldn’t be any problems. I mean, the game WORKS, but now the performance sucks.
After having a little skim read, my suspicion is that it could be related to this bit:
addGraphic(_map_BG, 1);
addGraphic(_map_BG_Accessories);
addGraphic(_map_BG_Accessories_2);
addGraphic(_map_Ground_Accessories, -2)
addGraphic(_map_Ground_Accessories_2, -3)
Are you absolutely sure that’s not being called multiple times? If those get added multiple times without removing the old ones that’d kill performance quickly.
I can’t really see any obvious problems other than that!
Yes, they only get added once But if I remove those lines, then the FPS is back at 60…
I tried removing each one separately, and they all contribute to the FPS drop
any ideas? it’s really annoying to playtest the game when it’s so slow
@John_Andersson1 Help me out, here. Add the following block of code, run the game in debug and share the output with us.
Alrighty!
----- Tilemap Layer Dimensions -----
_map_BG: width => 1920 height => 1152
_map_BG_Accessories: width => 1920 height => 1152
_map_BG_Accessories_2: width => 1920 height => 1152
_map_Ground_Accessories: width => 1920 height => 1152
_map_Ground_Accessories_2: width => 1920 height => 1152
------------------------------------
Yeahhhhhhhh
1920 is kind of huge for a flash game, no? And you’ve got five of them.
yeah but we’re talking about 2D composite images with not that many colors… what should I do if I want to make a 1920x1080 game? Make it 192x108 and scale it up? Won’t it be the same thing? I’ve heard that scaling the games are bad for performance…
Are we really stuck with making low-res games?..
…
The number of colors doesn’t matter. A color is a color. You’re stuck making software-blitted Flash games. If you had access to the GPU, your game would blaze420, no problem; however, you don’t.
If you scale the game up, you will get better performance. Why? First, when you scale the game up, your GPU is actually doing the scaling, not the FlashPunk engine. The slowdown you’re seeing is due to FlashPunk doing all the great stuff it does every tick — drawing shit, checking to see if some shit ran into another shit, figuring out if someone pressed some shit, shit cetera.
Let’s crunch some numbers. Let’s say each pixel drawn onto the screen takes the same amount of time. We’ll call it t
. So, to draw one little pixel, it will take FlashPunk t
seconds.
Now, let’s calculate the amount of time it would take FlashPunk to draw one of your tilemaps at 192x108.
192 * 108 * t seconds = 20736t seconds
Let’s now see how long it would take to draw a tilemap at 1080p.
1920 * 1080 * t seconds = 2073600t seconds
That means, it would take FlashPunk 2,052,864 times longer to draw your game natively at 1080p than it would take to draw at 108p (again, the Flash player will handle the scaling x10 for you).
tl;dr: Drawing a game at 1080p is literally two-million times slower than making it 108p and scaling it up. Food for thought.
TileMap and Performance (Other Methods?)
The number of colors doesn’t matter, the thing that’s killing your performance is fillrate.
When the engine goes to render, it has to send a minimum of screenWidth * screenHeight
pixels to the display. If your window is 1920x1080, that’s a little over 2 million pixels to stick on the screen.
That’s the best case scenario, and unless your world is completely empty, it’s never going to happen.
Now, you’ve got five of these images. With nothing else in the mix, that’s 10 million pixels. Now consider that for every pixel displayed at (x, y), the engine is also taking the pixel that already exists at (x, y), and multiplying it with the new value.
The worst part? By and large, this is the fastest way to do things. Bitmap blitting is faster than using the DisplayList by a long shot; on the desktop, anyway. Having spent a lot of time digging around in Flashpunk’s guts, I can assure you that it’s extremely optimized, but even so, you’re asking a lot of it.
TileMap and Performance (Other Methods?)
Man. I just got teached. Now I understand it completely. I think this information has made me a better programmer (when it comes to optimizing in every aspect). Thanks to you both I know ultima is soon releasing stage3dpunk, but why doesn’t flashpunk already have GPU accessibility?
That answer is really a history question.
When Flash was originally conceived, it was designed to allow rich, interactive media to be available in browser via the use of a web plugin. The idea was simple: Instead of each browser deciding if they will support this media, a user can instead install a plugin once (__S__hockWave __F__lash, or .swf) and view the media.
The combination of vector graphics and cross-platform functionality made it a hit, since it was quick to download and worked everywhere. Keep in mind that when it released, a 56.6kbps dial up modem was bleeding edge tech and the plugin launched on Netscape 2.0. (For reference, one of Netscape’s competitors at the time was Mosaic, which would later be bought by Microsoft and become Internet Explorer.) There was limited raster support and no GPU support because, at the time, there were very few graphics cards, OpenGL was in its infancy, and Direct3D was a newborn.
As time changed, so did the technology, but it wasn’t until 2011 (with the release of Flash 11) that developers could access the GPU from Flash, and even then it was very convoluted and closed off. Although the idea of web browser-based games had been around for some time, none of them were really trying to be anything more than corporate time-wasters, primarily due to the fact that dedicated graphics cards still weren’t mainstream. Just think, $600 Dells were sold by the millions to businesses everywhere, and the people who had the money to buy a specialized computer to play games didn’t want to sit around and play point-and-click shovelware in their browsers.
When Chevy started writing FlashPunk (before Flash 11 was released), he wanted something that felt very similar to Game Maker, could be deployed on the web and could be played by anyone with a computer and the Flash plugin. Even after the release of Stage3D, no one really requested hardware accelerated graphics until Flash deployment to mobile became a viable deployment option. The people who used FlashPunk did so because it worked on any computer they used. The people who wanted speed would use XNA or C++, and if it had to work on the web, they might pay to use Unity.
Everything up until this point has (with some exceptions) been single-developer indie “experiences” or “shoot the monkey” advergames. It’s only now, with the release of Starling, Unity going “free to use,” and build-once-deploy-everywhere mobile games that people want to make beautiful, high-resolution, hardware-accelerated games with Flash.
tl;dr: lazy devs
lmao
Very informative and enjoyable read. Thanks a lot for that
Note that although Stage3D may help here, it will not instantly solve all of your performance worries. It has performance bottlenecks of its own (particularly uploading textures) so be aware of that when I do finally get Stage3DPunk up here.
Well, in terms of Stage3DPunk a LOT of stuff is going on behind the scenes to minimize the impact of the bottlenecks so it’s not likely to get much more optimized on that level, however Adobe have been known to improve Stage3D performance with some runtime updates (or offer new techniques to improve performance, such as RectangleTextures in Air 3.8). So I guess it’s not impossible that those bottlenecks will be reduced, but generally they are just implicit in how Stage3D/Hardware acceleration works; uploading textures and changing GPU state is just limited by the way the GPU pipeline is designed. This is no different to programming natively with OpenGL and C++; you have the same performance bottlenecks (though to a lesser degree in most cases).
Basically, those bottlenecks tend to be the same bottlenecks you’d face making games on any platform, with any engine. The real ‘fix’ for them is simply more powerful hardware.
But it means that in some cases software rendering performance will actually be better than using Stage3D. A good example of this is text that constantly uploads to the GPU; in regular blitted FlashPunk this doesn’t really have a penalty since FlashPunk blits everything to a buffer anyway so it’s just doing its normal thing. But with Stage3D it will crush your framerate fairly quickly because the GPU prefers to draw stuff uninterrupted. If you start uploading textures every frame or having a lot of state/texture changes, it stalls the GPU and things can get slow. But if you treat it right, you’ll be able to destroy software blitting performance in terms of raw muscle (it’s easy to get 10000+ sprites going in Stage3D on modern hardware if you have thought it through).
Stage3DPunk itself tries its best to abstract these more difficult concepts away from you, the developer, so you don’t have to worry about it but it can’t do that in every situation.