惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Cyberwarzone
Cyberwarzone
F
Full Disclosure
V
Visual Studio Blog
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
有赞技术团队
有赞技术团队
J
Java Code Geeks
博客园 - 【当耐特】
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
博客园 - 叶小钗
L
LINUX DO - 最新话题
T
Threatpost
S
SegmentFault 最新的问题
Vercel News
Vercel News
云风的 BLOG
云风的 BLOG
C
Cyber Attacks, Cyber Crime and Cyber Security
Google DeepMind News
Google DeepMind News
Know Your Adversary
Know Your Adversary
S
Schneier on Security
V
Vulnerabilities – Threatpost
D
DataBreaches.Net
G
GRAHAM CLULEY
Latest news
Latest news
P
Privacy International News Feed
D
Darknet – Hacking Tools, Hacker News & Cyber Security
C
CXSECURITY Database RSS Feed - CXSecurity.com
Scott Helme
Scott Helme
L
Lohrmann on Cybersecurity
T
The Exploit Database - CXSecurity.com
Security Latest
Security Latest
G
Google Developers Blog
L
LangChain Blog
MyScale Blog
MyScale Blog
Project Zero
Project Zero
N
News and Events Feed by Topic
Hacker News - Newest:
Hacker News - Newest: "LLM"
大猫的无限游戏
大猫的无限游戏
P
Proofpoint News Feed
Blog — PlanetScale
Blog — PlanetScale
阮一峰的网络日志
阮一峰的网络日志
N
News | PayPal Newsroom
www.infosecurity-magazine.com
www.infosecurity-magazine.com
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
SecWiki News
SecWiki News
T
Tor Project blog
C
Check Point Blog
Google Online Security Blog
Google Online Security Blog
GbyAI
GbyAI
The Last Watchdog
The Last Watchdog
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
WordPress大学
WordPress大学

机核

