zoukankan      html  css  js  c++  java
  • 在flash中用双向链表实现受控动画

    虽然flash中对实现连续的动画有很好的支持, 但是在编写游戏的时候,这还远远不够好。

    场景:你的英雄比怪物先一帧击中了对方,对方因为受到攻击原本准备法术的动作被停止了。这个时候下一帧不能继续播放准备法术/释放法术的动画了,而应该及时播放怪物被击中的动画。

    游戏中这类场景是比较常见的,这就要求重新实现一个更好控制,更易改变的动画控制系统。

    我决定自己实现一个动画调度器来控制所有的动画。这个调度器需要能在整个系统绘制新帧的时候做出合适响应。我采用的方式是监听系统的enterFrame事件,并且保留一个自系统开始以来frame计数。按FPS=60计算,使用uint型能在数十天内良好运行,考虑到游戏规模,这个时间已经足够长了 ^-^

    public class AnimationDispatcher{
     //帧数统计
     private var _frameCounter : uint;
     
     public function listenEnterFrame(e:Event):void{
      _frameCounter++;
     }
    }
    

    接下来实现被控制的动画。

    public interface IActionFrame{
     
     //下一次需要执行的帧数
     function get nextActionFrame():uint;
     
     //执行动作
     function doAction():void;
     
     //执行完doAction后是否需要把对象重新放回list中
     function needToPushBack():Boolean;
    }
    

    链表的节点:

    internal class ListNode{
     private var _previous : ListNode;
     private var _next : ListNode;
     private var _item : IActionFrame;
     
     public function ListNode(item:IActionFrame){
      _item = item;
     }
     
     public function get previous():ListNode{
      return _previous;
     }
     
     public function set previous(value:ListNode){
      _previous = value; 
     }
     
     public function get next():ListNode{
      return _next;
     }
     public function set next(value:ListNode):void{
      _next = value;
     }
     public function get item():IActionFrame{
      return _item;
     }
    }
    

    链表:

    public class LinkedList{
     private var _head : ListNode;
     private var _tail : ListNode; 
     public function LinkedList(){
      _head = new ListNode(null);
      _tail = new ListNode(null);
      
      _head.next = _tail;
      _tail.previous = _head;
     }
     public function add(item:IActionFrame):void{
      if (item == null) return;
      var newNode : ListNode = new ListNode(item);
     
      var currentNode : ListNode = _head.next;
      while (currentNode != null){
       if (currentNode == _tail){
        _tail.previous.next = newNode;
        newNode.next = _tail;
        tail.previous = newNode;
        break;
       }
       
       if (currentNode.item.nextActionFrame > newNode.nextActionFrame){
        currentNode.previous.next = newNode;
        currentNode.previous  = newNode;
        newNode.previous = currentNode.previous;
        newNode.next = newNode;
        break;
       }
       currentNode = currentNode.next;
      }
     }
     
     //移除列表中的item
     public function remove(item:IActionFrame):void{
      if (item == null)return;
      if (_head.next == _tail) return;
      var currentNode : ListNode = _head.next;
      while (currentNode != tail){
       if (currentNode.item == item){
        currentNode.previous.next = currentNode.next;
        currentNode.next.previous = currentNode.previous;
        break;
       }
       currentNode = currentNode.next;
      }
     }
     
     //获取下一个需要处理的对象,同时从列表中移除此对象
     public function nextActiveFrame(currentFrame:uint):IActionFrame{
      if (_tail.next == _tail) return null;
      if (_tail.next.item.nextActionFrame > currentFrame) return null;
      var result : ListNode = _tail.next;
      
      _tail.next = _tail.next.next;
      _tail.next.previous = _tail;
      
      return result.item;
     }
    }
    

    最后修改AnimationDispatcher类,使之能管理所有的动画:

    public class AnimationDispatcher{
     private var _frameCounter : uint;
     private var _list : LinkedList = new LinkedList();
     
     public function listenEnterFrame(e:Event):void{
      _frameCounter++;
      while ((var item : IActionFrame = _list.nextActiveFrame) != null){
       //执行动作及处理下一帧间隔
       item.doAction();
       if (item.needToPushBack()){
        _list.add(item);
       }
      }
     }
    }
    
  • 相关阅读:
    [CareerCup] 1.4 Replace Spaces 替换空格
    [CareerCup] 1.3 Permutation String 字符串的排列
    Android @1x,@2x,@3x 资源文件自动分包工具
    Android 使用xml实现边框阴影,背景渐变效果(附有RGB颜色查询对照表)
    Android中快速实现自定义字体!
    Android AS升级3.1 编译报错:The SourceSet 'instrumentTest' is not recognized by the Android Gradle Plugin.
    Android getRunningTasks和getRunningAppProcesses失效
    Android 实现朋友圈有图片和视频
    Android 仿微信朋友圈拍小视频上传到服务器
    Android setUserVisibleHint-- fragment真正的onResume和onPause方法
  • 原文地址:https://www.cnblogs.com/mingxing/p/1780001.html
Copyright © 2011-2022 走看看