游戏开发常用算法

游戏开发常用算法2007-01-22 10:47

■■■对象数组   
比如要构建一个有很多属性的数组,简单的可以这样做:  
2004 代码:  
var a:Array = new Array();   
for (var i = 0; i<10; i++) {   
a[i] = new Object();   
a[i].x = 10;   
a[i].y = 10*i;   
a[i].name = "---";   
a[i].id = i;   
// 随便你给什么属性啊。   
}   
先用局部变量存储对象会更好一点。  
var a=new Array()  
for(var i=0;i<10;i++){  
var ta=new Object();  
ta.x=10;  
ta.y=10;  
ta.name="n"+i;  
a.push(ta);  
}  
或者更简便一点的方法:  
var a=new Array()  
for(var i=0;i<10;i++){  
a[i]={x:10,y:10,name:"n"+i}  
}  


■■■程序控制角色运动   
下面这段代码控制 MovieClip mc 从 (50,50) 横向运动到(100,50) 停止,速度为 5 pixel:  
mc._x = mc._y=50;   
mc.onEnterFrame = function() {   
_x += 5;   
trace(_x);   
if (_x == 100) {   
delete (mc.onEnterFrame);   
}   
};   


■■■精确计时   
我们设定了时间为 60 秒,然后通过 setInterval 来定期(每1000milliseconds)触发一个函数 runTimer。  
function runTimer 用来计时,当时间到了以后,转去执行 outThere。  
function outThere 用来处理时间到了以后的动作,不要忘记 clearInterval(intervalID),停止计时。  
var time:Number = 60;   
var intervalID:Number;   
intervalID = setInterval(runTimer, 1000);   
function runTimer() {   
time--;   
trace(time);   
if (time == 0) {   
outThere();   
}   
}   
function outThere() {   
// blah blah blah   
clearInterval(intervalID);   
}   


■■■找到目前最小的一个可用的深度 Depth(来自国外)   
针对 Flash Player 6 的:  
availTopDepth = function () {   
var allDepths = [];   
for (var z in _root) {   
if (_root[z] instanceof Button || _root[z] instanceof MovieClip || _root[z] instanceof TextField) {   
allDepths.push(_root[z].getDepth());   
}   
}   
if (allDepths.length != 0) {   
sortAll = function (a, b) { if (ab) {return 1;} else {return 0;}};   
allDepths.sort(sortAll);   
return (parseInt(allDepths[allDepths.length-1])+1);   
}   
};   
trace(_root.availTopDepth());   
放置一个 MovieClip 在 Stage,再执行这段 Action 就会得到最近的一个可用深度。我们也可以用这个来创建绝对不  

会出问题的 MovieClip,比如:  
_root.createEmptyMovieClip("mc_name", availTopDepth());  
getNextHighestDepth() 以及 getInstanceAtDepth(depth)是 for player 7 的。  


■■■鼠标消隐  
鼠标消隐之后,右健弹出菜单,鼠标就又出现了,并且一直保留着~  
完整的解决方法是:在 左健抬起、右健第二次抬起、回车键抬起的时候再次消隐鼠标。  
完整的方法比较复杂,下面是一个简单的解决方法,可以解决绝大多数的问题:  
onEnterFrame=function(){  
if(Key.isDown(1)|| Key.isDown(Key.ENTER)){  
Mouse.hide();  
}  
}  


■■■我常用的一个加速度移动的代码  
//以下代码放到主场景第一帧  
stop();  
_global.a = 5;  
//移动加速度,越大越慢  
_global.click_x = 0;  
//用来记录点击鼠标的位置  
_global.click_y = 0;  
_root.onMouseDown = function() {  
_global.click_x = _root._xmouse;  
_global.click_y = _root._ymouse;  
//me是受控mc的instance name  
me.onEnterFrame = function() {  
if (Math.abs(_global.click_x-me._x)<2 && Math.abs(_global.click_y-me._y)<2) {  
//如果已经基本移到了鼠标点过的位置就取消这个事件句柄的响应程序  
delete (this.onEnterFrame);  
return;  
} else {  
//控制移动
me._x += (_global.click_x-me._x)/_global.a;  
me._y += (_global.click_y-me._y)/_global.a;  
}  
};  
};  
//以下部分可选  
//a_v是个可以输入的文本框,用来输入加速度,即可以自定义速度,方便调试  
a_v.onChanged = function() {  
if (a_v.text == "" || Number(a_v.text)>1000 || Number(a_v.text)<0) {  
//default value  
a_v.text = 5;  
} else {  
_global.a = Number(a_v.text) ? Number(a_v.text) : 5;  
//trace(_global.a);  
}  
};  


