小游戏和GUI编程(3) | 基于 SFML 的字符阵

2024-02-10 18:28
文章标签 编程 字符 gui 小游戏 sfml

本文主要是介绍小游戏和GUI编程(3) | 基于 SFML 的字符阵,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

小游戏和GUI编程(3) | 基于 SFML 的字符阵

1. 简介

使用 EasyX 图形库时, 官方第一个例子是字符阵。 EasyX 不开源, 也不能跨平台, API 陈旧, API 是 C 而不是 C++。 现在使用 SFML 来实现字符阵, 克服 EasyX 的这些问题。

SFML 的 API 不如 EasyX 那么简单, 稍微复杂是因为功能更强大。 主要关注这么几个功能点: 使用 SFML 时怎样渲染文字? 怎样更新屏幕来营造字符阵的效果?

SFML 版本为 2.6.1, 原始的 EasyX 代码在这里 char-matrix, 对应的 raylib 代码在这里.

2. SFML 绘制文字

2.1 加载字体

需要先加载字体, SFML 不会扫描系统字体, 传入的是字体文件的路径。

使用 sf::Font 类, 主要用它的 loadFromFile() 函数。

    sf::Font font;const std::string asset_dir = "../Resources";if (!font.loadFromFile(asset_dir + "/SourceHanSansCN-Regular.otf")){printf("Error: font not found\n");return 1;}

2.2 绘制文字

使用 sf::Text 类, 它继承自 Drawable 类和 Transformable 类, 因此可以使用

class SFML_GRAPHICS_API Text : public Drawable, public Transformable
{
public:void setFont(const Font& font); // 设置字体void setString(const String& string); // 设置文本内容void setCharacterSize(unsigned int size); // 设置字符大小void setFillColor(const Color& color); // 设置字体颜色...
};class SFML_GRAPHICS_API Transformable
{
public:void setPosition(float x, float y); // 设置位置...
};

根据上述 api, 能够创建 “Hello World” 的文本, 设置它为绿色, 在屏幕中央显示:

在这里插入图片描述

关键代码

        window.clear();// draw the matrix heresf::Text text;text.setFont(font);text.setString("Hello, World");text.setCharacterSize(42); // in pixelstext.setFillColor(sf::Color::Green);sf::FloatRect bbox = text.getGlobalBounds();text.setPosition(win_width / 2 - bbox.width/2, win_height / 2 - bbox.height/2);window.draw(text);window.display();

3. 字符阵列

这一小节, 分析字符阵列的原理, 然后在前一节的基础绘制代码基础上进行实现。

3.1 在随机位置显示三个随机字母

int x = (rand() % 80) * 8;  // [0, 640] 范围内的随机数, 间距是8
int y = (rand() % 20) * 24; // [0, 480] 范围内的随机数, 间距是24
int c = (rand() % 26) + 'a'; // [97, 122] 范围内的随机数, 也就是随机小写字母
sf::Text text;
text.setFont(font);
text.setString(std::string(1, c));
text.setCharacterSize(26); // in pixels
text.setFillColor(sf::Color::Green);
text.setPosition(x, y);
window.draw(text);

3.2 擦除一个像素行

通过绘制一个和背景颜色一样(黑色)的矩形来做到。

// 画线, 擦掉一个像素行
sf::RectangleShape line(sf::Vector2f(win_width, 2));
line.setFillColor(sf::Color::Black);
line.setPosition(0, line_index);
line_index = (line_index + 1) % win_height; // line_index 初始值为0
window.draw(line);

其中 RectangleShape 类继承自 Shape 类, 因此能调用 setFillColor(), setPosition() 等函数:

class SFML_GRAPHICS_API RectangleShape : public Shape
{...
};

3.3 确保擦除效果

和常规不一样的地方是, 需要保持前一帧的绘制内容。

因此需要去掉 window.clear() 的调用。

3.4 完整代码和效果

