本系列博文翻译自以下文章

http://blog.sklambert.com/html5-canvas-game-panning-a-background/

Languages: HTML5, JavaScript

Code: https://github.com/straker/galaxian-canvas-game/tree/master/part1

1.游戏背景滚动

最终的游戏演示界面如下:

控制:移动 –  (←↑↓→)箭头
射击 – 空格

The HTML5 Page

<!DOCTYPE html>
<html>
<head>
<title>Space Shooter Demo</title>
<style>
canvas {
position: absolute;
top: 0px;
left: 0px;
background: transparent;
}
</style>
</head>
<body onload="init()">
<!-- The canvas for the panning background -->
<canvas id="background" width="600" height="360">
Your browser does not support canvas. Please try again with a different browser.
</canvas>
<script src="space_shooter_part_one.js"></script>
</body>
</html>

以上代码创建了一个600宽,360高的画布。

基础

创建一个封装全部图像的js对象:

/**
* Define an object to hold all our images for the game so images
* are only ever created once. This type of object is known as a
* singleton.
*/
var imageRepository = new function() {
// Define images
this.background = new Image();
// Set images src
this.background.src = "imgs/bg.png";
}
 

接下来,我们创建Drawable对象,所有以后的可以运动的物体对象都继承于它,Drawable对象包含一个空的draw方法。

/**
* Creates the Drawable object which will be the base class for
* all drawable objects in the game. Sets up default variables
* that all child objects will inherit, as well as the default
* functions.
*/
function Drawable() {
this.init = function(x, y) {
// Default variables
this.x = x;
this.y = y;
}
this.speed = 0;
this.canvasWidth = 0;
this.canvasHeight = 0;
// Define abstract function to be implemented in child objects
this.draw = function() {
};
}
接下来我们创建背景Background对象,注意红色部分的代码,红色2句代码是背景移动的核心。
第一句让背景从纵坐标0开始向下移动,第二句让背景从纵坐标(0-画布)高度开始向下移动,这样就产生了背景在不断向下移动的效果。
最后一句蓝色代码是将
Background对象的原形设置为Drawable对象,继承Drawable中的变量和方法。
/**
* Creates the Background object which will become a child of
* the Drawable object. The background is drawn on the "background"
* canvas and creates the illusion of moving by panning the image.
*/
function Background() {
this.speed = 1; // Redefine speed of the background for panning
// Implement abstract function
this.draw = function() {
// Pan background
this.y += this.speed;
this.context.drawImage(imageRepository.background, this.x, this.y);
// Draw another image at the top edge of the first image
this.context.drawImage(imageRepository.background, this.x, this.y - this.canvasHeight);
// If the image scrolled off the screen, reset
if (this.y >= this.canvasHeight)
this.y = 0;
};
}
// Set Background to inherit properties from Drawable
Background.prototype = new Drawable();
 

最后一步

创建Game对象,Game对象获得web页面中定义的画布,初始化背景对象Background,设置背景对象的context以及画布宽,画布高属性。

/**
* Creates the Game object which will hold all objects and data for
* the game.
*/
function Game() {
/*
* Gets canvas information and context and sets up all game
* objects.
* Returns true if the canvas is supported and false if it
* is not. This is to stop the animation script from constantly
* running on older browsers.
*/
this.init = function() {
// Get the canvas element
this.bgCanvas = document.getElementById('background');
// Test to see if canvas is supported
if (this.bgCanvas.getContext) {
this.bgContext = this.bgCanvas.getContext('2d');
// Initialize objects to contain their context and canvas
// information
Background.prototype.context = this.bgContext;
Background.prototype.canvasWidth = this.bgCanvas.width;
Background.prototype.canvasHeight = this.bgCanvas.height;
// Initialize the background object
this.background = new Background();
this.background.init(0,0); // Set draw point to 0,0
return true;
} else {
return false;
}
};
// Start the animation loop
this.start = function() {
animate();
};
}

以下是动画功能的实现,其中requestAnimFrame类似一个timer,会不定期的回调 animate()函数; animate()函数中调用game.background.draw();不断的重绘背景图片的位置,以实现背景滚动的动画效果。

 
/**
* The animation loop. Calls the requestAnimationFrame shim to
* optimize the game loop and draws all game objects. This
* function must be a gobal function and cannot be within an
* object.
*/
function animate() {
requestAnimFrame( animate );
game.background.draw();
}
/**
* requestAnim shim layer by Paul Irish
* Finds the first API that works to optimize the animation loop,
* otherwise defaults to setTimeout().
*/
window.requestAnimFrame = (function(){
return window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.oRequestAnimationFrame ||
window.msRequestAnimationFrame ||
function(/* function */ callback, /* DOMElement */ element){
window.setTimeout(callback, 1000 / 60);
};
})();

最后启动程序:

/**
* Initialize the Game and starts it.
*/
var game = new Game();
function init() {
if(game.init())
game.start();
}
最后的运行效果如下:

博主其他系列博文推荐:

1.网络采集软件核心技术剖析系列博文索引

2.手把手教你使用FineUI开发一个b/s结构的取送货管理信息系统系列博文索引

