从零开始手把手教你使用javascript+canvas开发一个
2020-12-29 本文已影响0人
__豆约翰__
项目演示
项目演示地址:
项目源码:
代码结构
本节做完效果
image.pngEnemy.js
//敌人类
function Enemy(cxt,img,type,x,y,width,height){
this.cxt = cxt;
this.img = img;
this.x = x;//55
this.y = y;//0
this.width = width;
this.height = height;
//敌人类型
this.type = type;
this.sp = 2;
//移动的方向
this.dir = null;
//下个移动位置
this.nextPosition = null;
//记录已经走过的位置
this.hadWalk = {};
}
Enemy.prototype = {
//敌人在图片中对应的位置
enemyMap : [{x:0,y:0},{x:40,y:0},{x:80,y:0},{x:120,y:0},{x:160,y:0},{x:200,y:0},{x:240,y:0},{x:280,y:0},{x:320,y:0},{x:360,y:0},
{x:400,y:0},{x:440,y:0},{x:480,y:0},{x:520,y:0},{x:560,y:0},{x:600,y:0},{x:640,y:0},{x:680,y:0},{x:720,y:0},{x:760,y:0}],
//画出敌人
draw : function(){
//冰冻中,画出冰冻图
if(this.frozenTime > 0){
Canvas.drawImg(this.cxt,this.img,this.enemyMap[this.type].x,this.enemyMap[this.type].y+40,this.width,this.height,this.x,this.y,this.width,this.height);
}
//画出正常图
else Canvas.drawImg(this.cxt,this.img,this.enemyMap[this.type].x,this.enemyMap[this.type].y,this.width,this.height,this.x,this.y,this.width,this.height);
//计算血量百分比
var persen = Math.floor(this.life / this.maxLife * 100) / 2;
//画出血量
Canvas.fillRect(this.cxt,this.x-5,this.y-5,persen,3,"rgba(38,223,116,0.8)");
},
//更新敌人信息
update : function(){
//超出坐标
if(this.x >= 500){
return false;
}
var xIndex = parseInt(this.x / 50,10),//1
yIndex = parseInt(this.y / 50,10);//0
//判断是否有下个移动位置信息,或者下哥移动位置信息是否已经走到了
if(!this.nextPosition ||
((this.x >= this.nextPosition.x - 5 && this.x <= this.nextPosition.x)
&& (this.y >= this.nextPosition.y - 5 && this.y <= this.nextPosition.y))
){
//走到最右侧
if(xIndex + 1 >= 10){
xIndex = -1;
}
else{
//判断往下能否走
if(MapData[xIndex][yIndex+1] && !this.hadWalk[xIndex+"_"+(yIndex+1)]){
this.dir = "down";
yIndex += 1;
}
//判断往右能否走
else if(MapData[xIndex+1][yIndex] && !this.hadWalk[(xIndex+1)+"_"+yIndex]){
this.dir = "right";
xIndex += 1;
}
else if(MapData[xIndex][yIndex-1] && !this.hadWalk[xIndex+"_"+(yIndex-1)]){
this.dir = "up";
yIndex -= 1;
}
else if(MapData[xIndex-1][yIndex] && !this.hadWalk[(xIndex-1)+"_"+yIndex]){
this.dir = "left";
xIndex -= 1;
}
}
//是否走到最右侧
if(xIndex == -1){
this.nextPosition = {x:500,y:yIndex*50+5};
}
//设置下个移动位置
else {
this.nextPosition = {x:xIndex*50+5,y:yIndex*50+5};
//记录已经走过的位置
this.hadWalk[xIndex+"_"+yIndex] = true;
}
}
//移动
switch(this.dir){
case "down":
this.y += this.sp;
break;
case "up":
this.y -= this.sp;
break;
case "left":
this.x -= this.sp;
break;
case "right":
this.x += this.sp;
break;
default:
break;
}
}
}
//更新所有敌人信息
function updateEnemy(){
var enemy;
for(var i=0,l=Game.enemyList.length;i<l;i++){
enemy = Game.enemyList[i];
if(!enemy)continue;
enemy.update();
}
}
//画出所有敌人
function drawEnemy(){
var enemy;
for(var i=0,l=Game.enemyList.length;i<l;i++){
enemy = Game.enemyList[i];
if(!enemy)continue;
enemy.draw();
}
}
game.js修改
每50次循环出一个敌人
tool.js新增
自动寻路算法解析
坐标系
向右为x轴
向下为y轴
整个地图为500*500
// 游戏对象
var hero = {
speed: 2, // 每秒移动的像素
x: 55,
y: 0,
srcx:120,
srcy:40,
flood:50,
//移动的方向
dir:null,
//下个移动位置
nextPosition: null,
//记录已经走过的位置
hadWalk:{}
};
英雄像素转换为网格(10*10)坐标
var xIndex = parseInt(hero.y / 50, 10),
yIndex = parseInt(hero.x / 50, 10);
最开始时,
xIndex = 1
yIndex = 0
初始时满足!hero.nextPosition
if (!hero.nextPosition ||
((hero.x >= hero.nextPosition.x - 5 && hero.x <= hero.nextPosition.x) && (hero.y >= hero.nextPosition.y - 5 && hero.y <= hero.nextPosition.y))
)
进入后,满足往下走
else {
//判断往下能否走
if(MapData[xIndex][yIndex+1] && !this.hadWalk[xIndex+"_"+(yIndex+1)]){
this.dir = "down";
yIndex += 1;
}
此时
xIndex = 1
yIndex = 1
然后,
//设置下个移动位置
else {
hero.nextPosition = {y: xIndex * 50 + 5, x: yIndex * 50 + 5};
//记录已经走过的位置
hero.hadWalk[xIndex + "_" + yIndex] = true;
}
hero.nextPosition = {
x:55,y:55
}
然后,
//移动
switch(hero.dir){
case "down":
hero.y += hero.speed;
break;
case "up":
hero.y -= hero.speed;
break;
case "left":
hero.x -= hero.speed;
break;
case "right":
hero.x += hero.speed;
break;
default:
break;
}
此时,
hero = {
speed: 2, // 每秒移动的像素
x: 2,
y: 55,
循环回去:
然后在hero.x未满足条件:
if (!hero.nextPosition ||
((hero.x >= hero.nextPosition.x - 5 && hero.x <= hero.nextPosition.x) && (hero.y >= hero.nextPosition.y - 5 && hero.y <= hero.nextPosition.y))
)
时,有25次(50/2),跳过上面条件里的代码,直接执行以下代码:
//移动
switch(hero.dir){
case "down":
hero.y += hero.speed;
break;
case "up":
hero.y -= hero.speed;
break;
case "left":
hero.x -= hero.speed;
break;
case "right":
hero.x += hero.speed;
break;
default:
break;
}
当再次hero.x满足条件:
if (!hero.nextPosition ||
((hero.x >= hero.nextPosition.x - 5 && hero.x <= hero.nextPosition.x) && (hero.y >= hero.nextPosition.y - 5 && hero.y <= hero.nextPosition.y))
)
时,重复之前的逻辑。
如此循环。
such that