我是Flash ActionScript 3.0和对象编程的新手。我正在尝试创建一个基于转向绘制形状的简单游戏。
public class Player extends Shape
{
public var X,Y,v,vX,vY,size,a,r:Number;
public var k,counter,leftKey,rightKey,_color:uint;
public var line:Shape = new Shape();
public var dot:Shape = new Shape();
/*...*/
/*constructor, giving values to variables here, not important*/
/*...*/
public function Move():void
{
a=a+0.05*k;
//player controls k parameter k=0 by default
//k=1 when right key pressed
//k=-1 when left key pressed
vX=v*Math.cos(a);
vY=v*Math.sin(a);
X=X+vX;
Y=Y+vY;
dot.x=X+vX*size/(2*v);
dot.y=Y+vY*size/(2*v);
if (counter==0)
{
line.graphics.lineTo(X,Y);
if (Math.random()<0.008) counter=12;
} else
{
line.graphics.moveTo(X, Y);
counter--;
}
}
}
函数Move在我的Player类中,从我的Main Class中的无限TimerEvent函数调用
public function mainLoop(TimerEvent:Event):void
{
for (var i:uint=0; i<players; i++) player[i].Move();
}
一开始似乎运行良好但经过一段时间后CPU使用量大幅增加,游戏变得无法播放。我相信它是由我的形状(线)变得越来越复杂造成的。
有没有合理的方法来优化它?我能以某种方式以较少的消费方式划清界限吗?我试图将其转换为位图,但这看起来很难看,并没有真正的帮助。
谢谢和欢呼!
答案 0 :(得分:0)
你是正确的假设你的形状代码减速 - 矢量数据在flash中每一帧重绘一次,所以它越复杂,绘制的时间就越长。一些解决方案,取决于您愿意做的事情:
Move
功能;你可能不需要那么高,因为自上一帧以来的移动差异可能小于一个像素。改为每隔X帧取样一次(其中X是您愿意接受的保真度)。这可以通过输入框架中的简单计数器来完成line.graphics.clear()
并只绘制数组中的点BitmapData
(例如,舞台的大小)。每隔一段时间,将line
绘制到BitmapData
并在图形上调用clear()
以获得向量数据的正确性。您不应该注意到质量的任何损失(在您绘图时将smoothing
设置为true
)在任何情况下我都会做第一点,然后在第二点和第三点之间进行选择,具体取决于你的用例
答案 1 :(得分:0)
扩展我的评论,尝试这样的事情:
public class Player extends Shape
{
public var X,Y,v,vX,vY,size,a,r:Number;
public var k,counter,leftKey,rightKey,_color:uint;
public var line:Shape = new Shape();
public var dot:Shape = new Shape();
/*...*/
/*constructor, giving values to variables here, not important*/
/*...*/
public function Player(){
//draw shapes
graphics.lineStyle(1);
graphics.drawCircle(0,0,r);
graphics.lineTo(size,0);//can't test this now, but make sure the line is in the same direction as rotation 0 (guessing it's to the right)
//your other constructor code here
}
public function Move():void
{
a=a+0.05*k;
//player controls k parameter k=0 by default
//k=1 when right key pressed
//k=-1 when left key pressed
vX=v*Math.cos(a);
vY=v*Math.sin(a);
X=X+vX;
Y=Y+vY;
x=X+vX*size/(2*v);
y=Y+vY*size/(2*v);
rotation = a * 57.2957795;//quick'n'dirty radians to degrees
}
如果你想绘制小径,你可以试试这样的东西:
var canvas:Bitmap = new BitmapData(state.stageWidth,stage.stageHeight,true,0xFF000000);
var ct:ColorTransform = new ColorTransform(1,1,1,.1);
public function mainLoop(TimerEvent:Event):void
{
for (var i:uint=0; i<players; i++) {
player[i].Move();
canvas.draw(player[i],player[i].transform.concatenatedMatrix,ct);
}
}
希望这是有道理的。
<强>更新强> 这是一个独立的代码片段,用于说明上述想法(具有未经测试的语法):
package {
import flash.display.Bitmap;
import flash.geom.ColorTransform;
import flash.display.BitmapData;
import flash.text.TextField;
import flash.ui.Keyboard;
import flash.events.Event;
import flash.events.KeyboardEvent;
import flash.utils.Dictionary;
import flash.display.Sprite;
public class PlayerMoveTest extends Sprite {
private var keys:Dictionary = new Dictionary();
private var players:Vector.<Player> = new Vector.<Player>();
private var trails:BitmapData;
private var fade:ColorTransform = new ColorTransform(1,1,1,.1);
public function PlayerMoveTest() {
addEventListener(Event.ADDED_TO_STAGE,init);
}
private function init(e:Event):void{
trails = new BitmapData(stage.stageWidth,stage.stageHeight,true,0x00FFFFFF);
addChild(new Bitmap(trails));
for(var i:int = 0 ; i < 2; i++){
var p:Player = addChild(new Player(10+i*10)) as Player;
p.x = stage.stageWidth * .5;
p.y = stage.stageHeight * .5;
players.push(p);
}
stage.addEventListener(KeyboardEvent.KEY_DOWN,onKeyDown);
stage.addEventListener(KeyboardEvent.KEY_UP,onKeyUp);
stage.addEventListener(Event.ENTER_FRAME,update);
}
private function onKeyDown(e:KeyboardEvent):void{
keys[e.keyCode] = true;
}
private function onKeyUp(e:KeyboardEvent):void{
keys[e.keyCode] = null;
}
private function update(e:Event):void{
if(keys[Keyboard.LEFT] != undefined) {players[0].a -= .05;players[1].a += .05;}
if(keys[Keyboard.RIGHT] != undefined) {players[0].a += .05;players[1].a -= .05;}
if(keys[Keyboard.UP] != undefined) {players[0].s += .15;players[1].s -= .15;}
if(keys[Keyboard.DOWN] != undefined) {players[0].s -= .15;players[0].s += .15;}
for(var i:int = 0 ; i < players.length; i++) {
players[i].move();
trails.draw(players[i],players[i].transform.concatenatedMatrix,fade);
}
}
}
}
import flash.display.*;
class Player extends Shape{
public var vx:Number,vy:Number,a:Number,size:Number,r:Number,s:Number;
public function Player(size:Number){
init(size);
}
private function init(size:Number):void{
vx = vy = a = s = 0;
this.size = size;
this.r = size * .25;
graphics.lineStyle(1);
graphics.drawCircle(0,0,r);
graphics.lineTo(size,0);
}
public function move():void{
rotation = a * 57.2957795;
vx = Math.cos(a) * s;
vy = Math.sin(a) * s;
x += vx;
y += vy;
if(x < 0) x = 0;
if(y < 0) y = 0;
if(x > stage.stageWidth) x = stage.stageWidth-width;
if(y > stage.stageHeight) y = stage.stageHeight-height;
}
}
您可以测试此代码here,这是预览:
使用箭头键驱动(向上箭头加速,左/右转向)。 第一个玩家是较小的玩家,拥有正确的控制,另一个玩家只是镜像以前的控件)