Step by Step 使用HTML5开发一个星际大战游戏(1)的更多相关文章

  1. Step by Step 使用HTML5开发一个星际大战游戏(2)

    HTML5 Canvas Game: 玩家飞船  本系列博文翻译自以下文章 http://blog.sklambert.com/html5-canvas-game-the-player-ship/ L ...

  2. 使用HTML5开发Kinect体感游戏

    一.简介 我们要做的是怎样一款游戏? 在前不久成都TGC2016展会上,我们开发了一款<火影忍者手游>的体感游戏,主要模拟手游章节<九尾袭来 >,用户化身四代,与九尾进行对决, ...

  3. Cocos2d-x-Lua 开发一个简单的游戏(记数字步进白色块状)

    Cocos2d-x-Lua 开发一个简单的游戏(记数字步进白色块状) 本篇博客来给大家介绍怎样使用Lua这门语言来开发一个简单的小游戏-记数字踩白块. 游戏的流程是这种:在界面上生成5个数1~5字并显 ...

  4. 使用Cocos2dx-JS开发一个飞行射击游戏

    一.前言 笔者闲来无事,某天github闲逛,看到了游戏引擎的专题,引起了自己的兴趣,于是就自己捣腾了一下Cocos2dx-JS.由于是学习,所谓纸上得来终觉浅,只是看文档看sample看demo,并 ...

  5. HTML5 - 开发一个自己的websocket服务器

    应用:node.js 主要步骤: 创建文件夹 创建app.js(server入口,app为自定义命名) npm init -y (快速创建一个package.json文件) 依赖包安装:nodejs- ...

  6. 从零开始手把手教你使用javascript+canvas开发一个塔防游戏01地图创建

    项目演示 项目演示地址: 体验一下 项目源码: 项目源码 代码结构 本节做完效果 游戏主页面 index.html <!DOCTYPE html PUBLIC "-//W3C//DTD ...

  7. 用Python做一个飞机大战游戏

    基于pygame的一款小游戏 这是我上半年做的一款小游戏,但是一直忘记了,现在才上传代码. github项目地址:StarMan 代码基于pygame,Python版本3.5.2运行正常. 游戏很简单 ...

  8. Nginx 模块开发(1)—— 一个稍稍能说明问题模块开发 Step By Step 过程

    1. Nginx 介绍        Nginx是俄罗斯人编写的十分轻量级的HTTP服务器,它的发音为“engine X”, 是一个高性能的HTTP和反向代理服务器,同时也是一个IMAP/POP3/S ...

  9. Step by Step: 基于MFC下的COM组件开发-Helloworld

    http://blog.csdn.net/sybifei/article/details/45008745 [这篇文章有问题, 仅供参考] http://blog.csdn.net/define_us ...

随机推荐

  1. 【bzoj1096-仓库建设】斜率优化

    dsy1096: [ZJOI2007]仓库建设 [问题描述] L公司有N个工厂,由高到底分布在一座山上.如图所示,工厂1在山顶,工厂N在山脚. 由于这座山处于高原内陆地区(干燥少雨),L公司一般把产品 ...

  2. 【mysql】索引与排序、重复索引、冗余索引

    索引与排序 排序可能发生2种情况: 1: 对于覆盖索引,直接在索引上查询时,就是有顺序的, using index 2: 先取出数据,形成临时表做filesort(文件排序,但文件可能在磁盘上,也可能 ...

  3. LCD实验学习笔记(一):Makefile

    主Makefile总领全局的就这句—— lcd.bin: $(objs) 要生成lcd.bin,依赖于objs列举的一堆文件:head.o init.o nand.o interrupt.o seri ...

  4. C++11 lambda函数符

    #include<iostream> #include<vector> #include<algorithm> #include<cmath> #inc ...

  5. [译]lambda表达式对 SAM (单个抽象方法类)type的处理方式

    在阅读Venkat Subramaniam的著作<Functional Programming in Java> 之后,方法模式和lambda完美结合让我印象深刻. 这种模式经常用作数据源 ...

  6. kafka consumer 代码示例

    使用者小组 使得许多进程的多台机器 在逻辑上作为一个单个的使用者 出现. 我们使用中,一种常见的情况是,我们按照逻辑划分出多个使用者小组,每个小组都是有作为一个逻辑整体的多台使用者计算机组成的集群. ...

  7. 使用python获取整月每一天的系统监控数据生成报表

    1.安装阿里开源监控工具tsar tsar官方网站 wget -O tsar.zip https://github.com/alibaba/tsar/archive/master.zip --no-c ...

  8. python的property的用法

    假设定义了一个类:C,该类必须继承自object类,有一私有变量_xclass C: def __init__(self): self.__x=None 1.现在介绍第一种使用属性的方法: 在该类中定 ...

  9. Laravel查询技巧

    1.同时增加几个字段的数量 DB::table('project') ->where('id',$yewuid) ->increment('count', 1, [ 'click'=> ...

  10. 对tmemorystream的一些改进_delphi教程

    http://www.cnblogs.com/linyawen/archive/2010/12/11/1903072.html 怎么又是关于Stream的,呵呵,应该说只是最近比较关心程式的效率问题, ...