相关文章推荐
英勇无比的大蒜  ·  CSS布局 ...·  3 月前    · 
低调的警车  ·  mysql递归查询所有子节点·  4 月前    · 
小眼睛的脆皮肠  ·  python - ...·  8 月前    · 
销魂的水桶  ·  pytorch ...·  1 年前    · 
How To Make A Simple HTML5 Canvas Game
自从我制作了一些HTML5游戏(例如Crypt Run)后,我收到了很多建议,要求我写一篇关于怎样利用HTML5 Canvas制作游戏的入门教程。花了一点时间考虑怎么着手写这篇文章后,我决定先实现一个我觉得最最简单的游戏,然后一行代码一行代码地进行讲解。
让我们开始吧,首先看看game.js,当然你也可以先玩玩这个游戏(译注:附件是游戏源码,用浏览器打开其中的index.html就可以玩了,或者也可以到 lostdecadegames 官网上去玩)。
附件下载地址: simple_canvas_game
// Create the canvas
var canvas = document.createElement("canvas");
var ctx = canvas.getContext("2d");
canvas.width = 512;
canvas.height = 480;
document.body.appendChild(canvas);

我们首先要做的是创建一个canvas对象。可以用JavaScript或HTML来做,都非常简单。此处我用的是JS。当创建了canvas之后,我们就可以获取它的上下文对象(context)、设置尺寸,并且把它加到当前文档中。 2. 载入图片
// Background image
var bgReady = false;
var bgImage = new Image();
bgImage.onload = function () {
    bgReady = true;
bgImage.src = "images/background.png";

游戏需要图像,所以让我们载入一些图片吧。我想尽量简单化,所以只用了Image对象来做,当然,还可以将载入图像的功能封装成一个类或别的任何形式。代码中的bgReady用来标识图片是否已完全载入,只有当图片载入完成后,我们才能使用它,如果在载入完成前就对其进行绘制或渲染,JS将会报一个DOM error的错误。
我们会用到三张图片(背景、英雄、怪物),每张图片都需要这样处理。 3. 定义游戏要使用的对象
// Game objects
var hero = {
    speed: 256, // movement in pixels per second
    x: 0,
var monster = {
    x: 0,
var monstersCaught = 0;

定义一些变量,稍后会用到。hero对象的speed属性表示英雄的移动速度(像素/秒);monster对象不会移动,所以仅仅具有一对坐标;monstersCaught表示玩家抓住的怪物数量。 4. 处理玩家输入
// Handle keyboard controls
var keysDown = {};
addEventListener("keydown", function (e) {
     keysDown[e.keyCode] = true;
}, false);
addEventListener("keyup", function (e) {
     delete keysDown[e.keyCode];
}, false);

现在进行输入的处理。(对具有web开发背景的人来说,这是目前为止第一个具有挑战性的部分)对一般的网页来说,当用户开始输入时,可能需要马上开始播放动画或请求数据。但在这里,我们想让游戏逻辑在一个单独的地方对游戏中发生的事情进行处理。为此我们需要将用户输入保存下来以备稍后处理,而不是立即处理。 我们通过简单地将事件对应的键编码(keyCode)保存在keysDown变量中来实现。如果该变量中具有某个键编码,就表示用户目前正按下这个键。简单吧! 5. 新游戏
// Reset the game when the player catches a monster
var reset = function () {
     hero.x = canvas.width / 2;
     hero.y = canvas.height / 2;
     // Throw the monster somewhere on the screen randomly
     monster.x = 32 + (Math.random() * (canvas.width - 64));
     monster.y = 32 + (Math.random() * (canvas.height - 64));
 通过调用reset函数来开始新游戏。该函数将英雄(即玩家角色)放到屏幕中间,然后随机选择一个位置来安置怪物。 
 6. 更新对象 
 
// Update game objects
var update = function (modifier) {
    if (38 in keysDown) { // Player holding up
        hero.y -= hero.speed * modifier;
    if (40 in keysDown) { // Player holding down
        hero.y += hero.speed * modifier;
    if (37 in keysDown) { // Player holding left
        hero.x -= hero.speed * modifier;
    if (39 in keysDown) { // Player holding right
        hero.x += hero.speed * modifier;
    // Are they touching?
        hero.x <= (monster.x + 32)
            && monster.x <= (hero.x + 32)
            && hero.y <= (monster.y + 32)
            && monster.y <= (hero.y + 32)
         ++monstersCaught;
         reset();
 这是update函数,游戏每隔一定时间会调用它一次。它所做的第一件事情是检查用户是否按下了上下左右四个箭头键。如果是,就将我们的英雄向相应的方向移动。 
 update有一个modifier参数,这看起来好像有点奇怪。你会在游戏的主函数即main函数中看到它,不过我在这儿先解释一下。modifier参数是一个从1开始的与时间相关的数。如果间隔刚好为1秒时,它的值就会为1,英雄移动的距离即为256像素(英雄的速度为256像素/秒);而如果间隔是0.5秒,它的值就为0.5,即英雄移动的距离为其速度的一半,以此类推。通常update函数调用的间隔很短,所以modifier的值很小,但用这种方式能够确保不管代码执行的速度怎么样,英雄的移动速度都是相同的。 
 我们已经实现了根据用户的输入来移动英雄,但我们还可以在移动英雄时对其进行检查,以确定是否有其他事件发生。例如:英雄是否与怪物发生了碰撞——当英雄与怪物发生碰撞时,我们为玩家进行计分(monstersCaught加1)并重置游戏(调用reset函数)。 
 7. 渲染对象 
 
// Draw everything
var render = function () {
    if (bgReady) {
         ctx.drawImage(bgImage, 0, 0);
    if (heroReady) {
         ctx.drawImage(heroImage, hero.x, hero.y);
    if (monsterReady) {
         ctx.drawImage(monsterImage, monster.x, monster.y);
    // Score
    ctx.fillStyle = "rgb(250, 250, 250)";
    ctx.font = "24px Helvetica";
    ctx.textAlign = "left";
    ctx.textBaseline = "top";
    ctx.fillText("Goblins caught: " + monstersCaught, 32, 32);
 当你能够看到你的行动时游戏才会变得更有趣,所以让我们在屏幕上绘制吧。首先我们将背景图片绘制到canvas,然后是英雄和怪物。注意顺序很重要,因为任何位于表层的图片都会将其下面的像素覆盖掉。 
 接下来是文字,这有些不同,我们调用fillText函数显示玩家的分数。因为不需要复杂的动画或者对文字进行移动,所以只是绘制一下就ok了。 
 8. 游戏主循环 
 
// The main game loop
var main = function () {
    var now = Date.now();
    var delta = now - then;
    update(delta / 1000);
    render();
    then = now;
 游戏的主循环用来控制游戏流程。首先我们要获得当前的时间,这样我们才能计算时间差(自上次循环以来经过的时间)。然后计算modifier的值并交给update(需要将delta除以1000以将其转换为毫秒)。最后调用render并更新记录的时间。 
 更多关于游戏循环的内容见“Onslaught! Arena Case Study”。 
 9. 开始游戏吧 
 
// Let's play this game!
reset();
var then = Date.now();
setInterval(main, 1); // Execute as fast as possible
快完成了,这是最后一段代码。首先调用reset来开始新游戏。(还记得吗,这会将英雄置中并随机安放怪物)。然后将起始时间保存到变量then中并启动游戏的主循环。 OK!(但愿)你现在已经理解了在HTML5 Canvas中用JS来开发游戏的基础知识了。建议最好是能够自己亲自试一把!

自从我制作了一些HTML5游戏(例如Crypt Run)后,我收到了很多建议,要求我写一篇关于怎样利用HTML5 Canvas制作游戏的入门教程。花了一点时间考虑怎么着手写这篇文章后,我决定先实现一个我觉得最最简单的游戏,然后一行代码一行代码地进行讲解。让我们开始吧,首先看看game.js,当然你也可以先玩玩这个游戏(译注:附件是游戏源码,用浏览器打开其中的index.html就可以玩了, 原文:How to make a simple HTML5 Canvas game 想要快速上手HTML5 Canvas游戏开发?下面通过一个例子来进行手把手教学。(如果你怀疑我的资历, A Wizard's Lizard这个游戏的半数以上开发是由我完成的) 我们直接来看源码里的game.js,当然你也可以在线体验一下游戏先。 游戏截图 // Create the canvas...
canvas学了有一个多礼拜了,觉得canvas真心好玩。学canvas的人想法估计都跟我差不多,抱着写游戏的态度去学canvas的。所以运动学啊、碰撞检测啊、一些简单的算法神马的是基础啊。以前没做过游戏的我学起来还真心吃力。今天就来说下用canvas写个最简单的弹力球游戏,就运用了最简单的重力作用以及碰撞检测。   先上DEMO:弹力球DEMO (鼠标点击canvas里的空白区域会给与小球新速度)   【创建小球对象】   第一步就是先创建一个小球对象,写好小球的构造函数: 复制代码代码如下:var Ball = function(x , y , r , color){
<meta charset="UTF-8"> <meta name="keywords" content="贪吃蛇"> <meta name="Description" content="这是一个初学者用来学习的小游戏"> <style type="text/cs    放大与缩小:scale(x, y)函数,xy轴放大,如果为负数,还可以使图形翻转。    平移:translate(x, y),xy轴平移    旋转:rotate(angle),参数为弧度,angle*Math.PI/180    利用transform矩阵实现多样化的变形:transform(a, b, c, d, e, f) context.fillStyle = "#fff"; context.beginPath(); context.arc(100, 100, 20, 0, Math.PI * 2, true); context.closePath(); context.fill(); // 点击消灭星星 canvas.addEventListener("click", function(event) { var x = event.pageX - canvas.offsetLeft; var y = event.pageY - canvas.offsetTop; if (context.isPointInPath(x, y)) { context.clearRect(0, 0, canvas.width, canvas.height); context.fillStyle = "#000"; context.fillRect(0, 0, canvas.width, canvas.height); </script> </body> </html> 这是一个简单的消灭星星小游戏,点击星星就会消灭,并清除画布重新绘制背景。您可以根据需要进行修改和完善。 (4-1) 如果S1为空,或栈顶运算符为右括号“)”,则直接将此运算符入栈; (4-2) 否则,若优先级比栈顶运算符的较高或相等,也将运算符压入S1; (4-3) 否则,将S1栈顶的运算符弹出并压入到S2中,再次转到(4-1)与S1中新的栈顶运算符相比较; (5) 遇到括号时: (5-1) 如果是右括号“)”,则直接压入S1; (5-2) 如果是左括号“(”,则依次弹出S1栈顶的运算符,并压入S2,直到遇到右括号为止,此时将这一对括号丢弃; 前缀、中缀、后缀表达式 dv1314: 大师,我悟了表情包 前缀、中缀、后缀表达式 Coffey强: