开发环境
- Cocos Creator 2.4.8,安装参考 cocos creator安装
- TypeScript
创建项目
资源导入
新建textures
目录并把资源导入。
场景设置
新建scripts
目录并在其下新建Game
脚本。
新建scenes
目录并在其下新建game
场景。
双击game
场景打开场景,Canvas
节点宽高设置成750x1334
并适配宽度,再把Game
脚本挂载上去。
UI 布局
Canvas
下新建空节点并重命名为table
。拖动textures/背景
到table
节点下并重命名为bg
。table
节点下新建空节点并重名为root
。拖动textures/奖项底
到root
节点下并重命名为item
,X
属性设置为-160
,Y
属性设置为160
。item
节点下新建Label
组件并重命名为text
。拖动textures/标识
到table
节点下并重命名为run
。拖动textures/开始按钮
到table
节点下并重命名为btnStart
并挂载Button组件
。
代码生成奖项
编辑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)
}
}
再次运行程序并点击点击抽奖
按钮,程序已经开始由快转慢转圈了。
资源和代码获取
关注干货悦读
公众号,点击源码
菜单获取下载链接。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。