views:

2056

answers:

5

I work on a 2D shooter game with lots of moving objects on the screen (bullets etc).

I use BitmapData.copyPixels(...) to render entire screen to a buffer:BitmapData. Then I "copyPixels" from "buffer" to screen:BitmapData. The framerate is 60.

private var bitmap:Bitmap = new Bitmap();
private var buffer:Bitmap = new Bitmap();

private function start():void {
    addChild(bitmap);
}

private function onEnterFrame():void {
    // render into "buffer"
    // copy "buffer" -> "bitmap"
}

The problem is that the sprites are tearing apart: some part of a sprite got shifted horizontally.

It looks like a PC game with VSYNC turned off.

Did anyone solve this problem?

UPDATE: the question is not about performance, but about getting rid of screen tearing.

[!] UPDATE: I've created another question and here you may try both implementations: using Flash way or BitmapData+copyPixels()

A: 

First thing you might want to do is stop treating the Flash Player like it is DOS. The Flash Player is a highly optimized 2D game engine as it is and I don't really understand why you are trying to reinvent the wheel by copying lots of bitmap slices around. Of course you will have performance issues.

The Flash Player doesn't let you sync to any vertical or horizontal blank because the Flash Player simply doesn't have any concept of this.

I personally think that you should rethink you approach if you want 'smoother' animation. The Flash Player is certainly capable of this, you're just trying the wrong approach.

Luke
Strange thing, copying chucks of bytes (bitmaps) in memory should be easier for computer rather than rendering it with math calculations. There should be a reason why "cacheAsBitmap" exist in Flash. Also, check this: http://aralbalkan.com/759
oshyshko
Your Sprites (DisplayObject's) do not have to be vector at all. The Flash Player is optimized to deal with this. When you start to recreate in ActionScript with bitmaps what the Flash Player already does very well and is optimized for, then you're just missing the point. I think you should read more of Tinic Uro blog: http://www.kaourantin.net
Luke
@Luke: Your answer would be more useful if it suggested a practical alternative, rather than just saying the original approach is wrong. There are several sources online suggesting the use of bitmaps and copyToPixels in the context of making 2D games so it's not the original poster who's doing the reinventing.
Kylotan
A: 

Don't save things to BitmapData, that will kill, absolutely kill your app. Bitmap Data is not very performant.

Make all your game elements in flash, as Sprites(or MovieClips if you must), and then work how flash was meant to work, as a vector animation platform. It was never optimized for 2d bitmap graphics. 2d vector graphics work well, and even if you import bitmaps they will work better moving around then they will rendered to a BitmapData object.

Kekoa
If I'll give up with buffering and add bitmaps as native Flash sprites (still bitmaps), then will it solve the VSYNC problem?
oshyshko
No it won't. But it will look far better than what you currently have. As I said in my answer to your question, the Flash Player has no concept of vsync. When you set the fps to 60 (which is absurd but that's beside the point) then the Flash Player will TRY to generate 60 fps. In reality it will almost never accomplish this.
Luke
I've found there are defininitely times you should use Bitmapdata for performance improvement.
Matt W
@Matt But your entire app, rendered in a BitmapData object every frame? This is seriously a bad idea. I'm not saying BitmapData is not useful.
Kekoa
A: 

the others are right, that this approach isn't very suitable for flash player ... still, i'm amazed, it doesn't work at all ...

few questions:

  • did you try to lock the bitmapData you are drawing into? (if not, this may help a lot!)
  • are you using transparent bitmaps? (general performance killer)
  • dir you try Stage::invalidate and rendering on Event.RENDER instead of rendering?
back2dos
- lock/unlock didn't help because copying "buffer" -> "bitmap" produces single event, so it is same single notification in both cases- I do use transparent bitmaps for projectiles - but, again, the problem is not in performance, the problem is in screen tearing- I tried to: * prepare "buffer" + stage.invalidate() in ENTER_EVENT and then * copy "buffer" -> "bitmap" in RENDER event Same result (screen tearing), but higher CPU consumption(I guess because it is because of events fired by stage.invalidate() )
oshyshko
A: 

. . These guys surely don't know what they are talking about. BitmapData.copyPixels is THE way to go when it comes down to flash games with lots of objects moving around. Sprite creation is just a masssive overhead and re-render the vectors every frame will simply kill your flash player in no time. Take a look: http://www.8bitrocket.com/newsdisplay.aspx?newspage=7496. . . About your problem... I'm sorry but I think it will be very hard to help without actual code snippets or at least a working example with the reproducible problem.

. . C'ya.

diego nunes
+1  A: 

I feel your pain as I'm currently in the trenches developing my own game. At default settings, the Flash renderer produces horrible screen tearing / v-sync issues, regardless of what code you produce.

This is why I was pleased to have found the most simple, elegant answer, that wasn't re-factoring code (which doesn't help a single bit, the problem is the Flash player, not code).

Just enable Hardware Acceleration in your Publish Settings. There's two different options:

Level 1: Direct; and Level 2: GPU.

Read more about it at the official documentation: Specify publish settings for SWF files, and decide what option is best for your game.

Target market does play a factor here, if it's a serious game for gamers, you don't need to worry about possible performance issues, as most gamers have GPU's.

This article did not provide me with the solution specifically, but lead me in the right direction. BUT, if your game is going to be in a browser window, you might have to use the same technique of setting wmode to direct or gpu as well.

Daniel Carvalho