开发html5 2d 赛车游戏以及打包发布为手机APP 第三话 拖动我们的主角车子
原本打算直接讲如何让NPC自动出来,但是检查代码的时候发现要让NPC车子出来得涉及到面向对象。所以决定这话先讲简单的面向对象化,还有怎么让主角车子能被拖动起来。
那么,我们就得修改一下咱们原来的代码,定义一个Car的类和定义用于保存Car类实例化对象的 zhujue
var zhujue; function Car(x,y,width,height,img) { this.x=x; this.y=y; this.width=width; this.height=height; this.img=img; }
Car类的属性有横坐标x,竖坐标y,宽width,高height,还有用保存Image()实例化对象的img,
然后在init()方法里面实例化 Car类,保存于zhujue, 把原先我们代码里面的主角车的那些属性的值都分别保存于zhujue.x ; zhujue.y ; zhujue.width ; zhujue.height ; zhujue.img
function init() { ................. //实例化 zhujue=Object.create(Car); // zhujue.x=canvas1.width / 2 - 40 / 2; zhujue.y=canvas1.height - 80; zhujue.width=40; zhujue.height=80; zhujuepic = new Image(); zhujue.img=zhujuepic; ................. }
我们画主角车的代码也改一改,改为zhujue的每一项属性
ctx.drawImage(zhujue.img, zhujue.x, zhujue.y, zhujue.width, zhujue.height);
这样一改,一看其实和上一话的效果差不多,但是区别就在于主角车的每一样属性这时已经是可变的了,这样也是为了后面能自动出现NPC车辆作准备
////////////////////////////////////////////////////////////////////////////////////////
咱们接下来要做的就是实现主角车辆能被拖拽移动的代码
html5在移动设备上的拖拽功能离不开下面的代码
添加手指点下去时的事件监听处理,要是监听到,就到onTouchStart方法里面去处理 canvas1.addEventListener('touchstart', onTouchStart, false); 添加手指点下去并移动时的事件监听处理,要是监听到,就到onTouchMove方法里面去处理 canvas1.addEventListener('touchmove',onTouchMove,false); 添加手指终止拖拽时的事件监听处理,要是监听到,就到onTouchEnd方法里面去处理 canvas1.addEventListener('touchend',onTouchEnd,false);
//监听到手指点下去事件的发生,执行下面代码 function onTouchStart(event) { ............. } //监听到手指点了下去并拖拽事件的发生,执行下面代码 function onTouchMove(event) { ............. } //监听到手指终止拖拽事件的发生,执行下面代码 function onTouchEnd(event) { .............. }
那么怎么确定手指点到了主角车,,而不是路面背景呢??
咱们要用到一个叫做碰撞检测功能的代码,所谓碰撞检测就是检测游戏中2件物体有没有碰撞;于是,检测手指是否碰撞到主角车也是可以实现的
function checkimpact(finger_x, finger_y, el2) { var e1 = { x: finger_x, y: finger_y, w: 10, h: 10 } var e2 = { x: el2.x, y: el2.y, w: el2.width, h: el2.height } var px, py; px = e1.x <= e2.x ? e2.x : e1.x; py = e1.y <= e2.y ? e2.y : e1.y; if (px >= e1.x && px <= e1.x + e1.w && py >= e1.y && py <= e1.y + e1.h && px >= e2.x && px <= e2.x + e2.w && py >= e2.y && py <= e2.y + e2.h) { return true; } else { return false; } }
解释:参数finger_x用于传递手指点击下的横坐标,参数finger_y用于传递手指点击下的竖坐标,el2代表要检测是否和手指发生碰撞的物件(这里主要是主角车)
var e1其实就是用来保存手指点下去的横坐标,竖坐标,还有影响范围的宽和高
var e2就是用来保存主角车的横坐标,竖坐标,主角车的宽和高
后面整个的就是对两个物件的碰撞检测判断,下面4个判断流程不用修改,当返回true的时候就代表碰撞发生了;当返回 false的时候,就代表碰撞没有发生
var px, py; px = e1.x <= e2.x ? e2.x : e1.x; py = e1.y <= e2.y ? e2.y : e1.y; if (px >= e1.x && px <= e1.x + e1.w && py >= e1.y && py <= e1.y + e1.h && px >= e2.x && px <= e2.x + e2.w && py >= e2.y && py <= e2.y + e2.h) { return true; } else { return false; }
接着定义全局变量 is_clicked_zhujue,用于保存手指和主角车的碰撞检测结果
var is_clicked_zhujue;
然后在处理手指点击下事件发生的方法onTouchStart()里面去调用checkimpact()方法,看看是否点中了主角车
function onTouchStart(event) { //手指点击事件的实例化对象 var touch = event.targetTouches[0]; //如果点中主角车则把true赋值给is_clicked_zhujue if(checkimpact(touch.pageX,touch.pageY,zhujue)) { //alert("1"); is_clicked_zhujue=true; } }
解释:大家看到//alert("1");可能会问是啥东西,有啥用途,,这是JS的弹框代码,如果把双斜杠//注释符号去掉,结合整个if(........)判断,就是当手指点击到主角车的时候,显示一个弹框,弹框的内容为“1”(默认代码里注释掉了弹框),然后把is_clicked_zhujue赋值为true
如果用的是HBuilder,我们复制HBuilder自带浏览器的当前页面地址,然后在360浏览器或者Google Chrome浏览器打开这个网址,按键盘上的F12打开调试模式,Device选择要模拟调试的设备型号(我随便选了iPhone5),然后点击一下主角车,看看有没有显示出弹框(普通网页浏览器由于只支持鼠标点击,不能模拟手指点击,所以我们这里要调试必须用到模拟手机模式,不然没法调试,另一个调试方法是用HBuilder线上打包为APK安装包,不过效率不好,除非你已经实现了全套功能,再放到自己的手机设备去调试)
上图显示点击了主角车,,出现了内容为“1”的弹框
想要当手指拖拽移动的时候,主角车子也跟着手指拖拽移动,到onTouchMove方法里面去实现
function onTouchMove(event) { //手指点击事件的实例化对象 var touch = event.targetTouches[0]; if(is_clicked_zhujue) { zhujue.x=touch.pageX-zhujue.width/2; zhujue.y=touch.pageY-zhujue.height/2; } }
解释:当手指拖拽移动,并且is_clicked_zhujue为true的时候,把主角的横坐标zhujue.x赋值为手指事件的X横坐标touch.pageX,把主角的竖坐标zhujue.y赋值为手指事件的Y竖坐标touch.pageY,这样,主角车就跟随手指拖拽移动了
最后,当手指点击事件终结并离开屏幕时,会自动进入onTouchEnd()方法,于是咱们在里面添加给is_clicked_zhujue的值赋为false的处理,防止下一次错误的拖拽
function onTouchEnd(event) { is_clicked_zhujue=false; }
效果
完整代码
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name="viewport" content="initial-scale=1.0, maximum-scale=1.0, user-scalable=no" /> <title>赛车游戏</title> <script type="text/javascript"> var ctx; var canvas1; var roadpic; var zhujuepic; var fenjiepic; var fen_y; var road_d; var zhujue; var is_clicked_zhujue; function Car(x,y,width,height,img) { this.x=x; this.y=y; this.width=width; this.height=height; this.img=img; } function init() { ctx = document.getElementById('canvas').getContext('2d'); canvas1 = document.getElementById('canvas'); canvas1.addEventListener('touchstart', onTouchStart, false); canvas1.addEventListener('touchmove',onTouchMove,false); canvas1.addEventListener('touchend',onTouchEnd,false); //------------------------------------------// zhujue=Object.create(Car); zhujue.x=canvas1.width / 2 - 40 / 2; zhujue.y=canvas1.height - 80; zhujue.width=40; zhujue.height=80; zhujuepic = new Image(); zhujue.img=zhujuepic; //------------------------------------------// roadpic = new Image(); fenjiepic = new Image(); roadpic.src = "img/road.png"; zhujuepic.src = "img/car1.png"; fenjiepic.src = "img/fenjie.png"; fen_y = 0; road_d = 1; setInterval(function(e) { animate(); }, 50); } function onTouchMove(event) { var touch = event.targetTouches[0]; if(is_clicked_zhujue) { zhujue.x=touch.pageX-zhujue.width/2; zhujue.y=touch.pageY-zhujue.height/2; } } function onTouchStart(event) { var touch = event.targetTouches[0]; if(checkimpact(touch.pageX,touch.pageY,zhujue)) { //alert("1"); is_clicked_zhujue=true; } } function onTouchEnd(event) { is_clicked_zhujue=false; } function animate() { ctx.clearRect(0, 0, canvas1.width, canvas1.height); //----------------------------------// if (road_d == 1) { ctx.drawImage(roadpic, 0, 0, canvas1.width + 8, canvas1.height + 8); road_d = 0; } else { ctx.drawImage(roadpic, 0, 0, canvas1.width, canvas1.height); road_d = 1; } //----------------------------------// for (var i = 0; i < 50; i++) { ctx.drawImage(fenjiepic, canvas1.width / 2 - 10 / 2, fen_y - 80 * i, 10, 30); } if (fen_y < canvas1.height) { fen_y = fen_y + 150; } else if (fen_y >= canvas1.height) { fen_y = 0; } //----------------------------------// ctx.drawImage(zhujue.img, zhujue.x, zhujue.y, zhujue.width, zhujue.height); } function checkimpact(finger_x, finger_y, el2) { var e1 = { x: finger_x, y: finger_y, w: 10, h: 10 } var e2 = { x: el2.x, y: el2.y, w: el2.width, h: el2.height } var px, py; px = e1.x <= e2.x ? e2.x : e1.x; py = e1.y <= e2.y ? e2.y : e1.y; if (px >= e1.x && px <= e1.x + e1.w && py >= e1.y && py <= e1.y + e1.h && px >= e2.x && px <= e2.x + e2.w && py >= e2.y && py <= e2.y + e2.h) { return true; } else { return false; } } </script> </head> <body onLoad="init();"> <canvas id="canvas" width="300" height="540"> </canvas> </body> </html>