[QUOTE=Saitama;1084045490]Bugün Konumuzda Cocos Creator ile Online Kafa Topu ve türevleri tarzında nasıl oyun yapılır onu anlatacağım. Kaynak bana ait değildir ama bedavada değildir size sunuyorum.
Oyunun nasıl görüneceğini düşünün
Dövüş için top oyunu iyidir, bu yüzden topa vurma oyunu yapalım, ardından oyunun ana hatlarını hayal edelim:
Oyun geliştirmek için ne kullanmalı?
Oyun geliştirme bir oyun motoru kullanmalıdır, böylece cocoscreater kullanılabilir, kullanımı kolay ve belgelerle dolu
Sadece oyun geliştirmek için CocosCreater kullanın oyun Ağ Sistemi için Ne Kullanılmalı?
Her şeyden önce, ağa bağlı bir oyundur, iletişim kurabilmelidir, http kesinlikle uygun değildir, sonra websocket kullanın, ardından socket.io kullanın Bu kütüphane basit ve kullanışlıdır.
Sadece çevrimiçi Socket.io kullanın oyunun servise ihtiyacı var
Bir ön uç oyun olarak, verileri mantıksal olarak işlemek ve senkronize etmek için bir arka uç hizmetine ihtiyaç vardır, peki onu yazmak için ne kullanmalıyım? Ben de yazacağım Nodejs, bu yüzden Express'i bir oyun hizmeti olarak kullanın.
Express geliştirmeyi kullan Sunucu Olarak Ne kullanılmalı? Basit olduğu için A panel veya pagoda türevi işinizi görecektir. Oyunun birkaç sahneye ihtiyacı var
Oyun eğlenceli ve neşeli, bu yüzden çizgi film stili daha uygun, o zaman bütün bir UI tasarımına ihtiyaç var, o zaman oyunun hangi sahnelere sahip olması gerektiğini düşünmelisiniz, oyun savaşına ek olarak bir lobi olmalı , aksi takdirde savaşmak iyi olmaz ve sadece savaşlar yeterli olmaz, bu yüzden tek başına bir oyun düşünmeliyim, o yüzden bir mermi oyunu yapalım, oynamayı severim ve bir tane yapacağım, o yüzden gelirim sonuca:
Senaryolar başlıca şunları içerir:
- salon
- Savaş oyunu sahnesi
- Tek başına oyun sahnesi
Oyunun UI ekranı iyi görünüyor
Oynanışa ek olarak en önemli şey ekran.İkisi birlikte eğlenceli bir oyun oluşturuyor, bu nedenle ekran özensiz olamaz.Blue Lake Do it'i kullanın
Karakterin iyi tasarlanmış olması ve animasyona sahip olması gerekir.
Karakterin tasarlanması gerekiyor, sadece koşan durağan bir resim olamaz, bu yüzden karakteri tasarlamanın yanı sıra koşma, zıplama, topa vurma vb. animasyon?Bildiğim iskelet animasyonu resimleri kaydediyor ve yapımı ucuz.
Örnek Karakterler
Oyun bir top oyunudur, bu nedenle fiziksel etkiler olmalıdır.
Her şeyden önce bu bir top oyunudur.Top döndürülebilir,esnek ve tekmelenebilir.İvme hesabına uygundur.Daha ünlü motor daha iyi performansa sahip ve kullanımı daha kolay olan box2d olmalıdır.
Fizik motoru box2d kullanın. o zaman yapmaya başla
Ağ iletişimini kurmak için önce socket.io'yu kullanın
mount socket.io
Socket.io dosyasını çevrimiçi indirin, işte bu
Ardından, projenin altına koyun ve ardından, küresel olarak kullanılabilmesi için CDN'deki CocosCreater ön uç index.html içe aktarma dosyalarına benzer şekilde, socket.io küresel bir bileşen haline gelmesi için geliştirme aracına ayarlayın.
Socket.io'ya dayalı oyun tarafı ağ iletişim modülü geliştirin
Bir dosya oluşturun ve adlandırın gameServerve ağ servislerini bu modüle düzgün bir şekilde yazın.Kod aşağıdaki gibidir:
import * as EVENT from './event-names.js'
class Server {
//构造函数
constructor() {
if (DEBUG) {
window.SOCKET = io.connect('wss://zero2one.moderate.run:8058');
} else {
window.SOCKET = io.connect('wss://zero2one.moderate.run:8058');
}
SOCKET.on('connection', () => {
g_Log("connection ok!!!");
this.sendMsg('connected', { "openId": g_UserData.openId });
});
this.addMsgListen();
}
registerMsgCallF(callMap) {
for (let [key, value] of callMap) {
window.SOCKET.on(key, msg => {
value(msg);
});
}
}
addMsgListen() {
let self = g_GAME;
//游戏开始
window.SOCKET.on(EVENT.S_GAME_START, msg => {
g_Log("gameStart");
g_UserData.id = msg.playerId;
g_Log("g_UserData.id" + g_UserData.id)
G_CHAIRID = g_UserData.id;
g_Log("g_UserData.id" + g_UserData.id);
cc.director.preloadScene("battle", function () {
cc.director.loadScene("battle");
});
});
window.SOCKET.on(EVENT.S_LOGIN_SUCCESS, msg => {
g_Log("!!!EVENT.S_LOGIN_SUCCESS 登陆回调")
g_UserData.openId = msg.openId;
window.g_openId = g_UserData.openId;
if (!DEBUG) {
var data = WXSDK.getLaunchOptionsSync()
g_Log("loginSucess" + JSON.stringify(data.query));
if (JSON.stringify(data.query) != "{}") {
g_Log("接受挑战向服务器发请求," + data.query);
this.send_joinRoom({ "type": 1, "openid": g_openId, "matchData": data.query/* data *//* g_UserData.openId */ })
g_GAME.m_startView.switchLayerShow(LAYER.matchL);
}
}
});
window.SOCKET.on(EVENT.S_CREATE_ROOM_OK, msg => {
g_Log("create_room_ok,切换比赛界面");
if (!DEBUG) {
g_GAME.m_startView.switchLayerShow(LAYER.matchL);
WXSDK.inviteFriend(msg);
}
});
}
sendMsg(key, data = "0") {
window.SOCKET.emit(key, data)
}
/**
* 发送登陆
*/
send_login(data, ...paras) {
g_Log("发送 login");
data.msgId = EVENT.C_LOIN
this.sendMsg('GAME_MSG', data);
}
/**
* 发送创建房间
* @param {obj-数据包} data
* @param {array-其余参数} paras
* @memberof Server
*/
send_match(data, ...paras) {
data.msgId = EVENT.C_CREATE_ROOM
this.sendMsg('GAME_MSG', data);
}
/**
* 发送加入房间
*/
send_joinRoom(data, ...paras) {
g_Log("发送 join_room");
data.msgId = EVENT.C_JOIN_ROOM
this.sendMsg('GAME_MSG', data);
}
/**
* 发送左移动-开始
*/
send_leftDown(data, ...paras) {
g_Log("发送 left_down");
data.msgId = EVENT.C_LEFT_DOWN
this.sendMsg('GAME_MSG', data);
}
/**
* 发送左移动-结束
*/
send_leftUp(data, ...paras) {
g_Log("发送 left_up");
data.msgId = EVENT.C_LEFT_UP
this.sendMsg('GAME_MSG', data);
}
/**
* 发送右移动-开始
*/
send_rightDown(data, ...paras) {
g_Log("发送 right_down");
data.msgId = EVENT.C_RIGHT_DOWN
this.sendMsg('GAME_MSG', data);
}
/**
* 发送右移动-结束
*/
send_rightUp(data, ...paras) {
g_Log("发送 right_up");
data.msgId = EVENT.C_RIGHT_UP;
this.sendMsg('GAME_MSG', data);
}
/**
* 发送击球
*/
send_hit(data, ...paras) {
g_Log("发送 hit");
data.msgId = EVENT.C_HIT;
this.sendMsg('GAME_MSG', data);
}
/**
* 发送跳跃
*/
send_jump(data, ...paras) {
g_Log("发送 jump");
data.msgId = EVENT.C_JUMP;
this.sendMsg('GAME_MSG', data);
}
}
module.exports = Server;Sunucudan gelen mesajları dinleyin
//游戏开始,进入对战页面
window.SOCKET.on(EVENT.S_GAME_START, msg => {
...
});
// 登陆成功,显示大厅页面
window.SOCKET.on(EVENT.S_LOGIN_SUCCESS, msg => {
...
});
// 匹配开始,切换匹配页面
window.SOCKET.on(EVENT.S_CREATE_ROOM_OK, msg => {
...
});Arka plana mesaj göndermek için arabirimi kapsülleyin
/**
* 发送登陆
*/
send_login(data, ...paras) {
...
}
/**
* 发送创建房间
* @param {obj-数据包} data
* @param {array-其余参数} paras
* @memberof Server
*/
send_match(data, ...paras) {
...
}
/**
* 发送加入房间
*/
send_joinRoom(data, ...paras) {
...
}
/**
* 发送左移动-开始
*/
send_leftDown(data, ...paras) {
...
}
/**
* 发送左移动-结束
*/
send_leftUp(data, ...paras) {
...
}
/**
* 发送右移动-开始
*/
send_rightDown(data, ...paras) {
...
}
/**
* 发送右移动-结束
*/
send_rightUp(data, ...paras) {
...
}
/**
* 发送击球
*/
send_hit(data, ...paras) {
...
}
/**
* 发送跳跃
*/
send_jump(data, ...paras) {
...
}Bir sahne oluşturmak için CocosCreater'ı kullanın
Öncelikle sahneleri ve seviyeleri ayıralım, onları nasıl anlıyorsunuz~~~? Analoji ile anlayabilirsiniz:
- Senaryo : Ön uç yönlendirmemize benzetme.
- Hiyerarşi : Ebeveyn ve alt düğümlerin hiyerarşik yapısıdır.
Daha sonra iş göre ayrılır:
- Lobi sahnesi : esas olarak bazı oyun bilgilerinin görüntülenmesinden ve bazı sayfaların atlanmasından sorumludur. İşletme esas olarak yardım ve ayarlara odaklanır. Bağımsız oyun nispeten basit olduğundan, onu tek başına bir sahne olarak kullanmaya gerek yoktur. Görüntüleme ve gizleme arasında geçiş yaparak doğrudan bir düğüm olarak kullanılabilir.
- Savaş sahnesi : Stadyumun tamamı temel olarak fizik motoruyla inşa edilir ve iş esas olarak savaşa odaklanır.
Ardından, karşılık gelen iki sahne dosyası vardır:
Geliştirme lobisi sahnesi
Senaryo iş analizi
Salon olması gerektiği gibi görünmeli
- Savaş oyunu girişi
- Bağımsız oyun girişi
- rol seçimi girişi
- Top girişi seçmekten yoruldu
- Diğer çeşitli süslü sayfalar: başarı sayfası, eşleştirme sayfası, oyun tanıtım sayfası vb.
- Bağımsız oyun mermi topu sayfası
Ardından, sahnenin komut dosyası şu şekilde yazılabilir: Ardından, sahneyi oluşturmak için ilgili komut dosyasını oluşturun:
Ve bu sahneye monte edilmiş:
Ardından, UI düğümüne bağlanmak için değişkeni bildirin, böylece dom'u elde etmeye ve işlemleri gerçekleştirmeye benzer şekilde komut dosyasında kullanılabilir.
cc.Class({
...
properties: {
// 大厅页面
m_lobbyLayer: cc.Node,
//各个层的预制体
// 成就页面
m_achieventLayerPre: cc.Prefab,
// 角色页面
m_characterLayerPre: cc.Prefab,
// 游戏结束页面
m_endLayerPre: cc.Prefab,
// 匹配页面
m_matchLayerPre: cc.Prefab,
// 球节点
m_ballPrefab: cc.Prefab,
// 游戏玩法界面
m_gameInfoLayeyPrefab: cc.Prefab,
// 单机游戏-子弹游戏页面
m_gameBulletLayer: cc.Prefab,
}
...
})Ardından düzenleyicide karşılık gelen düğümü bağlayın:
Bu şekilde, lobi sahnesinin temel çalışması ön olarak tamamlanır ve ardından etkileşim geliştirilir. İlk olarak, komut dosyasında şöyle bir geri arama işlevi oluşturun:
onBtnClick(event, data) {
//没有这个界面就创建
if (!this.m_layerArr[data]) this.addLayer(data);
//切页面
this.switchLayerShow(data);
data in this.m_btnCallFMgr
? this.m_btnCallFMgr[data].call(this, data)
: g_Log("该按钮未配置函数");
}
}Ardından geliştirme araçlarını bağlayın
Savaş oyununun geri araması özel olarak ele alınmalıdır, çünkü bu bir savaş oyunudur, arka planın eşleşmesini istemesi ve ardından başarıdan sonra bildirmesi gerekir, bu nedenle geri arama işlevinin yalnızca gameServer modülündeki arabirimi göndermesi ve çağırması gerekir. .
...
CallF_battle(data) {
g_Log("玩家对战");
//回调消息create_room_ok
g_SERVER.send_match({
type: 1,
openid: g_openId
? g_openId
: Date.now() /* data */ /* g_UserData.openId */,
});
}
...Konu tutarsa savaş sahnesini anlatacağım şimididen teşekkürler.[/QUOTE
başarılar dilerim hocam.