都看过这种广告吧,武器围着小人转圈圈,被武器碰到的小怪就扣血。看着很有意思,手痒尝试着用现有的知识实现一个
就不花时间去学习游戏引擎了,用纯原生js+canvas库做一个网页版的小实现吧
首先在canvas上将玩家操控的主角画出来,贴图就不做了,直接上圆点吧
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
| <html> <head> <title>dddemo</title> <style> canvas { border: 1px solid black; } </style> </head> <body> <canvas id="gameMap" width="400" height="400"></canvas> <script> var canvas = document.getElementById("gameMap"); var context = canvas.getContext("2d"); var cX = canvas.width/2; var cY = canvas.height/2; var r = 10; function draw() { context.clearRect(0,0,400,400); context.beginPath(); context.arc(cX,cY,r,0,2*Math.PI); context.closePath(); context.fillStyle = "black"; context.fillText("我是人物",cX-10,cY-12,800); context.fill(); requestAnimationFrame(draw); } draw(); </script> </body>
|
接下来最重要的就是他边上的武器了,剑呢?就不画了,直接拿根线条代替吧
CanvasRenderingContext2D.lineTo() 是 Canvas 2D API 使用直线连接子路径的终点到 x,y 坐标的方法
子路径即是圆点所在的坐标,那么x,y目标坐标呢?我们可以使用三角函数来进行计算
设(cx,cy)为圆心所在的坐标,ang为弧度制的角(初始为0),每次draw执行的时候都更新角+speed(速度)
根据三角函数与弧度制,cos(ang) = x/圆半径,而这里的圆半径就是线的长度,因此线的坐标为
x = cos(ang)*r,加上cX的偏移量,y轴同理;于是可以推导出线的坐标为
(cX+cos(ang)*线长度,cY+sin(ang)*线长度)
ok,写出相应的代码实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
| <html> <head> <title>dddemo</title> <style> canvas { border: 1px solid black; } </style> </head> <body> <canvas id="gameMap" width="400" height="400"></canvas> <script> var canvas = document.getElementById("gameMap"); var context = canvas.getContext("2d"); var cX = canvas.width/2; var cY = canvas.height/2; var r = 10; var ang = 0; function draw() { context.clearRect(0,0,400,400); context.beginPath(); context.arc(cX,cY,r,0,2*Math.PI); context.closePath(); context.fillStyle = "black"; context.fillText("我是人物",cX-10,cY-12,800); context.fill();
console.log(ang); console.log(cX+"/"+cY+"/圆坐标"); var lx = cX + Math.cos(ang)*80; var ly = cY + Math.sin(ang)*80; console.log(Math.cos(ang)+"/"+Math.sin(ang)); console.log("-----"); context.beginPath(); context.moveTo(cX,cY); context.lineTo(lx,ly); context.closePath(); context.stroke(); ang += 0.03; requestAnimationFrame(draw); } draw(); </script> </body>
|
ok,现在它会动了,接下来要让他移动。由于“武器”和“人物”的绘制都是根据圆心坐标来的,我们只需要监听wasd更改圆心的坐标就完事了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| window.addEventListener("keydown", handlerMove);
function handlerMove(event) { var key = event.key; switch(key) { case "w": cY -= 5; break; case "a": cX -= 5; break; case "s": cY += 5; break; case "d": cX += 5; break; default: break; } }
|
效果如下:
接下来我们设置几个敌人,敌人就用绿色的球球表示
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98
| <html> <head> <title>dddemo</title> <style> canvas { border: 1px solid black; } </style> </head> <body> <canvas id="gameMap" width="400" height="400"></canvas> <script> var canvas = document.getElementById("gameMap"); var context = canvas.getContext("2d"); var cX = canvas.width/2; var cY = canvas.height/2; var r = 10; var ang = 0; var mX = cX+128; var mY = cY+128; var mR = 10;
window.addEventListener("keydown", handlerMove);
function handlerMove(event) { var key = event.key; switch(key) { case "w": cY -= 5; break; case "a": cX -= 5; break; case "s": cY += 5; break; case "d": cX += 5; break; default: break; } } function draw() { context.clearRect(0,0,400,400); context.beginPath(); context.arc(cX,cY,r,0,2*Math.PI); context.closePath(); context.fillStyle = "black"; context.fillText("我是人物",cX-10,cY-12,800); context.fill(); var lx = cX+Math.cos(ang)*80; var ly = cY+Math.sin(ang)*80; console.log("圆坐标:("+cX+","+cY+")"); console.log("角:"+ang+"cos:"+Math.cos(ang)); console.log("角:"+ang+"sin:"+Math.sin(ang)); context.beginPath(); context.moveTo(cX,cY); context.lineTo(lx,ly); context.closePath(); context.stroke(); ang += 0.03; context.beginPath(); context.arc(mX,mY,mR,0,2*Math.PI); context.closePath(); context.fillStyle = "green"; context.fillText("我是敌人",mX-10,mY-12,800); context.fill(); requestAnimationFrame(draw); } draw(); </script> </body>
|
接下来在draw函数中,计算线与敌人的距离,两点间的距离公式
var dis = Math.sqrt(Math.pow((lx - mX), 2) + Math.pow((ly - mY), 2));
当被线击中时,敌人颜色变为红色,300毫秒后恢复绿色
稍微整理一下代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115
| <html> <head> <title>dddemo</title> <style> canvas { border: 1px solid black; } </style> </head> <body> <canvas id="gameMap" width="400" height="400"></canvas> <script> var canvas = document.getElementById("gameMap"); var context = canvas.getContext("2d"); var cX = canvas.width/2; var cY = canvas.height/2; var r = 10; var ang = 0; var mX = cX+128; var mY = cY+128; var mR = 10; var mC = "green"; var mH = 100;
window.addEventListener("keydown", handlerMove);
function handlerMove(event) { var key = event.key; switch(key) { case "w": cY -= 5; break; case "a": cX -= 5; break; case "s": cY += 5; break; case "d": cX += 5; break; default: break; } } function draw() { context.clearRect(0,0,400,400); context.beginPath(); context.arc(cX,cY,r,0,2*Math.PI); context.closePath(); context.fillStyle = "black"; context.fillText("我是人物",cX-10,cY-12,800); context.fill(); var lx = cX+Math.cos(ang)*80; var ly = cY+Math.sin(ang)*80; console.log("圆坐标:("+cX+","+cY+")"); console.log("角:"+ang+"cos:"+Math.cos(ang)); console.log("角:"+ang+"sin:"+Math.sin(ang)); context.beginPath(); context.moveTo(cX,cY); context.lineTo(lx,ly); context.closePath(); context.stroke(); ang += 0.03; if(mH>0){ context.beginPath(); context.arc(mX,mY,mR,0,2*Math.PI); context.closePath(); context.fillStyle = mC; context.fillText("敌人 血量:"+mH+"/100",mX-10,mY-12,800); context.fill(); } var dis = Math.sqrt(Math.pow((lx - mX), 2) + Math.pow((ly - mY), 2)); if(dis<mR){ mC = "red"; mH = mH-1; if(mH<=0){ mH = 0; mR = 0; } setTimeout(function(){ mC = "green"; },300); } requestAnimationFrame(draw); } draw(); </script> </body>
|
完整的效果如下:
溜了,等我画好贴图整个小游戏出来