游戏性能旗舰最强之选,一加 Ace 6 至尊版国补到手价2999元起 6元钱自己更换电动车刹车线 《生化危机9:安魂曲》编剧Haris Orkin专访 摸金游戏?音乐游戏!暗区新赛季这把能弹的琴有何来历? 好评国产武侠SRPG《息风谷战略》免费DLC现已推出 | 机核 GCORES 碎片 《生化危机:安魂曲》将于5月实装首个免费更新内容 | 机核 GCORES 新锐东方游戏,谱写世界新章! 沉浸式恋爱视觉小说游戏《心象演算》免费试玩版现已正式上线 | 机核 GCORES 互动影游《代号三国:龙起》上线!穿越三国与曹操并肩、与佳人同行、与权谋博弈! 《老头收集梦想生活》,游戏酒桌会6,录音笔VOL.689 | 机核 GCORES 破界·共生——《白日梦:无限世界》五大核心游戏特点解析 价格已到史低,锐龙5 9600X/锐龙7 9700X正适合抄底 时间循环之旅即刻启程!《归环》一周目测试今日开启 热门在线韩游变魂游,洛奇衍生作能否打破“花瓶”魔咒? LG UltraGear evo 全新高端显示器系列:当“5K”遇见“AI”,不止强大,更懂热爱 反套路三国互动影游《代号三国:龙起》今日上线! 愿望单登记人数突破10万!备受瞩目的“女儿养成游戏” 《梦幻魔法公主》今日于Steam平台上线!限时八折优惠中 《黑神话:悟空》全球音乐会2026巡演将于4月29日12时开票 | 机核 GCORES “Snowguelike”生存肉鸽挖矿新作《蛙穿雪境》公布发售日期,5月7日正式上线 | 机核 GCORES 重塑移动办公、AI创作新境!全新华硕灵耀Air系列、ProArt 骁龙版震撼首发,创芯未来 均分88:《Saros》媒体评分汇总 | 机核 GCORES 上海烛龙公布合作遗迹探险游戏《吉时已到》首支预告片 | 机核 GCORES 首个独立游戏《萝薇日记》已上线Steam! 烛龙新IP《吉时已到》首曝,打造国内首款中式合作遗迹探险游戏 喜加一:《暗黑破坏神Ⅳ》国服现已开启限时免费领取本体活动 | 机核 GCORES 新版《生化危机》电影定于9月18日上映,官方网站现已上线 | 机核 GCORES 《冲就完事模拟器2》“星球大战”联动DLC正式宣布 | 机核 GCORES SteamController将于5月4日发售,售价99美元 | 机核 GCORES 事已至此,内存这么用也算省钱了,“2+1”非对称双通道应用实测 505游戏母公司现已收购《明末:渊虚之羽》IP | 机核 GCORES 基石 手动杂谈12|格斗游戏也能讲好故事 | 机核 GCORES I Love You Mr Snowball 我的向日葵小姐 会比GTA6先发售吗?最硬核的生存游戏《DAYZ》要推新DLC了 周记02:在2026遇到新怪谈 什么硬件,能让游戏Loading界面快速消失? | 机核 GCORES GadioSpec《百年风云世界杯》免费试听集 | 机核 GCORES 百年风云世界杯Vol.1丨足球崛起 | 机核 GCORES 100年前,一群人提前替我们经历了AI恐惧 | 机核 GCORES 《呼啸山庄》2026 ——一辆当代艺术的大卡车冲撞了我的大脑 手游《天穗之咲稻姬:日之香巡灵传》宣布将于7月27日停服 | 机核 GCORES 集结梦之队,征战世界杯,《最佳球会ONLINE》上线Steam 山水绝景随心拼 休闲建造游戏《千里山河录》Steam商店页公开 巫师帽、法袍、魔杖,为什么它们是影视、游戏里的法师必备三件套? 《无鞘信使》-第一章 复古风自动战斗肉鸽《终结之终结》Steam商店页面现已上线 电脑里有一款不破不立的MMO,录音笔VOL.688 | 机核 GCORES 《生化危机》30周年纪念周边发售,这次是真的“保护伞” 可靠耐用+AI全能,惠普战66 2025锐龙版深度体验 《时之书:无尽终章》关卡“大航海时代”全球首次公开 经典名作《乌龙派出所》改编经营模拟游戏《乌龙派出所~阿两的商店街物语~》正式宣布支持简体中文 明日开冲,解锁反套路三国互动影游《代号三国:龙起》即将上线 独立游戏《这是我的宝藏!》已发售~ 降低难度不是唯一解,无压力死亡也是好体验 Netflix官宣新片《普通人》:讲述韩国现代史上的权力风暴 《生化危机:安魂曲》全球销量现已突破700万份 《绝地鸭卫》PC版5月15日正式发售 亡妻回忆录?女性向情感叙事游戏《S-mail》现已正式发售 全新酷黑风格,酷睿Ultra 200S PLUS的高性价比搭档!七彩虹BATTLE-AX B860M-PLUS S WIFI7 V20 超级黑刃主板测评 胖狗 索尼发布了港台地区PS5产品价格调整公告,将于5月1日起实施 二次元怪猎+性感美女!《碧蓝幻想:无尽黄昏》开启Beta公测 这款怪谈类型中式恐怖游戏居然更新了?! 《百日战纪 -最终防卫学园-》改编漫画将于今年冬季开启连载 《如被附身,请致电我们》:匈牙利黑色幽默恐怖小说 《竹屿山房杂部卷五》(译文) 大树 超越引擎 摄影分享丨四月 碎片杂记vol.72 当老式FPS与老式动画技术碰撞出新时代的火花—《神探杰克鼠》 想做独游,如何避免首个项目就褒姒? 在线多人动作游戏《OCTOPinbs》将于5月12日上线Steam! 《酒鬼女神的酒诡》确定将于2026年登陆Steam 《CRYMELIGHT》将于11月5日(周四)正式发售!4月25日开始预购! 钢铁国度MKI部落Evolution,蛮兵部分 【钢铁国度】部落-Primal MK I,蛮兵部分 这是一个高中生用ai跑出来的作品,我自称他为物理神话 钢铁国度MKI部落Metamorphosis,蛮兵部分上 钢铁国度MKI部落Metamorphosis,蛮兵部分下 INDIE Live Expo于4月25日举办:首发9款新作,超200款独立游戏亮相 暗黑卡牌策略新作《魔忌:穷鼠啮狸》发布全新中文试玩版和发售预告片,4月30日正式上线在即 战锤40K长篇小说:变节者・苦难主宰(三)(全书完) 战锤40K长篇小说:变节者・苦难主宰(二) 战锤40K长篇小说:变节者・苦难主宰(一) 英语语言学习丨短语专题1:短语的特点 唯一的EVE战争 【少前同人】【M200】战术人形会梦见音乐会吗 【昏迷3】即将发售,前作主角悉数到场!“恶灵”宋老师化身可操控角色 业内人士:游戏公司“十有八九”使用生成式AI,包括卡普空 欢庆一周年:《光与影:33号远征队》全新纪念艺术图、超值折扣与免费更新同步上线 才刚刚开始呢 【抽奖】《星际卡车司机》推出免费大型更新,四折平史低折扣进行中 四人合作FPS游戏《佣兵猎手》抢先体验重大更新 1 现已上线 Raw Fury新作《深馅地牢 Deep Dish Dungeon》将于今秋加入 XGP 塔防幸存者游戏《魔怪来袭》推出首个 DLC 《饿狼传说:群狼之城》1周年纪念!新DLC“沃尔夫冈·克劳萨”今日参战 猫狗相伴 欢乐闯关 双人合作平台跳跃游戏《猫狗同行》上线Steam商店页 《同行:月球逃脱》(Together: Moon Escape)上线将于明日上线Steam
编辑器开发、Bevy 移植基本完成 etc. #002
宏楼 · 2024-06-03 · via 机核

