今天分享一个抽奖的类Lottery

/*
 * Copyright (C) 2014 Jason Fang ( [email protected] )
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package fyc.framework.anim;

import java.util.concurrent.TimeUnit;

import android.animation.Animator;
import android.animation.Animator.AnimatorListener;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.annotation.TargetApi;
import android.os.Build;
import android.os.CountDownTimer;
import android.view.animation.DecelerateInterpolator;
import android.view.animation.LinearInterpolator;
import android.widget.ImageView;
import fyc.framework.util.Flog;
import fyc.framework.util.RandomUtils;

/**
 * @author Jason Fang
 * @datetime 2015年1月29日 下午7:19:36
 */
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public class Lottery {
    static final boolean DEBUG = true;

    private static final int LOADING_UNIT_DEGREE = 360 * 5;
    private static final int LOADING_DURATION     = 720 * 5;
    private static final long LOTTERY_TIME_OUT     = TimeUnit.SECONDS.toMillis(5);

    private ImageView mImageView;
    private ObjectAnimator mLoadingAnim;
    private float mInitDegree = 0;
    private int mMaxLevel = 10;
    private int mUnitDegree;
    private int[] mLevelMap;
    private long mTimeout = LOTTERY_TIME_OUT;

    private boolean mIsLottering = false;
    private boolean mIsInStop = false;

    private OnLotteryListener mListener;
    private LotteryTimeOut mLotteryTimeOut;

    private Lottery(ImageView imageView, OnLotteryListener listener) {
        mImageView = imageView;
        mListener = listener;
    }

    public static Lottery newInstance(ImageView imageView, OnLotteryListener listener) {
        return new Lottery(imageView, listener);
    }

    public Lottery setLevel(int level) {
        mMaxLevel = level;
        mUnitDegree = 360 / mMaxLevel;
        return this;
    }

    public Lottery setLevelMap(int[] levelMap) {
        if (levelMap.length != mMaxLevel) {
            throw new IllegalArgumentException("levelMap length must equal MaxLevel!");
        }
        mLevelMap = levelMap;
        return this;
    }

    public Lottery setTimeOut(int timeout) {
        if (timeout <= 0) return this;

        mTimeout = TimeUnit.SECONDS.toMillis(timeout);
        return this;
    }

    public Lottery start() {
        if (mIsLottering) return this;
        mIsLottering = true;

        if (DEBUG) Flog.i("start");

        loadingAnimStart();

        if (mListener != null) {
            mListener.onLotteryStart();
        }

        mLotteryTimeOut = new LotteryTimeOut();
        mLotteryTimeOut.start();

        return this;
    }

    public void stop(int level) {
        if (mIsInStop) return;
        mIsInStop = true;

        if (mLotteryTimeOut != null) {
            mLotteryTimeOut.cancel();
        }

        int levelAward = getLevelAward(level);

        if (mLoadingAnim != null && mLoadingAnim.isRunning()) {
            mLoadingAnim.cancel();
        }

        if (levelAward < 0 || levelAward > mMaxLevel) {
            throw new IllegalArgumentException("level cannot below 0 or than MaxLevel!");
        }

        float stopDegree = 0;
        if (levelAward == 0) {
            stopDegree = LOADING_UNIT_DEGREE - mUnitDegree / 2;
        } else {
            stopDegree = (LOADING_UNIT_DEGREE - mUnitDegree / 2) + RandomUtils.getRandom(mUnitDegree * levelAward + 5, mUnitDegree * (levelAward + 1) - 5);
        }

        float startDegree = 0f;
        if (mLoadingAnim != null) {
            startDegree = (Float)mLoadingAnim.getAnimatedValue() % 360;
        } else {
            throw new RuntimeException("Must invoke start first!");
        }

        long duration = (long)((stopDegree - startDegree) / ((LOADING_UNIT_DEGREE / (float)LOADING_DURATION)));

        stopAnimStart(startDegree, stopDegree, duration, levelAward);

        mInitDegree = stopDegree;
    }

    int getLevelAward(int level) {
        if (mLevelMap == null || mLevelMap.length == 0 || level == 0) return level;
        return mLevelMap[level - 1];
    }

    void loadingAnimStart() {
        mLoadingAnim = ObjectAnimator.ofFloat(mImageView, "rotation", mInitDegree % 360, LOADING_UNIT_DEGREE);
        mLoadingAnim.setInterpolator(new LinearInterpolator());
        mLoadingAnim.setRepeatCount(ValueAnimator.INFINITE);
        mLoadingAnim.setDuration(LOADING_DURATION);
        mLoadingAnim.start();
    }

    void stopAnimStart(float startDegree, float stopDegree, long duration, int levelAward) {
        ObjectAnimator anim = ObjectAnimator.ofFloat(mImageView, "rotation", startDegree, stopDegree);
        anim.setInterpolator(new DecelerateInterpolator());
        anim.setDuration(duration * 2);
        anim.addListener(new LotteryAnimatorListener(levelAward));
        anim.start();
    }

    class LotteryTimeOut extends CountDownTimer {

        public LotteryTimeOut() {
            super(mTimeout, mTimeout);
        }

        @Override
        public void onTick(long millisUntilFinished) {
        }

        @Override
        public void onFinish() {
            stop(0);
        }

    }

    class LotteryAnimatorListener implements AnimatorListener {

        private int mLevel;

        public LotteryAnimatorListener() {
        }

        public LotteryAnimatorListener(int level) {
            mLevel = level;
        }

        @Override
        public void onAnimationStart(Animator animation) {
        }

        @Override
        public void onAnimationEnd(Animator animation) {
            if (mListener != null) {
                mListener.onLotteryStop(mLevel);
                mIsLottering = false;
                mIsInStop = false;
            }
        }

        @Override
        public void onAnimationCancel(Animator animation) {
        }

        @Override
        public void onAnimationRepeat(Animator animation) {
        }

    }

    public interface OnLotteryListener {
        public void onLotteryStart();
        public void onLotteryStop(int level);
    }
}

