123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221 |
- import { _decorator, Node, Label, EventTouch, Vec3, UITransform, Prefab, tween} from 'cc';
- import { BaseExp } from '../core/base/BaseExp';
- import { autoBind } from '../extend/AutoBind';
- import { Constants } from '../data/Constants';
- import { userIns } from '../data/UserData';
- import { Utils } from '../utils/Utils';
- import { uiMgr } from '../core/manager/UIManager';
- import { stateMgr } from '../core/manager/StateManager';
- import { ITEM_TYPE, ResUtil } from '../utils/ResUtil';
- import { PoolManager } from '../core/manager/PoolManager';
- import { bundleMgr } from '../core/manager/BundleManager';
- import { audioMgr } from '../core/manager/AudioManager';
- const { ccclass, property } = _decorator;
- //扔飞镖
- @ccclass('TossBoomerangUI')
- export class TossBoomerangUI extends BaseExp {
- @autoBind({ type: Node, tooltip: "靶面中的所有靶心" })
- public content: Node;
- @autoBind({ type: Node, tooltip: "飞镖按钮" })
- public shoot_btn: Node;
- @autoBind({ type: Label, tooltip: "金币文本" })
- public gold_lable: Label;
- @autoBind({ type: Label, tooltip: "钻石文本" })
- public diamond_lable: Label;
- @autoBind({ type: Label, tooltip: "飞镖个数文本" })
- public boomerang_num_lable: Label;
- //是否正在扔飞镖
- private isBoomeranging: boolean = false;
-
- start() {
- this.hasAnim = false;
- this.closeOnBlank = false;
- //注册动态变化值
- stateMgr.registerUI(Constants.gold, this.gold_lable);
- stateMgr.registerUI(Constants.diamond, this.diamond_lable);
- this.content.children.forEach(child => {
- child.on(Node.EventType.TOUCH_END, this.startToss.bind(this), this);
- })
- }
-
- public show(...args: any[]){
- this.setBoomerang();
- }
- /**
- * 设置飞镖个数
- */
- public setBoomerang(){
- if(userIns.data.boomerang > 0){
- this.boomerang_num_lable.string = userIns.data.boomerang;
- }else{
- this.boomerang_num_lable.string = `Buy`;
- }
- }
- /**
- * 购买飞镖
- */
- public buyBoomerang(){
- uiMgr.show(Constants.popUIs.buyBoomerangUI);
- }
- /**
- * 扔飞镖数据
- */
- public startToss(event:EventTouch = null,param:any = null){
- if(this.isBoomeranging)return;
- if(userIns.data.boomerang <= 0){
- this.buyBoomerang();
- return;
- }
- let target_plate:Node = null;
- if(event){
- target_plate = event.target;
- }else{
- //获取靶心
- let r:number = Utils.getRandomInt(0,this.content.children.length - 1);
- target_plate = this.content.children[r];
- }
- audioMgr.playOneShot(Constants.audios.dart);
- this.isBoomeranging = true;
- userIns.data.boomerang -= 1;
- this.setBoomerang();
- //总的权重
- const totalWeight = userIns.boomerangTable.reduce((sum, item) => sum + item.weight, 0);
- //生成随机数(包含安全容错)
- const random = Math.min(Math.random() * totalWeight, totalWeight - 1e-6);
- let accumulatedWeight = 0;
- let selectedItem: any = null;
- //遍历查找命中的条目
- for(const item of userIns.boomerangTable) {
- if (random < accumulatedWeight + item.weight) {
- selectedItem = item;
- break;
- }
- accumulatedWeight += item.weight;
- }
- if(!selectedItem) {
- selectedItem = userIns.boomerangTable[0];
- }
- //加载飞镖预制体
- ResUtil.loadRes(`items/tossBoomerang`).then((ret:Node)=>{
- var boomerang:Node = PoolManager.getNode(ret,this.content);
- //获取靶面尺寸(假设靶面锚点在中心)
- const targetSize = target_plate.getComponent(UITransform)?.contentSize;
- //生成随机角度(0-360度)
- const angle = Math.random() * Math.PI * 2;
- //根据权重计算偏移比例(权重越大,offsetRatio越小) 获取靶面中心的世界坐标
- const targetWorldPos = target_plate.parent.getComponent(UITransform)
- .convertToWorldSpaceAR(target_plate.position);
- //转换为父节点坐标系下的坐标
- const targetCenter = target_plate.parent.getComponent(UITransform)
- .convertToNodeSpaceAR(targetWorldPos);
- //生成基于靶心坐标的随机偏移(权重越大越靠近中心)平方曲线增强中心聚集 缩小最大偏移范围
- const maxRadius = targetSize.width * 0.2;
- const offsetRatio = Math.pow(1 - (selectedItem.weight / totalWeight), 2);
- //最终落点计算(以靶心为基准)
- const targetPos = new Vec3(
- targetCenter.x + Math.cos(angle) * maxRadius * offsetRatio,
- targetCenter.y + Math.sin(angle) * maxRadius * offsetRatio,
- 0
- );
- const targetUITransform = target_plate.getComponent(UITransform);
- const radius = targetUITransform.contentSize.width / 2.0 * 1.5; // 半径取宽度的一半
- const randomAngle = Math.random() * Math.PI * 2; // 生成0-360度的随机角度
- //新起始点计算(靶面中心 + 半径 * 随机角度)
- const startPos = new Vec3(
- target_plate.position.x + radius * Math.cos(randomAngle),
- target_plate.position.y + radius * Math.sin(randomAngle),
- 0
- );
- //飞镖初始位置(从屏幕下方飞出)
- //let startPos: Vec3 = Utils.convertPosition(this.shoot_btn,this.target_plate.parent);
- boomerang.position = startPos.clone();
- let middePos = Utils.randomUIPointGenerator(target_plate,startPos,200);
- let pos = Utils.calculateParabolaCenter(startPos,targetPos);
- let controlPoint = new Vec3(middePos.x + pos.x,middePos.y,middePos.z)
- //贝塞尔轨迹计算
- const calculateTrajectory = (t: number, p0: Vec3, p1: Vec3, p2: Vec3) => {
- const u = 1 - t;
- return new Vec3(
- u*u*p0.x + 2*u*t*p1.x + t*t*p2.x,
- u*u*p0.y + 2*u*t*p1.y + t*t*p2.y,
- 0
- );
- };
- tween(boomerang)
- .to(0.8, {}, {
- onUpdate: (_, ratio: number) => {//计算当前帧位置
- const currentPos = calculateTrajectory(
- ratio,
- startPos,
- controlPoint,
- targetPos
- );
- //更新位置和旋转
- boomerang.position = currentPos;
- boomerang.angle = Utils.getAngle(currentPos,targetPos)-90;
- }
- })
- .call(()=>{
- boomerang.position = targetPos;
- })
- .start();
- this.scheduleOnce(() => {
- if(boomerang.parent) {
- PoolManager.putNode(boomerang);
- this.handleReward(selectedItem);
- this.isBoomeranging = false;
- }
- },1)
- });
- }
- /**
- * 奖励处理方法
- * @param item
- */
- private handleReward(item: any) {
- const [type, amount] = item.quantity.split('_');
- audioMgr.playOneShot(Constants.audios.reward);
- switch(type) {
- case '1001': {//金币
- userIns.data.gold += parseInt(amount);
- uiMgr.show(Constants.popUIs.obtainUI,[item.id,()=>{
- ResUtil.flyAnim(ITEM_TYPE.Coin, this.shoot_btn, this.gold_lable.node, 5, 50,(b) => {});
- }]);
- }
- break;
- case '1002':{ //钻石
- userIns.data.diamond += parseInt(amount);
- uiMgr.show(Constants.popUIs.obtainUI,[item.id,()=>{
- ResUtil.flyAnim(ITEM_TYPE.Diamond, this.shoot_btn, this.diamond_lable.node, 5, 50,(b) => {});
- }]);
- }
- break;
- default: {//武器解锁 获得显示武器栏
- const [gun_id,num] = item.quantity.split('_');
- userIns.unlockGun(gun_id);
- uiMgr.show(Constants.popUIs.obtainUI,[item.id,()=>{}]);
- }
- break;
- }
- }
- /**
- * 按钮点击事件
- * @param event 事件
- * @param param 参数
- */
- override onBtnClicked(event:EventTouch, param:any) {
- super.onBtnClicked(event,param);
- let btnName = event.target.name;
- if(btnName === 'shoot_btn'){//扔飞镖的操作
- this.startToss();
- }
- }
- }
|