日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

Cocos2d-html5《王者之剑》实现 (1)

發(fā)布時(shí)間:2024/1/8 编程问答 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Cocos2d-html5《王者之剑》实现 (1) 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
前面,《 手把手,快速搭建 Cocos2d-HTML5 開(kāi)發(fā)調(diào)試環(huán)境》 與 《 如何自定義 Cocos2d-HTML5 Loading 界面》 兩篇文章,幫助了我們搭建了其開(kāi)發(fā)環(huán)境,并了解了 H5 ( 以下對(duì) Cocos2d-HTML5 簡(jiǎn)稱 H5,顯然,它不是 * 流感,沒(méi)那么大破壞力) 的大致加載流程,此文開(kāi)始就要使用 H5 來(lái)制作一個(gè)簡(jiǎn)單的動(dòng)作游戲 王者之劍,完成效果如下所示(所有的源碼你可以在 【 這里】查看),顯示效果可以在 【 這里】查看(請(qǐng)耐心等待加載): 這是一個(gè)簡(jiǎn)單的游戲打斗場(chǎng)景,一個(gè)英雄,一個(gè)怪物,可以控制英雄來(lái)回走動(dòng)并且攻擊,怪物實(shí)現(xiàn)簡(jiǎn)單 AI 并且自動(dòng)攻擊,有著不同的血量槽,控制系統(tǒng),可以使用觸摸,但為了操作的體驗(yàn),同樣實(shí)現(xiàn)了 鍵盤(pán)映射 ,可以使用 W、A、S、D 來(lái)控制人物的走動(dòng),J、U、I 實(shí)現(xiàn)一個(gè)普通攻擊和兩個(gè)特效攻擊。 項(xiàng)目組織 為了使項(xiàng)目的代碼結(jié)構(gòu)清晰,前期規(guī)劃好功能是必須的,先從整體看一下,項(xiàng)目的組織結(jié)構(gòu),然后會(huì)對(duì)其中內(nèi)部實(shí)現(xiàn)做些必要的解說(shuō): 如上所示, Arthur 為游戲項(xiàng)目的主目錄,與它同級(jí)的目錄,是 H5 的庫(kù)目錄,當(dāng)然截圖中,為了發(fā)布,刪除了一些不必要的文件,在 Arthut 目錄下,包含一般項(xiàng)目都包含的結(jié)構(gòu)組織。 index.html :?這是游戲的展示界面,其中包含 “gameCanvas” ,作為游戲繪制的所在,它引用加載了 cocos2d.js cocos2d.js :?項(xiàng)目初始化在這里進(jìn)行,并完成系統(tǒng)庫(kù)和項(xiàng)目源碼的 js 加載,最后將控制權(quán)交給 main.js 文件 main.js :?當(dāng) H5 庫(kù)加載完畢,執(zhí)行內(nèi)中代碼,完成項(xiàng)目資源加載,并運(yùn)行第一個(gè)場(chǎng)景 src :?此目錄包含了游戲中編寫(xiě)的 js 源代碼文件 res :?游戲所需的資源,如圖片,字體等 在這個(gè)游戲中相對(duì)復(fù)雜一點(diǎn)的就是控制系統(tǒng)了, HudLayer 中添加實(shí)現(xiàn)了 ActionButton 普通攻擊按鈕, Joypad 可觸摸 360 度 搖桿功能,和 KeyMap 游戲控制鍵盤(pán)映射方案。Characters 實(shí)現(xiàn)了人物和怪物的功能,各種動(dòng)作控制。Loading 替換了 H5 的默認(rèn)加載界面,使用了一個(gè)進(jìn)度條顯示加載進(jìn)度。GameLayer 作為游戲的主場(chǎng)景,各種游戲的流程控制在這里進(jìn)行。 360 度 可觸摸搖桿實(shí)現(xiàn) 這里的搖桿,默認(rèn)是為了觸摸實(shí)現(xiàn),之后添加的鍵盤(pán)映射,只是為了讓操作更為方便而已(在 PC 瀏覽器中),觸摸不同于搖桿的所在,就是這里的搖桿可以是 360 度以內(nèi)的任意角度,也就是可以控制任意以任意方向移動(dòng),這是鍵盤(pán)所不具備的,上下左右四個(gè)鍵,再加上每?jī)蓚€(gè)方向的組合也就八個(gè)方向。
  • var?Joypad?=?cc.Layer.extend({?
  • _winSize:?null,?
  • _pCenter:?null,?
  • _pControlSprite:?null,?
  • _pDefaultPoint:?null,?
  • ??
  • _pDefaultRotation:?null,?
  • _pRotation:?null,?
  • ??
  • _pDelegate:?null,?
  • _pKeyDown:?false,?
  • ctor:function(){?
  • ?this._super();?
  • ??
  • _winSize?=?cc.Director.getInstance().getWinSize();?
  • _pCenter?=?cc.p(_winSize.width?/?2,?_winSize.height?/?2);?
  • ??
  • ?},?
  • init:function(){?
  • ?var?bRet?=?false;?
  • ?if?(this._super()){?
  • cc.log("Joypad?init?..");?
  • ?//?控制桿所在位置?
  • ?this._pDefaultPoint?=?cc.p(110,?110);?
  • ?//?默認(rèn)旋轉(zhuǎn)角度,以使開(kāi)口正對(duì)右側(cè)?
  • ?this._pDefaultRotation?=?26;?
  • ?//?實(shí)際旋轉(zhuǎn)角度?
  • ?this._pRotation?=?0;?
  • ??
  • ?this.setPosition(this._pDefaultPoint);?
  • ??
  • ?this.addChild(cc.Sprite.create(s_Joypad1));?
  • ?this.addChild(cc.Sprite.create(s_Joypad2));?
  • ?this._pControlSprite?=?cc.Sprite.create(s_Joypad3);?
  • ?this.addChild(this._pControlSprite);?
  • ?this.addChild(cc.Sprite.create(s_Joypad4));?
  • ??
  • ?this.updateRotation();?
  • ??
  • bRet?=?true;?
  • ?}?
  • ?return?bRet;?
  • ?},?
  • keyStart:function(degrees){?
  • ?if?(this._pDelegate)?
  • ?this._pDelegate.actionJoypadStart(this._pRotation);?
  • ?},?
  • keyUpdate:function(degrees){?
  • ?this._pRotation?=?degrees;?
  • ?this.updateRotation();?
  • ?if?(this._pDelegate)?
  • ?this._pDelegate.actionJoypadUpdate(this._pRotation);?
  • ?},?
  • keyEnded:function(degrees){?
  • ?if?(this._pDelegate)?
  • ?this._pDelegate.actionJoypadEnded(this._pRotation);?
  • ?},?
  • onEnter:function(){?
  • ?this._super();?
  • cc.Director.getInstance().getTouchDispatcher().addTargetedDelegate(this,?0,?true);?
  • ?},?
  • onTouchBegan:function?(touch,?event){?
  • ?//?點(diǎn)擊點(diǎn)的范圍判斷?
  • ?var?curPoint?=?touch.getLocation();?
  • ?if?(curPoint.x?>?_winSize.width?/?2?||?curPoint.y?>?_winSize.height?/?2?){?
  • ?return?false;?
  • ?}?
  • ??
  • ?//?var?sp?=?cc.pSub(this._pDefaultPoint,?curPoint);?
  • ?//?var?angle?=?cc.pToAngle(sp);?
  • ??
  • ?this.updateTouchRotation(touch,?event);?
  • ?this.updateRotation();?
  • ?if(this._pDelegate)?
  • ?this._pDelegate.actionJoypadStart(this._pRotation);?
  • ?else?
  • cc.log('_pDelegate?is?null?...?');?
  • ??
  • ?//?cc.log("Joypad?touch?...");?
  • ?return?true;?
  • ?},?
  • onTouchMoved:function?(touch,?event){?
  • ?this.updateTouchRotation(touch,?event);?
  • ?this.updateRotation();?
  • ??
  • ?if?(this._pDelegate)?
  • ?this._pDelegate.actionJoypadUpdate(this._pRotation);?
  • ?else?
  • cc.log('_pDelegate?is?null?...?');?
  • ??
  • ?//?var?a?=?cc.pAngleSigned(?curPoint,?this._pDefaultPoint);?
  • ?//?cc.log("Joypad?touch?mvove?..."?+?rotation)?;?
  • ?},?
  • onTouchEnded:function?(touch,?event){?
  • ?this.updateTouchRotation(touch,?event);?
  • ?this.updateRotation();?
  • ?if?(this._pDelegate)?
  • ?this._pDelegate.actionJoypadEnded(this._pRotation);?
  • ?else?
  • cc.log('_pDelegate?is?null?...?');?
  • ?},?
  • updateTouchRotation:function(touch,?event){?
  • ?var?curPoint?=?touch.getLocation();?
  • ?var?sp?=?cc.pSub(curPoint,?this._pDefaultPoint);?
  • ?var?angle?=?cc.pToAngle(sp)?;//?*?-57.29577951;?
  • ?var?rotation?=?angle?*?-57.29577951;?
  • rotation?=?rotation?<?0???360?+?rotation:?rotation;?
  • ?this._pRotation?=?rotation;?
  • ?},?
  • updateRotation:function(){?
  • ?this._pControlSprite.setRotation(this._pDefaultRotation?+?this._pRotation);?
  • ?},?
  • setDelegate:function(dg){?
  • ?this._pDelegate?=?dg;?
  • ?}?
  • });?

  • 在初始化方法中,加載了搖桿資源文件,它分解成幾個(gè)組成部分,以便于很好的控制,并且保存了可旋轉(zhuǎn)元素精靈的引用this._pControlSprite,以便于隨時(shí)控制它的旋轉(zhuǎn)角度,如圖中 Joypad3.png 圖片。 以觸摸的動(dòng)作來(lái)控制動(dòng)作的執(zhí)行,Joypad 中包含了一個(gè)名為 _pDelegate 的屬性,它作為控制搖桿的代理,以通知其它 (如 人物),搖桿現(xiàn)在變動(dòng)了,分別在 onTouchBegan 中調(diào)用, this._pDelegate.actionJoypadStart(this._pRotation);,onTouchMoved?中調(diào)用 this._pDelegate.actionJoypadUpdate(this._pRotation);?和在 onTouchEnded 中調(diào)用 this._pDelegate.actionJoypadEnded(this._pRotation);。 只需要在傳入的 _pDelegate 中實(shí)現(xiàn)此三種函數(shù),就可以通過(guò)搖桿來(lái)控制其操作了,H5 使用 javascript 相比如 C++ 倒也省去了接口定義等繁雜的操作。可以看見(jiàn),在三個(gè)函數(shù)調(diào)用中,所傳入的參數(shù)為觸摸的角度,在觸摸是通知控制顯示搖桿中 “羅盤(pán)” 的旋轉(zhuǎn)。Joypad 對(duì)內(nèi)通過(guò)觸摸控制顯示,對(duì)外通過(guò)觸摸調(diào)用代理,以達(dá)到顯示和控制相一致的目的。通過(guò)觸摸的點(diǎn)相對(duì)搖桿原點(diǎn)的位置關(guān)系,很容計(jì)算出其角度。 由于這里的搖桿設(shè)計(jì)是 360 度任意角度,所以在 delegate 中傳出一個(gè)參數(shù),以標(biāo)示角度關(guān)系,如果并不需要那么復(fù)雜的控制,如前文所言,只需固定八個(gè)方向的控制,那么這里傳出的參數(shù)可以使用 枚舉 類型,代表八個(gè)不同的方向,也會(huì)使得游戲邏輯變得稍微簡(jiǎn)單。 最后可以為 Joypad 層封裝一個(gè)簡(jiǎn)單好用的調(diào)用方式:
  • Joypad.create?=?function(){?
  • ?var?joypad?=?new?Joypad();?
  • ?if?(joypad?&&?joypad.init()){?
  • ?return?joypad;?
  • ?}?
  • ?return?null;?
  • };?
  • 攻擊 與 特效攻擊 在這個(gè)游戲中,有一個(gè)普通攻擊和兩個(gè)特效攻擊,這兩個(gè)不同,但很顯然,他們都是攻擊,卻又相同,先看看他們的共同點(diǎn):
  • //?ActionButton.js?
  • ??
  • var?ActionButton?=?cc.Node.extend({?
  • _sprite:?null,?
  • _rect:?null,?
  • _delegate:?null,?
  • _attackType:?null,?
  • ??
  • _childObj:?null,?
  • rect:function(){?
  • ?var?size?=?this._sprite.getContentSize();?
  • ?return?cc.rect(-size.width?/?2,?-size.height?/?2,?size.width,?size.height);?
  • ?},?
  • setChindObj:function(obj){?
  • ?this._childObj?=?obj;?
  • ?},?
  • init:function(image){?
  • ?this._super();?
  • ??
  • ?this._sprite?=?cc.Sprite.create(image);?
  • ?this.addChild(this._sprite);?
  • ?return?true;?
  • ?},?
  • setDelegate:function(delegate){?
  • ?this._delegate?=?delegate;?
  • ?},?
  • setAttackType:function(at){?
  • ?this._attackType?=?at;?
  • ?},?
  • getAttackType:function(){?
  • ?return?this._attackType;?
  • ?},?
  • onEnter:function(){?
  • cc.Director.getInstance().getTouchDispatcher().addTargetedDelegate(this,?0,?false);?
  • ?this._super();?
  • ?},?
  • onExit:function(){?
  • cc.Director.getInstance().getTouchDispatcher().removeDelegate(this);?
  • ?this._super();?
  • ?},?
  • containsTouchLocation:function(touch){?
  • ?return?cc.rectContainsPoint(this.rect(),?this.convertTouchToNodeSpace(touch));?
  • ?},?
  • onTouchBegan:function(touch,?event){?
  • ?//?區(qū)域判斷?
  • ?if?(!this.containsTouchLocation(touch))?
  • ?return?false;?
  • ?this.click();?
  • ?//?播放點(diǎn)擊動(dòng)畫(huà)?
  • ?return?true;?
  • ?},?
  • click:function(){?
  • ?if(this._delegate?&&?this._childObj.isCanClick()){?
  • ?this._delegate.attackButtonClick(this.getAttackType());?
  • ?this.beganAnimation();?
  • ?}?
  • ?},?
  • onTouchEnded:function(touch,?event){?
  • ?this.endedAnimation();?
  • ?},?
  • beganAnimation:function(){?
  • ?},?
  • endedAnimation:function(){?
  • ?},?
  • isCanClick:function(){?
  • ?return?true;?
  • ?}?
  • });?
  • 定義了一個(gè) ActionButton 攻擊按鈕類型,它實(shí)現(xiàn)了 onTouchBegan 作為按鈕點(diǎn)擊的觸發(fā)場(chǎng)所,觸發(fā)了 click 事件,再由 click 處理調(diào)用代理的事件,傳出一個(gè)參數(shù),以標(biāo)示攻擊的類型 AttackType,在判斷點(diǎn)擊的時(shí)候還需要檢測(cè)點(diǎn)擊區(qū)域是否在按鈕的可點(diǎn)擊范圍之內(nèi),當(dāng)然再觸發(fā)攻擊動(dòng)作之時(shí),按鈕本身也實(shí)現(xiàn)了一些動(dòng)畫(huà)特效,如點(diǎn)擊效果,技能冷卻效果,它由beganAnimation 方法實(shí)現(xiàn)。 但我們看見(jiàn)在 ActionButton 并沒(méi)有實(shí)現(xiàn) beganAnimation,在方法里面并沒(méi)有實(shí)現(xiàn)任何代碼,這因?yàn)?ActionButton 只是作為 攻擊按鈕 的抽象,它只定義了攻擊按鈕具體由那些功能,能做哪些事情,如可以播放點(diǎn)擊時(shí)的動(dòng)畫(huà),但具體的動(dòng)畫(huà)內(nèi)容,需要根據(jù)具體的攻擊按鈕有著不同的實(shí)現(xiàn)。
  • var?AttackButton?=?ActionButton.extend({?
  • _pt:?null,?
  • _ac:?null,?
  • ??
  • _defaultScale:?0.35,?
  • _maxScale:?0.5,?
  • ??
  • _inAction:?null,?
  • _outAction:?null,?
  • ??
  • _timestamp:?null,?
  • ctor:function(){?
  • ?this._super();?
  • ?this._pt=?cc.Sprite.create(s_AttackO);?
  • ?this._pt.setScale(this._maxScale);?
  • ?this.setChindObj(this);?
  • ??
  • ?//?this.addChild(this._pt);?
  • ??
  • ?var?aScale?=?cc.ScaleTo.create(0.1,?this._defaultScale);?
  • ?var?aFadein?=?cc.FadeIn.create(0.1);?
  • ?this._inAction?=?cc.Spawn.create(aScale,?aFadein);?
  • ??
  • ?var?oScale?=?cc.ScaleTo.create(.2,?this._maxScale);?
  • ?var?oFade?=?cc.FadeOut.create(0.2);?
  • ?this._outAction?=?cc.Spawn.create(oScale,?oFade);?
  • ?},?
  • beganAnimation:function(){?
  • ?var?timestamp?=?(new?Date()).valueOf();?
  • ?this._timestamp?=?timestamp;?
  • ??
  • ?this.removeChild(this._pt);?
  • ?this.addChild(this._pt);?
  • ?this._pt.runAction(this._inAction);?
  • ??
  • ?},?
  • endedAnimation:function(){?
  • ?this._pt.stopAllActions();?
  • ?this._pt.runAction(this._outAction);?
  • ?},?
  • clickUp:function(){?
  • ?this.endedAnimation();?
  • ?},?
  • isCanClick:function(){?
  • ?var?timestamp?=?(new?Date()).valueOf();?
  • ?return?timestamp?-?this._timestamp?>?600;?
  • ?}?
  • });?
  • 普通攻擊按鈕的效果,初始化設(shè)置圖片素材,播放動(dòng)畫(huà)為一個(gè)光圈放大縮小顯示,它 繼承 自 ActionButton ,同樣實(shí)現(xiàn)了 beganAnimation 方法。另外一種是特效攻擊的實(shí)現(xiàn):
  • var?AttackEffect?=?ActionButton.extend({?
  • _pt:?null,?
  • _ac:?null,?
  • _isCanClick:?true,?
  • ctor:function(){?
  • ?this._super();?
  • ?var?h?=?cc.Sprite.create(s_AttackFreeze);?
  • ?this._pt?=?cc.ProgressTimer.create(h);?
  • ?this._pt.setType(cc.PROGRESS_TIMER_TYPE_RADIAL);?
  • ?this._pt.setReverseDirection(true);?
  • ?this._pt.setScale(0.43);?
  • ??
  • ?var?to?=?cc.ProgressTo.create(0,?99.999);?
  • ?var?to1?=?cc.ProgressTo.create(2,?0);?
  • ?var?ac2?=?cc.CallFunc.create(this.callBack,?this);?
  • ?this._ac?=?cc.Sequence.create(to,?to1,?ac2);?
  • ?this.setChindObj(this);?
  • ?},?
  • beganAnimation:function(){?
  • ?this.removeChild(this._pt);?
  • ?this.addChild(this._pt);?
  • ?this._pt.runAction(this._ac);?
  • ?this._isCanClick?=?false;?
  • ?},?
  • endedAnimation:function(){?
  • ?},?
  • callBack:function(){?
  • ?//?cc.log("call?back");?
  • ?this._isCanClick?=?true;?
  • ?},?
  • isCanClick:function(){?
  • ?return?this._isCanClick;?
  • ?}?
  • });?
  • 特效攻擊有個(gè)冷卻效果,不能在一定時(shí)間范圍內(nèi)連續(xù)攻擊,使用一個(gè) 旋轉(zhuǎn)的 Progress 來(lái)達(dá)到這樣的效果。

    總結(jié)

    以上是生活随笔為你收集整理的Cocos2d-html5《王者之剑》实现 (1)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

    如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。