CocosCreator学习1:做一个简单的游戏
2017-02-20 21:41
447 查看
把计步器写好了,到了写游戏场景、控件什么的时候,傻眼了。想做一个简单的地图,可以在地图上点击选择城市,发现用Cocos2D-X代码码出来好麻烦,尤其是城市位置问题,需要调试去找对像素区域做一个按钮控制,整个人都不好了。本来还想尝试用Tiled map来做,想法很逗比,应该不能用。今晚被长辈连番教育中,说到了撞墙走弯路才想起来,当初光顾着学引擎看代码了,竟然忘了还有CocosCreator,这么简单实用的工具我竟然没有去用,太傻了。而且现在距离比较提交程序结果时间也比较紧了,直接用CocosCreator做游戏时最明智的。下面将转向CocosCreator的学习。
CocosCreator有很详细的入门教程,下面我就跟随这个教程来进行学习。
http://www.cocos.com/docs/creator/getting-started/quick-start.html#–2
打开后如图:
在资源管理器面板中,可以看到项目中的文件。项目资源的根目录叫asserts,对应于解压初始版本得到的文件夹名。其中标注bf图标的文件是位图字体,是一种字体资源,由fnt文件和同名的png图片文件共同组成。
双击New Scene,就会在场景编辑器和层级管理器中打开这个场景。在层级管理器中可以看到当前场景的所有节点和他们的层级关系。
其中的Design Resolution属性用来指定游戏分辨率,Fit Hight和Fit Width是分辨率自适应匹配方法。只需要把图像放到Canvas下,就可以完成对不同分辨率的自适应,非常简单。
在资源管理器中将textures中background图像拖到
层级管理器的Canvas下即可增加背景图像,会看到Canvas下增加了一个background子节点。
点击文件->保存场景或使用快捷键ctrl+s保存场景后,在场景编辑器中便会显示增加的背景图像。
点击窗口左上角工具栏的第四格矩形变换工具,然后选中场景编辑器中的背景图像,可以实现对图像尺寸、位置、锚点的修改。
当然也可以直接使用属性检查器来直接设置这些参数。
在实际的应用开发中背景图像一般都是要大于显示范围的,这样可以让背景图覆盖整个屏幕,不出现穿帮的情况。
增加地面
使用和增加背景图像相同的方法,将地面图像拖到层级管理器的Canvas上,将ground节点移到background节点下方。
在层级管理器中,下方的节点的渲染顺序在上方节点之后,也就是说下方节点会遮挡上方节点。
使用相同的方法可以对地面图像的尺寸、位置、锚点进行修改。
增加主角
同样的方法,将主角图像player拖到ground下方。在之后的动画中,需要主角接触地面并跳跃,因此将锚点改为最下方,即y值为0,然后将它拖到地面上。
脚本也就是游戏的逻辑规则,需要代码实现。
首先在资源管理器中右键点击assets文件夹,新建->文件夹,创建一个名为New Folder的文件夹,然后对其右击选择新建->JavaScript,创建一个JavaScript脚本NewScript,重命名为Player,双击即可打开编写界面。Cocos Creator 中脚本名称就是组件的名称。
在Player中的properties部分增加以下代码:
这些属性用于规定主角的移动方式,可以在属性检查器中直接设置属性的数值。
然后在层级编辑器中选择player,在属性检查器中选择添加组件,选择增加用户脚本组件->Player,即可为主角添加组件。
现在可以在属性检查器看到Player组件并修改属性数值了。
跳跃和移动代码
在properties代码块下面定义setJumpAction方法:
修改onLoad: function:
onLoad方法会在场景加载完成后立即执行,所以在这里进行初始化操作。
保存脚本运行一下试试,可以看到player不断的在进行跳跃动作。
在setJumpAction下面定义setInputControl方法来实现用A和D控制主角的移动操作:
修改onLoad方法,在其中加入向左和向右加速的开关,以及主角当前在水平方向的速度,最后再调用我们刚添加的setInputControl方法,在场景加载后就开始监听键盘输入:
最后修改update方法,添加加速度、速度和主角当前位置的设置:
这样就可以实现对主角移动的控制了。
制作Prefab脚本-星星
这里增加游戏规则,从随机位置生成星星,用主角接住星星即可得分。
对于重复生成的节点,可以保存成Prefab(预置)资源,作为动态生成节点时的模板。
这里直接将assets/textures/star资源到场景中,位置随意,给星星增加一个脚本,当主角碰到星星时,让星星消失。
给star节点增加脚本,将pickRadius值设置为60。将层级管理器中的star节点拖到资源管理器的assets文件夹下,将场景中的star节点删除。star现在即为Prefab资源。
添加游戏控制脚本
在assets/scripts文件夹下添加游戏的主逻辑脚本Game,添加生成星星需要的属性:
然后将Game添加到Canvas节点上,然后将star这个Prefab资源拖到Canvas属性检查器Game组件中的Star Prefab属性上。把层级管理器中的ground和Player节点也拖到组件中相应属性处即可。设置Min Star Duration和Max Star Duration值为3和5,之后生成星星时,会在这两个值之间随机取值作为星星消失前经过的时间。
在随机位置生成星星
修改Game脚本,在onLoad方法后面添加星星的逻辑:
添加主角碰触收集星星的行为
重点在于星星要随时获取主角节点的位置,才能判断与主角的距离是否小于可收集距离。因此将Game组件的实例传给星星并保存,然后可以随时通过game.player来访问主角节点。
在Game脚本的spawnNewStar方法最后添加如下代码:
然后在star脚本里onLoad方法后面添加getPlayerDistance和onPicked方法:
在update方法中添加每帧判断距离,如果距离小于pickRadius属性规定值,就执行收集行为:
现在可以看效果了。
添加计分牌
在层级管理器的Canvas中右键创建新节点->创建渲染节点->Label(文字),命名为score。将position设为(0,180),string设为score:0,Font Size设为50。从资源管理器中将assets/mikado_outline_shadow位图字体资源拖到Font属性中。
添加得分逻辑
在Game的properties里添加score需要的属性:
在onLoad方法里添加计分用的变量初始化:
在update方法后面添加gainScore的新方法:
将score节点拖到Canvas属性的Game组件中的Score Display属性中。
在Star脚本的onPicked方法中添加gainScore的调用:
这样收集到星星,分数就会变化了。
失败判断和重新开始
加入给星星加入计时消失的逻辑,在Game脚本的onLoad方法的spawNewStar调用之前加入需要的变量声明:
// Game.js
onLoad: function () {
// …
// 初始化计时器
this.timer = 0;
this.starDuration = 0;
// 生成一个新的星星
this.spawnNewStar();
// 初始化计分
this.score = 0;
},
然后在spawnNewStar方法最后加入重置计时器的逻辑,其中this.minStarDuration和this.maxStarDuration是我们一开始声明的Game组件属性,用来规定星星消失时间的随机范围:
在update方法中加入计时器更新和判断超过时限的逻辑:
最后加入gameOver方法,游戏失败重新加载场景。
然后修改Star脚本,加入即将消失星星的提示效果,在update方法中加入以下代码:
这样游戏画面和逻辑就全部完成了,可以说游戏已经基本完成了。
加入音效
首先加入跳跃音效,在Player脚本中引用声音文件资源jumpAudio属性:
修改setJumpAction方法,插入播放音效的回调,并通过添加playJumpSound方法来播放声音:
然后加入得分音效,在Game脚本的properties添加引用声音文件:
在gainScore方法添加播放声音的代码:
在层级管理器中,将assets/audio/jump声音资源拖到Player节点的组件Jump Audio属性上。将assets/audio/score资源拖拽到Canvas节点Game组件的Score Audio属性上。
大功告成,一个完整的游戏就做好了。
CocosCreator有很详细的入门教程,下面我就跟随这个教程来进行学习。
http://www.cocos.com/docs/creator/getting-started/quick-start.html#–2
打开项目
教程中提供了一个简单游戏的初始版本,我就从这个游戏入手进行学习。从CocosCreator选择打开其他项目,打开start_project文件夹,选中即可打开。注意下载的start_project不能放在CocosCreator路径下。打开后如图:
在资源管理器面板中,可以看到项目中的文件。项目资源的根目录叫asserts,对应于解压初始版本得到的文件夹名。其中标注bf图标的文件是位图字体,是一种字体资源,由fnt文件和同名的png图片文件共同组成。
创建场景
下面来创建游戏场景。游戏场景一般包括:场景图像(Sprite)、文字(Label)、角色、以组件形式附加在场景节点上的游戏逻辑脚本。在资源管理器中点击asserts目录前面的加号,选择Scene,会创建一个New Scene的场景文件。双击New Scene,就会在场景编辑器和层级管理器中打开这个场景。在层级管理器中可以看到当前场景的所有节点和他们的层级关系。
Canvas画布节点/渲染根节点
现在New Scene中只有一个Canvas节点,称为画布节点或渲染根节点,点击选中Canvas可以在属性检查器中看到他的属性。其中的Design Resolution属性用来指定游戏分辨率,Fit Hight和Fit Width是分辨率自适应匹配方法。只需要把图像放到Canvas下,就可以完成对不同分辨率的自适应,非常简单。
设置场景图像
增加背景图像在资源管理器中将textures中background图像拖到
层级管理器的Canvas下即可增加背景图像,会看到Canvas下增加了一个background子节点。
点击文件->保存场景或使用快捷键ctrl+s保存场景后,在场景编辑器中便会显示增加的背景图像。
点击窗口左上角工具栏的第四格矩形变换工具,然后选中场景编辑器中的背景图像,可以实现对图像尺寸、位置、锚点的修改。
当然也可以直接使用属性检查器来直接设置这些参数。
在实际的应用开发中背景图像一般都是要大于显示范围的,这样可以让背景图覆盖整个屏幕,不出现穿帮的情况。
增加地面
使用和增加背景图像相同的方法,将地面图像拖到层级管理器的Canvas上,将ground节点移到background节点下方。
在层级管理器中,下方的节点的渲染顺序在上方节点之后,也就是说下方节点会遮挡上方节点。
使用相同的方法可以对地面图像的尺寸、位置、锚点进行修改。
增加主角
同样的方法,将主角图像player拖到ground下方。在之后的动画中,需要主角接触地面并跳跃,因此将锚点改为最下方,即y值为0,然后将它拖到地面上。
编写脚本
创建并添加脚本脚本也就是游戏的逻辑规则,需要代码实现。
首先在资源管理器中右键点击assets文件夹,新建->文件夹,创建一个名为New Folder的文件夹,然后对其右击选择新建->JavaScript,创建一个JavaScript脚本NewScript,重命名为Player,双击即可打开编写界面。Cocos Creator 中脚本名称就是组件的名称。
在Player中的properties部分增加以下代码:
// Player.js //... properties: { // 主角跳跃高度 jumpHeight: 0, // 主角跳跃持续时间 jumpDuration: 0, // 最大移动速度 maxMoveSpeed: 0, // 加速度 accel: 0, }, //...
这些属性用于规定主角的移动方式,可以在属性检查器中直接设置属性的数值。
然后在层级编辑器中选择player,在属性检查器中选择添加组件,选择增加用户脚本组件->Player,即可为主角添加组件。
现在可以在属性检查器看到Player组件并修改属性数值了。
跳跃和移动代码
在properties代码块下面定义setJumpAction方法:
// Player.js properties: { //... }, setJumpAction: function () { // 跳跃上升 var jumpUp = cc.moveBy(this.jumpDuration, cc.p(0, this.jumpHeight)).easing(cc.easeCubicActionOut()); // 下落 var jumpDown = cc.moveBy(this.jumpDuration, cc.p(0, -this.jumpHeight)).easing(cc.easeCubicActionIn()); // 不断重复 return cc.repeatForever(cc.sequence(jumpUp, jumpDown)); },
修改onLoad: function:
// Player.js onLoad: function () { // 初始化跳跃动作 this.jumpAction = this.setJumpAction(); this.node.runAction(this.jumpAction); },
onLoad方法会在场景加载完成后立即执行,所以在这里进行初始化操作。
保存脚本运行一下试试,可以看到player不断的在进行跳跃动作。
在setJumpAction下面定义setInputControl方法来实现用A和D控制主角的移动操作:
// Player.js setJumpAction: function () { //... }, setInputControl: function () { var self = this; // 添加键盘事件监听 cc.eventManager.addListener({ event: cc.EventListener.KEYBOARD, // 有按键按下时,判断是否是我们指定的方向控制键,并设置向对应方向加速 onKeyPressed: function(keyCode, event) { switch(keyCode) { case cc.KEY.a: self.accLeft = true; self.accRight = false; break; case cc.KEY.d: self.accLeft = false; self.accRight = true; break; } }, // 松开按键时,停止向该方向的加速 onKeyReleased: function(keyCode, event) { switch(keyCode) { case cc.KEY.a: self.accLeft = false; break; case cc.KEY.d: self.accRight = false; break; } } }, self.node); },
修改onLoad方法,在其中加入向左和向右加速的开关,以及主角当前在水平方向的速度,最后再调用我们刚添加的setInputControl方法,在场景加载后就开始监听键盘输入:
// Player.js onLoad: function () { // 初始化跳跃动作 this.jumpAction = this.setJumpAction(); this.node.runAction(this.jumpAction); // 加速度方向开关 this.accLeft = false; this.accRight = false; // 主角当前水平方向速度 this.xSpeed = 0; // 初始化键盘输入监听 this.setInputControl(); },
最后修改update方法,添加加速度、速度和主角当前位置的设置:
// Player.js update: function (dt) { // 根据当前加速度方向每帧更新速度 if (this.accLeft) { this.xSpeed -= this.accel * dt; } else if (this.accRight) { this.xSpeed += this.accel * dt; } // 限制主角的速度不能超过最大值 if ( Math.abs(this.xSpeed) > this.maxMoveSpeed ) { // if speed reach limit, use max speed with current direction this.xSpeed = this.maxMoveSpeed * this.xSpeed / Math.abs(this.xSpeed); } // 根据当前速度更新主角的位置 this.node.x += this.xSpeed * dt; },
这样就可以实现对主角移动的控制了。
制作Prefab脚本-星星
这里增加游戏规则,从随机位置生成星星,用主角接住星星即可得分。
对于重复生成的节点,可以保存成Prefab(预置)资源,作为动态生成节点时的模板。
这里直接将assets/textures/star资源到场景中,位置随意,给星星增加一个脚本,当主角碰到星星时,让星星消失。
// Star.js properties: { // 星星和主角之间的距离小于这个数值时,就会完成收集 pickRadius: 0 },
给star节点增加脚本,将pickRadius值设置为60。将层级管理器中的star节点拖到资源管理器的assets文件夹下,将场景中的star节点删除。star现在即为Prefab资源。
添加游戏控制脚本
在assets/scripts文件夹下添加游戏的主逻辑脚本Game,添加生成星星需要的属性:
// Game.js properties: { // 这个属性引用了星星预制资源 starPrefab: { default: null, type: cc.Prefab }, // 星星产生后消失时间的随机范围 maxStarDuration: 0, minStarDuration: 0, // 地面节点,用于确定星星生成的高度 ground: { default: null, type: cc.Node }, // player 节点,用于获取主角弹跳的高度,和控制主角行动开关 player: { default: null, type: cc.Node } },
然后将Game添加到Canvas节点上,然后将star这个Prefab资源拖到Canvas属性检查器Game组件中的Star Prefab属性上。把层级管理器中的ground和Player节点也拖到组件中相应属性处即可。设置Min Star Duration和Max Star Duration值为3和5,之后生成星星时,会在这两个值之间随机取值作为星星消失前经过的时间。
在随机位置生成星星
修改Game脚本,在onLoad方法后面添加星星的逻辑:
// Game.js onLoad: function () { // 获取地平面的 y 轴坐标 this.groundY = this.ground.y + this.ground.height/2; // 生成一个新的星星 this.spawnNewStar(); }, spawnNewStar: function() { // 使用给定的模板在场景中生成一个新节点 var newStar = cc.instantiate(this.starPrefab); // 将新增的节点添加到 Canvas 节点下面 this.node.addChild(newStar); // 为星星设置一个随机位置 newStar.setPosition(this.getNewStarPosition()); }, getNewStarPosition: function () { var randX = 0; // 根据地平面位置和主角跳跃高度,随机得到一个星星的 y 坐标 var randY = this.groundY + cc.random0To1() * this.player.getComponent('Player').jumpHeight + 50; // 根据屏幕宽度,随机得到一个星星 x 坐标 var maxX = this.node.width/2; randX = cc.randomMinus1To1() * maxX; // 返回星星坐标 return cc.p(randX, randY); }
添加主角碰触收集星星的行为
重点在于星星要随时获取主角节点的位置,才能判断与主角的距离是否小于可收集距离。因此将Game组件的实例传给星星并保存,然后可以随时通过game.player来访问主角节点。
在Game脚本的spawnNewStar方法最后添加如下代码:
// Game.js spawnNewStar: function() { // ... // 将 Game 组件的实例传入星星组件 newStar.getComponent('Star').game = this; },
然后在star脚本里onLoad方法后面添加getPlayerDistance和onPicked方法:
// Star.js getPlayerDistance: function () { // 根据 player 节点位置判断距离 var playerPos = this.game.player.getPosition(); // 根据两点位置计算两点之间距离 var dist = cc.pDistance(this.node.position, playerPos); return dist; }, onPicked: function() { // 当星星被收集时,调用 Game 脚本中的接口,生成一个新的星星 this.game.spawnNewStar(); // 然后销毁当前星星节点 this.node.destroy(); },
在update方法中添加每帧判断距离,如果距离小于pickRadius属性规定值,就执行收集行为:
// Star.js update: function (dt) { // 每帧判断和主角之间的距离是否小于收集距离 if (this.getPlayerDistance() < this.pickRadius) { // 调用收集行为 this.onPicked(); return; } },
现在可以看效果了。
添加计分牌
在层级管理器的Canvas中右键创建新节点->创建渲染节点->Label(文字),命名为score。将position设为(0,180),string设为score:0,Font Size设为50。从资源管理器中将assets/mikado_outline_shadow位图字体资源拖到Font属性中。
添加得分逻辑
在Game的properties里添加score需要的属性:
// Game.js properties: { // ... // score label 的引用 scoreDisplay: { default: null, type: cc.Label } },
在onLoad方法里添加计分用的变量初始化:
// Game.js onLoad: function () { // ... // 初始化计分 this.score = 0; },
在update方法后面添加gainScore的新方法:
// Game.js gainScore: function () { this.score += 1; // 更新 scoreDisplay Label 的文字 this.scoreDisplay.string = 'Score: ' + this.score.toString(); },
将score节点拖到Canvas属性的Game组件中的Score Display属性中。
在Star脚本的onPicked方法中添加gainScore的调用:
// Star.js onPicked: function() { // 当星星被收集时,调用 Game 脚本中的接口,生成一个新的星星 this.game.spawnNewStar(); // 调用 Game 脚本的得分方法 this.game.gainScore(); // 然后销毁当前星星节点 this.node.destroy(); },
这样收集到星星,分数就会变化了。
失败判断和重新开始
加入给星星加入计时消失的逻辑,在Game脚本的onLoad方法的spawNewStar调用之前加入需要的变量声明:
// Game.js
onLoad: function () {
// …
// 初始化计时器
this.timer = 0;
this.starDuration = 0;
// 生成一个新的星星
this.spawnNewStar();
// 初始化计分
this.score = 0;
},
然后在spawnNewStar方法最后加入重置计时器的逻辑,其中this.minStarDuration和this.maxStarDuration是我们一开始声明的Game组件属性,用来规定星星消失时间的随机范围:
// Game.js spawnNewStar: function() { // ... // 重置计时器,根据消失时间范围随机取一个值 this.starDuration = this.minStarDuration + cc.random0To1() * (this.maxStarDuration - this.minStarDuration); this.timer = 0; },
在update方法中加入计时器更新和判断超过时限的逻辑:
// Game.js update: function (dt) { // 每帧更新计时器,超过限度还没有生成新的星星 // 就会调用游戏失败逻辑 if (this.timer > this.starDuration) { this.gameOver(); return; } this.timer += dt; },
最后加入gameOver方法,游戏失败重新加载场景。
// Game.js gameOver: function () { this.player.stopAllActions(); //停止 player 节点的跳跃动作 cc.director.loadScene('game'); }
然后修改Star脚本,加入即将消失星星的提示效果,在update方法中加入以下代码:
// Star.js update: function() { // ... // 根据 Game 脚本中的计时器更新星星的透明度 var opacityRatio = 1 - this.game.timer/this.game.starDuration; var minOpacity = 50; this.node.opacity = minOpacity + Math.floor(opacityRatio * (255 - minOpacity)); }
这样游戏画面和逻辑就全部完成了,可以说游戏已经基本完成了。
加入音效
首先加入跳跃音效,在Player脚本中引用声音文件资源jumpAudio属性:
// Player.js properties: { // ... // 跳跃音效资源 jumpAudio: { default: null, url: cc.AudioClip }, },
修改setJumpAction方法,插入播放音效的回调,并通过添加playJumpSound方法来播放声音:
// Player.js setJumpAction: function () { // 跳跃上升 var jumpUp = cc.moveBy(this.jumpDuration, cc.p(0, this.jumpHeight)).easing(cc.easeCubicActionOut()); // 下落 var jumpDown = cc.moveBy(this.jumpDuration, cc.p(0, -this.jumpHeight)).easing(cc.easeCubicActionIn()); // 添加一个回调函数,用于在动作结束时调用我们定义的其他方法 var callback = cc.callFunc(this.playJumpSound, this); // 不断重复,而且每次完成落地动作后调用回调来播放声音 return cc.repeatForever(cc.sequence(jumpUp, jumpDown, callback)); }, playJumpSound: function () { // 调用声音引擎播放声音 cc.audioEngine.playEffect(this.jumpAudio, false); },
然后加入得分音效,在Game脚本的properties添加引用声音文件:
// Game.js properties: { // ... // 得分音效资源 scoreAudio: { default: null, url: cc.AudioClip } },
在gainScore方法添加播放声音的代码:
// Game.js gainScore: function () { this.score += 1; // 更新 scoreDisplay Label 的文字 this.scoreDisplay.string = 'Score: ' + this.score.toString(); // 播放得分音效 cc.audioEngine.playEffect(this.scoreAudio, false); },
在层级管理器中,将assets/audio/jump声音资源拖到Player节点的组件Jump Audio属性上。将assets/audio/score资源拖拽到Canvas节点Game组件的Score Audio属性上。
大功告成,一个完整的游戏就做好了。
相关文章推荐
- Android游戏——学习小结(一个简单的设计小游戏)动画射击
- Java学习笔记(一)用Eclipse把一个简单游戏项目生成可执行的JAR文件
- cocos2d-x学习(3)---游戏实例开发:一个简单的射击游戏二
- cocos2d-x学习(2)---游戏实例开发:一个简单的射击游戏一
- pygame学习笔记(6):完成一个简单的游戏
- Android游戏——学习小结(一个简单的设计小游戏)动画射击
- pygame学习笔记(6)——一个超级简单的游戏
- cocos2d-x 3.0来做一个简单的游戏教程 win32平台 vs2012 详解献给刚開始学习的人们!
- cocos2d开发学习六:一个简单的打地鼠游戏demo
- java学习做的一个简单的骑士飞行棋游戏!
- cocos2d-x学习(4)---游戏实例开发:一个简单的射击游戏三
- 开发一个网络学习游戏(抛砖引玉)
- FlashCom学习第二课:创建一个使用视频的简单的Flash动画
- 一个用JS作的简单的画图程序,可改画线粗细和顡色,觉得挺有意思的,所以放上来,以供相互学习
- 一个自写的共享内存简单的例子,学习原理之用
- 一个简单的游戏源代码
- 委托delegate的学习.+一个简单的委托和委托链的例子
- 通过制作一个简单的时钟学习WPF中DispatcherTimer的使用 Level 100
- [BizTalk][Adapter][部署]BTS学习笔记1:建立一个简单的Biztalk数据交换项目(一)
- MOSS Search学习记录(二):配置爬网并尝试一个简单的搜索