从零开始开发html5游戏html汽车游戏

SongKer 发布时间:2016-02-18 分类:Game 阅读:4187次 1 条评论

开发html5小游戏需要有JavaScript的基础。通过JavaScript生成画布,游戏循环来不停地绘制图形创建动画。

教程开始之前可以尝试游戏试玩,开发的是一个全屏手机游戏,在PC上打开可能不太适应。手机游戏地址:汽车游戏

教程开始:

1、创建画布

var CANVAS_WIDTH = window.innerWidth;
var CANVAS_HEIGHT = window.innerHeight;
var canvasElement = $("<canvas width='" + CANVAS_WIDTH + "' height='" + CANVAS_HEIGHT + "'></canvas>");
var canvas = canvasElement.get(0).getContext("2d");
canvasElement.appendTo('body');

2、游戏循环:不停的绘图

为了游戏的连贯性实现动画等效果,需要对画布频繁的渲染(静态的页面就可以不用循环)。如下的代码会周期性的执行update和draw方法。

var scale = CANVAS_WIDTH / 320, FPS =30;  //通过scale计算出其他元素的宽高
setInterval(function() {
    update();
    draw();
}, 1000/FPS);

3、画布绘图

步骤2已经搭建起了一个循环的条件,在实现动画前我们可以在update和draw里将文字或者一张图片输出到画布上。

打印“www.songker.com”这几个黑色字体代码如下:

function draw() {
  canvas.fillStyle = "#000"; // 设置字体颜色
  canvas.fillText("www.songker.com!", 50, 50);
}

4、道路的绘制:创建‘道路’元素

我们将上面的代码改掉,将道路绘制上去。创建一个包含道路的所有信息的一个对象,包含’道路‘的draw和run方法。代码:

//滚动的道路
var sight = {
    speed: 10,
    x: 0,
    y: 0,
    width: CANVAS_WIDTH,
    height: 1126 * scale,   //根据屏幕比例得出图片实际高度
    run: function () {
        this.y += this.speed;
        if (this.y >= this.height) //第一张图已完毕
        {
            //console.log("road blank");
            this.y = 0;
        }
    },
    draw: function () {
        var road_img = new Image();
        road_img.src = "images/road.png";
        canvas.drawImage(road_img, this.x, this.y, this.width, this.height);
        canvas.drawImage(road_img, this.x, this.y - this.height, this.width, this.height);
    }
};

然后在全局draw方法中执行sight.draw(),在update中执行sight.run()实现‘跑动’的道路。

function draw() {
    canvas.clearRect(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT);
    sight.draw();
};
function update() {
    sight.run();
};

每完成一次绘制需要将上次画布上的内容清除掉,清除代码就是canvas.clearRect(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT)。

以上就完成了一个简单的'跑动的'道路。

5、绘制玩家的汽车

创建一个叫player对象,包含绘制、运动等所有玩家汽车的元素。

//玩家的汽车
var player = {
    width: 75 * scale,
    height: 149 * scale,
    x: CANVAS_WIDTH / 2 - (75 * scale) / 2,
    y: CANVAS_HEIGHT - (149 * scale),
    framePNG: new Array("images/car_1.png", "images/car_2.png"),
    layer: 0,       //当前一张图片
    move: function () {
        this.layer += 1;
        if (this.layer > 3&&this.layer <= 30 && this.layer%2==1)
            this.layer += 1;
        if (this.layer > 30)
            this.layer = 0;
    },
    draw: function () {
        var car_img = new Image();
        car_img.src = this.framePNG[this.layer % 2];
        canvas.drawImage(car_img, this.x, this.y, this.width, this.height);
    }
};

玩家的汽车有两张差异图片,循环绘制这两张图片产生汽车加速的效果。再次更新全局的draw和update方法,绘制玩家汽车:

function draw() {
    canvas.clearRect(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT);
    sight.draw();
    player.draw();
};
function update() {
    sight.run();
    player.move();
};

目前汽车还无法移动,我们可以给画布添加一个触摸移动事件,让汽车跟着我们手指的移动而移动。

