【问题标题】:AS3 Spritesheet animationAS3 Spritesheet 动画
【发布时间】:2014-03-25 01:37:44
【问题描述】:

我正在开发一个游戏,其中会有不同方面的人,我想知道如何在动画的每一帧中加载一个文件,经过大量搜索后,我在另一个 flash 项目中创建了一个新的 Ball 类并制作了我自己这段代码只是为了测试

public class Ball extends MovieClip {

    private var spriteSheet:Bitmap;

    public function Ball() 
    {
        var loader:Loader = new Loader();
        loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onLoadComplete);
        loader.load(new URLRequest("Ball.png"));
    }

    private function onFrameLoop(e:Event)
    {
        switchFrame();
    }

    private function switchFrame()
    {
        var frameBitmapData:BitmapData = new BitmapData(50, 50);
        frameBitmapData.copyPixels(spriteSheet.bitmapData, new Rectangle(0, (50*(currentFrame-1)), 50, 50), new Point(0,0));
        var frame:Bitmap = new Bitmap(frameBitmapData);
        this.addChild(frame);
    }

    private function onLoadComplete(e:Event)
    {
        var loaderInfo:LoaderInfo = e.target as LoaderInfo;
        spriteSheet = loaderInfo.content as Bitmap;

        this.addEventListener(Event.ENTER_FRAME, onFrameLoop);
    }
}

}

它起作用了,我刚刚在 Ball MovieClip Symbol 上添加了 5 个空白关键帧。问题是,如果我打算为移动设备制作这款游戏​​,并且可能同时有 20 个人在舞台上,这是否足够快?还必须有另一种方法,因为 XML 文件必须用于某些事情,对吗?那么其他方式是什么?

PD:我知道每次执行 switchFrame 函数时我都不会删除帧位图。

我需要一个好的答案,不要将我链接到我可能不会理解的东西

【问题讨论】:

    标签: actionscript-3 flash animation sprite-sheet


    【解决方案1】:

    您基本上是在每帧创建一个新的 BitmapData 对象 - 真的很糟糕。你不清理旧框架 - 真的很糟糕。怎么强调都不过分。您需要一个Bitmap 对象和一个BitmapData 对象(以及一个Rectangle 对象)来制作一个工作精灵。想象一下,您将获得 1000 个球,每个球每帧制作一个位图 - 您的游戏很快就会崩溃。但是,如果每个球都有一个本地位图,那么一切都应该足够顺利。

    我在制作精灵表时还有一个警告,copyPixels() 方法在屏幕上没有很多对象时有效,如果你越过某个阈值,你最好制作一个 BitmapData 对象对于动画的每一帧,只需更改您的精灵每一帧所具有的那些位图的bitmapData 链接。

    public class Ball extends MovieClip {
    
    private static var spriteSheet:BitmapData; // first, why storing a Bitmap if you don't need it be moving?
    private static var spriteArray:Vector.<BitmapData>; // This will store split spritesheet
    
    private var bitmap:Bitmap; // this will be displaying proper frame
    private var currentFrame:int; // what frame are you displaying
    public static function initialize():void {
        // loading static assets should better be made in a static function
        if (!spriteSheet) {
           var loader:Loader = new Loader();
           loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onLoadComplete);
           loader.load(new URLRequest("Ball.png"));
        }
    }
    public function Ball() {
        bitmap=new Bitmap(); // null bitmap is displayed
        addChild(bitmap);
        currentFrame=0;
        addEventListener(Event.ENTER_FRAME, onFrameLoop,null,0,true); // weak listener
        // to not hog memory if you'd create and remove balls
    }
    private function onFrameLoop(e:Event)
    {
        switchFrame();
    }
    
    private function switchFrame()
    {
        if (!spriteArray) return; // oops, not initialized
        currentFrame++;
        if (currentFrame>=spriteArray.length) currentFrame=0;
        bitmap.bitmapData=spriteArray[currentFrame]; // voila. Now this particular Ball
        // will display the proper BitmapData out of sliced sprite sheet.
    }
    
    private static function onLoadComplete(e:Event)
    {
        var loaderInfo:LoaderInfo = e.target as LoaderInfo;
        spriteSheet = (loaderInfo.content as Bitmap).bitmapData; // store the bitmapdata
        // now cut the loaded sprite sheet apart
        var i:int=Math.floor(spritesheet.width/50); // how many frames are in there
        var r:Rectangle=new Rectangle(0,0,50,50);
        var p:Point=new Point(); // why making N identical points? Just make one
        spriteArray=new Vector.<BitmapData>();
        for (var j:int=0;j<i;j++) {
            var bd:BitmapData=new BitmapData(50,50);
            r.x=50*j; // update rectangle to cut next frame
            bd.copyPixels(spriteSheet,r,p); // cut the frame in a new BitmapData
            spriteArray.push(bd); // store the frame
        }
        // once this is complete, your sprite sheet is ready
    }
    }
    
    }
    

    【讨论】:

    • 为什么在公共静态函数中?
    • 一个公共静态函数可以让你在类范围内做一些事情,而无需创建该类的实例。而且因为精灵表位图实际上是针对班级的,而不是针对任何单个球的,所以最好在获得球之前使其可用。该事件由代码在调用静态函数时生成的loader 生成,在完成加载位图之后。
    猜你喜欢
    • 2014-09-13
    • 2012-04-21
    • 1970-01-01
    • 2018-10-10
    • 2013-10-27
    • 2014-06-28
    • 2015-11-27
    • 2018-05-21
    • 2013-03-24
    相关资源
    最近更新 更多