Cocos Creator3.x设置动态加载背景图并且循环移动

效果图

项目结构

项目层级结构:

预制:

代码

typescript 复制代码
import { _decorator, CCFloat, Component, Node, Sprite, instantiate, Prefab, assert, UITransform } from 'cc';
const { ccclass, property } = _decorator;

/**
 * 背景脚本
 */
@ccclass('Background')
export class Background extends Component {
    /** 背景图片预制体 */
    @property(Prefab)
    backgroundPrefab: Prefab;

    /** 背景图片移动速度 */
    @property(CCFloat)
    speed: number = 400;

    /** 背景图片高度 */
    private bgHeight: number;

    /** 背景节点数组 */
    private backgroundNodeArray: Node[] = [];

    /** 背景图片数量 */
    private readonly bgPicNum = 2;

    /**
     * 初始化背景图片数组
     */
    private initBackgroundNodeArray() {
        for (let i = 0; i < this.bgPicNum; i++) {
            // 实例化预制体
            let bgNode = instantiate(this.backgroundPrefab);
            // 推入背景图片数组
            this.backgroundNodeArray.push(bgNode);
            // 挂载到背景根节点下
            this.node.addChild(bgNode);
            // 初始化背景图片高度
            this.initBackgroundHeight(bgNode);
        }
    }

    /**
     *  初始化背景图片高度
     */
    private initBackgroundHeight(bgNode: Node) {
        // 如果已初始化高度则返回
        if (!!this.bgHeight) {
            return;
        }
        // 获取背景图片精灵
        let bgSprite = bgNode.getComponent(Sprite);
        assert(!!bgSprite, "背景图片精灵未设置");
        // 动态读取背景图片高度
        this.bgHeight = bgSprite.spriteFrame.height;
    }

    /**
     * 初始化每个背景图片的位置
     */
    private initEachBackgroundNodePosition() {
        for (let i = 0; i < this.backgroundNodeArray.length; i++) {
            let bgNode = this.backgroundNodeArray[i];
            // 图片位置按图片高度叠加
            bgNode.setPosition(bgNode.position.x, this.bgHeight * i);
        }
    }

    start() {
        assert(!!this.backgroundPrefab, "背景图片预制体未设置");
        // 初始化背景图片数组
        this.initBackgroundNodeArray();
        // 初始化背景图片位置
        this.initEachBackgroundNodePosition();
    }

    update(deltaTime: number) {
        // 更新背景图片位置
        this.updateBackgroundPosition(deltaTime);
    }

    /**
     * 更新背景图片位置
     * @param deltaTime 时间间隔
     */
    private updateBackgroundPosition(deltaTime: number) {
        this.backgroundNodeArray.forEach(bgNode => {
            // 背景图片随时间下移
            bgNode.setPosition(bgNode.position.x, bgNode.position.y - this.speed * deltaTime);
            // 如果背景图片超出屏幕高度,则重置位置,接在上方
            if (bgNode.getPosition().y < -this.bgHeight) {
                // 计算帧运行到这里时,节点实际位置和背景图片高度的余数(如果图片下边界是-425,那么节点实际运行到这里时可能是-427了,就要把差值-2给补到平移的距离上去)
                let diff = bgNode.getPosition().y % this.bgHeight;
                // 重置图片位置
                bgNode.setPosition(bgNode.position.x, diff + this.bgHeight * (this.bgPicNum - 1));
            }
        });
    }
}
相关推荐
海带紫菜菠萝汤9 小时前
MSE (Media Source Extensions) 实战:流媒体分块加载与自适应码率
前端·javascript·音视频
张元清10 小时前
React useMount Hook:只在挂载时执行一次的正确姿势 (2026)
javascript·react.js
晓说前端10 小时前
TypeScript 核心语法应用 —— Vue 3 中的使用(上)
前端·typescript
breeze jiang10 小时前
JavaScript 单例模式:用静态属性保证 Popup 只创建一次
开发语言·javascript·单例模式
No Silver Bullet10 小时前
Vue进阶(贰幺叁)vue.config.js 中 productionSourceMap 作用详解
前端·javascript·vue.js
用户8471810541910 小时前
LangChain中间件教程及DeepAgents应用
javascript·agent
huabuyu10 小时前
INP 自动化归因与自愈:如何自动定位、修复并验证一次卡顿
前端·javascript
BreezeJiang10 小时前
浏览器里的 DeepSeek 到底怎么跑起来?关键在 Worker、缓存和流式消息
javascript
BreezeJiang10 小时前
单例模式真正解决的不是“只能 new 一次”,而是统一资源入口
javascript
小林ixn10 小时前
WebGPU + Transformers.js:把 DeepSeek-R1 塞进浏览器,真香!
javascript·llm·gpu