Facebook Twitter RSS
formats

Game lags on Chrome – solved?

Published on March 12, 2013, by in Tutorials.

EDIT: Well, it seems that the problem goes deeper than just that – while this article resolves part of the issue, there are other things that may cause framedrops on Chrome/pepperflash that I haven’t yet identified.

Some of my games have this sad problem of not working very well on Google Chrome browser because of mysterious framerates drops. Yesterday I’ve found what seems to be a reason of this issue… so if you’ve ever bothered with your Flash not working well under Chrome browser, keep on reading!

 

What exact issue does this post tries fix?

My problem with Flash performance under Chrome was – as it turned out – connected with using BitmapData objects. So, since there is probably more than one problem with Flash on Chrome, if you’re not using BitmapData anywhere in your code, this might be not for you :(

 

BitmapData is fast as hell, but its birth is pain for Chrome

There, the heading nails it. It seems that the Chrome performance problem (like with 400 Years) is caused by creating BitmapData objects.

Here is some meat, I know you’ve been waiting for it:

 

The code

(I’m also attaching source files of this project, so you can play with it yourself.)

First, let’s set up a simple AS3 project with a single Bitmap object on stage. This bitmap will be displaying a BitmapData object. We will need one more BitmapData for the showcase.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
private var bitmapData:BitmapData;  // main BitmapData
private var bitmap:Bitmap;    // main Bitmap
private var squareBitmapData:BitmapData // BitmapData for color squares
 
private function init():void 
{
  bitmapData = new BitmapData(stage.stageWidth, stage.stageHeight, false,
    0x000000);
  bitmap = new Bitmap(bitmapData);
  addChild(bitmap);
 
  squareBitmapData = new BitmapData(2, 2, true, 0xFFFFFFFF);
 
  addEventListener(Event.ENTER_FRAME, loop);
}
private var bitmapData:BitmapData; 	// main BitmapData
private var bitmap:Bitmap; 		// main Bitmap
private var squareBitmapData:BitmapData	// BitmapData for color squares

private function init():void 
{
	bitmapData = new BitmapData(stage.stageWidth, stage.stageHeight, false,
		0x000000);
	bitmap = new Bitmap(bitmapData);
	addChild(bitmap);

	squareBitmapData = new BitmapData(2, 2, true, 0xFFFFFFFF);

	addEventListener(Event.ENTER_FRAME, loop);
}

 

OK, so we have our bitmap on stage and we have added a listener that will call loop() function on each frame. This function will simulate complex 2D graphics operations by calling a certain method 500 times :-)

 

1
2
3
4
5
6
7
8
9
10
11
private function loop(evt:Event):void
{
  bitmapData.lock();
  for (var i:int = 0; i < 500; i++ )
  {
    // call EITHER methodA() OR methodB()
    methodA();
    //methodB();
  } 
  bitmapData.unlock();
}
private function loop(evt:Event):void
{
	bitmapData.lock();
	for (var i:int = 0; i < 500; i++ )
	{
		// call EITHER methodA() OR methodB()
		methodA();
		//methodB();
	}	
	bitmapData.unlock();
}

 

Both methods – A and B – do the following: draw a picture on our main bitmap. To make things simple, our “picture” will be a 2×2 bitmap with a random color and random alpha.

Method A takes our squareBitmapData object that we have created before and fills it with a random color. Then it uses copyPixels() to put the result pixels in a random spot on our display.

1
2
3
4
5
6
7
8
9
private function methodA():void
{
  squareBitmapData.fillRect(squareBitmapData.rect,
    Math.random() * 255 * 255 * 255 * 255);
 
  bitmapData.copyPixels(squareBitmapData, squareBitmapData.rect,
    new Point(Math.random() * bitmapData.width,
    Math.random() * bitmapData.height));
}
private function methodA():void
{
	squareBitmapData.fillRect(squareBitmapData.rect,
		Math.random() * 255 * 255 * 255 * 255);

	bitmapData.copyPixels(squareBitmapData, squareBitmapData.rect,
		new Point(Math.random() * bitmapData.width,
		Math.random() * bitmapData.height));
}

 

Method B creates its own local BitmapData object with a random color.  Then it uses copyPixels() to put the result pixels in a random spot on our display.

 

1
2
3
4
5
6
7
private function methodB():void
{
  bitmapData.copyPixels(new BitmapData(2, 2, true,
    Math.random() * 255 * 255 * 255 * 255), new Rectangle(0, 0, 2, 2),
    new Point(Math.random() * bitmapData.width,
    Math.random() * bitmapData.height));
}
private function methodB():void
{
	bitmapData.copyPixels(new BitmapData(2, 2, true,
		Math.random() * 255 * 255 * 255 * 255), new Rectangle(0, 0, 2, 2),
		new Point(Math.random() * bitmapData.width,
		Math.random() * bitmapData.height));
}

 

The result – let the FPS speak

Perhaps I’m just stupid. Perhaps it should be an obvious thing right from the start that creating new objects instances is time-consuming activity and will kill performance.

…But it doesn’t do that.

At least on browsers OTHER than Chrome.

See for yourself: I’ve added a simple FPS counter to the previous example.

 

Method A – should have good performance on all browsers Method B – if you’re using Chrome it will probably lag as hell.

The project is published to run at 60FPS.

If this example doesn’t work for you or you don’t have both Chrome and other browser installed, here are some screenshots:

Method A - Firefox Method A - Chrome
Method A – using single BitmapData for each iteration

 

Method B - Firefox Method B - Chrome
Method B – using new BitmapData for each iteration

There you have it. Instead of nice and smooth 60 frames per second, we barely get 16 fps, which is of course unacceptable.

 