■■■随机输出1到100而不从复的语句~~~   
seq = new Array(100);  
pArray = new Array(100);  
function makeRandom() {  
for (i=1; i<=100; i++) {  
seq[i] = "A";  
}  
}  
function mRandom() {  
while (true) {  
n = int(random(100))+1;  
if (seq[n] == "A") {  
seq[n] = "0";  
break;  
}  
}  
return (n);  
}  
function rArray() {  
for (i=1; i<=100; i++) {  
pArray[i] = mRandom();  
trace(pArray[i]);  
}  
}  
stop();  


■■■偷梁换柱~~~   
我们可以用这样一个技巧,在某些函数外部加一些东西而不需要了解函数的代码~~  
比如,假如当前有很多mc 覆盖了onEnterFrame函数,我们可以这样了解那些在_root下的mc 的onEnterFrame函  

数是以什么顺序执行的:  
代码:  
for(var i in _root){  
if(_root[i].onEnterFrame != null){//如果这个Object实现了onEnterFrame接口的话  
_root[i].oldFunc = _root[i].onEnterFrame;//首先保存原来的onEnterFrame的句柄  
_root[i].onEnterFrame = function(){//然后开始替换了~~加上一层壳~~  
trace(this+ ": onEnterFrame Called.");  
this.oldFunc();//我们用保留的句柄调用原来的函数  
trace(this+ ": onEnterFrame Returned.");  
}  
}  
}  
如果要取消这些附加的操作:  
代码:  
for(var i in _root){  
if(_root[i].oldFunc!= null){//如果发现改过得痕迹  
_root[i].onEnterFrame = _root[i].oldFunc;  
delete(oldFunc);  
}  
}  
呵呵这些操作的关键在于 flash里面的引用机制:  
所有函数名都是引用,而函数本身是浮在数据的海洋里面的。如果没有任何变量引用他,他就会被回收。如果有,  

他就不会被回收。所以有着样一个有趣的事情:delete函数不会删掉任何东西,除了要求删掉的那个名字:(和java  

机制相似,而和C不同)  

a= function(){trace("Function a called");}  
b=a;  
delete(a);//除了a这个名字被删掉以外,没有任何事情发生  
b();  

函数通过this得到其调用者的实例。  


■■■MovieClipPlus.as  
定义了一些简单的MC操作  
//画点:由于flash没有画点,那我们就画短线  
MovieClip.prototype.point = OxMovieClipPoint;  
function OxMovieClipPoint(x, y) {  
this.moveTo(x, y);  
this.lineTo(x+1, y);  
}  
//画矩形,左上角x1,y1 右下角x2,y2, 颜色rgb, 不透明度alpha  
MovieClip.prototype.rect = OxMovieClipRect;  
function OxMovieClipRect(x1, y1, x2, y2, rgb, alpha) {  
this.beginFill(rgb, alpha);  
this.moveTo(x1, y1);  
this.lineTo(x1, y2);  
this.lineTo(x2, y2);  
this.lineTo(x2, y1);  
this.lineTo(x1, y1);  
this.endFill();  
}  
//画圆:这么bt的冬冬当然不是我写的,作者素Jody Keating  
//圆心x,y ,半径r  
MovieClip.prototype.circle = OxMovieClipCircle;  
function OxMovieClipCircle(x, y, r) {  
var a = r*0.414213562;  
var b = r*0.707106781;  
this.moveTo(x+r, y);  
this.curveTo(x+r, y-a, x+b, y-b);  
this.curveTo(x+a, y-r, x, y-r);  
this.curveTo(x-a, y-r, x-b, y-b);  
this.curveTo(x-r, y-a, x-r, y);  
this.curveTo(x-r, y+a, x-b, y+b);
this.curveTo(x-a, y+r, x, y+r);  
this.curveTo(x+a, y+r, x+b, y+b);  
this.curveTo(x+r, y+a, x+r, y);  
}  


