如何使用pygbag结合pickle或其他库实现浏览器端游戏数据保存?
浏览器端Pygbag游戏存档问题解决
问题原因
浏览器环境下,Pygbag运行在WebAssembly沙盒中,没有直接访问本地文件系统的权限,你原来写的"Civ Data/main.pkl"路径是针对本地桌面环境的,在浏览器里无法识别,导致保存失败。
适配Pygbag内置存储的方案
Pygbag提供了虚拟的应用存储目录,可以通过os.path.expanduser("~")获取,修改保存代码如下:
import os import pickle # 创建并获取应用专属的存储目录 save_dir = os.path.join(os.path.expanduser("~"), "Civ Data") os.makedirs(save_dir, exist_ok=True) save_path = os.path.join(save_dir, "main.pkl") # 保存数据(改用with语句自动关闭文件) with open(save_path, "wb") as file: pickle.dump(kingdoms, file)
加载时同样使用这个路径即可,这种方式的存档会存在浏览器为Pygbag分配的虚拟存储中,关闭浏览器后通常不会丢失(取决于浏览器的存储策略)。
下载/上传存档的备选方案
如果上述内置存储方案不符合需求,可以实现手动下载存档文件、后续上传加载的功能:
1. 下载存档
将序列化后的pickle数据转为浏览器可识别的Blob对象,生成下载链接让玩家保存到本地:
import pickle from js import document, Blob, URL # 序列化游戏数据 save_data = pickle.dumps(kingdoms) # 创建二进制Blob对象 blob = Blob.new([save_data], {"type": "application/octet-stream"}) # 生成下载URL download_url = URL.createObjectURL(blob) # 创建隐藏的下载链接并触发点击 download_link = document.createElement("a") download_link.href = download_url download_link.download = "paperciv_save.pkl" download_link.style.display = "none" document.body.appendChild(download_link) download_link.click() # 清理资源 document.body.removeChild(download_link) URL.revokeObjectURL(download_url)
2. 加载本地存档
创建文件上传控件,让玩家选择本地的存档文件,读取后反序列化加载:
import pickle from js import document, FileReader from pyodide.ffi import create_proxy def handle_save_upload(event): # 获取选中的文件 save_file = event.target.files[0] reader = FileReader.new() # 文件读取完成后的回调 def on_file_loaded(e): global kingdoms # 将读取的ArrayBuffer转为bytes并反序列化 save_bytes = bytes(e.target.result) kingdoms = pickle.loads(save_bytes) # 这里可以添加加载成功后的提示逻辑 reader.onload = create_proxy(on_file_loaded) reader.readAsArrayBuffer(save_file) # 创建文件上传控件 upload_input = document.createElement("input") upload_input.type = "file" upload_input.accept = ".pkl" upload_input.onchange = create_proxy(handle_save_upload) # 将控件添加到页面(可以放在游戏UI合适的位置) document.body.appendChild(upload_input)
内容的提问来源于stack exchange,提问作者igr2020
相关产品推荐
相关产品推荐