#include <SFML/Graphics.hpp>int main()
{constexpr int win_width = 640;constexpr int win_height = 480;sf::VideoMode videomode(win_width, win_height);const std::string title = "Char Matrix SFML";sf::RenderWindow window(videomode, title);window.setFramerateLimit(60);sf::Font font;const std::string asset_dir = "../Resources";if (!font.loadFromFile(asset_dir + "/Courier-12.ttf")){printf("Error: font not found\n");return 1;}int line_index = 0;srand((unsigned)time(NULL));while (window.isOpen()){sf::Event event;while (window.pollEvent(event)){if (event.type == sf::Event::Closed) { window.close(); }}// draw the matrix hereif (0){window.clear();sf::Text text;text.setFont(font);text.setString("Hello, World");text.setCharacterSize(42); // in pixelstext.setFillColor(sf::Color::Green);sf::FloatRect bbox = text.getGlobalBounds();text.setPosition(win_width / 2 - bbox.width/2, win_height / 2 - bbox.height/2);window.draw(text);}if (1){ for (int i = 0; i < 3; i++){int x = (rand() % 80) * 8;  // [0, 640] 范围内的随机数, 间距是8int y = (rand() % 20) * 24; // [0, 480] 范围内的随机数, 间距是24int c = (rand() % 26) + 'a'; // [97, 122] 范围内的随机数, 也就是随机小写字母sf::Text text;text.setFont(font);text.setString(std::string(1, c));text.setCharacterSize(26); // in pixelstext.setFillColor(sf::Color::Green);text.setPosition(x, y);window.draw(text);}// 画线, 擦掉一个像素行sf::RectangleShape line(sf::Vector2f(win_width, 2));line.setFillColor(sf::Color::Black);line.setPosition(0, line_index);line_index = (line_index + 1) % win_height;window.draw(line);}window.display();}return 0;
}

在这里插入图片描述

4. 总结

通过查看 SFML 文档, 把字符阵的代码翻译到了基于 SFML 的实现, 关键 API 如下:

  • sf::Font::loadFromFile("xxx.ttf") 加载字体
  • sf::Text 类, 用于设置字体
  • sf::RectangleShape 类, 用于绘制单行矩形
  • 临时移除了 window.clear() 的调用

References

  • https://www.sfml-dev.org/tutorials/2.6/graphics-text.php
  • https://docs.easyx.cn/zh-cn/char-matrix
  • https://www.cnblogs.com/zjutzz/p/17067313.html

这篇关于小游戏和GUI编程(3) | 基于 SFML 的字符阵的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/697786

相关文章

揭秘Python Socket网络编程的7种硬核用法

《揭秘PythonSocket网络编程的7种硬核用法》Socket不仅能做聊天室,还能干一大堆硬核操作,这篇文章就带大家看看Python网络编程的7种超实用玩法,感兴趣的小伙伴可以跟随小编一起... 目录1.端口扫描器:探测开放端口2.简易 HTTP 服务器:10 秒搭个网页3.局域网游戏:多人联机对战4.

Java并发编程必备之Synchronized关键字深入解析

《Java并发编程必备之Synchronized关键字深入解析》本文我们深入探索了Java中的Synchronized关键字,包括其互斥性和可重入性的特性,文章详细介绍了Synchronized的三种... 目录一、前言二、Synchronized关键字2.1 Synchronized的特性1. 互斥2.

Python GUI框架中的PyQt详解

《PythonGUI框架中的PyQt详解》PyQt是Python语言中最强大且广泛应用的GUI框架之一,基于Qt库的Python绑定实现,本文将深入解析PyQt的核心模块,并通过代码示例展示其应用场... 目录一、PyQt核心模块概览二、核心模块详解与示例1. QtCore - 核心基础模块2. QtWid

Python异步编程中asyncio.gather的并发控制详解

《Python异步编程中asyncio.gather的并发控制详解》在Python异步编程生态中,asyncio.gather是并发任务调度的核心工具,本文将通过实际场景和代码示例,展示如何结合信号量... 目录一、asyncio.gather的原始行为解析二、信号量控制法:给并发装上"节流阀"三、进阶控制

C语言字符函数和字符串函数示例详解

《C语言字符函数和字符串函数示例详解》本文详细介绍了C语言中字符分类函数、字符转换函数及字符串操作函数的使用方法,并通过示例代码展示了如何实现这些功能,通过这些内容,读者可以深入理解并掌握C语言中的字... 目录一、字符分类函数二、字符转换函数三、strlen的使用和模拟实现3.1strlen函数3.2st

C# string转unicode字符的实现

《C#string转unicode字符的实现》本文主要介绍了C#string转unicode字符的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随... 目录1. 获取字符串中每个字符的 Unicode 值示例代码:输出:2. 将 Unicode 值格式化

C#多线程编程中导致死锁的常见陷阱和避免方法

《C#多线程编程中导致死锁的常见陷阱和避免方法》在C#多线程编程中,死锁(Deadlock)是一种常见的、令人头疼的错误,死锁通常发生在多个线程试图获取多个资源的锁时,导致相互等待对方释放资源,最终形... 目录引言1. 什么是死锁?死锁的典型条件:2. 导致死锁的常见原因2.1 锁的顺序问题错误示例:不同

PyCharm接入DeepSeek实现AI编程的操作流程

《PyCharm接入DeepSeek实现AI编程的操作流程》DeepSeek是一家专注于人工智能技术研发的公司,致力于开发高性能、低成本的AI模型,接下来,我们把DeepSeek接入到PyCharm中... 目录引言效果演示创建API key在PyCharm中下载Continue插件配置Continue引言

Java 字符数组转字符串的常用方法

《Java字符数组转字符串的常用方法》文章总结了在Java中将字符数组转换为字符串的几种常用方法,包括使用String构造函数、String.valueOf()方法、StringBuilder以及A... 目录1. 使用String构造函数1.1 基本转换方法1.2 注意事项2. 使用String.valu

Go语言使用Buffer实现高性能处理字节和字符

《Go语言使用Buffer实现高性能处理字节和字符》在Go中,bytes.Buffer是一个非常高效的类型,用于处理字节数据的读写操作,本文将详细介绍一下如何使用Buffer实现高性能处理字节和... 目录1. bytes.Buffer 的基本用法1.1. 创建和初始化 Buffer1.2. 使用 Writ