■■■两点间的直线移动  
var s = 15;  
_root.onMouseDown = function() {  
var oldM_x = _root._xmouse;  
var oldM_y = _root._ymouse;  
ax = aa._x;  
ay = aa._y;  
dis = Math.sqrt((oldM_x-ax)*(oldM_x-ax)+(oldM_y-ay)*(oldM_y-ay));  
xa = (oldM_x-ax)/dis;  
ya = (oldM_y-ay)/dis;  
amove();  
};  
function amove() {  
onEnterFrame = function () {  
aa._x += s*xa;  
aa._y += s*ya;  
if (Math.sqrt((aa._x-ax)*(aa._x-ax)+(aa._y-ay)*(aa._y-ay))>dis) {  
delete onEnterFrame;  
}  
};  
}  


■■■计算两个对象之间/两点之间的距离(注册点)  
function getDistanceOf(target1, target2, x2, y2) {  
if (arguments.length == 4) {  
dx = x2-target1;  
dy = y2-target2;  
} else if (arguments.length == 2) {  
dx = target2._x-target1._x;  
dy = target2._y-target1._y;  
}  
return Math.sqrt(dx*dx+dy*dy);  
}  
//Arguments 对象是一个数组,其中包含作为参数传递给任何函数的值。每次在动作脚本中调用函数时,都会为该函  

数自动创建 Arguments 对象。同时还会创建一个局部变量 arguments,使您可引用 arguments 对象。  

■■■让播放的MC暂停一段时间   
function pausePlay(sec) {   
pfunc = function () {   
this.play();   
clearInterval(this.pint);   
}   
stop();   
this.pint = setInterval(this, "pfunc", sec*1000);   
}   
//这样调用.sec是暂停的时间,单位是秒.   
pausePlay(2);   


■■■onHitTest(target),自己写的一个MC事件,当该MC与指定的MC hitTest的时候触发事件.其实也没什么特别的地方,一样也是用setInterval来实现  
stop();   
MovieClip.prototype.listen = function(target) {   
if (this.isHiting == undefined) {   
this.isHiting = this.hitTest(target);   
}   
if (this.hitTest(target)) {   
if (this.isHiting == false) {   
this.broadcastMessage("onHitTest", this, target);//广播事件,给事件传递this和target两个参数   
}   
this.isHiting = true;   
} else {   
this.isHiting = false;   
}   
};//为MovieClip添加域成员listen成员,用于监视当前对象与目标是否碰撞   
MovieClip.prototype.watch = function(target) {   
this.timer = setInterval(this, "listen", 50, target);   
};//以每50毫秒检测一次的速度来检测是否碰撞   
MovieClip.prototype.unWatch = function() {   
clearInterval(this.timer);   
};//停止对对象的监视   
ASBroadcaster.initialize(MovieClip.prototype);//初始化MovieClip原型为事件源   

//下面是调用的示例   

//假设有两个MovieClip,左边ball,右边wall,让ball不断往wall移动,同时监视wall,一旦击中触发事件onHitTest   

ball.onEnterFrame = function() {   
this._x += 5;   
};//让ball不断往右方移动工   
myListener = new Object();   
myListener.onHitTest = function(source,target){   
trace("The " + source._name + " hit " + target._name + ".");   
};   
ball.addListener(myListener);//创建监听员并注册给ball   
ball.watch(wall);//让ball监视wall

