下载SDL2库
为了实现音乐播放功能,你需要下载SDL2和SDL_mixer相关文件
假如你是Windows电脑,两个库都需要下载-VC.zip
结尾的压缩包
SDL2解压
观察压缩包里面的文件夹,最重要的有两个:include
和lib
lib
文件夹下有静态链接库也有动态链接库,按照下面图片进行放置:
注意:这个bin文件夹如果不需要其他功能,则只保留SDL2.dll
和SDL2_mixer.dll
即可
请把两个压缩包的include都解压到这里
编写zig的build文件
const std = @import("std");
// Build总的来说是一个由依赖组成的有向无环图
// 从主文件开始
pub fn build(b: *std.Build) void {
// 为了标准化,提供了两个函数:standardTargetOptions、standardOptimizeOption
// standardTargetOptions: 设置生成文件在运行时所在的操作系统,如windows,linux等
// standardOptimizeOption:设置生成文件的release或者debug类型
const target = b.standardTargetOptions(.{});
const optimize = b.standardOptimizeOption(.{});
const exe = b.addExecutable(.{
.name = "sdl2",
.root_source_file = b.path("src/main.zig"),
.target = target,
.optimize = optimize,
});
exe.addIncludePath(.{ .cwd_relative = "D:/SDK/SDL2/include" });
// 把静态库和动态库加载到系统库下
exe.addLibraryPath(.{ .cwd_relative = "D:/SDK/SDL2/lib" });
exe.addLibraryPath(.{ .cwd_relative = "D:/SDK/SDL2/bin" });
// 链接里面的系统库文件
exe.linkSystemLibrary("SDL2");
exe.linkSystemLibrary("SDL2_mixer");
// 我们需要C标准库的内容,所以要连接C库
exe.linkLibC();
// 由于直接使用installBinFile无法设定绝对路径,所以改用addInstallBinFile方法,并且设置依赖,等到最后构建的时候,会向上查找所需依赖项并逐个构建
const sdl2_mv_step = b.addInstallBinFile(.{ .cwd_relative = "D:/SDK/SDL2/bin/SDL2.dll" }, "SDL2.dll");
b.getInstallStep().dependOn(&sdl2_mv_step.step);
const sdl2_mixer_step = b.addInstallBinFile(.{ .cwd_relative = "D:/SDK/SDL2/bin/SDL2_mixer.dll" }, "SDL2_mixer.dll");
b.getInstallStep().dependOn(&sdl2_mixer_step.step);
b.installArtifact(exe);
// 这个会在Build图中创建一个运行步骤,当其他步骤依赖此步骤的时候,这个步骤将会被执行
// 下面的一段代码将会建立上述的一个依赖
const run_cmd = b.addRunArtifact(exe);
// 下面的都是模板原来的内容
run_cmd.step.dependOn(b.getInstallStep());
if (b.args) |args| {
run_cmd.addArgs(args);
}
const run_step = b.step("run", "Run the app");
run_step.dependOn(&run_cmd.step);
const lib_unit_tests = b.addTest(.{
.root_source_file = b.path("src/root.zig"),
.target = target,
.optimize = optimize,
});
const run_lib_unit_tests = b.addRunArtifact(lib_unit_tests);
const exe_unit_tests = b.addTest(.{
.root_source_file = b.path("src/main.zig"),
.target = target,
.optimize = optimize,
});
const run_exe_unit_tests = b.addRunArtifact(exe_unit_tests);
const test_step = b.step("test", "Run unit tests");
test_step.dependOn(&run_lib_unit_tests.step);
test_step.dependOn(&run_exe_unit_tests.step);
}
编写main.zig
const std = @import("std");
const c = @cImport({
@cInclude("stdio.h");
@cInclude("stdlib.h");
});
const sdl = @cImport({
@cInclude("SDL.h");
});
const sdl_music = @cImport({
@cInclude("SDL_mixer.h");
});
pub fn main() !void {
const WINDOW_W = 800;
const WINDOW_H = 600;
if (sdl.SDL_Init(sdl.SDL_INIT_VIDEO) != 0) {
sdl.SDL_LogError(sdl.SDL_LOG_CATEGORY_ERROR, "%s", sdl.SDL_GetError());
return error.InitSDLError;
}
defer sdl.SDL_Quit();
// 我要播放FLAC类型的歌曲,所以初始化这个
_ = sdl_music.Mix_Init(sdl_music.MIX_INIT_FLAC);
defer sdl_music.Mix_Quit();
const window: *sdl.SDL_Window = sdl.SDL_CreateWindow("yay square", 800, 150, WINDOW_W, WINDOW_H, sdl.SDL_WINDOW_SHOWN) orelse {
sdl.SDL_LogError(sdl.SDL_LOG_CATEGORY_ERROR, "%s", sdl.SDL_GetError());
return error.WindowError;
};
defer sdl.SDL_DestroyWindow(window);
const renderer: *sdl.SDL_Renderer = sdl.SDL_CreateRenderer(window, -1, sdl.SDL_RENDERER_ACCELERATED | sdl.SDL_RENDERER_PRESENTVSYNC) orelse {
sdl.SDL_LogError(sdl.SDL_LOG_CATEGORY_ERROR, "%s", sdl.SDL_GetError());
return error.RendererError;
};
defer sdl.SDL_DestroyRenderer(renderer);
_ = sdl_music.Mix_OpenAudio(sdl_music.MIX_DEFAULT_FREQUENCY, sdl_music.MIX_DEFAULT_FORMAT, sdl_music.MIX_DEFAULT_CHANNELS, 2048);
defer sdl_music.Mix_CloseAudio();
// 在当前运行目录下查找这首歌
const music: *sdl_music.Mix_Music = sdl_music.Mix_LoadMUS("So Far Away.flac") orelse {
std.debug.print("CANT LOAD MUSIC", .{});
return error.CantPlayMusic;
};
defer sdl_music.Mix_FreeMusic(music);
_ = sdl_music.Mix_PlayMusic(music, 10);
var event: sdl.SDL_Event = undefined;
out: while (true) {
while (sdl.SDL_PollEvent(&event) == 1) {
switch (event.type) {
sdl.SDL_QUIT => {
_ = c.puts("Exited!");
return;
},
sdl.SDL_MOUSEBUTTONDOWN => {
_ = c.printf("Button down at (%d, %d)\n", event.button.x, event.button.y);
},
sdl.SDL_MOUSEBUTTONUP => {
_ = c.printf("Button up at (%d, %d)\n", event.button.x, event.button.y);
},
sdl.SDL_KEYDOWN => {
_ = c.printf("Key down: %s\n", sdl.SDL_GetKeyName(event.key.keysym.sym));
},
sdl.SDL_KEYUP => {
_ = c.printf("Key up: %s\n", sdl.SDL_GetKeyName(event.key.keysym.sym));
if (event.key.keysym.sym == sdl.SDLK_HOME) {
_ = c.puts("Exited by key.");
break :out;
}
},
else => {},
}
_ = c.fflush(c.__acrt_iob_func(1));
}
sdl.SDL_Delay(5);
}
}
如果之前写过SDL2相关代码的可以很明显的看出来,其实所有SDL2的函数都被包含在了sdl这个变量中,而这个变量引用了SDL.h
头文件
zig在进行编译的过程中会把头文件的C代码转换成zig代码:
运行
# 运行命令(编译并运行)
zig build run
# 假如直接运行sdl2.exe,则要保证这个目录下面有歌
我的文件目录如下:
结语
zig与c/c++代码可以无缝结合这一点我很喜欢
学习zig大概四天左右,对于这门语言的理解还是有很大欠缺,如果有写的不对的地方,欢迎各位大佬评论✍🏻
希望zig语言可以快速发展,社区生态更加丰富