學習CocosCreator有段時間了,如今花了兩天時間寫了個像素鳥的小遊戲,這個遊戲以前又看到過,可是不知道怎麼又下架了,以前仍是蠻火的遊戲,想起來後去網上看了看,原來是由於侵犯了 超級瑪麗 的遊戲元素,都是像素級小遊戲,嗯,國外人的版權意識仍是挺高的。好了,題外話就到這了,開始切入正題吧。node
寫這個遊戲也不難,最主要的是思路,該怎麼去寫,我也在網上看到過 C++版 的,易語言的,Cocos2d的,都挺多的,都是大神啊web
![](http://static.javashuo.com/static/loading.gif)
我這個是Creator版的,跟Cocos2d有點差異,可是差異又不大服務器
好了,上代碼(原本是想截圖的,可是想一想仍是要對得起本身,仍是手敲吧)dom
這個遊戲我是用 ts 寫的,外加CocosCreator學習
onLoad(){動畫
// 獲取到小鳥,管道,背景,陸地的節點, 這些this的都是先在前面聲明瞭的this
// 小鳥
this.bird = cc.find('layout_wrap/node_bird', this.node)
// 背景
this.bg = cc.find('layout_wrap/layout_bg', this.node)
// 管道
this.pipe = cc.find('layout_wrap/layout_cont', this.node)
// 陸地
this.land = cc.find('layout_wrap/layout_land', this.node)
}spa
// 這裏去初始化一下,一些聲明的遊戲數據blog
private initData(): void {
this.time = 0 // 幀率(每幀調用,模擬小鳥扇動翅膀)
this.speed = 0 // 速度
this.distance = 150 // 管道距離
this.rateSpeed = 1 // 移速
this.upSpeed = 2 // 加速
this.slowSpeed = 0.06 // 減速
// 監聽運行事件
let wrap = cc.find('layout_wrap', this.node)
wrap.on(cc.Node.EventType.TOUCH_START, this.runnIng.bind(this), this)
// 開始界面
this.layoutstar = cc.find('layout_wrap/layout_star', this.node)
// 開始按鈕
this.starbtn = cc.find('layout_content/button_play', this.layoutstar)
this.addClickEvent(this.starbtn, 'onClickStar')
// 暫停按鈕
let pausebtn = cc.find('node_score/button_pause', wrap)
this.addClickEvent(pausebtn, 'onClickPause')
// 繼續按鈕
let resumebtn = cc.find('layout_pause/button_resume', wrap)
this.addClickEvent(resumebtn, 'onClickResume')
// 遊戲結束,從新開始
let again = cc.find('layout_over/node_content/button_play', wrap)
this.addClickEvent(again, 'onClickAgain')
// Get Ready提示節點
this.ready = cc.find('node_score/node_ready', wrap)
// 遊戲結束
this.gameover = cc.find('layout_over', wrap)
// 加載管道
this.addPipe()
// 碰撞系統
let manager = cc.director.getCollisionManager()
manager.enabled = true
}
//下面開始寫功能
// 點擊開始
protected onClickStar(): void {
// 縮放界面
let act = cc.callFunc(() => {
this.layoutstar.active = false
this.layoutstar.destroy()
})
// 這裏用到動做系統的縮放和漸隱,算是一點點動畫效果吧
let seq = cc.sequence(cc.spawn(cc.scaleTo(0.3, 0), cc.fadeOut(0.3)), act)
if (this.layoutstar) {
this.layoutstar.runAction(seq)
}
// 這裏是避免忘記吧結束界面沒有隱藏掉,
if (this.gameover) {
this.gameover.active = false
}
}
// 點擊運行
private runnIng(): void {
if (this.ready.active && !this.layoutstar.active) {
// 隱藏Get Ready提示節點
this.ready.active = false
// 顯示update, ison是做爲update的開關
this.ison = true
}
this.speed = 2.5 // 給小鳥一個向上的加速度
}
// 加載管道, 這裏的管道是經過預製體來加載上去的
private addPipe(): void {
this.LoadPrefabs('node_pipe', (n: cc.Node) => {
if (!n) {
return
}
for (let i = 0; i < 4; i++) {
// 複製節點
let copy = cc.instantiate(n)
// 插入節點
this.pipe.addChild(copy, i)
// 調整管道位置
copy.x = this.node.width / 2 + (this.distance + copy.width) * i
// 480~720
copy.y = (Math.random() * 0.5 + 1) * 480
if (i > 0) {
// 相鄰管道之間的差距不超過120
this.distanceY(i, i - 1)
}
}
})
}
// 移動背景
private moveBg(bgs: cc.Node): void {
bgs.x = bgs.x - 1
// 當背景移動出屏幕後,將這個背景再加到兩個背景的前面
// 像素對齊,因此bg.x爲一個確切數
if (bgs.x < -614) {
bgs.x = 1228
// 調整節點順序
if (bgs == this.bg.children[0]) {
this.bg.children[1].zIndex = 0
this.bg.children[2].zIndex = 1
this.bg.children[0].zIndex = 2
} else if (bgs == this.bg.children[1]) {
this.bg.children[2].zIndex = 0
this.bg.children[0].zIndex = 1
this.bg.children[1].zIndex = 2
} else if (bgs == this.bg.children[2]) {
this.bg.children[0].zIndex = 0
this.bg.children[1].zIndex = 1
this.bg.children[2].zIndex = 2
}
}
}
// 移動管道
private movePipe(pipes: cc.Node): void {
pipes.x = pipes.x - 2
// 當管道移動一個屏幕寬後,再將這個管道的位置改變到屏幕右側
if (pipes.x < -(pipes.width + this.node.width / 2)) {
pipes.x = 515
// 480~1000
pipes.y = (Math.random() + 1) * 520 - 40
// 相鄰管道之間的差距不超過120
if (pipes == this.pipe.children[0]) {
this.distanceY(0, 3)
} else if (pipes == this.pipe.children[1]) {
this.distanceY(1, 0)
} else if (pipes == this.pipe.children[2]) {
this.distanceY(2, 1)
} else if (pipes == this.pipe.children[3]) {
this.distanceY(3, 2)
}
}
}
// 移動陸地
private moveLand(lands: cc.Node): void {
lands.x = lands.x - 2 * this.rateSpeed
// 當陸地移動一個屏幕寬後,再將這個陸地的位置改變到屏幕右側
if (lands.x < -(this.node.width)) {
lands.x = this.node.width - 2 * this.rateSpeed
}
}
// 相鄰管道之間的Y方向差距
private distanceY(a: number, b: number): void {
if (Math.abs(this.pipe.children[a].y - this.pipe.children[b].y) > 140) {
this.pipe.children[a].y = this.pipe.children[b].y + ((Math.random() * 2 - 1) * 140)
if (this.pipe.children[a].y > 1000) {
this.pipe.children[a].y = this.pipe.children[b].y - (Math.random() * 140)
} else if (this.pipe.children[a].y < 480) {
this.pipe.children[a].y = this.pipe.children[b].y + (Math.random() * 140)
}
}
}
// 最主要的是這個思路,要造成流暢的效果,就要每幀都去調用它,
update(dt: number) {
// 終止移動
if (this.gameover.active) {
this.ison = false
}
// 幀率切換節點的顯示,模擬扇翅膀
if (this.ison) {
let timeTemp = this.time + dt
this.time = timeTemp
if (this.time > 0.5) {
if (this.bird.children[0].active) {
this.bird.children[0].active = false
this.bird.children[1].active = true
}
else if (this.bird.children[1].active) {
this.bird.children[1].active = false
this.bird.children[2].active = true
}
else if (this.bird.children[2].active) {
this.bird.children[2].active = false
this.bird.children[3].active = true
}
else if (this.bird.children[3].active) {
this.bird.children[3].active = false
this.bird.children[0].active = true
}
// 別忘了要重置爲零
this.time = 0
}
// 給定小鳥的降低減速
this.speed = this.speed - 0.06
// 小鳥在y軸上的移動
this.bird.y = this.bird.y + this.speed
// 小鳥上飛改變方向, 經過改變旋轉方向來實現小鳥的朝向
this.bird.angle = this.speed * 10
// 移動背景
this.moveBg(this.bg.children[0])
this.moveBg(this.bg.children[1])
this.moveBg(this.bg.children[2])
// 移動管道
this.movePipe(this.pipe.children[0])
this.movePipe(this.pipe.children[1])
this.movePipe(this.pipe.children[2])
this.movePipe(this.pipe.children[3])
// 移動陸地
this.moveLand(this.land.children[0])
this.moveLand(this.land.children[1])
}
}
// 這是掛載在主場景上的腳本,畫面和功能作出來了,可是若是沒有結束,那麼相信這個遊戲也不會太有趣
// 如何來結束遊戲? 那就是當小鳥裝上管道後,就結束遊戲,若是沒有,那就加分啦遊戲
// 這裏用到的是碰撞去寫的,固然也能夠去用其餘的方法去實現
// 這是掛載在小鳥的這個節點上的腳本
// 加載的時候會初始分數
onLoad() {
// 分數
this.gameMain.Score = 0
// 分數節點
this.topScore = cc.find('node_score/label_score', this.node.parent)
}
// 這裏用到的碰撞,在小鳥,管道,和中間的空隙都會綁定碰撞的組件
// 當小鳥撞在管道上,遊戲結束,
// 小鳥經過中間的空隙,加一分
onCollisionEnter(other, self) {
if (other.tag == 2) {
this.gameMain.Score++
} else if (other.tag == 1) {
this.gameOver()
}
// 顯示分數
this.topScore.getComponent(cc.Label).string = this.gameMain.Score.toString()
}
// 結束遊戲
private gameOver(): void {
// 顯示結束遊戲的界面
let gameover = cc.find('layout_over', this.node.parent)
gameover.active = true
// 漸顯
gameover.runAction(cc.fadeTo(0.5, 255))
// 分數
let scorelabel = cc.find('node_content/sprite_panel/label_score', gameover).getComponent(cc.Label)
scorelabel.string = this.gameMain.Score.toString()
// 重置分數
this.scheduleOnce(() => {
this.gameMain.Score = 0
}, 0.5)
}
好啦,一個簡單的單機像素鳥就作好了,想要更詳細的源碼的小夥伴能夠私聊我哦~~
下面放出效果圖,唉,沒有掛載服務器,沒法直接上傳到web平臺,只能放出gif啦