cocos creator从零开发幸运转盘

开发环境

创建项目

创建项目

资源导入

新建textures目录并把资源导入。

资源导入

场景设置

新建scripts目录并在其下新建Game脚本。

新建脚本1

新建脚本2

新建scenes目录并在其下新建game场景。

新建场景

双击game场景打开场景,Canvas节点宽高设置成750x1334并适配宽度,再把Game脚本挂载上去。

Canvas设置

UI 布局

Canvas下新建空节点并重命名为table。拖动textures/背景table节点下并重命名为bgtable节点下新建空节点并重名为root。拖动textures/奖项底root节点下并重命名为itemX属性设置为-160Y属性设置为160item节点下新建Label组件并重命名为text。拖动textures/标识table节点下并重命名为run。拖动textures/开始按钮table节点下并重命名为btnStart并挂载Button组件

item1

item2

开始按钮

代码生成奖项

编辑scripts/Game脚本,内容如下。

const { ccclass } = cc._decorator


@ccclass
export default class LuckyTable extends cc.Component {
    private runNode: cc.Node

    private itemNum: number = 12 //奖项数量

    private _items: cc.Node[] = []

    private _idxLast: number = 0


    protected onLoad(): void {
        this.runNode = this.node.getChildByName('table').getChildByName('run')

        this.initItem()

        this._idxLast = this.randRange(0, this._items.length - 1)

        this.runNode.setPosition(this._items[this._idxLast].getPosition())

        const btnStart = this.node.getChildByName('table').getChildByName('btnStart')
        btnStart.on('click', this.onBtnStart, this)
    }


    private onBtnStart() {
        cc.log('点击了开始按钮')
    }


    private initItem() {
        const prefab = this.node.getChildByName('table').getChildByName('root').children[0]
        let lastPos = prefab.getPosition()

        for (let i = 0; i < this.itemNum; i++) {
            const item = cc.instantiate(prefab)
            item.getChildByName('text').getComponent(cc.Label).string = `${i + 1}`

            lastPos = this.getItemPosition(i, item, lastPos)

            item.parent = prefab.parent
            item.setPosition(lastPos)

            this._items.push(item)
        }

        prefab.destroy()
    }


    private getItemPosition(idx: number, item: cc.Node, lastPos: cc.Vec2): cc.Vec2 {
        if (idx == 0) return lastPos

        const sep = 6 //奖项间隔
        const pos = cc.Vec2.ZERO

        if (idx >= 1 && idx <= 3) {//上
            pos.y = lastPos.y
            pos.x = lastPos.x + (item.width + sep)
        } else if (idx >= 4 && idx <= 6) {//右
            pos.x = lastPos.x
            pos.y = lastPos.y - (item.height + sep)
        } else if (idx >= 7 && idx <= 9) {//下
            pos.y = lastPos.y
            pos.x = lastPos.x - (item.width + sep)
        } else if (idx >= 10 && idx <= 11) {//左
            pos.x = lastPos.x
            pos.y = lastPos.y + (item.height + sep)
        }

        return pos
    }


    // 整数范围随机 [min, max]
    private randRange(min: number, max: number): number {
        return Math.round(Math.random() * (max - min) + min)
    }
}

运行程序后,发现奖项生成好了,标识也随机显示了,点击点击抽奖按钮也输出了日志。

运行程序

生成奖项

实现转圈效果

编辑scripts/Game脚本,内容如下。

const { ccclass } = cc._decorator


@ccclass
export default class LuckyTable extends cc.Component {
    private runNode: cc.Node

    private itemNum: number = 12 //奖项数量
    private initSpeed: number = 5000 //初始运行速度

    private _items: cc.Node[] = []
    private _itemLen: number //两个奖项的距离(宽高一样)

    private _idxLast: number = 0

    private _isClick: boolean = false

    private _runTotal: number //这次转圈总共转的格子
    private _runNum: number //这次转圈转了几个格子了

    private _runSpeed: number //实时运行速度(最开始跟 initSpeed 一样,每运行一个格子减去 _itemSpeed)
    private _itemSpeed: number //每个格子的运行速度


    protected onLoad(): void {
        this.runNode = this.node.getChildByName('table').getChildByName('run')

        this.initItem()

        this._itemLen = this._items[0].getPosition().sub(this._items[1].getPosition()).len()

        this._idxLast = this.randRange(0, this._items.length - 1)

        this.runNode.setPosition(this._items[this._idxLast].getPosition())

        const btnStart = this.node.getChildByName('table').getChildByName('btnStart')
        btnStart.on('click', this.onBtnStart, this)
    }


    private onBtnStart() {
        if (this._isClick) return
        this._isClick = true

        const idxTarget = this.randRange(0, this._items.length - 1)
        const num = this._idxLast <= idxTarget ? idxTarget - this._idxLast : this._items.length - (idxTarget - this._idxLast)
        const round = this.randRange(3, 5)

        this._runTotal = this._items.length * round + num
        this._runNum = 1

        this._runSpeed = this.initSpeed
        this._itemSpeed = this.initSpeed / (this._runTotal + 2) //这里至少要加 1, 不然最后一个格子没速度了

        cc.log(`${this._idxLast + 1} =====> ${(this._idxLast + this._runTotal) % this._items.length + 1}`)

        this.run()
    }


    private run() {
        const time = this._itemLen / this._runSpeed

        const idx = (this._idxLast + this._runNum) % this._items.length
        const targetItem = this._items[idx]

        cc.tween(this.runNode).
            to(time, { x: targetItem.x, y: targetItem.y }).
            call(() => {
                if (this._runNum >= this._runTotal) {
                    this._isClick = false
                    this._idxLast = idx
                    return
                }

                this._runNum++
                this._runSpeed -= this._itemSpeed

                this.run()
            }).start()
    }

    private initItem() {
        const prefab = this.node.getChildByName('table').getChildByName('root').children[0]
        let lastPos = prefab.getPosition()

        for (let i = 0; i < this.itemNum; i++) {
            const item = cc.instantiate(prefab)
            item.getChildByName('text').getComponent(cc.Label).string = `${i + 1}`

            lastPos = this.getItemPosition(i, item, lastPos)

            item.parent = prefab.parent
            item.setPosition(lastPos)

            this._items.push(item)
        }

        prefab.destroy()
    }


    private getItemPosition(idx: number, item: cc.Node, lastPos: cc.Vec2): cc.Vec2 {
        if (idx == 0) return lastPos

        const sep = 6 //奖项间隔
        const pos = cc.Vec2.ZERO

        if (idx >= 1 && idx <= 3) {//上
            pos.y = lastPos.y
            pos.x = lastPos.x + (item.width + sep)
        } else if (idx >= 4 && idx <= 6) {//右
            pos.x = lastPos.x
            pos.y = lastPos.y - (item.height + sep)
        } else if (idx >= 7 && idx <= 9) {//下
            pos.y = lastPos.y
            pos.x = lastPos.x - (item.width + sep)
        } else if (idx >= 10 && idx <= 11) {//左
            pos.x = lastPos.x
            pos.y = lastPos.y + (item.height + sep)
        }

        return pos
    }


    // 整数范围随机 [min, max]
    private randRange(min: number, max: number): number {
        return Math.round(Math.random() * (max - min) + min)
    }
}

再次运行程序并点击点击抽奖按钮,程序已经开始由快转慢转圈了。

资源和代码获取

关注干货悦读公众号,点击源码菜单获取下载链接。

本作品采用《CC 协议》,转载必须注明作者和本文链接
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!