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会解决这个问题的

results matching ""

    No results matching ""