摘要:原文鏈接譯文來(lái)自我的博客簡(jiǎn)介如果你想用做個(gè)游戲,那么來(lái)對(duì)地方了?,F(xiàn)在可以看到字母在屏幕上移動(dòng)了,恭喜你,你已經(jīng)快入門(mén)了。
原文鏈接
譯文來(lái)自我的博客
簡(jiǎn)介如果你想用canvas做個(gè)游戲,那么來(lái)對(duì)地方了。
但是但是你至少知道javascript怎么拼寫(xiě)(╯‵□′)╯︵┻━┻
既然沒(méi)問(wèn)題,那先來(lái)玩一下或者下載
創(chuàng)建canvas標(biāo)簽廢話(huà)不多說(shuō),我們必須創(chuàng)建一個(gè)canvas標(biāo)簽,簡(jiǎn)單起見(jiàn),用一下不喜歡的jQuery
var CANVAS_WIDTH = 480; var CANVAS_HEIGHT = 320; var canvasElement = $(""); var canvas = canvasElement.get(0).getContext("2d"); canvasElement.appendTo("body");游戲循環(huán)
為了能夠讓游戲平滑動(dòng)畫(huà),我們用30幀的頻率。
var FPS = 30; setInterval(function() { update(); draw(); }, 1000/FPS);
現(xiàn)在我們可以先給這兩個(gè)函數(shù)放置play,重要的是setInterval函數(shù)會(huì)定期照顧他們的。
hello world現(xiàn)在我們有了這個(gè)循環(huán),讓我們開(kāi)始畫(huà)東西吧~
function draw() { canvas.fillStyle = "#000"; // Set color to black canvas.fillText("Sup Bro!", 50, 50); }
注意:確認(rèn)修改之后刷新一下,萬(wàn)一哪里不對(duì),代碼變的少還能看出哪里不對(duì)。
如果沒(méi)錯(cuò),那么顯示的是靜止的字母,雖然好看,但我們已經(jīng)有了動(dòng)畫(huà)循環(huán),所以我們應(yīng)該很容易讓他動(dòng)起來(lái)。
var textX = 50; var textY = 50; function update() { textX += 1; textY += 1; } function draw() { canvas.fillStyle = "#000"; canvas.fillText("Sup Bro!", textX, textY); }
現(xiàn)在如果沒(méi)出錯(cuò),那么字母應(yīng)該在移動(dòng),但是有殘影出現(xiàn)。想想為什么會(huì)這樣,因?yàn)槲覀儧](méi)有清除之前的畫(huà)面呢,so 我們加點(diǎn)清除畫(huà)布的代碼。
function draw() { canvas.clearRect(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT); canvas.fillStyle = "#000"; canvas.fillText("Sup Bro!", textX, textY); }
現(xiàn)在可以看到字母在屏幕上移動(dòng)了,恭喜你,你已經(jīng)快入門(mén)了。讓我們繼續(xù)。
創(chuàng)建玩家接下來(lái)創(chuàng)建一個(gè)物體用來(lái)給玩家控制,我們創(chuàng)建了一個(gè)簡(jiǎn)單的object:
var player = { color: "#00A", x: 220, y: 270, width: 32, height: 32, draw: function() { canvas.fillStyle = this.color; canvas.fillRect(this.x, this.y, this.width, this.height); } };
我們簡(jiǎn)單地著色了這個(gè)物體,當(dāng)我們清除畫(huà)布的時(shí)候,畫(huà)上這個(gè)物體。
function draw() { canvas.clearRect(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT); player.draw(); }鍵盤(pán)控制
使用jQuery HotKeys
使用jQuery HotKeys,這個(gè)插件提供了簡(jiǎn)單的鍵盤(pán)輸入檢測(cè)
我們可以這么綁定事件
$(document).bind("keydown", "left", function() { ... });
不用想哪個(gè)按鍵是哪個(gè)號(hào)碼真舒服,我們剛才實(shí)現(xiàn)了“當(dāng)玩家按上的時(shí)候,做一些事情”,碉堡的插件!
玩家的移動(dòng)
鍵盤(pán)輸入檢測(cè)已經(jīng)完成了,但我們還要處理鍵盤(pán)輸入之后要做什么。
你可能會(huì)想使用事件驅(qū)動(dòng)的方式去處理鍵盤(pán)輸入,但是這樣做系統(tǒng)不一,按鍵效果不一樣,而且脫離了動(dòng)畫(huà)循環(huán)呢,這樣做就可以跨系統(tǒng)了,保證了一致性,也讓游戲更平滑了。
有一個(gè)好消息,我們有一個(gè)key_status.js的文件,提供了類(lèi)似keydown.left等等。去下載的文件里找
現(xiàn)在我們可以去查詢(xún)是否有按鍵了,然后我們就這么寫(xiě):
function update() { if (keydown.left) { player.x -= 2; } if (keydown.right) { player.x += 2; } }
這樣玩家可以控制了。
你可能注意到玩家可以跑出屏幕,讓我們限制一下玩家的位置,而且似乎控制速度有點(diǎn)慢,我們順便加加速。
function update() { if (keydown.left) { player.x -= 5; } if (keydown.right) { player.x += 5; } player.x = player.x.clamp(0, CANVAS_WIDTH - player.width); }
clamp這個(gè)函數(shù)可以在下載的util.js里看到
然后我們加點(diǎn)炮彈進(jìn)去。
function update() { if (keydown.space) { player.shoot(); } if (keydown.left) { player.x -= 5; } if (keydown.right) { player.x += 5; } player.x = player.x.clamp(0, CANVAS_WIDTH - player.width); } player.shoot = function() { console.log("Pew pew"); // :) Well at least adding the key binding was easy... };添加更多物體
子彈
我們需要一個(gè)數(shù)組放子彈
var playerBullets = [];
接下來(lái)我們創(chuàng)建一個(gè)子彈原型
function Bullet(I) { I.active = true; I.xVelocity = 0; I.yVelocity = -I.speed; I.width = 3; I.height = 3; I.color = "#000"; I.inBounds = function() { return I.x >= 0 && I.x <= CANVAS_WIDTH && I.y >= 0 && I.y <= CANVAS_HEIGHT; }; I.draw = function() { canvas.fillStyle = this.color; canvas.fillRect(this.x, this.y, this.width, this.height); }; I.update = function() { I.x += I.xVelocity; I.y += I.yVelocity; I.active = I.active && I.inBounds(); }; return I; }
但玩家射擊時(shí),我們應(yīng)該實(shí)例子彈,然后添加到子彈數(shù)組中.
player.shoot = function() { var bulletPosition = this.midpoint(); playerBullets.push(Bullet({ speed: 5, x: bulletPosition.x, y: bulletPosition.y })); }; player.midpoint = function() { return { x: this.x + this.width/2, y: this.y + this.height/2 }; };
我們需要把子彈的動(dòng)畫(huà)添加到?jīng)]幀的動(dòng)畫(huà)里,為了能讓子彈變成無(wú)限的效果,我們過(guò)濾了子彈數(shù)組,只保留了激活的子彈.同時(shí)刪除了已經(jīng)撞到敵人的子彈.
function update() { ... playerBullets.forEach(function(bullet) { bullet.update(); }); playerBullets = playerBullets.filter(function(bullet) { return bullet.active; }); }
最后一步就是畫(huà)子彈了.
function draw() { ... playerBullets.forEach(function(bullet) { bullet.draw(); }); }
敵人
現(xiàn)在我們要像添加子彈一樣添加敵人.
enemies = []; function Enemy(I) { I = I || {}; I.active = true; I.age = Math.floor(Math.random() * 128); I.color = "#A2B"; I.x = CANVAS_WIDTH / 4 + Math.random() * CANVAS_WIDTH / 2; I.y = 0; I.xVelocity = 0 I.yVelocity = 2; I.width = 32; I.height = 32; I.inBounds = function() { return I.x >= 0 && I.x <= CANVAS_WIDTH && I.y >= 0 && I.y <= CANVAS_HEIGHT; }; I.draw = function() { canvas.fillStyle = this.color; canvas.fillRect(this.x, this.y, this.width, this.height); }; I.update = function() { I.x += I.xVelocity; I.y += I.yVelocity; I.xVelocity = 3 * Math.sin(I.age * Math.PI / 64); I.age++; I.active = I.active && I.inBounds(); }; return I; }; function update() { ... enemies.forEach(function(enemy) { enemy.update(); }); enemies = enemies.filter(function(enemy) { return enemy.active; }); if(Math.random() < 0.1) { enemies.push(Enemy()); } }; function draw() { ... enemies.forEach(function(enemy) { enemy.draw(); }); }加載和添加圖片
雖然目前這些方塊飛來(lái)飛去看起來(lái)很酷,但有圖片就更酷了。我們使用了一個(gè)叫sprite.js的文件,可以從下載的文件里看到。
player.sprite = Sprite("player"); player.draw = function() { this.sprite.draw(canvas, this.x, this.y); }; function Enemy(I) { ... I.sprite = Sprite("enemy"); I.draw = function() { this.sprite.draw(canvas, this.x, this.y); }; ... }碰撞檢測(cè)
我們已經(jīng)有了很多敵人飛來(lái)飛去了,但他們沒(méi)有交互呢mb打不到他們,我們是時(shí)候加點(diǎn)碰撞檢測(cè)了.
讓我們使用一個(gè)簡(jiǎn)單的方法檢測(cè):
function collides(a, b) { return a.x < b.x + b.width && a.x + a.width > b.x && a.y < b.y + b.height && a.y + a.height > b.y; }
我們需要檢測(cè)如下兩種碰撞:
玩家子彈和敵方飛船
玩家和敵方飛船
讓我們給update加入處理碰撞之后的處理
function handleCollisions() { playerBullets.forEach(function(bullet) { enemies.forEach(function(enemy) { if (collides(bullet, enemy)) { enemy.explode(); bullet.active = false; } }); }); enemies.forEach(function(enemy) { if (collides(enemy, player)) { enemy.explode(); player.explode(); } }); } function update() { ... handleCollisions(); }
現(xiàn)在我們需要給敵方飛船和玩家添加爆炸效果,爆炸的同時(shí)會(huì)移除
function Enemy(I) { ... I.explode = function() { this.active = false; // Extra Credit: Add an explosion graphic }; return I; }; player.explode = function() { this.active = false; // Extra Credit: Add an explosion graphic and then end the game };聲音
為了可玩性,我們將要添加聲音效果進(jìn)去,我們用到sound.js這個(gè)文件,讓事情變得非常簡(jiǎn)單。
player.shoot = function() { Sound.play("shoot"); ... } function Enemy(I) { ... I.explode = function() { Sound.play("explode"); ... } }
使用這些API就能很快地完成一個(gè)簡(jiǎn)單的游戲.
告別再說(shuō)一下游戲地址,也可以下載
well,我希望你開(kāi)始喜歡用js和html5寫(xiě)簡(jiǎn)單的游戲,隨著學(xué)習(xí)的深入,將來(lái)會(huì)有更多地挑戰(zhàn)呢.
參考文獻(xiàn)HTML5 Canvas Cheat Sheet
HTML5 Game EnginesSF怎么自動(dòng)讀取gist的信息。。我在SF刪了這個(gè)鏈接
第一次完整的翻譯一篇文章,真蛋疼有些句子感覺(jué)不好翻,就隨便糊弄一下,BTW,我也按這個(gè)教程寫(xiě)了例子,好像寫(xiě)完還有很多問(wèn)題呢(逃
順便吐槽一下,SF編輯器怎么沒(méi)有刪除線(xiàn),╭(╯^╰)╮
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/77932.html
摘要:全文為這些年,我曾閱讀深入理解過(guò)或正在閱讀學(xué)習(xí)即將閱讀的一些優(yōu)秀經(jīng)典前端后端書(shū)籍。當(dāng)然,如果您喜歡這篇文章,可以動(dòng)手點(diǎn)點(diǎn)贊或者收藏。 全文為這些年,我曾閱讀、深入理解過(guò)(或正在閱讀學(xué)習(xí)、即將閱讀)的一些優(yōu)秀經(jīng)典前端/Java后端書(shū)籍。全文為純?cè)瓌?chuàng),且將持續(xù)更新,未經(jīng)許可,不得進(jìn)行轉(zhuǎn)載。當(dāng)然,如果您喜歡這篇文章,可以動(dòng)手點(diǎn)點(diǎn)贊或者收藏。 基礎(chǔ) 基礎(chǔ)書(shū)籍 進(jìn)階 進(jìn)階階段,深入學(xué)習(xí)的書(shū)...
摘要:全文為這些年,我曾閱讀深入理解過(guò)或正在閱讀學(xué)習(xí)即將閱讀的一些優(yōu)秀經(jīng)典前端后端書(shū)籍。當(dāng)然,如果您喜歡這篇文章,可以動(dòng)手點(diǎn)點(diǎn)贊或者收藏。 全文為這些年,我曾閱讀、深入理解過(guò)(或正在閱讀學(xué)習(xí)、即將閱讀)的一些優(yōu)秀經(jīng)典前端/Java后端書(shū)籍。全文為純?cè)瓌?chuàng),且將持續(xù)更新,未經(jīng)許可,不得進(jìn)行轉(zhuǎn)載。當(dāng)然,如果您喜歡這篇文章,可以動(dòng)手點(diǎn)點(diǎn)贊或者收藏。 基礎(chǔ) 基礎(chǔ)書(shū)籍 進(jìn)階 進(jìn)階階段,深入學(xué)習(xí)的書(shū)...
摘要:全文為這些年,我曾閱讀深入理解過(guò)或正在閱讀學(xué)習(xí)即將閱讀的一些優(yōu)秀經(jīng)典前端后端書(shū)籍。當(dāng)然,如果您喜歡這篇文章,可以動(dòng)手點(diǎn)點(diǎn)贊或者收藏。 全文為這些年,我曾閱讀、深入理解過(guò)(或正在閱讀學(xué)習(xí)、即將閱讀)的一些優(yōu)秀經(jīng)典前端/Java后端書(shū)籍。全文為純?cè)瓌?chuàng),且將持續(xù)更新,未經(jīng)許可,不得進(jìn)行轉(zhuǎn)載。當(dāng)然,如果您喜歡這篇文章,可以動(dòng)手點(diǎn)點(diǎn)贊或者收藏。 基礎(chǔ) 基礎(chǔ)書(shū)籍 進(jìn)階 進(jìn)階階段,深入學(xué)習(xí)的書(shū)...
摘要:全文為這些年,我曾閱讀深入理解過(guò)或正在閱讀學(xué)習(xí)即將閱讀的一些優(yōu)秀經(jīng)典前端后端書(shū)籍。當(dāng)然,如果您喜歡這篇文章,可以動(dòng)手點(diǎn)點(diǎn)贊或者收藏。 全文為這些年,我曾閱讀、深入理解過(guò)(或正在閱讀學(xué)習(xí)、即將閱讀)的一些優(yōu)秀經(jīng)典前端/Java后端書(shū)籍。全文為純?cè)瓌?chuàng),且將持續(xù)更新,未經(jīng)許可,不得進(jìn)行轉(zhuǎn)載。當(dāng)然,如果您喜歡這篇文章,可以動(dòng)手點(diǎn)點(diǎn)贊或者收藏。 基礎(chǔ) 基礎(chǔ)書(shū)籍 進(jìn)階 進(jìn)階階段,深入學(xué)習(xí)的書(shū)...
摘要:正在失業(yè)中的課多周刊第期我們的微信公眾號(hào),更多精彩內(nèi)容皆在微信公眾號(hào),歡迎關(guān)注。若有幫助,請(qǐng)把課多周刊推薦給你的朋友,你的支持是我們最大的動(dòng)力。是一種禍害譯本文淺談了在中關(guān)于的不好之處。淺談超時(shí)一運(yùn)維的排查方式。 正在失業(yè)中的《課多周刊》(第3期) 我們的微信公眾號(hào):fed-talk,更多精彩內(nèi)容皆在微信公眾號(hào),歡迎關(guān)注。 若有幫助,請(qǐng)把 課多周刊 推薦給你的朋友,你的支持是我們最大的...
閱讀 3054·2021-11-25 09:43
閱讀 1650·2021-11-24 11:15
閱讀 2370·2021-11-22 15:25
閱讀 3515·2021-11-11 16:55
閱讀 3253·2021-11-04 16:10
閱讀 2785·2021-09-14 18:02
閱讀 1697·2021-09-10 10:50
閱讀 1081·2019-08-29 15:39