昨天在家装了IE9,感觉不错,界面终于清爽了,跑HTML5也还不错!期待IE10正式版!

  上一节我简单了介绍了HTML5 canvas 中的 drawImage方法,并绘制了一条扇动翅膀的小红龙,那么,今天我想让小龙在我的控制下飞行起来!

  首先我们再回顾下drawImage的九个参数,第一个参数是绘制对象,可以是图片,也可以是canvas,第二到五个参数是图片的裁剪参数,控制裁剪的位置与大小,第六至九个参数控制绘制到画布的位置与大小!到这里,估计大家都知道该怎么做了,只要更改图片在画面的位置就可以让小红龙“飞行”起来了!

  不过先别急,在这处理这个过程前,还有涉及到一个方向的问题,在2D游戏中,一般主流有四个方向或者八个方向两种(横版的是二个方向的,最近也比较流行),我这里将以八个方向为例,演示如何控制小红龙的飞行!

  为了方便控制,我先定义一个枚举对象,嗯,不过JS中不存在枚举对象,没关系,JS是一种十分自由的语言,我发现我越来越喜欢它了,我定义一个对象字面量!

var Directions={        North:6,        NorthEast:7,        East:0,        SouthEast:1,        South:2,        SouthWest:3,        West:4,        NorthWest:5    };

  本节演示的精灵素材继续沿用上一节的小红龙!我在这里用0-7 来代表东南西北等八个方向!这里哪个方向代表哪个数字是有一定规律的,细心的朋友可能发现了,在素材图中,每一行均代表了一个方向!Directions中每个方向的值对应每行的索引值,比如第一行,红龙的朝向为东,则Directions.East=0,第二行为东南,则Directions.SouthEast=1,依此类推!

  然后定义一个对象来保存精灵的当前位置,一个对象来保存精灵当前朝向!

var currentPoint = {"X":0,"Y":0};
var direction=0;

  然后可以通过onclick事件来处理精灵的移动!另外,我通过canvas的onmousemove事件来获取当前的鼠标点击坐标,完整代码如下

var ctx = document.getElementById("scene").getContext("2d");var ctxW = document.getElementById("scene").width;//画布宽var ctxH = document.getElementById("scene").height;//画面高var currentPoint = {"X":0,"Y":0};//精灵当前位置var mousePoint = {"X":0,"Y":0};//鼠标相对位置var direction=0;//当前朝向var Directions={        North:6,        NorthEast:7,        East:0,        SouthEast:1,        South:2,        SouthWest:3,        West:4,        NorthWest:5    };

