【Cocos Creator 3.x】篇——第四章 子系统

目录

[1 UI系统](#1 UI系统)

[1.1 Canvas](#1.1 Canvas)

[1.2 Sprite组件](#1.2 Sprite组件)

Sprite渲染模式

[1.3 Label组件](#1.3 Label组件)

[1.4 Button组件](#1.4 Button组件)

Button过渡效果

[1.5 ProgressBar组件](#1.5 ProgressBar组件)

[1.6 ScrollView组件](#1.6 ScrollView组件)

[2 动画系统](#2 动画系统)

[2.1 Animation组件](#2.1 Animation组件)

[2.2 创建动画剪辑](#2.2 创建动画剪辑)

[2.3 动画事件](#2.3 动画事件)

[3 音频系统](#3 音频系统)

[3.1 AudioSource组件](#3.1 AudioSource组件)

[4 物理系统](#4 物理系统)

[4.1 物理组件](#4.1 物理组件)

2D物理组件

碰撞检测

[4.2 射线检测](#4.2 射线检测)

[5 网络系统](#5 网络系统)

[5.1 HTTP请求](#5.1 HTTP请求)

[5.2 WebSocket](#5.2 WebSocket)

[6 总结](#6 总结)


本文介绍了Cocos Creator 3.x的核心游戏开发系统,主要包括:UI系统(Canvas、Sprite、Label、Button、ProgressBar和ScrollView组件)、动画系统(Animation组件、动画剪辑创建和事件处理)、音频系统(AudioSource组件控制)、物理系统(2D物理组件、碰撞检测和射线检测)以及网络系统(HTTP请求和WebSocket通信)。

通过代码示例详细展示了各系统的使用方法,为开发者提供了完整的游戏开发基础框架参考。

1 UI系统

1.1 Canvas

Canvas是UI系统的根节点,所有UI元素都应该放在Canvas下。

复制代码
import { _decorator, Component, Node, Canvas } from 'cc';
const { ccclass, property } = _decorator;
​
@ccclass('CanvasExample')
export class CanvasExample extends Component {
    start() {
        // 获取Canvas组件
        const canvas = this.node.getComponent(Canvas);
        
        if (canvas) {
            // 设置分辨率适配
            canvas.alignCanvasWithScreen = true;
            
            // 获取画布大小
            const size = canvas.getCanvasSize();
            console.log(`画布大小: ${size.width} x ${size.height}`);
        }
    }
}

1.2 Sprite组件

Sprite组件用于显示2D图片。

复制代码
import { _decorator, Component, Node, Sprite, SpriteFrame } from 'cc';
const { ccclass, property } = _decorator;
​
@ccclass('SpriteExample')
export class SpriteExample extends Component {
    @property({ type: SpriteFrame })
    public spriteFrame: SpriteFrame = null!;
​
    start() {
        // 获取Sprite组件
        const sprite = this.node.getComponent(Sprite);
        
        // 设置SpriteFrame
        sprite.spriteFrame = this.spriteFrame;
        
        // 设置渲染模式
        sprite.type = Sprite.Type.SIMPLE;
        
        // 设置颜色
        sprite.color.set(255, 255, 255, 255);
    }
}

Sprite渲染模式

复制代码
// 普通模式
sprite.type = Sprite.Type.SIMPLE;
​
// 九宫格模式(适合UI按钮等可拉伸元素)
sprite.type = Sprite.Type.SLICED;
​
// 平铺模式
sprite.type = Sprite.Type.TILED;
​
// 填充模式(适合进度条等)
sprite.type = Sprite.Type.FILLED;

1.3 Label组件

Label组件用于显示文字。

复制代码
import { _decorator, Component, Node, Label } from 'cc';
const { ccclass, property } = _decorator;
​
@ccclass('LabelExample')
export class LabelExample extends Component {
    start() {
        const label = this.node.getComponent(Label);
        
        // 设置文字内容
        label.string = 'Hello, Cocos Creator!';
        
        // 设置字体大小
        label.fontSize = 24;
        
        // 设置颜色
        label.color.set(255, 0, 0, 255);
        
        // 设置对齐方式
        label.horizontalAlign = Label.HorizontalAlign.CENTER;
        label.verticalAlign = Label.VerticalAlign.CENTER;
        
        // 设置溢出处理
        label.overflow = Label.Overflow.CLAMP;
        
        // 设置是否换行
        label.enableWrapText = true;
    }
}

1.4 Button组件

Button组件用于响应用户点击。

复制代码
import { _decorator, Component, Node, Button } from 'cc';
const { ccclass, property } = _decorator;
​
@ccclass('ButtonExample')
export class ButtonExample extends Component {
    @property({ type: Node })
    public buttonNode: Node = null!;
​
    start() {
        const button = this.buttonNode.getComponent(Button);
        
        // 设置按钮交互状态
        button.interactable = true;
        
        // 添加点击事件
        button.clickEvents.push({
            target: this.node,
            component: 'ButtonExample',
            handler: 'onButtonClick',
            customEventData: 'custom data'
        });
        
        // 通过代码添加点击事件
        this.buttonNode.on('click', this.onButtonClick, this);
    }
    
    onButtonClick(event: any, customData?: string) {
        console.log('按钮被点击!');
        console.log('自定义数据:', customData);
    }
}

Button过渡效果

复制代码
import { _decorator, Component, Node, Button } from 'cc';
const { ccclass, property } = _decorator;
​
@ccclass('ButtonTransition')
export class ButtonTransition extends Component {
    start() {
        const button = this.node.getComponent(Button);
        
        // 设置过渡类型
        button.transition = Button.Transition.COLOR;
        
        // 设置不同状态的颜色
        const colorBlock = button.color;
        colorBlock.normal = new Color(255, 255, 255, 255);
        colorBlock.pressed = new Color(200, 200, 200, 255);
        colorBlock.hover = new Color(230, 230, 230, 255);
        colorBlock.disabled = new Color(100, 100, 100, 255);
        button.color = colorBlock;
    }
}

1.5 ProgressBar组件

ProgressBar组件用于显示进度。

复制代码
import { _decorator, Component, Node, ProgressBar } from 'cc';
const { ccclass, property } = _decorator;
​
@ccclass('ProgressBarExample')
export class ProgressBarExample extends Component {
    @property({ type: Node })
    public progressBarNode: Node = null!;
    
    private progressBar: ProgressBar | null = null;
    private currentProgress: number = 0;
​
    start() {
        this.progressBar = this.progressBarNode.getComponent(ProgressBar);
        
        // 设置进度范围
        this.progressBar.totalLength = 100;
        this.progressBar.progress = 0;
        
        // 设置方向
        this.progressBar.direction = ProgressBar.Direction.LEFT_TO_RIGHT;
        
        // 开始加载动画
        this.startLoading();
    }
    
    startLoading() {
        const interval = setInterval(() => {
            this.currentProgress += 5;
            
            if (this.progressBar) {
                this.progressBar.progress = this.currentProgress / 100;
            }
            
            if (this.currentProgress >= 100) {
                clearInterval(interval);
                console.log('加载完成!');
            }
        }, 100);
    }
}

1.6 ScrollView组件

ScrollView组件用于滚动显示内容。

复制代码
import { _decorator, Component, Node, ScrollView, Label } from 'cc';
const { ccclass, property } = _decorator;
​
@ccclass('ScrollViewExample')
export class ScrollViewExample extends Component {
    @property({ type: Node })
    public scrollViewNode: Node = null!;
    
    @property({ type: Node })
    public contentNode: Node = null!;
​
    start() {
        const scrollView = this.scrollViewNode.getComponent(ScrollView);
        
        // 设置滚动方向
        scrollView.horizontal = false;
        scrollView.vertical = true;
        
        // 设置回弹效果
        scrollView.bounceEnabled = true;
        
        // 设置惯性滚动
        scrollView.inertia = true;
        
        // 添加列表项
        this.createListItems();
    }
    
    createListItems() {
        for (let i = 0; i < 20; i++) {
            const itemNode = new Node(`Item_${i}`);
            const label = itemNode.addComponent(Label);
            label.string = `列表项 ${i + 1}`;
            label.fontSize = 24;
            
            // 设置位置
            itemNode.setPosition(0, -i * 50, 0);
            
            // 添加到content节点
            itemNode.parent = this.contentNode;
        }
        
        // 更新content大小
        this.contentNode.setContentSize(400, 20 * 50);
    }
}

2 动画系统

2.1 Animation组件

Animation组件用于播放动画剪辑。

复制代码
import { _decorator, Component, Node, Animation } from 'cc';
const { ccclass, property } = _decorator;
​
@ccclass('AnimationExample')
export class AnimationExample extends Component {
    @property({ type: Node })
    public animatedNode: Node = null!;
    
    private animation: Animation | null = null;
​
    start() {
        this.animation = this.animatedNode.getComponent(Animation);
        
        if (this.animation) {
            // 播放动画
            this.animation.play('walk');
            
            // 设置循环模式
            const state = this.animation.getState('walk');
            if (state) {
                state.wrapMode = Animation.WrapMode.Loop;
            }
        }
    }
    
    playAnimation() {
        if (this.animation) {
            // 播放指定动画
            this.animation.play('jump');
            
            // 播放下一个动画
            this.animation.playNext();
        }
    }
    
    pauseAnimation() {
        if (this.animation) {
            this.animation.pause();
        }
    }
    
    resumeAnimation() {
        if (this.animation) {
            this.animation.resume();
        }
    }
    
    stopAnimation() {
        if (this.animation) {
            this.animation.stop();
        }
    }
}

2.2 创建动画剪辑

复制代码
import { _decorator, Component, Node, AnimationClip, animation } from 'cc';
const { ccclass, property } = _decorator;
​
@ccclass('CreateAnimation')
export class CreateAnimation extends Component {
    start() {
        // 创建动画剪辑
        const clip = new AnimationClip();
        clip.name = 'custom_animation';
        clip.duration = 1; // 1秒
        clip.sample = 30; // 30帧/秒
        
        // 创建曲线
        const curve = new animation.BasicCurve();
        
        // 添加关键帧(位置动画)
        const positions: number[] = [];
        const times: number[] = [];
        
        times.push(0);
        positions.push(0, 0, 0); // 起始位置
        
        times.push(0.5);
        positions.push(100, 100, 0); // 中间位置
        
        times.push(1);
        positions.push(0, 0, 0); // 结束位置
        
        curve.keys = times;
        curve.values = positions;
        
        // 设置曲线目标
        clip.addCurve('position', curve);
        
        // 添加到Animation组件
        const animation = this.node.getComponent(Animation);
        if (animation) {
            animation.addClip(clip);
            animation.play('custom_animation');
        }
    }
}

2.3 动画事件

复制代码
import { _decorator, Component, Node, Animation } from 'cc';
const { ccclass, property } = _decorator;
​
@ccclass('AnimationEvent')
export class AnimationEvent extends Component {
    start() {
        const animation = this.node.getComponent(Animation);
        
        if (animation) {
            // 监听动画事件
            animation.on(Animation.EventType.FINISHED, this.onAnimationFinished, this);
            animation.on(Animation.EventType.LOOP, this.onAnimationLoop, this);
            
            // 监听特定动画状态
            const state = animation.getState('attack');
            if (state) {
                state.on('frame', this.onFrame, this);
            }
        }
    }
    
    onAnimationFinished(type: Animation.EventType, state: any) {
        console.log('动画播放完成:', state.name);
    }
    
    onAnimationLoop(type: Animation.EventType, state: any) {
        console.log('动画循环:', state.name);
    }
    
    onFrame(frame: number, state: any) {
        console.log(`当前帧: ${frame}`);
    }
}

3 音频系统

3.1 AudioSource组件

AudioSource组件用于播放音频。

复制代码
import { _decorator, Component, Node, AudioSource, AudioClip } from 'cc';
const { ccclass, property } = _decorator;
​
@ccclass('AudioExample')
export class AudioExample extends Component {
    @property({ type: AudioClip })
    public bgmClip: AudioClip = null!;
    
    @property({ type: AudioClip })
    public sfxClip: AudioClip = null!;
    
    private audioSource: AudioSource | null = null;
​
    start() {
        // 获取AudioSource组件
        this.audioSource = this.node.getComponent(AudioSource);
        
        if (!this.audioSource) {
            // 如果没有,添加一个
            this.audioSource = this.node.addComponent(AudioSource);
        }
        
        // 播放背景音乐
        this.playBGM();
    }
    
    playBGM() {
        if (this.audioSource) {
            this.audioSource.clip = this.bgmClip;
            this.audioSource.loop = true;
            this.audioSource.volume = 0.5;
            this.audioSource.play();
        }
    }
    
    playSFX() {
        // 创建临时AudioSource播放音效
        const tempNode = new Node('TempAudio');
        const tempSource = tempNode.addComponent(AudioSource);
        tempSource.clip = this.sfxClip;
        tempSource.loop = false;
        tempSource.volume = 0.8;
        tempSource.play();
        
        // 播放完成后销毁临时节点
        setTimeout(() => {
            tempNode.destroy();
        }, this.sfxClip.duration * 1000);
    }
    
    stopAudio() {
        if (this.audioSource) {
            this.audioSource.stop();
        }
    }
    
    pauseAudio() {
        if (this.audioSource) {
            this.audioSource.pause();
        }
    }
    
    resumeAudio() {
        if (this.audioSource) {
            this.audioSource.resume();
        }
    }
}

4 物理系统

4.1 物理组件

Cocos Creator 3.x提供了完整的2D和3D物理系统。

2D物理组件

复制代码
import { _decorator, Component, Node, RigidBody2D, Collider2D, PhysicsSystem2D } from 'cc';
const { ccclass, property } = _decorator;
​
@ccclass('Physics2DExample')
export class Physics2DExample extends Component {
    @property({ type: Node })
    public playerNode: Node = null!;
​
    start() {
        // 获取刚体组件
        const rigidBody = this.playerNode.getComponent(RigidBody2D);
        
        if (rigidBody) {
            // 设置质量
            rigidBody.mass = 1;
            
            // 设置重力缩放
            rigidBody.gravityScale = 1;
            
            // 设置是否受重力影响
            rigidBody.gravityScale = 1;
            
            // 设置速度
            rigidBody.linearVelocity = new Vec2(100, 200);
            
            // 设置角速度
            rigidBody.angularVelocity = 0;
            
            // 设置是否允许旋转
            rigidBody.fixedRotation = true;
        }
        
        // 开启物理系统
        PhysicsSystem2D.instance.enable = true;
        
        // 设置重力
        PhysicsSystem2D.instance.gravity = new Vec2(0, -100);
    }
}

碰撞检测

复制代码
import { _decorator, Component, Node, Collider2D, Contact2DType } from 'cc';
const { ccclass, property } = _decorator;
​
@ccclass('CollisionDetection')
export class CollisionDetection extends Component {
    onLoad() {
        const collider = this.node.getComponent(Collider2D);
        
        if (collider) {
            // 监听碰撞事件
            collider.on(Contact2DType.BEGIN_CONTACT, this.onBeginContact, this);
            collider.on(Contact2DType.END_CONTACT, this.onEndContact, this);
            collider.on(Contact2DType.PRE_SOLVE, this.onPreSolve, this);
            collider.on(Contact2DType.POST_SOLVE, this.onPostSolve, this);
        }
    }
    
    onBeginContact(selfCollider: Collider2D, otherCollider: Collider2D) {
        console.log(`开始碰撞: ${otherCollider.node.name}`);
        
        // 检查碰撞对象标签
        if (otherCollider.node.tag === 1) {
            console.log('碰到了敌人!');
        }
    }
    
    onEndContact(selfCollider: Collider2D, otherCollider: Collider2D) {
        console.log(`结束碰撞: ${otherCollider.node.name}`);
    }
    
    onPreSolve(selfCollider: Collider2D, otherCollider: Collider2D) {
        console.log('碰撞前处理');
    }
    
    onPostSolve(selfCollider: Collider2D, otherCollider: Collider2D) {
        console.log('碰撞后处理');
    }
}

4.2 射线检测

复制代码
import { _decorator, Component, Node, PhysicsSystem2D, Vec2 } from 'cc';
const { ccclass, property } = _decorator;
​
@ccclass('RaycastExample')
export class RaycastExample extends Component {
    start() {
        // 射线检测
        const start = new Vec2(0, 0);
        const end = new Vec2(100, 100);
        
        const results = PhysicsSystem2D.instance.raycast(start, end);
        
        if (results.length > 0) {
            console.log(`检测到 ${results.length} 个碰撞`);
            
            for (const result of results) {
                console.log(`碰撞对象: ${result.collider.node.name}`);
                console.log(`碰撞点: ${result.point}`);
            }
        }
    }
}

5 网络系统

5.1 HTTP请求

复制代码
import { _decorator, Component, Node } from 'cc';
import { HttpRequest } from 'cc/net';
const { ccclass, property } = _decorator;
​
@ccclass('HttpExample')
export class HttpExample extends Component {
    async fetchData() {
        try {
            // GET请求
            const response = await HttpRequest.get('https://api.example.com/data');
            console.log('GET响应:', response);
            
            // POST请求
            const postData = {
                username: 'player1',
                score: 100
            };
            const postResponse = await HttpRequest.post('https://api.example.com/save', postData);
            console.log('POST响应:', postResponse);
        } catch (error) {
            console.error('请求失败:', error);
        }
    }
}

5.2 WebSocket

复制代码
import { _decorator, Component, Node } from 'cc';
import { WebSocket } from 'cc/net';
const { ccclass, property } = _decorator;
​
@ccclass('WebSocketExample')
export class WebSocketExample extends Component {
    private ws: WebSocket | null = null;
​
    connect() {
        // 创建WebSocket连接
        this.ws = new WebSocket('wss://game.example.com/ws');
        
        // 监听连接事件
        this.ws.onOpen(() => {
            console.log('WebSocket连接成功');
            
            // 发送消息
            this.ws?.send(JSON.stringify({
                type: 'join',
                room: 'game1'
            }));
        });
        
        // 监听消息
        this.ws.onMessage((event: any) => {
            const data = JSON.parse(event.data);
            console.log('收到消息:', data);
            
            // 处理消息
            this.handleMessage(data);
        });
        
        // 监听错误
        this.ws.onError((error: any) => {
            console.error('WebSocket错误:', error);
        });
        
        // 监听关闭
        this.ws.onClose((code: number, reason: string) => {
            console.log(`WebSocket关闭: ${code} - ${reason}`);
        });
        
        // 连接
        this.ws.connect();
    }
    
    handleMessage(data: any) {
        switch (data.type) {
            case 'joinSuccess':
                console.log('加入房间成功');
                break;
            case 'gameStart':
                console.log('游戏开始');
                break;
            case 'update':
                console.log('游戏状态更新:', data.state);
                break;
        }
    }
    
    sendMessage(message: any) {
        if (this.ws && this.ws.readyState === WebSocket.OPEN) {
            this.ws.send(JSON.stringify(message));
        }
    }
    
    disconnect() {
        this.ws?.close();
    }
}

6 总结

通过本章的学习,你应该掌握了:

  1. UI系统的核心组件(Sprite、Label、Button、ProgressBar、ScrollView)

  2. 动画系统的使用(Animation组件、动画剪辑、动画事件)

  3. 音频系统的使用(AudioSource组件)

  4. 物理系统的基本操作(刚体、碰撞检测、射线检测)

  5. 网络系统的使用(HTTP请求、WebSocket)

这些子系统构成了Cocos Creator 3.x游戏开发的基础,掌握它们可以帮助你开发出功能丰富的游戏。

相关推荐
li-xun1 小时前
我的在线工具箱继续升级:新增 Token 计算器、AI 提示词生成器和开发者格式化工具
javascript·django·html5
ikoala1 小时前
Codex 怎么买、怎么充值?先把这两套计费搞清楚
前端·javascript·后端
wuhen_n1 小时前
RAG 优化实战:检索精准度提升全方案
前端·langchain·ai编程
Mike_jia2 小时前
DataEase:人人可用的开源BI神器,企业数据决策民主化实战指南
前端
lichenyang4532 小时前
从一次“重新发送 / 重新生成”开始,聊聊流式聊天状态机到底解决了什么问题
前端
前端Hardy2 小时前
一个时代结束了:npm 终于对 install 脚本下手了
前端·javascript·后端
撑死胆大的2 小时前
2026开发变局:国标落地后,软件开发彻底换赛道
前端·低代码·ai·大模型
魔士于安2 小时前
Shader forge技术美术专用
游戏·unity·游戏引擎·贴图·技术美术·模型