消滅星星(Popstar)遊戲是怎麼開發實現的?難不難?

玩這個遊戲最多的應該是女生和小孩了,我玩的不多!


@謝邀

這是我在知乎第二次認真回答問題,第一次給了開發一個 Flappy Bird 需要多少行代碼,多少時間?效果還不錯。首先表明我是一個代碼帝,喜歡用代碼說話,輕砸。

開發這樣的遊戲難不難,我覺得不難,玩通關比開發難多了,我一個禮拜才玩到第五關,開發兩天就夠了;

有圖有真相,我開發過

邏輯實現

基本的流程就是這樣 創建10*10隨機星星——觸摸——檢測顏色——消除星星——掉落移動——合併星星——檢測死局——結束 大概如此

代碼實現是基於js編程語言,cocos2d-x遊戲引擎實現的;

1 創建隨機單個星星,並加入單個星星掉落動畫

MainLayer.prototype.getRandomStar = function (colIndex, rowIndex) {
this.starSize = 72;
var stars = PS_MAIN_TEXTURE.STARS;
var randomStar = stars[getRandom(stars.length)];
var starSprite = cc.Sprite.createWithSpriteFrameName(randomStar);
starSprite.setAnchorPoint(cc.p(0.5, 0.5));
starSprite.setPosition(cc.p(36 + colIndex * this.starSize,
1300));
starSprite.starData = {name: randomStar, indexOfColumn: colIndex, indexOfRow: rowIndex};
starSprite.setZOrder(100);

var flowTime = rowIndex / 10;
var fallAction = cc.MoveTo.create(flowTime, cc.p(36 + colIndex * this.starSize,
36 + rowIndex * this.starSize));
starSprite.runAction(fallAction);
return starSprite;
}

2 根據表格位置初始化10*10星星群,產生星星從空中墜落的效果

MainLayer.prototype.initStarTable = function () {
this.starTable = new Array(this.numX);
for (var i = 0; i &< this.numX; i++) { var sprites = new Array(this.numY); for (var j = 0; j &< this.numY; j++) { var pSprite0 = this.getRandomStar(i, j); if (pSprite0 != null) { this.rootNode.addChild(pSprite0); } sprites[j] = pSprite0; } this.starTable[i] = sprites; } }

3 10*10星星群檢測觸摸事件,通過this.sameColorList.length可以判斷是第一次觸摸還是第二次觸摸 ;數組長度 &>1表示第二次觸摸,這裡又有分支,觸摸的是剛才同一顏色區域還是其他區域?如果是原來顏色區域,刪除this.removeSameColorStars(),如果不是原來顏色區域,恢復原狀,然後新的檢測;數組長度 &<=1表示第一次觸摸 直接檢測顏色相同區域

MainLayer.prototype.onTouchesBegan = function (touches, event) {
var loc = touches[0].getLocation();
this.ccTouchBeganPos = loc;

for (var i = 0; i &< this.starTable.length; i++) { var sprites = this.starTable[i]; for (var j = 0; j &< sprites.length; j++) { var pSprite0 = sprites[j]; if (pSprite0) { var ccRect = pSprite0.getBoundingBox(); if (isInRect(ccRect, this.ccTouchBeganPos)) { if (this.sameColorList.length &> 1) {
if (this.sameColorList.contains(pSprite0)) {
cc.AudioEngine.getInstance().playEffect(PS_MAIN_SOUNDS.broken, false);
this.removeSameColorStars();
} else {
for (var k = 0; k &< this.sameColorList.length; k++) { if (this.sameColorList[k]) { this.sameColorList[k].runAction(cc.ScaleTo.create(0.1, 1)); } } this.checkSameColorStars(pSprite0); if (this.sameColorList.length &> 1) {
cc.AudioEngine.getInstance().playEffect(PS_MAIN_SOUNDS.select, false);
}
}
} else {
this.checkSameColorStars(pSprite0);
if (this.sameColorList.length &> 1) {
cc.AudioEngine.getInstance().playEffect(PS_MAIN_SOUNDS.select, false);
}
}

break;
}
}
}
}
};

4 建立單個星星的四個方向檢測,上下左右,把顏色相同的放在一個數組裡面,回調這個數組;其實最後用這個函數的時候主要是判斷數組的大小;數組大於1,說明四周有相同顏色的;

