Actual font rendering support
This commit is contained in:
parent
50a5fc6985
commit
fa8d09d504
@ -3,4 +3,6 @@ import 'package:flutter/material.dart';
|
|||||||
class Palette {
|
class Palette {
|
||||||
static const defaultBg = Colors.black;
|
static const defaultBg = Colors.black;
|
||||||
static const defaultFg = Colors.white;
|
static const defaultFg = Colors.white;
|
||||||
|
|
||||||
|
static const subtitle = Colors.yellow;
|
||||||
}
|
}
|
||||||
|
12
lib/game.dart
Normal file
12
lib/game.dart
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
import 'package:dartterm/colors.dart';
|
||||||
|
import 'package:dartterm/terminal.dart';
|
||||||
|
|
||||||
|
void main() async {
|
||||||
|
at(0, 0).puts("Hello, bats!");
|
||||||
|
at(0, 2).fg(Palette.subtitle).small().puts("Beware of the bat!");
|
||||||
|
at(4, 4)
|
||||||
|
.bg(Palette.subtitle)
|
||||||
|
.fg(Palette.defaultBg)
|
||||||
|
.big()
|
||||||
|
.puts("BEWARE OF THE BAT!");
|
||||||
|
}
|
@ -1,9 +1,11 @@
|
|||||||
import 'package:dartterm/colors.dart';
|
import 'package:dartterm/colors.dart';
|
||||||
import 'package:dartterm/terminal.dart';
|
import 'package:dartterm/game.dart' as game;
|
||||||
|
import 'package:dartterm/terminal.dart' as terminal;
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/scheduler.dart';
|
import 'package:flutter/scheduler.dart';
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
|
// terminal.at(0, 0).puts("Hello, world!");
|
||||||
runApp(const App());
|
runApp(const App());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -41,6 +43,7 @@ class _ViewerState extends State<Viewer> {
|
|||||||
super.initState();
|
super.initState();
|
||||||
ticker = Ticker(tick);
|
ticker = Ticker(tick);
|
||||||
ticker!.start();
|
ticker!.start();
|
||||||
|
game.main();
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -48,7 +51,8 @@ class _ViewerState extends State<Viewer> {
|
|||||||
return Scaffold(
|
return Scaffold(
|
||||||
body: Center(
|
body: Center(
|
||||||
child: AspectRatio(
|
child: AspectRatio(
|
||||||
aspectRatio: width / height, child: terminal.toWidget(context)),
|
aspectRatio: terminal.width / terminal.height,
|
||||||
|
child: terminal.toWidget(context)),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,32 +13,6 @@ class Terminal {
|
|||||||
|
|
||||||
Terminal() {
|
Terminal() {
|
||||||
tiles = [for (var i = 0; i < nTiles; i += 1) Tile.empty()];
|
tiles = [for (var i = 0; i < nTiles; i += 1) Tile.empty()];
|
||||||
for (final (x, c) in toCp437String("Hello, world!").indexed) {
|
|
||||||
tiles[x].content = Content(Font.normal.imageName, c % 32, 2 * (c ~/ 32));
|
|
||||||
tiles[x + Terminal.width].content =
|
|
||||||
Content(Font.normal.imageName, c % 32, 2 * (c ~/ 32) + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (final (x, c) in toCp437String("BEWARE OF THE BAT!").indexed) {
|
|
||||||
tiles[x + Terminal.width * 2].content =
|
|
||||||
Content(Font.small.imageName, c % 16, c ~/ 16);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (final (x, c) in toCp437String("BEWARE OF THE BAT!").indexed) {
|
|
||||||
tiles[Terminal.width * (x + 2)].content =
|
|
||||||
Content(Font.small.imageName, c % 16, c ~/ 16);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (final (x, c) in toCp437String("BEWARE OF THE BAT!").indexed) {
|
|
||||||
tiles[2 * x + 4 + Terminal.width * 4].content =
|
|
||||||
Content(Font.big.imageName, 2 * (c % 32), 2 * (c ~/ 32));
|
|
||||||
tiles[2 * x + 4 + Terminal.width * 5].content =
|
|
||||||
Content(Font.big.imageName, 2 * (c % 32), 2 * (c ~/ 32) + 1);
|
|
||||||
tiles[2 * x + 1 + 4 + Terminal.width * 4].content =
|
|
||||||
Content(Font.big.imageName, 2 * (c % 32) + 1, 2 * (c ~/ 32));
|
|
||||||
tiles[2 * x + 1 + 4 + Terminal.width * 5].content =
|
|
||||||
Content(Font.big.imageName, 2 * (c % 32) + 1, 2 * (c ~/ 32) + 1);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CustomPaint toWidget(BuildContext context) {
|
CustomPaint toWidget(BuildContext context) {
|
||||||
@ -65,6 +39,92 @@ class Terminal {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class Cursor {
|
||||||
|
final Terminal t;
|
||||||
|
int x, y;
|
||||||
|
Color? _bg, _fg;
|
||||||
|
Font font = Font.normal;
|
||||||
|
|
||||||
|
// TODO: Clip
|
||||||
|
|
||||||
|
Cursor({required this.t, required this.x, required this.y});
|
||||||
|
|
||||||
|
void clear() {
|
||||||
|
t.tiles = [for (var i = 0; i < nTiles; i += 1) Tile.empty()];
|
||||||
|
}
|
||||||
|
|
||||||
|
void putc(int c) {
|
||||||
|
for (var dx = 0; dx < font.cellWidth; dx += 1) {
|
||||||
|
for (var dy = 0; dy < font.cellHeight; dy += 1) {
|
||||||
|
var i = t.fromXY(x + dx, y + dy);
|
||||||
|
|
||||||
|
if (i != null) {
|
||||||
|
final (sourceCx, sourceCy) = (
|
||||||
|
(c % font.nCellsW) * font.cellWidth + dx,
|
||||||
|
(c ~/ font.nCellsW) * font.cellHeight + dy
|
||||||
|
);
|
||||||
|
|
||||||
|
t.tiles[i].content = Content(font.imageName, sourceCx, sourceCy);
|
||||||
|
|
||||||
|
final (bg, fg) = (_bg, _fg);
|
||||||
|
if (bg != null) {
|
||||||
|
t.tiles[i].bg = bg;
|
||||||
|
}
|
||||||
|
if (fg != null) {
|
||||||
|
t.tiles[i].fg = fg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void puts(String s) {
|
||||||
|
var startX = x;
|
||||||
|
for (final c in toCp437String(s)) {
|
||||||
|
if (c == 10) {
|
||||||
|
// newline
|
||||||
|
x = startX;
|
||||||
|
y += font.cellHeight;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (c == 13) {
|
||||||
|
// carriage return
|
||||||
|
x = startX;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
putc(c);
|
||||||
|
x += font.cellWidth;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Cursor fg(Color c) {
|
||||||
|
_fg = c;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
Cursor bg(Color c) {
|
||||||
|
_bg = c;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
Cursor small() {
|
||||||
|
font = Font.small;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
Cursor normal() {
|
||||||
|
font = Font.normal;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
Cursor big() {
|
||||||
|
font = Font.big;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Clip {}
|
||||||
|
|
||||||
class Tile {
|
class Tile {
|
||||||
Content? content;
|
Content? content;
|
||||||
|
|
||||||
@ -85,11 +145,19 @@ class Content {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// reexports
|
// reexports
|
||||||
Terminal terminal = Terminal();
|
Terminal _terminal = Terminal();
|
||||||
const int width = Terminal.width;
|
const int width = Terminal.width;
|
||||||
const int height = Terminal.height;
|
const int height = Terminal.height;
|
||||||
const int nTiles = Terminal.nTiles;
|
const int nTiles = Terminal.nTiles;
|
||||||
|
|
||||||
Widget toWidget(BuildContext context) {
|
Widget toWidget(BuildContext context) {
|
||||||
return terminal.toWidget(context);
|
return _terminal.toWidget(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
void clear() {
|
||||||
|
at(0, 0).clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
Cursor at(int x, int y) {
|
||||||
|
return Cursor(t: _terminal, x: x, y: y);
|
||||||
}
|
}
|
||||||
|
@ -44,7 +44,7 @@ class TerminalCustomPainter extends CustomPainter {
|
|||||||
|
|
||||||
// == Draw the background and foreground of every tile ==
|
// == Draw the background and foreground of every tile ==
|
||||||
for (var i = 0; i < nTiles; i++) {
|
for (var i = 0; i < nTiles; i++) {
|
||||||
final (pcxDst, pcyDst) = terminal.toXY(i) ?? (0, 0);
|
final (pcxDst, pcyDst) = t.toXY(i) ?? (0, 0);
|
||||||
final (pxDst, pyDst) = (pcxDst * cellW, pcyDst * cellH);
|
final (pxDst, pyDst) = (pcxDst * cellW, pcyDst * cellH);
|
||||||
final rectDst = Rect.fromLTWH(pxDst.toDouble(), pyDst.toDouble(),
|
final rectDst = Rect.fromLTWH(pxDst.toDouble(), pyDst.toDouble(),
|
||||||
cellW.toDouble(), cellH.toDouble());
|
cellW.toDouble(), cellH.toDouble());
|
||||||
|
Loading…
Reference in New Issue
Block a user