html5 Game开发系列文章之 二 精灵(下)
昨天在家装了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开发系列文章之 二 精灵(下)相关推荐
- html5 Game开发系列文章之 三 搭建基本游戏框架(代码封装)
在之前的二节中,我做出一个基本的游戏精灵--一条红色的飞行的小飞龙,但是在进行下一步开发前,我觉得有必要对现有的代码进行封装!在这一节中,我将封装一些基本的方法,并演示如何在JS中实现继承! 首先了解 ...
- HTML5游戏开发系列教程5(译)
原文地址:http://www.script-tutorials.com/html5-game-development-lesson-5/ 最终我决定准备下一篇游戏开发系列的文章,我们将继续使用can ...
- Windows Mobile 开发系列文章收藏 - Windows Mobile 6.x
收集整理一些Windows Mobile 6.x开发相关文章, 文章及相关代码大部分搜集自网络,版权属于原作者! 智能手机 手机词汇 研发手机基本流程 WAP协议分析(1) ...
- Android蓝牙开发系列文章-蓝牙设备类型知多少?
在写<Android蓝牙开发系列文章-蓝牙音箱连接>时,计划细化出一篇讲解蓝牙设备类型的文章,现在它来了~ 阅读其他内容,可以点击<Android蓝牙开发系列文章-策划篇>,或 ...
- 一步步实现windows版ijkplayer系列文章之二——Ijkplayer播放器源码分析之音视频输出——视频篇...
一步步实现windows版ijkplayer系列文章之一--Windows10平台编译ffmpeg 4.0.2,生成ffplay 一步步实现windows版ijkplayer系列文章之二--Ijkpl ...
- 【微信小程序开发•系列文章一】入门
本系统文章主要有以下几篇: <[微信小程序开发•系列文章一]入门> <[微信小程序开发•系列文章二]视图层> <[微信小程序开发•系列文章三]数据层> <[微 ...
- Asp.net服务器控件开发系列文章 汇总
简介: Asp.net包含一个页面和控件框架,即WebForms,服务器控件是WebForms编程模型的基本要素,控件简化了页面开发的过程,控件为代码复用和封装提供了一种机制,非常适合 ...
- Android蓝牙开发系列文章-扫不到蓝牙设备,你的姿势对了吗?
在写<Android蓝牙开发系列文章-蓝牙音箱连接>时,计划细化出两篇文章,分别是: 关于蓝牙设备类型分类的,这个已经完成了,阅读请点击<Android蓝牙开发系列文章-蓝牙设备类型 ...
- oracle迁移postsql的,osdba's blog : Oracle迁移PostgreSQL系列文章之二:merge语句
Oracle迁移PostgreSQL系列文章之二:merge语句 Posted on 2015-03-06 11:12:46 by osdba 我们知道,Oracle中有一个特别的merge语句.而P ...
最新文章
- python线程的注意点(线程之间执行是无序的、主线程会等待所有的子线程执行结束再结束(守护主线程)、线程之间共享全局变量、线程之间共享全局变量数据出现错误问题(线程等待(join)、互斥锁))
- (转)数据库设计范式深入浅出
- c如何返回数组给java
- 2018年网络规划设计师下午真题
- 管理系统网页模板_档案管理系统应该涵盖一些什么功能?
- 6-3 断言与防御式编程
- 使用libxml2库生成和解析文件
- 简明 Python 教程
- C语言求质数的几种简单易懂方法
- 动态场景下的语义SLAM的简单实现(基于YOLOv5目标检测)
- 手把手教你搭建属于自己的服务器
- Latex数学用法总结
- 什么是南桥芯片和北桥芯片?南桥芯片和北桥芯片区别
- 直播运营-直播抠图效果完整展示
- 人物-作家-马克·吐温:马克·吐温
- TPshop项目-功能测试(1)
- CDC-NCM和CDC-ECM性能差别
- Shiro密码加密 盐值加密
- ubuntu下查看硬件信息等指令整理,安装并简单运行HotSpot
- 高数考研归纳 - 积分学 - 重积分
热门文章
- 夏普将在迪拜推出植物工厂种草莓
- 重生之我是赏金猎人-SRC漏洞挖掘(二)-逆向app破解数据包sign值实现任意数据重放添加
- VSCode编译C程序
- Python 三角形面积计算
- linux中nice和prio关系,进程调度 – Linux内核API task_nice
- WPF实现鼠标划过点亮粒子背景特效
- RHEL9.0 安全启动提示Verification failed: (0x1A) Secureity Violation解决方法
- Bilinear CNN Model理解(附代码实现)
- v-if、v-show、v-html 的原理
- 如何在谷歌Chrome新版浏览器中打开并编辑Word/Excel/PPT等Office文档?(视频演示)