|
|
@@ -0,0 +1,353 @@
|
|
|
+package com.adealink.weparty.game.rocket.dialog
|
|
|
+
|
|
|
+import android.annotation.SuppressLint
|
|
|
+import android.graphics.Color
|
|
|
+import android.graphics.drawable.ColorDrawable
|
|
|
+import android.os.Bundle
|
|
|
+import android.os.CountDownTimer
|
|
|
+import android.view.Gravity
|
|
|
+import android.view.View
|
|
|
+import android.view.WindowManager
|
|
|
+import androidx.fragment.app.viewModels
|
|
|
+import androidx.recyclerview.widget.LinearLayoutManager
|
|
|
+import androidx.recyclerview.widget.RecyclerView
|
|
|
+import com.adealink.frame.aab.util.getCompatString
|
|
|
+import com.adealink.frame.base.Rlt
|
|
|
+import com.adealink.frame.base.fastLazy
|
|
|
+import com.adealink.frame.ext.isViewBindingValid
|
|
|
+import com.adealink.frame.log.Log
|
|
|
+import com.adealink.frame.mvvm.lifecycle.observeOnDestroy
|
|
|
+import com.adealink.frame.mvvm.view.viewBinding
|
|
|
+import com.adealink.frame.router.Router
|
|
|
+import com.adealink.frame.router.annotation.RouterUri
|
|
|
+import com.adealink.frame.util.ONE_HOUR
|
|
|
+import com.adealink.frame.util.ONE_MINUTE
|
|
|
+import com.adealink.frame.util.ONE_SECOND
|
|
|
+import com.adealink.frame.util.getDayEndTime
|
|
|
+import com.adealink.frame.util.runOnUiThread
|
|
|
+import com.adealink.weparty.commonui.dialogfragment.BaseDialogFragment
|
|
|
+import com.adealink.weparty.commonui.ext.gone
|
|
|
+import com.adealink.weparty.commonui.ext.hide
|
|
|
+import com.adealink.weparty.commonui.ext.show
|
|
|
+import com.adealink.weparty.commonui.recycleview.adapter.multitype.MultiTypeAdapter
|
|
|
+import com.adealink.weparty.game.R
|
|
|
+import com.adealink.weparty.game.databinding.DialogRocketMainPanelBinding
|
|
|
+import com.adealink.weparty.game.rocket.adapter.LevelRocketTabItemViewBinder
|
|
|
+import com.adealink.weparty.game.rocket.comp.RocketLevelRewardComp
|
|
|
+import com.adealink.weparty.game.rocket.comp.RocketRandListComp
|
|
|
+import com.adealink.weparty.game.rocket.data.LevelRocketTabData
|
|
|
+import com.adealink.weparty.game.rocket.data.TAG_ROCKET_EFFECT
|
|
|
+import com.adealink.weparty.game.rocket.listener.IRocketTabListener
|
|
|
+import com.adealink.weparty.game.rocket.viewmodel.RocketViewModel
|
|
|
+import com.adealink.weparty.game.viewmodel.GameViewModelFactory
|
|
|
+import com.adealink.weparty.module.game.Game
|
|
|
+import com.adealink.weparty.module.game.rocket.RocketLevel
|
|
|
+import com.adealink.weparty.module.room.RoomModule
|
|
|
+import com.tencent.qgame.animplayer.AnimConfig
|
|
|
+import com.tencent.qgame.animplayer.inter.IAnimListener
|
|
|
+import com.tencent.qgame.animplayer.util.ScaleType
|
|
|
+import java.io.File
|
|
|
+import java.util.Date
|
|
|
+import java.util.TimeZone
|
|
|
+import com.adealink.weparty.R as APP_R
|
|
|
+
|
|
|
+@RouterUri(path = [Game.Rocket.RocketPanel.PATH], desc = "火箭主面板")
|
|
|
+class RocketPanelDialog : BaseDialogFragment(R.layout.dialog_rocket_main_panel),
|
|
|
+ IRocketTabListener {
|
|
|
+
|
|
|
+ private val binding by viewBinding(DialogRocketMainPanelBinding::bind)
|
|
|
+ private val rocketViewModel by viewModels<RocketViewModel>({ this }) { GameViewModelFactory() }
|
|
|
+ private var countDownTimer: CountDownTimer? = null
|
|
|
+ private val rocketTabsAdapter = MultiTypeAdapter()
|
|
|
+ private val rocketTabsList by fastLazy {
|
|
|
+ arrayListOf(
|
|
|
+ // 目前仅有4级
|
|
|
+// LevelRocketTabData(RocketLevel.LEVE5),
|
|
|
+ LevelRocketTabData(RocketLevel.LEVE4),
|
|
|
+ LevelRocketTabData(RocketLevel.LEVE3),
|
|
|
+ LevelRocketTabData(RocketLevel.LEVE2),
|
|
|
+ LevelRocketTabData(RocketLevel.LEVE1)
|
|
|
+ )
|
|
|
+ }
|
|
|
+ private var selectedRocketLevel: RocketLevel? = null
|
|
|
+ private var rewardComp: RocketLevelRewardComp? = null
|
|
|
+
|
|
|
+ override fun onCreate(savedInstanceState: Bundle?) {
|
|
|
+ super.onCreate(savedInstanceState)
|
|
|
+ setStyle(STYLE_NO_TITLE, com.adealink.weparty.R.style.BottomDialog)
|
|
|
+ Router.bind(this)
|
|
|
+ }
|
|
|
+
|
|
|
+ override fun onStart() {
|
|
|
+ super.onStart()
|
|
|
+ resetDialogAttributes()
|
|
|
+ }
|
|
|
+
|
|
|
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
|
|
+ super.onViewCreated(view, savedInstanceState)
|
|
|
+ viewLifecycleOwner.observeOnDestroy {
|
|
|
+ countDownTimer?.cancel()
|
|
|
+ binding.bgEffectView.setAnimListener(null)
|
|
|
+ binding.bgEffectView.stopPlay()
|
|
|
+ binding.rocketEffectView.setAnimListener(null)
|
|
|
+ binding.rocketEffectView.stopPlay()
|
|
|
+ }
|
|
|
+ showLaunchPadAnimation()
|
|
|
+ }
|
|
|
+
|
|
|
+ override fun initViews() {
|
|
|
+ super.initViews()
|
|
|
+ rocketTabsAdapter.register(LevelRocketTabItemViewBinder(this))
|
|
|
+ binding.rvRocketLevel.layoutManager =
|
|
|
+ LinearLayoutManager(context, RecyclerView.VERTICAL, false)
|
|
|
+ binding.rvRocketLevel.adapter = rocketTabsAdapter
|
|
|
+ rocketTabsAdapter.items = rocketTabsList
|
|
|
+ rocketTabsAdapter.notifyDataSetChanged()
|
|
|
+
|
|
|
+ binding.ivClose.setOnClickListener {
|
|
|
+ dismiss()
|
|
|
+ }
|
|
|
+ val kingClickListener = View.OnClickListener {
|
|
|
+ val act = activity ?: return@OnClickListener
|
|
|
+ Router.build(act, Game.Rocket.RocketKing.PATH).start()
|
|
|
+ }
|
|
|
+ binding.ivKing.setOnClickListener(kingClickListener)
|
|
|
+ binding.ivRecord.setOnClickListener {
|
|
|
+ Router.getRouterInstance<BaseDialogFragment>(Game.Rocket.RocketRecord.PATH)
|
|
|
+ ?.show(childFragmentManager)
|
|
|
+ }
|
|
|
+ binding.ivHelp.setOnClickListener {
|
|
|
+ Router.getRouterInstance<BaseDialogFragment>(Game.Rocket.RocketRule.PATH)
|
|
|
+ ?.show(childFragmentManager)
|
|
|
+ }
|
|
|
+ binding.bgEffectView.setScaleType(ScaleType.FIT_CENTER)
|
|
|
+ binding.bgEffectView.setLoop(Int.MAX_VALUE)
|
|
|
+ binding.rocketEffectView.setScaleType(ScaleType.CENTER_CROP)
|
|
|
+ binding.rocketEffectView.setLoop(Int.MAX_VALUE)
|
|
|
+ binding.vTopSpace.setOnClickListener { dismiss() }
|
|
|
+ binding.vTopSpace1.setOnClickListener { dismiss() }
|
|
|
+ }
|
|
|
+
|
|
|
+ @SuppressLint("NotifyDataSetChanged")
|
|
|
+ override fun observeViewModel() {
|
|
|
+ super.observeViewModel()
|
|
|
+ rocketViewModel.maxRocketLevelLD.observe(viewLifecycleOwner) {
|
|
|
+ rocketTabsList.clear()
|
|
|
+ for (i in it downTo 1) {
|
|
|
+ rocketTabsList.add(LevelRocketTabData(RocketLevel.map(i)))
|
|
|
+ }
|
|
|
+ rocketTabsAdapter.items = rocketTabsList
|
|
|
+ rocketTabsAdapter.notifyDataSetChanged()
|
|
|
+ }
|
|
|
+ rocketViewModel.currRocketInfoLD.observe(viewLifecycleOwner) {
|
|
|
+ if (this.selectedRocketLevel != it.first) {
|
|
|
+ this.selectedRocketLevel = it.first
|
|
|
+ updateLaunchPadRocket()
|
|
|
+ }
|
|
|
+
|
|
|
+ rocketTabsList.onEach { rocketTab ->
|
|
|
+ rocketTab.selected = rocketTab.level == it.first
|
|
|
+ }
|
|
|
+ rocketTabsAdapter.items = rocketTabsList
|
|
|
+ rocketTabsAdapter.notifyDataSetChanged()
|
|
|
+ rewardComp?.changeToLevel(it.first)
|
|
|
+ //更新进度
|
|
|
+ updateEnergyProgress(it.second)
|
|
|
+ }
|
|
|
+ rocketViewModel.rocketRewardLD.observeWithoutCache(viewLifecycleOwner) {
|
|
|
+ RoomModule.getJoinedRoomId()?.let { roomId ->
|
|
|
+ rocketViewModel.getRocketInfo(roomId, true)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ override fun initComponents() {
|
|
|
+ super.initComponents()
|
|
|
+ rewardComp = RocketLevelRewardComp(this, binding.layoutAward).also {
|
|
|
+ it.attach()
|
|
|
+ }
|
|
|
+ RocketRandListComp(this, binding.layoutTop3).attach()
|
|
|
+ }
|
|
|
+
|
|
|
+ override fun loadData() {
|
|
|
+ super.loadData()
|
|
|
+ startCountDown()
|
|
|
+ RoomModule.getJoinedRoomId()?.let { roomId ->
|
|
|
+ rocketViewModel.getRocketInfo(roomId, true)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private fun startCountDown() {
|
|
|
+ // PM Mark:每日重置火箭的时间用utc+2.5的24点
|
|
|
+ val dayEndTime = getDayEndTime(Date(), TimeZone.getTimeZone("UTC")).time
|
|
|
+ val offsetMillis = (2.5 * 60 * 60 * 1000).toLong()
|
|
|
+ val millisInFuture = dayEndTime - offsetMillis - System.currentTimeMillis()
|
|
|
+ countDownTimer = object : CountDownTimer(millisInFuture, 1000L) {
|
|
|
+
|
|
|
+ override fun onTick(millisUntilFinished: Long) {
|
|
|
+ updateLeftTime(millisUntilFinished)
|
|
|
+ }
|
|
|
+
|
|
|
+ override fun onFinish() {
|
|
|
+ runOnUiThread(
|
|
|
+ {
|
|
|
+ loadData()
|
|
|
+ }, 2000L
|
|
|
+ )
|
|
|
+ }
|
|
|
+ }
|
|
|
+ countDownTimer?.start()
|
|
|
+ }
|
|
|
+
|
|
|
+ private fun updateLeftTime(millisUntilFinished: Long) {
|
|
|
+ if (!isViewBindingValid()) {
|
|
|
+ return
|
|
|
+ }
|
|
|
+ var leftTimeMS: Long = millisUntilFinished
|
|
|
+ val leftTimeHour = leftTimeMS / ONE_HOUR
|
|
|
+ leftTimeMS = leftTimeMS.rem(ONE_HOUR)
|
|
|
+ val leftTimeMinute = leftTimeMS / ONE_MINUTE
|
|
|
+ leftTimeMS = leftTimeMS.rem(ONE_MINUTE)
|
|
|
+ val leftTimeSeconds = leftTimeMS / ONE_SECOND
|
|
|
+ binding.layoutProgressTime.countDownHourTv.text = getTimeNumStr(leftTimeHour)
|
|
|
+ binding.layoutProgressTime.countDownMinTv.text = getTimeNumStr(leftTimeMinute)
|
|
|
+ binding.layoutProgressTime.countDownSecondTv.text = getTimeNumStr(leftTimeSeconds)
|
|
|
+ }
|
|
|
+
|
|
|
+ private fun getTimeNumStr(value: Long): String {
|
|
|
+ return when {
|
|
|
+ value >= 10 -> "$value"
|
|
|
+ else -> "0${value}"
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private fun resetDialogAttributes() {
|
|
|
+ val dialog = dialog ?: return
|
|
|
+ val window = dialog.window ?: return
|
|
|
+ val layoutParams = window.attributes
|
|
|
+ layoutParams.gravity = Gravity.BOTTOM
|
|
|
+ layoutParams.width = WindowManager.LayoutParams.MATCH_PARENT
|
|
|
+ layoutParams.height = WindowManager.LayoutParams.MATCH_PARENT
|
|
|
+ layoutParams.dimAmount = 0.7f
|
|
|
+ window.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
|
|
|
+ window.attributes = layoutParams
|
|
|
+ dialog.setCanceledOnTouchOutside(true)
|
|
|
+ }
|
|
|
+
|
|
|
+ override fun onLevelRocketSelected(level: RocketLevel) {
|
|
|
+ if (selectedRocketLevel?.level == level.level) {
|
|
|
+ return
|
|
|
+ }
|
|
|
+ this.selectedRocketLevel = level
|
|
|
+ rocketViewModel.changeToLevel(level, true)
|
|
|
+ updateLaunchPadRocket()
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 展示发射台动效
|
|
|
+ */
|
|
|
+ private fun showLaunchPadAnimation() {
|
|
|
+ rocketViewModel.getLaunchPadEffectPath().observe(viewLifecycleOwner) {
|
|
|
+ when (it) {
|
|
|
+ is Rlt.Success -> {
|
|
|
+ binding.ivBg.gone()
|
|
|
+ binding.bgEffectView.show()
|
|
|
+ binding.bgEffectView.startPlay(File(it.data))
|
|
|
+ }
|
|
|
+
|
|
|
+ is Rlt.Failed -> {
|
|
|
+ binding.ivBg.show()
|
|
|
+ binding.bgEffectView.gone()
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 更新发射台火箭动效
|
|
|
+ */
|
|
|
+ private fun updateLaunchPadRocket() {
|
|
|
+ val level = selectedRocketLevel ?: return
|
|
|
+
|
|
|
+ val effectPath = rocketViewModel.getDownloadedLaunchPadRocketEffectPath(level)
|
|
|
+ if (effectPath != null) {
|
|
|
+ playRocketVapVideo(effectPath)
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ showStaticLaunchPadRocket()
|
|
|
+ rocketViewModel.getLaunchPadRocketEffectPath(level).observe(viewLifecycleOwner) {
|
|
|
+ when (it) {
|
|
|
+ is Rlt.Success -> {
|
|
|
+ playRocketVapVideo(it.data)
|
|
|
+ }
|
|
|
+
|
|
|
+ is Rlt.Failed -> {
|
|
|
+ showStaticLaunchPadRocket()
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private fun playRocketVapVideo(effectPath: String) {
|
|
|
+ if (!isViewBindingValid()) {
|
|
|
+ return
|
|
|
+ }
|
|
|
+ binding.rocketIv.hide()
|
|
|
+ binding.rocketEffectView.show()
|
|
|
+ if (binding.rocketEffectView.isRunning()) {
|
|
|
+ binding.rocketEffectView.setAnimListener(object : IAnimListener {
|
|
|
+
|
|
|
+ override fun onFailed(errorType: Int, errorMsg: String?) {
|
|
|
+ Log.e(TAG_ROCKET_EFFECT, "play error, errorType:$errorType, errorMsg:$errorMsg")
|
|
|
+ }
|
|
|
+
|
|
|
+ override fun onVideoStart() {
|
|
|
+ }
|
|
|
+
|
|
|
+ override fun onVideoRender(frameIndex: Int, config: AnimConfig?) {
|
|
|
+ }
|
|
|
+
|
|
|
+ override fun onVideoComplete() {
|
|
|
+ }
|
|
|
+
|
|
|
+ override fun onVideoDestroy() {
|
|
|
+ Log.d(TAG_ROCKET_EFFECT, "playRocketVapVideo, onVideoDestroy")
|
|
|
+ if (!isViewBindingValid()) {
|
|
|
+ return
|
|
|
+ }
|
|
|
+ binding.rocketEffectView.startPlay(File(effectPath))
|
|
|
+ }
|
|
|
+ })
|
|
|
+ binding.rocketEffectView.stopPlay()
|
|
|
+ } else {
|
|
|
+ binding.rocketEffectView.startPlay(File(effectPath))
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 展示静态发射台
|
|
|
+ */
|
|
|
+ private fun showStaticLaunchPadRocket() {
|
|
|
+ binding.rocketEffectView.hide()
|
|
|
+ val resId = when (selectedRocketLevel?.level ?: 1) {
|
|
|
+ 2 -> APP_R.drawable.game_rocket_level_2_large_ic
|
|
|
+ 3 -> APP_R.drawable.game_rocket_level_3_large_ic
|
|
|
+ 4 -> APP_R.drawable.game_rocket_level_4_large_ic
|
|
|
+ in 5..Int.MAX_VALUE -> APP_R.drawable.game_rocket_level_5_large_ic
|
|
|
+ else -> APP_R.drawable.game_rocket_level_1_large_ic
|
|
|
+ }
|
|
|
+ binding.rocketIv.show()
|
|
|
+ binding.rocketIv.setImageResource(resId)
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 更新能量条
|
|
|
+ */
|
|
|
+ private fun updateEnergyProgress(progress: Int) {
|
|
|
+ val ratio = progress / 100F
|
|
|
+ binding.layoutProgressTime.sinProgressBehind.progress = ratio
|
|
|
+ binding.layoutProgressTime.tvProgress.text =
|
|
|
+ getCompatString(APP_R.string.common_percent, progress)
|
|
|
+ }
|
|
|
+}
|