$("canvas").bind('touchmove',function (e) {
    // 如果这个元素的位置内只有一个手指的话
    if (e.originalEvent.targetTouches.length == 1) {
        e.originalEvent.preventDefault();// 阻止浏览器默认事件,重要 
        var touch = e.originalEvent.targetTouches[0];
        var PlayerX = touch.pageX < player.width / 2 ? 0 : touch.pageX - player.width / 2;
        PlayerX = touch.pageX > CANVAS_WIDTH - player.width / 2 ? CANVAS_WIDTH - player.width : PlayerX;
        var PlayerY = touch.pageY < player.height / 2 ? 0 : touch.pageY - player.height / 2;
        PlayerY = touch.pageY > CANVAS_HEIGHT - player.height/2 ? CANVAS_HEIGHT - player.height : PlayerY;
        // 把元素放在手指所在的位置
        player.x = PlayerX;
        player.y = PlayerY;
    }
});

6、绘制其他的NPC汽车

var NPC = {
    meter: 0,
    BlockCarCollet: [],
    framePNG: Array(
        { width: 70, height: 120, xVelocity: 0, yVelocity: 2, src: "images/block_01.png" },
        { width: 50, height: 180, xVelocity: 0, yVelocity: 4, src: "images/block_02.png" },
        { width: 82, height: 141, xVelocity: 0, yVelocity: -4, src: "images/block_03.png" },
        { width: 50, height: 180, xVelocity: 0, yVelocity: 6, src: "images/block_02.png" }
    ),
    BlockCar:function(I) {
        I.active = true;
        I.frameOBJ = this.framePNG[I.Num];
        I.width = I.frameOBJ.width * scale;
        I.height = I.frameOBJ.height * scale;
        I.inScreen = function () {
            return I.x > 0 && I.x < CANVAS_WIDTH && I.y > -200 && I.y < CANVAS_HEIGHT + 200;
        };
        I.draw = function () {
            var imgOBJ = new Image();
            imgOBJ.src = I.frameOBJ.src;
            canvas.drawImage(imgOBJ, I.x, I.y, I.width, I.height);
        };
        I.update = function () {
            I.x += I.frameOBJ.xVelocity;
            I.y += I.frameOBJ.yVelocity;
            I.active = I.active && I.inScreen();
        }
        return I;
    },
    draw: function () {
        this.meter += 1;
        if (this.meter > 2000) {
            this.meter = 0;
        }
        if (this.meter % 50==0)
        {
            var index = GetRandomNum(1, this.framePNG.length) % this.framePNG.length;
            var frameOBJ = this.framePNG[index];
            this.BlockCarCollet.push(this.BlockCar({
                x: GetRandomNum(15, CANVAS_WIDTH - frameOBJ.width-15),
                y: frameOBJ.yVelocity < 0 ? CANVAS_HEIGHT : -100,
                Num: index
            }));
        }
    }
};

更新update和draw方法:

function draw() {
    canvas.clearRect(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT);
    sight.draw();
    player.draw();
    NPC.draw();
    NPC.BlockCarCollet.forEach(function (car) {
        car.draw();
    });
};
function update() {
    sight.run();
    player.move();
    NPC.BlockCarCollet.forEach(function (car) {
        car.update();
    });
    
    //handleCollisions();
    
    NPC.BlockCarCollet = NPC.BlockCarCollet.filter(function (car) {return car.active});
};

游戏基本完成。出现的唯一问题是,汽车之间没有碰撞事件。在update里添加一个碰撞事件handleCollisions():

function handleCollisions()
{
    NPC.BlockCarCollet.forEach(function (CarA) {
        NPC.BlockCarCollet.forEach(function (CarB) {
            if (CarA != CarB && collides(CarA, CarB)) {
                console.log("boom!!");
                CarA.active = CarB.active = false;
            }
        });
        if (collides(CarA, player))
        {
            console.log("gameover!!");
        }
    });
};
function collides(a, b)
{
    return (a.x + a.width > b.x &&
        a.y + a.height > b.y &&
        a.x < b.x + b.width &&
        a.y < b.y + b.height);
}
function GetRandomNum(Min, Max) {
    var Range = Max - Min;
    var Rand = Math.random();
    return (Min + Math.round(Rand * Range));
}

以上是游戏的全部代码,测试的话请用手机端打开这个网址http://songker.com/Code/car/index.html

我也是刚学习html5开发,有什么问题大家一起交流。

已有1条留言

发表评论:

◎欢迎您的参与讨论。