碰撞檢測(cè)
像上面這個(gè),英雄可以穿墻而過,那就沒什么意思了。我們要想辦法讓英雄感受到障礙物的存在。
在第一章中,我們給每個(gè)方塊都設(shè)置了一個(gè)“walkable”屬性,當(dāng)某個(gè)位置方塊的walkable屬性是false的時(shí)候,英雄就無法穿過它。當(dāng)值為true的時(shí)候,英雄就可以從上面走過(這個(gè)東西叫做“邏輯”:)。
為了讓這個(gè)邏輯起作用,我們將會(huì)這樣做: 當(dāng)方向鍵被按下以后,我們首先檢查下一個(gè)方塊是不是可通行的。 如果是,我們就移動(dòng)英雄。如果不是,那么就忽略掉按鍵事件。
這是完美的墻的碰撞:
英雄貼著墻站著,而且下一步他就會(huì)進(jìn)到墻里面。我們不會(huì)讓它發(fā)生的。
但是這個(gè)世界總是不夠完美,要是英雄只和墻接觸一部分呢?
這就要求我們檢測(cè)英雄的全部四個(gè)角是否和墻接觸了。只要任意一個(gè)角和墻接觸(上圖中是左下角),移動(dòng)就是不合理的。
或者,英雄沒有貼著墻站,但是下一步就要跑到墻里去了,雖然只是一部分:
我們不得不讓他這樣貼著墻站著:
“這么難?!”,你也許會(huì)喊,“不太可能辦到吧?”不用擔(dān)心,實(shí)際上很簡(jiǎn)單的~
檢查四個(gè)角
我們不希望英雄的任何一部分能進(jìn)到墻里面去,只要四個(gè)角沒有進(jìn)去就行了,這是假設(shè)英雄的大體形狀是個(gè)長(zhǎng)方形(他們確實(shí)是的)。
為了實(shí)現(xiàn)這個(gè)功能,讓我們寫個(gè)函數(shù):getMyCorners function getMyCorners (x, y, ob) { ob.downY = Math.floor((y+ob.height-1)/game.tileH); ob.upY = Math.floor((y-ob.height)/game.tileH); ob.leftX = Math.floor((x-ob.width)/game.tileW); ob.rightX = Math.floor((x+ob.width-1)/game.tileW); //檢測(cè)他們是否是障礙物 ob.upleft = game["t_"+ob.upY+"_"+ob.leftX].walkable; ob.downleft = game["t_"+ob.downY+"_"+ob.leftX].walkable; ob.upright = game["t_"+ob.upY+"_"+ob.rightX].walkable; ob.downright = game["t_"+ob.downY+"_"+ob.rightX].walkable; }
這個(gè)函數(shù)接收了3個(gè)參數(shù):對(duì)象中心的x/y位置(象素值)、對(duì)象的名稱。
“等一下”,你也許會(huì)迷惑,“我們不是已經(jīng)在英雄對(duì)象中保存了他的當(dāng)前位置了嗎?”是的,但是我們當(dāng)時(shí)存的是當(dāng)前的位置,這里處理的是將要達(dá)到位置(先假定英雄可以移動(dòng))。
首先,我們根據(jù)這個(gè)x/y坐標(biāo)計(jì)算出英雄所處的方塊?赡苡⑿鄣闹行脑谝粋(gè)方塊上面,但是左上角在另外一個(gè)方塊上面,左下角又在第三個(gè)方塊中,這是有可能的。 (y+英雄的高度)/方塊高度=英雄下面的兩個(gè)角所在區(qū)塊的行值。
最后的四行使用了我們計(jì)算出的方塊的可通行性。例如,左上角使用upY行l(wèi)eftX列的方塊的walkable屬性。你可以看到,得到的四個(gè)結(jié)果(upleft、downleft、upright、downright)被保存到ob對(duì)象中了,所以我們以后還可以用到它。
我要再一次指出的是,getMyCorners函數(shù)不僅可以用在英雄上面,這里的ob也可以是任何可移動(dòng)的對(duì)象。做區(qū)塊游戲要多考慮函數(shù)的通用性,在后面的章節(jié)中你會(huì)體會(huì)到這種思想的正確性。
移動(dòng)
當(dāng)我們檢查了四個(gè)角以后,現(xiàn)在就可以很簡(jiǎn)單地移動(dòng)了:
如果4個(gè)角都是可以通行的,那么就移動(dòng),否則不移動(dòng)。但是要讓最后英雄貼著墻站著,還得多寫幾個(gè)字。修改后的moveChar函數(shù)處理4個(gè)可能的方向的移動(dòng),它看起來可能有些長(zhǎng),實(shí)際上僅僅是4段類似的代碼。讓我們看看:
function moveChar(ob, dirx, diry) { getMyCorners (ob.x, ob.y+ob.speed*diry, ob); if (diry == -1) { if (ob.upleft and ob.upright) { ob.y += ob.speed*diry; } else { ob.y = ob.ytile*game.tileH+ob.height; } } if (diry == 1) { if (ob.downleft and ob.downright) { ob.y += ob.speed*diry; } else { ob.y = (ob.ytile+1)*game.tileH-ob.height; } } getMyCorners (ob.x+ob.speed*dirx, ob.y, ob); if (dirx == -1) { if (ob.downleft and ob.upleft) { ob.x += ob.speed*dirx; } else { ob.x = ob.xtile*game.tileW+ob.width; } } if (dirx == 1) { if (ob.upright and ob.downright) { ob.x += ob.speed*dirx; } else { ob.x = (ob.xtile+1)*game.tileW-ob.width; } } ob.clip._x = ob.x; ob.clip._y = ob.y; ob.clip.gotoAndStop(dirx+diry*2+3); ob.xtile = Math.floor(ob.clip._x/game.tileW); ob.ytile = Math.floor(ob.clip._y/game.tileH); //---------下面兩行由qhwa添加-------- ob.height = ob.clip._height/2; ob.width = ob.clip._width/2; //--------------------------------- return (true); }
像以前一樣,moveChar函數(shù)通過鍵盤檢測(cè)函數(shù)傳遞過來的值得到對(duì)象和方向。 這一行: getMyCorners (ob.x, ob.y+ob.speed*diry, ob); 計(jì)算垂直移動(dòng)(當(dāng)diry不等于0時(shí))后的四個(gè)角的可行性, 隨后,通過四個(gè)角walkable的值檢查是不是合法的移動(dòng): if (diry == -1) { if (ob.upleft and ob.upright) { ob.y += ob.speed*diry; } else { ob.y = ob.ytile*game.tileH+ob.height; } }
這塊代碼是用來檢測(cè)向上的移動(dòng)的。當(dāng)上箭頭鍵被按下去后,diry的值等于-1。 我們使用了getMyCorners函數(shù)得到的ob.upleft和ob.upright值,如果他們都是true,那就意味著上面兩個(gè)角所在方塊都是可通行的,我們就給角色的y坐標(biāo)加上ob.speed*diry,讓角色朝上移動(dòng)。
但是如果這兩個(gè)角任何一個(gè)碰巧是不可通行的,即ob.upleft或者ob.upright是false, 我們就要把角色放到墻邊上。為了讓角色貼著它上面的墻,他的中心點(diǎn)必須距離當(dāng)前方塊的上邊緣char.height象素,如圖:
ob.ytile×game.tileH得到的是當(dāng)前方塊的y坐標(biāo),也就是上邊緣的y坐標(biāo),再加上角色的height值,就是正確的位置了。同樣的道理,另外三個(gè)方向的部分也可以這樣分析出來。
最后一行的把實(shí)際的mc放到計(jì)算出來的坐標(biāo)處,讓角色顯示正確的動(dòng)畫幀,并且更新角色的屬性。同以前一樣,函數(shù)返回true值。
Qhwa注:我在這里加了兩行 ob.height = ob.clip._height/2; ob.width = ob.clip._width/2;
這是因?yàn)楫?dāng)clip這個(gè)影片夾子跳轉(zhuǎn)相應(yīng)的幀后,原來的_width和_height可能會(huì)發(fā)生變化,如果還用初始化時(shí)的值,可能就會(huì)出錯(cuò)。如果英雄的高度和寬度是一樣的,就沒有必要這么做了。Tony推薦使用確定的而且相同的高度和寬度。
下載源文件
出處:藍(lán)色理想
責(zé)任編輯:qhwa
上一頁 鍵盤控制的移動(dòng) 下一頁 芝麻開門-地圖切換
◎進(jìn)入論壇Flash專欄版塊參加討論
|