随笔-自控概率的大转盘抽奖

这篇具有很好参考价值的文章主要介绍了随笔-自控概率的大转盘抽奖。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

        最近项目需要做一个大转盘抽奖功能,抽奖的道具、数量及概率都有策划配置。废话不多说,先上配置表:

[
{"id":0,"type":1,"num":5,"proportion":20},
{"id":1,"type":0,"num":1500,"proportion":7},
{"id":2,"type":1,"num":20,"proportion":8},
{"id":3,"type":0,"num":500,"proportion":15},
{"id":4,"type":1,"num":5,"proportion":20},
{"id":5,"type":0,"num":1500,"proportion":7},
{"id":6,"type":1,"num":20,"proportion":8},
{"id":7,"type":0,"num":500,"proportion":15}
]

        对应的C#的实体类如下:

public class PrizeWhellData
{
    /// <summary>
    /// id
    /// </summary>
    public int id;

    /// <summary>
    /// 类型(0:金币;1:钻石;2:装饰币;3:各种道具预留)
    /// </summary>
    public int type;

    /// <summary>
    /// 数值
    /// </summary>
    public int num;

    /// <summary>
    /// 占比
    /// </summary>
    public float proportion;
}

        接下来就是转盘的功能了:

  • 首先是初始化阶段,配表Json解析这里就不写了。已经存在prizeWhellDataDic这个字典里了。
    public Transform RollPanel;//旋转的转盘
    public Button startBtn;//开始按钮
    private bool isClick;
    int rollID;

    #region 转盘相关
    RollState curState; //当前转盘的状态
    float allTime = 0;//旋转时间  总的时间
    float endAngle;//最终的角度

    //变速段
    float MaxSpeed = 800;//最大速度
    float factor;//速度因子
    float accelerateTime = 1;//加速到最大速度的时间 ---暂定为1
    float speedUpTime = 3;//加速段的总时间
    float tempAngle;//开始减速段时转盘此时的旋转角度
    float k = 2f; //减速阶段的速度系数 --减速快慢由此决定 
    #endregion
    
    //角度,分了8份,所以角度是以下8份
    private string[] angles = new string[8] { "0,45", "45,90", "90,135", 
        "135,180", "180,225", "225,270", "270,315", "315,360" };
    private List<int> rates = new();//几率数组
    public Text[] itemTexts;
    public Image[] itemIcons;

    // 配表数据
    private Dictionary<int, PrizeWhellData> prizeWhellDataDic = new();

    private void Start()
    {
        startBtn.onClick.AddListener(StartBtnEvent);

        for (int i = 0; i < prizeWhellDataDic.Count; i++)
        {
            if (prizeWhellDataDic[i].type == 0)
            {
                //如果是金币,放金币的图片
                itemIcons[i].sprite = GameManager.Instance.GetSpriteAtlas("pw_icon_glodBig");
            }
            else if (prizeWhellDataDic[i].type == 1)
            {
                //如果是钻石,放钻石的图片
                if (prizeWhellDataDic[i].num > 10)
                {
                    itemIcons[i].sprite = GameManager.Instance.GetSpriteAtlas("pw_icon_gemB");
                }
                else
                { 
                    itemIcons[i].sprite = GameManager.Instance.GetSpriteAtlas("pw_icon_gemS");
                }
            }
            itemIcons[i].SetNativeSize();
            itemTexts[i].text = string.Format("x{0}", prizeWhellDataDic[i].num);
            rates.Add((int)prizeWhellDataDic[i].proportion);
        }
        
        //初始化数据
        isClick = true;
        rollID = 0;
        RollPanel.rotation = Quaternion.identity;
        //for (int i = 0; i < 100; i++)
        //{
        //    Debug.LogError("testRandRate:   " + randRate());
        //}
    }
  • 接下来就是旋转的功能逻辑:

 文章来源地址https://www.toymoban.com/news/detail-604601.html

    void Update()
    {
        if (curState == RollState.None)
        {
            return;
        }
        allTime += Time.deltaTime;
        //先进入加速阶段
        if (curState == RollState.SpeedUp)
        {
            factor = allTime / accelerateTime;
            factor = factor > 1 ? 1 : factor;
            RollPanel.Rotate(factor * MaxSpeed * Time.deltaTime * new Vector3(0, 0, -1), Space.Self);
        }
        //当旋转时间大于等于了加速段的时间就开始进行减速
        if (allTime >= speedUpTime && curState == RollState.SpeedUp)
        {
            curState = RollState.SpeedDown;
            tempAngle = GetTempAngle();
            //Debug.Log("tempAngle:" + tempAngle);
        }
        if (curState == RollState.SpeedDown)
        {
            //通过差值运算实现旋转到指定角度(球型插值无法实现大于360°的计算)
            tempAngle = Mathf.Lerp(tempAngle, endAngle, Time.deltaTime * k);
            RollPanel.rotation = Quaternion.Euler(0, 0, tempAngle);

            //旋转结束
            if (Mathf.Abs(tempAngle - endAngle) <= 1)
            {
                curState = RollState.None;
                StartCoroutine(End());
            }
        }
    }

    private IEnumerator End()
    { 
        //奖励rollid
        if (prizeWhellDataDic.ContainsKey(rollID))
        {
            int numCount = prizeWhellDataDic[rollID].num;
            if (prizeWhellDataDic[rollID].type == 0)
            {//金币
                UIController.Instance._uiMain._goldRec.GetComponent<Canvas>().overrideSorting = true;

                Vector3 endPos = UIController.Instance._uiMain._currentGoldImg.transform.position;
                TweenUtility.PlayBoomCoinFly(Vector3.zero, endPos, numCount, 1.2f);
                AudioManager.Instance.PlayAudio("box_gold");
            }
            else if (prizeWhellDataDic[rollID].type == 1)
            { //钻石
                UIController.Instance._uiMain._diamondRec.GetComponent<Canvas>().overrideSorting = true;

                Vector3 endPos = UIController.Instance._uiMain._currentDiamondImg.transform.position;
                TweenUtility.PlayBoomCoinFly(Vector3.zero, endPos, numCount, 1.2f);
                AudioManager.Instance.PlayAudio("box_gem");
            }
        }

        yield return new WaitForSeconds(1.5f);

        if (prizeWhellDataDic.ContainsKey(rollID))
        {
            if (prizeWhellDataDic[rollID].type == 0)
            {//金币
                Debug.Log("获取到了金币:" + prizeWhellDataDic[rollID].num);
            }
            else if (prizeWhellDataDic[rollID].type == 1)
            { //钻石
                Debug.Log("获得了钻石:" + prizeWhellDataDic[rollID].num);
            }
        }
        startBtn.gameObject.SetActive(true);
        isClick = true;
    }

    private void StartBtnEvent()
    {
        startBtn.gameObject.SetActive(false);

        if (!isClick) return;
        StartTurnWheel();
    }

    /// <summary>
    /// 开始旋转转盘
    /// </summary>
    public void StartTurnWheel()
    {
        if (curState != RollState.None)
        {
            return;
        }

        isClick = false;

        allTime = 0;
        tempAngle = 0;
        rollID = randRate();
        endAngle = GetEndAngle(rollID);
        //Debug.LogError("rollID: " + rollID + "    endAngle: " + endAngle);
        curState = RollState.SpeedUp;
    }

    //  0      1      2        3        4        5        6        7     
    //(0,45)(45,90)(90,135)(135,180)(180,225)(225,270)(270,315)(315,360)
    //获取旋转的结果,通过设定的概率然后随机得到结果,我们可以自定义概率

    /// <summary>
    /// 得到当前转盘的旋转角度
    /// </summary>
    /// <returns></returns>
    private float GetTempAngle()
    {
        //Debug.Log("RollPanel.eulerAngles.z: " + RollPanel.eulerAngles.z);
        return (360 - RollPanel.eulerAngles.z) % 360;
    }

    /// <summary>
    /// 计算结束时的角度,因为是顺时针旋转所以是负的
    /// </summary>
    /// <param name="rollId"></param>
    /// <returns></returns>
    private float GetEndAngle(int rollId)
    {
        float min = CFunc.ObjToFloat(angles[rollId].Split(",")[0]);
        float max = CFunc.ObjToFloat(angles[rollId].Split(",")[1]);
        return -(360 - Random.Range(min + 5, max - 5));
    }
    
    //rate:几率数组(%),  total:几率总和(100%)
    public int randRate(int total = 100)
    {
        int rand = Random.Range(0, total + 1);
        for (int i = 0; i < rates.Count; i++)
        {
            rand -= rates[i];
            if (rand <= 0)
            {
                return i;
            }
        }
        return 0;
    }

    /// <summary>
    /// 转盘旋转的四种状态
    /// </summary>
    public enum RollState
    {
        None,
        SpeedUp,
        SpeedDown,
        End
    }

 这就是大转盘的基本功能。可以在其中添加一些特效和动画效果。

 

