Files

428 lines
8.4 KiB
Vue
Raw Permalink Normal View History

<script setup>
import { onLaunch, onShow, onHide } from '@dcloudio/uni-app'
import { useGameStore } from '@/store/game.js'
import { usePlayerStore } from '@/store/player.js'
import {
saveGame,
loadGame,
resetGame as resetGameStorage,
hasSaveData
} from '@/utils/storage.js'
import {
startGameLoop,
stopGameLoop,
isGameLoopRunning,
calculateOfflineEarnings,
applyOfflineEarnings,
updateLastSaveTime,
refreshMarketPrices
} from '@/utils/gameLoop.js'
import { checkAndTriggerEvent } from '@/utils/eventSystem.js'
import { addItemToInventory } from '@/utils/itemSystem.js'
import { unlockSkill } from '@/utils/skillSystem.js'
// 记录应用隐藏时间(用于计算离线收益)
let appHideTime = Date.now()
onLaunch(() => {
try {
console.log('App Launch')
// 初始化Store
const gameStore = useGameStore()
const playerStore = usePlayerStore()
// 设置自动保存触发器
gameStore.triggerAutoSave = () => {
performAutoSave()
}
// 设置事件触发器
gameStore.triggerEvent = (type, context) => {
checkAndTriggerEvent(gameStore, playerStore, type, context)
}
// 加载存档
const loadResult = loadGame(gameStore, playerStore)
if (loadResult.success) {
// 存档加载成功
console.log('Save loaded, version:', loadResult.version)
// 添加欢迎日志
gameStore.addLog('欢迎回来!', 'info')
// 初始化市场价格(如果需要)
if (gameStore.gameTime.day !== gameStore.marketPrices.lastRefreshDay) {
refreshMarketPrices(gameStore)
}
} else if (loadResult.isNewGame) {
// 新游戏
console.log('Starting new game')
initializeNewGame(gameStore, playerStore)
} else {
// 加载失败,重置游戏
console.error('Load failed, resetting game')
resetGameStorage(gameStore, playerStore)
initializeNewGame(gameStore, playerStore)
}
// 启动游戏循环
startGameLoop(gameStore, playerStore)
// 更新保存时间
updateLastSaveTime()
} catch (error) {
console.error('App Launch failed:', error)
// 可以在这里显示友好的错误提示
}
})
onShow(() => {
console.log('App Show')
const gameStore = useGameStore()
const playerStore = usePlayerStore()
// 检查离线收益
checkOfflineEarnings(gameStore, playerStore)
// 确保游戏循环正在运行
if (!isGameLoopRunning()) {
startGameLoop(gameStore, playerStore)
}
})
onHide(() => {
console.log('App Hide')
const gameStore = useGameStore()
const playerStore = usePlayerStore()
// 记录隐藏时间
appHideTime = Date.now()
// 自动保存
performAutoSave()
// 停止游戏循环
stopGameLoop()
})
/**
* 初始化新游戏
* @param {Object} gameStore - 游戏Store
* @param {Object} playerStore - 玩家Store
*/
function initializeNewGame(gameStore, playerStore) {
// 重置所有数据
resetGameStorage(gameStore, playerStore)
// 给予初始货币
playerStore.currency.copper = 500 // 500铜币 = 5银币
// 给予初始物品
addItemToInventory(playerStore, 'wooden_stick', 1)
addItemToInventory(playerStore, 'bread', 5)
// 解锁木棍精通技能
unlockSkill(playerStore, 'stick_mastery')
// 添加欢迎日志
gameStore.addLog('欢迎来到荒野求生!', 'info')
gameStore.addLog('你在营地醒来,身边有一些铜币和物资...', 'story')
// 初始化市场价格
refreshMarketPrices(gameStore)
// 触发初始事件
checkAndTriggerEvent(gameStore, playerStore, 'enter', { locationId: 'camp' })
}
/**
* 检查并应用离线收益
* @param {Object} gameStore - 游戏Store
* @param {Object} playerStore - 玩家Store
*/
function checkOfflineEarnings(gameStore, playerStore) {
const now = Date.now()
const offlineSeconds = Math.floor((now - appHideTime) / 1000)
// 离线时间不足1分钟不计算收益
if (offlineSeconds < 60) {
return
}
// 计算离线收益
const earnings = calculateOfflineEarnings(
gameStore,
playerStore,
offlineSeconds
)
// 应用离线收益
if (earnings && (Object.keys(earnings.skillExp || {}).length > 0 || earnings.currency > 0)) {
applyOfflineEarnings(gameStore, playerStore, earnings)
gameStore.addLog(`离线 ${earnings.timeDisplay} 期间获得了收益`, 'info')
}
// 更新隐藏时间,避免重复计算
appHideTime = now
}
/**
* 执行自动保存
* @returns {boolean} 是否保存成功
*/
function performAutoSave() {
const gameStore = useGameStore()
const playerStore = usePlayerStore()
const success = saveGame(gameStore, playerStore)
if (success) {
console.log('Auto-save completed')
} else {
console.error('Auto-save failed')
}
return success
}
/**
* 手动保存游戏暴露给全局
* @returns {boolean}
*/
window.manualSave = function () {
return performAutoSave()
}
/**
* 获取存档信息暴露给全局
* @returns {Object|null}
*/
window.getSaveInfo = function () {
const gameStore = useGameStore()
const playerStore = usePlayerStore()
return {
gameTime: gameStore.gameTime,
playerLevel: playerStore.level.current,
location: playerStore.currentLocation,
hasSave: hasSaveData()
}
}
/**
* 解锁木棍精通技能用于测试
*/
window.unlockStickSkill = function () {
const playerStore = usePlayerStore()
unlockSkill(playerStore, 'stick_mastery')
return 'stick_mastery unlocked'
}
</script>
<style lang="scss">
/* 全局样式 */
@import '@/uni.scss';
page {
background-color: $bg-primary;
color: $text-primary;
font-size: 28rpx;
line-height: 1.6;
}
/* 滚动条样式 */
::-webkit-scrollbar {
width: 8rpx;
}
::-webkit-scrollbar-thumb {
background-color: $bg-tertiary;
border-radius: 4rpx;
}
/* ==================== 过渡动画 ==================== */
/* 淡入淡出 */
.fade-enter-active,
.fade-leave-active {
transition: opacity 0.3s ease;
}
.fade-enter-from,
.fade-leave-to {
opacity: 0;
}
/* 滑动进入 - 从右侧 */
.slide-right-enter-active,
.slide-right-leave-active {
transition: all 0.3s ease;
}
.slide-right-enter-from {
transform: translateX(100%);
opacity: 0;
}
.slide-right-leave-to {
transform: translateX(100%);
opacity: 0;
}
/* 滑动进入 - 从左侧 */
.slide-left-enter-active,
.slide-left-leave-active {
transition: all 0.3s ease;
}
.slide-left-enter-from {
transform: translateX(-100%);
opacity: 0;
}
.slide-left-leave-to {
transform: translateX(-100%);
opacity: 0;
}
/* 滑动进入 - 从下方 */
.slide-up-enter-active,
.slide-up-leave-active {
transition: all 0.3s ease;
}
.slide-up-enter-from {
transform: translateY(100%);
opacity: 0;
}
.slide-up-leave-to {
transform: translateY(100%);
opacity: 0;
}
/* 缩放动画 */
.scale-enter-active,
.scale-leave-active {
transition: all 0.2s ease;
}
.scale-enter-from,
.scale-leave-to {
transform: scale(0.9);
opacity: 0;
}
/* 弹跳动画 */
.bounce-enter-active {
animation: bounce-in 0.4s ease;
}
.bounce-leave-active {
animation: bounce-in 0.3s ease reverse;
}
@keyframes bounce-in {
0% {
transform: scale(0);
opacity: 0;
}
50% {
transform: scale(1.05);
}
100% {
transform: scale(1);
opacity: 1;
}
}
/* 闪烁动画 */
@keyframes flash {
0%, 100% { opacity: 1; }
50% { opacity: 0.5; }
}
.flash {
animation: flash 0.5s ease;
}
/* 脉冲动画 */
@keyframes pulse {
0%, 100% {
transform: scale(1);
opacity: 1;
}
50% {
transform: scale(1.05);
opacity: 0.8;
}
}
.pulse {
animation: pulse 1.5s ease infinite;
}
/* 摇晃动画 */
@keyframes shake {
0%, 100% { transform: translateX(0); }
25% { transform: translateX(-10rpx); }
75% { transform: translateX(10rpx); }
}
.shake {
animation: shake 0.3s ease;
}
/* 旋转加载 */
@keyframes spin {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
.spin {
animation: spin 1s linear infinite;
}
/* 打字机效果 */
@keyframes typewriter {
from { width: 0; }
to { width: 100%; }
}
/* ==================== 工具类 ==================== */
/* 过渡效果 */
.transition-all {
transition: all 0.3s ease;
}
.transition-fast {
transition: all 0.15s ease;
}
.transition-slow {
transition: all 0.5s ease;
}
/* 悬停效果 */
.hover-scale {
transition: transform 0.2s ease;
}
.hover-scale:active {
transform: scale(0.95);
}
.hover-bright {
transition: filter 0.2s ease;
}
.hover-bright:active {
filter: brightness(1.2);
}
</style>