【ZIG】SDL2实现音乐播放

下载SDL2库

为了实现音乐播放功能,你需要下载SDL2和SDL_mixer相关文件

假如你是Windows电脑,两个库都需要下载-VC.zip结尾的压缩包

SDL2解压

观察压缩包里面的文件夹,最重要的有两个:includelib

lib文件夹下有静态链接库也有动态链接库,按照下面图片进行放置:

SDL2目录

注意:这个bin文件夹如果不需要其他功能,则只保留SDL2.dllSDL2_mixer.dll即可

BIN
请把两个压缩包的include都解压到这里

include
lib

编写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转换

运行

# 运行命令(编译并运行)
zig build run
# 假如直接运行sdl2.exe,则要保证这个目录下面有歌

我的文件目录如下:
文件目录

结语

zig与c/c++代码可以无缝结合这一点我很喜欢

学习zig大概四天左右,对于这门语言的理解还是有很大欠缺,如果有写的不对的地方,欢迎各位大佬评论✍🏻

希望zig语言可以快速发展,社区生态更加丰富

GITHUB

zig_sdl2_sample

  • 5
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值