首页 > 代码库 > JS写小游戏(一):游戏框架

JS写小游戏(一):游戏框架

前言

  前一阵发现一个不错的网站,都是一些用html5+css+js写的小游戏,于是打算学习一番,写下这个系列博客主要是为了加深理解,当然也有一些个人感悟,如果英文好可以直接Click Here.

概述

  一般,小游戏都要关注两个问题:刷新和交互。因为游戏一般是动态的,所以需要不断刷新。JavaScript是单线程,如果用C语言写过贪吃蛇之类的小游戏,应该知道,单线程一般是挂起一个时间来达到动态效果。比如C语言的Sleep(),JS的setInterval()等。但是js还有一种更高性能的方法requestAnimationFrame。可以在网上找些资料进行学习,在此不做赘述。另一个就是交互,即用户需要通过鼠标、键盘控制游戏,从编程角度来书就是要添加对应事件的监听器。

  以下,正式开始。

HTML5

  先创建一个canvas画布:

 1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="UTF-8"> 5 <title>Rembound.com Example</title> 6 <script type="text/javascript" src="http://www.mamicode.com/script.js"></script> 7 </head> 8 <body> 9 <canvas id="viewport" width="640" height="480"></canvas>10 </body>11 </html> 

JS

  添加以下基本代码,代码详情可以看注释,最好单步调试加深理解:

//窗口加载完成后调用window.onload = function() {    // 获取画布及context(上下文)    var canvas = document.getElementById("viewport");     var context = canvas.getContext("2d");     // 记录时间帧,这个最好通过单步调试来理解    var lastframe = 0;    var fpstime = 0;    var framecount = 0;    var fps = 0;     // 初始化游戏,添加鼠标的监听事件    function init() {        canvas.addEventListener("mousemove", onm ouseMove);        canvas.addEventListener("mousedown", onm ouseDown);        canvas.addEventListener("mouseup", onm ouseUp);        canvas.addEventListener("mouseout", onm ouseOut);         // 进入游戏主循环        main(0);    }     // 主循环    function main(tframe) {        // 结束时继续调用main函数        window.requestAnimationFrame(main);         // 更新游戏        update(tframe);        render();    }     // 更新游戏状态,计算已经过去了的时间    function update(tframe) {        var dt = (tframe - lastframe) / 1000;        lastframe = tframe;         //更新帧数计数器        updateFps(dt);    }     function updateFps(dt) {        if (fpstime > 0.25) {            //计算帧数            fps = Math.round(framecount / fpstime);             //重置时间            fpstime = 0;            framecount = 0;        }         //增加帧时间、帧数        fpstime += dt;        framecount++;    }     // 渲染(更新画布)    function render() {        drawFrame();    }     //     function drawFrame() {        // 背景、边界        context.fillStyle = "#d0d0d0";        context.fillRect(0, 0, canvas.width, canvas.height);        context.fillStyle = "#e8eaec";        context.fillRect(1, 1, canvas.width-2, canvas.height-2);         // 标题头        context.fillStyle = "#303030";        context.fillRect(0, 0, canvas.width, 65);         // 标题        context.fillStyle = "#ffffff";        context.font = "24px Verdana";        context.fillText("HTML5 Canvas Basic Framework - Rembound.com", 10, 30);         // 显示帧数        context.fillStyle = "#ffffff";        context.font = "12px Verdana";        context.fillText("Fps: " + fps, 13, 50);    }     //鼠标监听    function onm ouseMove(e) {}    function onm ouseDown(e) {}    function onm ouseUp(e) {}    function onm ouseOut(e) {}     // 获取鼠标位置    function getMousePos(canvas, e) {        var rect = canvas.getBoundingClientRect();        return {            x: Math.round((e.clientX - rect.left)/(rect.right - rect.left)*canvas.width),            y: Math.round((e.clientY - rect.top)/(rect.bottom - rect.top)*canvas.height)        };    }     // 游戏入口    init();};

  效果:

  技术分享

添加游戏元素

  以上就是一个通用的游戏框架了,虽然它在不断刷新,但是没什么直观感受,以下建立一个简单游戏来感受一下:

 ......      var framecount = 0;    var fps = 0;     // 游戏平面    var level = {        x: 1,        y: 65,        width: canvas.width - 2,        height: canvas.height - 66    };        // 小方块    var square = {        x: 0,        y: 0,        width: 0,        height: 0,        xdir: 0,        ydir: 0,        speed: 0    }        // 分数    var score = 0;    // 初始化游戏,添加鼠标的监听事件    function init() {....

  在init()函数中添加:

....        canvas.addEventListener("mouseout", onm ouseOut);         // 初始化方块        square.width = 100;        square.height = 100;        square.x = level.x + (level.width - square.width) / 2;        square.y = level.y + (level.height - square.height) / 2;        square.xdir = 1;        square.ydir = 1;        square.speed = 200;                // 初始化分数        score = 0;            // 进入游戏主循环        main(0);....

  在update()函数中更新方块

....        //更新帧数计数器        updateFps(dt);       // 基于时间移动方块        square.x += dt * square.speed * square.xdir;        square.y += dt * square.speed * square.ydir;                // 处理碰撞        if (square.x <= level.x) {            // Left edge            square.xdir = 1;            square.x = level.x;        } else if (square.x + square.width >= level.x + level.width) {            // Right edge            square.xdir = -1;            square.x = level.x + level.width - square.width;        }        if (square.y <= level.y) {            // Top edge            square.ydir = 1;            square.y = level.y;        } else if (square.y + square.height >= level.y + level.height) {            // Bottom edge            square.ydir = -1;            square.y = level.y + level.height - square.height;        }    ...

  render()函数中还要渲染方块

....        // 绘制方块        context.fillStyle = "#ff8080";        context.fillRect(square.x, square.y, square.width, square.height);                // 绘制内部        context.fillStyle = "#ffffff";        context.font = "38px Verdana";        var textdim = context.measureText(score);        context.fillText(score, square.x+(square.width-textdim.width)/2, square.y+65);...

  添加鼠标事件

    function onm ouseDown(e) {        // 获取鼠标位置        var pos = getMousePos(canvas, e);                // 检查是否碰到了方块        if (pos.x >= square.x && pos.x < square.x + square.width &&            pos.y >= square.y && pos.y < square.y + square.height) {                        // 增加分数            score += 1;                        // 增加速度            square.speed *= 1.1;                        // 随机给一个新的位置            square.x = Math.floor(Math.random()*(level.x+level.width-square.width));            square.y = Math.floor(Math.random()*(level.y+level.height-square.height));                        // 随机方向            square.xdir = Math.floor(Math.random() * 2) * 2 - 1;            square.ydir = Math.floor(Math.random() * 2) * 2 - 1;        }    }

效果

  技术分享

 

  完整源代码:Click Here

  注:这只是众多小游戏合集中的一个,今后会继续添加。

 

JS写小游戏(一):游戏框架