JavaScript实现U3D

模块

define(function()
{
  function U3D(canvas)
  {
    var U = this;
    //全局时间对象
    U.Time = new TimeClass();
    //游戏时间控制器
    var gameTimer;
    //画布上下文
    var canvas2D = canvas.getContext("2d");
    //最长检测碰撞频率
    const CHECK_FRAME = 30;
    //当前频率计数器
    var gameFrame = 0;
    //碰撞检测列表
    var collisionList = [];
    //绘画游戏列表
    var drawList = [];

    //根据z值从小到大插入到绘画列表中
    function Z_IndexInset(o)
    {
      for(var i in drawList)
      {
        if(o.Z_INDEX < drawList[i].Z_INDEX)
        {
          drawList.splice(i,0,o);
          return;
        }
      }
      drawList.push(o);
    }

    //根据需要的更新频率从快到慢插入到碰撞检测列表中
    function CollisionInsert(c)
    {
      for(var i in collisionList)
      {
        if(c.CHECK_FREQUENCY < collisionList[i].CHECK_FREQUENCY)
        {
          collisionList.splice(i,0,c);
          return;
        }
      }
      collisionList.push(c);
    }

    //游戏暂停
    U.GamePause = function()
    {
      cancelAnimationFrame(gameTimer);
    }

    //游戏恢复
    U.GameUpdate = function()
    {
      if(gameFrame != CHECK_FRAME) { gameFrame++; } else { gameFrame = 0; }
      GameDraw();
      CollisionChecked();
      gameTimer = requestAnimationFrame(U.GameUpdate);
    }

    //绘制所有对象
    function GameDraw()
    {
      canvas2D.clearRect(0,0,canvas.width,canvas.height);
      for(var i in drawList)
      {
        drawList[i].Draw();
      }
    }

    //碰撞检测
    function CollisionChecked()
    {
      for(var i = 0;i<collisionList.length;i++)
      {
        if(gameFrame % collisionList[i].CHECK_FREQUENCY != 0){return;}
        if(i == collisionList.length - 1){break;}
        for(var j = i + 1;j < collisionList.length;j++)
        {
          for(var key in collisionList[i].collisionType)
          {
            if(collisionList[i].collisionType[key] == collisionList[j].collisionType)
            {
              //可在此处添加当物体拥有旋转角度时调用另一种判断方式
              ConllisionCheck(collisionList[i],collisionList[j]);
              break;
            }
          }
        }
      }
    }

    //不带旋转的方形碰撞检测
    function ConllisionCheck(col1,col2)
    {
      var x = Math.abs(col1.x - col2.x);
      var w = Math.abs((col1.width+col2.width)/2);
      var y = Math.abs(col1.y - col2.y);
      var h = Math.abs((col1.height+col2.height)/2);

      if(x < w && y < h)
      {
        col1.OnCollision2D(col2);
        col2.OnCollision2D(col1);
      }
    }

    //精灵类
    U.Sprite = function(x, y, width, height, url)
    {
      var self = this;
      self.x = x;
      self.y = y;
      self.width = width;
      self.height = height;
      var image = new Image();
      image.src = url;
      self.speed = 0;
      self.angle = 0;
      self.Z_INDEX = 0;
      //此物体的碰撞体名称
      self.collisionType = self.constructor.name;
      //此物体需要和哪些物体进行碰撞检测,如:["Cat","Dog"]
      self.collisionType = [];
      //此物体每几帧才进行一次碰撞检测
      self.CHECK_FREQUENCY = 1;
      //实例化时重写本字段定义物体碰撞后的执行代码。
      self.OnCollision2D = function(c) {};
      //动画帧,继承可按此格式重写重写
      self.artist =
      {
        //默认
        "default" : [{x:0,y:0,width:self.width,height:self.height}],
        //可在此添加更多的帧动画
      }
      //动画逻辑代码,继承时可按照此格式重写本字段
      self.animation =
      {
        //动画状态名称
        "default":
        {
          //本动画相关字段,可在此添加额外字段
          bool: true,
          Execute: function()
          {
            if (!self.animation["default"].bool) { return; }
            var inSelf = this;
            //动画具体执行代码
          }
        }
        //可在此添加额外动画
      }
      self.Draw = function()
      {
        canvas2D.save();
        self.animator.Execute();
        canvas2D.translate(self.x, self.y);
        canvas2D.rotate(self.angle);
        FrameExecute();
        canvas2D.drawImage(image,frame.x,frame.y,frame.width,frame.height,-self.width / 2, -self.height / 2, self.width, self.height);
        canvas2D.restore();
      }
      //帧动画相关
      var frames = self.artist["default"];
      var frame = frames[0];
      var frameTime = 100;
      var addFrame = 0;
      var frameIndex = 0;
      function FrameExecute()
      {
        if(frameTime == -1){return;}
        if(addFrame >= frameTime)
        {
          addFrame = 0;
          if(frameIndex == frames.length-1){ frameIndex = 0; }else{ frameIndex++; }
          frame = frames[frameIndex];
        }
        else
        {
          addFrame += U.Time.deltaTime * 1000;
        }
      }

      self.animator =
      {
        Execute: function()
        {
          for (var key in self.animation)
          {
            self.animation[key].Execute();
          }
        },
        //改变动画状态
        SetBool: function(behavior, bool)
        {
          self.animation[behavior].bool = bool;
        },
        //改变显示的帧动画
        ChangeArtist : function(name,time)
        {
          frames = self.artist[name];
          frame = frames[0];
          frameTime = time;
        }
      }
      //实例化时需要调用此方法将此物体加入到游戏中
      self.Add = function()
      {
        self.animator.ChangeArtist("default",-1);
        if(self.collisionType.length != 0)
        {
          CollisionInsert(self);
        }
        Z_IndexInset(self);
      }
      //在游戏中删除此物体
      self.Destroy = function()
      {
        for(var i in drawList)
        {
          if(drawList[i] === self)
          {
            drawList.splice(i,1);
            break;
          }
        }
        for(var i in collisionList)
        {
          if(collisionList[i] === self)
          {
            collisionList.splice(i,1);
            break;
          }
        }
      }
    }

    //时间类
    function TimeClass()
    {
      var init = true;
      var now = 0;
      var lastFpsTime = 0;
      var lastUpdateTime = 0;
      //每秒更新的FPS
      this.fps = 0;
      //时间增量
      this.deltaTime = 0;

      this.Update = function()
      {
        now = new Date().getTime();
        //初始化
        if (init)
        {
          init = false;
          lastFpsTime = now;
        }
        else
        {
          var offset = now - lastFpsTime;
          this.deltaTime = offset/1000;
          //每隔一秒返回一个新的FPS
          if (now - lastUpdateTime > 1000)
          {
            lastUpdateTime = now;
            this.fps = (1 / offset * 1000).toFixed(0);
          }
          lastFpsTime = now;
        }
      }
    }

    (function TimeUpdate()
    {
      U.Time.Update();
      requestAnimationFrame(TimeUpdate);
    })();
  }

  return U3D;
});

使用示例

require(["U3D"],function(U3D)
{
  var canvas = document.getElementById("canvas");
  var U = new U3D(canvas);

  function Cat(x,y,width,height)
  {
    U.Sprite.call(this,x,y,width,height,"cat.png");
    var self = this;
    self.collisionType = ["Cat"];
    self.speed = 10;
    //重写动画逻辑
    self.animation =
    {
      "default":
      {
        bool: true,
        Execute: function()
        {
          if (!self.animation["default"].bool) { return; }
          var inSelf = this;

          self.x += U.Time.deltaTime * self.speed;
        }
      }
    }
    //重写动画帧
    self.artist =
    {
      "default" : [{x:0,y:0,width:35,height:35},{x:35,y:0,width:35,height:35},{x:70,y:0,width:35,height:35}]
    }
    self.OnCollision2D = function()
    {
      self.speed = -self.speed;
    }
    self.Add();
  }


  var a = new Cat(200,50,36,36);
  //开始游戏
  U.GameUpdate();

  window.addEventListener("click",function(){a.animator.ChangeArtist("default",300)});
})
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值