根據(jù)微信官方對外公開的消息寞焙,微信小游戲的腳步越來越接近了储狭。它的開發(fā)者資格門檻和使用者門檻都很低互婿,以后必將引爆一波"全民開發(fā)小游戲"浪潮。
官方的開發(fā)工具創(chuàng)建項(xiàng)目即可獲取 打飛機(jī)
的源碼辽狈,這是一個很小但五臟俱全的2D游戲慈参,相信大多數(shù)嗅覺靈敏的程序員小哥哥們都已經(jīng)體驗(yàn)并且親手改造過啦。
但是如果你想借助微信的平臺刮萌,做一個交互性驮配、可玩性很強(qiáng)的 聯(lián)網(wǎng)游戲
,就有一定的難度啦着茸。不用怕壮锻,有 Bmob 的最新產(chǎn)品 游戲SDK 助力,第一波流量紅利你也能輕松抓卒汤猜绣!這次教程我們就來討論 如何在完全不懂服務(wù)器開發(fā)的情況下做一個實(shí)時聯(lián)網(wǎng)對戰(zhàn)的微信小游戲 (聯(lián)網(wǎng)飛機(jī)大戰(zhàn))。
前言
為了能通讀這篇文章敬特,你最好:
- 已經(jīng)掌握開發(fā)簡單的微信小游戲掰邢,能看懂官方
打飛機(jī)
源碼就行,甚至?xí)?Javascript
輸出HelloWorld也行 - 略懂Java伟阔,其實(shí)不懂也行辣之,在JS的基礎(chǔ)上很容易引申,主要是要有 面向?qū)ο?/strong> 的思想
下文重點(diǎn)都是講如何快速上手開發(fā) 聯(lián)網(wǎng)的微信小游戲 减俏, 但 如果你懂得一些U3D開發(fā)召烂,Bmob官方
也同時提供了 Unity3D版本的Demo+SDK
,兩者可以跨平臺互通一起玩娃承,且接口規(guī)范高度一致,基本上覆蓋市面上所有的主流終端
PS:微信小游戲怕篷、Unity3D的SDK都是 開源 的,歡迎各位糾錯
最簡單的步驟
- 獲取 比目游戲云服務(wù) (下稱
官網(wǎng)
)的賬號历筝,文章下方有獲得方式; - 在
官網(wǎng)
下載微信小游戲Demo+SDK
廊谓,導(dǎo)入到微信開發(fā)者工具
(下稱工具
)梳猪,并修改AppKey
; - 在
官網(wǎng)
配置玩家同步屬性蒸痹,并發(fā)布
下載的云端代碼
春弥,然后在官網(wǎng)
選擇一個云服務(wù)器開啟(PS:云服務(wù)器是免費(fèi)的); - 試運(yùn)行
Demo
叠荠,如果console
沒有報(bào)錯的話匿沛,點(diǎn)擊工具
的預(yù)覽
,用微信掃描二維碼榛鼎; - 現(xiàn)在逃呼,就可以在游戲內(nèi)
創(chuàng)建房間
鳖孤,體驗(yàn)電腦與手機(jī)聯(lián)網(wǎng)對戰(zhàn)啦;
接下來大概介紹一下微信小游戲項(xiàng)目開發(fā)的要點(diǎn)抡笼,云端代碼的詳解和U3D版本的教程將陸續(xù)推出
運(yùn)行效果
左邊的是 微信小游戲-開發(fā)者工具
的游戲頁面苏揣,與右邊的 Unity3D-MacOS-Editor
跨平臺玩
Demo測試運(yùn)行視頻 (B站無廣告?zhèn)魉烷T)
超清/720P模式觀看體驗(yàn)更好哦
不得不說程序員自己來做UI真的丑得可以,那個"房間"界面真的無力吐槽
目前的Demo跨平臺玩耍還有點(diǎn)小問題推姻,例如玩家平匈、怪物的移動速度不統(tǒng)一。但同平臺對戰(zhàn)是高度一致的藏古。 這個問題與SDK沒有關(guān)系增炭,都是Demo本地項(xiàng)目的參數(shù)設(shè)置,主要是因?yàn)閁nity項(xiàng)目都用的是絕對值校翔,微信小游戲項(xiàng)目都是相對值弟跑,后續(xù)Unity也采用相對值的方式,完善Demo防症。
如何從零開發(fā)
論游戲開發(fā)的經(jīng)驗(yàn)孟辑,相信各位讀者中比我厲害的人多了去了。我這里就根據(jù)我個人的開發(fā)歷程蔫敲,圍繞 聯(lián)網(wǎng)飛機(jī)大戰(zhàn)
這個項(xiàng)目饲嗽,講一下從零開發(fā)游戲的步驟吧。(嫌麻煩的可以不用看這一篇)
- 確定游戲主題奈嘿、玩法貌虾;
- 理清多個客戶端之間需要 同步的屬性、互相通知的事件裙犹;
- 分析客戶端與服務(wù)器需要 交互的事件尽狠;
- 制作/收集圖片、動畫叶圃、音效素材袄膏;
- 開發(fā)/照搬游戲世界的物理引擎,包括物體渲染掺冠、移動沉馆、碰撞檢測(以及內(nèi)存管理)等;
- 先開發(fā)服務(wù)端游戲邏輯(Java云端代碼)德崭,有利于理清整個游戲的邏輯斥黑;
- 后開發(fā)客戶端游戲邏輯、接入SDK眉厨;
- 測試锌奴、發(fā)布;
下面是展開來講 (獲取Demo缺猛、SDK完整源碼的方式見文章底部)
-
玩法:這個項(xiàng)目準(zhǔn)備做成可以容納超多人同時在線的飛機(jī)大戰(zhàn)缨叫,所有設(shè)定基本上和微信小游戲官方Demo一樣椭符,增加了幾個設(shè)定:
- 有四種造型、級別不同的Bot(有些人習(xí)慣稱為 '電腦'耻姥,也可以稱為'飛機(jī)NPC') - 第3销钝、4級的Bot可以開火,子彈(下稱Fire)飛行速度與玩家一致琐簇,4級Bot的開火頻率更高 - Bot有生命值(不再是一碰就死)蒸健,分別是2、3婉商、4似忧、4,表示可以承受的Fire攻擊次數(shù) - Player(玩家)和Bot都分為兩個陣營丈秩,陣營內(nèi)無隊(duì)友傷害 - Player的陣營由服務(wù)器隨機(jī)劃分盯捌,也可以改成玩家自己決定 - 刷怪邏輯放在云端,指定新產(chǎn)生的Bot的陣營蘑秽、位置饺著、類型 - Player受到傷害即淘汰,F(xiàn)ire碰到任何物體都消失 - Player之間肠牲、Bot之間幼衰、Player與Bot 如果發(fā)生碰撞,會同歸于盡 - Player的開火暫時做成自動的缀雳,而不是按鍵開火 - Player的開火事件(開火坐標(biāo))是直接發(fā)送到其它客戶端渡嚣,不經(jīng)過云端代碼 - Player的淘汰交由云端處理,由云端校驗(yàn)后肥印,再把該事件和勝負(fù)判定分發(fā)下去 - Bot的淘汰判定交由云端處理识椰、分發(fā) - 當(dāng)某一方Player全部死亡時,另一方勝利深碱;雙方各剩一人時同歸于盡則平局
-
客戶端間屬性同步裤唠、事件通知:玩家僅有兩個屬性需要自動同步、分發(fā)莹痢,一個是
位置
,另一個是分?jǐn)?shù)
墓赴;直接同步的事件僅有開火
- 位置:這是一個2D游戲竞膳,所以玩家位置可以用float[2]類型表達(dá) 但是為了保持一致性,Demo用了int[2]诫硕,數(shù)值由0-65535坦辟,表達(dá)0%-100% (一致性,是指跨平臺或分辨率章办、屏幕大小不同時锉走,坐標(biāo)需要達(dá)成一致最好用百分比) - 分?jǐn)?shù):僅云端代碼有權(quán)限修改滨彻,根據(jù)Player、Bot的擊落事件加分 可以在游戲結(jié)束時挪蹭,結(jié)算成經(jīng)驗(yàn)值亭饵,保存到Bmob數(shù)據(jù)庫 - 開火:直接通知到其它客戶端,僅記錄Fire的起點(diǎn)坐標(biāo)即可梁厉,也就是[0-65535,0-65535] 表達(dá)成byte[]時辜羊,一個0-65535的int可以變成兩個0-255的數(shù)字組成 再加上需要標(biāo)記這次通知的事件類型(開火),這里定flag為50 也就是開火時向其它玩家發(fā)送 [50, 0-255, 0-255, 0-255, 0-255]
-
客戶端-云端交互事件:需要服務(wù)器做的事情有:保存房間信息词顾;分配隊(duì)伍八秃;正式通知游戲開始;刷怪邏輯肉盹;判定Bot淘汰昔驱;判定Player淘汰;添加Player分?jǐn)?shù)上忍;判定勝負(fù)結(jié)果骤肛;戰(zhàn)績記錄
- 房間、戰(zhàn)績信息:通過云端代碼的Bmob數(shù)據(jù)庫操作API完成 - 分配隊(duì)伍:在客戶端Scene.OnLoad后通知服務(wù)器睡雇,服務(wù)器進(jìn)行隊(duì)伍分配 將玩家隨機(jī)萌衬、均勻分成兩隊(duì),然后下發(fā)它抱,客戶端處理完畢再通知服務(wù)器 - 正式開始:服務(wù)器確認(rèn)所有客戶端處理了隊(duì)伍信息后秕豫,通知所有客戶端開始游戲 - 刷怪邏輯:隨機(jī)Bot的陣營、x軸位置观蓄、類型混移、名字,下發(fā)給客戶端處理 - Bot淘汰:任意客戶端上報(bào)'目睹'某Bot被擊毀侮穿,云端即采信歌径、下發(fā)、記分 所謂'目睹'亲茅,就是客戶端渲染時進(jìn)行碰撞檢測回铛,發(fā)現(xiàn)這個Bot的hp為0 - Player淘汰:n個客戶端'目睹'某Player被擊毀,在短時間內(nèi)n>=m克锣,云端才采信茵肃、下發(fā)、記分 當(dāng)玩家僅有2袭祟、3人時验残,m為1,也就是上報(bào)即采信 當(dāng)玩家有4巾乳、5您没、6人時鸟召,m為2,不采信單個上報(bào) 當(dāng)玩家超過6人時氨鹏,m為3欧募,也就是起碼3人上報(bào)才采信 '短時間'目前是設(shè)為2000ms,也就是上報(bào)信息的有效期為2秒 - 判定勝負(fù)結(jié)果:兩隊(duì)最后一人同時淘汰時平局喻犁;某隊(duì)先于敵隊(duì)全員淘汰則敗
- 素材:來自美工/Unity Assets商店
-
物理引擎:來自微信官方Demo(Sprite.js)/腦洞+造輪子/第三方途徑下載
// 小改進(jìn)后的矩形碰撞檢測: isCollideWith(sp) { if (this.visible && sp.visible) { let dis = sp.x - this.x; if (-sp.width < dis && dis < this.width) { dis = sp.y - this.y; if (-sp.height < dis && dis < this.height) return true; } } return false; }
- Java云端代碼:在上面第3點(diǎn)已經(jīng)有說明槽片,這里放幾段代碼:
Room.java:
// public class Room extends RoomBase
// 保存到Bmob數(shù)據(jù)庫的id
public String mObjectId = null;
// 先分配隊(duì)伍,后開始游戲肢础。分配隊(duì)伍這段時間还栓,不是真正的游戲開始,不要刷怪
public boolean isNotReallyStart;
// 刷怪的時間間隔(毫秒)传轰,決定了刷怪的頻率剩盒,根據(jù)玩家人數(shù)來定。人越多慨蛙,刷怪越快
private long botSpawnSpan;
// 上次刷怪的時間記錄
private long lastBotSpawnTime = 0;
// 怪物的個數(shù)辽聊,也順便作為id
private long botCount = 0;
// 置信區(qū)間: 計(jì)算擊中的邏輯放到了客戶端的時候,擊中敵人/怪物的事件期贫,不能完全聽信其中一個客戶端跟匆,防止ping差異擊殺、外掛
// 怪物還相對無關(guān)緊要通砍,某一個客戶端上報(bào)了玛臂,就選擇相信他
// 但是玩家的淘汰影響到體驗(yàn),需要多個玩家同時認(rèn)證的情況下判定
// 于是約定:如果房間有2封孙、3人迹冤,可以一個人說了算(以免掉線玩家無敵)
// 如果有4個人玩游戲,需要2個人在短時間內(nèi)"看到"某個玩家的死亡虎忌,那么這個玩家才是真正的死亡了
// 更多人的情況下泡徙,最多只要3個人在短時間內(nèi)說某個玩家死亡,就可以作出判定
// 特殊的膜蠢,如果某個玩家是匯報(bào)自己死亡堪藐,那么不用經(jīng)過置信區(qū)間檢測,直接判定死亡
public int confidenceInterval = 1;
private final Set<String> dieBotsNames = new HashSet<String>();
public static final byte//
NotifyType_AssignTeam = 1,//
NotifyType_BotSpawn = 2,//
NotifyType_ReallyStart = 3,//
NotifyType_PlayerCrash = 4,//
NotifyType_BotDie = 5,//
NotifyType_GameOver = 6//
;
@Override
public void onCreate() {
// 各1個玩家的時候挑围,1秒2個怪庶橱;以此類推
// botSpawnSpan = (1000 / 2) / (playerCount / 2);
botSpawnSpan = (2000) / (playerCount / 2);
// 計(jì)算死亡判定的置信區(qū)間
if (playerCount > 3)
confidenceInterval = 2;
else if (playerCount > 5)
confidenceInterval = 3;
HttpResponse response = Bmob.getInstance().insert("Room", JSON.toJson(//
"roomId", roomId,//
"master", masterId,//
"masterKey", masterKey,//
"joinKey", joinKey,//
"playerCount", playerCount,//
"address", address,//
"tcpPort", tcpPort,//
"udpPort", udpPort,//
"websocketPort", websocketPort,//
"status", 0// 0: 開啟中,1: 游戲中贪惹,2:
// 房間關(guān)閉
));
mObjectId = response.jsonData.getString("objectId");
}
@Override
public void onGameStart() {
if (!Functions.isStrEmpty(mObjectId))
Bmob.getInstance().update("Room", mObjectId,
JSON.toJson("status", 1));
dieBotsNames.clear();
isNotReallyStart = true;
lastBotSpawnTime = 0;
botCount = 0;
}
@Override
public void onDestroy() {
if (!Functions.isStrEmpty(mObjectId))
Bmob.getInstance().update("Room", mObjectId,
JSON.toJson("status", 2));
}
@Override
@BmobGameSDKHook
public void onTick() {
if (isNotReallyStart)
return;
long curTime = getTime();
if (curTime > lastBotSpawnTime + botSpawnSpan) {
spawnBot();
lastBotSpawnTime = curTime;
}
}
// 分配隊(duì)伍
public void assignTeam() {
// 游戲開始,所有玩家就位了寂嘉,將房間內(nèi)的玩家隨機(jī)奏瞬、平均分到兩隊(duì)
// 服務(wù)器發(fā)送到客戶端的通知枫绅,就拿第一位當(dāng)作消息類型的區(qū)分吧(flag)
for (Player p : players)
p.teamId = 0;
// 如果[1]=1,表示players[0]是隊(duì)伍1; [2]=0表示players[1]是隊(duì)伍2
byte[] team = new byte[playerCount + 1];
// (flag)1表示分隊(duì)情況
team[0] = NotifyType_AssignTeam;
// 其中一個隊(duì)的人數(shù)
int team1Count = playerCount / 2;
while (team1Count != 0) {
int id = ((int) (Math.random() * 100000) % playerCount) + 1;
if (team[id] != 1) {
players[id - 1].teamId = 1;
team[id] = 1;
team1Count--;
}
}
sendToAll(team);
}
// 刷怪
private void spawnBot() {
botCount++;
// 游戲里面有4種難度不同的怪硼端,將概率按1:2:3:4來劃分并淋,越難打的怪出現(xiàn)幾率越低
// 位置(主要是x軸)隨機(jī),按byte表示珍昨,0-255县耽,表示最左邊到最右邊,128是在屏幕中鍵
// [0]表示flag镣典,這個通知是一個刷怪事件
// [1]表示隊(duì)伍代號兔毙,這個怪是哪一邊的(和assignTeam的分配一致)
// [2]表示刷怪點(diǎn)x軸的位置
// [3]表示怪物種類
// [4-]表示怪物名(Bot[Type]_[Id])
byte botTeam = (byte) (((int) (Math.random() * 100)) % 2);
byte botPositionX = (byte) (((int) (Math.random() * 0xffff)) & 0xff);
byte botType = (byte) (Math.random() * 10); // 0-9
if (botType == 9) // 9
botType = 3;
else if (botType > 6) // 7、8
botType = 2;
else if (botType > 3) // 4兄春、5澎剥、6
botType = 1;
else
botType = 0; // 0、1赶舆、2哑姚、3,默認(rèn)都是怪物0
byte[] botName = ("Bot" + botType + "_" + Long.toHexString(botCount))
.getBytes();
byte[] botInfo = new byte[4 + botName.length];
// (flag)2表示分隊(duì)情況
botInfo[0] = NotifyType_BotSpawn;
botInfo[1] = botTeam;
botInfo[2] = botPositionX;
botInfo[3] = botType;
arraycopy(botName, 0, botInfo, 4, botName.length);
sendToAll(botInfo);
}
--
Player.java:
// public class Player extends PlayerBase
public int teamId = 0;
private boolean isDead = false;
private boolean isLoadOk = false, isTeamClear = false;
private long[] dieReports;
// 不重復(fù)下發(fā)怪物死亡事件
@BmobGameSDKHook
public native void setIsDead(boolean isDead);
@Override
public void onGameStart() {
dieReports = new long[room.playerCount];
isLoadOk = false;
isDead = false;
setIsDead(isDead);
syncToClient();
}
@BmobGameSDKHook
public strictfp void onAction_OnGameLoad(byte[] bs) {
// 加載好了游戲場景
this.isLoadOk = true;
// 檢查是否全部都準(zhǔn)備好了
for (Player p : roommates)
if (!p.isLoadOk)
return;
// 開始分配隊(duì)伍
room.assignTeam();
}
@BmobGameSDKHook
public strictfp void onAction_OnTeamInfoGet(byte[] bs) {
// 收到了隊(duì)伍安排
this.isTeamClear = true;
// 檢查是否全部都準(zhǔn)備好了
for (Player p : roommates)
if (!p.isTeamClear)
return;
// 讓房間真正運(yùn)作起來
room.reallyPlaying();
}
// 有玩家上報(bào)芜茵,發(fā)現(xiàn)某一個玩家死亡
@BmobGameSDKHook
public strictfp void onAction_PlayerCrash(byte[] infos) {
if (room.isNotReallyStart || isDead)// 已經(jīng)死亡的玩家叙量,匯報(bào)不予采信
return;
// 注意,如果是敵機(jī)碰到自己九串,會發(fā)送兩條绞佩,一條說自己被對方撞死,另一條是對方被自己撞死蒸辆,這個時候都當(dāng)作是匯報(bào)自己死亡
// 0: 墜機(jī)對象的no征炼,用byte表達(dá)的話,最多兼容256人大房間
// 1: 傷害者類型(0: 敵方玩家(直接碰撞); 1: 敵方炮彈; 2: 敵方Bot)
// 2: 如果是敵方玩家直接碰撞躬贡,那么對方的no是什么
int dieNo = (int) infos[0];
if (dieNo < 0 || dieNo > room.playerCount) {// 如果是128人以上的房間谆奥,dieNo可能是-127~-1,要考慮兼容
kick(); // 不合法的上報(bào)拂玻,踢出玩家
return;
}
int murdererNo = -1;
if (infos[1] == 0) {
murdererNo = (int) infos[2];
if (murdererNo < 0 || murdererNo > room.playerCount) {
kick(); // 不合法的上報(bào)酸些,踢出玩家
return;
}
}
if (dieNo == no || murdererNo == no) {
// 給另外一個玩家添加一個死亡報(bào)告
if (dieNo == no) {
if (murdererNo != -1)
roommates[murdererNo].reportDie(this);
} else
roommates[dieNo].reportDie(this);
die();// 本玩家死亡
} else { // 觀察其它玩家的死亡
roommates[dieNo].reportDie(this);
}
}
void reportDie(Player reporter) {
if (room.isNotReallyStart || isDead) // 死豬不怕開水燙
return;
long curTime = getTime();
dieReports[reporter.no] = curTime;
int dieCount = 0;
long reportExpired = curTime - 2000;
for (long time : dieReports)
if (time > reportExpired)
dieCount++;
if (dieCount < room.confidenceInterval)
return;
die();
}
void die() {
isDead = true;
setIsDead(isDead);
syncToClient();
sendToAll(new byte[] { Room.NotifyType_PlayerCrash, (byte) no });
int[] teamAliveCounts = new int[] { 0, 0 };
String msg = String.format("Player[%d][%s] die\n", no, getUserId());
for (Player p : roommates) {
if (p.isDead) {
msg += p.no + " is dead, team " + p.teamId + "\n";
continue;
}
teamAliveCounts[p.teamId]++;
msg += p.no + " is alive, team " + p.teamId + "\n";
}
msg += String.format("team_0 has alive[%d] and team_1 is [%d]", no,
teamAliveCounts[0], teamAliveCounts[1]);
if (teamAliveCounts[0] == 0 || teamAliveCounts[1] == 0) { // 有一個隊(duì)沒人了
// 準(zhǔn)備發(fā)送GameOver, 0:平局,1:勝利檐蚜,2:失敗
byte[] toTeam0 = new byte[] { Room.NotifyType_GameOver, 0 }, //
toTeam1 = new byte[] { Room.NotifyType_GameOver, 0 };
if (teamAliveCounts[0] == teamAliveCounts[1]) {// 都沒人了
} else if (teamAliveCounts[0] == 0) { // 隊(duì)伍1勝利
toTeam0[1] = 2;
toTeam1[1] = 1;
} else {
toTeam0[1] = 1;
toTeam1[1] = 2;
}
for (Player p : roommates)
p.send(p.teamId == 0 ? toTeam0 : toTeam1);
room.gameOver(); // 游戲結(jié)束
}
}
// 有玩家上報(bào)魄懂,怪物死亡
@BmobGameSDKHook
public strictfp void onAction_BotDie(byte[] infos) { // 暫時放怪物名
if (room.isNotReallyStart)
return;
// cn.bmob.gamesdk.server.Main.l("BotDie: (" +
// java.util.Arrays.toString(infos) + ") : " + infos.length);
if (room.isBotDieNow(new String(infos))) {// 不重復(fù)的
byte[] sendInfos = new byte[1 + infos.length];
sendInfos[0] = Room.NotifyType_BotDie;
arraycopy(infos, 0, sendInfos, 1, infos.length);
sendToAll(sendInfos);
}
}
// 游戲中掉線,當(dāng)作死亡
@Override
public void onOffline() {
if (room.isNotReallyStart)
return;
die();
}
// 游戲中離開房間闯第,當(dāng)作死亡
@Override
public void onLeave() {
if (room.isNotReallyStart)
return;
die();
}
-
接入SDK:
// game.js // 根據(jù)屏幕大小來定玩家的大小, 我們定玩家如果需要穿過整個y軸最少需要2秒市栗,怪物需要8秒 const PlayerMaxSpeed = screenHeight / 2000; // px per sec const BotSpeed = screenHeight / 8000; // px per sec const EnemyFireSpeed = screenHeight / 3000; // px per sec const FriendFireSpeed = -EnemyFireSpeed; // 其它玩家更新屬性 onOthersStatus(no, changedAttr, hisStatus) { if (changedAttr.position) { let y = hisStatus.position[1]; let gameObj = this.players[no].gameObject; if (gameObj.isTeammate) y = 65535 - y; gameObj.x = hisStatus.position[0] / WidthRatio - PlayerWidth / 2; gameObj.y = y / HeightRatio - PlayerHeight / 2; } } // 其它玩家發(fā)送事件 onTransfer(no, body) { switch (body.shift()) { case 50: console.log('Fire from: ', this.players[no]); let isTeammate = this.players[no].gameObject.isTeammate, x = (body[0] << 8) | body[1], y = (body[2] << 8) | body[3]; if (isTeammate) y = 65535 - y; let fire = new Sprite( isTeammate ? ImgSrc_Fire_Friend : ImgSrc_Fire_Enemy, FireWidth, FireHeight, x / WidthRatio, y / HeightRatio ); fire.objType = 3; // 0: sundries; 1: player; 2: bot; 3: fire fire.velocity = isTeammate ? FriendFireSpeed : EnemyFireSpeed; fire.teamId = isTeammate ? this.mTeamId : (1 - this.mTeamId); this.gameObjArr.push(fire); break; } } // 云端通知 onCloudNotify(notify) { switch (notify.shift()) { case NotifyType_AssignTeam: this.assignTeam(notify); break; case NotifyType_BotSpawn: this.botSpawn( notify[0] == this.mTeamId, (notify[1]) * screenWidth / 255, notify[2], model.bytesToString(notify, 3, notify.length) ); break; case NotifyType_ReallyStart: this.startGame(); break; case NotifyType_PlayerCrash: this.renderPlayerDie(notify[0]); break; case NotifyType_BotDie: this.botDie(model.bytesToString(notify, 0, notify.length)); break; case NotifyType_GameOver: this.isGameStart = false; switch (notify[0]) { case 0: this.gameDraw(); break; case 1: this.gameWin(); break; case 2: this.gameLose(); break; } break; } }
測試、發(fā)布:灰常好玩,下階段準(zhǔn)備做成四個陣營的玩法
開發(fā)體驗(yàn)
在基本素材填帽、組件(物理引擎)等預(yù)備充分的情況下蛛淋,花了不到兩個小時就將一個單機(jī)游戲改造成了聯(lián)網(wǎng)對戰(zhàn)的游戲,而且邏輯也足夠健壯篡腌,效果還是很酷的褐荷。再加上SDK是開源的,有什么問題很容易定位嘹悼。
總體來講叛甫,Bmob Game SDK真正拉低了網(wǎng)絡(luò)游戲開發(fā)的門檻,完全沒有了以前龐大杨伙、繁雜的后端開發(fā)和服務(wù)器運(yùn)維工作其监,讓很多受限于資源、只能開發(fā)單機(jī)游戲的團(tuán)隊(duì)和項(xiàng)目有了新的出路~
獲取Demo缀台、SDK完整源碼的方式:
加官方客服棠赛,小小琪QQ:2967459363
官方Q群:726133616
其他教程
落地成盒?Bmob幫你開發(fā)自己的聯(lián)網(wǎng)"吃雞"游戲