4 import BearLibTerminal
;
6 interface Graphicshandler
{
8 // Originally, this was pragma(inline, true) pure final void pline(T...)(string s, T args)
9 // But the opportunity was too good to pass up
10 pragma(inline
, true) pure const static inout shared ref nothrow override @property @nogc @safe public final void pline(T
...)(string s
, T args
) if (true) {
13 } else if (args
.length
== 0) {
16 pline(format(s
, args
));
25 private struct startendspec
{ int startx
, starty
, endx
, endy
, cursx
, cursy
; }
27 // Find the x-y coordinates to start drawing from in the map so the camera is centred on the player
28 // FUN FACT while coding this, I had no idea what it did or how
29 // it worked. I still have no idea how it works. But it does!
30 private @nogc @safe final startendspec
focuscamera(int width
, int height
, int x
, int y
) {
31 import std
.math
: round
;
33 int startx
, starty
, endx
, endy
;
34 int offsetx
, offsety
; // offsets are distance from top edge, left edge to centre
38 offsetx
= cast(int)round(width
/ 2.0);
39 offsety
= cast(int)round(height
/ 2.0);
41 // Don't keep the map centred when we're near an edge,
42 // actually move the @ closer to the edge
58 endx
= startx
+ width
;
59 endy
= starty
+ height
;
65 cursx
= width
- (map_x
- x
) - 1;
70 cursy
= height
- (map_y
- y
) - 1;
84 class BLThandler
: Graphicshandler
{
87 this(Game g
, string title
="") {
91 terminal
.set("input.cursor-blink-rate=2147483647");
92 terminal
.set("input.cursor-symbol=0x2588");
93 terminal
.set("font: dvsm.ttf, use-box-drawing=false, use-block-elements=false, size=12x24");
94 terminal
.set("window.resizeable=true");
98 auto lens
= focuscamera(maxx(), maxy(), game
.u
.x
, game
.u
.y
);
99 int tmpx
= 0, tmpy
= 0;
103 foreach (uint i
; lens
.starty
..lens
.endy
) {
105 foreach (uint j
; lens
.startx
..lens
.endx
) {
107 if ((mon
= game
.mon_at(i
, j
)) is null) {
110 if (!game
.map
[i
][j
].visible
)
113 terminal
.color(mon
.fgcolour
.toint
);
114 terminal
.bkcolor(mon
.bgcolour
.toint
);
116 /* x and y both start at 1, so we want to get them to 0
117 * in order to align them with the edges of the terminal.
118 * But it's okay to "add" 1 to y, because we want to leave
119 * an extra line up to for messages.
121 terminal
.printf(tmpx
-1, tmpy
, mon
.glyph
);
127 int tmpx
= 0, tmpy
= 0;
129 auto lens
= focuscamera(maxx(), maxy(), game
.u
.x
, game
.u
.y
);
131 foreach (uint i
; lens
.starty
..lens
.endy
) {
133 foreach (uint j
; lens
.startx
..lens
.endx
) {
136 terminal
.color((game
.map
[i
][j
].visible ? game
.map
[i
][j
].fgcolour
.lighten(20) : game
.map
[i
][j
].fgcolour
.darken(20)).toint
);
137 terminal
.bkcolor(game
.map
[i
][j
].bgcolour
.toint
);
138 /* x and y both start at 1, so we want to get them to 0
139 * in order to align them with the edges of the terminal.
140 * But it's okay to "add" 1 to y, because we want to leave
141 * an extra line up to for messages.
143 // import std.conv: to;
144 // curses.mvprint(tmpy, tmpx-1, to!string(to!string(game.map[i][j].dijkstra)[0]));
145 if (game
.map
[i
][j
].blocks_light
) {
146 terminal
.printf(tmpx
-1, tmpy
, game
.map
[i
][j
].visible ?
"█" : "▒"); //game.map[i][j].glyph);
148 terminal
.printf(tmpx
-1, tmpy
, game
.map
[i
][j
].visible ?
"." : "."); //game.map[i][j].glyph);
155 void pline(string msg
) {
156 if (msg
.length
== 0) {
160 terminal
.color(0xffffffff);
161 terminal
.bkcolor(0xff000000);
163 // TODO chop stuff up based on words, not character counts
164 pure string
[] chopupmsg(string msgtext
, int x
) {
167 immutable int maxlen
= x
- cast(int)" --More--".length
;
168 while (msgtext
.length
> x
) {
169 buf
~= (msgtext
[tmp
..tmp
+maxlen
] ~ " --More--");
171 msgtext
= msgtext
[tmp
..$];
177 terminal
.print(0, 0, fillstr(maxx()));
180 if (msg
.length
<= maxx()) {
182 terminal
.print(0, 0, msg
);
185 string
[] buffer
= chopupmsg(msg
, /*cast(int)*/maxx());
187 loop: foreach (lineindex
; 0..buffer
.length
) {
188 terminal
.print(0, 0, buffer
[lineindex
]);
192 if (c
== terminal
.keycode
.escape
) {
194 terminal
.print(0, 0, buffer
[$-1]);
197 if (lineindex
< buffer
.length
-1) {
198 while ((c
!= terminal
.keycode
.enter) && (c
!= terminal
.keycode
.space
)) {
199 if (c
== terminal
.keycode
.escape
) {
201 terminal
.print(0, 0, buffer
[$-1]);
212 int maxx() { return terminal
.state(terminal
.keycode
.width
); }
213 int maxy() { return terminal
.state(terminal
.keycode
.height
); }
220 char[terminal
.keycode
] keycode2char
= [terminal
.keycode
.a
: 'a',
221 terminal
.keycode
.b
: 'b',
222 terminal
.keycode
.c
: 'c',
223 terminal
.keycode
.d
: 'd',
224 terminal
.keycode
.e
: 'e',
225 terminal
.keycode
.f
: 'f',
226 terminal
.keycode
.g
: 'g',
227 terminal
.keycode
.h
: 'h',
228 terminal
.keycode
.i
: 'i',
229 terminal
.keycode
.j
: 'j',
230 terminal
.keycode
.k
: 'k',
231 terminal
.keycode
.l
: 'l',
232 terminal
.keycode
.m
: 'm',
233 terminal
.keycode
.n
: 'n',
234 terminal
.keycode
.o
: 'o',
235 terminal
.keycode
.p
: 'p',
236 terminal
.keycode
.q
: 'q',
237 terminal
.keycode
.r
: 'r',
238 terminal
.keycode
.s
: 's',
239 terminal
.keycode
.t
: 't',
240 terminal
.keycode
.u
: 'u',
241 terminal
.keycode
.v
: 'v',
242 terminal
.keycode
.w
: 'w',
243 terminal
.keycode
.x
: 'x',
244 terminal
.keycode
.y
: 'y',
245 terminal
.keycode
.z
: 'z',
246 terminal
.keycode
.KP_1
: '1',
247 terminal
.keycode
.KP_2
: '2',
248 terminal
.keycode
.KP_3
: '3',
249 terminal
.keycode
.KP_4
: '4',
250 terminal
.keycode
.KP_5
: '5',
251 terminal
.keycode
.KP_6
: '6',
252 terminal
.keycode
.KP_7
: '7',
253 terminal
.keycode
.KP_8
: '8',
254 terminal
.keycode
.KP_9
: '9',
255 terminal
.keycode
.KP_0
: '0',
256 terminal
.keycode
.enter: '\n',
257 terminal
.keycode
.escape
: '\033',
258 terminal
.keycode
.backspace
: '\b',
259 terminal
.keycode
.tab
: '\t',
260 terminal
.keycode
.space
: ' ',
261 terminal
.keycode
.minus
: '-',
262 terminal
.keycode
.equals
: '=',
263 terminal
.keycode
.lbracket
: '[',
264 terminal
.keycode
.rbracket
: ']',
265 terminal
.keycode
.backslash
: '\\',
266 terminal
.keycode
.semicolon
: ';',
267 terminal
.keycode
.apostrophe
: '\'',
268 terminal
.keycode
.grave
: '`',
269 terminal
.keycode
.comma
: ',',
270 terminal
.keycode
.period
: '.',
271 terminal
.keycode
.slash
: '/',
284 pause = 0x48 /* Pause/Break */,
291 right = 0x4F /* Right arrow */,
292 left = 0x50 /* Left arrow */,
293 down = 0x51 /* Down arrow */,
294 up = 0x52 /* Up arrow */,
296 terminal
.keycode
.KP_divide
: '/',
297 terminal
.keycode
.KP_multiply
: '*',
298 terminal
.keycode
.KP_minus
: '-',
299 terminal
.keycode
.KP_plus
: '+',
300 terminal
.keycode
.KP_enter
: '\n',
301 terminal
.keycode
.KP_1
: '1',
302 terminal
.keycode
.KP_2
: '2',
303 terminal
.keycode
.KP_3
: '3',
304 terminal
.keycode
.KP_4
: '4',
305 terminal
.keycode
.KP_5
: '5',
306 terminal
.keycode
.KP_6
: '6',
307 terminal
.keycode
.KP_7
: '7',
308 terminal
.keycode
.KP_8
: '8',
309 terminal
.keycode
.KP_9
: '9',
310 terminal
.keycode
.KP_0
: '0',
311 terminal
.keycode
.KP_period
: '.',
317 mouse_left = 0x80 /* Buttons */,
322 mouse_move = 0x85 /* Movement event */,
323 mouse_scroll = 0x86 /* Mouse scroll event */,
324 mouse_x = 0x87 /* Cusor position in cells */,
326 mouse_pixel_x = 0x89 /* Cursor position in pixels */,
327 mouse_pixel_y = 0x8A,
328 mouse_wheel = 0x8B /* Scroll direction and amount */,
329 mouse_clicks = 0x8C /* Number of consecutive clicks */,
333 while ((k
= terminal
.read()) !in keycode2char
) {}
334 return keycode2char
[k
];