0464-Bomb-实现通关界面

环境

  • Time 2024-03-23
  • Zig 0.12.0-dev.3152+90c1a2c41
  • WSL-Ubuntu 22.04.3 LTS
  • raylib 5.0

前言

说明

参考资料:

  1. 《游戏开发:世嘉新人培训教材》
  2. 图片素材:https://www.ituring.com.cn/book/1742

目标

如果达到了最大地图,则显示通关界面。

popup.zig

const std = @import("std");
const engine = @import("engine.zig");
const map = @import("map.zig");

pub const MenuType = enum { quit, title, reset, next };
pub const PopupType = enum { clear, over, ending };

pub const Popup = union(PopupType) {
    clear: TimePopup,
    over: TimePopup,
    ending: TimePopup,

    pub fn update(self: *Popup) ?MenuType {
        return switch (self.*) {
            inline else => |*case| case.update(),
        };
    }

    pub fn draw(self: Popup) void {
        switch (self) {
            inline else => |sequence| sequence.draw(),
        }
    }

    pub fn deinit(self: Popup) void {
        switch (self) {
            inline else => |sequence| sequence.deinit(),
        }
    }
};

pub fn initWithType(popupType: PopupType) Popup {
    return switch (popupType) {
        .clear => .{ .clear = TimePopup.init("clear.png", .next) },
        .over => .{ .over = TimePopup.init("over.png", .title) },
        .ending => .{ .ending = TimePopup.init("ending.png", .title) },
    };
}

const TimePopup = struct {
    image: engine.Image,
    time: usize,
    target: MenuType,

    fn init(name: []const u8, target: MenuType) TimePopup {
        return TimePopup{
            .image = engine.Image.init(name),
            .time = engine.time(),
            .target = target,
        };
    }

    fn update(self: TimePopup) ?MenuType {
        return if (engine.time() - self.time > 2000) self.target else null;
    }

    fn draw(self: TimePopup) void {
        self.image.draw();
    }

    fn deinit(self: TimePopup) void {
        self.image.deinit();
    }
};

stage.zig

const std = @import("std");
const popup = @import("popup.zig");
const play = @import("play.zig");

pub const SequenceType = enum { title, mode, stage };
pub const SequenceData = union(SequenceType) {
    title: void,
    mode: bool,
    stage: usize,
};

pub fn init(mode: bool, level: usize) ?Stage {
    const gameplay = play.Gameplay.init(mode, level) orelse return null;
    return Stage{ .level = level, .gameplay = gameplay };
}

const maxLevel = 3;
pub const Stage = struct {
    level: usize,
    gameplay: play.Gameplay,
    popup: ?popup.Popup = null,

    pub fn update(self: *Stage) ?SequenceData {
        if (self.popup) |*option| {
            const menu = option.update() orelse return null;
            defer option.deinit();
            switch (menu) {
                .title => return .title,
                .reset => return .{ .stage = self.level },
                .next => return .{ .stage = self.level + 1 },
                .quit => self.popup = null,
            }
        }

        const popupType = self.gameplay.update() orelse return null;

        if (popupType == .clear and self.level + 1 == maxLevel)
            self.popup = popup.initWithType(.ending)
        else
            self.popup = popup.initWithType(popupType);

        return null;
    }

    pub fn draw(self: Stage) void {
        self.gameplay.draw();
        if (self.popup) |option| option.draw();
    }

    pub fn deinit(self: *Stage) void {
        if (self.popup) |option| option.deinit();
        self.gameplay.deinit();
    }
};

效果

bomb

总结

实现显示通关界面。

附录

posted @ 2026-08-18 14:36  jiangbo4444  阅读(3)  评论(0)    收藏  举报