200字范文,内容丰富有趣,生活中的好帮手!
200字范文 > cocos creator |《合成大西瓜》源码 解读

cocos creator |《合成大西瓜》源码 解读

时间:2021-09-10 18:11:20

相关推荐

cocos creator |《合成大西瓜》源码 解读

更多源码请扫码关注公众号

编者荐语:

不辜负每一份热爱

以下文章来源于懒惰的An,作者懒惰的An

懒惰的An

《合成大西瓜》原版开发者,cocos游戏开发小辣鸡,会发一些自己做的游戏源码或功能教程,搬运一些大老的技术分享~因为我比较懒,所以也可能不发~

大家好,我是An~wx公众号也申请了半年了,第一次写文,水平很低,凑活看吧

大西瓜火了,这两天也是在网上看到了各种模仿的大西瓜作品,可能也有朋友想知道这么简单的小游戏是怎么做的,今天我们也来模仿还原一下原版手感的合成大西瓜

正题:

第一步:打开CocosCreator,今天我们用2.4.3来制作

新建工程,导入素材~~

因为是竖屏游戏,Canvas参数设置成720*1288

在Canvas下加入一个新的精灵节点Sprite,size设置成720*1280,命名为BG

再把地板素材拖到BG下面,名字为Floor,在BG新建两个新的单色精灵Sprite节点,大小设置为20*1280,放在背景图片两侧

同时给Floor,WallLeft,WallRight挂上RigidBody刚体组件和PhysicsBoxCollider碰撞器组件,RigidBody组件的Type设置为Static

这样一个场景就做好了

下面做一个水果的预制体

在Canvas下新建一个空节点,用于存放我们下落的水果 名字就叫FruitNode,再新建一个空节点叫TargetFruitNode,用于存放我们当前控制的水果节点,我们从水果素材里随便拿出一个放在FruitNode节点下,改名叫FruitPre,同时给FruitPre加上RigidBody和PhysicalCircleCollider,参数也设置好

还要记得设置好分组 墙壁设置成wall,水果设置成fruit

然后把节点拖到Perfab文件夹里,这样预制体就做好了

然后把场景里的FruitPre删掉

这样基本工作就做好了

下面我们写代码

在scripts创建一个ts脚本,名字为GameManager,脚本设置成单例