如果要指针初始化指向圆盘的缝隙. 需要做简要的修改!

DEMO

mLottery = Lottery.newInstance(mWheel, new OnLotteryListener() {

            @Override
            public void onLotteryStop(int level) {
                Flog.i("onLotteryStop:" + level);
            }

            @Override
            public void onLotteryStart() {
                Flog.i("onLotteryStart");
            }
        })
        .setLevel(10)  //总共几个奖
        .setLevelMap(new int[]{5, 1, 1, 1, 1, 1, 1, 1, 1, 1}) //映射奖项
        .setTimeOut(4);

获取到服务器端值之后调用

mLottery.stop(5);  //参数为几等奖

时间: 2024-11-05 22:54:19

今天分享一个抽奖的类Lottery的相关文章

分享一个记录日志的类,可多线程使用。

好久没写博客了,今天分享一个自己用的日志类,非原创,借鉴了前辈的一个想法,然后修改来的. 日志我们是必须的,现在程序都是多线程并发了,记日志就有可能出现问题了,lock?影响性能.log4net太重量级了,本日志是一个轻量级的小工具. 废话不多说,看源码: 1 using System; 2 using System.Collections.Generic; 3 using System.IO; 4 using System.Text; 5 6 namespace GEDU.CourseOnli

[原创]分享一个轻量级日志类

日常开发中,常常会在程序部署到生产环境后发现有些问题,但无法直接调试,这就需要用到日志,本来想找一些开源的完善的日志类来实现,但试了几个都感觉太重.于是意识到一个问题,懒是偷不得的,只好撸起袖子,自己写一个.这个日志类是基于订阅模式的,而且是线程安全的,现在分享给大家,希望能给大家带来帮助. 闲话不多说,直接上代码.代码有两个实现版本(Java与C#),这里放出的是C#. 一共用到三个类:JzgLogs.cs主类,LogBuffer.cs日志缓冲类,LogInfo是用于日志缓冲中做记录的实体类,

分享一个Redis帮助类

最近在项目中使用了redis来存储已经下载过的URL,项目中用的是ServiceStack来操作Redis,一开始ServiceStack的版本用的是最新的,后来发现ServiceStack已经商业化了,非商业版本每个小时只能操作6000次Redis,后来把ServiceStack换成了V3版本. 在项目中用到了redis的Hash集合,但是ServiceStack封装的使用起来不方便,于是就自己封装了一个dll,利用的ServiceStack的pool来动态创建IRedisClient实例,创

分享一个简单的简单的SQLHelper类

分享一个简单的简单的SQLHelper类,代码如下: 1 class SqlHelper 2 { 3 public static readonly string connstr = 4 ConfigurationManager.ConnectionStrings["dbConnStr"].ConnectionString; 5 6 public static int ExecuteNonQuery(string cmdText, 7 params SqlParameter[] para

分享一个PHP调试日志类

分享一个我自己用的在 WordPress 开发中用得到的一个调试日志类. <?php /** * @author: suifengtec coolwp.com * @date: 2013-02-03 09:55:55 * @last Modified by: suifengtec coolwp.com * @last Modified time: 2015-07-12 18:40:02 */ if(function_exists('add_action')){ defined('ABSPATH'

分享一个SqliteHelper类

分享一个SqliteHelper类 SQLite作为一个本地文件数据库相当好用,小巧.快速.支持事务.关系型,甚至可以运行在Android上.在很久以前的一个项目中,我们用过它来将接收到的数据做本地统计,数据量很大,甚至于我们想自己搞个内存空间专门做缓存,缓存满后再一点点地往SQLite中移,现在看起来是多余的,这也不符合开发的过程.在开发中,应该先把功能做出来,如果有性能问题,再找出解决方法.直接在SQLite中做插入而不是先在内存中做,它的效率已经达到了要求. 现在跟大家分享一个对SQLit

分享一个线程安全的单例模板类

单例模式应该说是最简单的设计模式了.在此分享一个线程安全的单例模板类. template <typename Type> class CSingleton { public: static Type* GetInstance() { // kBeingCreatedMarker用来表示单例实例正在创建过程中. // 此处初始化为1是因为操作系统不会分配地址为1的指针. static const volatile intptr_t kBeingCreatedMarker = 1; // 如果m_

分享一个自定义的console类 让你不再纠结JS中的调试代码的兼容

分享一个自定义的console类 让你不再纠结JS中的调试代码的兼容 在写JS的过程中,为了调试我们常常会 写很多 console.log.console.info.console.group.console.warn.console.error代码来查看JS 的运行情况,但发布时又因为IE不支持console,又要去掉这些代码,一不小心就会出错 问题的产生 在写JS的过程中,为了调试我们常常会写很多 console.log.console.info.console.group.console.

分享一个用OnGUI在手机上打印调试信息的工具类

游戏发布到手机上调试的时候有时候会需要在屏幕上打印一些信息,我写了一个小工具类,分享出来,用的是OnGUI,很简单,直接上代码了 using UnityEngine; using System.Collections; using System.Collections.Generic; public class OnGUIDebug : MonoBehaviour { public static OnGUIDebug Instance; public int FontSize = 40; pub