昨天我们引入了静态资源(assets
)以及给瓦片上色
坏蛋Dan:rust基础学习--基于Bevy实现扫雷小游戏day4
今天咱们继续
既然已经上完色了,接下来该准备实现交互了。
既然是交互,那自然就是避不开点击事件了。
那么我们得解决两个问题:
第一个好解决,游戏引擎没有事件监听机制就奇了怪了。
重点是第二个。
在没有api
的情况下,最简单最暴力的方式自然是获取点击的位置,然后再通过坐标 + 瓦片size
来计算。
这里文档说官方没有提供相关api
,所以这回真的只能暴力了。
在开始之前,这里还需要注意一点:窗口和我们的扫雷不一定是完全覆盖的,所以需要判断点击的是否是扫雷范围内的,然后才能计算是哪个瓦片。
我们到board_plugin/src/resources
文件夹里创建一个board.rs
文件,这个资源用来表示我们的扫雷块,之前的tile_map
是裸露直接暴露给app
的,这样不是很好,因为有些关联信息并没有被带上,比如当前扫雷块在窗口的位置。
你可能会想我们拓展下tile_map
的字段即可。但实际上这样是不对的,tile_map
并不能完全代表扫雷块,把这个扫雷块位置放到它里面是一种不规范的行为。
所以这里新开了一个board.rs
用来表示扫雷块,这个tile_map
自然是它的其中一个字段
这里选择使用资源来实现是因为到时候是需要改变数据的,tile
和tile_map
都是资源,这样到时候就能直接穿透到tile
上去修改数据。
计算逻辑很简单,就是用(点击的位置(相对于窗口) - 当前扫雷块的起始位置(左下角在窗口中的位置) / tile_size
)。这样就获得了点击对应在扫雷块中的坐标即确定了对应的瓦片位置。
不过这里我们并没有实现in_bounds
也就是判断是否在扫雷块中的逻辑。
另外还有一点你应该有点疑惑,那就是为什么这个window
在被position
减去之前要自己/ 2.
呢?
因为position
点击是根据world space
的,而wprld space
是默认当前camera
为中心的,而我们的窗口是以左下角为中心的,所以这里position
多减去width/2
和height/2
个位置来对准window
坐标轴。
别忘了暴露出去
然后我们来实现这个in_bounds
方法,我们在board_plugin/src
下新建bounds.rs
,你可能会疑惑为啥不放到components
里,因为这里不是为了实体服务的,这个bounds
是用于表示我们扫雷块资源的范围的,原本应该由官方提供相应的。
代码很简单就不多说了。
然后我们来调用这俩货。
回到lib.rs
的create_board
方法中, 由于我们的资源需要数据依赖,所以自然是不能在最开始插进去的,相反,我们得放在最后再加上去,因为是需要所有权的,为了避免影响到中间数据处理,这里得放在最后。
xy
[2]: 降维打击,返回一个二维的Vec2
。
那么现在还差一步,监听事件点击。
我们在board_plugin/src
文件夹里创建一个systems
的文件夹用来存放交互的逻辑,虽然lib.rs
中也有逻辑,但是那也是为了配置而需要的逻辑,初始化数据,处理数据,组装数据等。
我们在里面创建mod.rs
和input.rs
文件。
input.rs
中实现交互逻辑
get_primary
:返回主要的窗口的引用。MouseButtonInput
:鼠标按钮输入事件。ButtonState
:鼠标按钮的状态,自然是有Pressed
和Released
按压和释放两种状态。MouseButton
:有四个属性,鼠标左/右键,滑轮以及一些鼠标的自定义宏键(都属于Other
)。这里做的事情也很简单,监听鼠标左键Pressed
,然后计算点击的坐标
这里有辨别是鼠标左键还是右键的逻辑,因为扫雷游戏右键可以插旗。
然后我们引入到lib.rs
里的build
中注册这个system
。
然后我们来执行下cargo run
当你点击按钮的时候就会触发打印,输出对应坐标。
不过我们现在还没有实现点击之后触发的逻辑,这块是扫雷的核心逻辑。
剩下的mod.rs
就不放出来了。
万事差不多都具备了,可以开始实现核心逻辑了。
发布于 2023-02-12 17:52・IP 属地广东