因为本篇涉及较大量代码,又因为机核文章没有代码块,因此阅读体验不佳。 若你有阅读代码的兴趣,可以到 itch.io 阅读本日志:点击跳转

编辑器 @宏楼 Koiro

现在编辑器可以进行方块编辑、选区移动、加载 & 保存存档的功能。

1 / 2

更好的方块注册系统和序列化系统 @宏楼 Koiro

方块注册系统

系统本身并不复杂,核心实现大概是这样,我们确保每个方块有一个唯一的 registry name,利用 registry name 和对应的 Block Builder 的行为生成方块:

lazy_static! { pub static ref BLOCK_REGISTRY: Mutex<BlockRegistry> = Mutex::new(BlockRegistry::default()); } pub trait BlockBuilder { fn spawn(&self, world: &mut World, spawn_cmd: &SpawnBlockCmd) -> Result<()>; } #[derive(Default)] pub struct BlockRegistry { map: HashMap<String, Box<dyn BlockBuilder + Send>>, } impl BlockRegistry { pub fn register_block<T: BlockBuilder + Send + 'static>(&mut self, reg_name: &str, builder: T) { //... } pub fn get_block_builder(&self, reg_name: &str) -> Option<&Box<dyn BlockBuilder + Send>> { //... } //... }

因为生成方块时 world 所有权冲突问题,所以方块注册表并没有使用 Bevy 的 Resource 和 Non-Send Resource,而是使用 lazy_static.

序列化系统

序列化和反序列化行为用 DeserializeManager 和 SerializeManager 管理。分别在保存和加载时调用。序列化时,场景会被序列化成 toml 中的 Table. 根据需要保存在磁盘或内存中。

#[derive(Default, Resource, Clone)] pub struct CatDeserializerManager { pub map: HashMap<Stage, HashMap<String, SystemId<DeserializeContext, Result<()>>>>, } #[derive(Default, Resource, Clone)] pub struct CatSerializerManager { pub map: HashMap<String, SystemId<(), Result<Table>>>, }

同时为加载做了阶段,每个阶段会间隔几帧执行。

#[derive(Default, Clone, PartialEq, Eq, Reflect, Hash)] pub enum Stage { Start, Pre, #[default] Normal, Post, End, }

Action 系统 @Rasp

@Koiro 补充:命令模式之所以叫 Action 是因为 Command 被 bevy 用了

为了让玩家的交互和地图上发生的事情可以被撤销,我们要先把命令模式做完。

用几个栈的组合可以实现动作和反动作(也就是撤销)操作的存储和执行,这个比较简单。比较有趣的问题是,这些栈里面要存什么。

由于我们在使用 Rust,我决定用 Trait 对象实现所有 Action 通用的功能。

