昨天在家裝了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").onmousemove=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").onclick=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.onload=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.onload=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
歡迎大家回復你的意見,比如哪些東西需要詳細介紹,哪些東西可以簡寫,代碼有更好的實現方法等等,我會一一改進的!