MainLayer.prototype.checkOneStarFourSide = function (sprite) {
if (sprite == null) {
return;
}
// cc.log("checkOneStarFourSide");
var fourSideSpriteList = [];
var color = sprite.starData.color;
var col = sprite.starData.indexOfColumn;
var row = sprite.starData.indexOfRow;

//up
if (row &< 9) { var upSprite = this.starTable[col][row + 1]; if (upSprite != null upSprite.starData.color == color) { fourSideSpriteList.push(upSprite); } } //down if (row &> 0) {
var downSprite = this.starTable[col][row - 1];
if (downSprite != null downSprite.starData.color == color) {
fourSideSpriteList.push(downSprite);
}
}

//left
if (col &> 0) {
var leftSprite = this.starTable[col - 1][row];
if (leftSprite != null leftSprite.starData.color == color) {
fourSideSpriteList.push(leftSprite);
}
}

//right
if (col &< 9) { var rightSprite = this.starTable[col + 1][row]; if (rightSprite != null rightSprite.starData.color == color) { fourSideSpriteList.push(rightSprite); } } return fourSideSpriteList; }

5 檢測相同顏色區域,這裡的演算法比較複雜;有兩個數組this.sameColorList和newSameColorList,前者是全局星星數組,後者是每次擴展新加入的星星;比如這樣情況,一個星星左右上有相同的星星,上面的上面還有一個星星,總共五個相同星星:三次檢測情況是this.sameColorList為1---4----5 ,而newSameColorList為1--3--1,各種曲折,讀者好好理解下;

MainLayer.prototype.checkSameColorStars = function (sprite) {
if (sprite == null) {
return;
}
this.sameColorList = [];
this.sameColorList.push(sprite);
var newSameColorList = [];
newSameColorList.push(sprite);

//by logic ,check the same color star list
while (newSameColorList.length &> 0) {
for (var i = 0; i &< newSameColorList.length; i++) { var fourSide = this.checkOneStarFourSide(newSameColorList[i]); if (fourSide.length &> 0) {
for (var j = 0; j &< fourSide.length; j++) { if (!this.sameColorList.contains(fourSide[j])) { this.sameColorList.push(fourSide[j]); newSameColorList.push(fourSide[j]); } } } newSameColorList.splice(i, 1); } } cc.log("sameColorList length==" + this.sameColorList.length); if (this.sameColorList.length &> 1) {
for (var k = 0; k &< this.sameColorList.length; k++) { var simpleStar = this.sameColorList[k]; if (simpleStar) { simpleStar.runAction(cc.ScaleTo.create(0.1, 1.08)); } } } }

6 移除剛才選中的相同顏色的星星,併產生爆炸粒子效果

MainLayer.prototype.removeSameColorStars = function () {
for (var k = 0; k &< this.sameColorList.length; k++) { var simpleStar = this.sameColorList[k]; if (simpleStar) { var col = simpleStar.starData.indexOfColumn; var row = simpleStar.starData.indexOfRow; this.starTable[col].splice(row, 1, null); this.rootNode.removeChild(simpleStar); if (sys.platform != "browser") { var starParticle = cc.StarParticle.create(this.rootNode, (36 + col * this.starSize), (36 + row * this.starSize), "spark"); starParticle.runAction(cc.Sequence.create(cc.DelayTime.create(0.8), cc.CleanUp.create(starParticle))); } } } this.sameColorList = []; this.fallStar(); }

7 星星掉落 填充空缺,主要是如果一個地方有空缺,就把它上面的星星位置和數據交換,用到數組的方法splice,可到網上查看js數組的一些方法應用

