模块
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)});
})