- 音频(音频.md §2):Session.Sound 事件回调,破坏/放置/攻击/村民环境音接入, 客户端 audio.Manager 3D 衰减 + 监听器跟随 + 音量可调 - 原版掉落:草方块→泥土、石头→圆石、树叶无掉落(no_drop);掉落物实体 用物品图标小广告牌渲染(物品纹理并入实体图集) - 动物攻击(动物体系.md §5):左键优先射线命中实体(半径 0.6 球体判定), 伤害/击退/死亡移除+肉类掉落;僵尸掉腐肉 - 村庄村民(村民系统.md §2):Generator.VillageAt 定位村庄中心,会话扫描 已加载区块在村庄生成 3 名村民 - 种子与灵敏度配置:client.yaml world.seed/name、mouse_sensitivity; 存档与种子联动;鼠标左右反转修复(右移应右转) - 设置界面(UI与输入.md §6):屏幕状态 4,灵敏度/音量滑条、世界种子显示、 按键教程多行列表(cjkfont 支持 \\n)、完成按钮;主菜单/暂停菜单入口 - 准星指向方块名:左下角 CJK 显示(lang 本地化,tick 光栅化渲染线程上传) - 截图统一存项目根目录 jietu/(paths.RootDir;dev 构建识别 bin/ 布局)
46 lines
1.3 KiB
Go
46 lines
1.3 KiB
Go
//go:build gl
|
||
|
||
// 开发测试工具:自动进游戏 + 截图(dev 测试通过后再打包)。
|
||
package main
|
||
|
||
import (
|
||
"fmt"
|
||
"image"
|
||
"image/png"
|
||
"os"
|
||
"path/filepath"
|
||
|
||
"mc/internal/paths"
|
||
|
||
"github.com/go-gl/gl/v3.3-core/gl"
|
||
)
|
||
|
||
// saveScreenshot 从默认帧缓冲读取像素并保存为 PNG(渲染线程调用)。
|
||
// 截图统一存项目根目录 jietu/:裸文件名自动归入该目录,
|
||
// 带目录/绝对路径保持原样(打包产物 bin/ 不再混入截图)。
|
||
func (a *clientApp) saveScreenshot(path string) error {
|
||
if filepath.Base(path) == path { // 无目录成分 → 根目录 jietu/
|
||
dir := filepath.Join(paths.RootDir(), "jietu")
|
||
if err := os.MkdirAll(dir, 0o755); err != nil {
|
||
return fmt.Errorf("创建截图目录: %w", err)
|
||
}
|
||
path = filepath.Join(dir, path)
|
||
}
|
||
w, h := int32(a.winW), int32(a.winH)
|
||
pix := make([]uint8, w*h*4)
|
||
gl.ReadPixels(0, 0, w, h, gl.RGBA, gl.UNSIGNED_BYTE, gl.Ptr(pix))
|
||
img := image.NewRGBA(image.Rect(0, 0, int(w), int(h)))
|
||
// 垂直翻转(GL 原点在左下)
|
||
for y := int32(0); y < h; y++ {
|
||
srcRow := (h - 1 - y) * w * 4
|
||
dstRow := y * w * 4
|
||
copy(img.Pix[dstRow:dstRow+w*4], pix[srcRow:srcRow+w*4])
|
||
}
|
||
f, err := os.Create(path)
|
||
if err != nil {
|
||
return fmt.Errorf("创建截图文件: %w", err)
|
||
}
|
||
defer f.Close()
|
||
return png.Encode(f, img)
|
||
}
|