标签:des android style class c code

|
1 |
<li><a
href="projects/flappybird/index.html">flappybird </a> <span> - Game</span></li> |


首先加载资源和添加游戏背景:
|
1
2
3
4
5 |
this.winSize = cc.Director.getInstance().getWinSize(); cc.SpriteFrameCache.getInstance().addSpriteFrames(res.flappy_packer); this.bgSprite = cc.Sprite.create(res.bg); this.bgSprite.setPosition(this.winSize.width / 2, this.winSize.height / 2); this.addChild(this.bgSprite, 0); |
游戏资源使用TexturePacker打包在flappy_packer.plist文件中,函数名跟cocos2d-x c++版本是一样的。 初始化地面:
|
1
2
3
4
5
6
7
8
9
10
11
12
13 |
Helloworld.prototype.initGround = function() { //cc.log("initGround"); this.groundSprite = cc.Sprite.create(res.ground); var
halfGroundW = this.groundSprite.getContentSize().width; var
halfGroundH = this.groundSprite.getContentSize().height; this.groundSprite.setAnchorPoint(0.5, 0.5); this.groundSprite.setPosition(halfGroundW / 2, halfGroundH / 2); this.addChild(this.groundSprite, GROUND_Z); var
action1 = cc.MoveTo.create(0.5, cc.p(halfGroundW / 2 - 120, this.groundSprite.getPositionY())); var
action2 = cc.MoveTo.create(0, cc.p(halfGroundW / 2, this.groundSprite.getPositionY())); var
action = cc.Sequence.create(action1, action2); this.groundSprite.runAction(cc.RepeatForever.create(action)); }; |
js可以使用proptotype来为类型添加行为,不理解的可以google一下。当然也可以跟init函数一样写在里面,像这样:
|
1
2
3
4
5
6
7 |
var Helloworld = cc.Layer.extend({ init:function
() { }, initGround::function() { } ); |
这里为地面定义两个动作,因为地面图片宽度是840px,而游戏屏幕分辨率指定是720×1280,所以先让地面向左移动120px,再迅速回到原位置。
初始化小鸟动画:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 |
Helloworld.prototype.initBird = function() { //cc.log("initBird"); var
animation = cc.AnimationCache.getInstance().getAnimation("FlyBirdAnimation") if(!animation) { var
animFrames = []; var
str = ""; var
birdFrameCount = 4; for
(var i = 1; i < birdFrameCount; ++ i) { str = "bird"
+ i + ".png"; var
frame = cc.SpriteFrameCache.getInstance().getSpriteFrame(str); animFrames.push(frame); } var
animation = cc.Animation.create(animFrames, 0.05); cc.AnimationCache.getInstance().addAnimation(animation, "FlyBirdAnimation"); } this.flyBird = cc.Sprite.createWithSpriteFrameName(res.fly_bird); this.flyBird.setAnchorPoint(cc.p(0.5, 0.5)); this.flyBird.setPosition(this.winSize.width / 2, this.winSize.height / 2); this.addChild(this.flyBird, BIRD_Z); var
actionFrame = cc.Animate.create(animation); var
flyAction = cc.RepeatForever.create(actionFrame); this.flyBird.runAction(cc.RepeatForever.create(flyAction)); }; |
小鸟自身动画是一个帧动画,创建成功后添加到缓存中。
初始化ready界面,就是游戏开始的时候提示用户点击的画面:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 |
Helloworld.prototype.initReady = function() { this.readyLayer = cc.Layer.create(); var
logo = cc.Sprite.createWithSpriteFrameName(res.logo); logo.setAnchorPoint(cc.p(0.5, 0.5)); logo.setPosition(this.winSize.width / 2, this.winSize.height - logo.getContentSize().height - 50); this.readyLayer.addChild(logo); var
getReady = cc.Sprite.createWithSpriteFrameName(res.getReady); getReady.setAnchorPoint(cc.p(0.5, 0.5)); getReady.setPosition(this.winSize.width / 2, this.winSize.height / 2 + getReady.getContentSize().height); this.readyLayer.addChild(getReady); var
click = cc.Sprite.createWithSpriteFrameName(res.click); click.setAnchorPoint(cc.p(0.5, 0.5)); click.setPosition(this.winSize.width / 2, getReady.getPositionY() - getReady.getContentSize().height / 2 - click.getContentSize().height / 2); this.readyLayer.addChild(click); this.addChild(this.readyLayer); }; |
效果如下:
添加点击屏幕时小鸟上升和下降自由落体的动画:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 |
Helloworld.prototype.runBirdAction = function
() { var
riseHeight = 50; var
birdX = this.flyBird.getPositionX(); var
birdY = this.flyBird.getPositionY(); var
bottomY = this.groundSprite.getContentSize().height - this.flyBird.getContentSize().height / 2; var
actionFrame = cc.Animate.create(cc.AnimationCache.getInstance().getAnimation("FlyBirdAnimation")); var
flyAction = cc.RepeatForever.create(actionFrame); //上升动画 var
riseMoveAction = cc.MoveTo.create(0.2, cc.p(birdX, birdY + riseHeight)); var
riseRotateAction = cc.RotateTo.create(0, -30); var
riseAction = cc.Spawn.create(riseMoveAction, riseRotateAction); //下落动画 //模拟自由落体运动 var
fallMoveAction = FreeFall.create(birdY - bottomY); var
fallRotateAction =cc.RotateTo.create(0, 30); var
fallAction = cc.Spawn.create(fallMoveAction, fallRotateAction); this.flyBird.stopAllActions(); this.flyBird.runAction(flyAction); this.flyBird.runAction(cc.Spawn.create( cc.Sequence.create(riseAction, fallAction) ) ); }; |
这里自定义了一个自由落体的Action:FreeFall:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76 |
var FreeFall = cc.ActionInterval.extend( { timeElasped:0, m_positionDeltaY:null, m_startPosition:null, m_targetPosition:null, ctor:function() { cc.ActionInterval.prototype.ctor.call(this); this.yOffsetElasped = 0; this.timeElasped = 0; this.m_positionDeltaY = 0; this.m_startPosition = cc.p(0, 0); this.m_targetPosition = cc.p(0, 0); }, initWithDuration:function
(duration) { if
(cc.ActionInterval.prototype.initWithDuration.call(this, duration)) { return
true; } return
false; }, initWithOffset:function(deltaPosition) { var
dropTime = Math.sqrt(2.0*Math.abs(deltaPosition)/k_Acceleration) * 0.1; //cc.log("dropTime=" + dropTime); if
(this.initWithDuration(dropTime)) { this.m_positionDeltaY = deltaPosition; return
true; } //cc.log("dropTime =" + dropTime + "; deltaPosition=" + deltaPosition); return
false; }, isDone:function() { if
(this.m_targetPosition.y >= this._target.getPositionY()) { return
true; } return
false; }, //Node的runAction函数会调用ActionManager的addAction函数,在ActionManager的addAction函数中会调用Action的startWithTarget,然后在Action类的startWithTarget函数中设置_target的值。 startWithTarget:function(target) { //cc.log("startWithTarget target=" + target); cc.ActionInterval.prototype.startWithTarget.call(this, target); this.m_startPosition = target.getPosition(); this.m_targetPosition = cc.p(this.m_startPosition.x, this.m_startPosition.y - this.m_positionDeltaY); }, update:function(dt) { this.timeElasped += dt; //cc.log("isdone=" + this.timeElasped); if
(this._target && !(this.m_targetPosition.y >= this._target.getPositionY())) { var
yMoveOffset = 0.5 * k_Acceleration * this.timeElasped * this.timeElasped * 0.3; if
(cc.ENABLE_STACKABLE_ACTIONS) { var
newPos = cc.p(this.m_startPosition.x, this.m_startPosition.y - yMoveOffset); if
(this.m_targetPosition.y > newPos.y) { newPos.y = this.m_targetPosition.y; this._target.stopAction(this); } this._target.setPosition(newPos); } else
{ this._target.setPosition(cc.p(this.m_startPosition.x, this.m_startPosition.y + this.m_positionDeltaY * dt)); } } } }); FreeFall.create = function(deltaPosition) { var
ff = new FreeFall(); ff.initWithOffset(deltaPosition); return
ff; }; |
模仿了CCActionInterval.js中的其他内置的Action,如MoveBy,主要重写了initWithDuration,startWithTarget,update,isDone函数。 initWithDuration是设置该action运行的时间,时间的长短决定下降的速度。 startWithTarget函数由ActionManager调用,设置_target的值。 update函数在ActionInterval的step函数中会调用,在这个函数中不断更新精灵的坐标,使用了自由落体计算位移的公式。 isDone函数设置了动作是否运行结束。 重力加速度和action运行的时间需要不断调试。
添加水管:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 |
function getRandom(maxSize) { return
Math.floor(Math.random() * maxSize) % maxSize; } Helloworld.prototype.addPipe = function
() { cc.log("addPipe"); var
ccSpriteDown = cc.Sprite.createWithSpriteFrameName(res.holdback1); var
pipeHeight = ccSpriteDown.getContentSize().height; var
pipeWidth = ccSpriteDown.getContentSize().width; var
groundHeight = this.groundSprite.getContentSize().height; //小鸟飞行区间高度 var
acrossHeight = 300; var
downPipeHeight = 100 + getRandom(400); // cc.log("downPipeHeight=" + downPipeHeight); var
upPipeHeight = this.winSize.height - downPipeHeight - acrossHeight - groundHeight; var
PipeX = this.winSize.width + pipeWidth / 2; ccSpriteDown.setZOrder(1); ccSpriteDown.setAnchorPoint(cc.p(0.5, 0.5)); ccSpriteDown.setPosition(cc.p(PipeX + pipeWidth / 2, groundHeight + pipeHeight / 2 - (pipeHeight - downPipeHeight))); var ccSpriteUp = cc.Sprite.createWithSpriteFrameName(res.holdback2); ccSpriteUp.setZOrder(1); ccSpriteUp.setAnchorPoint(cc.p(0.5, 0.5)); ccSpriteUp.setPosition(cc.p(PipeX + pipeWidth / 2, this.winSize.height + (pipeHeight- upPipeHeight) - pipeHeight / 2)); this.addChild(ccSpriteDown, PIPE_Z); this.addChild(ccSpriteUp, PIPE_Z); this.PipeSpriteList.push(ccSpriteDown); this.PipeSpriteList.push(ccSpriteUp); this.score += 1; }; |
分为上下两根水管,随机设置上下水管的高度,固定小鸟飞行区间的高度为300。然后把创建的水管放到数组中,同时每添加一排水管就增加一分。
添加碰撞检测函数:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27 |
Helloworld.prototype.getRect = function(a) { var
pos = a.getPosition(); var
content = a.getContentSize(); return
cc.rect(pos.x - content.width / 2, pos.y - content.height / 2, content.width, content.height); }; Helloworld.prototype.collide = function
(a, b) { var
aRect = this.getRect(a); var
bRect = this.getRect(b); return
cc.rectIntersectsRect(aRect, bRect); }; Helloworld.prototype.checkCollision = function
() { if
(this.collide(this.flyBird, this.groundSprite)) { //cc.log("hit floor"); this.birdFallAction(); return; } for
(var i = 0; i < this.PipeSpriteList.length; i++) { var
pipe = this.PipeSpriteList[i]; if
(this.collide(this.flyBird, pipe)) { cc.log("hit pipe i="
+ i); this.birdFallAction(); break; } } } |
采用最简单的方式:判断矩形是否相交。把小鸟分别跟地面和数组中的水管进行检测,如果发生碰撞,则执行小鸟死亡动画:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 |
Helloworld.prototype.birdFallAction = function
() { this.gameMode = OVER; this.flyBird.stopAllActions(); this.groundSprite.stopAllActions(); var
birdX = this.flyBird.getPositionX(); var
birdY = this.flyBird.getPositionY(); var
bottomY = this.groundSprite.getContentSize().height + this.flyBird.getContentSize().width / 2; var
fallMoveAction = FreeFall.create(birdY - bottomY); var
fallRotateAction =cc.RotateTo.create(0, 90); var
fallAction = cc.Spawn.create(fallMoveAction, fallRotateAction); this.flyBird.runAction(cc.Sequence.create(cc.DelayTime.create(0.1), fallAction) ); this.runAction(cc.Sequence.create(cc.DelayTime.create(1.0), cc.CallFunc.create(this.showGameOver, this)) ); } |
让小鸟旋转90度,然后垂直下落,然后显示game over画面:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56 |
Helloworld.prototype.showGameOver = function
() { var
userDefault = cc.UserDefault.getInstance(); var
oldScore = userDefault.getIntegerForKey("score"); var
maxScore = 0; if(this.score > oldScore) { maxScore = this.score; userDefault.setIntegerForKey("score", maxScore); }else
{ maxScore = oldScore; } var
gameOverLayer = cc.Layer.create(); cc.log("gameover="
+ res.gameover); var
gameOver = cc.Sprite.createWithSpriteFrameName(res.gameover); gameOver.setAnchorPoint(cc.p(0.5, 0.5)); gameOver.setPosition(this.winSize.width / 2, this.winSize.height - gameOver.getContentSize().height / 2 - 150); gameOverLayer.addChild(gameOver); var
scorePanel = cc.Sprite.createWithSpriteFrameName(res.scorePanel); scorePanel.setAnchorPoint(cc.p(0.5, 0.5)); scorePanel.setPosition(gameOver.getPositionX(), gameOver.getPositionY() - gameOver.getContentSize().height / 2 - scorePanel.getContentSize().height / 2 - 60); gameOverLayer.addChild(scorePanel); if(this.score > oldScore) { var
gold = cc.Sprite.createWithSpriteFrameName(res.gold); gold.setAnchorPoint(cc.p(0.5, 0.5)); gold.setPosition(68 + gold.getContentSize().width / 2, 72 + gold.getContentSize().height / 2); scorePanel.addChild(gold); }else
{ var
gray = cc.Sprite.createWithSpriteFrameName(res.gray); gray.setAnchorPoint(cc.p(0.5, 0.5)); gray.setPosition(68 + gray.getContentSize().width / 2, 72 + gray.getContentSize().height / 2); scorePanel.addChild(gray); } var
newScoreLabel = cc.LabelAtlas.create(this.score, res.number, 22, 28, ‘0‘); newScoreLabel.setAnchorPoint(cc.p(0.5, 0.5)); newScoreLabel.setScale(1.2); newScoreLabel.setPosition(scorePanel.getContentSize().width - newScoreLabel.getContentSize().width - 90, newScoreLabel.getContentSize().height / 2 + 180); scorePanel.addChild(newScoreLabel); var
maxScoreLabel = cc.LabelAtlas.create(maxScore, res.number, 22, 28, ‘0‘); maxScoreLabel.setAnchorPoint(cc.p(0.5, 0.5)); maxScoreLabel.setScale(1.2); maxScoreLabel.setPosition(newScoreLabel.getPositionX(), maxScoreLabel.getContentSize().height / 2 + 75); scorePanel.addChild(maxScoreLabel); var
start = cc.Sprite.createWithSpriteFrameName(res.start); var
startMenuItem = cc.MenuItemSprite.create(start, null, null, this.restartGame, this); var
startMenu = cc.Menu.create(startMenuItem); startMenu.setAnchorPoint(cc.p(0.5, 0.5)); startMenu.setPosition(this.winSize.width / 2 , scorePanel.getPositionY() - scorePanel.getContentSize().height / 2 - start.getContentSize().height / 2 - 60); gameOverLayer.addChild(startMenu); this.addChild(gameOverLayer, GAMEOVER_Z); }; |
显示game over时保存游戏数据,显示这局游戏的分数和历史最高分。
点击开始游戏按钮,就可以重新开始游戏:
|
1
2
3
4
5 |
Helloworld.prototype.restartGame = function() { var
scene = cc.Scene.create(); scene.addChild(Helloworld.create()); cc.Director.getInstance().replaceScene(cc.TransitionFade.create(1.2, scene)); }; |
记得在init函数中清空水管数组:
|
1 |
this.PipeSpriteList = []; |
下面是Helloworld类的代码:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73 |
var Helloworld = cc.Layer.extend({ gameMode:null, bgSprite:null, groundSprite:null, flyBird:null, PipeSpriteList:[], passTime: 0, winSize: 0, screenRect:null, readyLayer:null, score: 0, scoreLabel:null, init:function
() { cc.log("helloworld init"); this._super(); this.PipeSpriteList = []; this.winSize = cc.Director.getInstance().getWinSize(); cc.SpriteFrameCache.getInstance().addSpriteFrames(res.flappy_packer); this.bgSprite = cc.Sprite.create(res.bg); this.bgSprite.setPosition(this.winSize.width / 2, this.winSize.height / 2); this.addChild(this.bgSprite, 0); this.initGround(); this.initReady(); this.screenRect = cc.rect(0, 0, this.winSize.width, this.winSize.height); this.gameMode = READY; this.score = 0; this.scheduleUpdate(); this.setTouchEnabled(true); return
true; }, onTouchesBegan:function
(touches, event) { }, onTouchesMoved:function
(touches, event) { }, onTouchesEnded:function
(touches, event) { if
(this.gameMode == OVER) { return; } if
(this.gameMode == READY) { this.gameMode = START; this.readyLayer.setVisible(false); this.initBird();; } this.runBirdAction(); }, onTouchesCancelled:function
(touches, event) { }, update:function(dt) { if
(this.gameMode != START) { return; } for(var
i = 0; i < this.PipeSpriteList.length; ++ i) { var
pipe = this.PipeSpriteList[i]; pipe.setPositionX(pipe.getPositionX() - 3); if
(pipe.getPositionX() < -pipe.getContentSize().width / 2) { this.PipeSpriteList.splice(i, 1); //cc.log("delete pipe i=" + i); } } this.passTime += 1; if(this.passTime >= this.winSize.width / 6) { this.addPipe(); this.passTime = 0; } this.checkCollision(); } }); |
在update函数中更新水管的位置,如果水管出了左边的屏幕就从数组中移除,每经过一定的时间就添加一排水管。 现在看看index.html的内容,在浏览器中访问的就是它:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27 |
<!DOCTYPE HTML> <html> <head> <meta
charset="utf-8"> <title>Flappy Bird-codingnow.cn</title> <link
rel="icon"
type="image/png"
href="http://codingnow.cn/favicon.ico"> <meta
name="viewport"
content="user-scalable=no"/> <meta
name="screen-orientation"
content="portrait"/> <meta
name="apple-mobile-web-app-capable"
content="yes"/> <meta
name="full-screen"
content="yes"/> <meta
name="x5-fullscreen"
content="true"/> <style> body, canvas, div { -moz-user-select: none; -webkit-user-select: none; -ms-user-select: none; -khtml-user-select: none; -webkit-tap-highlight-color: rgba(0, 0, 0, 0); } </style> </head> <body
style="padding:0; margin: 0;text-align: center;background: #f2f6f8;"> <canvas
id="gameCanvas"
width="720"
height="1280"></canvas> <script
src="cocos2d.js"></script> <img
style="position:absolute;left:-9999px"
src="http://zhoujianghai.github.io/games/flappybird/res/icon_wechat.png"
onerror="this.parentNode.removeChild(this)"> </body> </html> |
在这个文件中指定了canvas的尺寸。html的内容从cocos2d-html5自带的例子中copy过来的,这里在底部添加了一个img,这个图片是分享到微信朋友圈时显示在左边的图片。 当浏览器窗口大小改变时,为了能自动调整显示游戏完整画面,需要在main.js的applicationDidFinishLaunching函数中添加:
|
1
2
3 |
cc.EGLView.getInstance().adjustViewPort(true); cc.EGLView.getInstance().setDesignResolutionSize(720, 1280, cc.RESOLUTION_POLICY.SHOW_ALL); cc.EGLView.getInstance().resizeWithBrowserSize(true); |
还记得那个build.xml文件么,可以使用ant打包工具,把src目录下的js代码跟引擎代码打包成一个myApp-HelloWorld.js文件,这样我们只需要把res资源、cocos2d.js、index.html、myApp-HelloWorld.js放到网站上就可以了,也就更安全了。切换到项目build.xml所在目录,在命令符窗口执行:ant。很快就会生成myApp-HelloWorld.js文件,然后还需要修改cocos2d.js的window.addEventListener函数,修改s.src的值为myApp-HelloWorld.js,cocos2d.js文件里有详细注释的。
ok,flappy bird游戏的主要代码就完成了,感觉cocos2d-html5还是非常强大的,开发效率很高。 现在还只能在本地运行游戏,为了能在外网访问,可以把项目传到github上,创建github pages,可以参考:http://pages.github.com/
cocos2dx-html5 实现网页版flappy bird游戏,布布扣,bubuko.com
cocos2dx-html5 实现网页版flappy bird游戏
标签:des android style class c code
原文地址:http://www.cnblogs.com/maoIT/p/3751078.html