Console Library 8.0.0
A header-only library that makes C++ simple
Loading...
Searching...
No Matches
screen.h
Go to the documentation of this file.
1
8
9/*
10Copyright (c) 2026 MrXie1109
11
12Permission is hereby granted, free of charge, to any person obtaining a copy
13of this software and associated documentation files (the "Software"), to deal
14in the Software without restriction, including without limitation the rights
15to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
16copies of the Software, and to permit persons to whom the Software is
17furnished to do so, subject to the following conditions:
18
19The above copyright notice and this permission notice shall be included in all
20copies or substantial portions of the Software.
21
22THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28SOFTWARE.
29*/
30
31#pragma once
32#include <array>
33#include <cmath>
34#include <cstdlib>
35#include <iostream>
36#include <string>
37#include <utility>
38
39namespace console {
47 template <unsigned COLS, unsigned ROWS>
48 class Screen {
50 static_assert(COLS % 2 == 0, "COLS must be a multiple of 2!");
52 static_assert(ROWS % 4 == 0, "ROWS must be a multiple of 4!");
53
54 std::array<std::array<unsigned char, COLS / 2>, ROWS / 4>
56
57 public:
59 Screen() : masks() {}
60
67 void point(unsigned x, unsigned y, bool on = true) {
68 if (x >= COLS || y >= ROWS) return;
69 unsigned braille_col = x / 2;
70 unsigned braille_row = y / 4;
71 unsigned sub_x = x % 2;
72 unsigned sub_y = y % 4;
73 static const unsigned char mapping[2][4]
74 = {{0, 1, 2, 6}, {3, 4, 5, 7}};
75 unsigned char bit = 1 << mapping[sub_x][sub_y];
76 if (on)
77 masks[braille_row][braille_col] |= bit;
78 else
79 masks[braille_row][braille_col] &= ~bit;
80 }
81
91 void line(int x0, int y0, int x1, int y1, bool on = true) {
92 int dx = std::abs(x1 - x0);
93 int dy = -std::abs(y1 - y0);
94 int sx = x0 < x1 ? 1 : -1;
95 int sy = y0 < y1 ? 1 : -1;
96 int err = dx + dy;
97 while (true) {
98 point(x0, y0, on);
99 if (x0 == x1 && y0 == y1) break;
100 int e2 = 2 * err;
101 if (e2 >= dy) err += dy, x0 += sx;
102 if (e2 <= dx) err += dx, y0 += sy;
103 }
104 }
105
115 void rect(int x0, int y0, int x1, int y1, bool on = true) {
116 line(x0, y0, x1, y0, on);
117 line(x1, y0, x1, y1, on);
118 line(x1, y1, x0, y1, on);
119 line(x0, y1, x0, y0, on);
120 }
121
131 void fillRect(int x0, int y0, int x1, int y1, bool on = true) {
132 if (x0 > x1) std::swap(x0, x1);
133 if (y0 > y1) std::swap(y0, y1);
134 for (int y = y0; y <= y1; ++y)
135 for (int x = x0; x <= x1; ++x) point(x, y, on);
136 }
137
146 void circle(int cx, int cy, int r, bool on = true) {
147 int x = 0, y = r;
148 int d = 3 - 2 * r;
149 while (x <= y) {
150 point(cx + x, cy + y, on);
151 point(cx - x, cy + y, on);
152 point(cx + x, cy - y, on);
153 point(cx - x, cy - y, on);
154 point(cx + y, cy + x, on);
155 point(cx - y, cy + x, on);
156 point(cx + y, cy - x, on);
157 point(cx - y, cy - x, on);
158 if (d < 0)
159 d = d + 4 * x + 6;
160 else
161 d = d + 4 * (x - y) + 10, y--;
162 x++;
163 }
164 }
165
174 void fillCircle(int cx, int cy, int r, bool on = true) {
175 int x = 0, y = r;
176 int d = 3 - 2 * r;
177 while (x <= y) {
178 for (int i = cx - x; i <= cx + x; ++i) {
179 point(i, cy + y, on);
180 point(i, cy - y, on);
181 }
182 for (int i = cx - y; i <= cx + y; ++i) {
183 point(i, cy + x, on);
184 point(i, cy - x, on);
185 }
186
187 if (d < 0) {
188 d += 4 * x + 6;
189 } else {
190 d += 4 * (x - y) + 10;
191 y--;
192 }
193 x++;
194 }
195 }
196
198 void clear() {
199 for (auto &row : masks)
200 for (auto &cell : row) cell = 0;
201 }
202
212 template <class CharT, class Traits = std::char_traits<CharT>>
213 void update(std::basic_ostream<CharT, Traits> &os = std::cout,
214 bool clear = false) const {
215 if (clear) {
216 os << "\033[2J";
217 }
218 std::string out;
219 out.reserve((ROWS / 4) * (COLS / 2 * 3 + 1));
220 for (unsigned row = 0; row < ROWS / 4; ++row) {
221 for (unsigned col = 0; col < COLS / 2; ++col) {
222 unsigned int code = 0x2800 + masks[row][col];
223 out += static_cast<char>(0xE0 | (code >> 12));
224 out += static_cast<char>(0x80 | ((code >> 6) & 0x3F));
225 out += static_cast<char>(0x80 | (code & 0x3F));
226 }
227 out += '\n';
228 }
229 os << "\033[H" << out.c_str() << std::flush;
230 }
231 };
232}
void point(unsigned x, unsigned y, bool on=true)
在屏幕上绘制一个点。
Definition screen.h:67
void update(std::basic_ostream< CharT, Traits > &os=std::cout, bool clear=false) const
将 Screen 存储的虚拟屏幕输出到指定流。
Definition screen.h:213
std::array< std::array< unsigned char, COLS/2 >, ROWS/4 > masks
列数必须是 2 的倍数。
Definition screen.h:55
void circle(int cx, int cy, int r, bool on=true)
在屏幕上绘制空心圆。
Definition screen.h:146
void fillRect(int x0, int y0, int x1, int y1, bool on=true)
在屏幕上绘制实心矩形。
Definition screen.h:131
void rect(int x0, int y0, int x1, int y1, bool on=true)
在屏幕上绘制空心矩形。
Definition screen.h:115
void line(int x0, int y0, int x1, int y1, bool on=true)
在屏幕上绘制一条直线。
Definition screen.h:91
void clear()
清空屏幕。
Definition screen.h:198
Screen()
默认构造函数,构造一个空白的 Screen
Definition screen.h:59
void fillCircle(int cx, int cy, int r, bool on=true)
在屏幕上绘制实心圆。
Definition screen.h:174
本库所有组件所在的顶层命名空间。