Why is it different on Chrome?

Why would Flash work differently on Chrome? If you’ve ever had problems with it, you probably already know this one – Pepper Flash plugin.

pepper flash plugin

While other browsers use Flash Player installed from Adobe’s website, Chrome has its own plugin that is automatically updated.  How cool is that?

Not cool at all, especially that Chrome’s Pepper Flash isn’t particularly good Flash player – even according to Google Search that will point you to the most relevant results like  “How to disable Pepper Flash”  ;-)

Even worse thing – it sets itself as a default Flash player. What can you do about that?

As a user? Disable it and keep disabling it after each Chrome update (yes, it switches back without asking you).

As a developer? Nothing. You can’t expect your users to all disable Pepper Flash plugin. If you’re lucky, maybe 1% of your audience manages to do that. Others will rate your game 0/5 because it doesn’t work fast enough for them.

Sadly, the only solutions to all Chrome problems are:

A) find little pesky details and use workarounds

B) wait for Google to fix it.

Which option is more realistic and probable – guess yourself.  Maybe it’s all a part of Google’s secret master-plan to kill Flash  :roll:

» Click here to grab source files «

FPS Counter by kaioa.com

formats

A Small Talk At The Back Of Beyond – Beta tests!

Published on February 28, 2013, by in Games.

UPDATE:

Beta is over, but the game will still be updated with new suggestions/bug fixes!

Thank you everyone!  :-)

 

 

Here is my new game: A small talk at the back of beyond. It’s a text-based, umm, puzzle game about conversation. Something between the games Facade and Don’t Shit Your Pants. 

The game is currently in beta – it is finished and playable, but as English is not my main language, I guess there will be some grammar/spelling errors in such a text-heavy game.

Besides – I feel like I’m missing lots of players potential questions/statements that the game should know a response to.

If you happen to:

  • Find an error in my game
  • Feel like the computer should know a response to something that he didn’t

be sure to give me a feedback in comments to this post.

Here is the game:

A small talk at the back of beyond

 

A Small Talk At The Back Of Beyond

A Small Talk Screenshot 1

A Small Talk - Screenshot 2

formats

400 hours after creating 400 Years

Published on February 19, 2013, by in Games.

It’s been good over two weeks since I’ve finished creating 400 Years. The development process started around the beginning of January and lasted for 3 weeks (with this one additional week for small fixes etc.)

400 Years was created as January game for One Game A Month challenge, but more like “by the way” than just “I need a game for January”. The game started with an idea of an immortal (or very-very-long-lived) being giving something to a primitive civilization and then waiting patiently to see what happens. And by “waiting patiently” I mean waiting for ages. This Monkeys-Meet-The-Monolith based concept evolved into a simple puzzle platforming game. One of those where puzzle are there only to complete the story, not the other – usual – way around.

So there we have it – a stone idol, based on Easter Island’s famous Moai figures((This is not a coincidence. I had the following elements: sea shore as a starting point, a village of primitive people, a grassy lands and a hero that needs to be made of stone so he could peacefully stand still for ages, even underwater. Moai was the obvious choice. Even more obvious since most of the Easter Island statues are made of compressed volcanic ashes. Yeah. Does it add anything to the story depth for you?)), abandons its guarding post by the sea shore and travels into the land, driven by the need of helping those tiny mortal humans. An idea like this is difficult to execute without thinking, even remotely, of Black and White series, where you play as a god and interact with villagers…  Black and White however represents completely different kind of interaction – it grants divine powers allowing you to throw people around. In 400 Years you don’t have this, as you are not a god or even god’s avatar. Almost everything you can do is limited to: walking and waiting. And yes, it’s difficult to deny it, 400 Years lacks a bit when it comes to player’s freedom of choice. You only have one path to follow, you have to help humans and see their little village grow and thrive. But this was not always the case.

The idea at first was to let players decide if they want to help human settlement, ignore it completely, or – on the contrary – raze it to the ground. Buildings were supposed to allow an interaction – this interaction being “Press E to attack“. Damaged buildings would repair over time, but with enough damage, people would just die-off, leaving nothing but ruins as the proof they ever existed.

After the game was featured on Newgrounds and Kongregate many people started asking for a sequel or a longer version. And – while I’m very surprised to have this amount of positive feedback – I think I understand what would people like to see in a longer version of 400 Years – and why.

So, the friendly and good giant statue could have been a cold-blooded murderer. He could also have been ignorant, not caring for humans at all. As I see it now, this would have changed the meaning of the game completely. For better or worse – it’s up to you to decide – but I felt really torn apart when I realized there is no way I can implement all those features into one month project. Because of the full time job, because I had to draw every graphic element by myself, because the game code was already getting a bit sloppy. I had no choice but to cut those features out, together with multiple endings (help everyone, save the world but kill humans, help humans but let the world destroy, etc… YES all those were actually planned!).

But I feel like there is also a good side of this. By limiting and making the idea simpler, the finished game turned out to be more solidcondensed experience – up to the point I felt it was actually a good thing I cut the other endings. This time I felt “the less is the more” if one can say that. Sometimes it’s better not to expand the story too much because it could lose its meaning on the way. Some say it’s way to short – not that it’s not interactive enough but just too short in general. More places to explore, more puzzles to solve – I get it. But considering the slow pace of the whole experience (including our protagonist’s speed) I believe the amount of gameplay present in the game is just enough for our hasty, fast society to digest. That being said, I’m currently not planning to expand the game in any way – at least not now. I have to focus on future projects, the ideas won’t turn into games themselves.

Maybe I will return to this idea in the future. Time will tell.

Tags: , ,