画中游 WIM 开发日记(一) 我到底要开发的是什么样的软件及其上架鸿蒙商城经历
我想做一款不是“照片浏览器”也不是“传统相册”的产品:它把照片变成可进入的时空副本,在世界地图上作为入口,让用户像玩 RPG 一样“操控自己”的小人走进过去的场景。第一阶段以 Web 为基础、先做 2D 快速成型,再逐步演进为伪 3D 俯视角和 XR 沉浸式体验。本文说明开发初衷、交互/心理学逻辑、技术选型理由、实现路线与首个可运行的前端示例代码(Ionic + Tailwind + Phaser
如果有什么意见和建议,欢迎支招,忙碌两个月现在成绩很失望,下次应该加快迭代速度了
因为前期为了接入AI自动制作场景,浪费一个多月,这是需要改进的,核心功能一定要精简和快速上线测试,不行就得下一个或者等等思考成熟
一、为什么要做「画中游」?
我们每天拍下太多照片,但照片本身是静止的、二维的和被动的。十年后,物理世界、街景、商店、路标几乎全部变样:一切都在更新换代。现在只有两种“回到过去”的方式:翻看照片或回忆。两者都有极限——照片只能看,无法“走进去”;回忆随着时间变得模糊、片段化、并常常不真实。
我想要的不是更漂亮的照片浏览器,而是一种新的“回访方式”:
- 把一张照片 快速构建成一个类游戏场景的副本(保留关键视觉元素与空间关系);
- 在“世界地图”上把每张照片的场景当作一个入口,用户可以按时间轴或地理位置随时进入不同时间点的副本;
- 使用 RPG 的控制范式(移动、观察、互动),当用户操控小人时,会把部分意识投射到小人身上,从而产生强烈的代入感;
- 在场景中逐步加入听觉、触觉(通过设备振动/外设)、和视觉的层次化渲染,形成“跨时空”的沉浸式体验。
心理学上,人类对“控制感”与“代理感(agency)”非常敏感。把“可控的对象”作为意识延伸,会让用户把目标对象视作自己一部分。我们用操控小人的方式,降低进入时空的心理门槛:不是“观看过去”,而是“在过去中行动”。
- 我不是在“还原过去”——而是在提供一种“可控的再访体验”,让记忆可以被操控、被延展、被感知投射。
- 先把业务流程打通(上传照片 → 自动生成场景副本 → 在地图上生成入口 → 进入并以 RPG 控制游玩),表现层用迭代的方式逐步升级。
- Web 技术(Ionic + Angular + Tailwind + Phaser)在初期能快速验证交互模型、覆盖平台并兼容 AI/按需加载,利于大规模空间与大量副本的扩展。
- 交互设计核心:完全控制 → 意识投射 → 感官叠加 → 沉浸式跨时空体验。
二、产品定位与首要目标
短期目标(验证层)
- 实现从照片到可进入副本的流水线:上传 → 解析 → 场景构建 → 地图入口生成 → 进入游玩。
- 用二维(2D)表现,节省成本并快速迭代交互模型。
- 验证 RPG 控制带来的意识投射与沉浸感(用户研究 / 定性访谈)。
中期目标(进阶体验)
- 将 2D 升级为伪 3D 俯视角(增强深度感与自由度)。
- 引入基于 AI 的场景扩展:自动补齐视野外细节、生成动态事件(比如一段声音、一段光影)。
- 支持简单的多人同步或分享(在同一时间点互访)。
长期目标(沉浸层)
- 支持 XR(AR/VR)体验,真正做到“进入记忆空间”。
- 连接更多外设(触觉手套、空间音频、力反馈)以增强跨感官体验。
- 建立开放的时空地图生态,让用户互相创建/交易“记忆副本”。
三、为什么先做 Web+鸿蒙?为什么选 Ionic + Tailwind + Phaser + Angular?
选择 Web 的理由
- 跨平台与低门槛:一次开发可覆盖桌面、移动、平板,便于快速收集早期用户反馈。
- 按需加载与分片:大量的时空副本意味着海量资源,Web 的模块化与懒加载非常适合按需拉取场景资源。
- AI 友好:Web 便于接入云端或边缘的 AI 服务,用于照片语义解析、场景补全、自动物件生成等。
- 迭代速度快:前端开发与热更新效率高,便于快速验证交互与 UX 假设。
选型理由
- Ionic:移动优先的 UI 套件,便于做 Hybrid App 与 PWA,快速打通手机用户的触控体验与后台服务。
- Angular:结构化、注入式服务与模块化支持复杂业务流程、路由管理、状态管理和依赖注入,便于把“照片→场景→地图→进入”这类复杂流程用服务化方式串联。
- Tailwind:原子化 CSS,快速搭建响应式 UI,同时便于配合 Ionic 做定制化样式。
- Phaser.js:成熟的 2D 游戏框架,轻量、性能好,方便实现 RPG 控制逻辑、地图层和交互对象(NPC/物件)的事件系统。
组合优势:Ionic+Angular 负责应用框架和页面流,Tailwind 负责样式与快速迭代,Phaser 负责游戏化场景渲染与交互逻辑。这样的分工让业务层和表现层解耦,同时保证可扩展性。
四、核心体验设计:从“控制”到“投射”
-
完全控制(Full agency)
- RPG 模式提供明确的输入映射(键盘/触屏虚拟摇杆/手柄),用户能精准控制小人的位置与朝向。
-
意识投射(Projection)
- 当用户操作到一定熟练度,会把小人当作“自我延伸”。这一点来自长期的游戏交互与日常工具使用经验(鼠标、触控板等)。
-
感官叠加(Sensory layering)
- 视觉(照片基础 + 渲染优化)
- 听觉(原始环境音、AI 增强的背景声)
- 触觉(移动设备振动、外设反馈)
- 通过分层逐步增强沉浸感,避免一开始就把体验做得太重导致技术风险高。
-
记忆的可控性
- 用户可以在场景中添加注释、重置视角、播放“过去的对话”(如果有录音)或标注事件,使记忆变成可改写/可拓展的“活体资料”。
五、前端示例
下面示例展示了Ionic + Angular + Tailwind + Phaser 的基础整合思路:一个 Ionic 页面嵌入 Phaser Canvas,上传图片后触发一个简单的“贴图为背景 + RPG 控制”的 Phaser Scene。注意:这只是演示最小可运行逻辑,实际项目需要把图片切片、碰撞、热点、按需加载与 AI 场景构建接入后端。
文件结构示意(简化)
src/
app/
pages/
world-entry/
world-entry.page.ts
world-entry.page.html
world-entry.page.scss
services/
photo-scene.service.ts
world-entry.page.html
<ion-header>
<ion-toolbar>
<ion-title>画中游 - 快速 Demo</ion-title>
</ion-toolbar>
</ion-header>
<ion-content class="p-4">
<div class="flex gap-2 mb-4">
<input type="file" (change)="onFile($event)" class="hidden" #fileInput />
<button class="btn" (click)="fileInput.click()">上传照片生成场景</button>
<button class="btn-ghost" (click)="enterDemo()">进入演示场景</button>
</div>
<div id="game-container" class="w-full h-[70vh] border rounded-lg overflow-hidden"></div>
</ion-content>
world-entry.page.ts
import { Component, ElementRef, ViewChild, AfterViewInit } from '@angular/core';
import Phaser from 'phaser';
import { PhotoSceneService } from '../../services/photo-scene.service';
@Component({
selector: 'app-world-entry',
templateUrl: './world-entry.page.html',
styleUrls: ['./world-entry.page.scss'],
})
export class WorldEntryPage implements AfterViewInit {
@ViewChild('gameContainer', { static: false }) gameContainer!: ElementRef;
phaserGame?: Phaser.Game;
config: Phaser.Types.Core.GameConfig;
constructor(private photoScene: PhotoSceneService) {
this.config = {
type: Phaser.AUTO,
parent: 'game-container',
width: window.innerWidth,
height: Math.floor(window.innerHeight * 0.7),
scene: [DemoScene],
physics: {
default: 'arcade',
arcade: { debug: false }
}
};
}
ngAfterViewInit() {
this.phaserGame = new Phaser.Game(this.config);
}
onFile(event: Event) {
const input = event.target as HTMLInputElement;
if (!input.files || !input.files[0]) return;
const file = input.files[0];
this.photoScene.uploadAndBuild(file).then(sceneInfo => {
// 简单示例:当后端返回已处理的贴图 URL,发送给 Phaser Scene 更新背景
(this.phaserGame?.scene.getScene('DemoScene') as any).setBackground(sceneInfo.previewUrl);
});
}
enterDemo() {
(this.phaserGame?.scene.getScene('DemoScene') as any).startControl();
}
}
/** 简单 Phaser Scene(演示用) */
class DemoScene extends Phaser.Scene {
player!: Phaser.Types.Physics.Arcade.SpriteWithDynamicBody;
cursors!: Phaser.Types.Input.Keyboard.CursorKeys;
bg?: Phaser.GameObjects.Image;
constructor() { super({ key: 'DemoScene' }); }
preload() {
// 默认背景,上传后可替换
this.load.image('defaultBg', 'assets/default_background.jpg');
this.load.spritesheet('player', 'assets/player.png', { frameWidth: 32, frameHeight: 48 });
}
create() {
this.bg = this.add.image(0, 0, 'defaultBg').setOrigin(0, 0).setDisplaySize(this.scale.width, this.scale.height);
this.player = this.physics.add.sprite(100, 100, 'player');
this.player.setCollideWorldBounds(true);
this.cursors = this.input.keyboard.createCursorKeys();
}
update() {
const speed = 150;
this.player.setVelocity(0);
if (this.cursors.left?.isDown) this.player.setVelocityX(-speed);
if (this.cursors.right?.isDown) this.player.setVelocityX(speed);
if (this.cursors.up?.isDown) this.player.setVelocityY(-speed);
if (this.cursors.down?.isDown) this.player.setVelocityY(speed);
}
setBackground(url: string) {
// 简化:如果接入远程 URL,需要处理跨域或先下载到 assets
this.textures.remove('uploadedBg');
this.load.image('uploadedBg', url);
this.load.once('complete', () => {
this.bg?.setTexture('uploadedBg');
// 这里可以触发额外的场景构建(碰撞图 / 热点)
});
this.load.start();
}
startControl() {
// 这里可以触发一些 UI 提示,提示用户控制方式
console.log('控制已启用');
}
}
photo-scene.service.ts(示意)
import { Injectable } from '@angular/core';
@Injectable({ providedIn: 'root' })
export class PhotoSceneService {
async uploadAndBuild(file: File): Promise<{ previewUrl: string }> {
// 实际项目:上传到后端 -> 后端用 AI/规则生成场景资源 -> 返回 previewUrl / resource package
// 这里用本地 URL 做示范
const previewUrl = URL.createObjectURL(file);
// 模拟后端处理延时
await new Promise(res => setTimeout(res, 500));
return { previewUrl };
}
}
说明:
- 上面示例极简,仅用于展示如何把 Phaser 嵌入到 Ionic/Angular 页面,如何把用户上传的照片作为场景背景快速替换,以及如何以 RPG 控制为基础搭建输入映射。实际场景生成需要后端支持(语义分析、图像补全、切片打包与碰撞数据生成)。
六、实现优先级与迭代路径
第一阶段(MVP) — 业务流优先
- 完成:上传 → 简单的图像贴图场景 → 地图入口(时间轴/位置)→ RPG 基本控制
- 验证指标:用户能否将注意力投射到小人并完成简单导航;上传到进入的平均时延;首日留存/次留。
第一阶段基本完成
兼容鸿蒙平台修改了6次,包括动态夜间模式、定位、注册、地图展示问题等
其实12月初就就绪,但后面删除了功能,做了较大调整,初期设计问题也是影响大
目前还留下剪切板的兼容性,后续与操作盘一起更新,感觉点击目标运动的方式,不如类似王者的轮盘控制“顺心"
目前的下载体验数量太低,但因为在搬家期间,暂时没法补充更多内容,只能等稳定下来
第二阶段(体验升级)
- 引入 AI 场景补全:视野之外的区域自动填充;语义标注(桌子、门、人物)。
- 增强交互:热点(点击对象弹注释)、音频层(还原当时环境声或生成逼真氛围)。
- 引入伪 3D:增加多层地面、俯视角度、视差滚动。
第三阶段(沉浸化)
- XR 支持:基于 WebXR 的 AR/VR 支持(先做 AR 叠加再做全 VR)。
- 外设集成:触觉、空间音频、体感输入。
- 多人/社交功能:共同访问与同步事件回放。
七、风险与应对
- 场景自动构建精度不足:早期用“弱 AI + 规则”策略,先保证可用性(可交互热点少但可靠),后期再用深度模型做细化。
- 资源量大、加载慢:采用按需加载、分片与缓存机制,并优先生成低分辨率的“预览”用于快速进入。
- 隐私与许可问题:照片里的第三方(人物/地点)涉及隐私或肖像权,需在上传流程中做明确提示与同意机制,并提供私有/公开选项。
- 沉浸体验成本高:分阶段投入,先以低成本的感官增强(声效、轻触)替代昂贵外设。
八、现状和下一步任务
现状就是数据很惨淡,免费的鸿蒙平台也是个位数,我感觉是介绍/类型、传达出现了问题
下一步不计划
-
挖掘价值表达 - 介绍和副标题
-
适当的宣传
我发现发在抖音,一下子就限流了,一小时播放0,还不如随便发几个字的,感觉应该是发现是营销,所以需要找找应对策略
结语
画中游 WIM 不是在造一个更漂亮的相册,而是在做一个记忆的可进入地图,把“过去”变成“可控制的场所”。我相信“控制感”会帮助用户把部分意识投射回过去,而这个过程本身就是一种疗愈、复盘或创作。技术上,我们用 Web 的方式快速验证、用游戏化的交互降低学习成本,并用 AI 做铺垫支撑大规模的空间构建。接下来的目标是把业务流程打通,尽快拿出能让人“走进去”的第一版,并通过真实用户的反馈不断迭代表现。
更多推荐





所有评论(0)