Cocos Creator TypeScript 套牛游戏(可微信小游戏)

视频操作地址:https://www.bilibili.com/video/BV1NN4y1V7Jy/?vd_source=0a0b591838e1a4cda6ec55da0e1c9019

源码地址:https://gitee.com/OnlyOneW/cocos-study/tree/master/cocos-cow

0 前提

cococs官方脚本指南
已安装Cocos Creator 3.5.2

1 新建2D项目

2 新建文件夹

在资源管理器中新建文件夹用来保存对应的资源

  • scenes : 保存场景
  • scripts : 保存脚本资源
  • res : 保存图片等资源
  • framework : 保存自定义类文件
  • clips : 保存动画文件
  • prefacs : 保存自定义预制文件

3 拖入图片等资源至res文件夹

会提供资源文件:res下的res-cow

4 搭建主页面

    1. 项目,项目设置里,调整尺寸为竖屏 (适配屏幕高度):640*960,
    1. 选中层级管理器,保存场景至,scenes文件夹下,命名:Main (ctrl+s 保存)
    1. 搭建背景
      新建2D对象,sprite(精灵):spt_bg
      设置背景图、尺寸:640*960 (默认的)
    1. 搭建按钮
      在spt_bg下,新建UI组件,Button(按钮):btn_capture
      删除btn_capture下的Label
      设置4种状态下的图片:初始、按下,设置给的图片,其余2个删掉
      设置大小:173*129
      拖动到合适位置
    1. 搭建牛儿
      把第一张牛儿图片拖到层级管理器spt_bg下,重命名为:cow

5 奔跑的牛

5.1 代码实现

在framework新建TypeScript,命名:CowSkin

  1. 牛的皮肤类
import { _decorator, Component, Node } from 'cc';
const { ccclass, property } = _decorator;

@ccclass('CowSkin')
export class CowSkin  {
    
	@property(cc.SpriteFrame)
	public cows : [cc.SpriteFrame] = [];
}

在scripts新建TypeScript,命名:cow
2. 牛的类型数组

import { CowSkin } from '../framework/CowSkin';
@property(CowSkin)
public cow_sets : [CowSkin] = [];


private _intervalTime = 0;
private _randomType = Math.floor(Math.random()*3);
  1. update回调函数实现帧动画,更换皮肤
update(deltaTime: number) {
		let dt = deltaTime ;
        // 间隔时间
        this._intervalTime += dt;
        let index = Math.floor(this._intervalTime / 0.2);
        index = index%3;
        // 获取一种牛的类型
        let cowSet = this.cow_sets[this._randomType];
        
        // 获取精灵组件
        let sprite = this.node.getComponent(cc.Sprite);
        sprite.spriteFrame = cowSet.cows[index];
    }

5.2 定义一个数组实现奔跑动画

在clips 文件夹下新建动画剪辑:runClip,层级管理器,选中cow,选择动画编辑器,关联新建的runClip文件,编辑动画,设置播放模式,加入尾帧事件,runCallback

cow.ts加入下面函数:

runCallback() {
	    cc.log("一个轮回结束!");
	    this._randomType = Math.floor(Math.random()*3);
	}

选择Play on load

保存

退出动画编辑

5.3 属性检查器按顺序拖入图片

层级管理器,选中cow,关联cow.ts,设置参数,并按顺序拖入图片

5.4 将整个cow节点作为预制体

把cow节点拖到prefabs文件夹下,删除cow节点,把cow预制节点,拖到spt_bg下

选择Play on load

至此随机不同种的牛奔跑,已实现

6 新建game.ts

新建game.ts当做全局脚本文件,挂载到Canvas

7 套绳

拖动套绳图片:rope,至背景图片spt_bg下,默认不显示

7.1 改锚点

    1. 改预制体cow的锚点

选中,选矩形变化,移至牛头下,用于方便判断牛头是否套住,删除原来的cow,重新拖一下

    1. 调整绳子的锚点至,圆圈中央

7.2 game.ts新建属性

@property(cc.Node)
public rope_node : cc.Node = null;


@property(cc.Node)
public cow_ins : cc.Node =null;


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


@property(cc.Prefab)
public cow_prefab : cc.Prefab = null;

@property
public time  = 0;

private _mainScene = 'Main';

并在Canvas里绑定

  • rope_node(rope)
  • cow_ins(cow)
  • rope_imgs(4张绳子图片按顺序拖动)
  • cow_prefab(cow预制体)
  • time(60)

保存

注:此处容易忽略初始化绑定

7.3 按钮事件绑定代码,

start() {
		
		let btn_capture_node = cc.find("Canvas/spt_bg/btn_capture");
				
		btn_capture_node.on(NodeEventType.TOUCH_START, this._touchStart_btn_capture, this);
		
    }

并定义

_touchStart_btn_capture (touch: Touch, event: EventTouch) {
		
		
 }

具体请见最后

8 计分器和倒计时

8.1 第一步:界面添加Label

  • 分数显示
    在spt_bg下,新建2D对象,Label(文本):lb_score,来显示得分
    设置初始值 : Score:0
    设置大小 : 50
    拖动到合适位置

  • 倒计时
    在spt_bg下,新建2D对象,Label(文本):lb_count_down,来显示倒计时
    设置初始参数:60s
    设置大小 : 50
    并添加位图字体样式和字体颜色:#EB78E6
    拖动到合适位置

8.2 第二步:用位图字体让显示更美观

去掉勾选:UseSystemFont
拖入已备好的字体资源,至Font

8.3 第三步:编写逻辑代码

此步片段代码可忽略,直接查看总代码

  • 分数显示
start () {
        // 定义初始化得分为0
        this.scoreNum = 0;
}
    
// 捕捉成功,分数+1
this.scoreNum++;
let lb_score = cc.find("Canvas/spt_bg/lb_score").getComponent(cc.Label);
lb_score.string = "Score: " + this.scoreNum;
  • 倒计时
start () {
    // 获得计时器组件
    let countDownLabel = cc.find("Canvas/spt_bg/lb_count_down").getComponent(cc.Label);
    let time = 60;
    // 倒计时
    this.schedule(function () {
        time--;
        countDownLabel.string = "Time: " + time + " s";
    },1);
},

9 背景音效

9.1 导入模块

import { AudioSource, assert} from 'cc';

9.2 添加组件:AudioSource

Canvas里,添加组件 按钮,选择 Audio -> AudioSource

设置文件
设置播放方式

9.3 属性

@property(cc.AudioClip)
public audio_clip : cc.AudioClip = null;
	
@property(AudioSource)
public audioSource: AudioSource = null!;

Canvas里绑定属性 audio_clip

9.4 初始化audioSource属性

start() {
	// 获取 AudioSource 组件
	const audioSource_set = this.node.getComponent(AudioSource)!;
	// 检查是否含有 AudioSource,如果没有,则输出错误消息
	assert(audioSource_set);
	// 将组件赋到全局变量 audioSource 中
	this.audioSource = audioSource_set;
}

9.5 播放套中音效

// 音效
this.audioSource.playOneShot(this.audio_clip, 1);

10 粒子

10.1 导入模块

import { ParticleSystem2D} from 'cc';

10.2 新建ParticleSystem2D(粒子)

在rope下,新建2D对象,ParticleSystem2D(粒子):pc2d_fireworks

10.3 设置粒子参数

不勾选 PlayOnLoad
勾选 Custom
设置 SpriteFrame

10.4 显示粒子效果

套中牛,显示粒子效果

// 粒子
let pc2d_fireworksNode = cc.find("Canvas/spt_bg/rope/pc2d_fireworks");
this.fireworks = pc2d_fireworksNode.getComponent(ParticleSystem2D)
this.fireworks.resetSystem()

11 最终成就系统

倒计时为0时游戏结束,并根据玩家的最终得分显示成就;比如小于等于3分就是套牛青铜,大于三分小于6分就是套牛高手,大于6分以上就是套牛王者。

11.1 制作一个显示用的弹窗

包含一个关闭按钮,标题和称号。

  • spt_result
    Canvas下,新建2D对象,sprite(精灵):spt_result
    设置背景图、尺寸、九宫格(Sliced)模式,
    (九宫格编辑得选中图片去编辑)
    默认不显示

  • close
    拖入关闭按钮至spt_result 背景下,,命名为close
    调整参数
    调整位置:182 182

  • lb_title
    在spt_result下,新建2D对象,Label(文本):lb_title,来显示等级
    设置初始参数:60 #252323
    调整位置

  • lb_content
    在spt_result下,新建2D对象,Label(文本):lb_content,来显示分数
    设置初始参数:80 #252323
    调整位置

11.2 最终代码

11.2.1 game.ts导入模块

import { _decorator, Component, Node ,Vec3 , NodeEventType,Tween, AudioSource, assert,ParticleSystem2D} from 'cc';

11.2.2 套绳逻辑代码

_touchStart_btn_capture (touch: Touch, event: EventTouch) {
		let bgNode = touch.currentTarget._parent;
		let currentTarget = touch.currentTarget;
		this.rope_node.active = true;
		// 设置绳子在当前父节点的顺序
		this.rope_node.setSiblingIndex(100);
		let rope_node_p = this.rope_node.getPosition();
		let rope_node_y_start = - 600 ;
		let rope_node_y_up = 115 ;
		let rope_node_y_down = -600 ;
		// 设置绳子起始位置
		this.rope_node.setPosition(rope_node_p.x,rope_node_y_start);
		rope_node_p = this.rope_node.getPosition();
		let that = this ;
		let tao_num: number = 100;
		let tween_node :cc.Node = this.rope_node ;
		let tweenDuration: number = 0.5;
		let t1 = cc.tween(tween_node)
		    .to(tweenDuration, { position: new Vec3(rope_node_p.x,rope_node_y_up,0) }
				,{          
					onUpdate:(target:Vec3, ratio:number)=>{
						this.rope_node = target;
					}
				}
			)
			// to 动作完成后会调用该方法     
			.call( ()=>{
				// 获取当前牛儿的x点
				let cow_ins_p = that.cow_ins.getPosition()
				let currentX = cow_ins_p.x;
				if (currentX > -tao_num && currentX < tao_num){
				    cc.log("捕捉成功!");
					
					// 音效
					this.audioSource.playOneShot(this.audio_clip, 1);
					
					// 粒子
					let pc2d_fireworksNode = cc.find("Canvas/spt_bg/rope/pc2d_fireworks");
					this.fireworks = pc2d_fireworksNode.getComponent(ParticleSystem2D)
					this.fireworks.resetSystem()
					
				    // 移除
				    bgNode.removeChild(that.cow_ins);
				    // 获取牛儿的类型
					let cowType = that.cow_ins.getComponent("cow")
					
				    let ropeType = cowType._randomType +1;
					
					that.rope_node.getComponent(cc.Sprite).spriteFrame = that.rope_imgs[ropeType];
					
				    // 生成新的牛节点
				    that.cow_ins = cc.instantiate(that.cow_prefab);
					that.cow_ins.setPosition(cow_ins_p.x,0);
					
				    bgNode.addChild(that.cow_ins);
				    //
				    that.success = true;
				    // 分数+1
				    that.scoreNum ++;
				} else {
				    cc.log("捕捉失败!")
				}
			})
		let t2 = cc.tween(tween_node)
		    .to(tweenDuration, { position: new Vec3(rope_node_p.x,rope_node_y_down,0) }
				,{
					onUpdate:(target:Vec3, ratio:number)=>{   
						this.rope_node = target;   
					}
				}
			)
			// to 动作完成后会调用该方法
			.call( ()=>{
				that.rope_node.getComponent(cc.Sprite).spriteFrame = that.rope_imgs[0];
				// 判断是否捕捉成功
				if (that.success == true) {
				    let  scoreLabel = cc.find("Canvas/spt_bg/lb_score").getComponent(cc.Label);
				    scoreLabel.string = "Score:" + that.scoreNum;
				    that.success = false;
				}
			})
		cc.tween(tween_node).sequence(t1, t2).start(); // 将 t1 和 t2 两个缓动加入到新的缓动队列内
		
		
	}
	

11.2.3 游戏结束,展示结果弹窗

start() {
		
		// 获取 AudioSource 组件
		const audioSource_set = this.node.getComponent(AudioSource)!;
		// 检查是否含有 AudioSource,如果没有,则输出错误消息
		assert(audioSource_set);
		// 将组件赋到全局变量 audioSource 中
		this.audioSource = audioSource_set;
		
		let btn_capture_node = cc.find("Canvas/spt_bg/btn_capture");				
		btn_capture_node.on(NodeEventType.TOUCH_START, this._touchStart_btn_capture, this);
		
		
		this.success = false;
		// 初始分数
		this.scoreNum = 0;
		
		
		let countDownLabel = cc.find("Canvas/spt_bg/lb_count_down").getComponent(cc.Label);
		countDownLabel.string = this.time + "s";
		
		
		this.schedule(function () {
		    this.time --;
		    countDownLabel.string = this.time + "s";
		    if (this.time == 0) {
		        cc.log("游戏结束!");
		        // 获取弹窗节点
		        let resultNode = cc.find("Canvas/spt_result");
				
				//绑定关闭事件
				let closeNode = cc.find("Canvas/spt_result/close");
				closeNode.on(NodeEventType.TOUCH_START, this._touchStart_close, this);
				
		        // 获取title和content两个节点
		        let titleNode = resultNode.getChildByName("lb_title");
		        let contentNode = resultNode.getChildByName("lb_content");
		        // 展示分数
		        titleNode.getComponent(cc.Label).string = "最终得分 " + this.scoreNum;
		        // 获取组件
		        let contentLabel = contentNode.getComponent(cc.Label);
		        switch (true) {
		            case this.scoreNum <= 3:
		                contentLabel.string = "套牛新手";
		                break;
		            case this.scoreNum < 6:
		                contentLabel.string = "套牛神手";
		                break;
		            case this.scoreNum >= 6:
		                contentLabel.string = "套牛圣手";
		                break;
		
		        }
		        resultNode.active = true;
		        let score = this.scoreNum;
		       
		
		        cc.director.pause();
		
		    }
		
		},1);
		
		
    }

11.2.4 关闭按钮

// 关闭按钮,继续游戏
	_touchStart_close(touch: Touch, event: EventTouch) {
	    cc.log("继续游戏");
	    cc.director.resume();
	    cc.director.loadScene(this._mainScene);
	}

错误:因为函数后有逗号
index.js:1 Error: Unable to resolve bare specifier ‘__unresolved_2’ from http://localhost:7456/scripting/x/chunks/34/341ab3341f38daa5d6eb502f45f16e9d150576f5.js (SystemJS Error#8 https://git.io/JvFET#8)

参考

粒子和音频

补充说明

资源来源于网络各种免费分享,及自身学习总结,
若有不当可评论指正

A
B
C
D
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

wx_h13813744

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值