pub trait Action: Send + Sync { fn r#do(&self, world: &mut World); fn undo(&self, world: &mut World); fn name(&self) -> String; }

可以注意到,两个核心方法的签名都是对自身的不可变借用。这实际上是一个设计失误,不可变借用自身导致在动作和反动作之间保存状态变得不可能。这会让类似“移除一个方块并在撤销时还原这个方块”这类的操作无法实现,因为我们无法保存那个“被移除的方块”。但是如果使用了可变借用,又会遇到一些跟 Bevy 相关的所有权问题。

一个临时解决方案是使用 Mutex:

pub trait ActionMut: Send + Sync { fn r#do(&mut self, world: &mut World); fn undo(&mut self, world: &mut World); } impl<AM: ActionMut> Action for (String, Mutex<AM>) { fn r#do(&self, world: &mut World) { let mut inner = self.1.lock().unwrap(); inner.r#do(world); } fn undo(&self, world: &mut World) { let mut inner = self.1.lock().unwrap(); inner.undo(world); } fn name(&self) -> String { format!("{}", self.0) } }

这样,我们就可以为需要可变借用自身的 Action 实现对应的 Trait 并且不会破坏先前实现的代码。

方块的合并与反合并 @Rasp

之前在 Unity 里面实现这个功能的时候因为没有认真想过怎么做撤销,用了一个非常草率的解决方案。

这个草率的解决方案基于一个假设:方块集合不能从中间断开。意思是,如果两个方块粘在一起,那么游戏中没有正常的操作能够把它们分开。相信你已经看出问题了,撤回操作作为合并操作的反操作,会破坏这个假设,导致旧有的解决方案没法正常使用。

新的解决方案基于一个基本原理:我们要保存方块、保存它跟谁粘在一起,更重要的是:保存这个方块所有的邻居信息。这样,通过对比当前邻居信息和之前邻居的差异,可以分辨出到底发生了什么:连接还是断开,又或者是增加了新的方块。

#[derive(Component, Reflect, Default)] pub struct BlockUnionSet { // core neighbors: HashMap<Entity, [Option<Neighbor>; 4]>, // polymer polymer_id: HashMap<Entity, u64>, polymers: HashMap<u64, Vec<Entity>>, empty_polyer_id: Vec<u64>, // edge #[reflect(ignore)] edges: HashMap<String, BTreeSet<Edge>>, }

比较邻居信息并且更新方块集合的代码看起来像这样:

for (neighbor_in_set, neighbor_on_map) in neighbors { match (neighbor_in_set, neighbor_on_map) { (None, None) => { /* nop */ } (None, Some(on_map)) => { // in this case, we have to check the new neighbor is the same or not if block.reg_name == blocks[&on_map].reg_name { // if they are, we merge self.merge_polymer(entity, on_map); } } (Some(in_set), None) => { // in this case, we have to check our old neighbor if in_set.0 { // if our old neighbor and entity are the same, it means we lost a neighbor // we will request a deep refresh for this entity and it's connected blocks deep_refresh_list.push(entity); } } (Some(in_set), Some(on_map)) => { // in this case, we have to consider our old neighbor is the same with us or not if in_set.0 { // if they were and it's not now if blocks[&on_map].reg_name != block.reg_name { // we lost a neighbor deep_refresh_list.push(entity); deep_refresh_list.push(on_map); } } else { // if they were not but they are now if blocks[&on_map].reg_name == block.reg_name { // we have a new neighbor deep_refresh_list.push(entity); deep_refresh_list.push(on_map); } } } } }

更令人欣喜的是,存储了邻居相关的信息之后,后面方块集合边缘的寻找和判断也变得简单了。

玩家移动 @Rasp

在方块合并和反合并工作的基础上,我们可以把玩家移动的部分做完。

由于 Tilemap 部分完成了很多工作,留给我的部分不多。

首先我们要为单个方块编写移动相关的 Action,实现过程也很简单。在有了这个功能之后,我们通过先判断玩家的移动方向是否有障碍,如果有就判断障碍物是否可以移动。最后把所有需要移动的方块对应的移动 Action 都推进栈中等待执行即可。

边界改变交互 @宏楼 Koiro

边界改变的逻辑由 Asepirin 完成了,我仅需要做边界改变的交互与视觉设计。我们使用了虚拟光标。目前的效果是临时的,借此机会熟悉了些 bevy 中使用 shader.