火拼《俄罗斯方块》解析
一.簡介
俄羅斯方塊(Tetris, 俄文:Тетрис)是一款風靡全球的電視游戲機和掌上游戲機游戲,它由俄羅斯人阿列克謝·帕基特諾夫發明,故得此名。俄羅斯方塊的基本規則是移動、旋轉和擺放游戲自動輸出的各種方塊,使之排列成完整的一行或多行并且消除得分。由于上手簡單、老少皆宜,從而家喻戶曉,風靡世界。
?
?
二.需求分析
(完全按照QQ游戲的制作,如下圖:)
?
三.技術分析與實現
1.方塊位置定位
解決方案:建立盒子模型
由于長條的存在,所以建立一個4*4的盒子模型,任何一個方塊都會存在該盒子當中,方塊的定位就===盒子的定位。
?
2.顏色狀態的生成與保存
隨機生成顏色:
function?randomColor()?{????????//16進制方式表示顏色0-F
????????var?arrHex?=?["0",?"1",?"2",?"3",?"4",?"5",?"6",?"7",?"8",?"9",?"A",?"B",?"C",?"D",?"E",?"F"];
????????var?strHex?=?"#";
????????var?index;
????????for?(var?i?=?0;?i?<?6;?i++)?{
????????????//取得0-15之間的隨機整數
????????????index?=?Math.round(Math.random()?*?15);
????????????strHex?+=?arrHex[index];
????????}
????????return?strHex;
?}?
? ??
顏色保存:(那一個方塊的一種狀態做示例)
var?diamonds?=?new?Array();????diamonds[0]?=?{?x:?appearPosition.position.x?+?1,?y:?appearPosition.position.y,?diamondColor:?color?};
????diamonds[1]?=?{?x:?appearPosition.position.x?+?0,?y:?appearPosition.position.y?+?1,?diamondColor:?color?};
????diamonds[2]?=?{?x:?appearPosition.position.x?+?1,?y:?appearPosition.position.y?+?1,?diamondColor:?color?};
????diamonds[3]?=?{?x:?appearPosition.position.x?+?2,?y:?appearPosition.position.y?+?1,?diamondColor:?color?};
所有生成的方塊有個diamondColor屬性,用于存顏色。appearPosition.position是盒子模型的位置。
3.碰撞檢測
碰撞分兩種,一種是元素與左右墻壁和底部的碰撞,另外一種是方塊與底部方塊的接觸碰撞
a.元素與左右墻壁和底部的碰撞
??? a.1元素與底部的碰撞檢測
if?(diamonds[i].y?*?height?+?height?>=?canvasHeight)?{????????appearPosition.position.x?=?Math.round(appearPosition.position.x);
????????appearPosition.position.y?=?Math.round(appearPosition.position.y);
????????createElement();
????????breakTag?=?1;
? ?}??
?
a.2元素與左右墻壁的碰撞檢測
function?returnRightOrLeft()?{????????var?max_X?=?11;
????????for?(i?=?0;?i?<?diamonds.length;?i++)?{
????????????if?(diamonds[i].x?>?max_X)?{
????????????????max_X?=?diamonds[i].x;
????????????}
????????}
????????if?(max_X?!=?11)?appearPosition.position.x?=?appearPosition.position.x?-?(max_X?-?11);
????????var?min_X?=?0;
????????for?(i?=?0;?i?<?diamonds.length;?i++)?{
????????????if?(diamonds[i].x?<?min_X)?{
????????????????min_X?=?diamonds[i].x;
????????????}
????????}
????????if?(min_X?!=?0)?appearPosition.position.x?=?appearPosition.position.x?-?min_X;
????}
b.元素與元素碰撞檢測
//判斷下面是否有元素????for?(j?=?0;?j?<?bottomElement.length;?j++)?{
????????if?(bottomElement[j].x?==?diamonds[i].x)?{
????????????if?(Math.round(bottomElement[j].y)?==?Math.round(diamonds[i].y?+?1))?{
????????????????appearPosition.position.x?=?Math.round(appearPosition.position.x);
????????????????appearPosition.position.y?=?Math.round(appearPosition.position.y);
????????????????createElement();
????????????????breakTag?=?1;
????????????}
????????}
????}
????//判斷arrayOne是否在arrayTwo的右邊
????function?IsAtRight(arrayOne,?arrayTwo)?{
????????for?(i?=?0;?i?<?arrayOne.length;?i++)?{
????????????for?(j?=?0;?j?<?arrayTwo.length;?j++)?{
????????????????if?(Math.round(arrayOne[i].y)?==?Math.round(arrayTwo[j].y))?{
????????????????????if?(arrayTwo[j].x?==?arrayOne[i].x?+?1)?return?true;
????????????????}
????????????}
????????}
????????return?false;
????}
????//判D斷arrayOne是否在arrayTwo的左邊
????function?IsAtLeft(arrayOne,?arrayTwo)?{
????????for?(i?=?0;?i?<?arrayOne.length;?i++)?{
????????????for?(j?=?0;?j?<?arrayTwo.length;?j++)?{
????????????????if?(Math.round(arrayOne[i].y)?==?Math.round(arrayTwo[j].y))?{
????????????????????if?(arrayTwo[j].x?==?arrayOne[i].x?-?1)?return?true;
????????????????}
????????????}
????????}
????????return?false;
????}
4.方塊變形
var?direction?=?0;????if?(e.keyCode?==?87)?{
????????direction++;
????????direction?%=?4;
????}
W鍵是變形,0123分別代表四種。
如果是長條或者只有兩種狀態的直接? if (direction % 2 == 0) {},如果是正方塊直接忽略direction,因為它就一種形狀。
?
5.鍵盤捕獲(目前WSAD+空格,W是變形,S和空格都是加速,IE9和FF異常,建議在谷歌瀏覽器下運行)
document.onkeydown?=?function?(e)?{????????if?(e.keyCode?==?65)?{
????????????for?(i?=?0;?i?<?diamonds.length;?i++)?{
????????????????if?(diamonds[i].x?==?0)?{
????????????????????return;
????????????????}
????????????}
????????????if?(IsAtLeft(diamonds,?bottomElement))?{
????????????????return;
????????????}
????????????appearPosition.position.x?-=?1;
????????}
????????if?(e.keyCode?==?87)?{
????????????direction++;
????????????direction?%=?4;
????????}
????????if?(e.keyCode?==?68)?{
????????????for?(i?=?0;?i?<?diamonds.length;?i++)?{
????????????????if?(diamonds[i].x?==?11)?{
????????????????????return;
????????????????}
????????????}
????????????if?(IsAtRight(diamonds,?bottomElement))?{
????????????????return;
????????????}
????????????appearPosition.position.x?+=?1;
????????}
????????if?(e.keyCode?==?32)?{
????????????delay?=?1;
????????}
????????if?(e.keyCode?==?83)?{
????????????delay?=?1;
????????}
????}
????document.onkeyup?=?function?(e)?{
????????if?(e.keyCode?==?32)?{
????????????delay?=?20;
????????}
????????if?(e.keyCode?==?83)?{
????????????delay?=?20;
????????}
????}
??
6.消除加分
//一行滿了的話,消除并加分????function?clearUp()?{
????????for?(var?line?=?0;?line?<?21;?line++)?{
????????????var?count?=?0;
????????????for?(var?i?=?0;?i?<?bottomElement.length;?i++)?{
????????????????if?(bottomElement[i].y?==?line)?{
????????????????????count++;
????????????????}
????????????}
????????????if?(count?==?12)?clearByLineNum(line);
????????}
????????//?if(count==12)
????}
????function?clearByLineNum(num)?{
????????//以上的元素下降一行
????????score++;
????????var?count?=?0;
????????for?(i?=?0;?i?<?bottomElement.length;?i++)?{
????????????if?(bottomElement[i].y?==?num)?{
????????????????count++;
????????????}
????????}
????????for?(var?j?=?0;?j?<?count;?j++)?{
????????????for?(var?i?=?0;?i?<?bottomElement.length;?i++)?{
????????????????if?(bottomElement[i].y?==?num)?{
????????????????????bottomElement.splice(i,?1);
????????????????????break;
????????????????}
????????????}
????????}
????????for?(i?=?0;?i?<?bottomElement.length;?i++)?{
????????????if?(bottomElement[i].y?<?num)?{
????????????????bottomElement[i].y?+=?1;
????????????}
????????}
????} 消除加分有一個潛在的邏輯就是,在該行以上的元素的位置下降一個格子。
?
7.控制核心Jscex? Show Time
var?JropAsync?=?eval(Jscex.compile("async",?function?()?{????????var?breakTag?=?0;
????????while?(true)?{
????????????color?=?randomColor();
????????????rectBlockIndex?=?MR()?*?7?|?0;
????????????direction?=?MR()?*?3?|?0;
????????????$await(Jscex.Async.sleep(1));
????????????while?(true)?{
????????????????for?(i?=?0;?i?<?diamonds.length;?i++)?{
????????????????????if?(diamonds[i].y?*?height?+?height?>=?525)?{
????????????????????????appearPosition.position.x?=?Math.round(appearPosition.position.x);
????????????????????????appearPosition.position.y?=?Math.round(appearPosition.position.y);
????????????????????????createElement();
????????????????????????breakTag?=?1;
????????????????????}
????????????????????//判D斷?下?面?是?否?有D元a素?
????????????????????for?(j?=?0;?j?<?bottomElement.length;?j++)?{
????????????????????????if?(bottomElement[j].x?==?diamonds[i].x)?{
????????????????????????????if?(Math.round(bottomElement[j].y)?==?Math.round(diamonds[i].y?+?1))?{
????????????????????????????????appearPosition.position.x?=?Math.round(appearPosition.position.x);
????????????????????????????????appearPosition.position.y?=?Math.round(appearPosition.position.y);
????????????????????????????????createElement();
????????????????????????????????breakTag?=?1;
????????????????????????????}
????????????????????????}
????????????????????}
????????????????}
????????????????if?(breakTag?==?1)?{
????????????????????for?(i?=?0;?i?<?diamonds.length;?i++)?{
????????????????????????//alert(diamonds[i].x?+?"____"?+?diamonds[i].y)
????????????????????????bottomElement.push(diamonds[i]);
????????????????????}
????????????????????clearUp();
????????????????????//清?空?下?降μ的?元a素?
????????????????????diamonds.splice(0,?diamonds.length);
????????????????????appearPosition?=?{?position:?{?x:?4,?y:?-2?},?direction:?0?};
????????????????????breakTag?=?0;
????????????????????break;
????????????????}
????????????????appearPosition.position.y?+=?step;
????????????????draw();
????????????????$await(Jscex.Async.sleep(delay));
????????????}
????????}
????}));
這是也整個俄羅斯方塊的控制核心,由兩個while循環構成,簡單大方。
轉載于:https://www.cnblogs.com/yangmengsheng/p/6026203.html
總結
以上是生活随笔為你收集整理的火拼《俄罗斯方块》解析的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 每天学命令flipOrRotateObj
- 下一篇: 基于Simulink宽带单基地雷达系统仿