与完全相同的处理小程序相比,简单的 Flash 测试应用程序运行速度非常慢
因此,我正在逐渐地、痛苦地从Processing转向Flash,以便希望能够为更广泛的受众开发游戏。最后,我在 Flash 中得到了一个可用的应用程序,它只需让用户单击即可创建块,这些块随后会被鼠标吸引。我也在处理中做了完全相同的事情,只是为了比较速度。然而,当我运行 Flash 版本并添加大约 15-20 个块时,帧速率下降到 5-10 FPS。在处理版本中,我可以添加 ~60,而没有明显的减速。这是怎么回事,闪电侠?
每个版本源的链接:
这里是每个版本的源代码,以防万一您是一个向导,只需严厉地盯着代码并告诉其行为即可提供帮助:
Flash 版本:
blocks.fla
import flash.events.Event;
import flash.display.MovieClip;
stage.addEventListener( Event.ENTER_FRAME, onenter );
stage.addEventListener( MouseEvent.MOUSE_DOWN, onclick );
var main = this;
var lastFrame:Number;
var Blocks:Array = new Array();
function onenter( e:Event ):void
{
var time:Number = getTimer();
for( var i = 0; i < Blocks.length; i++ )
{
Blocks[ i ].run();
}
FrameRate.text = String( Blocks.length ) + "\n" + String( 1000 / ( time - lastFrame ) );
lastFrame = time;
}
function onclick( e:MouseEvent ):void
{
var block1 = new Block( Blocks, main, mouseX, mouseY );
}
Block.as
package {
import flash.display.MovieClip;
import flash.geom.Vector3D;
public class Block extends MovieClip {
var velocity:Vector3D = new Vector3D( 0, 0 );
var position:Vector3D = new Vector3D( x, y );
var acceleration:Vector3D = new Vector3D( 0, 0 );
public function Block( Blocks:Array, This, x:Number, y:Number ) {
Blocks.push( this );
This.addChild( this );
position.x = x;
position.y = y;
}
public function run()
{
x = position.x;
y = position.y;
//position.incrementBy( velocity );
position.x += velocity.x;
position.y += velocity.y;
acceleration.x = stage.mouseX - position.x;
acceleration.y = stage.mouseY - position.y;
acceleration.normalize();
//velocity.incrementBy( acceleration );
velocity.x += acceleration.x;
velocity.y += acceleration.y;
velocity.x *= 0.95;
velocity.y *= 0.95;
this.graphics.beginFill( 0 );
this.graphics.moveTo( -10, -10 );
this.graphics.lineTo( 10, -10 );
this.graphics.lineTo( 10, 10 );
this.graphics.lineTo( -10, 10 );
this.graphics.lineTo( -10, -10 );
this.graphics.endFill();
}
}
}
处理版本:
sketch_mar02b.pde
Block[] blocks = new Block[ 0 ];
void setup()
{
frameRate( 60 );
size( 550, 400 );
textFont( createFont( "Verdana", 20 ) );
}
void draw()
{
background( 255 );
for( int i = 0; i < blocks.length; i++ )
{
blocks[ i ].run();
}
text( blocks.length + "\n" + frameRate, 0, 20 );
}
void mousePressed()
{
new Block( mouseX, mouseY );
}
Block.pde
class Block
{
PVector position = new PVector( 0, 0 );
PVector velocity = new PVector( 0, 0 );
PVector acceleration = new PVector( 0, 0 );
Block( float x, float y )
{
position.set( x, y, 0 );
blocks = ( Block[] ) append( blocks, this );
}
void run()
{
position.add( velocity );
acceleration.set( mouseX - position.x, mouseY - position.y, 0 );
acceleration.normalize();
velocity.add( acceleration );
velocity.mult( 0.95 );
pushMatrix();
translate( position.x, position.y );
fill( 0 );
rect( -10, -10, 20, 20 );
popMatrix();
}
}
感谢您的帮助!
So I'm gradually, painfully moving from Processing to Flash in order to hopefully develop games to a wider audience. At long last, I get a working application in Flash made that simply lets the user click to create blocks which subsequently gravitate towards the mouse. I made the exact same thing in Processing too, just to compare speeds. However, when I run the Flash version and add around 15-20 blocks, the framerate drops to 5-10 FPS. In the Processing version I can add ~60 with no noticeable slowdown. What's the deal, Flash?
Links to each version's source:
Here is the source for each in case you are a wizard and can help just by glowering at the code sternly and telling it to behave:
Flash version:
blocks.fla
import flash.events.Event;
import flash.display.MovieClip;
stage.addEventListener( Event.ENTER_FRAME, onenter );
stage.addEventListener( MouseEvent.MOUSE_DOWN, onclick );
var main = this;
var lastFrame:Number;
var Blocks:Array = new Array();
function onenter( e:Event ):void
{
var time:Number = getTimer();
for( var i = 0; i < Blocks.length; i++ )
{
Blocks[ i ].run();
}
FrameRate.text = String( Blocks.length ) + "\n" + String( 1000 / ( time - lastFrame ) );
lastFrame = time;
}
function onclick( e:MouseEvent ):void
{
var block1 = new Block( Blocks, main, mouseX, mouseY );
}
Block.as
package {
import flash.display.MovieClip;
import flash.geom.Vector3D;
public class Block extends MovieClip {
var velocity:Vector3D = new Vector3D( 0, 0 );
var position:Vector3D = new Vector3D( x, y );
var acceleration:Vector3D = new Vector3D( 0, 0 );
public function Block( Blocks:Array, This, x:Number, y:Number ) {
Blocks.push( this );
This.addChild( this );
position.x = x;
position.y = y;
}
public function run()
{
x = position.x;
y = position.y;
//position.incrementBy( velocity );
position.x += velocity.x;
position.y += velocity.y;
acceleration.x = stage.mouseX - position.x;
acceleration.y = stage.mouseY - position.y;
acceleration.normalize();
//velocity.incrementBy( acceleration );
velocity.x += acceleration.x;
velocity.y += acceleration.y;
velocity.x *= 0.95;
velocity.y *= 0.95;
this.graphics.beginFill( 0 );
this.graphics.moveTo( -10, -10 );
this.graphics.lineTo( 10, -10 );
this.graphics.lineTo( 10, 10 );
this.graphics.lineTo( -10, 10 );
this.graphics.lineTo( -10, -10 );
this.graphics.endFill();
}
}
}
Processing version:
sketch_mar02b.pde
Block[] blocks = new Block[ 0 ];
void setup()
{
frameRate( 60 );
size( 550, 400 );
textFont( createFont( "Verdana", 20 ) );
}
void draw()
{
background( 255 );
for( int i = 0; i < blocks.length; i++ )
{
blocks[ i ].run();
}
text( blocks.length + "\n" + frameRate, 0, 20 );
}
void mousePressed()
{
new Block( mouseX, mouseY );
}
Block.pde
class Block
{
PVector position = new PVector( 0, 0 );
PVector velocity = new PVector( 0, 0 );
PVector acceleration = new PVector( 0, 0 );
Block( float x, float y )
{
position.set( x, y, 0 );
blocks = ( Block[] ) append( blocks, this );
}
void run()
{
position.add( velocity );
acceleration.set( mouseX - position.x, mouseY - position.y, 0 );
acceleration.normalize();
velocity.add( acceleration );
velocity.mult( 0.95 );
pushMatrix();
translate( position.x, position.y );
fill( 0 );
rect( -10, -10, 20, 20 );
popMatrix();
}
}
Thanks for helping out!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
一个问题是,每次执行 .run 时,您都会重新绘制精灵的图形框,但精灵不会随着时间的推移而发生变化。因此,只需在构造函数中绘制一次就足够了。
但是,如果由于某种原因您确实必须重新绘制每一帧怎么办?也许随着时间的推移改变盒子的颜色?好吧,您忽略了清除旧图像......所以每一帧您只是向图形对象添加越来越多的矢量点。因此,实际上,虽然看起来只有一个黑色方块,但实际上在几秒钟后就拥有了数千个黑色方块的数据。您可以像这样清除图形对象...
作为微观优化,您可以将 this.graphics 分配给局部变量...
我注意到的另一件事是,您似乎没有基于时间的移动,而是它是基于框架的。方块本身不知道已经过去了多少时间,所以它们会放慢速度。另一种方法是根据经过的时间进行移动,这将使它们以正确的“速度”移动,但应用程序会为此丢帧。
由于这是一个您正在处理的盒子,因此您还可以使用graphics.drawRect()而不是逐行绘制盒子。
根据我自己的测试,选项 1 效果最好。如果您确实必须重绘,请确保执行graphics.clear(),因为即使对于大量框,它也几乎同样有效。
编辑添加...
您的示例在添加 .clear() 函数调用后确实执行得很好。不过,我应该提醒您,JVM 肯定会比 Flash Player 具有更好的性能。这并不是说人们不能制作高性能的Flash应用程序,而是说Flash Player在处理CPU渲染时的性能上限比Java要低得多。当然,如果您愿意生活在最前沿,您可以查看新的“Molehill”3D api,它具有这样的能力...
Wii 上的 3D 游戏使用 Molehill 移植到 Flash,以 60fps 运行http://blog.theflashblog.com/?p=2593
One problem is that on every execution of .run you're redrawing the sprite's graphic box, but the sprite doesn't change at all over time. So just drawing once in the constructor is enough.
But what if you DO have to redraw every frame for some reason? Maybe to change the color of the box over time? Well, you're neglecting to clear your old image... so every frame you just add more and more vector points to the graphics objects. So in reality while it looks like you have just one black square you actually have thousands of black squares worth of data after only a few seconds. You can clear out the graphics object like this...
As a micro optimization, you can assign this.graphics to a local variable...
Another thing I notice is that you don't appear to have time-based movement, but rather it's frame based. The blocks themselves have no idea how much time has elapsed, so they'll slow down. The alternative is to base their movement on elapsed time, which will keep them moving at the right "speed" but the app will drop frames to do it.
Since this is a box you're dealing with, you can also use graphics.drawRect() instead of drawing a box line by line.
In my own testing, option 1 worked the best. If you do have to redraw, make sure to do graphics.clear(), as that works almost as well even for large numbers of boxes.
EDIT to add...
Your example, after adding the .clear() function calls does perform very well. I should however caution you that the JVM is most certainly going to have better performance than the Flash Player. This isn't to say that people can't make highly performant Flash applications, but that the upper ceiling for performance in the Flash Player when dealing with CPU rendering is much lower than that of Java. Of course, if you're willing to live on the bleeding edge you can check out the new "Molehill" 3D apis that are capable of things like this...
3D game on the Wii ported to Flash using molehill, running at 60fpshttp://blog.theflashblog.com/?p=2593