■■■发点缓动函数  
Math.linearTween = function(t, b, c, d) {  
return c*t/d+b;  
};  
//线性运动函数  
Math.easeInQuad = function(t, b, c, d) {  
return c*(t /= d)*t+b;  
};  
//二次缓入函数  
Math.easeOutQuad = function(t, b, c, d) {  
return -c*(t /= d)*(t-2)+b;  
};  
//二次缓出函数  
Math.easeINOutQuad = function(t, b, c, d) {  
if ((t /= d/2)<1) {  
return c/2*t*t+b;  
}  
return -c/2*((--t)*(t-2)-1)+b;  
};  
//二次缓入缓出函数  
Math.easeInCubic = function(t, b, c, d) {  
return c*Math.pow(t/d, 3)+b;  
};  
//三次缓入函数  
Math.easeOutCubic = function(t, b, c, d) {  
return c*(Math.pow(t/d-1, 3)+1)+b;  
};  
//三次缓出函数  
Math.easeINOutCubic = function(t, b, c, d) {  
if ((t /= d/2)<1) {  
return c/2*Math.pow(t, 3)+b;  
}  
return c/2*(Math.pow(t-2, 3)+2)+b;  
};  
//三次缓入缓出函数  
Math.easeInQuart = function(t, b, c, d) {  
return c*Math.pow(t/d, 4)+b;  
};  
//四次缓入函数  
Math.easeOutQuart = function(t, b, c, d) {  
return -c*(Math.pow(t/d-1, 4)-1)+b;  
};  
//四次缓出函数  
Math.easeINOutQuart = function(t, b, c, d) {  
if ((t /= d/2)<1) {  
return c/2*Math.pow(t, 4)+b;  
}  
return -c/2*(Math.pow(t-2, 4)-2)+b;  
};  
//四次缓入缓出函数  
Math.easeInQuint = function(t, b, c, d) {  
return c*Math.pow(t/d, 5)+b;  
};  
//五次缓入函数  
Math.easeOutQuint = function(t, b, c, d) {  
return c*(Math.pow(t/d-1, 5)+1)+b;  
};  
//五次缓出函数  
Math.easeINOutQuint = function(t, b, c, d) {  
if ((t /= d/2)<1) {  
return c/2*Math.pow(t, 5)+b;  
}  
return c/2*(Math.pow(t-2, 5)+2)+b;  
};  
//五次缓入缓出函数  
Math.easeInSine = function(t, b, c, d) {  
return c*(1-Math.cos(t/d*(Math.PI/2)))+b;  
};  
//正弦缓出函数  
Math.easeOutSine = function(t, b, c, d) {  
return c*Math.sin(t/d*(Math.PI/2))+b;  
};  
//正弦缓出函数  
Math.easeINOutSine = function(t, b, c, d) {  
return c/2*(1-Math.cos(Math.PI*t/d))+b;  
};  
//正弦缓入缓出函数  
Math.easeInExpo = function(t, b, c, d) {  
return c*Math.pow(2, 10*(t/d-1))+b;  
};  
//指数缓入函数  
Math.easeOutExpo = function(t, b, c, d) {  
return c*(-Math.pow(2, -10*t/d)+1)+b;  
};  
//指数缓出函数  
Math.easeINOutExpo = function(t, b, c, d) {  
if ((t /= d/2)<1) {  
return c/2*Math.pow(2, 10*(t-1))+b;  
}  
return c/2*(-Math.pow(2, -10*--t)+2)+b;  
};  
//指数缓入缓出函数  
Math.easeInCirc = function(t, b, c, d) {  
return c*(1-Math.sqrt(1-(t /= d)*t))+b;  
};  
//圆形缓入函数  
Math.easeOutCirc = function(t, b, c, d) {  
return c*Math.sqrt(1-(t=t/d-1)*t)+b;  
};  
//圆形缓出函数  
Math.easeINOutCirc = function(t, b, c, d) {  
if ((t /= d/2)<1) {  
return c/2*(1-Math.sqrt(1-t*t))+b;  
}  
return c/2*(Math.sqrt(1-(t -= 2)*t)+1)+b;  
};  
//圆形缓入缓出函数  


来自:http://hi.baidu.com/ywx620/item/a2d845e10c38643a4cdcafe5


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值