Html5游戏框架createJs的简单用法
声明:本文为原创文章,如需转载,请注明来源WAxes,谢谢!http://www.it165.net/pro/html/201403/11105.html
楼主记忆力不好,最近刚好用了一下createJs框架,怕以后一段时间没用后会忘记,所以在此做个记录,或许以后用得着。
createJs网上的中文教程挺少的,以前UC有个Xcanvas的论坛有createJs的详细教程,但是随着XCanvas团队的解散, 那个网站也关闭了。。网上的大部分都是非常基础的教程,有点千遍一律的感觉。所以楼主就去把createJs下载下来,硬着头皮看英文文档了。凭着楼主这 英语六级只考了三百多分的渣渣来说,看起来很费力啊,不过还是勉强摸索出了大概的用法。所以现在就是学了多少就记录多少,之后或许也会不定期更新一下该框 架的新的学习心得。毕竟对自己以后还是有帮助的。
希望本文能帮到那些想学createJs的新手。因为楼主也是刚学的,所以本文或许有不正确之处,因此本文仅当参考,若有不正之处欢迎斧正。
闲话说到这,直接进入主题。
楼主用createJs写了个简单的跑酷游戏DEMO,就拿它做例子吧。 看DEMO戳我。
createJs的由来,基础什么的就不说了,就直接说createJs的用法吧。
首先到createJs官网下载,createJs分成easelJs(图形动画)、preloadJs(文件加载)、soundJs(音频控 制)以及tweenJs(补间动画)四部分,大家下载的时候,建议下载两个文件,一个是压缩版文件,用于项目中的引用,再下载个源码文件,用于查看用法、 API、demo等。因为楼主目前只用了easelJs和preloadJs,所以暂时就只说这两个,其实就这两个已经非常够用了。
接下来开始分析代码:
首先引入js文件
1.
<script src=
'easeljs-0.7.1.min.js'
></script>
2.
<script src=
'preloadjs-0.4.1.min.js'
></script>
然后进行舞台初始化操作:
01.
function init(){
02.
stage =
new
createjs.Stage(
'cas'
);
03.
C_W = stage.canvas.width;
04.
C_H = stage.canvas.height;
05.
06.
var manifest = [
07.
{src:
'image/man.png'
, id:
'man'
},
08.
{src:
'image/ground.png'
, id:
'ground'
},
09.
{src:
'image/bg.png'
, id:
'bg'
},
10.
{src:
'image/high.jpg'
, id:
'high'
},
11.
{src:
'image/coins.png'
, id:
'coin'
}
12.
]
13.
14.
loader =
new
createjs.LoadQueue(
false
);
15.
loader.addEventListener(
'complete'
, handleComplete);
16.
loader.loadManifest(manifest);
17.
18.
drawLoading();
19.
}
上面就用到了preloadJs中的方法,实例化一个loader,把需要加载的图片文件放在manifest里面,进行加载,加载完成后调用回调handleCompelete函数:
01.
function handleComplete(){
//当图片素材load完后执行该方法
02.
var manImage = loader.getResult(
'man'
),
03.
lowground = loader.getResult(
'ground'
),
04.
highground = loader.getResult(
'high'
),
05.
bgImage = loader.getResult(
'bg'
),
06.
coins = loader.getResult(
'coin'
);
07.
08.
sky =
new
createjs.Shape();
09.
sky.graphics.bf(bgImage).drawRect(
0
,
0
,C_W,C_H);
10.
sky.setTransform(
0
,
0
,
1
, C_H/bgImage.height);
11.
stage.addChild(sky);
12.
13.
man = createMan(
200
,
326
,manImage);
14.
15.
//该框为判定角色的判定区域
16.
kuang =
new
createjs.Shape();
17.
kuang.graphics.beginStroke(
'rgba(255,0,0,0.5)'
).drawRect(
0
,
0
, man.size().w , man.picsize().h*
1.5
);
18.
// stage.addChild(kuang);
19.
20.
mapHandle(lowground , highground , coins);
21.
22.
createjs.Ticker.timingMode = createjs.Ticker.RAF;
//设置循环方法,可以是requestAnimationFrame或者是setTimeout
23.
createjs.Ticker.setFPS(
30
);
//舞台帧率控制
24.
createjs.Ticker.addEventListener(
'tick'
, tick);
//绑定舞台每一帧的逻辑发生函数
25.
26.
window.addEventListener(
'keydown'
, function(event){
27.
event = event||window.event;
28.
if
(event.keyCode===
32
&&man.jumpNum<man.jumpMax){
29.
man.jump();
30.
}
31.
})
32.
}
获得加载完成后端的图片数据就直接用loader.getResult就可以获取了,跑酷游戏需要一个背景,所以,我们实例化一个sky,然后进行 位图绘制,bf方法是beginBitmapFill的缩写,该方法就是开始绘制位图,后面的drawRect是位图的绘制区域,区域当然是整个画布啦, 所以就是drawRect(0,0,C_W,C_H)。实例化出来sky后就直接添加到舞台stage里面就行了。接下来是实例化一个角 色,createMan方法后面有说,是自己封装的。
然后进行舞台循环设置,上面有注释了,就不说了。
下面是人物模块的封装
001.
(function(w){
002.
var FRAME_RATE =
13
,
//精灵表播放速度
003.
SCALE_X =
1.5
,
//X轴缩放
004.
SCALE_Y =
1.5
,
//Y轴缩放
005.
GRAVITY =
3
,
//重力加速度
006.
JUMP_SPEED =
2.6
,
//垂直速度
007.
WIDTH =
40
,
008.
HEIGHT =
96
,
009.
PICWIDTH =
64
,
010.
PICHEIGHT =
64
,
011.
PROPORTION =
150
/
1
;
//游戏与实际的距离比例
012.
013.
var Man = function(x , y , img){
014.
this
.x = x;
015.
this
.y = y;
016.
this
.endy = y;
017.
this
.vx =
0.5
;
018.
this
.vy =
0
;
019.
this
.ground = [];
020.
this
.state =
'run'
;
021.
this
.jumpNum =
0
;
022.
this
.jumpMax =
1
;
023.
this
.init(img);
024.
}
025.
026.
Man.prototype = {
027.
constructors:Man,
028.
029.
init:function(img){
030.
var manSpriteSheet =
new
createjs.SpriteSheet({
//实例化精灵表绘制器
031.
'images'
:[img],
032.
'frames'
:{
'regX'
:
0
,
'height'
:PICWIDTH,
'count'
:
45
,
'regY'
:
1
,
'width'
:PICHEIGHT},
033.
'animations'
:{
034.
'run'
:{
035.
frames:[
21
,
20
,
19
,
18
,
17
,
16
,
15
,
14
,
13
,
12
],
//精灵表每一帧的位置
036.
next:
'run'
,
//当精灵表循环完后的下一步动作
037.
speed:
1
,
//精灵表播放速度
038.
},
039.
'jump'
:{
040.
frames:[
34
,
35
,
36
,
37
,
38
,
39
,
40
,
41
,
42
,
43
],
041.
next:
'run'
,
042.
speed:
1
,
043.
},
044.
'die'
:{
045.
frames:[
8
,
7
,
6
,
5
,
4
,
3
,
2
,
1
,
0
],
046.
next:
'die'
,
047.
speed:
1
,
048.
}
049.
}
050.
});
051.
this
.sprite =
new
createjs.Sprite(manSpriteSheet ,
this
.state);
//实例化精灵
052.
this
.sprite.framerate = FRAME_RATE;
//精灵表绘制速率
053.
this
.sprite.setTransform(
this
.x,
this
.y, SCALE_X, SCALE_Y);
//设置精灵的位置
054.
stage.addChild(
this
.sprite);
//添加到舞台
055.
},
056.
057.
update:function(){
058.
var sprite =
this
.sprite;
059.
var time = createjs.Ticker.getInterval()/
1000
;
//获取当前帧与上一帧的时间间隔
060.
061.
if
(
this
.state===
'run'
){
062.
if
(sprite.x<
this
.x){
063.
sprite.x +=
this
.vx;
064.
}
else
{
065.
sprite.x =
this
.x
066.
}
067.
}
068.
if
(
this
.endy>sprite.y||
this
.state===
'jump'
){
//角色的动作处理
069.
var nexty = sprite.y+time*
this
.vy*PROPORTION;
070.
this
.vy += time*GRAVITY;
071.
sprite.y += time*
this
.vy*PROPORTION;
072.
if
(Math.abs(sprite.y-
this
.endy)<
10
&&
this
.vy>
0
){
073.
this
.state =
'run'
;
074.
sprite.y=
this
.endy;
075.
this
.vy =
0
;
076.
}
077.
}
078.
079.
if
(sprite.x+(PICWIDTH*SCALE_X-WIDTH)/
2
<
0
||sprite.y>C_H+
200
){
080.
this
.die();
081.
createjs.Ticker.reset();
082.
alert(
'you are Die!'
);
083.
}
084.
085.
switch
(
this
.state){
086.
case
'run'
:
087.
this
.jumpNum =
0
;
088.
break
;
089.
case
'die'
:
090.
if
(sprite.currentFrame===
0
){
091.
sprite.paused =
true
;
092.
}
093.
break
;
094.
}
095.
},
096.
097.
run:function(){
098.
this
.sprite.gotoAndPlay(
'run'
)
099.
},
100.
101.
jump:function(){
102.
this
.vy = -JUMP_SPEED;
103.
this
.state =
'jump'
;
104.
this
.sprite.gotoAndPlay(
'jump'
);
//让精灵表播放特定的动画
105.
this
.jumpNum++;
106.
},
107.
108.
die:function(){
109.
this
.state =
'die'
;
110.
this
.sprite.gotoAndPlay(
'die'
)
111.
},
112.
113.
size:function(){
114.
return
{
115.
w:WIDTH,
116.
h:HEIGHT
117.
}
118.
},
119.
120.
picsize:function(){
121.
return
{
122.
w:PICWIDTH,
123.
h:PICHEIGHT
124.
}
125.
}
126.
}
127.
128.
w.createMan = function(x , y , img){
129.
return
new
Man(x , y , img)
130.
};
131.
})(window)
人物模块封装就是简单的在createJs的封装之上进行进一步的封装,封装很简单,就是用createJs实例化一个精灵类,再绑定精灵表,因为本文讲createJs的大概用法,所以游戏的逻辑处理就不具体解释了。
下面贴出封装的石头以及金币模块,简单说下背景的循环,预先实例化一堆石头和金币,然后移动响应的石头,当石头移动到超出舞台区域时,把他的visible属性置为false,再重新添加一个石头在最后的位置进行新的一次移动。
001.
(function(w){
002.
var SPEED =
4
,
003.
COIN_STAY_X =
20
,
004.
COIN_STAY_Y =
20
,
005.
COIN_STAY_WIDTH =
30
,
006.
COIN_STAY_HEIGHT =
30
,
007.
COIN_SCALE_X =
0.08
,
008.
COIN_SCALE_Y =
0.08
;
009.
010.
//地上的石头类
011.
012.
var Stone = function(x,kind,allImage){
013.
this
.x = x;
014.
this
.kind = kind;
015.
this
.allImage = allImage;
016.
this
.init();
017.
}
018.
019.
var sp = Stone.prototype;
020.
021.
sp.init=function(){
022.
this
.shape =
new
createjs.Shape();
023.
if
(
this
.kind!==
'C'
){
024.
this
.h =
this
.allImage[
this
.kind].height;
025.
this
.w =
this
.allImage[
this
.kind].width*
2
;
026.
this
.y = C_H -
this
.h;
027.
this
.shape.graphics.beginBitmapFill(
this
.allImage[
this
.kind]).drawRect(
0
,
0
,
this
.w,
this
.h);
028.
this
.shape.setTransform(
this
.x,
this
.y,
1
,
1
);
029.
}
else
{
030.
this
.h = -
1000
;
031.
this
.w =
170
;
032.
this
.y = C_H -
this
.h;
033.
this
.shape.graphics.beginFill(
'#000'
).drawRect(
0
,
0
,
this
.w,
this
.h);
034.
this
.shape.setTransform(
this
.x,
this
.y,
1
,
1
);
035.
}
036.
this
.shape.visible =
false
;
037.
this
.shape.cache(
0
,
0
,
this
.w ,
this
.h);
038.
stage.addChild(
this
.shape);
039.
}
040.
041.
sp.update=function(){
042.
this
.shape.x -= SPEED;
043.
}
044.
045.
//金币类
046.
var Coin = function(image){
047.
this
.sizeX = COIN_SCALE_X;
048.
this
.sizeY = COIN_SCALE_Y;
049.
050.
this
.isget =
false
;
051.
this
.init = function(){
052.
this
.shape =
new
createjs.Shape();
053.
this
.shape.graphics.beginBitmapFill(image).drawRect(
0
,
0
, image.width, image.height);
054.
this
.shape.setTransform(
0
,
0
, COIN_SCALE_X, COIN_SCALE_Y);
055.
this
.shape.visible =
false
;
056.
stage.addChild(
this
.shape);
057.
}
058.
this
.init();
059.
060.
this
.update = function(){
061.
if
(
this
.isget){
062.
this
.sizeX =
this
.sizeX + ((COIN_STAY_WIDTH/image.width) -
this
.sizeX)*
0.1
;
063.
this
.sizeY =
this
.sizeY + ((COIN_STAY_HEIGHT/image.height) -
this
.sizeY)*
0.1
;
064.
this
.shape.setTransform(
065.
this
.shape.x + (COIN_STAY_X -
this
.shape.x)*
0.1
,
066.
this
.shape.y + (COIN_STAY_Y -
this
.shape.y)*
0.1
,
067.
this
.sizeX,
068.
this
.sizeY
069.
);
070.
071.
if
(Math.abs(
this
.shape.x-COIN_STAY_X)<
0.5
&&Math.abs(
this
.shape.y-COIN_STAY_Y)<
0.5
){
072.
this
.shape.visible =
false
;
073.
this
.isget =
false
;
074.
this
.sizeX = COIN_SCALE_X;
075.
this
.sizeY = COIN_SCALE_Y;
076.
this
.shape.setTransform(
0
,
0
,
this
.sizeX,
this
.sizeY);
077.
}
078.
}
else
{
079.
this
.shape.x -= SPEED;
080.
if
(
this
.shape.x<-image.width*COIN_SCALE_X){
081.
this
.shape.visible =
false
;
082.
}
083.
}
084.
}
085.
086.
this
.size = function(){
087.
return
{
088.
w:image.width*COIN_SCALE_X,
089.
h:image.height*COIN_SCALE_Y
090.
}
091.
}
092.
}
093.
094.
w.createCoin = function(image){
095.
return
new
Coin(image)
096.
}
097.
098.
w.createStone = function(x,kind,allImage){
099.
return
new
Stone(x,kind,allImage);
100.
}
101.
})(window)
封装方法跟上面的人物模块封装差不多,不过人物是用精灵类,石头金币则是用形状类了。就是通过位图的绘制,来绘制位图的图片,原理都一样。
最后是舞台逐帧处理的tick方法:
01.
function tick(event){
//舞台逐帧逻辑处理函数
02.
man.update();
03.
04.
kuang.x = man.sprite.x+(man.picsize().w*
1.5
-man.size().w)/
2
;
//参考框
05.
kuang.y = man.sprite.y;
06.
07.
man.ground.length=
0
;
08.
var cg = stoneHandle();
09.
10.
if
(man.ground[
0
]&&!cg) {
11.
man.ground.sort(function(a,b){
return
b.h-a.h});
12.
man.endy = man.ground[
0
].y-man.picsize().h*
1.5
;
13.
}
14.
15.
allCoins.forEach(function(cc , index){
16.
if
(cc.shape.visible){
17.
if
(
18.
Math.abs((kuang.x+man.size().w/
2
) - (cc.shape.x+cc.size().w/
2
)) <= (man.size().w+cc.size().w)/
2
&&
19.
Math.abs((kuang.y+man.size().h/
2
) - (cc.shape.y+cc.size().h/
2
)) <= (man.size().h+cc.size().h)/
2
&&
20.
!cc.isget
21.
){
22.
cc.isget =
true
;
23.
countCoin.innerHTML = parseInt(countCoin.innerHTML)+
1
24.
}
25.
cc.update();
26.
}
27.
})
28.
29.
document.getElementById(
'showFPS'
).innerHTML = man.endy
30.
stage.update(event)
31.
}
在每一帧的处理,就像自己写游戏一样啦,就是把舞台里的所有对象逐个进行逻辑运算,进行相应处理。
基本上createJs的用法还是相对比较简单并且强大的。比自己去造轮子能省很多功夫。下面贴出所有代码:
主页面:
001.
<!doctype html>
002.
<html lang=
'en'
>
003.
<head>
004.
<meta charset=
'UTF-8'
>
005.
<style>
006.
/*#cas{margin:auto;display: block;}*/
007.
.view{width: 700px;height:500px;position: relative;}
008.
#coins{width:90px;height: 70px;line-height: 70px;position:absolute;left:0px;top:
0
;padding-left:
60px;background:url(image/coins.png) no-repeat;background-size:30px
30px;background-position:20px 20px;font-size: 34px;color: #FFF;}
009.
</style>
010.
<title>跑酷游戏</title>
011.
<script src=
'easeljs-0.7.1.min.js'
></script>
012.
<script src=
'preloadjs-0.4.1.min.js'
></script>
013.
<script src=
'person.js'
></script>
014.
<script src=
'otherThings.js'
></script>
015.
</head>
016.
<body>
017.
<div
class
=
'view'
>
018.
<canvas id=
'cas'
width=
'700'
height=
'500'
>您的<a href=
"http://www.it165.net/edu/ewl/"
target=
"_blank"
class
=
"keylink"
>浏览器</a>不支持canvas</canvas>
019.
<div id=
'coins'
>
0
</div>
020.
</div>
021.
<div id=
'showFPS'
style=
'display: none;'
></div>
022.
<script>
023.
var fps = document.getElementById(
'showFPS'
),
024.
countCoin = document.getElementById(
'coins'
);
025.
var stage , C_W , C_H , loader;
026.
var man , ground , sky;
027.
028.
function init(){
029.
stage =
new
createjs.Stage(
'cas'
);
030.
C_W = stage.canvas.width;
031.
C_H = stage.canvas.height;
032.
033.
var manifest = [
034.
{src:
'image/man.png'
, id:
'man'
},
035.
{src:
'image/ground.png'
, id:
'ground'
},
036.
{src:
'image/bg.png'
, id:
'bg'
},
037.
{src:
'image/high.jpg'
, id:
'high'
},
038.
{src:
'image/coins.png'
, id:
'coin'
}
039.
]
040.
041.
loader =
new
createjs.LoadQueue(
false
);
042.
loader.addEventListener(
'complete'
, handleComplete);
043.
loader.loadManifest(manifest);
044.
045.
drawLoading();
046.
}
047.
048.
function drawLoading(){
049.
var ctx = stage.canvas.getContext(
'2d'
);
050.
ctx.textAlign =
'center'
;
051.
ctx.textBaseline =
'middle'
;
052.
ctx.fillStyle =
'#000'
;
053.
ctx.fillRect(
0
,
0
,C_W,C_H);
054.
ctx.fillStyle =
'#FFF'
;
055.
ctx.font =
'25px 微软雅黑'
;
056.
ctx.fillText(
'Loading...'
,C_W/
2
,C_H/
2
)
057.
}
058.
059.
//地图数据,mapData为石头数据,coinCode为金币数据
060.
var mapData = [
061.
'AAAACBBAAACABBAAACAABBBAAAABAAAAAACABCABCABCAAAABBBBBBAAAAACAAAAAAAAAAAABBBBBBAAAAAACACACACACAAAABBBBAAAAACAAAAAAAAAAAABBBBBBAAAAAACACACACACAABBAAAAAAABBA'
,
062.
'AAAAAAAACAABAAAAAAAAAAAAAAABBBBBBCBBBBBBBBAAAAAAAAAAAAAAAAAAAAAAAAACACACACACACACACACACBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBBBBBBBBBBBCBCBCBCAAAAAAAAAAAAAAAAAA'
,
063.
'AAAAAAAACAABAAAAAAAAAAAACACACACACACACACABAABABABABABABABACBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCABABACBCBCACACACACACACACACACACACACACACACACACACACACACAAAAAAAAAAAAAAAA'
064.
],
065.
coinCode = [
066.
'--------##########----------------############-#--#---##############-----------------##########-#-#-#-#-#-#-#-##-------################-------------###'
,
067.
'--#--#-------####----------##----###-----####-#--#---####-#-#-#-######------####------#####-#-#-#-#-#-#-#-##-------################---############--###'
,
068.
'-------#--#-------####----------##----##--##############---------######------####------#####-#-#-#-#-#-#-#-##----------################-------------###'
069.
]
070.
071.
function handleComplete(){
//当图片素材load完后执行该方法
072.
var manImage = loader.getResult(
'man'
),
073.
lowground = loader.getResult(
'ground'
),
074.
highground = loader.getResult(
'high'
),
075.
bgImage = loader.getResult(
'bg'
),
076.
coins = loader.getResult(
'coin'
);
077.
078.
sky =
new
createjs.Shape();
079.
sky.graphics.bf(bgImage).drawRect(
0
,
0
,C_W,C_H);
080.
sky.setTransform(
0
,
0
,
1
, C_H/bgImage.height);
081.
stage.addChild(sky);
082.
083.
man = createMan(
200
,
326
,manImage);
084.
085.
//该框为判定角色的判定区域
086.
kuang =
new
createjs.Shape();
087.
kuang.graphics.beginStroke(
'rgba(255,0,0,0.5)'
).drawRect(
0
,
0
, man.size().w , man.picsize().h*
1.5
);
088.
// stage.addChild(kuang);
089.
090.
mapHandle(lowground , highground , coins);
091.
092.
createjs.Ticker.timingMode = createjs.Ticker.RAF;
093.
createjs.Ticker.setFPS(
30
);
094.
createjs.Ticker.addEventListener(
'tick'
, tick);
095.
096.
window.addEventListener(
'keydown'
, function(event){
097.
event = event||window.event;
098.
if
(event.keyCode===
32
&&man.jumpNum<man.jumpMax){
099.
man.jump();
100.
}
101.
})
102.
}
103.
104.
105.
var mapIndex =
0
,
//地图序列
106.
Mix =
0
,
//地图数组的索引
107.
allStones = [],
//存放所有的石头
108.
allCoins = [],
//所有金币
109.
showSt = [];
//存放显示出来的石头
110.
111.
function mapHandle(lowground , highground , coins){
//初始化地图
112.
allStones.length =
0
;
113.
var stoneImage = {
'A'
:lowground ,
'B'
:highground},kind =
null
;
114.
for
(var i=
0
;i<
30
;i++){
//把需要用到的石头预先放入容器中准备好
115.
switch
(i){
116.
case
0
:kind=
'A'
;
break
;
117.
case
10
:kind=
'B'
;
break
;
118.
case
20
:kind=
'C'
;
break
;
119.
}
120.
var st = createStone(C_W , kind , stoneImage);
121.
allStones.push(st)
122.
}
123.
124.
for
(var i=
0
;i<
10
;i++){
//把需要用到的金币预先放入容器中
125.
var coin = createCoin(coins);
126.
allCoins.push(coin);
127.
}
128.
129.
Mix = Math.floor(Math.random()*mapData.length);
//随机地图序列
130.
for
(var i=
0
;i<
8
;i++){
131.
setStone(
false
)
132.
}
133.
}
134.
135.
function setStone(remove){
//添加陆地的石头
136.
var arg = mapData[Mix].charAt(mapIndex),
137.
coarg = coinCode[Mix].charAt(mapIndex),
138.
cc =
null
;
139.
140.
if
(coarg===
'#'
){
141.
for
(var i=
0
;i<allCoins.length;i++){
142.
if
(!allCoins[i].shape.visible){
143.
cc = allCoins[i];
144.
cc.shape.visible =
true
;
145.
break
;
146.
}
147.
}
148.
}
149.
150.
for
(var z=
0
;z<allStones.length;z++){
151.
if
(!allStones[z].shape.visible&&allStones[z].kind===arg){
152.
var st = allStones[z];
153.
st.shape.visible =
true
;
154.
st.shape.x = showSt.length===
0
?
0
:showSt[showSt.length-
1
].shape.x+showSt[showSt.length-
1
].w;
155.
156.
if
(cc){
157.
cc.shape.x = showSt.length===
0
?allStones[z].w/
2
-cc.size().w/
2
:showSt[showSt.length-
1
].shape.x+showSt[showSt.length-
1
].w+allStones[z].w/
2
-cc.size().w/
2
;
158.
cc.shape.y = arg===
'C'
? C_H-loader.getResult(
'high'
).height-
50
: allStones[z].shape.y-cc.size().h/
2
-
50
;
159.
}
160.
161.
if
(remove) showSt.shift();
162.
showSt.push(st);
163.
break
;
164.
}
165.
}
166.
167.
mapIndex++;
168.
if
(mapIndex>=mapData[Mix].length){
169.
Mix = Math.floor(Math.random()*mapData.length)
170.
mapIndex=
0
;
171.
}
172.
}
173.
174.
function tick(event){
//舞台逐帧逻辑处理函数
175.
man.update();
176.
177.
kuang.x = man.sprite.x+(man.picsize().w*
1.5
-man.size().w)/
2
;
//参考框
178.
kuang.y = man.sprite.y;
179.
180.
man.ground.length=
0
;
181.
var cg = stoneHandle();
182.
183.
if
(man.ground[
0
]&&!cg) {
184.
man.ground.sort(function(a,b){
return
b.h-a.h});
185.
man.endy = man.ground[
0
].y-man.picsize().h*
1.5
;
186.
}
187.
188.
allCoins.forEach(function(cc , index){
189.
if
(cc.shape.visible){
190.
if
(
191.
Math.abs((kuang.x+man.size().w/
2
) - (cc.shape.x+cc.size().w/
2
)) <= (man.size().w+cc.size().w)/
2
&&
192.
Math.abs((kuang.y+man.size().h/
2
) - (cc.shape.y+cc.size().h/
2
)) <= (man.size().h+cc.size().h)/
2
&&
193.
!cc.isget
194.
){
195.
cc.isget =
true
;
196.
countCoin.innerHTML = parseInt(countCoin.innerHTML)+
1
197.
}
198.
cc.update();
199.
}
200.
})
201.
202.
document.getElementById(
'showFPS'
).innerHTML = man.endy
203.
stage.update(event)
204.
}
205.
206.
207.
function stoneHandle(){
//石头的逐帧处理 cg为判断当前角色的位置是否被阻挡,overStone是保存离开stage的石头块
208.
var cg =
false
, overStone =
null
;
209.
allStones.forEach(function(s){
//遍历石头,确定玩家落点
210.
if
(s.shape.visible){
211.
s.update();
212.
213.
if
(s.shape.visible&&s.shape.x<=-s.w){
214.
overStone = s;
215.
}
216.
217.
var juli = Math.abs((kuang.x+man.size().w/
2
)-(s.shape.x+s.w/
2
));
218.
if
(juli<=(man.size().w+s.w)/
2
&& man.ground.indexOf(s)===-
1
){
219.
man.ground.push(s);
220.
221.
if
((s.shape.x+s.w/
2
)>(kuang.x+man.size().w/
2
)&&s.y<(kuang.y+man.size().h-
10
)){
222.
man.sprite.x = s.shape.x-man.picsize().w-
8
;
223.
cg =
true
;
224.
}
225.
}
226.
}
227.
});
228.
if
(overStone) {
229.
setStone(
true
);
230.
overStone.shape.visible =
false
;
231.
}
232.
233.
return
cg;
234.
}
235.
236.
init();
237.
</script>
238.
</body>
239.
</html>
人物模块:
001.
(function(w){
002.
var FRAME_RATE =
13
,
//精灵表播放速度
003.
SCALE_X =
1.5
,
//X轴缩放
004.
SCALE_Y =
1.5
,
//Y轴缩放
005.
GRAVITY =
3
,
//重力加速度
006.
JUMP_SPEED =
2.6
,
//垂直速度
007.
WIDTH =
40
,
008.
HEIGHT =
96
,
009.
PICWIDTH =
64
,
010.
PICHEIGHT =
64
,
011.
PROPORTION =
150
/
1
;
//游戏与实际的距离比例
012.
013.
var Man = function(x , y , img){
014.
this
.x = x;
015.
this
.y = y;
016.
this
.endy = y;
017.
this
.vx =
0.5
;
018.
this
.vy =
0
;
019.
this
.ground = [];
020.
this
.state =
'run'
;
021.
this
.jumpNum =
0
;
022.
this
.jumpMax =
1
;
023.
this
.init(img);
024.
}
025.
026.
Man.prototype = {
027.
constructors:Man,
028.
029.
init:function(img){
030.
var manSpriteSheet =
new
createjs.SpriteSheet({
031.
'images'
:[img],
032.
'frames'
:{
'regX'
:
0
,
'height'
:PICWIDTH,
'count'
:
45
,
'regY'
:
1
,
'width'
:PICHEIGHT},
033.
'animations'
:{
034.
'run'
:{
035.
frames:[
21
,
20
,
19
,
18
,
17
,
16
,
15
,
14
,
13
,
12
],
036.
next:
'run'
,
037.
speed:
1
,
038.
},
039.
'jump'
:{
040.
frames:[
34
,
35
,
36
,
37
,
38
,
39
,
40
,
41
,
42
,
43
],
041.
next:
'run'
,
042.
speed:
1
,
043.
},
044.
'die'
:{
045.
frames:[
8
,
7
,
6
,
5
,
4
,
3
,
2
,
1
,
0
],
046.
next:
'die'
,
047.
speed:
1
,
048.
}
049.
}
050.
});
051.
this
.sprite =
new
createjs.Sprite(manSpriteSheet ,
this
.state);
052.
this
.sprite.framerate = FRAME_RATE;
053.
this
.sprite.setTransform(
this
.x,
this
.y, SCALE_X, SCALE_Y);
054.
stage.addChild(
this
.sprite);
055.
},
056.
057.
update:function(){
058.
var sprite =
this
.sprite;
059.
var time = createjs.Ticker.getInterval()/
1000
;
060.
061.
if
(
this
.state===
'run'
){
062.
if
(sprite.x<
this
.x){
063.
sprite.x +=
this
.vx;
064.
}
else
{
065.
sprite.x =
this
.x
066.
}
067.
}
068.
if
(
this
.endy>sprite.y||
this
.state===
'jump'
){
069.
var nexty = sprite.y+time*
this
.vy*PROPORTION;
070.
this
.vy += time*GRAVITY;
071.
sprite.y += time*
this
.vy*PROPORTION;
072.
if
(Math.abs(sprite.y-
this
.endy)<
10
&&
this
.vy>
0
){
073.
this
.state =
'run'
;
074.
sprite.y=
this
.endy;
075.
this
.vy =
0
;
076.
}
077.
}
078.
079.
if
(sprite.x+(PICWIDTH*SCALE_X-WIDTH)/
2
<
0
||sprite.y>C_H+
200
){
080.
this
.die();
081.
createjs.Ticker.reset();
082.
alert(
'you are Die!'
);
083.
}
084.
085.
switch
(
this
.state){
086.
case
'run'
:
087.
this
.jumpNum =
0
;
088.
break
;
089.
case
'die'
:
090.
if
(sprite.currentFrame===
0
){
091.
sprite.paused =
true
;
092.
}
093.
break
;
094.
}
095.
},
096.
097.
run:function(){
098.
this
.sprite.gotoAndPlay(
'run'
)
099.
},
100.
101.
jump:function(){
102.
this
.vy = -JUMP_SPEED;
103.
this
.state =
'jump'
;
104.
this
.sprite.gotoAndPlay(
'jump'
);
105.
this
.jumpNum++;
106.
},
107.
108.
die:function(){
109.
this
.state =
'die'
;
110.
this
.sprite.gotoAndPlay(
'die'
)
111.
},
112.
113.
size:function(){
114.
return
{
115.
w:WIDTH,
116.
h:HEIGHT
117.
}
118.
},
119.
120.
picsize:function(){
121.
return
{
122.
w:PICWIDTH,
123.
h:PICHEIGHT
124.
}
125.
}
126.
}
127.
128.
w.createMan = function(x , y , img){
129.
return
new
Man(x , y , img)
130.
};
131.
})(window)
物品模块:
001.
(function(w){
002.
var SPEED =
4
,
003.
COIN_STAY_X =
20
,
004.
COIN_STAY_Y =
20
,
005.
COIN_STAY_WIDTH =
30
,
006.
COIN_STAY_HEIGHT =
30
,
007.
COIN_SCALE_X =
0.08
,
008.
COIN_SCALE_Y =
0.08
;
009.
010.
//地上的石头类
011.
012.
var Stone = function(x,kind,allImage){
013.
this
.x = x;
014.
this
.kind = kind;
015.
this
.allImage = allImage;
016.
this
.init();
017.
}
018.
019.
var sp = Stone.prototype;
020.
021.
sp.init=function(){
022.
this
.shape =
new
createjs.Shape();
023.
if
(
this
.kind!==
'C'
){
024.
this
.h =
this
.allImage[
this
.kind].height;
025.
this
.w =
this
.allImage[
this
.kind].width*
2
;
026.
this
.y = C_H -
this
.h;
027.
this
.shape.graphics.beginBitmapFill(
this
.allImage[
this
.kind]).drawRect(
0
,
0
,
this
.w,
this
.h);
028.
this
.shape.setTransform(
this
.x,
this
.y,
1
,
1
);
029.
}
else
{
030.
this
.h = -
1000
;
031.
this
.w =
170
;
032.
this
.y = C_H -
this
.h;
033.
this
.shape.graphics.beginFill(
'#000'
).drawRect(
0
,
0
,
this
.w,
this
.h);
034.
this
.shape.setTransform(
this
.x,
this
.y,
1
,
1
);
035.
}
036.
this
.shape.visible =
false
;
037.
this
.shape.cache(
0
,
0
,
this
.w ,
this
.h);
038.
stage.addChild(
this
.shape);
039.
}
040.
041.
sp.update=function(){
042.
this
.shape.x -= SPEED;
043.
}
044.
045.
//金币类
046.
var Coin = function(image){
047.
this
.sizeX = COIN_SCALE_X;
048.
this
.sizeY = COIN_SCALE_Y;
049.
050.
this
.isget =
false
;
051.
this
.init = function(){
052.
this
.shape =
new
createjs.Shape();
053.
this
.shape.graphics.beginBitmapFill(image).drawRect(
0
,
0
, image.width, image.height);
054.
this
.shape.setTransform(
0
,
0
, COIN_SCALE_X, COIN_SCALE_Y);
055.
this
.shape.visible =
false
;
056.
stage.addChild(
this
.shape);
057.
}
058.
this
.init();
059.
060.
this
.update = function(){
061.
if
(
this
.isget){
062.
this
.sizeX =
this
.sizeX + ((COIN_STAY_WIDTH/image.width) -
this
.sizeX)*
0.1
;
063.
this
.sizeY =
this
.sizeY + ((COIN_STAY_HEIGHT/image.height) -
this
.sizeY)*
0.1
;
064.
this
.shape.setTransform(
065.
this
.shape.x + (COIN_STAY_X -
this
.shape.x)*
0.1
,
066.
this
.shape.y + (COIN_STAY_Y -
this
.shape.y)*
0.1
,
067.
this
.sizeX,
068.
this
.sizeY
069.
);
070.
071.
if
(Math.abs(
this
.shape.x-COIN_STAY_X)<
0.5
&&Math.abs(
this
.shape.y-COIN_STAY_Y)<
0.5
){
072.
this
.shape.visible =
false
;
073.
this
.isget =
false
;
074.
this
.sizeX = COIN_SCALE_X;
075.
this
.sizeY = COIN_SCALE_Y;
076.
this
.shape.setTransform(
0
,
0
,
this
.sizeX,
this
.sizeY);
077.
}
078.
}
else
{
079.
this
.shape.x -= SPEED;
080.
if
(
this
.shape.x<-image.width*COIN_SCALE_X){
081.
this
.shape.visible =
false
;
082.
}
083.
}
084.
}
085.
086.
this
.size = function(){
087.
return
{
088.
w:image.width*COIN_SCALE_X,
089.
h:image.height*COIN_SCALE_Y
090.
}
091.
}
092.
}
093.
094.
w.createCoin = function(image){
095.
return
new
Coin(image)
096.
}
097.
098.
w.createStone = function(x,kind,allImage){
099.
return
new
Stone(x,kind,allImage);
100.
}
101.
})(window)
简单的记录,如果有疑问请在评论提出,楼主看到会尽量解答。。。。自己用createJs的时候,最好多查查API文档哈,createJs的文档还是挺全面的,如果看不懂英文,就跟楼主一样下载个有道词典吧。哈哈哈。