HTML5canvas实现回合制战棋游戏(1):加载和绘制图形
HTML5 canvas 实现回合制战棋游戏(1):加载和绘制图形
游戏介绍
之前写了⼀个 python 版本的回合制战棋游戏,最近学习了⼀下 javascript ES6 语法,因为 ES6 新增加了 class 语法糖,可以⽐较⽅便的将 python 的 class 实现移植过来。使⽤ html5 canvs 绘制游戏图像,利⽤ javascript ES6 重新实现了这个游戏。
游戏实现了类似英雄⽆敌3 中战⽃场景的回合制玩法:
canvas动画对战双⽅每个⽣物每⼀轮有⼀次⾏动机会,可以⾏⾛或攻击对⽅。
每个⽣物属性有:⾏⾛范围,速度,⽣命,伤害,防御,攻击 和 是否是远程兵种。
当把对⽅⽣物都消灭时,即胜利。
实现了简单的AI。
游戏截图如下:
图1图1中,是游戏的开始页⾯,‘start game’是⼀个按钮,点击开始运⾏游戏。
图2图2中,⽬前轮到⾏动的⽣物是我⽅的左下⾓背景为浅蓝⾊的步兵,可以看到背景为深蓝⾊的⽅格为步兵可以⾏⾛的范围。背景为绿⾊的⽅格为⽬前选定要⾏⾛到得⽅格。⿏标指向敌⽅⽣物,如果敌⽅⽣物背景⽅格颜⾊变成黄⾊,表⽰可以攻击,可以看到允许攻击斜对⾓的敌⼈。图中还有⽯块,表⽰不能移动到的地图⽅格。
完整代码
游戏实现代码的 github 链接
这边是 csdn 的下载链接
代码⽬录
为了更好的管理,将游戏的资源,配置⽂件和代码分成了多个⽬录进⾏保存。
介绍下代码各个⽬录的使⽤:
images ⽬录:存放游戏中⽤到的⽣物和地图格⼦图⽚。
data ⽬录:存放游戏会⽤到的配置⽂件,保存关卡地图配置的 entity_data.js,保存⽣物属性配置的 entity.js。
js ⽬录:存放游戏实现的 js ⽂件。
index.html:在浏览器中打开这个 html ⽂件来运⾏游戏。
游戏运⾏
1.⽀持的浏览器
⽬前有在 Firefox, Google Chrome 和 Microsoft Edge 上测试 ok。
Mac Safari 没有测试过,IE 是不⽀持 Javascript ES6 语法的。
2.运⾏
直接⽤浏览器执⾏代码根⽬录下的 index.html ⽂件。
HTML5 canvas 绘制图形
canvas 介绍
canvas 使⽤ JavaScript 在⽹页上绘制图像。canvas 画布是⼀个矩形区域,可以在这个矩形上以像素为单位绘制各种图形(图⽚,⽂字,矩形等)。canvas 提供了绘制线段、矩形、圆形、⽂字和图像的⽅法。
绘制图形前,需要先创建⼀个 canvas 对象,设置 canvas 矩形区域的宽度和⾼度,调⽤ getContext 函数返回⼀个对象 ctx,然后就可以⽤ ctx 对象来绘制图形。
var canvas = ateElement("canvas");
var ctx = Context("2d");
canvas.width =MAP_WIDTH;
canvas.height =MAP_HEIGHT;
document.body.appendChild(canvas);
绘制函数
在⼀个游戏中需要绘制图⽚,⽂字和图形。图形可以有线段,矩形,复杂点的有多边形,椭圆等。
HTML5 canvas 提供了函数来绘制线段、矩形、字符和图像,可以通过下⾯链接看下函数使⽤介绍:
但是 canvas 提供的绘制功能不是简单的⼀个函数就能实现,需要设置各种参数,下边是游戏中提供的封装函数,代码在 js/tool.js ⽂件中:
绘制线段函数 drawLine : 绘制⼀条从起点(start_x, start_y) 到终点(end_x, end_y)的线段,颜⾊为 color。
绘制图⽚函数 drawImage :source_rect 表⽰截取图⽚资源上的⼀个矩形⼤⼩的图形,绘制在 dest_rect 表⽰的 canvas 上的矩形中。
绘制四边形函数 drawRect:调⽤的 fillRect 函数绘制⼀个“被填充”的矩形。绘制⼀个左上⾓位置在(x,y),宽度为 width,⾼度为 height 的矩形,矩形填充的颜⾊为 color。
绘制字符函数 drawText:调⽤的 fillText 函数绘制⼀⾏“被填充的”⽂本。font 表⽰字符的⼤⼩,字体等设置。
function drawLine(ctx, color, start_x, start_y, end_x, end_y){
ctx.strokeStyle = color;
ctx.beginPath();
ctx.lineTo(end_x, end_y);
ctx.stroke();
}
function drawImage(ctx, img, source_rect, dest_rect){
ctx.drawImage(img, source_rect[0], source_rect[1], source_rect[2], source_rect[3],
dest_rect[0], dest_rect[1], dest_rect[2], dest_rect[3]);
}
function drawRect(ctx, color, x, y, width, height){
ctx.fillStyle = color;
ctx.fillRect(x, y, width, height);
}
function drawText(ctx, color, str, font, x, y){
ctx.font = font;
ctx.fillStyle = color;
ctx.fillText(str, x, y);
}
加载图⽚
在游戏中每个⽣物都有⼀个图⽚,需要先将图⽚加载完成后,才能在 canvas 中绘制,不然浏览器执
⾏时会报错。⼀个图⽚对象可以在canvas 上绘制多个相同类型的⽣物,所以我们可以⽤⼀个 Map 对象来预先加载所有的图⽚对象,然后在创建具体的类时(⽐如⽣物类),获取这个图⽚对象。
所有图⽚的名称和资源位置定义在 js\contants.py ⽂件中,IMAGE_SRC_MAP Map 对象保存了图⽚名称和资源位置的对应关系。
// IMAGE NAME
const GRID_IMAGE='tile.png';
const DEVIL='devil';
const FOOTMAN='footman';
const MAGICIAN='magician';
const EVILWIZARD='evilwizard';
const FIREBALL='fireball';
var IMAGE_SRC_MAP=new Map([
[GRID_IMAGE,'images/tile.png'],
[DEVIL,'images/devil.png'],
[FOOTMAN,'images/footman.png'],
[MAGICIAN,'images/magician.png'],
[EVILWIZARD,'images/evilwizard.png'],
[FIREBALL,'images/fireball.png']
]);
加载图⽚的代码在 js/tool.js ⽂件中:
loadAllGraphics 函数:遍历参数 img_src_map Map 对象,每个图⽚创建⼀个 对象,对象的成员 img 是⼀个 Image 对象,成员ready 表⽰图⽚是否加载完成。将这个对象保存到 IMAGE_MAP Map 对象中。
getMapGridImage 函数:因为⼀个图⽚中含有多个地图背景的⼩图⽚。将每个⼩图⽚都创建⼀个 Ima
geWrapper 封装类来表⽰。
function loadAllGraphics(img_src_map){
for(let key of img_src_map.keys()){
let tmp ={'img':new Image(),'ready':false};
IMAGE_MAP.set(key, tmp);
load=function(){
let tmp =(key);
};
tmp.img.src = img_(key);
}
}
function getMapGridImage(){
let grid_rect =new Map([
[String(),[0,21,20,20]],
[String(),[0,0,20,20]]
]);
let grid_image_map =new Map();
for(let key of grid_rect.keys()){
let img =new ImageWrapper(GRID_IMAGE, (key));
grid_image_map.set(key, img);
}
return grid_image_map;
}
function getLevelData(level_num){
let level ='level_'+ level_num;
return (level);
}
var IMAGE_MAP=new Map();
loadAllGraphics(IMAGE_SRC_MAP);
var GRID_IMAGE_MAP=getMapGridImage();
在 js\contants.py ⽂件中提供了⼀个图⽚的封装类,
构造函数 constructor :从 IMAGE_MAP Map 对象中根据图⽚名称获取图⽚对象,rect 表⽰截取图⽚资源上的⼀个矩形⼤⼩的图形。
draw 函数:根据 ready 成员变量值判断该图⽚是否加载完成,这样外部调⽤者可以不⽤考虑图⽚是否加载完成的细节问题。
class ImageWrapper{
constructor(name, rect){
this.img =(name);
< = rect;
}
draw(ctx, dest_rect){
if(ady){
drawImage(ctx,this.img., dest_rect);
}
}
}
看下图⽚封装类的实际应⽤,在 js\entity.py ⽂件中实现了远程⽣物的⽕球类,在 FireBall 类的构造函数中,调⽤ loadImage 函数创建了⼀个 ImageWrapper 类对象,这样在 draw 函数中绘制⽕球图⽚时,可以不⽤考虑图⽚是否加载完成的问题。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论