merge remote and local changes
This commit is contained in:
@@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
|
||||
|
||||
class Cube
|
||||
{
|
||||
private:
|
||||
|
||||
|
||||
|
||||
public:
|
||||
Cube() = default;
|
||||
};
|
||||
@@ -0,0 +1,553 @@
|
||||
#include <iostream>
|
||||
#include <array>
|
||||
#include <cstdint>
|
||||
<<<<<<< HEAD:src/main.cpp
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
=======
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <thread>
|
||||
#include <chrono>
|
||||
>>>>>>> 777ff96602c52c86f03d612bb4213de746f580a5:src/Apps/Demo/main.cpp
|
||||
#include "Vector2.h"
|
||||
#include "Vector3.h"
|
||||
#include "Vector4.h"
|
||||
#include "Matrix4x4.h"
|
||||
#include "MathUtil.h"
|
||||
#include "Color.h"
|
||||
#include "Triangle.h"
|
||||
#include "Camera.h"
|
||||
#include <cstdlib>
|
||||
#include "Timer.h"
|
||||
#include "Vertex.h"
|
||||
<<<<<<< HEAD:src/main.cpp
|
||||
#include "DepthBuffer.h"
|
||||
#include "SpriteAssetLoader.h"
|
||||
#include "SpriteRasterizer.h"
|
||||
#include "Image.h"
|
||||
#include "TomGameApp.h"
|
||||
#include "AudioInput.h"
|
||||
#include "AudioOutput.h"
|
||||
#include "ButtonInput.h"
|
||||
=======
|
||||
#include "DrawContext.h"
|
||||
#include "test_sprite.h"
|
||||
#include "font_atlas.h"
|
||||
>>>>>>> 777ff96602c52c86f03d612bb4213de746f580a5:src/Apps/Demo/main.cpp
|
||||
|
||||
#include "Display.h"
|
||||
#include "TimeSource.h"
|
||||
#ifdef USE_FRAMEBUFFER
|
||||
#include "FBDisplay.h"
|
||||
#else
|
||||
#include "SDLDisplay.h"
|
||||
#endif
|
||||
|
||||
const int32_t width = 800;
|
||||
const int32_t height = 600;
|
||||
const int32_t tomWidth = 800;
|
||||
const int32_t tomHeight = 480;
|
||||
|
||||
struct ProjectedVertex
|
||||
{
|
||||
Math::Vector3 screen;
|
||||
bool visible = false;
|
||||
};
|
||||
|
||||
struct CubeFace
|
||||
{
|
||||
std::array<int, 4> vertices;
|
||||
};
|
||||
|
||||
struct CubeTriangle
|
||||
{
|
||||
std::array<int, 3> vertices;
|
||||
};
|
||||
|
||||
static ProjectedVertex ProjectToScreen(
|
||||
const Math::Vector3 &vertex,
|
||||
const Math::Matrix4x4 &mvp,
|
||||
const Math::Matrix4x4 &viewport)
|
||||
{
|
||||
using namespace Math;
|
||||
|
||||
const Vector4 clip = mvp * Vector4::Point(vertex);
|
||||
if (std::abs(clip.w) < 1e-5f)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
const float invW = 1.0f / clip.w;
|
||||
const float ndcX = clip.x * invW;
|
||||
const float ndcY = clip.y * invW;
|
||||
const float ndcZ = clip.z * invW;
|
||||
|
||||
if (ndcX < -1.0f || ndcX > 1.0f || ndcY < -1.0f || ndcY > 1.0f || ndcZ < -1.0f || ndcZ > 1.0f)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
const Vector4 screen = viewport * Vector4(ndcX, ndcY, ndcZ, 1.0f);
|
||||
ProjectedVertex result;
|
||||
result.screen = Vector3(screen.x, screen.y, screen.z);
|
||||
result.visible = true;
|
||||
return result;
|
||||
}
|
||||
|
||||
static bool IsFaceVisible(const CubeFace &face, const std::array<Math::Vector3, 8> &viewSpaceVertices)
|
||||
{
|
||||
using namespace Math;
|
||||
|
||||
const Vector3 &v0 = viewSpaceVertices[face.vertices[0]];
|
||||
const Vector3 &v1 = viewSpaceVertices[face.vertices[1]];
|
||||
const Vector3 &v2 = viewSpaceVertices[face.vertices[2]];
|
||||
const Vector3 faceNormal = (v1 - v0).cross(v2 - v0);
|
||||
const Vector3 faceCenter =
|
||||
(viewSpaceVertices[face.vertices[0]] +
|
||||
viewSpaceVertices[face.vertices[1]] +
|
||||
viewSpaceVertices[face.vertices[2]] +
|
||||
viewSpaceVertices[face.vertices[3]]) /
|
||||
4.0f;
|
||||
|
||||
return faceNormal.dot(faceCenter) > 0.0f;
|
||||
}
|
||||
|
||||
static bool IsTriangleVisible(const CubeTriangle &triangle, const std::array<Math::Vector3, 8> &viewSpaceVertices)
|
||||
{
|
||||
using namespace Math;
|
||||
|
||||
const Vector3 &v0 = viewSpaceVertices[triangle.vertices[0]];
|
||||
const Vector3 &v1 = viewSpaceVertices[triangle.vertices[1]];
|
||||
const Vector3 &v2 = viewSpaceVertices[triangle.vertices[2]];
|
||||
const Vector3 faceNormal = (v1 - v0).cross(v2 - v0);
|
||||
const Vector3 faceCenter = (v0 + v1 + v2) / 3.0f;
|
||||
|
||||
return faceNormal.dot(faceCenter) > 0.0f;
|
||||
}
|
||||
|
||||
<<<<<<< HEAD:src/main.cpp
|
||||
static bool HasArg(int argc, char* argv[], const std::string& expected)
|
||||
{
|
||||
for (int i = 1; i < argc; ++i)
|
||||
{
|
||||
if (argv[i] != nullptr && expected == argv[i])
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static std::string FindSpriteAssetPath(const std::string& fileName)
|
||||
{
|
||||
const char* roots[] = {
|
||||
"game/assets/sprites/",
|
||||
"../game/assets/sprites/",
|
||||
"../../game/assets/sprites/",
|
||||
"../../../game/assets/sprites/",
|
||||
"/tmp/game/assets/sprites/",
|
||||
"/usr/local/share/imx6u-game/sprites/"
|
||||
};
|
||||
|
||||
for (size_t i = 0; i < sizeof(roots) / sizeof(roots[0]); ++i)
|
||||
{
|
||||
const std::string path = std::string(roots[i]) + fileName;
|
||||
std::ifstream file(path.c_str(), std::ios::binary);
|
||||
if (file.good())
|
||||
{
|
||||
return path;
|
||||
}
|
||||
}
|
||||
|
||||
return std::string("game/assets/sprites/") + fileName;
|
||||
}
|
||||
|
||||
static bool LoadSpriteAsset(const std::string& fileName, RenderData::Image& image)
|
||||
{
|
||||
const std::string path = FindSpriteAssetPath(fileName);
|
||||
if (!Asset::SpriteAssetLoader::Load(path, image))
|
||||
{
|
||||
std::cerr << "Load sprite asset failed: " << path << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static int RunTomGame()
|
||||
{
|
||||
#ifdef USE_FRAMEBUFFER
|
||||
Platform::IDisplay *display = new Platform::FBDisplay();
|
||||
#else
|
||||
Platform::IDisplay *display = new Platform::SDLDisplay();
|
||||
#endif
|
||||
|
||||
if (!display->init(tomWidth, tomHeight))
|
||||
{
|
||||
delete display;
|
||||
return -1;
|
||||
}
|
||||
|
||||
Core::FrameBuffer frameBuffer(tomWidth, tomHeight);
|
||||
Rasterizer::SpriteRasterizer spriteRasterizer(&frameBuffer);
|
||||
|
||||
RenderData::Image background;
|
||||
RenderData::Image tomStand;
|
||||
RenderData::Image tomListen;
|
||||
RenderData::Image tomSay1;
|
||||
RenderData::Image tomSay2;
|
||||
RenderData::Image tomSay3;
|
||||
RenderData::Image tomSay4;
|
||||
RenderData::Image button;
|
||||
|
||||
if (!LoadSpriteAsset("background.sprite", background) ||
|
||||
!LoadSpriteAsset("Tom-stand.sprite", tomStand) ||
|
||||
!LoadSpriteAsset("Tom-listhen.sprite", tomListen) ||
|
||||
!LoadSpriteAsset("Tom-say1.sprite", tomSay1) ||
|
||||
!LoadSpriteAsset("Tom-say2.sprite", tomSay2) ||
|
||||
!LoadSpriteAsset("Tom-say3.sprite", tomSay3) ||
|
||||
!LoadSpriteAsset("Tom-say4.sprite", tomSay4) ||
|
||||
!LoadSpriteAsset("ui-record.sprite", button))
|
||||
{
|
||||
std::cerr << "Run ConvertTomSprites before starting --tom." << std::endl;
|
||||
display->shutdown();
|
||||
delete display;
|
||||
return -1;
|
||||
}
|
||||
|
||||
Game::AudioInput audioInput;
|
||||
Game::AudioOutput audioOutput;
|
||||
Game::ButtonInput buttonInput;
|
||||
#if defined(__linux__)
|
||||
buttonInput.init();
|
||||
#endif
|
||||
|
||||
Game::TomGameAssets assets;
|
||||
assets.background = &background;
|
||||
assets.tomStand = &tomStand;
|
||||
assets.tomListen = &tomListen;
|
||||
assets.tomSay1 = &tomSay1;
|
||||
assets.tomSay2 = &tomSay2;
|
||||
assets.tomSay3 = &tomSay3;
|
||||
assets.tomSay4 = &tomSay4;
|
||||
assets.button = &button;
|
||||
|
||||
Game::TomGameApp app(&frameBuffer, &spriteRasterizer, &audioInput, &audioOutput, &buttonInput);
|
||||
app.set_assets(assets);
|
||||
if (!app.is_ready())
|
||||
{
|
||||
std::cerr << "TomGameApp assets are incomplete." << std::endl;
|
||||
display->shutdown();
|
||||
delete display;
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool isRunning = true;
|
||||
uint32_t lastTime = display->get_time_ms();
|
||||
while (isRunning)
|
||||
{
|
||||
display->poll_events(isRunning);
|
||||
const uint32_t currentTime = display->get_time_ms();
|
||||
const float deltaTime = static_cast<float>(currentTime - lastTime) * 0.001f;
|
||||
lastTime = currentTime;
|
||||
|
||||
app.update(deltaTime);
|
||||
frameBuffer.clear(RenderData::Color(18, 18, 24, 255));
|
||||
app.draw();
|
||||
display->present(&frameBuffer);
|
||||
}
|
||||
|
||||
buttonInput.shutdown();
|
||||
audioInput.shutdown();
|
||||
audioOutput.shutdown();
|
||||
display->shutdown();
|
||||
delete display;
|
||||
return 0;
|
||||
=======
|
||||
static void PrintUsage(const char *program_name)
|
||||
{
|
||||
std::cout
|
||||
<< "Usage: " << program_name << " [--fps 30|45|60]\n"
|
||||
<< " " << program_name << " [--fps=30|45|60]\n";
|
||||
}
|
||||
|
||||
struct ProgramOptions
|
||||
{
|
||||
uint32_t target_fps;
|
||||
bool show_help;
|
||||
|
||||
ProgramOptions()
|
||||
: target_fps(Core::Timer::DefaultFps),
|
||||
show_help(false)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
static ProgramOptions ParseProgramOptions(int argc, char *argv[])
|
||||
{
|
||||
ProgramOptions options;
|
||||
|
||||
for (int i = 1; i < argc; ++i)
|
||||
{
|
||||
const char *arg = argv[i];
|
||||
const char *fps_value = nullptr;
|
||||
|
||||
if (std::strcmp(arg, "--help") == 0 || std::strcmp(arg, "-h") == 0)
|
||||
{
|
||||
options.show_help = true;
|
||||
return options;
|
||||
}
|
||||
else if (std::strcmp(arg, "--fps") == 0)
|
||||
{
|
||||
if (i + 1 < argc)
|
||||
{
|
||||
fps_value = argv[++i];
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cerr << "Missing value for --fps, falling back to 30. Supported: 30, 45, 60.\n";
|
||||
}
|
||||
}
|
||||
else if (std::strncmp(arg, "--fps=", 6) == 0)
|
||||
{
|
||||
fps_value = arg + 6;
|
||||
}
|
||||
|
||||
if (fps_value != nullptr)
|
||||
{
|
||||
const uint32_t parsed_fps = static_cast<uint32_t>(std::strtoul(fps_value, nullptr, 10));
|
||||
if (Core::Timer::is_supported_fps(parsed_fps))
|
||||
{
|
||||
options.target_fps = parsed_fps;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cerr << "Unsupported FPS '" << fps_value << "', falling back to 30. Supported: 30, 45, 60.\n";
|
||||
options.target_fps = Core::Timer::DefaultFps;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return options;
|
||||
}
|
||||
|
||||
static void SleepRemainingFrameTime(const Core::Timer &timer, const Platform::ITimeSource &time_source)
|
||||
{
|
||||
const uint32_t sleep_ms = timer.remaining_frame_ms(time_source.get_time_ms());
|
||||
if (sleep_ms > 0u)
|
||||
{
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(sleep_ms));
|
||||
}
|
||||
>>>>>>> 777ff96602c52c86f03d612bb4213de746f580a5:src/Apps/Demo/main.cpp
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
<<<<<<< HEAD:src/main.cpp
|
||||
if (HasArg(argc, argv, "--tom"))
|
||||
{
|
||||
return RunTomGame();
|
||||
}
|
||||
=======
|
||||
const ProgramOptions options = ParseProgramOptions(argc, argv);
|
||||
if (options.show_help)
|
||||
{
|
||||
PrintUsage(argv[0]);
|
||||
return 0;
|
||||
}
|
||||
Core::Timer timer(options.target_fps);
|
||||
Platform::SteadyTimeSource time_source;
|
||||
>>>>>>> 777ff96602c52c86f03d612bb4213de746f580a5:src/Apps/Demo/main.cpp
|
||||
|
||||
#ifdef USE_FRAMEBUFFER
|
||||
Platform::IDisplay *display = new Platform::FBDisplay();
|
||||
#else
|
||||
Platform::IDisplay *display = new Platform::SDLDisplay();
|
||||
#endif
|
||||
|
||||
if (!display->init(width, height))
|
||||
{
|
||||
delete display;
|
||||
return -1;
|
||||
}
|
||||
|
||||
Gfx::DrawContext ctx(width, height);
|
||||
std::cout << "Target FPS: " << timer.target_fps() << std::endl;
|
||||
|
||||
RenderData::BitmapFont font;
|
||||
font.atlas = RenderData::Image(font_atlas_pixels, font_atlas_width, font_atlas_height);
|
||||
font.char_w = font_char_w;
|
||||
font.char_h = font_char_h;
|
||||
font.columns = font_columns;
|
||||
font.first_char = font_first_char;
|
||||
|
||||
RenderData::Image sprite_img(test_sprite_pixels, test_sprite_width, test_sprite_height, 0x00000000);
|
||||
RenderData::SpriteRegion sprite_region(&sprite_img, 0, 0, sprite_img.width, sprite_img.height);
|
||||
|
||||
const std::array<uint16_t, 8 * 4> tileIds = {
|
||||
0, RenderData::Tilemap::EmptyTile, 0, RenderData::Tilemap::EmptyTile, 0, RenderData::Tilemap::EmptyTile, 0, RenderData::Tilemap::EmptyTile,
|
||||
RenderData::Tilemap::EmptyTile, 0, RenderData::Tilemap::EmptyTile, 0, RenderData::Tilemap::EmptyTile, 0, RenderData::Tilemap::EmptyTile, 0,
|
||||
0, RenderData::Tilemap::EmptyTile, 0, RenderData::Tilemap::EmptyTile, 0, RenderData::Tilemap::EmptyTile, 0, RenderData::Tilemap::EmptyTile,
|
||||
RenderData::Tilemap::EmptyTile, 0, RenderData::Tilemap::EmptyTile, 0, RenderData::Tilemap::EmptyTile, 0, RenderData::Tilemap::EmptyTile, 0};
|
||||
RenderData::Tilemap testTilemap(tileIds.data(), 8, 4, &sprite_img, sprite_img.width, sprite_img.height, 1);
|
||||
|
||||
Scene::Camera camera;
|
||||
camera.transform.position = Math::Vector3(0.0f, 0.0f, 3.0f);
|
||||
camera.transform.rotation = Math::Vector3(0.0f, 3.1415926535f, 0.0f);
|
||||
|
||||
const std::array<Math::Vector3, 8> cubeVertices = {
|
||||
Math::Vector3(-0.5f, -0.5f, -0.5f),
|
||||
Math::Vector3(0.5f, -0.5f, -0.5f),
|
||||
Math::Vector3(0.5f, 0.5f, -0.5f),
|
||||
Math::Vector3(-0.5f, 0.5f, -0.5f),
|
||||
Math::Vector3(-0.5f, -0.5f, 0.5f),
|
||||
Math::Vector3(0.5f, -0.5f, 0.5f),
|
||||
Math::Vector3(0.5f, 0.5f, 0.5f),
|
||||
Math::Vector3(-0.5f, 0.5f, 0.5f)};
|
||||
|
||||
const std::array<CubeFace, 6> cubeFaces = {
|
||||
CubeFace{{0, 3, 2, 1}},
|
||||
CubeFace{{4, 5, 6, 7}},
|
||||
CubeFace{{0, 4, 7, 3}},
|
||||
CubeFace{{1, 2, 6, 5}},
|
||||
CubeFace{{0, 1, 5, 4}},
|
||||
CubeFace{{3, 7, 6, 2}}};
|
||||
const std::array<CubeTriangle, 12> cubeTriangles = {
|
||||
CubeTriangle{{0, 3, 2}}, CubeTriangle{{0, 2, 1}},
|
||||
CubeTriangle{{4, 5, 6}}, CubeTriangle{{4, 6, 7}},
|
||||
CubeTriangle{{0, 4, 7}}, CubeTriangle{{0, 7, 3}},
|
||||
CubeTriangle{{1, 2, 6}}, CubeTriangle{{1, 6, 5}},
|
||||
CubeTriangle{{0, 1, 5}}, CubeTriangle{{0, 5, 4}},
|
||||
CubeTriangle{{3, 7, 6}}, CubeTriangle{{3, 6, 2}}};
|
||||
|
||||
const RenderData::Color clearColor(18, 18, 24, 255);
|
||||
const RenderData::Color cubeColor(240, 240, 240, 255);
|
||||
const RenderData::Color fpsColor(0, 255, 80, 255);
|
||||
const RenderData::Color fpsBg(0, 0, 0, 200);
|
||||
const float aspectRatio = static_cast<float>(width) / static_cast<float>(height);
|
||||
|
||||
int32_t fps = 0;
|
||||
int32_t frame_count = 0;
|
||||
uint32_t last_fps_time = 0;
|
||||
char fps_text[32];
|
||||
|
||||
bool isRunning = true;
|
||||
uint32_t animation_time_ms = 0;
|
||||
while (isRunning)
|
||||
{
|
||||
timer.begin_frame(time_source.get_time_ms());
|
||||
const uint32_t fixed_delta_ms = timer.fixed_delta_ms();
|
||||
animation_time_ms += fixed_delta_ms;
|
||||
|
||||
display->poll_events(isRunning);
|
||||
|
||||
ctx.clear(clearColor);
|
||||
|
||||
const float animation_time = static_cast<float>(animation_time_ms) / 1000.0f;
|
||||
const Math::Matrix4x4 model =
|
||||
Math::MathUtil::get_rotation_matrix_y(animation_time) *
|
||||
Math::MathUtil::get_rotation_matrix_x(static_cast<float>(animation_time_ms * 6u) / 10000.0f);
|
||||
const Math::Matrix4x4 view = camera.get_view_matrix();
|
||||
const Math::Matrix4x4 modelView = view * model;
|
||||
const Math::Matrix4x4 projection = camera.get_perspective_projection_matrix(aspectRatio);
|
||||
const Math::Matrix4x4 viewport = camera.get_viewport_matrix(static_cast<float>(width), static_cast<float>(height));
|
||||
const Math::Matrix4x4 mvp = projection * modelView;
|
||||
|
||||
std::array<Math::Vector3, 8> viewSpaceVertices;
|
||||
std::array<ProjectedVertex, 8> projectedVertices;
|
||||
for (size_t i = 0; i < cubeVertices.size(); ++i)
|
||||
{
|
||||
viewSpaceVertices[i] = (modelView * Math::Vector4::Point(cubeVertices[i])).to_vector3();
|
||||
projectedVertices[i] = ProjectToScreen(cubeVertices[i], mvp, viewport);
|
||||
}
|
||||
|
||||
std::array<bool, 6> visibleFaces = {};
|
||||
for (size_t faceIndex = 0; faceIndex < cubeFaces.size(); ++faceIndex)
|
||||
{
|
||||
visibleFaces[faceIndex] = IsFaceVisible(cubeFaces[faceIndex], viewSpaceVertices);
|
||||
}
|
||||
|
||||
std::array<RenderData::Triangle, 12> drawTriangles;
|
||||
size_t drawCommandCount = 0;
|
||||
for (const CubeTriangle &cubeTriangle : cubeTriangles)
|
||||
{
|
||||
if (!IsTriangleVisible(cubeTriangle, viewSpaceVertices))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
const ProjectedVertex &v0 = projectedVertices[cubeTriangle.vertices[0]];
|
||||
const ProjectedVertex &v1 = projectedVertices[cubeTriangle.vertices[1]];
|
||||
const ProjectedVertex &v2 = projectedVertices[cubeTriangle.vertices[2]];
|
||||
if (!v0.visible || !v1.visible || !v2.visible)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
drawTriangles[drawCommandCount++] =
|
||||
RenderData::Triangle(
|
||||
Scene::Vertex(v0.screen),
|
||||
Scene::Vertex(v1.screen),
|
||||
Scene::Vertex(v2.screen));
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < drawCommandCount; ++i)
|
||||
{
|
||||
ctx.draw_triangle(drawTriangles[i], cubeColor);
|
||||
}
|
||||
|
||||
for (size_t faceIndex = 0; faceIndex < cubeFaces.size(); ++faceIndex)
|
||||
{
|
||||
if (!visibleFaces[faceIndex])
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
const CubeFace &face = cubeFaces[faceIndex];
|
||||
for (size_t edgeOffset = 0; edgeOffset < face.vertices.size(); ++edgeOffset)
|
||||
{
|
||||
const int startIndex = face.vertices[edgeOffset];
|
||||
const int endIndex = face.vertices[(edgeOffset + 1) % face.vertices.size()];
|
||||
const ProjectedVertex &start = projectedVertices[startIndex];
|
||||
const ProjectedVertex &end = projectedVertices[endIndex];
|
||||
if (!start.visible || !end.visible)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
ctx.draw_line(
|
||||
Math::Vector2(start.screen.x, start.screen.y).to_vector2Int(),
|
||||
Math::Vector2(end.screen.x, end.screen.y).to_vector2Int(),
|
||||
clearColor);
|
||||
}
|
||||
}
|
||||
|
||||
// sprite 测试
|
||||
ctx.draw_sprite(10, 10, sprite_img);
|
||||
ctx.draw_sprite_region_ex(30, 10, sprite_region, 2, false, false);
|
||||
ctx.draw_sprite_region_ex(10, 30, sprite_region, 3, true, false);
|
||||
ctx.draw_tilemap(testTilemap, 650, 500, 96, 48, static_cast<int32_t>(animation_time_ms / 20u) % 32, 0);
|
||||
|
||||
// FPS 计数
|
||||
++frame_count;
|
||||
const uint32_t now = time_source.get_time_ms();
|
||||
if (now - last_fps_time >= 1000)
|
||||
{
|
||||
fps = frame_count;
|
||||
frame_count = 0;
|
||||
last_fps_time = now;
|
||||
}
|
||||
std::snprintf(fps_text, sizeof(fps_text), "FPS: %d", fps);
|
||||
ctx.draw_text(font, 4, 4, fpsColor, fpsBg, fps_text);
|
||||
|
||||
ctx.present(display);
|
||||
SleepRemainingFrameTime(timer, time_source);
|
||||
}
|
||||
|
||||
display->shutdown();
|
||||
delete display;
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user