|
@@ -1,175 +1,83 @@
|
|
// game.page.ts
|
|
// game.page.ts
|
|
-import { Component, ViewChild, ElementRef, AfterViewInit, HostListener } from '@angular/core';
|
|
|
|
|
|
+import { Component, ViewChild, ElementRef, AfterViewInit, HostListener , OnInit} from '@angular/core';
|
|
import * as PIXI from 'pixi.js';
|
|
import * as PIXI from 'pixi.js';
|
|
import { Howl, Howler } from 'howler';
|
|
import { Howl, Howler } from 'howler';
|
|
import { Haptics, ImpactStyle } from '@capacitor/haptics';
|
|
import { Haptics, ImpactStyle } from '@capacitor/haptics';
|
|
-
|
|
|
|
|
|
+import { ModalController } from '@ionic/angular';
|
|
@Component({
|
|
@Component({
|
|
selector: 'app-game',
|
|
selector: 'app-game',
|
|
templateUrl: 'game.page.html',
|
|
templateUrl: 'game.page.html',
|
|
styleUrls: ['game.page.scss'],
|
|
styleUrls: ['game.page.scss'],
|
|
standalone: false,
|
|
standalone: false,
|
|
})
|
|
})
|
|
-export class GamePage implements AfterViewInit {
|
|
|
|
-
|
|
|
|
- @ViewChild('gameCanvas') canvasRef!: ElementRef;
|
|
|
|
- @ViewChild('gameCanvasContainer') containerRef!: ElementRef;
|
|
|
|
-
|
|
|
|
- // 游戏状态
|
|
|
|
- currentGame: 'bubble' | 'sand' = 'bubble';
|
|
|
|
- score = 0;
|
|
|
|
- isMuted = false;
|
|
|
|
- showAchievement = false;
|
|
|
|
- achievementText = '';
|
|
|
|
- achievementIcon = '';
|
|
|
|
-
|
|
|
|
- // PIXI实例
|
|
|
|
- private app!: PIXI.Application;
|
|
|
|
- private bubbles: PIXI.Sprite[] = [];
|
|
|
|
- private sandTexture!: PIXI.RenderTexture;
|
|
|
|
-
|
|
|
|
- ngAfterViewInit() {
|
|
|
|
- this.initPixi();
|
|
|
|
- this.loadAssets();
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- private initPixi(){
|
|
|
|
|
|
+export class GamePage implements OnInit {
|
|
|
|
|
|
- }
|
|
|
|
|
|
+ currentMood = {
|
|
|
|
+ score: 0.6,
|
|
|
|
+ description: "轻度焦虑",
|
|
|
|
+ tags: ["工作压力", "时间紧迫"]
|
|
|
|
+ };
|
|
|
|
|
|
- private loadAssets(){
|
|
|
|
- PIXI.Assets.load([
|
|
|
|
- { alias: 'bubble', src: 'assets/images/bubble.png' },
|
|
|
|
- { alias: 'brush', src: 'assets/images/brush.png' }
|
|
|
|
- ]).then(() => {
|
|
|
|
- //this.initBubbleGame();
|
|
|
|
- //this.initSandGame();
|
|
|
|
- this.switchGameMode();
|
|
|
|
- });
|
|
|
|
|
|
+ demoBubbles = Array(8).fill(0);
|
|
|
|
+ unlockedAchievements = {
|
|
|
|
+ bubble: true,
|
|
|
|
+ sand: false,
|
|
|
|
+ raindrop:false,
|
|
|
|
+ constellation:false
|
|
|
|
+ };
|
|
|
|
+ showRecommendation = true;
|
|
|
|
+ recommendedGame = "禅意沙画";
|
|
|
|
+ constructor(private modalCtrl: ModalController) {}
|
|
|
|
+ ngOnInit() {
|
|
|
|
+ // 从服务获取最新情绪数据和游戏解锁状态
|
|
}
|
|
}
|
|
-
|
|
|
|
- /** 切换游戏模式 */
|
|
|
|
- switchGameMode() {
|
|
|
|
- this.app.stage.removeChildren();
|
|
|
|
- if (this.currentGame === 'bubble') {
|
|
|
|
- this.app.stage.addChild(...this.bubbles);
|
|
|
|
|
|
+ getMoodGradient() {
|
|
|
|
+ const score = this.currentMood.score;
|
|
|
|
+ if (score > 0.7) {
|
|
|
|
+ return 'linear-gradient(135deg, #a8edea 0%, #fed6e3 100%)';
|
|
|
|
+ } else if (score > 0.4) {
|
|
|
|
+ return 'linear-gradient(135deg, #f6f7f9 0%, #e9ecef 100%)';
|
|
} else {
|
|
} else {
|
|
- this.initSandDrawing();
|
|
|
|
|
|
+ return 'linear-gradient(135deg, #ff9a9e 0%, #fad0c4 100%)';
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- /** 沙画绘制逻辑 */
|
|
|
|
- private initSandDrawing() {
|
|
|
|
- const brush = PIXI.Sprite.from('brush');
|
|
|
|
- brush.anchor.set(0.5);
|
|
|
|
- brush.visible = false;
|
|
|
|
-
|
|
|
|
- const sandGraphics = new PIXI.Graphics();
|
|
|
|
- let drawing = false;
|
|
|
|
- let lastPoint: PIXI.Point | null = null;
|
|
|
|
-
|
|
|
|
- // 触摸/鼠标事件
|
|
|
|
- this.app.stage.eventMode = 'static';
|
|
|
|
- this.app.stage.hitArea = this.app.screen;
|
|
|
|
- this.app.stage
|
|
|
|
- .on('pointerdown', (e: PIXI.FederatedPointerEvent) => {
|
|
|
|
- drawing = true;
|
|
|
|
- lastPoint = e.global.clone();
|
|
|
|
- brush.position.copyFrom(e.global);
|
|
|
|
- brush.visible = true;
|
|
|
|
- })
|
|
|
|
- .on('pointermove', (e: PIXI.FederatedPointerEvent) => {
|
|
|
|
- if (!drawing) return;
|
|
|
|
-
|
|
|
|
- // 绘制沙粒轨迹
|
|
|
|
- //sandGraphics.lineStyle({ width: 8, color: 0xf4d03f, alpha: 0.7 });
|
|
|
|
- if (lastPoint) {
|
|
|
|
- sandGraphics.moveTo(lastPoint.x, lastPoint.y);
|
|
|
|
- sandGraphics.lineTo(e.global.x, e.global.y);
|
|
|
|
|
|
+ async openGame(gameType: string) {
|
|
|
|
+ let component;
|
|
|
|
+ switch(gameType) {
|
|
|
|
+ case 'bubble':
|
|
|
|
+ //component = BubbleGamePage;
|
|
|
|
+ break;
|
|
|
|
+ case 'sand':
|
|
|
|
+ if (!this.unlockedAchievements.sand) {
|
|
|
|
+ // 显示解锁条件提示
|
|
|
|
+ return;
|
|
}
|
|
}
|
|
- lastPoint = e.global.clone();
|
|
|
|
-
|
|
|
|
- // 更新笔刷位置
|
|
|
|
- brush.position.copyFrom(e.global);
|
|
|
|
- this.playSound('draw');
|
|
|
|
- })
|
|
|
|
- .on('pointerup', () => {
|
|
|
|
- drawing = false;
|
|
|
|
- brush.visible = false;
|
|
|
|
- lastPoint = null;
|
|
|
|
- });
|
|
|
|
-
|
|
|
|
- this.app.stage.addChild(sandGraphics, brush);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- // 音效
|
|
|
|
- private sounds = {
|
|
|
|
- pop: new Howl({ src: ['assets/sfx/pop.mp3'] }),
|
|
|
|
- draw: new Howl({ src: ['assets/sfx/sand-draw.mp3'] }),
|
|
|
|
- unlock: new Howl({ src: ['assets/sfx/achievement.mp3'] })
|
|
|
|
- };
|
|
|
|
-
|
|
|
|
- /** 播放音效 */
|
|
|
|
- private playSound(type: keyof typeof this.sounds) {
|
|
|
|
- if (!this.isMuted) {
|
|
|
|
- this.sounds[type].play();
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /**
|
|
|
|
- * 切换声音状态
|
|
|
|
- * 功能说明:
|
|
|
|
- * 1. 切换全局静音状态
|
|
|
|
- * 2. 控制所有音效实例
|
|
|
|
- * 3. 提供触觉反馈
|
|
|
|
- * 4. 保存状态到本地存储
|
|
|
|
- */
|
|
|
|
- async toggleSound() {
|
|
|
|
- try {
|
|
|
|
- // 切换静音状态
|
|
|
|
- this.isMuted = !this.isMuted;
|
|
|
|
-
|
|
|
|
- // 触觉反馈(需要Capacitor支持)
|
|
|
|
- await Haptics.impact({ style: ImpactStyle.Light });
|
|
|
|
-
|
|
|
|
- // 控制全局音频
|
|
|
|
- Howler.mute(this.isMuted);
|
|
|
|
-
|
|
|
|
- // 同步控制单独音效实例(可选)
|
|
|
|
- Object.values(this.sounds).forEach(sound => {
|
|
|
|
- sound.mute(this.isMuted);
|
|
|
|
- });
|
|
|
|
-
|
|
|
|
- // 保存状态到本地存储
|
|
|
|
- localStorage.setItem('gameMuteState', JSON.stringify(this.isMuted));
|
|
|
|
-
|
|
|
|
- // 显示状态提示
|
|
|
|
- this.showSoundStateToast();
|
|
|
|
- } catch (error) {
|
|
|
|
- console.error('切换声音时出错:', error);
|
|
|
|
|
|
+ //component = SandGamePage;
|
|
|
|
+ break;
|
|
|
|
+ case 'raindrop':
|
|
|
|
+ if (!this.unlockedAchievements.raindrop) {
|
|
|
|
+ // 显示解锁条件提示
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ //component = SandGamePage;
|
|
|
|
+ break;
|
|
|
|
+ case 'constellation':
|
|
|
|
+ if (!this.unlockedAchievements.constellation) {
|
|
|
|
+ // 显示解锁条件提示
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ //component = SandGamePage;
|
|
|
|
+ break;
|
|
|
|
+ default:
|
|
|
|
+ return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
-
|
|
|
|
- /** 显示声音状态提示 */
|
|
|
|
- private showSoundStateToast() {
|
|
|
|
- this.achievementText = this.isMuted ? '静音模式已开启' : '声音模式已开启';
|
|
|
|
- this.achievementIcon = this.isMuted ? 'volume-mute' : 'volume-high';
|
|
|
|
- this.showAchievement = true;
|
|
|
|
-
|
|
|
|
- setTimeout(() => {
|
|
|
|
- this.showAchievement = false;
|
|
|
|
- }, 1500);
|
|
|
|
|
|
+ openAchievements() {
|
|
|
|
+ // 打开成就页面
|
|
}
|
|
}
|
|
|
|
|
|
- /** 初始化时读取静音状态 */
|
|
|
|
- private initSoundState() {
|
|
|
|
- const savedState = localStorage.getItem('gameMuteState');
|
|
|
|
- if (savedState) {
|
|
|
|
- this.isMuted = JSON.parse(savedState);
|
|
|
|
- Howler.mute(this.isMuted);
|
|
|
|
- }
|
|
|
|
|
|
+ dismissRecommendation() {
|
|
|
|
+ this.showRecommendation = false;
|
|
}
|
|
}
|
|
-
|
|
|
|
- constructor() {}
|
|
|
|
-
|
|
|
|
}
|
|
}
|