1.0 代码结构 开始冒险的第一步,整个窗口出来
首先我们使用 cargo init vk_1_1_0
创建一个基础的Rust项目
vk_1_1_0
src
cargo.toml
.git
大概是这个样子的
我们需要安装一些库. Rust是一个非常好的工具因为他提供了Cargo这么好用的减少心智负担的工具 我们打开 cargo.toml 大概按照下面的抄抄
[package]
#这个一般都给你写好了,不用操心
name = "vk_00"
#项目名称
version = "0.1.0"
#项目版本
authors = ["lemonhx <runzhe2001@hotmail.com>"]
#作者们
edition = "2018"
[dependencies]
#依赖的库
winit = "0.19.0"
#用来创建窗口的
ash = "0.28.0"
#vulkan绑定
num = "0.2"
#用来操作数字的
cgmath = "0.17"
#数学库
image = "0.21"
#用来操作图片的
memoffset = "0.3"
#用来操作内存的
tobj = "0.1.6"
[target.'cfg(target_os = "windows")'.dependencies]
winapi = { version = "0.3.6", features = ["windef", "libloaderapi"] }
#这一堆是windows的api绑定
抄好之后使用cargo run
下载依赖并运行,不出问题的话就会有hello world窗口弹出
首先呢,我们要在src
目录下创建一个lib.rs
用来管理我们项目的结构
随后在新建一个app
文件夹用来存放主要的代码
在app
目录下创建一个mod.rs
用来管理app下的结构
现在目录大概长这样
vk_1_1_0
src
app
mod.rs
main.rs
lib.rs
cargo.toml
.git
准备工作做得差不多了,现在我们开始创建即将运行我们所有的Vulkan的窗口吧!
在src/app
目录下新建app.rs
并在mod.rs
中加入
pub mod app;
将这个文件注册到我们的项目
然后在lib.rs
加入
pub mod app;
将app文件夹注册到我们的项目
现在考虑一下如何创建窗口
在src
下创建window.rs
并在lib.rs
下加入
pub mod window;
然后在window.rs
下加入以下内容
use winit::*; //我们需要这个库创建窗口
pub fn window_create(
title: String, //窗口标题
width: u32, //宽度
height: u32, //高度
events_loop: &EventsLoop,//事件循环
) -> winit::Window {
winit::WindowBuilder::new() //创建窗口工具
.with_title(title) //设置标题
.with_dimensions((width, height).into()) //设置大小
.build(events_loop) //传入事件循环
.expect("Err 窗口创建失败 原因:") //创建失败后报错
}
上面这一堆代码总体来讲就是很简单明了,但是事件循环是什么可能很多人不知道我可以大概解释一下:
我自己在跑步(循环),跑着跑着被绊倒了(遇到事件),我爬起来(事件的处理方式),我继续跑(重新回到循环)
这个是一个简单的事件循环,同样,我还可以
跑步(循环),被车撞了(遇到事件),躺地上求救(事件处理),没人搭理死了(处理结果)
很简单明了,创建窗口需要绑定一个事件循环的原因是,你可能对着这个窗口按键,点击鼠标,拖拽,窗口会用你之前定义好的事件处理方式去处理这些事件.
所以现在,我们可以定义一组事件的处理方式
在src
目录下创建events_handler
文件夹
创建mod.rs
写入以下内容
use winit::{ControlFlow, Event, VirtualKeyCode, WindowEvent};// 使用 控制流 事件 按键代码 窗口事件
// 这个函数收到一个事件,返回一个控制流(之后干什么)
pub fn event_handler(event: Event) -> winit::ControlFlow {
match event {
// 处理键盘输入事件
Event::WindowEvent { event, .. } => match event {
WindowEvent::KeyboardInput { input, .. } => {
if let Some(VirtualKeyCode::Escape) = input.virtual_keycode {//如果是ESC被按下来了
ControlFlow::Break //退出事件循环
} else {
ControlFlow::Continue //要不啥也不干
}
}
WindowEvent::CloseRequested => ControlFlow::Break, //如果窗口被关了,退出程序
_ => ControlFlow::Continue,
},
_ => ControlFlow::Continue,
}
}
最后开始写app.rs
我们的app暂时仅仅只有一个窗口,所以我们创建一个结构体包含一个窗口实例就行了
use winit::*; //使用winit库
pub struct App {
pub window: Window,//结构体内的window是Window类型的
}
//创建方法
impl App {
pub fn new(events_loop: &EventsLoop) -> App {
let window = window_create("题目".to_string(), 800, 600, events_loop); //使用之前定义的那个窗口创建
return App { window: window }; //返回App结构体
}
}
最后,我们更改main.rs
use vk_1_1_0::app::app::*;
use vk_1_1_0::events_handler::*;
fn main() {
let mut evl = winit::EventsLoop::new(); //创建事件循环
let vulkan_app = App::new(&evl); //把事件循环绑定到窗口上
evl.run_forever(event_handler); //开始事件循环
//这个run_forever是一个函数接受一个函数,所以我们把事件处理函数传进去
}
最后cargo run
会有一个窗口弹出
补充: 如果终端显示 error: process didn't exit successfully: target\debug\vk_00.exe
(exit code: 0xc0000005, STATUS_ACCESS_VIOLATION)或类似问题,请不要急,在1.2会解决这个问题的