public static Instance: GameManager = null;onLoad () {if(GameManager.Instance!=null){GameManager.Instance.destroy();}GameManager.Instance = this;cc.director.getPhysicsManager().enabled=true;//物理游戏,开启物理}

脚本挂在Canvas上,首先获取到节点和预制体

@property(cc.Node)fruitNode:cc.Node=null;@property(cc.Node)targetfruitNode:cc.Node=null;@property(cc.Prefab)fruitPre:cc.Prefab=null;targetFruit:cc.Node=null;

然后写第一个方法,在屏幕上方生成一个水果,直接上代码

createOneFruit(_pos: cc.Vec2) {let fruit = cc.instantiate(this.fruitPre);//实例化一个预制体fruit.setParent(this.targetfruitNode)//更改fruit父节点fruit.setPosition(_pos);//设置坐标fruit.setScale(0)//出生时scale设置为0fruit.getComponent(cc.RigidBody).type = cc.RigidBodyType.Static;//刚体类型设置为Static防止下落fruit.getComponent(cc.PhysicsCircleCollider).radius = 0;//碰撞器半径先设置位0,下落时再改到相应水果大小fruit.getComponent(cc.PhysicsCircleCollider).apply();//保存碰撞器更改的参数//水果生成时执行一个缩放动作cc.tween(fruit).to(0.5, { scale: 1 }, { easing: 'backOut' }).call(() => {this.targetFruit = fruit;//将我们控制的水果targetFruit设置为刚生成的fruit}).start()}

在start()里调用一下

start() {this.createOneFruit(cc.v2(0,500))}

运行:

这样只能生成固定的一个水果,我们应该在代码里随意生成我们想要的水果,该怎么写呢。首先声明一个SpriteFrame数组,存放我们所有的水果素材

@property(cc.SpriteFrame)Allfruit: cc.SpriteFrame[] = [];

然后改一下生成水果的代码

/*** 生成一个水果/只用于生成上方的水果* @param _fruitNum 水果类型 0是葡萄 以此类推* @param _pos 水果生成的位置*/createOneFruit(_fruitNum: number, _pos: cc.Vec2) {let fruit = cc.instantiate(this.fruitPre);//实例化一个预制体fruit.setParent(this.targetfruitNode)//更改fruit父节点fruit.getComponent(cc.Sprite).spriteFrame=this.Allfruit[_fruitNum];//更改fruit的图片fruit.getComponent("FruitCollision").fruitNumber=_fruitNum;//fruit碰撞回调脚本,里面有一个当前水果类型如果是葡萄fruitNumber为0用于相同合成检测fruit.setPosition(_pos);//设置坐标fruit.setScale(0)//出生时scale设置为0fruit.getComponent(cc.RigidBody).type=cc.RigidBodyType.Static;//刚体类型设置为Static防止下落fruit.getComponent(cc.PhysicsCircleCollider).radius=0;//碰撞器半径先设置位0,下落时再改到相应水果大小fruit.getComponent(cc.PhysicsCircleCollider).apply();//保存碰撞器更改的参数//水果生成时执行一个缩放动作cc.tween(fruit).to(0.5,{scale:1},{easing:'backOut'}).call(()=>{this.targetFruit=fruit;//将我们控制的水果targetFruit设置为刚生成的fruit}).start()}

继续新建一个InputController脚本 挂在Canvas上 ,该脚本控制水果,点击哪里水果就会移动到那个位置的坐标x,滑动时水果会跟随,松开水果下落

直接上代码

touchNum: number = 0;// LIFE-CYCLE CALLBACKS:// onLoad () {}start() {this.openTouch();}// update (dt) {}openTouch() {this.node.on(cc.Node.EventType.TOUCH_START, this.onTouchStart, this);this.node.on(cc.Node.EventType.TOUCH_MOVE, this.onTouchMove, this);this.node.on(cc.Node.EventType.TOUCH_END, this.onTouchEnd, this);this.node.on(cc.Node.EventType.TOUCH_CANCEL, this.onTouchEnd, this);}onTouchStart(e) {if (GameManager.Instance.targetFruit != null) {//检测targetFruit是否为空 空就不执行任何动作this.touchNum = 1;let posx = this.node.convertToNodeSpaceAR(e.getLocation()).x;//获取点击位置的x值let posy = GameManager.Instance.targetFruit.y;//获取上方水果的y值cc.tween(GameManager.Instance.targetFruit).to(0.1, { position: cc.v3(posx, posy, 0) }).start()}}onTouchMove(e) {if (GameManager.Instance.targetFruit != null) {this.touchNum = 1;GameManager.Instance.targetFruit.x = this.node.convertToNodeSpaceAR(e.getLocation()).x; //水果跟随鼠标移动}}onTouchEnd(e) {if (GameManager.Instance.targetFruit != null && this.touchNum == 1) { //this.touchNUm 是防止下落位置错误this.touchNum = 0;// 给targetFruit重新设置物理参数// 碰撞器的半径为fruit高度的一半GameManager.Instance.targetFruit.getComponent(cc.PhysicsCircleCollider).radius = GameManager.Instance.targetFruit.height / 2;// 保存GameManager.Instance.targetFruit.getComponent(cc.PhysicsCircleCollider).apply();// 刚体类型改为动态GameManager.Instance.targetFruit.getComponent(cc.RigidBody).type = cc.RigidBodyType.Dynamic;// 给一个初始的下落线速度GameManager.Instance.targetFruit.getComponent(cc.RigidBody).linearVelocity = cc.v2(0, -800)// 属性改完后,targetFruit设置为空,防止连续操作GameManager.Instance.targetFruit = null;this.scheduleOnce(() => {GameManager.Instance.createOneFruit(Math.floor(Math.random() * 5), cc.v2(0, 500));}, 0.5)}}

运行起来:

下面就剩合成方法了,继续搞。。。好累

新建脚本FruitCollision,挂在水果预制体上

fruitNumber: number = 0;//代表自身是那种类型的水果returnNumber: boolean = false;getNumberTime: number = 0;// LIFE-CYCLE CALLBACKS:// onLoad () {}start(){}update(dt) {if (this.returnNumber) {this.scheduleOnce(() => {this.getNumberTime=0;}, 0.25)this.returnNumber = false;}}// 防止多次碰撞getNumber() {let ad = this.getNumberTime;this.getNumberTime++;this.returnNumber = true;return ad;}onBeginContact(contact, selfCollider, otherCollider) {if (otherCollider.node.group == "fruit") {//this.endCtrl = true;// 只有下方的水果触发碰撞回调if (selfCollider.node.y < otherCollider.node.y) {return}// 水果一下落,放在FruitNode节点下selfCollider.node.parent = cc.find("Canvas/FruitNode");if (selfCollider.node.getComponent(cc.RigidBody) != null) {selfCollider.node.getComponent(cc.RigidBody).angularVelocity = 0;// 限制一下线速度}let selfNum = this.fruitNumber;let otherNum = otherCollider.node.getComponent("FruitCollision").fruitNumber;// 水果类型相同的合成if (selfNum == otherNum && selfNum < 9 && otherNum < 9) {if (selfCollider.node.getComponent("FruitCollision").getNumber() == 0) {otherCollider.node.getComponent(cc.PhysicsCircleCollider).radius = 0;otherCollider.node.getComponent(cc.PhysicsCircleCollider).apply()this.node.getComponent(cc.PhysicsCircleCollider).radius = 0;this.node.getComponent(cc.PhysicsCircleCollider).apply();cc.tween(selfCollider.node).to(0.1, { position: otherCollider.node.position }).call(() => {//生成下一个等级的水果GameManager.Instance.score += this.fruitNumber + 1;GameManager.Instance.createLevelUpFruit(this.fruitNumber + 1, otherCollider.node.position);otherCollider.node.active = false;selfCollider.node.active = false;otherCollider.node.destroy();selfCollider.node.destroy();}).start()}} else if (selfNum == otherNum && selfNum == 9 && otherNum == 9) {if (selfCollider.node.getComponent("FruitCollision").getNumber() == 0) {otherCollider.node.getComponent(cc.PhysicsCircleCollider).radius = 0;otherCollider.node.getComponent(cc.PhysicsCircleCollider).apply()this.node.getComponent(cc.PhysicsCircleCollider).radius = 0;this.node.getComponent(cc.PhysicsCircleCollider).apply();cc.tween(selfCollider.node).to(0.1, { position: otherCollider.node.position }).call(() => {GameManager.Instance.score += this.fruitNumber + 1;GameManager.Instance.createLevelUpFruit(this.fruitNumber + 1, otherCollider.node.position);otherCollider.node.active = false;selfCollider.node.active = false;otherCollider.node.destroy();selfCollider.node.destroy();}).start()}}}}

再次运行,已经可以合成了,合成更高级的水果我换成了独立的方法 卸载GameManager里

/*** 生成高一级的水果* @param _fruitNum 水果* @param _pos 位置*/createLevelUpFruit(_fruitNum, _pos) {//AudioManager.Instance.Play(6, false, 1)let fruit = cc.instantiate(this.fruitPre);fruit.parent = this.fruitNode;fruit.getComponent(cc.Sprite).spriteFrame = this.Allfruit[_fruitNum];fruit.getComponent("FruitCollision").fruitNumber = _fruitNum;fruit.position = _pos;fruit.scale = 0;fruit.getComponent(cc.RigidBody).linearVelocity = cc.v2(0, -100);fruit.getComponent(cc.PhysicsCircleCollider).radius = fruit.height / 2;fruit.getComponent(cc.PhysicsCircleCollider).apply();cc.tween(fruit).to(0.5, { scale: 1 }, { easing: 'backOut' }).call(() => {if (fruit.getComponent(cc.PhysicsCircleCollider) != null) {fruit.getComponent(cc.PhysicsCircleCollider).radius = fruit.height / 2;fruit.getComponent(cc.RigidBody).type = cc.RigidBodyType.Dynamic;fruit.getComponent(cc.PhysicsCircleCollider).apply();}}).start()GameManager.Instance.fruitHeigth = GameManager.Instance.findHighestFruit();}

后面红线预警方法,结束检测方法,结束方法, 加分等,我会另外加上并打成压缩包。

可以关注我公众号“懒惰的An” 回复“大西瓜”获取代码

也可以在本公众号回复关键字获取源码:

大西瓜

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。