跳到主要内容

快速开始

本指南将带你克隆运行时、编译它,并使用真实的 GPU 后端将一个 .riv 文件显示到屏幕上。

前提条件

  • 支持 C++17 的较新版本 clangMSVC
  • git — 构建脚本会自行克隆并引导 premake5
  • 你所选择渲染器对应的平台 SDK(用于 D3D 的 Windows SDK、用于 Metal 的 Xcode、用于 Vulkan 的 Vulkan SDK 等)。

Rive 使用 clang vector builtins。使用 clang 构建时,请使用可用的最新版本 — 较旧的工具链可能无法编译渲染器。

1. 克隆并构建运行时

git clone https://github.com/rive-app/rive-runtime.git
cd rive-runtime/renderer

运行时随附了一个构建辅助脚本 build/build_rive.sh(Windows 上有 PowerShell 包装脚本 build_rive.ps1)。它会在首次运行时安装固定版本的 premake5,并根据你的平台分发到正确的构建系统 (macOS/Linux 上的 gmake2、Windows 上的 MSBuild 等)。

macOS / Linux:

../build/build_rive.sh release

Windows:

..\build\build_rive.ps1 release

常见变体:

  • build_rive.sh(无参数)— 为宿主平台进行 debug 构建。
  • build_rive.sh release clean — 清理后重新构建。
  • build_rive.sh ninja release — 使用 Ninja 而不是 make。
  • build_rive.sh ios release / build_rive.sh android release — 交叉编译。

构建产物位于 out/release/(或 out/debug/)。你需要链接 librive.a(Windows 上为 rive.lib),以及各后端渲染器库,例如 librive_pls_renderer.a

2. 将头文件添加到你的项目

公共 include 根目录为:

rive-runtime/include            # rive-cpp core
rive-runtime/renderer/include # GPU renderer (only if you use rive::gpu)

一个最小 CMake 片段:

target_include_directories(my_app PRIVATE
${RIVE}/include
${RIVE}/renderer/include
)

target_link_libraries(my_app PRIVATE
rive
rive_pls_renderer
# plus your backend, e.g. d3d11, dxgi on Windows
)

3. 加载 .riv 文件

#include "rive/file.hpp"
#include <fstream>
#include <iterator>
#include <vector>

using namespace rive;

std::vector<uint8_t> readFile(const char* path) {
std::ifstream in(path, std::ios::binary);
return {std::istreambuf_iterator<char>(in), {}};
}

// `factory` is a Factory* — usually your RenderContext (which inherits Factory).
auto bytes = readFile("hero.riv");

ImportResult result;
rcp<File> file = File::import(bytes, factory, &result);
if (!file || result != ImportResult::success) {
// Bad file or unsupported version.
return;
}

4. 选择 Artboard 和 State Machine

#include "rive/artboard.hpp"
#include "rive/animation/state_machine_instance.hpp"

std::unique_ptr<ArtboardInstance> artboard = file->artboardDefault();

std::unique_ptr<StateMachineInstance> sm = artboard->defaultStateMachine();
if (!sm && artboard->stateMachineCount() > 0) {
sm = artboard->stateMachineAt(0);
}

5. Advance 并绘制

渲染循环每帧包含三个阶段:advancedrawflush

#include "rive/renderer/rive_renderer.hpp"
#include "rive/renderer/render_context.hpp"

void renderFrame(float dt) {
sm->advanceAndApply(dt);

RenderContext::FrameDescriptor frame{};
frame.renderTargetWidth = windowWidth;
frame.renderTargetHeight = windowHeight;
frame.clearColor = 0xff202020; // ARGB
renderContext->beginFrame(frame);

RiveRenderer renderer(renderContext.get());
renderer.save();
renderer.align(Fit::contain,
Alignment::center,
AABB(0, 0, windowWidth, windowHeight),
artboard->bounds());
sm->draw(&renderer);
renderer.restore();

RenderContext::FlushResources flush{};
flush.renderTarget = renderTarget.get();
renderContext->flush(flush);
}
💡

advanceAndApply 使用固定时间步长(例如 1/120s),并累计真实经过时间。在固定步长下,状态机是确定性的,这能让播放在不同机器和帧率上保持可复现。参见 Rendering Loop

6. 转发输入

将指针事件路由回状态机,以便监听器和命中测试能够正常工作:

#include "rive/renderer.hpp"

Mat2D align = computeAlignment(Fit::contain,
Alignment::center,
AABB(0, 0, w, h),
artboard->bounds());

Vec2D toArtboard(int x, int y) {
return align.invertOrIdentity() * Vec2D{(float)x, (float)y};
}

sm->pointerMove(toArtboard(mouseX, mouseY));
sm->pointerDown(toArtboard(mouseX, mouseY));
sm->pointerUp(toArtboard(mouseX, mouseY));

接下来