export function getPosByAngle(angle, len) { const radian = angle * Math.PI / 180; const x = Math.sin(radian) * len; const y = Math.cos(radian) * len; return { x, y }; } export function getAngleByPos(px, py, mx, my) { const x = Math.abs(px - mx); const y = Math.abs(py - my); const z = Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2)); const cos = y / z; const radina = Math.acos(cos); // 用反三角函数求弧度 let angle = Math.floor(180 / (Math.PI / radina) * 100) / 100; // 将弧度转换成角度 if (mx > px && my > py) {// 鼠标在第四象限 angle = 180 - angle; } if (mx === px && my > py) {// 鼠标在y轴负方向上 angle = 180; } if (mx > px && my === py) {// 鼠标在x轴正方向上 angle = 90; } if (mx < px && my > py) {// 鼠标在第三象限 angle = 180 + angle; } if (mx < px && my === py) {// 鼠标在x轴负方向 angle = 270; } if (mx < px && my < py) {// 鼠标在第二象限 angle = 360 - angle; } // console.log('angle: ', angle); return angle; } export function exchangeNodePos(baseNode, targetNode) { return baseNode.convertToNodeSpaceAR(targetNode._parent.convertToWorldSpaceAR(cc.v2(targetNode.x, targetNode.y))); } export function RandomInt(a, b = 0) { let max = Math.max(a, b); let min = Math.min(a, b); return Math.floor(Math.random() * (max - min) + min); } export function randomSortByArr(arr) { const newArr = []; const tmpArr = arr.concat(); while (tmpArr.length > 0) { const randomIndex = Math.floor(tmpArr.length * Math.random()); newArr.push(tmpArr[randomIndex]); tmpArr.splice(randomIndex, 1); } return newArr; } export function setSprNodeMaxLen(sprNode, maxW, maxH) { const sx = maxW / sprNode.width; const sy = maxH / sprNode.height; const s = Math.min(sx, sy); sprNode.scale = Math.round(s * 1000) / 1000; } export function localPosTolocalPos(baseNode, targetNode) { const worldPos = targetNode.parent.convertToWorldSpaceAR(cc.v2(targetNode.x, targetNode.y)); const localPos = baseNode.parent.convertToNodeSpaceAR(cc.v2(worldPos.x, worldPos.y)); return localPos; } export function worldPosToLocalPos(worldPos, baseNode) { const localPos = baseNode.parent.convertToNodeSpaceAR(cc.v2(worldPos.x, worldPos.y)); return localPos; } export function getScaleRateBy2Node(baseNode, targetNode, maxFlag = true) { const worldRect1 = targetNode.getBoundingBoxToWorld(); const worldRect2 = baseNode.getBoundingBoxToWorld(); const sx = worldRect1.width / worldRect2.width; const sy = worldRect1.height / worldRect2.height; if (maxFlag) { return Math.max(sx, sy); } else { return Math.min(sx, sy); } } export function getDistance (start, end){ var pos = cc.v2(start.x - end.x, start.y - end.y); var dis = Math.sqrt(pos.x*pos.x + pos.y*pos.y); return dis; } export function playAudioByUrl(audio_url, cb=null) { if (audio_url) { cc.assetManager.loadRemote(audio_url, (err, audioClip) => { const audioId = cc.audioEngine.play(audioClip, false, 0.8); if (cb) { cc.audioEngine.setFinishCallback(audioId, () => { cb(); }); } }); } } export function btnClickAnima(btn, time=0.15, rate=1.05) { btn.tmpScale = btn.scale; btn.on(cc.Node.EventType.TOUCH_START, () => { cc.tween(btn) .to(time / 2, {scale: btn.scale * rate}) .start() }) btn.on(cc.Node.EventType.TOUCH_CANCEL, () => { cc.tween(btn) .to(time / 2, {scale: btn.tmpScale}) .start() }) btn.on(cc.Node.EventType.TOUCH_END, () => { cc.tween(btn) .to(time / 2, {scale: btn.tmpScale}) .start() }) } export function getSpriteFrimeByUrl(url, cb) { cc.loader.load({ url }, (err, img) => { const spriteFrame = new cc.SpriteFrame(img) if (cb) { cb(spriteFrame); } }) } export function getSprNode(resName) { const sf = cc.find('Canvas/res/img/' + resName).getComponent(cc.Sprite).spriteFrame; const node = new cc.Node(); node.addComponent(cc.Sprite).spriteFrame = sf; return node; } export function getSprNodeByUrl(url, cb) { const node = new cc.Node(); const spr = node.addComponent(cc.Sprite); getSpriteFrimeByUrl(url, (sf) => { spr.spriteFrame = sf; if (cb) { cb(spr); } }) } export function playAudio(audioClip, cb = null) { if (audioClip) { const audioId = cc.audioEngine.playEffect(audioClip, false); if (cb) { cc.audioEngine.setFinishCallback(audioId, () => { cb(); }); } } } export async function asyncDelay(time) { return new Promise((resolve, reject) => { try { cc.tween(cc.find('Canvas')) .delay(time) .call(()=>{ resolve(null); }) .start(); } catch (e) { reject(e); } }) } export class FireworkSettings { baseNode; // 父节点 nodeList; // 火花节点的array pos; // 发射点 side; // 发射方向 range; // 扩散范围 number; // 发射数量 scalseRange; // 缩放范围 constructor(baseNode, nodeList, pos = cc.v2(0, 0), side = cc.v2(0, 100), range = 50, number = 100, scalseRange = 0 ) { this.baseNode = baseNode; this.nodeList = nodeList; this.pos = pos; this.side = side; this.range = range; this.number = number; this.scalseRange = scalseRange; } static copy(firework) { return new FireworkSettings( firework.baseNode, firework.nodeList, firework.pos, firework.side, firework.range, firework.number, ); } } export async function showFireworks(fireworkSettings) { const { baseNode, nodeList, pos, side, range, number, scalseRange } = fireworkSettings; new Array(number).fill(' ').forEach(async (_, i) => { let rabbonNode = new cc.Node(); rabbonNode.parent = baseNode; rabbonNode.x = pos.x; rabbonNode.y = pos.y; rabbonNode.angle = 60 * Math.random() - 30; let node = cc.instantiate(nodeList[RandomInt(nodeList.length)]); node.parent = rabbonNode; node.active = true; node.x = 0; node.y = 0; node.angle = 0; node.scale = (Math.random() - 0.5) * scalseRange + 1; const rate = Math.random(); const angle = Math.PI * (Math.random() * 2 - 1); await asyncTweenBy(rabbonNode, 0.3, { x: side.x * rate + Math.cos(angle) * range * rate, y: side.y * rate + Math.sin(angle) * range * rate }, { easing: 'quadIn' }); cc.tween(rabbonNode) .by(8, { y: -2000 }) .start(); cc.tween(rabbonNode) .to(5, { scale: (Math.random() - 0.5) * scalseRange + 1 }) .start(); rabbonFall(rabbonNode); await asyncDelay(Math.random()); cc.tween(node) .by(0.15, { x: -10, angle: -10 }) .by(0.3, { x: 20, angle: 20 }) .by(0.15, { x: -10, angle: -10 }) .union() .repeatForever() .start(); cc.tween(rabbonNode) .delay(5) .to(0.3, { opacity: 0 }) .call(() => { node.stopAllActions(); node.active = false; node.parent = null; node = null; }) .start(); }); } async function rabbonFall(node) { const time = 1 + Math.random(); const offsetX = RandomInt(-200, 200) * time; await asyncTweenBy(node, time, { x: offsetX, angle: offsetX * 60 / 200 }); rabbonFall(node); } export async function asyncTweenTo(node, duration, obj, ease = undefined) { return new Promise((resolve, reject) => { try { cc.tween(node) .to(duration, obj, ease) .call(() => { resolve(null); }) .start(); } catch (e) { reject(e); } }); } export async function asyncTweenBy(node, duration, obj, ease = undefined) { return new Promise((resolve, reject) => { try { cc.tween(node) .by(duration, obj, ease) .call(() => { resolve(null); }) .start(); } catch (e) { reject(e); } }); } export function showTrebleFirework(baseNode, rabbonList) { const middle = new FireworkSettings(baseNode, rabbonList); middle.pos = cc.v2(0, -400); middle.side = cc.v2(0, 1000); middle.range = 200; middle.number = 100; middle.scalseRange = 0.4; const left = FireworkSettings.copy(middle); left.pos = cc.v2(-600, -400); left.side = cc.v2(200, 1000); const right = FireworkSettings.copy(middle); right.pos = cc.v2(600, -400); right.side = cc.v2(-200, 1000); showFireworks(middle); showFireworks(left); showFireworks(right); } export function onHomeworkFinish() { const middleLayer = cc.find('middleLayer'); if (middleLayer) { const middleLayerComponent = middleLayer.getComponent('middleLayer'); if (middleLayerComponent.role == 'student') { middleLayerComponent.onHomeworkFinish(() => { }); } } else { console.log('onHomeworkFinish'); } }