声明:本文为原创文章,如需转载,请注明来源WAxes,谢谢!
楼主记忆力不好,最近刚好用了一下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的文档还是挺全面的,如果看不懂英文,就跟楼主一样下载个有道词典吧。哈哈哈。
本文记录了一次使用createJs框架创建简单跑酷游戏的实践过程,包括游戏基本组件的封装、地图数据处理、角色与物品模块设计、以及舞台循环逻辑实现。提供了一个从零开始到完成的游戏示例,适合初学者理解和实践。
2517

被折叠的 条评论
为什么被折叠?



