当前位置: 首页 > news >正文

山东大学软件学院创新实训——个人博客(七)

日期:2026 年 5 月 24 日
项目:绘画 AI 博弈小游戏 —— 人机对抗绘画猜词与心理解读系统

一、工作概述

本周完成两大核心前端功能:

  1. 限定画具模式:在“经典模式”和“反向猜词模式”之外,新增第三种玩法。画家只能使用预设几何图形(圆形、矩形、直线、三角形)进行绘画,拖拽生成虚线预览,松手后实线确认。该模式降低了自由绘画的门槛,并为心理分析提供更规整的笔触数据。

  2. 画风档案展示页:为每位玩家生成独立的“画风档案”个人主页,展示其历史绘画行为数据的统计指标、风格标签、画风描述文字以及演变趋势图,形成可视化的个人艺术风格画像。

这两个功能进一步丰富了游戏玩法和数据分析维度。

二、限定画具模式

2.1 模式设计目标

在限定画具模式下,画家不能使用自由画笔,只能从以下四种几何工具中选择一种:

工具说明
圆形从起点到终点绘制椭圆(长宽由拖拽矩形决定)
矩形从起点到终点绘制矩形
直线从起点到终点绘制线段
三角形以起点横坐标的中点为顶点,底边为起点到终点的宽度

所有图形仅使用黑色(画笔颜色固定),粗细可在几何工具栏中选择(细/中/粗)。该模式便于分析玩家的构图偏好、空间感知和规则遵从度。

2.2 几何图形绘制引擎(canvas.js)
2.2.1 模式切换

DrawingBoard 类新增 setRestrictedMode(tools) 和 setFreeMode() 方法:

setRestrictedMode(tools) { this.restrictedMode = true; this.allowedTools = tools || ['circle', 'rectangle', 'line', 'triangle']; this.currentGeoTool = this.allowedTools[0]; this._unbindFreeDrawEvents(); // 移除原有自由绘制事件 this._bindGeoEvents(); // 绑定几何绘制事件 } setFreeMode() { this.restrictedMode = false; this._unbindGeoEvents(); this._bindEvents(); // 恢复自由绘制事件 }

2.2.2 几何图形交互(拖拽预览+确认)

_bindGeoEvents() 监听鼠标/触摸事件,实现橡皮筋效果:

onDown:记录起点,保存画布快照。

onMove:恢复快照后绘制虚线预览(半透明、虚线样式)。

onUp:恢复快照后绘制实线图形,保存撤销状态,记录行为数据,并通过 onStrokeUpdate 回调发送同步数据。

_bindGeoEvents() { let startPos = null, previewImg = null; const onDown = (e) => { startPos = getPos(e); previewImg = this.ctx.getImageData(0, 0, this.width, this.height); }; const onMove = (e) => { if (!startPos) return; const cur = getPos(e); this.ctx.putImageData(previewImg, 0, 0); this._drawGeoShape(startPos, cur, false); // 虚线预览 }; const onUp = (e) => { if (!startPos) return; const cur = getPos(e); this.ctx.putImageData(previewImg, 0, 0); this._drawGeoShape(startPos, cur, true); // 实线确认 this._saveState(); // 记录行为数据、发送同步... startPos = null; }; // 绑定事件并存储清理函数 }

2.2.3 图形绘制实现

_drawGeoShape(from, to, isFinal)根据currentGeoTool绘制:

_drawGeoShape(from, to, isFinal) { const ctx = this.ctx; ctx.strokeStyle = this.currentColor; ctx.lineWidth = this.currentSize; if (!isFinal) { ctx.setLineDash([6, 4]); ctx.strokeStyle += '80'; // 半透明 } else { ctx.setLineDash([]); } const dx = to.x - from.x, dy = to.y - from.y; switch (this.currentGeoTool) { case 'line': ctx.beginPath(); ctx.moveTo(from.x, from.y); ctx.lineTo(to.x, to.y); ctx.stroke(); break; case 'rectangle': ctx.strokeRect(from.x, from.y, dx, dy); break; case 'circle': ctx.beginPath(); ctx.ellipse(from.x+dx/2, from.y+dy/2, Math.abs(dx)/2, Math.abs(dy)/2, 0, 0, 2*Math.PI); ctx.stroke(); break; case 'triangle': // 等腰三角形:顶点在起点x中间上方,底边为终点y ctx.beginPath(); ctx.moveTo(from.x+dx/2, from.y); ctx.lineTo(from.x, to.y); ctx.lineTo(to.x, to.y); ctx.closePath(); ctx.stroke(); break; } }

2.2.4 远程同步

观众端收到 drawing_sync 且 stroke_data.type === 'geo' 时,调用 replayGeoShape:

replayGeoShape(data) { const savedTool = this.currentGeoTool; this.currentGeoTool = data.tool; this.currentColor = data.color || '#000'; this.currentSize = data.width || 4; this._drawGeoShape(data.from, data.to, true); this.currentGeoTool = savedTool; }
2.3 游戏控制器集成(game.js)

2.3.1 接收模式标记

在 pick_word_phase 事件中,后端下发 restricted_mode 和 allowed_tools:

s.on('pick_word_phase', (data) => { this.isRestricted = data.restricted_mode || false; this.allowedTools = data.allowed_tools || []; document.getElementById('round-info').textContent += (this.isRestricted ? ' · 📐 限定画具' : ''); });

2.3.2 激活几何画板

round_start事件中,画家端根据isRestricted调用画板模式切换并生成几何工具栏:

if (this.isDrawer) { // ... if (this.isRestricted && this.board.setRestrictedMode) { this.board.setRestrictedMode(this.allowedTools); this._showGeoToolbar(this.allowedTools); } else { this._showFreeToolbar(); } }

2.3.3 动态几何工具栏

_showGeoToolbar(tools) 创建临时工具栏,包含几何工具按钮、粗细选择、黑色提示,并隐藏原有的颜色、粗细、橡皮擦按钮。_showFreeToolbar() 恢复原始工具栏。

2.4 测试验证
测试项结果
进入限定模式,画板切换到几何模式
拖拽绘制圆形、矩形、直线、三角形✅(虚线预览,实线确认)
切换工具
粗细调节
撤销几何图形
远程同步(观众看到相同图形)
下一回合恢复自由模式

三、画风档案展示页

3.1 页面设计

新增 templates/profile.html 和路由 /profile/<user_id>。页面包含:

用户头部:头像、昵称、返回按钮。

摘要卡片:当前版本号、分析局数、生成模型、更新时间。

画风描述:AI 生成的文字总结。

风格标签:如“严谨型”“抽象派”等标签云。

量化指标网格:平均笔速、画面覆盖率、对称性、修改频率、笔画数、绘画时长、拐点密度、用色数量,带图标和单位。

演变趋势图:当历史版本 ≥2 时,用微型折线图展示关键指标的变化趋势(旧→新)。

历史版本列表:展示历次分析报告的文字摘要。

3.2 数据接口

前端调用 /api/style_profile/<user_id> 获取 JSON 数据,结构示例:

{ "has_profile": true, "latest": { "version": 3, "rounds_analyzed": 12, "model_used": "v1.0", "generated_at": 1716547200, "profile_text": "你的画风偏向细致构图...", "features": { "avg_stroke_speed": 0.32, "avg_canvas_coverage": 0.18, "avg_symmetry": 0.72, "avg_undo_eraser": 1.5, "avg_stroke_count": 42, "avg_duration_ms": 28500, "avg_turn_density": 0.08, "avg_color_count": 3.2, "tags": ["细节控", "高对称性"] } }, "history": [ /* 之前的版本 */ ] }
3.3 前端渲染(profile.html)

加载时显示 loading,获取数据后展示。

量化指标使用 METRIC_META 映射标签和单位,并格式化(百分比、秒等)。

演变趋势图:为每个关键指标生成 240×60 的 canvas 折线图,带渐变填充和趋势箭头。

历史版本按时间倒序列出,包含版本号、分析局数、模型、时间戳和描述文字。

关键函数:renderLatest()、renderEvolution()、drawSparkline()、renderHistory()。

3.4 与现有系统的集成

在游戏结束面板和用户大厅增加“我的画风档案”链接。

后端需实现聚合查询(从 drawing_behaviors 和 psychology_reports 计算用户均值、生成标签和描述文本),前端仅负责展示。

四、与代码的对应关系

功能模块文件关键代码位置
几何图形绘制引擎canvas.jssetRestrictedMode,_bindGeoEvents,_drawGeoShape,replayGeoShape
游戏控制器模式切换game.jspick_word_phase事件、round_start中的判断、_showGeoToolbar/_showFreeToolbar
画风档案页面profile.html完整 HTML + 内嵌 JS(loadProfile,renderLatest,renderEvolution,drawSparkline
房间页模式提示room.htmlmode_labels中的restricted: '📐 限定画具'

五、AI 辅助开发记录

Prompt(限定画具):

在 Canvas 画板中增加限定画具模式,只能绘制圆形、矩形、直线、三角形,拖拽时虚线预览,松手实线确认,支持撤销和远程同步。请给出核心代码。

AI 提供了起点/终点绘制和预览/确认的两阶段方案,我在此基础上集成了撤销栈、行为数据采集和 WebSocket 同步。

Prompt(画风档案):

设计一个个人画风档案页面,展示用户的历史绘画行为指标(速度、覆盖率、对称性等)的均值、风格标签、演变趋势图(微型折线图)和历史版本列表。请给出前端 HTML/JS 和后端 API 设计建议。

AI 帮助设计了指标映射、趋势图和列表渲染逻辑,我根据实际数据字段调整了格式化函数和绘图参数。

六、下周计划

多模式前端逻辑完善:配合后端完成“经典模式”、“反向猜词模式”、“限定画具模式”的完整流程测试。

画风档案数据源对接:确保后端 /api/style_profile/<user_id> 返回真实聚合数据,前端能正确展示。

性能优化:几何图形预览时的 putImageData 对大画布有一定开销,可优化为只擦除预览区域。

限定画具模式丰富了玩法,画风档案则让玩家更直观地了解自己的创作特点,两个功能共同提升了游戏的趣味性和个人化体验。

http://www.jsqmd.com/news/926161/

相关文章:

  • 2026年苏州3家资质齐全防水补漏服务商核心市场适配与专业能力分析报告 专业防水公司排名推荐(2026年5月防水补漏最新TOP权威排名) - 鼎壹万修缮说
  • 逐位二进制拼接 → 翻转 → 去头零 → 消邻重
  • 汽车行业:从4S店到充电桩,电子合同正在重构汽车服务签约体验
  • AE510 Smart Kit:边缘 AI 视觉套件,让传统售货机迈入智能结算时代
  • 别再傻傻分不清了!用OpenCV+Python实战搞懂单应矩阵、本质矩阵和基础矩阵
  • OpCore Simplify:终极黑苹果配置工具,3步完成复杂EFI配置
  • 用Python和R实战检验皮尔逊相关性五大假设(附完整代码与可视化)
  • 2026年南京五粮液回收服务商评测:四家机构实力对比 - 优质品牌商家
  • 云主机(华为)改密码的流水账
  • K-means实战避坑指南:如何用肘部法则和轮廓系数找到最佳K值(附Python代码)
  • 接收端电路
  • yolov26改进 | 添加注意力机制篇 | 添加DAttention (DAT)注意力机制二次创新C2PSA(附独家网络结构图)
  • 基于PLC两电梯协同运力控制系统设计(设计源文件+万字报告+讲解)(支持资料、图片参考_降重降ai)_文章底部可以扫码
  • 容器之间ros2可发现topic没有数据
  • 3分钟完成GTNH中文汉化:新手完整安装指南
  • 小学期第三周
  • 第一篇:uniapp+Django 互动功能全流程(登录缓存→点赞 / 收藏 / 评论列表显示)
  • HTML5 新特性概览:探索现代 Web 的强大能力
  • 从手动混乱到智能有序:Irony Mod Manager如何让Paradox游戏模组管理效率提升3倍?
  • 给你的 Agent 上一场“砍价考试“:用 Cattle Trade 思路搭一个最小博弈测评
  • VoxCPM 语音模型新手部署与调用全指南
  • Django+Vue智慧农业管理系统源码+论文
  • QGIS新手避坑指南:从高德路网数据到空间分析的全流程实操
  • 云成本治理框架:优化云计算成本
  • 别再当‘黑盒’模型受害者了!用Python的shap库5分钟看懂你的XGBoost模型决策
  • AI自进化的可能与形态:一种结构工程的推演
  • 2026年国产质量流量计TOP5排行 核心参数实测对比 - 优质品牌商家
  • 避坑指南:高通SA8255P平台Nor Flash烧录全流程与‘先擦后写’的血泪教训
  • Masa Mods中文汉化包:为你的Minecraft 1.21模组体验注入母语力量!
  • 剧本逻辑断层?角色扁平?对话生硬?,Gemini剧本辅助系统5大诊断模块+实时修复建议全披露