遊戲中常用算法

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

■■■對象數組   
比如要構建一個有很多屬性的數組,簡單的可以這樣做:  
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;  
};  
//圓形緩入緩出函數  

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章