| Home | Trees | Indices | Help |
|
|---|
|
|
1 """
2 The documentation for python-tdl. A Pythonic port of
3 U{libtcod<http://doryen.eptalys.net/libtcod/>}.
4
5 You can find the project page on Google Code
6 U{here<http://code.google.com/p/python-tdl/>}.
7
8 Getting Started
9 ===============
10 Once the library is imported you can load the font you want to use with
11 L{tdl.setFont}.
12 This is optional and when skipped will use a decent default font.
13
14 After that you call L{tdl.init} to set the size of the window and get the
15 root console in return.
16 This console is the canvas to what will appear on the screen.
17
18 Indexing Consoles
19 =================
20 For most methods taking a position you can use Python-style negative
21 indexes to refer to the opposite side of a console with (-1, -1)
22 starting at the bottom right.
23 You can also check if a point is part of a console using containment
24 logic i.e. ((x, y) in console).
25
26 Drawing
27 =======
28 Once you have the root console from L{tdl.init} you can start drawing on
29 it using a method such as L{Console.drawChar}.
30 When using this method you can have the char parameter be an integer or a
31 single character string.
32 The fgcolor and bgcolor parameters expect a three item list
33 [red, green, blue] with integers in the 0-255 range with [0, 0, 0] being
34 black and [255, 255, 255] being white.
35 Or instead you can use None for any of the three parameters to tell the
36 library to keep what is at that spot instead of overwriting it.
37 After the drawing functions are called a call to L{tdl.flush} will update
38 the screen.
39 """
40
41 import sys
42 import os
43
44 import ctypes
45 import weakref
46 import array
47 import itertools
48 import textwrap
49 import struct
50 import re
51 import warnings
52
53 from . import event, map, noise
54 from .__tcod import _lib, _Color, _unpackfile
55
56 _IS_PYTHON3 = (sys.version_info[0] == 3)
57
58 if _IS_PYTHON3: # some type lists to use with isinstance
59 _INTTYPES = (int,)
60 _NUMTYPES = (int, float)
61 _STRTYPES = (str, bytes)
62 else:
63 _INTTYPES = (int, long)
64 _NUMTYPES = (int, long, float)
65 _STRTYPES = (str,)
68 "changes string into bytes if running in python 3, for sending to ctypes"
69 if _IS_PYTHON3 and isinstance(string, str):
70 return string.encode()
71 return string
72
77 """Prepares a single character for passing to ctypes calls, needs to return
78 an integer but can also pass None which will keep the current character
79 instead of overwriting it.
80
81 This is called often and needs to be optimized whenever possible.
82 """
83 if char is None:
84 return None
85 if isinstance(char, _INTTYPES):
86 return char
87 if isinstance(char, _STRTYPES) and len(char) == 1:
88 return ord(char)
89 raise TypeError('Expected char parameter to be a single character string, number, or None, got: %s' % repr(char))
90
91 _fontinitialized = False
92 _rootinitialized = False
93 _rootConsoleRef = None
94 # remove dots from common functions
95 _setchar = _lib.TCOD_console_set_char
96 _setfore = _lib.TCOD_console_set_char_foreground
97 _setback = _lib.TCOD_console_set_char_background
98 _setcharEX = _lib.TCOD_console_put_char_ex
100 """Used internally.
101 Raise an assertion error if the parameters can not be converted into colors.
102 """
103 for color in colors:
104 assert _iscolor(color), 'a color must be a 3 item tuple, web format, or None, received %s' % repr(color)
105 return True
106
108 """Used internally.
109 A debug function to see if an object can be used as a TCOD color struct.
110 None counts as a parameter to keep the current colors instead.
111
112 This function is often part of an inner-loop and can slow a program down.
113 It has been made to work with assert and can be skipped with the -O flag.
114 Still it's called often and must be optimized.
115 """
116 if color is None:
117 return True
118 if isinstance(color, (tuple, list, _Color)):
119 return len(color) == 3
120 if isinstance(color, _INTTYPES):
121 return True
122 return False
123
124 ## not using this for now
125 #class Color(object):
126 #
127 # def __init__(self, r, g, b):
128 # self._color = (r, g, b)
129 # self._ctype = None
130 #
131 # def _getCType(self):
132 # if not self._ctype:
133 # self._ctype = _Color(*self._color)
134 # return self._ctype
135 #
136 # def __len__(self):
137 # return 3
138
139 -def _formatColor(color):
140 """Format the color to ctypes
141 """
142 if color is None:
143 return None
144 if isinstance(color, _Color):
145 return color
146 #if isinstance(color, Color):
147 # return color._getCType()
148 if isinstance(color, _INTTYPES):
149 # format a web style color with the format 0xRRGGBB
150 return _Color(color >> 16 & 0xff, color >> 8 & 0xff, color & 0xff)
151 return _Color(*color)
152
154 """Try to get the width and height of a bmp of png image file"""
155 file = open(filename, 'rb')
156 if file.read(8) == b'\x89PNG\r\n\x1a\n': # PNG
157 while 1:
158 length, = struct.unpack('>i', file.read(4))
159 chunkID = file.read(4)
160 if chunkID == '': # EOF
161 return None
162 if chunkID == b'IHDR':
163 # return width, height
164 return struct.unpack('>ii', file.read(8))
165 file.seek(4 + length, 1)
166 file.seek(0)
167 if file.read(8) == b'BM': # Bitmap
168 file.seek(18, 0) # skip to size data
169 # return width, height
170 return struct.unpack('<ii', file.read(8))
171 # return None on error, unknown file
177
179 """
180 Contains methods shared by both the L{Console} and L{Window} classes.
181 """
182 __slots__ = ('width', 'height', 'console', '__weakref__', '__dict__')
183
185 """Draws a single character.
186
187 @type x: int
188 @param x: X coordinate to draw at.
189 @type y: int
190 @param y: Y coordinate to draw at.
191
192 @type char: int, string, or None
193 @param char: Should be an integer, single character string, or None.
194
195 You can set the char parameter as None if you only want to change
196 the colors of the tile.
197
198 @type fgcolor: (r, g, b) or None
199 @param fgcolor: For fgcolor and bgcolor you use a 3 item list with
200 integers ranging 0-255 or None.
201
202 None will keep the current color at this position unchanged.
203 @type bgcolor: (r, g, b) or None
204 @param bgcolor: Background color. See fgcolor
205
206 @raise AssertionError: Having x or y values that can't be placed inside
207 of the console will raise an AssertionError.
208 You can use always use ((x, y) in console) to
209 check if a tile is drawable.
210 """
211
212 assert _verify_colors(fgcolor, bgcolor)
213 x, y = self._normalizePoint(x, y)
214 x, y = ctypes.c_int(x), ctypes.c_int(y)
215 self._setChar(x, y, _formatChar(char),
216 _formatColor(fgcolor), _formatColor(bgcolor))
217
219 """Draws a string starting at x and y. Optinally colored.
220
221 A string that goes past the right side will wrap around. A string
222 wraping to below the console will raise a L{TDLError} but will still be
223 written out. This means you can safely ignore the errors with a
224 try... except block if you're fine with partily written strings.
225
226 \\r and \\n are drawn on the console as normal character tiles. No
227 special encoding is done and any string will translate to the character
228 table as is.
229
230 For a string drawing operation that respects special characters see the
231 L{Typewriter} class.
232
233 @type x: int
234 @param x: X coordinate to draw at.
235 @type y: int
236 @param y: Y coordinate to draw at.
237
238 @type string: string or iterable
239 @param string: Can be a string or an iterable of numbers.
240
241 Special characters are ignored and rendered as any other
242 character.
243
244 @type fgcolor: (r, g, b) or None
245 @param fgcolor: For fgcolor and bgcolor you use a 3 item list with
246 integers ranging 0-255 or None.
247
248 None will keep the current color at this position unchanged.
249 @type bgcolor: (r, g, b) or None
250 @param bgcolor: Background color. See fgcolor
251
252 @raise AssertionError: Having x or y values that can't be placed inside
253 of the console will raise an AssertionError.
254
255 You can use always use ((x, y) in console) to
256 check if a tile is drawable.
257 """
258
259 x, y = self._normalizePoint(x, y)
260 assert _verify_colors(fgcolor, bgcolor)
261 fgcolor, bgcolor = _formatColor(fgcolor), _formatColor(bgcolor)
262 width, height = self.getSize()
263 batch = [] # prepare a batch operation
264 def _drawStrGen(x=x, y=y, string=string, width=width, height=height):
265 """Generator for drawStr
266
267 Iterates over ((x, y), ch) data for _setCharBatch, raising an
268 error if the end of the console is reached.
269 """
270 for char in string:
271 if y == height:
272 raise TDLError('End of console reached.')
273 #batch.append(((x, y), _formatChar(char))) # ((x, y), ch)
274 yield((x, y), _formatChar(char))
275 x += 1 # advance cursor
276 if x == width: # line break
277 x = 0
278 y += 1
279 self._setCharBatch(_drawStrGen(), fgcolor, bgcolor)
280
282 """Draws a rectangle starting from x and y and extending to width and height.
283
284 If width or height are None then it will extend to the edge of the console.
285
286 @type x: int
287 @param x: x coordinate to draw at.
288 @type y: int
289 @param y: y coordinate to draw at.
290
291 @type width: int or None
292 @param width: Width of the rectangle.
293
294 Can be None to extend to the bottom right of the
295 console or can be a negative number to be sized reltive
296 to the total size of the console.
297 @type height: int or None
298 @param height: Height of the rectangle. See width.
299
300 @type string: int, string, or None
301 @param string: Should be an integer, single character string, or None.
302
303 You can set the char parameter as None if you only want
304 to change the colors of an area.
305
306 @type fgcolor: (r, g, b) or None
307 @param fgcolor: For fgcolor and bgcolor you use a 3 item list with
308 integers ranging 0-255 or None.
309
310 None will keep the current color at this position unchanged.
311 @type bgcolor: (r, g, b) or None
312 @param bgcolor: Background color. See fgcolor
313
314 @raise AssertionError: Having x or y values that can't be placed inside
315 of the console will raise an AssertionError.
316
317 You can use always use ((x, y) in console) to
318 check if a tile is drawable.
319 """
320 x, y, width, height = self._normalizeRect(x, y, width, height)
321 assert _verify_colors(fgcolor, bgcolor)
322 fgcolor, bgcolor = _formatColor(fgcolor), _formatColor(bgcolor)
323 char = _formatChar(string)
324 # use itertools to make an x,y grid
325 # using ctypes here reduces type converstions later
326 grid = itertools.product((ctypes.c_int(x) for x in range(x, x + width)),
327 (ctypes.c_int(y) for y in range(y, y + height)))
328 # zip the single character in a batch variable
329 batch = zip(grid, itertools.repeat(char, width * height))
330 self._setCharBatch(batch, fgcolor, bgcolor, nullChar=(char is None))
331
333 """Similar to L{drawRect} but only draws the outline of the rectangle.
334
335 @type x: int
336 @param x: x coordinate to draw at.
337 @type y: int
338 @param y: y coordinate to draw at.
339
340 @type width: int or None
341 @param width: Width of the rectangle.
342
343 Can be None to extend to the bottom right of the
344 console or can be a negative number to be sized reltive
345 to the total size of the console.
346 @type height: int or None
347 @param height: Height of the rectangle. See width.
348
349 @type string: int, string, or None
350 @param string: Should be an integer, single character string, or None.
351
352 You can set the char parameter as None if you only want
353 to change the colors of an area.
354
355 @type fgcolor: (r, g, b) or None
356 @param fgcolor: For fgcolor and bgcolor you use a 3 item list with
357 integers ranging 0-255 or None.
358
359 None will keep the current color at this position unchanged.
360 @type bgcolor: (r, g, b) or None
361 @param bgcolor: Background color. See fgcolor
362
363 @raise AssertionError: Having x or y values that can't be placed inside
364 of the console will raise an AssertionError.
365
366 You can use always use ((x, y) in console) to
367 check if a tile is drawable.
368 """
369 x, y, width, height = self._normalizeRect(x, y, width, height)
370 assert _verify_colors(fgcolor, bgcolor)
371 fgcolor, bgcolor = _formatColor(fgcolor), _formatColor(bgcolor)
372 char = _formatChar(string)
373 if width == 1 or height == 1: # it's just a single width line here
374 return self.drawRect(x, y, width, height, char, fgcolor, bgcolor)
375
376 # draw sides of frame with drawRect
377 self.drawRect(x, y, 1, height, char, fgcolor, bgcolor)
378 self.drawRect(x, y, width, 1, char, fgcolor, bgcolor)
379 self.drawRect(x + width - 1, y, 1, height, char, fgcolor, bgcolor)
380 self.drawRect(x, y + height - 1, width, 1, char, fgcolor, bgcolor)
381
383 """Check if a point is in bounds and make minor adjustments.
384
385 Respects Pythons negative indexes. -1 starts at the bottom right.
386 Replaces the _drawable function
387 """
388 assert isinstance(x, _INTTYPES), 'x must be an integer, got %s' % repr(x)
389 assert isinstance(y, _INTTYPES), 'y must be an integer, got %s' % repr(y)
390
391 assert (-self.width <= x < self.width) and (-self.height <= y < self.height), \
392 ('(%i, %i) is an invalid postition on %s' % (x, y, self))
393
394 # handle negative indexes
395 if x < 0:
396 x += self.width
397 if y < 0:
398 y += self.height
399 return (x, y)
400
402 """Check if the rectangle is in bounds and make minor adjustments.
403 raise AssertionError's for any problems
404 """
405 x, y = self._normalizePoint(x, y) # inherit _normalizePoint logic
406
407 assert width is None or isinstance(width, _INTTYPES), 'width must be an integer or None, got %s' % repr(width)
408 assert height is None or isinstance(height, _INTTYPES), 'height must be an integer or None, got %s' % repr(height)
409
410 # if width or height are None then extend them to the edge
411 if width is None:
412 width = self.width - x
413 elif width < 0: # handle negative numbers
414 width += self.width
415 width = max(0, width) # a 'too big' negative is clamped zero
416 if height is None:
417 height = self.height - y
418 height = max(0, height)
419 elif height < 0:
420 height += self.height
421
422 # reduce rect size to bounds
423 width = min(width, self.width - x)
424 height = min(height, self.height - y)
425
426 return x, y, width, height
427
429 """Blit another console or Window onto the current console.
430
431 By default it blits the entire source to the topleft corner.
432
433 @type source: L{Console} or L{Window}
434 @param source: Source window can be a L{Console} or L{Window} instance.
435 It can even blit to itself without any problems.
436
437 @type x: int
438 @param x: X coordinate to blit to.
439 @type y: int
440 @param y: Y coordinate to blit to.
441
442 @type width: int or None
443 @param width: Width of the rectangle.
444
445 Can be None to extend as far as possible to the
446 bottom right corner of the blit area or can be a negative
447 number to be sized reltive to the total size of the
448 B{destination} console.
449 @type height: int or None
450 @param height: Height of the rectangle. See width.
451
452 @type srcX: int
453 @param srcX: The source consoles x coordinate to blit from.
454 @type srcY: int
455 @param srcY: The source consoles y coordinate to blit from.
456 """
457 # hardcode alpha settings for now
458 fgalpha=1.0
459 bgalpha=1.0
460
461 assert isinstance(source, (Console, Window)), "source muse be a Window or Console instance"
462
463 # handle negative indexes and rects
464 # negative width and height will be set realtive to the destination
465 # and will also be clamped to the smallest Console
466 x, y, width, height = self._normalizeRect(x, y, width, height)
467 srcX, srcY, width, height = source._normalizeRect(srcX, srcY, width, height)
468
469 # translate source and self if any of them are Window instances
470 srcX, srcY = source._translate(srcX, srcY)
471 source = source.console
472 x, y = self._translate(x, y)
473 self = self.console
474
475 if self == source:
476 # if we are the same console then we need a third console to hold
477 # onto the data, otherwise it tries to copy into itself and
478 # starts destroying everything
479 tmp = Console(width, height)
480 _lib.TCOD_console_blit(source, srcX, srcY, width, height, tmp, 0, 0, fgalpha, bgalpha)
481 _lib.TCOD_console_blit(tmp, 0, 0, width, height, self, x, y, fgalpha, bgalpha)
482 else:
483 _lib.TCOD_console_blit(source, srcX, srcY, width, height, self, x, y, fgalpha, bgalpha)
484
486 """Return the size of the console as (width, height)
487
488 @rtype: (int, int)
489 """
490 return self.width, self.height
491
493 """Scroll the contents of the console in the direction of x,y.
494
495 Uncovered areas will be cleared.
496 @type x: int
497 @param x: Distance to scroll along x-axis
498 @type y: int
499 @param y: Distance to scroll along y-axis
500 """
501 assert isinstance(x, _INTTYPES), "x must be an integer, got %s" % repr(x)
502 assert isinstance(y, _INTTYPES), "y must be an integer, got %s" % repr(x)
503 def getSlide(x, length):
504 """get the parameters needed to scroll the console in the given
505 direction with x
506 returns (x, length, srcx)
507 """
508 if x > 0:
509 srcx = 0
510 length -= x
511 elif x < 0:
512 srcx = abs(x)
513 x = 0
514 length -= srcx
515 else:
516 srcx = 0
517 return x, length, srcx
518 def getCover(x, length):
519 """return the (x, width) ranges of what is covered and uncovered"""
520 cover = (0, length) # everything covered
521 uncover = None # nothing uncovered
522 if x > 0: # left side uncovered
523 cover = (x, length - x)
524 uncover = (0, x)
525 elif x < 0: # right side uncovered
526 x = abs(x)
527 cover = (0, length - x)
528 uncover = (length - x, x)
529 return cover, uncover
530
531 width, height = self.getSize()
532 if abs(x) >= width or abs(y) >= height:
533 return self.clear() # just clear the console normally
534
535 # get the ranges of the areas that will be uncovered
536 coverX, uncoverX = getCover(x, width)
537 coverY, uncoverY = getCover(y, height)
538 # so at this point we know that coverX and coverY makes a rect that
539 # encases the area that we end up blitting to. uncoverX/Y makes a
540 # rect in the corner of the uncovered area. So we need to combine
541 # the uncoverX/Y with coverY/X to make what's left of the uncovered
542 # area. Explaining it makes it mush easier to do now.
543
544 # But first we need to blit.
545 x, width, srcx = getSlide(x, width)
546 y, height, srcy = getSlide(y, height)
547 self.blit(self, x, y, width, height, srcx, srcy)
548
549 if uncoverX: # clear sides (0x20 is space)
550 self.drawRect(uncoverX[0], coverY[0], uncoverX[1], coverY[1], 0x20)
551 if uncoverY: # clear top/bottom
552 self.drawRect(coverX[0], uncoverY[0], coverX[1], uncoverY[1], 0x20)
553 if uncoverX and uncoverY: # clear corner
554 self.drawRect(uncoverX[0], uncoverY[0], uncoverX[1], uncoverY[1], 0x20)
555
557 """Return the character and colors of a tile as (ch, fg, bg)
558
559 This method runs very slowly as is not recommended to be called
560 frequently.
561
562 @rtype: (int, (r, g, b), (r, g, b))
563 @returns: Returns a 3-item tuple. The first item is an integer of the
564 character at the position (x, y) the second and third are the
565 foreground and background colors respectfully.
566 """
567 raise NotImplementedError('Method here only exists for the docstring')
568
570 """Use ((x, y) in console) to check if a position is drawable on this console.
571 """
572 x, y = position
573 return (0 <= x < self.width) and (0 <= y < self.height)
574
576 """Contains character and color data and can be drawn to.
577
578 The console created by the L{tdl.init} function is the root console and is the
579 console that is rendered to the screen with L{flush}.
580
581 Any console created from the Console class is an off-screen console that
582 can be drawn on before being L{blit} to the root console.
583 """
584
585 __slots__ = ('_as_parameter_', '_typewriter')
586
588 """Create a new offscreen console.
589
590 @type width: int
591 @param width: Width of the console in tiles
592 @type height: int
593 @param height: Height of the console in tiles
594 """
595 if not _rootinitialized:
596 raise TDLError('Can not create Console\'s before tdl.init')
597 self._as_parameter_ = _lib.TCOD_console_new(width, height)
598 self.console = self
599 self.width = width
600 self.height = height
601 self._typewriter = None # "typewriter lock", makes sure the colors are set to the typewriter
602
603 @classmethod
605 """Make a Console instance, from a console ctype"""
606 self = cls.__new__(cls)
607 self._as_parameter_ = console
608 self.console = self
609 self.width = _lib.TCOD_console_get_width(self)
610 self.height = _lib.TCOD_console_get_height(self)
611 self._typewriter = None
612 return self
613
615 """
616 If the main console is garbage collected then the window will be closed as well
617 """
618 # If this is the root console the window will close when collected
619 try:
620 if isinstance(self._as_parameter_, ctypes.c_void_p):
621 global _rootinitialized, _rootConsoleRef
622 _rootinitialized = False
623 _rootConsoleRef = None
624 _lib.TCOD_console_delete(self)
625 except StandardError:
626 pass # I forget why I put this here but I'm to afraid to delete it
627
629 """Used internally
630
631 Mostly used just to replace this Console object with the root console
632 If another Console object is used then they are swapped
633 """
634 if isinstance(console, Console):
635 self._as_parameter_, console._as_parameter_ = \
636 console._as_parameter_, self._as_parameter_ # swap tcod consoles
637 else:
638 self._as_parameter_ = console
639 self.width = _lib.TCOD_console_get_width(self)
640 self.height = _lib.TCOD_console_get_height(self)
641 return self
642
644 """Convertion x and y to their position on the root Console for this Window
645
646 Because this is a Console instead of a Window we return the paramaters
647 untouched"""
648 return x, y
649
651 """Clears the entire Console.
652
653 @type fgcolor: (r, g, b)
654 @param fgcolor: Foreground color.
655
656 Must be a 3-item list with integers that range 0-255.
657
658 Unlike most other operations you can not use None here.
659 @type bgcolor: (r, g, b)
660 @param bgcolor: Background color. See fgcolor.
661 """
662 assert _verify_colors(fgcolor, bgcolor)
663 assert fgcolor and bgcolor, 'Can not use None with clear'
664 self._typewriter = None
665 _lib.TCOD_console_set_default_background(self, _formatColor(bgcolor))
666 _lib.TCOD_console_set_default_foreground(self, _formatColor(fgcolor))
667 _lib.TCOD_console_clear(self)
668
670 """
671 Sets a character.
672 This is called often and is designed to be as fast as possible.
673
674 Because of the need for speed this function will do NO TYPE CHECKING
675 AT ALL, it's up to the drawing functions to use the functions:
676 _formatChar and _formatColor before passing to this."""
677 # buffer values as ctypes objects
678 console = self._as_parameter_
679
680 if char is not None and fgcolor is not None and bgcolor is not None:
681 _setcharEX(console, x, y, char, fgcolor, bgcolor)
682 return
683 if char is not None:
684 _setchar(console, x, y, char)
685 if fgcolor is not None:
686 _setfore(console, x, y, fgcolor)
687 if bgcolor is not None:
688 _setback(console, x, y, bgcolor, bgblend)
689
691 """
692 Try to perform a batch operation otherwise fall back to _setChar.
693 If fgcolor and bgcolor are defined then this is faster but not by very
694 much.
695
696 batch is a iterable of [(x, y), ch] items
697 """
698 if fgcolor and not nullChar:
699 # buffer values as ctypes objects
700 self._typewriter = None # clear the typewriter as colors will be set
701 console = self._as_parameter_
702 if not bgcolor:
703 bgblend = 0
704 bgblend = ctypes.c_int(bgblend)
705
706 _lib.TCOD_console_set_default_background(console, bgcolor)
707 _lib.TCOD_console_set_default_foreground(console, fgcolor)
708 _putChar = _lib.TCOD_console_put_char # remove dots and make local
709 for (x, y), char in batch:
710 _putChar(console, x, y, char, bgblend)
711 else:
712 for (x, y), char in batch:
713 self._setChar(x, y, char, fgcolor, bgcolor, bgblend)
714
716 # inherit docstring
717 x, y = self._normalizePoint(x, y)
718 char = _lib.TCOD_console_get_char(self, x, y)
719 bgcolor = _lib.TCOD_console_get_char_background_wrapper(self, x, y)
720 fgcolor = _lib.TCOD_console_get_char_foreground_wrapper(self, x, y)
721 return char, tuple(fgcolor), tuple(bgcolor)
722
725
728 """A Window contains a small isolated part of a Console.
729
730 Drawing on the Window draws on the Console.
731
732 Making a Window and setting its width or height to None will extend it to
733 the edge of the console.
734 """
735
736 __slots__ = ('parent', 'x', 'y')
737
739 """Isolate part of a L{Console} or L{Window} instance.
740
741 @type console: L{Console} or L{Window}
742 @param console: The parent object which can be a L{Console} or another
743 L{Window} instance.
744
745 @type x: int
746 @param x: X coordinate to place the Window.
747
748 This follows the normal rules for indexing so you can use a
749 negative integer to place the Window relative to the bottom
750 right of the parent Console instance.
751 @type y: int
752 @param y: Y coordinate to place the Window.
753
754 See x.
755
756 @type width: int or None
757 @param width: Width of the Window.
758
759 Can be None to extend as far as possible to the
760 bottom right corner of the parent Console or can be a
761 negative number to be sized reltive to the Consoles total
762 size.
763 @type height: int or None
764 @param height: Height of the Window.
765
766 See width.
767 """
768 assert isinstance(console, (Console, Window)), 'console parameter must be a Console or Window instance, got %s' % repr(console)
769 self.parent = console
770 self.x, self.y, self.width, self.height = console._normalizeRect(x, y, width, height)
771 if isinstance(console, Console):
772 self.console = console
773 else:
774 self.console = self.parent.console
775
777 """Convertion x and y to their position on the root Console"""
778 # we add our position relative to our parent and then call then next parent up
779 return self.parent._translate((x + self.x), (y + self.y))
780
782 """Clears the entire Window.
783
784 @type fgcolor: (r, g, b)
785 @param fgcolor: Foreground color.
786
787 Must be a 3-item list with integers that range 0-255.
788
789 Unlike most other operations you can not use None here.
790 @type bgcolor: (r, g, b)
791 @param bgcolor: Background color. See fgcolor.
792 """
793 assert _verify_colors(fgcolor, bgcolor)
794 assert fgcolor and bgcolor, 'Can not use None with clear'
795 self.draw_rect(0, 0, None, None, 0x20, fgcolor, bgcolor)
796
799
801 myX = self.x # remove dots for speed up
802 myY = self.y
803 self.parent._setCharBatch((((x + myX, y + myY), ch) for ((x, y), ch) in batch),
804 fgcolor, bgcolor, bgblend)
805
806
808 # inherit docstring
809 x, y = self._normalizePoint(x, y)
810 self.parent.drawChar(x + self.x, y + self.y, char, fgcolor, bgcolor)
811
813 # inherit docstring
814 x, y, width, height = self._normalizeRect(x, y, width, height)
815 self.parent.drawRect(x + self.x, y + self.y, width, height, string, fgcolor, bgcolor)
816
818 # inherit docstring
819 x, y, width, height = self._normalizeRect(x, y, width, height)
820 self.parent.drawFrame(x + self.x, y + self.y, width, height, string, fgcolor, bgcolor)
821
823 # inherit docstring
824 x, y = self._normalizePoint(x, y)
825 return self.console.getChar(self._translate(x, y))
826
831
834 """Converts a console into a scrolling text log that respects special
835 characters.
836
837 This class works best on a L{Window} or off-screen L{Console} instance.
838 In a L{Window} for example the scrolling text is limited to the L{Window}'s
839 isolated area.
840 """
841
843 """Add a virtual cursor to a L{Console} or L{Window} instance.
844
845 @type console: L{Console} or L{Window}
846 """
847 assert isinstance(console, (Console, Window)), 'console parameter must be a Console or Window instance, got %s' % repr(console)
848 self.parent = console
849 if isinstance(self.parent, Console):
850 self.console = self.parent
851 else:
852 self.console = self.parent.console
853 self.cursor = (0, 0) # cursor position
854 self.scrollMode = 'scroll' #can be 'scroll', 'error'
855 self.fgcolor = _formatColor((255, 255, 255))
856 self.bgcolor = _formatColor((0, 0, 0))
857 self._bgblend = 1 # SET
858
860 """return the normalized the cursor position."""
861 width, height = self.parent.getSize()
862 while x >= width:
863 x -= width
864 y += 1
865 while y >= height:
866 if self.scrollMode == 'scroll':
867 y -= 1
868 self.parent.scroll(0, -1)
869 elif self.scrollMode == 'error':
870 # reset the cursor on error
871 self.cursor = (0, 0)
872 raise TDLError('Typewriter cursor has reached the end of the console')
873 return (x, y)
874
876 """Return the virtual cursor position.
877
878 @rtype: (int, int)
879 @return: Returns (x, y) a 2-integer tuple containing where the next
880 L{addChar} or L{addStr} will start at.
881
882 This can be changed with the L{move} method."""
883 x, y = self.cursor
884 width, height = self.parent.getSize()
885 while x >= width:
886 x -= width
887 y += 1
888 if y >= height and self.scrollMode == 'scroll':
889 y = height - 1
890 return x, y
891
893 """Move the virtual cursor.
894
895 @type x: int
896 @param x: X position to place the cursor.
897 @type y: int
898 @param y: Y position to place the cursor.
899 """
900 self.cursor = self.parent._normalizePoint(x, y)
901
903 """Change the foreground color"""
904 assert _iscolor(color)
905 assert color is not None
906 self.fgcolor = _formatColor(color)
907 if self.console._typewriter is self:
908 _lib.TCOD_console_set_default_foreground(self.console, self.fgcolor)
909
911 """Change the background color"""
912 assert _iscolor(color)
913 assert color is not None
914 self.bgcolor = _formatColor(color)
915 if self.console._typewriter is self:
916 _lib.TCOD_console_set_default_background(self.console, self.bgcolor)
917
919 """Make sure the colors on a console match the Typewriter instance"""
920 if self.console._typewriter is not self:
921 self.console._typewriter = self
922
923 _lib.TCOD_console_set_default_background(self.console, self.bgcolor)
924 _lib.TCOD_console_set_default_foreground(self.console, self.fgcolor)
925
926
928 """Draw a single character at the cursor."""
929 if char == '\n': # line break
930 x = 0
931 y += 1
932 return
933 if char == '\r': # return
934 x = 0
935 return
936 x, y = self._normalize(*self.cursor)
937 self.cursor = [x + 1, y] # advance cursor on next draw
938 self._updateConsole()
939 x, y = self.parent._translate(x, y)
940 _lib.TCOD_console_put_char(self.console._as_parameter_, x, y, _formatChar(char), self._bgblend)
941
942
944 """Write a string at the cursor. Handles special characters such as newlines.
945
946 @type string: string
947 @param string:
948 """
949 x, y = self.cursor
950 for char in string:
951 if char == '\n': # line break
952 x = 0
953 y += 1
954 continue
955 if char == '\r': # return
956 x = 0
957 continue
958 x, y = self._normalize(x, y)
959 self.parent.drawChar(x, y, char, self.fgcolor, self.bgcolor)
960 x += 1
961 self.cursor = (x, y)
962
964 """This method mimics basic file-like behaviour.
965
966 Because of this method you can replace sys.stdout or sys.stderr with
967 a L{Typewriter} instance.
968
969 @type string: string
970 """
971 # some 'basic' line buffer stuff.
972 # there must be an easier way to do this. The textwrap module didn't
973 # help much.
974 x, y = self._normalize(*self.cursor)
975 width, height = self.parent.getSize()
976 wrapper = textwrap.TextWrapper(initial_indent=(' '*x), width=width)
977 writeLines = []
978 for line in string.split('\n'):
979 if line:
980 writeLines += wrapper.wrap(line)
981 wrapper.initial_indent = ''
982 else:
983 writeLines.append([])
984
985 for line in writeLines:
986 x, y = self._normalize(x, y)
987 self.parent.drawStr(x, y, line[x:], self.fgcolor, self.bgcolor)
988 y += 1
989 x = 0
990 y -= 1
991 self.cursor = (x, y)
992
995 """Start the main console with the given width and height and return the
996 root console.
997
998 Call the consoles drawing functions. Then remember to use L{tdl.flush} to
999 make what's drawn visible on the console.
1000
1001 @type width: int
1002 @param width: width of the root console (in tiles)
1003
1004 @type height: int
1005 @param height: height of the root console (in tiles)
1006
1007 @type title: string
1008 @param title: Text to display as the window title.
1009
1010 If left None it defaults to the running scripts filename.
1011
1012 @type fullscreen: boolean
1013 @param fullscreen: Can be set to True to start in fullscreen mode.
1014
1015 @type renderer: string
1016 @param renderer: Can be one of 'GLSL', 'OPENGL', or 'SDL'.
1017
1018 Due to way Python works you're unlikely to see much of an
1019 improvement by using 'GLSL' or 'OPENGL' as most of the
1020 time Python is slow interacting with the console and the
1021 rendering itself is pretty fast even on 'SDL'.
1022
1023 @rtype: L{Console}
1024 @return: The root console. Only what is drawn on the root console is
1025 what's visible after a call to L{tdl.flush}.
1026 After the root console is garbage collected, the window made by
1027 this function will close.
1028 """
1029 RENDERERS = {'GLSL': 0, 'OPENGL': 1, 'SDL': 2}
1030 global _rootinitialized, _rootConsoleRef
1031 if not _fontinitialized: # set the default font to the one that comes with tdl
1032 setFont(_unpackfile('terminal8x8.png'), None, None, True, True)
1033
1034 if renderer.upper() not in RENDERERS:
1035 raise TDLError('No such render type "%s", expected one of "%s"' % (renderer, '", "'.join(RENDERERS)))
1036 renderer = RENDERERS[renderer.upper()]
1037
1038 # If a console already exists then make a clone to replace it
1039 if _rootConsoleRef and _rootConsoleRef():
1040 oldroot = _rootConsoleRef()
1041 rootreplacement = Console(oldroot.width, oldroot.height)
1042 rootreplacement.blit(oldroot)
1043 oldroot._replace(rootreplacement)
1044 del rootreplacement
1045
1046 if title is None: # use a default title
1047 if sys.argv:
1048 # Use the script filename as the title.
1049 title = os.path.basename(sys.argv[0])
1050 else:
1051 title = 'python-tdl'
1052
1053 _lib.TCOD_console_init_root(width, height, _encodeString(title), fullscreen, renderer)
1054
1055 #event.get() # flush the libtcod event queue to fix some issues
1056 # issues may be fixed already
1057
1058 event._eventsflushed = False
1059 _rootinitialized = True
1060 rootconsole = Console._newConsole(ctypes.c_void_p())
1061 _rootConsoleRef = weakref.ref(rootconsole)
1062
1063 return rootconsole
1064
1066 """Make all changes visible and update the screen.
1067
1068 Remember to call this function after drawing operations.
1069 Calls to flush will enfore the frame rate limit set by L{tdl.setFPS}.
1070
1071 This function can only be called after L{tdl.init}
1072 """
1073 if not _rootinitialized:
1074 raise TDLError('Cannot flush without first initializing with tdl.init')
1075
1076 _lib.TCOD_console_flush()
1077
1078 -def setFont(path, columns=None, rows=None, columnFirst=False,
1079 greyscale=False, altLayout=False):
1080 """Changes the font to be used for this session.
1081 This should be called before L{tdl.init}
1082
1083 If the font specifies its size in its filename (i.e. font_NxN.png) then this
1084 function can auto-detect the tileset formatting and the parameters columns
1085 and rows can be left None.
1086
1087 While it's possible you can change the font mid program it can sometimes
1088 break in rare circumstances. So use caution when doing this.
1089
1090 @type path: string
1091 @param path: Must be a string filepath where a bmp or png file is found.
1092
1093 @type columns: int
1094 @param columns: Number of columns in the tileset.
1095
1096 Can be left None for auto-detection.
1097
1098 @type rows: int
1099 @param rows: Number of rows in the tileset.
1100
1101 Can be left None for auto-detection.
1102
1103 @type columnFirst: boolean
1104 @param columnFirst: Defines if the characer order goes along the rows or
1105 colomns.
1106 It should be True if the charater codes 0-15 are in the
1107 first column.
1108 And should be False if the characters 0-15
1109 are in the first row.
1110
1111 @type greyscale: boolean
1112 @param greyscale: Creates an anti-aliased font from a greyscale bitmap.
1113 Otherwise it uses the alpha channel for anti-aliasing.
1114
1115 Unless you actually need anti-aliasing from a font you
1116 know uses a smooth greyscale channel you should leave
1117 this on False.
1118
1119 @type altLayout: boolean
1120 @param altLayout: An alternative layout with space in the upper left
1121 corner.
1122 The colomn parameter is ignored if this is True,
1123 find examples of this layout in the font/libtcod/
1124 directory included with the python-tdl source.
1125
1126 @raise TDLError: Will be raised if no file is found at path or if auto-
1127 detection fails.
1128
1129 @note: A png file that's been optimized can fail to load correctly on
1130 MAC OS X creating a garbled mess when rendering.
1131 Don't use a program like optipng or just use bmp files instead if
1132 you want your program to work on macs.
1133 """
1134 # put up some constants that are only used here
1135 FONT_LAYOUT_ASCII_INCOL = 1
1136 FONT_LAYOUT_ASCII_INROW = 2
1137 FONT_TYPE_GREYSCALE = 4
1138 FONT_LAYOUT_TCOD = 8
1139 global _fontinitialized
1140 _fontinitialized = True
1141 flags = 0
1142 if altLayout:
1143 flags |= FONT_LAYOUT_TCOD
1144 elif columnFirst:
1145 flags |= FONT_LAYOUT_ASCII_INCOL
1146 else:
1147 flags |= FONT_LAYOUT_ASCII_INROW
1148 if greyscale:
1149 flags |= FONT_TYPE_GREYSCALE
1150 if not os.path.exists(path):
1151 raise TDLError('no file exists at: "%s"' % path)
1152 path = os.path.abspath(path)
1153
1154 # and the rest is the auto-detect script
1155 imgSize = _getImageSize(path) # try to find image size
1156 if imgSize:
1157 imgWidth, imgHeight = imgSize
1158 # try to get font size from filename
1159 match = re.match('.*?([0-9]+)[xX]([0-9]+)', os.path.basename(path))
1160 if match:
1161 fontWidth, fontHeight = match.groups()
1162 fontWidth, fontHeight = int(fontWidth), int(fontHeight)
1163
1164 # estimate correct tileset size
1165 estColumns, remC = divmod(imgWidth, fontWidth)
1166 estRows, remR = divmod(imgHeight, fontHeight)
1167 if remC or remR:
1168 warnings.warn("Font may be incorrectly formatted.")
1169
1170 if not columns:
1171 columns = estColumns
1172 if not rows:
1173 rows = estRows
1174 else:
1175 # the font name excluded the fonts size
1176 if not (columns and rows):
1177 # no matched font size and no tileset is given
1178 raise TDLError('%s has no font size in filename' % os.path.basename(path))
1179
1180 if columns and rows:
1181 # confirm user set options
1182 if (fontWidth * columns != imgWidth or
1183 fontHeight * rows != imgHeight):
1184 warnings.warn("setFont parameters are set as if the image size is (%d, %d) when the detected size is actually (%i, %i)"
1185 % (fontWidth * columns, fontHeight * rows,
1186 imgWidth, imgHeight))
1187 else:
1188 warnings.warn("%s is probably not an image." % os.path.basename(path))
1189
1190 if not (columns and rows):
1191 # didn't auto-detect
1192 raise TDLError('Can not auto-detect the tileset of %s' % os.path.basename(path))
1193
1194 _lib.TCOD_console_set_custom_font(_encodeString(path), flags, columns, rows)
1195
1197 """Returns True if program is fullscreen.
1198
1199 @rtype: boolean
1200 @return: Returns True if the window is in fullscreen mode.
1201 Otherwise returns False.
1202 """
1203 if not _rootinitialized:
1204 raise TDLError('Initialize first with tdl.init')
1205 return _lib.TCOD_console_is_fullscreen()
1206
1208 """Changes the fullscreen state.
1209
1210 @type fullscreen: boolean
1211 """
1212 if not _rootinitialized:
1213 raise TDLError('Initialize first with tdl.init')
1214 _lib.TCOD_console_set_fullscreen(fullscreen)
1215
1217 """Change the window title.
1218
1219 @type title: string
1220 """
1221 if not _rootinitialized:
1222 raise TDLError('Not initilized. Set title with tdl.init')
1223 _lib.TCOD_console_set_window_title(_encodeString(title))
1224
1226 """Capture the screen and save it as a png file
1227
1228 @type path: string
1229 @param path: The filepath to save the screenshot.
1230
1231 If path is None then the image will be placed in the current
1232 folder with the names:
1233 screenshot001.png, screenshot002.png, ...
1234 """
1235 if not _rootinitialized:
1236 raise TDLError('Initialize first with tdl.init')
1237 if isinstance(fileobj, str):
1238 _lib.TCOD_sys_save_screenshot(_encodeString(fileobj))
1239 elif isinstance(fileobj, file): # save to temp file and copy to file-like obj
1240 tmpname = os.tempnam()
1241 _lib.TCOD_sys_save_screenshot(_encodeString(tmpname))
1242 with tmpname as tmpfile:
1243 fileobj.write(tmpfile.read())
1244 os.remove(tmpname)
1245 elif fileobj is None: # save to screenshot001.png, screenshot002.png, ...
1246 filelist = os.listdir('.')
1247 n = 1
1248 filename = 'screenshot%.3i.png' % n
1249 while filename in filelist:
1250 n += 1
1251 filename = 'screenshot%.4i.png' % n
1252 _lib.TCOD_sys_save_screenshot(_encodeString(filename))
1253 else:
1254 raise TypeError('fileobj is an invalid type: %s' % type(fileobj))
1255
1257 """Set the maximum frame rate.
1258
1259 @type frameRate: int
1260 @param frameRate: Further calls to L{tdl.flush} will limit the speed of
1261 the program to run at <frameRate> frames per second. Can
1262 also be set to 0 to run without a limit.
1263
1264 Defaults to None.
1265 """
1266 if frameRate is None:
1267 frameRate = 0
1268 assert isinstance(frameRate, _INTTYPES), 'frameRate must be an integer or None, got: %s' % repr(frameRate)
1269 _lib.TCOD_sys_set_fps(frameRate)
1270
1272 """Return the current frames per second of the running program set by
1273 L{setFPS}
1274
1275 @rtype: int
1276 @return: Returns the frameRate set by setFPS.
1277 If set to no limit, this will return 0.
1278 """
1279 return _lib.TCOD_sys_get_fps()
1280
1288
1289 __all__ = [_var for _var in locals().keys() if _var[0] != '_' and _var not in ['sys', 'os', 'ctypes', 'array', 'weakref', 'itertools', 'textwrap', 'struct', 're', 'warnings']]
1290 __all__ += ['_MetaConsole'] # keep this object public to show the documentation in epydoc
1291
| Home | Trees | Indices | Help |
|
|---|
| Generated by Epydoc 3.0.1 on Mon Dec 17 00:44:51 2012 | http://epydoc.sourceforge.net |