到了这里,关于随笔-自控概率的大转盘抽奖的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • html+css+js实现转盘抽奖

     

    2024年01月25日
    浏览(37)
  • 基于uniapp ts 实现微信小程序动态抽奖幸运大转盘

     这是view视图层布局,内容中有注释,这里就不过多标注 以下是数据层实现方法  注:本人技术比较菜,体谅体谅,有好的建议欢迎提出来 上述是个人理解。描述不恰当的地方欢迎指正。一起进步~

    2024年02月03日
    浏览(54)
  • 可控概率抽奖算法

    本文PHP语言去实现,只实现核心可控概率引擎,库存判断等其它业务需要其它代码配合实现。 weight权重概率字段,不是概率字段,不需要总和为100 如下,代表16个人抽奖,有10人是谢谢惠顾,有5人中2元,有1人中5元,有0人中50W。 3轮抽奖,每轮抽160万次,可得以下表格: 轮

    2024年02月19日
    浏览(26)
  • 概率论的学习和整理14: 概率发生变化的抽奖,如何计算概率?( 缺 VBA模拟部分)

    目录 1 问题:如果要考察的概率模型(抽奖)里,基础中奖概率一直在变化怎么办? 1.1 基础问题,抽奖抽中的概率会变化 1.2  概率稳定的老模型,有什么问题? 1.3 比如:构建这样的一个新模型 2 用excel 计算这些概率 2.1 不用几何分布,但是照样可以求第n次是第一次成功的概率

    2024年01月17日
    浏览(60)
  • 【Unity3D】UI Toolkit自定义元素

    1 前言         UI Toolkit 支持通过继承 VisualElement 实现自定义元素,便于通过脚本控制元素。另外,UI Toolkit 也支持将一个容器及其所有子元素作为一个模板,便于通过脚本复制模板。         如果读者对 UI Toolkit 不是太了解,可以参考以下内容。 UI Toolkit简介 UI Toolkit容器

    2024年02月09日
    浏览(55)
  • 【Unity3D框架】Unity Package Manager自定义包管理实践

            在公司开发的前两个项目,虽然搭建了基础的框架,有一些目录划分,但是当项目复杂度增长到一定程度,以及后续新开了一些新的项目之后,对于基础框架的管理就遇到了一些挑战,主要体现在以下几个方面:         1、多项目之间拷贝了类似的基础框架,但是

    2024年02月03日
    浏览(72)
  • Unity简单实现老虎机抽奖效果

    Unity:2019.4.36 VS:2017 1、右键—UI—RawImage (自己摆好位置并设置好大小,然后选择图片,挂载RawImageTest脚本。本案例需要创建6个RawImage,分别是一个背景图片、三列水果和两块遮板,背景图片必须放在最上面) 2、右键—UI—Button (同样自己摆好位置并修改大小,然后修改一

    2024年02月16日
    浏览(32)
  • Unity面试题随笔(一)

    1.Unity中碰撞器(Collider)和触发器(Trigger)的区别? 碰撞器(Collider)有碰撞效果,IsTrigger=false,可以调用OnCollisionEnter/Stay/Exit函数 触发器(Trigger)没有碰撞效果,isTrigger=true,可以调用OnTriggerEnter/Stay/Exit函数 2.物体发生碰撞的必要条件? 必须带有collider碰撞器和rigibody刚体属性或者人

    2024年02月07日
    浏览(50)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包