1. 事件方法
1.1. 新建事件方法
1.2. 键盘按键值对象
1.3. 初始化事件方法
1.4. 给body元素添加按键方法
1.5. 添加事件方法, 可以传递参数
1.6. 下一关卡方法
1.7. 帮助方法
1.8. 初始化事件
2. 测试事件
2.1. 配置3关数据
2.2. 点击上一关按钮
2.3. 点击下一关和重玩本关按钮
2.4. 点击游戏说明按钮
2.5. 上、下、左、右键和w、a、s、d键
3. 切换人物图片
3.1. 定义当前人物图片变量
3.2. 给事件传递图片对象
3.3. 人物行走的方法
3.4. 调用go方法
3.5. 修改绘制人物的图片为当前图片
3.6. index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>推箱子</title>
<style type="text/css">
* {
margin: 0;
padding: 0;
}
body {
background-color: #000;
}
#game {
width: 560px;
margin: 0 auto;
}
#canvas {
background: #fff;
}
#msg {
color: #fff;
font-size: 16px;
height: 40px;
line-height: 40px;
background-color: #000;
}
#btn {
height: 50px;
line-height: 50px;
background-color: #FFF;
}
#btn input {
height: 30px;
width: 100px;
-webkit-appearance: button;
}
</style>
</head>
<body>
<div id="game">
<canvas id="canvas" width="560px" height="560px"></canvas>
<div id="msg">第1关, 移动次数: 0</div>
<div id="btn">
<input type="button" id="previous" value="上一关" />
<input type="button" id="next" value="下一关" />
<input type="button" id="replay" value="重玩本关" />
<input type="button" id="descript" value="游戏说明" />
</div>
</div>
<script type="text/javascript" src="mapdata.js"></script>
<script type="text/javascript">
// 加载图片
function loadImages(){
var imageSrc = {
"block": "images/block.gif",
"wall": "images/wall.png",
"box": "images/box.png",
"ball": "images/ball.png",
"up": "images/up.png",
"down": "images/down.png",
"left": "images/left.png",
"right": "images/right.png"
};
var exports = {};
exports.images = {};
exports.succeed = false;
exports.init = function(callback){
var count = 0, imgCount = 0;
for (let key in imageSrc) {
imgCount++;
}
for(let key in imageSrc){
this.images[key] = new Image();
this.images[key].onload = function(){
count++;
if(count == imgCount){
exports.succeed = true;
}
callback(count, imgCount);
};
this.images[key].src = imageSrc[key];
}
};
return exports;
}
// 初始化场景
function initScene(level, images){
var block = images["block"];
for(let i = 0, ilen = level.length; i < ilen; i++){
for(let j = 0, jlen = level[i].length; j < jlen; j++){
let data = level[i][j];
let img = block;
switch(data){
case dataItem.wall:
img = images["wall"];
break;
case dataItem.ball:
img = images["ball"];
break;
case dataItem.box:
img = images["box"];
break;
case dataItem.down:
// img = images["down"];
img = curManImg; // 人物初始化使用向下的图片, 看起来是面向屏幕外
break;
}
// 画砖块
ctx.drawImage(block, j * w, i * h, block.width, block.height);
// 画墙、小球、箱子和人物
if(level[i][j] != 0){
ctx.drawImage(img, j * w + (w - img.width) / 2, i * h + (h - img.height), img.width, img.height);
}
}
}
}
// 事件方法
function doEvent(images){
// 键盘按键值对象
var keyCode = {
up: 38, // 键盘上的上键, 人物向上走
w: 87, // 键盘上的w键, 人物向上走
down: 40, // 键盘上的下键, 人物向下走
s: 83, // 键盘上的s键, 人物向下走
left: 37, // 键盘上的左键, 人物向左走
a: 65, // 键盘上的a键, 人物向左走
right: 39, // 键盘上的右键, 人物向右走
d: 68 // 键盘上的d键, 人物向右走
};
var exports = {};
// 初始化事件方法
exports.init = function(){
var previous = document.getElementById('previous');
var next = document.getElementById('next');
var replay = document.getElementById('replay');
var descript = document.getElementById('descript');
document.body.addEventListener('keyup', this.bodyKeyup, false);
this.addEventListener(previous, 'click', this.nextLevel, -1);
this.addEventListener(next, 'click', this.nextLevel, 1);
this.addEventListener(replay, 'click', this.nextLevel, 0);
this.addEventListener(descript, 'click', this.descript);
};
// 给body元素添加按键方法
exports.bodyKeyup = function(e){
switch(e.keyCode){
case keyCode.up:
case keyCode.w:
console.log('人物向上走');
exports.go('up');
break;
case keyCode.down:
case keyCode.s:
console.log('人物向下走');
exports.go('down');
break;
case keyCode.left:
case keyCode.a:
console.log('人物向左走');
exports.go('left');
break;
case keyCode.right:
case keyCode.d:
console.log('人物向右走');
exports.go('right');
break;
}
};
// 添加事件方法, 可以传递参数
exports.addEventListener = function(obj, name, fn, args){
var addfn = function(){
fn.call(obj, args);
};
obj.addEventListener(name, addfn, false);
};
// 下一关卡方法
exports.nextLevel = function(l){
curLevel += l;
if(curLevel < 0) {
curLevel = 0;
}
if(curLevel >= levels.length){
curLevel = levels.length - 1;
}
console.log('当前关卡: ' + curLevel);
};
// 帮助方法
exports.descript = function(){
alert("用键盘上的上、下、左、右键移动人物, 把箱子全部推到小球的位置即可过关。箱子只可向前推, 并且人物一次只能推动一个箱子。");
};
// 人物行走的方法
exports.go = function(dir){ // 人物图片key、方向
curManImg = images[dir];
initScene(levels[0], images);
};
return exports;
}
(function(global){
// 获取画布
global.can = document.getElementById('canvas');
// 获取画笔(实际上是CanvasRenderingContext2D对象)
global.ctx = global.can.getContext("2d");
global.w = 35, global.h = 35; // w矩阵元素的宽度, h矩阵元素的高度
// 0: 代表砖块; 1: 代表墙壁; 2: 代表小球; 3: 代表箱子; 4: 代表人物
global.dataItem = {block: 0, wall: 1, ball: 2, box: 3, down: 4};
global.curLevel = 0; // 当前关卡
var li = loadImages();
li.init(function(count, imgCount){
console.log(count / imgCount * 100 + '%');
if(li.succeed){
initScene(levels[0], li.images);
}
});
// 初始化事件
doEvent(li.images).init();
global.curManImg = li.images['down']; // 当前人物图片, 默认向下的人物图片
})(window);
</script>
</body>
</html>
3.7. mapdata.js
var levels=[]; // 关卡地图配置数据
levels[0]=[
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0],
[0,0,0,0,0,0,1,2,1,0,0,0,0,0,0,0],
[0,0,0,0,0,0,1,0,1,1,1,1,0,0,0,0],
[0,0,0,0,1,1,1,3,0,3,2,1,0,0,0,0],
[0,0,0,0,1,2,0,3,4,1,1,1,0,0,0,0],
[0,0,0,0,1,1,1,1,3,1,0,0,0,0,0,0],
[0,0,0,0,0,0,0,1,2,1,0,0,0,0,0,0],
[0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]];
levels[1]=[
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,1,1,1,1,1,0,0,0,0,0,0,0],
[0,0,0,0,1,4,0,0,1,0,0,0,0,0,0,0],
[0,0,0,0,1,0,3,3,1,0,1,1,1,0,0,0],
[0,0,0,0,1,0,3,0,1,0,1,2,1,0,0,0],
[0,0,0,0,1,1,1,0,1,1,1,2,1,0,0,0],
[0,0,0,0,0,1,1,0,0,0,0,2,1,0,0,0],
[0,0,0,0,0,1,0,0,0,1,0,0,1,0,0,0],
[0,0,0,0,0,1,0,0,0,1,1,1,1,0,0,0],
[0,0,0,0,0,1,1,1,1,1,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]];
levels[2]=[
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0],
[0,0,0,0,1,0,0,0,0,0,1,1,1,0,0,0],
[0,0,0,1,1,3,1,1,1,0,0,0,1,0,0,0],
[0,0,0,1,0,4,0,3,0,0,3,0,1,0,0,0],
[0,0,0,1,0,2,2,1,0,3,0,1,1,0,0,0],
[0,0,0,1,1,2,2,1,0,0,0,1,0,0,0,0],
[0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]];
3.8. 运行程序
3.8.1. 效果图
3.8.2. 向右移动
3.8.3. 向上移动
3.8.4. 向左移动
3.8.5. 向下移动