var timer;//定时器//获取鼠标相对坐标document.getElementById("scene").οnmοusemοve=function(e){    e = e || window.event;if(e.pageX || e.pageY){        mousePoint.X=parseInt(e.pageX);        mousePoint.Y = parseInt(e.pageY);    }else{        mousePoint.X=parseInt(e.clientX + document.body.scrollLeft - document.body.clientLeft);        mousePoint.Y=parseInt(e.clientY + document.body.scrollTop  - document.body.clientTop);    }var boundingClient=document.getElementById("scene").getBoundingClientRect();    mousePoint.X-=parseInt(boundingClient.left+document.documentElement.scrollLeft);    mousePoint.Y-=parseInt(boundingClient.top+document.documentElement.scrollTop);};//获取两个坐标点的距离function GetDistance(x,y){return Math.sqrt(Math.pow((x.X - y.X), 2) + Math.pow((x.Y - y.Y), 2));};//获取精灵朝向function GetDirection(current,target){var n = (target.Y - current.Y) / (target.X - current.X);if (Math.abs(n) >= Math.tan(Math.PI * 3 / 8) && target.Y <= current.Y) {return Directions.North;    } else if (Math.abs(n) > Math.tan(Math.PI / 8) && Math.abs(n) < Math.tan(Math.PI * 3 / 8) && target.X > current.X && target.Y < current.Y) {return Directions.NorthEast;    } else if (Math.abs(n) <= Math.tan(Math.PI / 8) && target.X >= current.X) {return Directions.East;    } else if (Math.abs(n) > Math.tan(Math.PI / 8) && Math.abs(n) < Math.tan(Math.PI * 3 / 8) && target.X > current.X && target.Y > current.Y) {return Directions.SouthEast;    } else if (Math.abs(n) >= Math.tan(Math.PI * 3 / 8) && target.Y >= current.Y) {return Directions.South;    } else if (Math.abs(n) > Math.tan(Math.PI / 8) && Math.abs(n) < Math.tan(Math.PI * 3 / 8) && target.X < current.X && target.Y > current.Y) {return Directions.SouthWest;    } else if (Math.abs(n) <= Math.tan(Math.PI / 8) && target.X <= current.X) {return Directions.West;    } else if (Math.abs(n) > Math.tan(Math.PI / 8) && Math.abs(n) < Math.tan(Math.PI * 3 / 8) && target.X < current.X && target.Y < current.Y) {return Directions.NorthWest;    } else {return 0;    }};//判断精灵是否到达指定坐标function RatherPoint(p1,p2){switch(direction){case Directions.North:return p1.Y<=p2.Y;case Directions.NorthEast:return p1.X>=p2.X||p1.Y<=p2.Y;case Directions.East:return p1.X>=p2.X;case Directions.SouthEast:return p1.X>=p2.X||p1.Y>=p2.Y;case Directions.South:return p1.Y>=p2.Y;case Directions.SouthWest:return p1.X<=p2.X||p1.Y>=p2.Y;case Directions.West:return p1.X<=p2.X;case Directions.NorthWest:return p1.X<=p2.X || p1.Y<=p2.Y;    };return true;};//获取每次移动步长function GetMovePoint(toPoint){var m=0,n=0,t=1;var speed=10;//移动速度    switch(direction){case Directions.North:            m=0;            n=-speed;break;case Directions.NorthEast:            t = GetDistance(currentPoint,toPoint);            m=speed * (toPoint.X-currentPoint.X)/t;            n=-speed * (currentPoint.Y - toPoint.Y)/t;break;case Directions.East:            m=speed;            n=0;break;case Directions.SouthEast://alert("Directions.SouthEast"+toPoint.X);            t = GetDistance(currentPoint,toPoint);//alert(t);            m=speed * (toPoint.X-currentPoint.X)/t;            n=speed * (toPoint.Y-currentPoint.Y)/t;break;case Directions.South:            m=0;            n=speed;break;case Directions.SouthWest:            t = GetDistance(currentPoint,toPoint);            m=-speed * (currentPoint.X-toPoint.X)/t;            n=speed * (toPoint.Y-currentPoint.Y)/t;break;case Directions.West:            m=-speed;            n=0;break;case Directions.NorthWest:            t = GetDistance(currentPoint,toPoint);            m=-speed * (currentPoint.X-toPoint.X)/t;            n=-speed * (currentPoint.Y-toPoint.Y)/t;break;    };return {"X":m,"Y":n};}//鼠标点击事件 document.getElementById("scene").οnclick=function(){    clearInterval(timer);//清除定时器    var tp = {"X":mousePoint.X,"Y":mousePoint.Y};//鼠标点击坐标,引用值不能直接用mousePoint,不然当鼠标在点击后移动时,目的坐标会变更    direction = GetDirection(currentPoint,tp);//设置精灵朝向    var movePoint = GetMovePoint(tp);//获取移动步长    timer=setInterval(function(){//判断是否到达目标        if(!RatherPoint(currentPoint,tp)){            currentPoint.X+=movePoint.X;            currentPoint.Y+=movePoint.Y;//碰撞检测            if(currentPoint.X>ctxW){                currentPoint=ctxW;                clearInterval(timer);            }if(currentPoint.X<0){                currentPoint=0;                clearInterval(timer);            }if(currentPoint.Y>ctxH){                currentPoint=ctxH;                clearInterval(timer);            }if(currentPoint.Y<0){                currentPoint=0;                clearInterval(timer);            }        }else{            clearInterval(timer);        }    },100);}

var index=0;var img = new Image();img.οnlοad=function(){    setInterval(function(){if(index>=9){            index=0;        }else{            index++;        }        ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);        ctx.drawImage(img,index * 75,direction * 70 ,75,70,currentPoint.X,currentPoint.Y,75,70);    },50);}img.src="1.jpg";

  

  GetDistance, GetDirection这两个方法其实我是直接从深蓝的博客中的copy过来的,有兴趣的朋友可以去看下他写的Silverlight游戏开发系列教程,写得非常好,地址是:http://www.cnblogs.com/alamiye010

  其实HTML5除了安全性能上面外,有一些效果处理起来还是相当方便的!大家玩魔兽时,对山丘之王的天神下凡应该都有印象,小矮人大吼一声,身子迅速变大,威风凛凛,其实用HTML5来做的话,非常简单的,其实就是图片缩放效果而已!

  不废话,直接上代码:

var ctx = document.getElementById("scene").getContext("2d");var index=0;var img = new Image();var size = 1;var timer;img.οnlοad=function(){    setInterval(function(){if(index>=9){            index=0;        }else{            index++;        }        ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);        ctx.drawImage(img,index * 75,0 ,75,70,20,20,parseInt(75*size),parseInt(70*size));    },50);}function BieShen(){    size = 1;    timer=setInterval(function(){        size+=0.1;//设定每次增大10%        if(size>2){            size=2;            clearInterval(timer);        }    },50);}img.src="1.jpg";

  到这里,一个基本的精灵就已经出现了!不过如果用来做游戏的话,这样零散的代码是很痛苦的,下一节,我将介绍如果封装这些代码!

  本节代码源码下载地址:http://files.cnblogs.com/hnvvv/html5_Game_L1_2.zip (注:变身效果也在里面,图片是直接以base64的字符串直接保存在HTML中,下载后直接用火狐,Chrome,IE9都可以运行)

  演示地址:http://www.iis0.com/html5/ (注:里面的代码比文章里面的要新一些,已经完成了基本的精灵,地图等,会不定时修改,每篇文章的源代码直接在文章后附出,不单独出现在演示地址中)

  目录地址:http://www.cnblogs.com/hnvvv/archive/2012/01/09/2317336.html

  

  欢迎大家回复你的意见,比如哪些东西需要详细介绍,哪些东西可以简写,代码有更好的实现方法等等,我会一一改进的!

转载于:https://www.cnblogs.com/hnvvv/archive/2012/01/14/2322218.html

html5 Game开发系列文章之 二 精灵(下)相关推荐

  1. html5 Game开发系列文章之 三 搭建基本游戏框架(代码封装)

    在之前的二节中,我做出一个基本的游戏精灵--一条红色的飞行的小飞龙,但是在进行下一步开发前,我觉得有必要对现有的代码进行封装!在这一节中,我将封装一些基本的方法,并演示如何在JS中实现继承! 首先了解 ...

  2. HTML5游戏开发系列教程5(译)

    原文地址:http://www.script-tutorials.com/html5-game-development-lesson-5/ 最终我决定准备下一篇游戏开发系列的文章,我们将继续使用can ...

  3. Windows Mobile 开发系列文章收藏 - Windows Mobile 6.x

    收集整理一些Windows Mobile 6.x开发相关文章, 文章及相关代码大部分搜集自网络,版权属于原作者! 智能手机      手机词汇      研发手机基本流程 WAP协议分析(1)     ...

  4. Android蓝牙开发系列文章-蓝牙设备类型知多少?

    在写<Android蓝牙开发系列文章-蓝牙音箱连接>时,计划细化出一篇讲解蓝牙设备类型的文章,现在它来了~ 阅读其他内容,可以点击<Android蓝牙开发系列文章-策划篇>,或 ...

  5. 一步步实现windows版ijkplayer系列文章之二——Ijkplayer播放器源码分析之音视频输出——视频篇...

    一步步实现windows版ijkplayer系列文章之一--Windows10平台编译ffmpeg 4.0.2,生成ffplay 一步步实现windows版ijkplayer系列文章之二--Ijkpl ...

  6. 【微信小程序开发•系列文章一】入门

    本系统文章主要有以下几篇: <[微信小程序开发•系列文章一]入门> <[微信小程序开发•系列文章二]视图层> <[微信小程序开发•系列文章三]数据层> <[微 ...

  7. Asp.net服务器控件开发系列文章 汇总

    简介:         Asp.net包含一个页面和控件框架,即WebForms,服务器控件是WebForms编程模型的基本要素,控件简化了页面开发的过程,控件为代码复用和封装提供了一种机制,非常适合 ...

  8. Android蓝牙开发系列文章-扫不到蓝牙设备,你的姿势对了吗?

    在写<Android蓝牙开发系列文章-蓝牙音箱连接>时,计划细化出两篇文章,分别是: 关于蓝牙设备类型分类的,这个已经完成了,阅读请点击<Android蓝牙开发系列文章-蓝牙设备类型 ...

  9. oracle迁移postsql的,osdba's blog : Oracle迁移PostgreSQL系列文章之二:merge语句

    Oracle迁移PostgreSQL系列文章之二:merge语句 Posted on 2015-03-06 11:12:46 by osdba 我们知道,Oracle中有一个特别的merge语句.而P ...

最新文章

  1. python线程的注意点(线程之间执行是无序的、主线程会等待所有的子线程执行结束再结束(守护主线程)、线程之间共享全局变量、线程之间共享全局变量数据出现错误问题(线程等待(join)、互斥锁))
  2. (转)数据库设计范式深入浅出
  3. c如何返回数组给java
  4. 2018年网络规划设计师下午真题
  5. 管理系统网页模板_档案管理系统应该涵盖一些什么功能?
  6. 6-3 断言与防御式编程
  7. 使用libxml2库生成和解析文件
  8. 简明 Python 教程
  9. C语言求质数的几种简单易懂方法
  10. 动态场景下的语义SLAM的简单实现(基于YOLOv5目标检测)
  11. 手把手教你搭建属于自己的服务器
  12. Latex数学用法总结
  13. 什么是南桥芯片和北桥芯片?南桥芯片和北桥芯片区别
  14. 直播运营-直播抠图效果完整展示
  15. 人物-作家-马克·吐温:马克·吐温
  16. TPshop项目-功能测试(1)
  17. CDC-NCM和CDC-ECM性能差别
  18. Shiro密码加密 盐值加密
  19. ubuntu下查看硬件信息等指令整理,安装并简单运行HotSpot
  20. 高数考研归纳 - 积分学 - 重积分

热门文章

  1. 夏普将在迪拜推出植物工厂种草莓
  2. 重生之我是赏金猎人-SRC漏洞挖掘(二)-逆向app破解数据包sign值实现任意数据重放添加
  3. VSCode编译C程序
  4. Python 三角形面积计算
  5. linux中nice和prio关系,进程调度 – Linux内核API task_nice
  6. WPF实现鼠标划过点亮粒子背景特效
  7. RHEL9.0 安全启动提示Verification failed: (0x1A) Secureity Violation解决方法
  8. Bilinear CNN Model理解(附代码实现)
  9. v-if、v-show、v-html 的原理
  10. 如何在谷歌Chrome新版浏览器中打开并编辑Word/Excel/PPT等Office文档?(视频演示)