HTML5+JS游戏开发模块----canvas图片拖放
2016-09-26 13:27
423 查看
边学边做笔记,现在游戏开发进入下一个阶段,canvas图片拖放模块,如果要做塔防类游戏,少不了拖放炮塔之类的。HTML5提供拖放标签,draggable,ondrop,ondragover,ondragup等标签实现元素拖放,但是,canvas内部图片是无法使用这种方式的。
canvas拖放难点:
1.鼠标移动到canvas上,记录鼠标坐标
2.怎样确定鼠标是否在图片上
3.怎样让图片跟随鼠标移动(模拟拖图片过程)
4.怎样让图片落到指定方块内
首先,鼠标移动到canvas上记录坐标,这个简单,只需要注意下兼容就好
if(e.offSetX||e.layerX){//兼容浏览器
this.mx=e.offSetX==undefined?e.layerX:e.offSetX;
this.my=e.offSetY==undefined?e.layerY:e.offSetY;
}
鼠标是否在图片上,需要增加范围判断,然后在给个变量赋值this.isDown=true;,作为是否让图片跟随依据
//对比坐标位置,是否点击图片
if(this.mx<X+W&&this.mx>X){
if(this.my<Y+H&&this.my>Y){
this.isDown=true;
}
}else{
this.isDown=false;
}
鼠标点击了图片,那么接下来就要图片跟随鼠标运动,原理就是鼠标的xy坐标作为绘画点,插入绘制图片的函数中去,然后不断的清理屏幕,重新画图
//如果isDown为真
if(this.isDown){
X=this.mx-W/2;//图片跟随鼠标移动
Y=this.my-H/2;
}清理屏幕,画图函数就不说了
然后就是确定图片落在那个方块中
if(X<parseInt(X/50)*50+W&&X>parseInt(X/50)*50){
if(Y<parseInt(Y/50)*50+H&&Y>parseInt(Y/50)*50){
if(X<500&&Y<500&&X>0&&Y>0){
X=parseInt(X/50)*50; //转换为方块坐标
Y=parseInt(Y/50)*50;
}}
上面简单说一下,之前图片跟随时候,鼠标是保持在图片中间的部分,所以XY点就不是方块左上角的点,故我们要把XY重新赋值
到这里,上面几个难点基本解决,之后就是程序简单框架搭建,turret.js是炮塔类,但由于个人初学者,搞不明白鼠标事件为何接收不到内部this.x坐标,同样也无法改变,所以搞几个全局变量,但有违类搭建原则,而我无能为力,后期重新分配类的属性吧,暂时将就一下。
html页面
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>塔防拖放效果</title>
</head>
<body>
<canvas id="can" width="625" height="505" ></canvas>
<script type="text/javascript" src="js/turrets.js"></script>
<script type="text/javascript">
var can;
var ctx;
var img;
var mx;//鼠标坐标
var my;
var turret;//炮塔对象
window.requestAnimFrame=(function(){
return window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.oRequestAnimationFrame||window.msRequestAnimationFrame||function( /* function FrameRequestCallback */ callback, /* DOMElement Element */ element) {
return window.setTimeout(callback, 1000 / 60);
};
})();//自动执行函数
document.body.onload=game();//游戏入口
function game(){//入口函数
init();
gameLoop();//游戏循环
}
//初始化函数
function init(){
can=document.getElementById('can');
ctx=can.getContext('2d');
img=new Image();
img.src='images/tafan.png';
turret=new Turret();//new 实例
turret.img=img;//图片地址
turret.ctx=ctx;
turret.init();
//鼠标事件
can.addEventListener("mousedown",turret.OnMouseDown,false);
can.addEventListener("mousemove",turret.OnMouseMove,false);
can.addEventListener("mouseup",turret.OnMouseUp,false);
}
//游戏循环函数
function gameLoop(){
ctx.clearRect(0,0,655,505);
draw();
requestAnimFrame(gameLoop);
}
//绘画游戏
function draw(){
ctx.save();
for(var i=0;i<11;i++){
ctx.beginPath();
ctx.moveTo(i*50,0);
ctx.lineTo(i*50,500);
ctx.strokeStyle='#eee';
ctx.stroke();
ctx.closePath();
ctx.beginPath();
ctx.moveTo(0,i*50);
ctx.lineTo(500,i*50);
ctx.strokeStyle='#eee';
ctx.stroke();
ctx.closePath();
ctx.beginPath();
ctx.moveTo(515,i*50);
ctx.lineTo(615,i*50);
ctx.strokeStyle='#000';
ctx.stroke();
ctx.closePath();
}
for(var j=0;j<3;j++){
ctx.beginPath();
ctx.moveTo(j*50+515,0);
ctx.lineTo(j*50+515,500);
ctx.strokeStyle='#000';
ctx.stroke();
ctx.closePath();
}
ctx.beginPath();
turret.draw();//画出炮塔
ctx.closePath();
ctx.restore();
}
</script>
</body>
</html>
炮塔类,好失败的类,汗!!!
var X,Y,W,H,isRect;
//炮塔类
function Turret(img){//传入图片地址
this.x=X;
this.y=Y;
this.w=W;//图片宽
this.h=H;
this.mx;//鼠标坐标
this.my;
this.img=img;
this.isDown=false;//是否点中图片
this.ctx;
this.isRect=isRect;
}
//初始化炮塔
Turret.prototype.init=function(){
X=515;
Y=200;//图片坐标
W=50;
H=50;
isDown=false;//默认鼠标没有点击图片
}
//重绘制炮塔
Turret.prototype.draw=function(){
if(isRect&&X<500&&Y<500){
this.ctx.arc(X+W/2,Y+H/2,150,0,2*Math.PI,false);
this.ctx.fillStyle='rgba(232,225,225,0.2)';//火力范围
this.ctx.fill();
this.ctx.strokeStyle='red';
this.ctx.stroke();
}
this.ctx.drawImage(this.img,X,Y,W,H);
}
//鼠标按下,确定是否点击到炮塔图片
Turret.prototype.OnMouseDown=function(e){
isRect=true;
if(e.offSetX||e.layerX){//兼容浏览器
this.mx=e.offSetX==undefined?e.layerX:e.offSetX;
this.my=e.offSetY==undefined?e.layerY:e.offSetY;
}
//对比坐标位置,是否点击图片
if(this.mx<X+W&&this.mx>X){
if(this.my<Y+H&&this.my>Y){
this.isDown=true;
}
}else{
this.isDown=false;
}
}
//鼠标移动
Turret.prototype.OnMouseMove=function(e){
if(e.offSetX||e.layerX){//兼容浏览器
this.mx=e.offSetX==undefined?e.layerX:e.offSetX;
this.my=e.offSetY==undefined?e.layerY:e.offSetY;
}
//如果isDown为真
if(this.isDown){
X=this.mx-W/2;//图片跟随鼠标移动
Y=this.my-H/2;
}
}
//鼠标按键松开
Turret.prototype.OnMouseUp=function(e){
if(e.offSetX||e.layerX){//兼容浏览器
this.mx=e.offSetX==undefined?e.layerX:e.offSetX;
this.my=e.offSetY==undefined?e.layerY:e.offSetY;
}
//接收图片
//如果图片当前坐标在某一个格子内,重画
if(X<parseInt(X/50)*50+W&&X>parseInt(X/50)*50){
if(Y<parseInt(Y/50)*50+H&&Y>parseInt(Y/50)*50){
if(X<500&&Y<500&&X>0&&Y>0){
X=parseInt(X/50)*50; //转换为方块坐标
Y=parseInt(Y/50)*50;
}
else{
X=515;
Y=200;
this.isDown=false;
}
this.isDown=false;
isRect=false;
}
}
}
实现鼠标拖放功能,接下来可能是要出塔防游戏,不过目前遇到问题,子弹跟随目标移动,目标寻路算法(压根看不懂算法),子弹碰撞,子弹飞行范围等一系列难题等待我慢慢解决。加油。
游戏截图
完整代码下载
canvas拖放难点:
1.鼠标移动到canvas上,记录鼠标坐标
2.怎样确定鼠标是否在图片上
3.怎样让图片跟随鼠标移动(模拟拖图片过程)
4.怎样让图片落到指定方块内
首先,鼠标移动到canvas上记录坐标,这个简单,只需要注意下兼容就好
if(e.offSetX||e.layerX){//兼容浏览器
this.mx=e.offSetX==undefined?e.layerX:e.offSetX;
this.my=e.offSetY==undefined?e.layerY:e.offSetY;
}
鼠标是否在图片上,需要增加范围判断,然后在给个变量赋值this.isDown=true;,作为是否让图片跟随依据
//对比坐标位置,是否点击图片
if(this.mx<X+W&&this.mx>X){
if(this.my<Y+H&&this.my>Y){
this.isDown=true;
}
}else{
this.isDown=false;
}
鼠标点击了图片,那么接下来就要图片跟随鼠标运动,原理就是鼠标的xy坐标作为绘画点,插入绘制图片的函数中去,然后不断的清理屏幕,重新画图
//如果isDown为真
if(this.isDown){
X=this.mx-W/2;//图片跟随鼠标移动
Y=this.my-H/2;
}清理屏幕,画图函数就不说了
然后就是确定图片落在那个方块中
if(X<parseInt(X/50)*50+W&&X>parseInt(X/50)*50){
if(Y<parseInt(Y/50)*50+H&&Y>parseInt(Y/50)*50){
if(X<500&&Y<500&&X>0&&Y>0){
X=parseInt(X/50)*50; //转换为方块坐标
Y=parseInt(Y/50)*50;
}}
上面简单说一下,之前图片跟随时候,鼠标是保持在图片中间的部分,所以XY点就不是方块左上角的点,故我们要把XY重新赋值
到这里,上面几个难点基本解决,之后就是程序简单框架搭建,turret.js是炮塔类,但由于个人初学者,搞不明白鼠标事件为何接收不到内部this.x坐标,同样也无法改变,所以搞几个全局变量,但有违类搭建原则,而我无能为力,后期重新分配类的属性吧,暂时将就一下。
html页面
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>塔防拖放效果</title>
</head>
<body>
<canvas id="can" width="625" height="505" ></canvas>
<script type="text/javascript" src="js/turrets.js"></script>
<script type="text/javascript">
var can;
var ctx;
var img;
var mx;//鼠标坐标
var my;
var turret;//炮塔对象
window.requestAnimFrame=(function(){
return window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.oRequestAnimationFrame||window.msRequestAnimationFrame||function( /* function FrameRequestCallback */ callback, /* DOMElement Element */ element) {
return window.setTimeout(callback, 1000 / 60);
};
})();//自动执行函数
document.body.onload=game();//游戏入口
function game(){//入口函数
init();
gameLoop();//游戏循环
}
//初始化函数
function init(){
can=document.getElementById('can');
ctx=can.getContext('2d');
img=new Image();
img.src='images/tafan.png';
turret=new Turret();//new 实例
turret.img=img;//图片地址
turret.ctx=ctx;
turret.init();
//鼠标事件
can.addEventListener("mousedown",turret.OnMouseDown,false);
can.addEventListener("mousemove",turret.OnMouseMove,false);
can.addEventListener("mouseup",turret.OnMouseUp,false);
}
//游戏循环函数
function gameLoop(){
ctx.clearRect(0,0,655,505);
draw();
requestAnimFrame(gameLoop);
}
//绘画游戏
function draw(){
ctx.save();
for(var i=0;i<11;i++){
ctx.beginPath();
ctx.moveTo(i*50,0);
ctx.lineTo(i*50,500);
ctx.strokeStyle='#eee';
ctx.stroke();
ctx.closePath();
ctx.beginPath();
ctx.moveTo(0,i*50);
ctx.lineTo(500,i*50);
ctx.strokeStyle='#eee';
ctx.stroke();
ctx.closePath();
ctx.beginPath();
ctx.moveTo(515,i*50);
ctx.lineTo(615,i*50);
ctx.strokeStyle='#000';
ctx.stroke();
ctx.closePath();
}
for(var j=0;j<3;j++){
ctx.beginPath();
ctx.moveTo(j*50+515,0);
ctx.lineTo(j*50+515,500);
ctx.strokeStyle='#000';
ctx.stroke();
ctx.closePath();
}
ctx.beginPath();
turret.draw();//画出炮塔
ctx.closePath();
ctx.restore();
}
</script>
</body>
</html>
炮塔类,好失败的类,汗!!!
var X,Y,W,H,isRect;
//炮塔类
function Turret(img){//传入图片地址
this.x=X;
this.y=Y;
this.w=W;//图片宽
this.h=H;
this.mx;//鼠标坐标
this.my;
this.img=img;
this.isDown=false;//是否点中图片
this.ctx;
this.isRect=isRect;
}
//初始化炮塔
Turret.prototype.init=function(){
X=515;
Y=200;//图片坐标
W=50;
H=50;
isDown=false;//默认鼠标没有点击图片
}
//重绘制炮塔
Turret.prototype.draw=function(){
if(isRect&&X<500&&Y<500){
this.ctx.arc(X+W/2,Y+H/2,150,0,2*Math.PI,false);
this.ctx.fillStyle='rgba(232,225,225,0.2)';//火力范围
this.ctx.fill();
this.ctx.strokeStyle='red';
this.ctx.stroke();
}
this.ctx.drawImage(this.img,X,Y,W,H);
}
//鼠标按下,确定是否点击到炮塔图片
Turret.prototype.OnMouseDown=function(e){
isRect=true;
if(e.offSetX||e.layerX){//兼容浏览器
this.mx=e.offSetX==undefined?e.layerX:e.offSetX;
this.my=e.offSetY==undefined?e.layerY:e.offSetY;
}
//对比坐标位置,是否点击图片
if(this.mx<X+W&&this.mx>X){
if(this.my<Y+H&&this.my>Y){
this.isDown=true;
}
}else{
this.isDown=false;
}
}
//鼠标移动
Turret.prototype.OnMouseMove=function(e){
if(e.offSetX||e.layerX){//兼容浏览器
this.mx=e.offSetX==undefined?e.layerX:e.offSetX;
this.my=e.offSetY==undefined?e.layerY:e.offSetY;
}
//如果isDown为真
if(this.isDown){
X=this.mx-W/2;//图片跟随鼠标移动
Y=this.my-H/2;
}
}
//鼠标按键松开
Turret.prototype.OnMouseUp=function(e){
if(e.offSetX||e.layerX){//兼容浏览器
this.mx=e.offSetX==undefined?e.layerX:e.offSetX;
this.my=e.offSetY==undefined?e.layerY:e.offSetY;
}
//接收图片
//如果图片当前坐标在某一个格子内,重画
if(X<parseInt(X/50)*50+W&&X>parseInt(X/50)*50){
if(Y<parseInt(Y/50)*50+H&&Y>parseInt(Y/50)*50){
if(X<500&&Y<500&&X>0&&Y>0){
X=parseInt(X/50)*50; //转换为方块坐标
Y=parseInt(Y/50)*50;
}
else{
X=515;
Y=200;
this.isDown=false;
}
this.isDown=false;
isRect=false;
}
}
}
实现鼠标拖放功能,接下来可能是要出塔防游戏,不过目前遇到问题,子弹跟随目标移动,目标寻路算法(压根看不懂算法),子弹碰撞,子弹飞行范围等一系列难题等待我慢慢解决。加油。
游戏截图
完整代码下载
相关文章推荐
- HTML5+JS游戏开发模块----canvas打字游戏
- js html 图片显示 canvas 压缩
- HTML5+JS游戏开发模块----canvas打字游戏升级版
- js+canvas+html 写的打字游戏
- 关于js合成图片 html2canvas
- js写的一个html游戏向导模块
- js截图及绕过服务器图片保存至本地(html2canvas)
- Web开发之html2canvas 实现纯JS网页截图简单例子
- 1.C#开发winform 开发调运检疫离线制证功能。调用cLodop打印控件(NVelocity模块,生成HTML(包含cLodop打印控件的js),使用WebBrowser,展现网页)总结
- html5+css3+js开发APP实例教程2 -- 图片/图标列表
- Html5+Lufylegend.js游戏开发(一)引擎介绍及原理
- JS HTML图片显示Canvas 压缩功能
- 用 HTML Canvas 创建一个图片浏览器
- html-css-js的几款前端开发工具
- SilverLight 游戏开发《连连看》: (一)图片布局
- 《人人都玩开心网:Ext JS+Android+SSH整合开发Web与移动SNS》销售排名第4,发篇ExtJS的文章(拖放树结点)庆祝下
- Android游戏开发之旅四 Canvas和Paint实例
- C#开发WPF/Silverlight动画及游戏系列教程(Game Tutorial):(四十五)制作精美的可任意拖放对象的物品栏及装备栏
- Android游戏开发之旅(四)Canvas和Paint实例
- Asp.net 组件开发中web资源文件(图片、js)的调用问题