2026-03-03 16:57:49 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 星域故事汇 - 主逻辑控制器
|
|
|
|
|
|
*/
|
|
|
|
|
|
import SceneManager from './scenes/SceneManager';
|
|
|
|
|
|
import UserManager from './data/UserManager';
|
|
|
|
|
|
import StoryManager from './data/StoryManager';
|
|
|
|
|
|
import AudioManager from './data/AudioManager';
|
|
|
|
|
|
|
|
|
|
|
|
export default class Main {
|
|
|
|
|
|
constructor() {
|
|
|
|
|
|
// 获取画布和上下文
|
|
|
|
|
|
this.canvas = GameGlobal.canvas;
|
|
|
|
|
|
this.ctx = this.canvas.getContext('2d');
|
|
|
|
|
|
this.screenWidth = GameGlobal.screenWidth;
|
|
|
|
|
|
this.screenHeight = GameGlobal.screenHeight;
|
|
|
|
|
|
this.dpr = GameGlobal.devicePixelRatio;
|
|
|
|
|
|
|
|
|
|
|
|
// 缩放上下文以适配设备像素比
|
|
|
|
|
|
this.ctx.scale(this.dpr, this.dpr);
|
|
|
|
|
|
|
|
|
|
|
|
// 初始化管理器
|
|
|
|
|
|
this.userManager = new UserManager();
|
|
|
|
|
|
this.storyManager = new StoryManager();
|
|
|
|
|
|
this.audioManager = new AudioManager();
|
|
|
|
|
|
this.sceneManager = new SceneManager(this);
|
|
|
|
|
|
|
|
|
|
|
|
// 初始化游戏
|
|
|
|
|
|
this.init();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
async init() {
|
|
|
|
|
|
// 先启动游戏循环,确保能渲染加载界面
|
|
|
|
|
|
this.bindEvents();
|
|
|
|
|
|
this.loop();
|
|
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
|
// 显示加载界面
|
|
|
|
|
|
this.showLoading('正在加载...');
|
|
|
|
|
|
console.log('[Main] 开始初始化...');
|
|
|
|
|
|
|
|
|
|
|
|
// 用户初始化(失败不阻塞)
|
|
|
|
|
|
console.log('[Main] 初始化用户...');
|
|
|
|
|
|
await this.userManager.init().catch(e => {
|
|
|
|
|
|
console.warn('[Main] 用户初始化失败,使用游客模式:', e);
|
|
|
|
|
|
});
|
|
|
|
|
|
console.log('[Main] 用户初始化完成');
|
|
|
|
|
|
|
|
|
|
|
|
// 加载故事列表
|
|
|
|
|
|
console.log('[Main] 加载故事列表...');
|
|
|
|
|
|
await this.storyManager.loadStoryList();
|
|
|
|
|
|
console.log('[Main] 故事列表加载完成,共', this.storyManager.storyList.length, '个故事');
|
|
|
|
|
|
|
|
|
|
|
|
// 隐藏加载界面
|
|
|
|
|
|
this.hideLoading();
|
|
|
|
|
|
|
|
|
|
|
|
// 进入首页
|
|
|
|
|
|
this.sceneManager.switchScene('home');
|
|
|
|
|
|
console.log('[Main] 初始化完成,进入首页');
|
|
|
|
|
|
|
|
|
|
|
|
// 设置分享
|
|
|
|
|
|
this.setupShare();
|
2026-03-09 14:15:00 +08:00
|
|
|
|
|
|
|
|
|
|
// 启动草稿检查(仅登录用户)
|
|
|
|
|
|
if (this.userManager.isLoggedIn) {
|
|
|
|
|
|
this.startDraftChecker();
|
|
|
|
|
|
}
|
2026-03-03 16:57:49 +08:00
|
|
|
|
} catch (error) {
|
|
|
|
|
|
console.error('[Main] 初始化失败:', error);
|
|
|
|
|
|
this.hideLoading();
|
|
|
|
|
|
this.showError('初始化失败,请重试');
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 显示加载
|
|
|
|
|
|
showLoading(text) {
|
|
|
|
|
|
this.isLoading = true;
|
|
|
|
|
|
this.loadingText = text;
|
|
|
|
|
|
this.render();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 隐藏加载
|
|
|
|
|
|
hideLoading() {
|
|
|
|
|
|
this.isLoading = false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 显示错误
|
|
|
|
|
|
showError(text) {
|
|
|
|
|
|
wx.showToast({
|
|
|
|
|
|
title: text,
|
|
|
|
|
|
icon: 'none',
|
|
|
|
|
|
duration: 2000
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 绑定事件
|
|
|
|
|
|
bindEvents() {
|
|
|
|
|
|
// 触摸开始
|
|
|
|
|
|
wx.onTouchStart((e) => {
|
|
|
|
|
|
if (this.sceneManager.currentScene) {
|
|
|
|
|
|
this.sceneManager.currentScene.onTouchStart(e);
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
// 触摸移动
|
|
|
|
|
|
wx.onTouchMove((e) => {
|
|
|
|
|
|
if (this.sceneManager.currentScene) {
|
|
|
|
|
|
this.sceneManager.currentScene.onTouchMove(e);
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
// 触摸结束
|
|
|
|
|
|
wx.onTouchEnd((e) => {
|
|
|
|
|
|
if (this.sceneManager.currentScene) {
|
|
|
|
|
|
this.sceneManager.currentScene.onTouchEnd(e);
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-09 14:15:00 +08:00
|
|
|
|
// 启动草稿检查定时器
|
|
|
|
|
|
startDraftChecker() {
|
|
|
|
|
|
// 避免重复启动
|
|
|
|
|
|
if (this.draftCheckTimer) return;
|
|
|
|
|
|
|
|
|
|
|
|
console.log('[Main] 启动草稿检查定时器');
|
|
|
|
|
|
|
|
|
|
|
|
// 每30秒检查一次
|
|
|
|
|
|
this.draftCheckTimer = setInterval(async () => {
|
|
|
|
|
|
try {
|
|
|
|
|
|
if (!this.userManager.isLoggedIn) return;
|
|
|
|
|
|
|
|
|
|
|
|
const result = await this.storyManager.checkNewDrafts(this.userManager.userId);
|
|
|
|
|
|
|
|
|
|
|
|
if (result && result.hasNew && result.count > 0) {
|
|
|
|
|
|
console.log('[Main] 检测到新草稿:', result.count);
|
|
|
|
|
|
|
|
|
|
|
|
// 先标记为已读,避免重复弹窗
|
|
|
|
|
|
await this.storyManager.markAllDraftsRead(this.userManager.userId);
|
|
|
|
|
|
|
|
|
|
|
|
// 弹窗通知
|
|
|
|
|
|
wx.showModal({
|
|
|
|
|
|
title: 'AI改写完成',
|
|
|
|
|
|
content: `您有 ${result.count} 个新的AI改写已完成,是否前往查看?`,
|
|
|
|
|
|
confirmText: '查看',
|
|
|
|
|
|
cancelText: '稍后',
|
|
|
|
|
|
success: (res) => {
|
|
|
|
|
|
if (res.confirm) {
|
|
|
|
|
|
// 跳转到个人中心的草稿箱 tab
|
|
|
|
|
|
this.sceneManager.switchScene('profile', { tab: 1 });
|
|
|
|
|
|
} else {
|
|
|
|
|
|
// 点击稍后,如果当前在个人中心页面则刷新草稿列表
|
|
|
|
|
|
const currentScene = this.sceneManager.currentScene;
|
|
|
|
|
|
if (currentScene && currentScene.refreshDrafts) {
|
|
|
|
|
|
currentScene.refreshDrafts();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
} catch (e) {
|
|
|
|
|
|
console.warn('[Main] 草稿检查失败:', e);
|
|
|
|
|
|
}
|
|
|
|
|
|
}, 30000);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 停止草稿检查定时器
|
|
|
|
|
|
stopDraftChecker() {
|
|
|
|
|
|
if (this.draftCheckTimer) {
|
|
|
|
|
|
clearInterval(this.draftCheckTimer);
|
|
|
|
|
|
this.draftCheckTimer = null;
|
|
|
|
|
|
console.log('[Main] 停止草稿检查定时器');
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-03 16:57:49 +08:00
|
|
|
|
// 设置分享
|
|
|
|
|
|
setupShare() {
|
|
|
|
|
|
wx.showShareMenu({
|
|
|
|
|
|
withShareTicket: true,
|
|
|
|
|
|
menus: ['shareAppMessage', 'shareTimeline']
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
wx.onShareAppMessage(() => {
|
|
|
|
|
|
return {
|
|
|
|
|
|
title: '星域故事汇 - 每个选择都是一个新世界',
|
|
|
|
|
|
imageUrl: '',
|
|
|
|
|
|
query: ''
|
|
|
|
|
|
};
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
wx.onShareTimeline(() => {
|
|
|
|
|
|
return {
|
|
|
|
|
|
title: '星域故事汇 - 沉浸式互动故事体验',
|
|
|
|
|
|
query: ''
|
|
|
|
|
|
};
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 游戏循环
|
|
|
|
|
|
loop() {
|
|
|
|
|
|
this.update();
|
|
|
|
|
|
this.render();
|
|
|
|
|
|
requestAnimationFrame(() => this.loop());
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 更新逻辑
|
|
|
|
|
|
update() {
|
|
|
|
|
|
if (this.sceneManager.currentScene) {
|
|
|
|
|
|
this.sceneManager.currentScene.update();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 渲染
|
|
|
|
|
|
render() {
|
|
|
|
|
|
// 清屏
|
|
|
|
|
|
this.ctx.clearRect(0, 0, this.screenWidth, this.screenHeight);
|
|
|
|
|
|
|
|
|
|
|
|
// 绘制背景
|
|
|
|
|
|
this.ctx.fillStyle = '#1a1a2e';
|
|
|
|
|
|
this.ctx.fillRect(0, 0, this.screenWidth, this.screenHeight);
|
|
|
|
|
|
|
|
|
|
|
|
// 渲染当前场景
|
|
|
|
|
|
if (this.sceneManager.currentScene) {
|
|
|
|
|
|
this.sceneManager.currentScene.render(this.ctx);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 渲染加载界面
|
|
|
|
|
|
if (this.isLoading) {
|
|
|
|
|
|
this.renderLoading();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 渲染加载界面
|
|
|
|
|
|
renderLoading() {
|
|
|
|
|
|
// 半透明遮罩
|
|
|
|
|
|
this.ctx.fillStyle = 'rgba(0, 0, 0, 0.7)';
|
|
|
|
|
|
this.ctx.fillRect(0, 0, this.screenWidth, this.screenHeight);
|
|
|
|
|
|
|
|
|
|
|
|
// 加载文字
|
|
|
|
|
|
this.ctx.fillStyle = '#ffffff';
|
|
|
|
|
|
this.ctx.font = '18px sans-serif';
|
|
|
|
|
|
this.ctx.textAlign = 'center';
|
|
|
|
|
|
this.ctx.fillText(this.loadingText || '加载中...', this.screenWidth / 2, this.screenHeight / 2);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|