MainLayer.prototype.fallStar = function () {
for (var i = 0; i &< this.starTable.length; i++) { var sprites = this.starTable[i]; var length = sprites.length; for (var j = 0; j &< length; j++) { var pSprite0 = sprites[j]; if (pSprite0 == null) { var k = j + 1; while (k &< length) { var upSprite = sprites[k]; if (upSprite != null) { upSprite.starData.indexOfColumn = i; upSprite.starData.indexOfRow = j; this.starTable[i].splice(j, 1, upSprite); this.starTable[i].splice(k, 1, null); k = length; var flowTime = 0.2; var fallAction = cc.MoveTo.create(flowTime, cc.p(36 + i * this.starSize, 36 + j * this.starSize)); upSprite.runAction(fallAction); } k++; } } } } this.deadStar(); // this.combineStar(); }

8 合併星星,如果最底部有空缺,星星必須向左合併,不能出現空缺

MainLayer.prototype.combineStar = function () {
for (var m = 0; m &< this.starTable.length; m++) { var mSprite0 = this.starTable[m][0]; if (mSprite0 == null) { if (m == (this.starTable.length - 1)) { for (var j = 0; j &< this.starTable[m].length; j++) { this.starTable[m].splice(j, 1, null); } } else { for (var i = (m + 1); i &< this.starTable.length; i++) { // this.starTable.splice((i - 1), 1, this.starTable[i]); for (var j = 0; j &< this.starTable[i].length; j++) { var pSprite0 = this.starTable[i][j]; this.starTable[i - 1].splice(j, 1, pSprite0); if (pSprite0 != null) { pSprite0.starData.indexOfColumn = (i - 1); var col = pSprite0.starData.indexOfColumn; var row = pSprite0.starData.indexOfRow; var moveAction = cc.MoveTo.create(0.1, cc.p(36 + col * this.starSize, 36 + row * this.starSize)); pSprite0.runAction(moveAction); } } } } } } this.deadStar(); }

9 遊戲到最後 會發生死局情況,程序自動判斷消除;這裡主要是循環檢測每一個星星,如果所有的星星四周都沒有相同星星的時候,就確認為死局,程序自動消除星星

MainLayer.prototype.deadStar = function () {
var isDead = true;
for (var i = 0; i &< this.starTable.length; i++) { var sprites = this.starTable[i]; var length = sprites.length; for (var j = 0; j &< length; j++) { var pSprite0 = sprites[j]; if (pSprite0 != null) { if (this.checkOneStarFourSide(pSprite0).length &> 0) {
isDead = false;
return;
}
}
}
}

if (isDead) {
for (var jj = 9; jj &>= 0; jj--) {
for (var ii = 0; ii &< 10; ii++) { var pSprite0 = this.starTable[ii][jj]; if (pSprite0 != null) { var delay = 4 + 0.3 * ii - 0.4 * jj; pSprite0.runAction(cc.Sequence.create( cc.DelayTime.create(delay), cc.CleanUp.create(pSprite0) )); var starParticle = cc.StarParticle.create(this.rootNode, (36 + ii * this.starSize), (36 + jj * this.starSize), "spark"); starParticle.runAction(cc.Sequence.create(cc.ScaleTo.create(0, 0), cc.DelayTime.create(delay), cc.ScaleTo.create(0, 1), cc.DelayTime.create(0.8), cc.CleanUp.create(starParticle))); } } } } }

基本就是這樣

想要源碼到我博客裡面找吧:http://blog.csdn.net/touchsnow/article/category/2094455


我身邊同事都玩過一段時間,邏輯就是永遠沒有通關分數是一個沒有盡頭的數加星星全部消完的成就感!


突然看到這個問題想回答一下,其實很多方法都可以做出來,可以用引擎寫,也可以用H5寫,或者圖形界面寫的,各種各樣方法可以達到。但這個問題讓我想起了我剛剛接觸編程的時候用純C寫出的在命令行里運行的貧民版Popstar小遊戲。

玩法一模一樣,我還加入的一些提高難度的關卡,當時剛學C語言不到一個月,跟大多數人一樣總想寫點什麼,但是其實什麼都不懂,對很多東西沒有概念。能力不夠熱情湊,查資料現學現買,最後完成一個東西,這個過程還是很有趣的。

多年過去了,再看自己原來寫的東西寫的真是爛,不過還是挺好玩的。。。

代碼就不貼了,實在是拿不出手。


我玩了一個學期,最高分玩到5萬多,然後一直沒有突破6萬


推薦閱讀:

IEEE 754格式是什麼?
Android開發和前端開發,該選擇哪個?
Minecraft開發圈內應不應該開發出降低門檻的程序?
C++求余用的「%」有與它效率相同的其它演算法嗎?
C語言中,main為什麼可以不是函數?

TAG:遊戲開發 | 編程 | Android開發 | CocosEditor | 消滅星星POPSTAR |