1 """
2 The documentation for python-tdl. A Pythonic port of
3 U{libtcod<http://doryen.eptalys.net/libtcod/>}.
4
5 Getting Started
6 ===============
7 Once the library is imported you can load the font you want to use with
8 L{tdl.setFont}.
9 This is optional and when skipped will use a decent default font.
10
11 After that you call L{tdl.init} to set the size of the window and get the
12 root console in return.
13 This console is the canvas to what will appear on the screen.
14
15 Indexing Consoles
16 =================
17 For most methods taking a position you can use Python-style negative
18 indexes to refer to the opposite side of a console with (-1, -1)
19 starting at the bottom right.
20 You can also check if a point is part of a console using containment
21 logic i.e. ((x, y) in console).
22
23 Drawing
24 =======
25 Once you have the root console from L{tdl.init} you can start drawing on
26 it using a method such as L{Console.drawChar}.
27 When using this method you can have the char parameter be an integer or a
28 single character string.
29 The fgcolor and bgcolor parameters expect a three item list
30 [red, green, blue] with integers in the 0-255 range with [0, 0, 0] being
31 black and [255, 255, 255] being white.
32 Or instead you can use None for any of the three parameters to tell the
33 library to keep what is at that spot instead of overwriting it.
34 After the drawing functions are called a call to L{tdl.flush} will update
35 the screen.
36 """
37
38 import sys
39 import os
40 import ctypes
41 import weakref
42 import array
43 import itertools
44 import textwrap
45
46 from . import event, map
47 from .__tcod import _lib, _Color, _unpackfile
48
49 _IS_PYTHON3 = (sys.version_info[0] == 3)
50
51 if _IS_PYTHON3:
52 _INTTYPES = (int,)
53 _NUMTYPES = (int, float)
54 _STRTYPES = (str, bytes)
55 else:
56 _INTTYPES = (int, long)
57 _NUMTYPES = (int, long, float)
58 _STRTYPES = (str,)
61 "changes string into bytes if running in python 3, for sending to ctypes"
62 if _IS_PYTHON3 and isinstance(string, str):
63 return string.encode()
64 return string
65
83
84 _fontinitialized = False
85 _rootinitialized = False
86 _rootconsole = None
87
88 _setchar = _lib.TCOD_console_set_char
89 _setfore = _lib.TCOD_console_set_char_foreground
90 _setback = _lib.TCOD_console_set_char_background
91 _setcharEX = _lib.TCOD_console_put_char_ex
93 """Used internally.
94 Raise an assertion error if the parameters can not be converted into colors.
95 """
96 for color in colors:
97 assert _iscolor(color), 'a color must be a 3 item tuple, web format, or None, received %s' % repr(color)
98 return True
99
101 """Used internally.
102 A debug function to see if an object can be used as a TCOD color struct.
103 None counts as a parameter to keep the current colors instead.
104
105 This function is often part of an inner-loop and can slow a program down.
106 It has been made to work with assert and can be skipped with the -O flag.
107 Still it's called often and must be optimized.
108 """
109 if color is None:
110 return True
111 if isinstance(color, (tuple, list, _Color)):
112 return len(color) == 3
113 if isinstance(color, _INTTYPES):
114 return True
115 return False
116
128
130 """
131 The catch all for most TDL specific errors.
132 """
133
236
287
337
356
383
440
447
474 def getCover(x, length):
475 """return the (x, width) ranges of what is covered and uncovered"""
476 cover = (0, length)
477 uncover = None
478 if x > 0:
479 cover = (x, length - x)
480 uncover = (0, x)
481 elif x < 0:
482 x = abs(x)
483 cover = (0, length - x)
484 uncover = (length - x, x)
485 return cover, uncover
486
487 width, height = self.getSize()
488 if abs(x) >= width or abs(y) >= height:
489 return self.clear()
490
491
492 coverX, uncoverX = getCover(x, width)
493 coverY, uncoverY = getCover(y, height)
494
495
496
497
498
499
500
501 x, width, srcx = getSlide(x, width)
502 y, height, srcy = getSlide(y, height)
503 self.blit(self, x, y, width, height, srcx, srcy)
504
505 if uncoverX:
506 self.drawRect(uncoverX[0], coverY[0], uncoverX[1], coverY[1], 0x20)
507 if uncoverY:
508 self.drawRect(coverX[0], uncoverY[0], coverX[1], uncoverY[1], 0x20)
509 if uncoverX and uncoverY:
510 self.drawRect(uncoverX[0], uncoverY[0], uncoverX[1], uncoverY[1], 0x20)
511
524
530
532 """Contains character and color data and can be drawn to.
533
534 The console created by the L{tdl.init} function is the root console and is the
535 console that is rendered to the screen with L{flush}.
536
537 Any console created from the Console class is an off-screen console that
538 can be drawn on before being L{blit} to the root console.
539 """
540
541 __slots__ = ('_as_parameter_', '_typewriter')
542
544 """Create a new offscreen console.
545
546 @type width: int
547 @param width: Width of the console in tiles
548 @type height: int
549 @param height: Height of the console in tiles
550 """
551 if not _rootinitialized:
552 raise TDLError('Can not create Console\'s before tdl.init')
553 self._as_parameter_ = _lib.TCOD_console_new(width, height)
554 self.console = self
555 self.width = width
556 self.height = height
557 self._typewriter = None
558
559
560 @classmethod
562 """Make a Console instance, from a console ctype"""
563 self = cls.__new__(cls)
564 self._as_parameter_ = console
565 self.console = self
566 self.width = _lib.TCOD_console_get_width(self)
567 self.height = _lib.TCOD_console_get_height(self)
568 self._typewriter = None
569
570 return self
571
585
600
602 """Convertion x and y to their position on the root Console for this Window
603
604 Because this is a Console instead of a Window we return the paramaters
605 untouched"""
606 return x, y
607
608 - def clear(self, fgcolor=(255, 255, 255), bgcolor=(0, 0, 0)):
609 """Clears the entire Console.
610
611 @type fgcolor: (r, g, b)
612 @param fgcolor: Foreground color.
613
614 Must be a 3-item list with integers that range 0-255.
615
616 Unlike most other operations you can not use None here.
617 @type bgcolor: (r, g, b)
618 @param bgcolor: Background color. See fgcolor.
619 """
620 assert _verify_colors(fgcolor, bgcolor)
621 assert fgcolor and bgcolor, 'Can not use None with clear'
622 self._typewriter = None
623 _lib.TCOD_console_set_default_background(self, _formatColor(bgcolor))
624 _lib.TCOD_console_set_default_foreground(self, _formatColor(fgcolor))
625 _lib.TCOD_console_clear(self)
626
627 - def _setChar(self, x, y, char, fgcolor=None, bgcolor=None, bgblend=1):
628 """
629 Sets a character.
630 This is called often and is designed to be as fast as possible.
631
632 Because of the need for speed this function will do NO TYPE CHECKING
633 AT ALL, it's up to the drawing functions to use the functions:
634 _formatChar and _formatColor before passing to this."""
635
636 console = self._as_parameter_
637
638 if char is not None and fgcolor is not None and bgcolor is not None:
639 _setcharEX(console, x, y, char, fgcolor, bgcolor)
640 return
641 if char is not None:
642 _setchar(console, x, y, char)
643 if fgcolor is not None:
644 _setfore(console, x, y, fgcolor)
645 if bgcolor is not None:
646 _setback(console, x, y, bgcolor, bgblend)
647
648 - def _setCharBatch(self, batch, fgcolor, bgcolor, bgblend=1, nullChar=False):
649 """
650 Try to perform a batch operation otherwise fall back to _setChar.
651 If fgcolor and bgcolor are defined then this is faster but not by very
652 much.
653
654 batch is a iterable of [(x, y), ch] items
655 """
656 if fgcolor and bgcolor and not nullChar:
657
658 self._typewriter = None
659 console = self._as_parameter_
660 bgblend = ctypes.c_int(bgblend)
661
662 _lib.TCOD_console_set_default_background(console, bgcolor)
663 _lib.TCOD_console_set_default_foreground(console, fgcolor)
664 _putChar = _lib.TCOD_console_put_char
665 for (x, y), char in batch:
666 _putChar(console, x, y, char, bgblend)
667 else:
668 for (x, y), char in batch:
669 self._setChar(x, y, char, fgcolor, bgcolor, bgblend)
670
672
673 x, y = self._normalizePoint(x, y)
674 char = _lib.TCOD_console_get_char(self, x, y)
675 bgcolor = _lib.TCOD_console_get_char_background_wrapper(self, x, y)
676 fgcolor = _lib.TCOD_console_get_char_foreground_wrapper(self, x, y)
677 return char, tuple(fgcolor), tuple(bgcolor)
678
680 return "<Console (Width=%i Height=%i)>" % (self.width, self.height)
681
682
683 -class Window(_MetaConsole):
684 """A Window contains a small isolated part of a Console.
685
686 Drawing on the Window draws on the Console.
687
688 Making a Window and setting its width or height to None will extend it to
689 the edge of the console.
690 """
691
692 __slots__ = ('parent', 'x', 'y')
693
694 - def __init__(self, console, x, y, width, height):
695 """Isolate part of a L{Console} or L{Window} instance.
696
697 @type console: L{Console} or L{Window}
698 @param console: The parent object which can be a L{Console} or another
699 L{Window} instance.
700
701 @type x: int
702 @param x: X coordinate to place the Window.
703
704 This follows the normal rules for indexing so you can use a
705 negative integer to place the Window relative to the bottom
706 right of the parent Console instance.
707 @type y: int
708 @param y: Y coordinate to place the Window.
709
710 See x.
711
712 @type width: int or None
713 @param width: Width of the Window.
714
715 Can be None to extend as far as possible to the
716 bottom right corner of the parent Console or can be a
717 negative number to be sized reltive to the Consoles total
718 size.
719 @type height: int or None
720 @param height: Height of the Window.
721
722 See width.
723 """
724 assert isinstance(console, (Console, Window)), 'console parameter must be a Console or Window instance, got %s' % repr(console)
725 self.parent = console
726 self.x, self.y, self.width, self.height = console._normalizeRect(x, y, width, height)
727 if isinstance(console, Console):
728 self.console = console
729 else:
730 self.console = self.parent.console
731
733 """Convertion x and y to their position on the root Console"""
734
735 return self.parent._translate((x + self.x), (y + self.y))
736
737 - def clear(self, fgcolor=(255, 255, 255), bgcolor=(0, 0, 0)):
738 """Clears the entire Window.
739
740 @type fgcolor: (r, g, b)
741 @param fgcolor: Foreground color.
742
743 Must be a 3-item list with integers that range 0-255.
744
745 Unlike most other operations you can not use None here.
746 @type bgcolor: (r, g, b)
747 @param bgcolor: Background color. See fgcolor.
748 """
749 assert _verify_colors(fgcolor, bgcolor)
750 assert fgcolor and bgcolor, 'Can not use None with clear'
751 self.draw_rect(0, 0, None, None, 0x20, fgcolor, bgcolor)
752
753 - def _setChar(self, x, y, char=None, fgcolor=None, bgcolor=None, bgblend=1):
754 self.parent._setChar((x + self.x), (y + self.y), char, fgcolor, bgcolor, bgblend)
755
757 myX = self.x
758 myY = self.y
759 self.parent._setCharBatch((((x + myX, y + myY), ch) for ((x, y), ch) in batch),
760 fgcolor, bgcolor, bgblend)
761
762
763 - def drawChar(self, x, y, char, fgcolor=(255, 255, 255), bgcolor=(0, 0, 0)):
767
768 - def drawRect(self, x, y, width, height, string, fgcolor=(255, 255, 255), bgcolor=(0, 0, 0)):
769
770 x, y, width, height = self._normalizeRect(x, y, width, height)
771 self.parent.drawRect(x + self.x, y + self.y, width, height, string, fgcolor, bgcolor)
772
773 - def drawFrame(self, x, y, width, height, string, fgcolor=(255, 255, 255), bgcolor=(0, 0, 0)):
774
775 x, y, width, height = self._normalizeRect(x, y, width, height)
776 self.parent.drawFrame(x + self.x, y + self.y, width, height, string, fgcolor, bgcolor)
777
782
784 return "<Window(X=%i Y=%i Width=%i Height=%i)>" % (self.x, self.y,
785 self.width,
786 self.height)
787
790 """Converts a console into a scrolling text log that respects special
791 characters.
792
793 This class works best on a L{Window} or off-screen L{Console} instance.
794 In a L{Window} for example the scrolling text is limited to the L{Window}'s
795 isolated area.
796 """
797
799 """Add a virtual cursor to a L{Console} or L{Window} instance.
800
801 @type console: L{Console} or L{Window}
802 """
803 assert isinstance(console, (Console, Window)), 'console parameter must be a Console or Window instance, got %s' % repr(console)
804 self.parent = console
805 if isinstance(self.parent, Console):
806 self.console = self.parent
807 else:
808 self.console = self.parent.console
809 self.cursor = (0, 0)
810 self.scrollMode = 'scroll'
811 self.fgcolor = _formatColor((255, 255, 255))
812 self.bgcolor = _formatColor((0, 0, 0))
813 self._bgblend = 1
814
816 """return the normalized the cursor position."""
817 width, height = self.parent.getSize()
818 while x >= width:
819 x -= width
820 y += 1
821 while y >= height:
822 if self.scrollMode == 'scroll':
823 y -= 1
824 self.parent.scroll(0, -1)
825 elif self.scrollMode == 'error':
826
827 self.cursor = (0, 0)
828 raise TDLError('Typewriter cursor has reached the end of the console')
829 return (x, y)
830
832 """Return the virtual cursor position.
833
834 @rtype: (int, int)
835 @return: Returns (x, y) a 2-integer tuple containing where the next
836 L{addChar} or L{addStr} will start at.
837
838 This can be changed with the L{move} method."""
839 x, y = self.cursor
840 width, height = self.parent.getSize()
841 while x >= width:
842 x -= width
843 y += 1
844 if y >= height and self.scrollMode == 'scroll':
845 y = height - 1
846 return x, y
847
848 - def move(self, x, y):
849 """Move the virtual cursor.
850
851 @type x: int
852 @param x: X position to place the cursor.
853 @type y: int
854 @param y: Y position to place the cursor.
855 """
856 self.cursor = self.parent._normalizePoint(x, y)
857
859 """Change the foreground color"""
860 assert _iscolor(color)
861 self.fgcolor = _formatColor(color)
862 if self.console._typewriter is self:
863 _lib.TCOD_console_set_default_foreground(self.console, self.fgcolor)
864
866 """Change the background color"""
867 assert _iscolor(color)
868 self.bgcolor = _formatColor(color)
869 if self.console._typewriter is self:
870 _lib.TCOD_console_set_default_background(self.console, self.bgcolor)
871
873 """Make sure the colors on a console match the Typewriter instance"""
874 if self.console._typewriter is not self:
875 self.console._typewriter = self
876
877 _lib.TCOD_console_set_default_background(self.console, self.bgcolor)
878 _lib.TCOD_console_set_default_foreground(self.console, self.fgcolor)
879
880
882 """Draw a single character at the cursor."""
883 if char == '\n':
884 x = 0
885 y += 1
886 return
887 if char == '\r':
888 x = 0
889 return
890 x, y = self._normalize(*self.cursor)
891 self.cursor = [x + 1, y]
892 self._updateConsole()
893 x, y = self.parent._translate(x, y)
894 _lib.TCOD_console_put_char(self.console._as_parameter_, x, y, _formatChar(char), self._bgblend)
895
896
898 """Write a string at the cursor. Handles special characters such as newlines.
899
900 @type string: string
901 @param string:
902 """
903 x, y = self.cursor
904 for char in string:
905 if char == '\n':
906 x = 0
907 y += 1
908 continue
909 if char == '\r':
910 x = 0
911 continue
912 x, y = self._normalize(x, y)
913 self.parent.drawChar(x, y, char, self.fgcolor, self.bgcolor)
914 x += 1
915 self.cursor = (x, y)
916
917 - def write(self, string):
918 """This method mimics basic file-like behaviour.
919
920 Because of this method you can replace sys.stdout or sys.stderr with
921 a L{Typewriter} instance.
922
923 @type string: string
924 """
925
926
927
928 x, y = self._normalize(*self.cursor)
929 width, height = self.parent.getSize()
930 wrapper = textwrap.TextWrapper(initial_indent=(' '*x), width=width)
931 writeLines = []
932 for line in string.split('\n'):
933 if line:
934 writeLines += wrapper.wrap(line)
935 wrapper.initial_indent = ''
936 else:
937 writeLines.append([])
938
939 for line in writeLines:
940 x, y = self._normalize(x, y)
941 self.parent.drawStr(x, y, line[x:], self.fgcolor, self.bgcolor)
942 y += 1
943 x = 0
944 y -= 1
945 self.cursor = (x, y)
946
947
948 -def init(width, height, title='python-tdl', fullscreen=False, renderer='OPENGL'):
949 """Start the main console with the given width and height and return the
950 root console.
951
952 Call the consoles drawing functions. Then remember to use L{tdl.flush} to
953 make what's drawn visible on the console.
954
955 @type width: int
956 @param width: width of the root console (in tiles)
957
958 @type height: int
959 @param height: height of the root console (in tiles)
960
961 @type title: string
962 @param title: Text to display as the window title.
963
964 @type fullscreen: boolean
965 @param fullscreen: Can be set to True to start in fullscreen mode.
966
967 @type renderer: string
968 @param renderer: Can be one of 'GLSL', 'OPENGL', or 'SDL'.
969
970 Due to way Python works you're unlikely to see much of an
971 improvement by using 'GLSL' or 'OPENGL' as most of the
972 time Python is slow interacting with the console and the
973 rendering itself is pretty fast even on 'SDL'.
974
975 This should be left at default or switched to 'SDL' for
976 better reliability and an instantaneous start up time.
977
978 @rtype: L{Console}
979 @return: The root console. Only what is drawn on the root console is
980 what's visible after a call to L{tdl.flush}.
981 After the root console is garbage collected, the window made by
982 this function will close.
983 """
984 RENDERERS = {'GLSL': 0, 'OPENGL': 1, 'SDL': 2}
985 global _rootinitialized, _rootconsole
986 if not _fontinitialized:
987 setFont(_unpackfile('terminal.png'), 16, 16, colomn=True)
988
989 if renderer.upper() not in RENDERERS:
990 raise TDLError('No such render type "%s", expected one of "%s"' % (renderer, '", "'.join(RENDERERS)))
991 renderer = RENDERERS[renderer.upper()]
992
993
994 if _rootconsole is not None:
995 oldroot = _rootconsole()
996 rootreplacement = Console(oldroot.width, oldroot.height)
997 rootreplacement.blit(oldroot)
998 oldroot._replace(rootreplacement)
999 del rootreplacement
1000
1001 _lib.TCOD_console_init_root(width, height, _encodeString(title), fullscreen, renderer)
1002
1003
1004
1005
1006 event._eventsflushed = False
1007 _rootinitialized = True
1008 rootconsole = Console._newConsole(ctypes.c_void_p())
1009 _rootconsole = weakref.ref(rootconsole)
1010
1011 return rootconsole
1012
1014 """Make all changes visible and update the screen.
1015
1016 Remember to call this function after drawing operations.
1017 Calls to flush will enfore the frame rate limit set by L{tdl.setFPS}.
1018
1019 This function can only be called after L{tdl.init}
1020 """
1021 if not _rootinitialized:
1022 raise TDLError('Cannot flush without first initializing with tdl.init')
1023
1024 _lib.TCOD_console_flush()
1025
1026 -def setFont(path, tileWidth, tileHeight, colomn=False,
1027 greyscale=False, altLayout=False):
1028 """Changes the font to be used for this session.
1029 This should be called before L{tdl.init}
1030
1031 While it's possible you can change the font mid program it can sometimes
1032 break in rare circumstances. So use caution when doing this.
1033
1034 @type path: string
1035 @param path: Must be a string filepath where a bmp or png file is found.
1036
1037 @type tileWidth: int
1038 @param tileWidth: The width of an individual tile.
1039
1040 @type tileHeight: int
1041 @param tileHeight: The height of an individual tile.
1042
1043 @type colomn: boolean
1044 @param colomn: Defines if the characer order goes along the rows or
1045 colomns.
1046 It should be True if the charater codes 0-15 are in the
1047 first column. And should be False if the characters 0-15
1048 are in the first row.
1049
1050 @type greyscale: boolean
1051 @param greyscale: Creates an anti-aliased font from a greyscale bitmap.
1052 Otherwise it uses the alpha channel for anti-aliasing.
1053
1054 @type altLayout: boolean
1055 @param altLayout: An alternative layout with space in the upper left
1056 corner. The colomn parameter is ignored if this is
1057 True, find examples of this layout in the font/
1058 directory included with the python-tdl source.
1059
1060 @raise TDLError: Will be raised if no file is found at path.
1061
1062 @note: A png file that's been optimized can fail to load correctly on
1063 MAC OS X creating a garbled mess when rendering.
1064 Don't use a program like optipng or just use bmp files instead if
1065 you want your program to work on macs.
1066 """
1067
1068 FONT_LAYOUT_ASCII_INCOL = 1
1069 FONT_LAYOUT_ASCII_INROW = 2
1070 FONT_TYPE_GREYSCALE = 4
1071 FONT_LAYOUT_TCOD = 8
1072 global _fontinitialized
1073 _fontinitialized = True
1074 flags = 0
1075 if altLayout:
1076 flags |= FONT_LAYOUT_TCOD
1077 elif colomn:
1078 flags |= FONT_LAYOUT_ASCII_INCOL
1079 else:
1080 flags |= FONT_LAYOUT_ASCII_INROW
1081 if greyscale:
1082 flags |= FONT_TYPE_GREYSCALE
1083 if not os.path.exists(path):
1084 raise TDLError('no file exists at: "%s"' % path)
1085 _lib.TCOD_console_set_custom_font(_encodeString(path), flags, tileWidth, tileHeight)
1086
1088 """Returns True if program is fullscreen.
1089
1090 @rtype: boolean
1091 @return: Returns True if the window is in fullscreen mode.
1092 Otherwise returns False.
1093 """
1094 if not _rootinitialized:
1095 raise TDLError('Initialize first with tdl.init')
1096 return _lib.TCOD_console_is_fullscreen()
1097
1099 """Changes the fullscreen state.
1100
1101 @type fullscreen: boolean
1102 """
1103 if not _rootinitialized:
1104 raise TDLError('Initialize first with tdl.init')
1105 _lib.TCOD_console_set_fullscreen(fullscreen)
1106
1108 """Change the window title.
1109
1110 @type title: string
1111 """
1112 if not _rootinitialized:
1113 raise TDLError('Not initilized. Set title with tdl.init')
1114 _lib.TCOD_console_set_window_title(_encodeString(title))
1115
1117 """Capture the screen and save it as a png file
1118
1119 @type path: string
1120 @param path: The filepath to save the screenshot.
1121
1122 If path is None then the image will be placed in the current
1123 folder with the names:
1124 screenshot001.png, screenshot002.png, ...
1125 """
1126 if not _rootinitialized:
1127 raise TDLError('Initialize first with tdl.init')
1128 if isinstance(fileobj, str):
1129 _lib.TCOD_sys_save_screenshot(_encodeString(fileobj))
1130 elif isinstance(fileobj, file):
1131 tmpname = os.tempnam()
1132 _lib.TCOD_sys_save_screenshot(_encodeString(tmpname))
1133 with tmpname as tmpfile:
1134 fileobj.write(tmpfile.read())
1135 os.remove(tmpname)
1136 elif fileobj is None:
1137 filelist = os.listdir('.')
1138 n = 1
1139 filename = 'screenshot%.3i.png' % n
1140 while filename in filelist:
1141 n += 1
1142 filename = 'screenshot%.4i.png' % n
1143 _lib.TCOD_sys_save_screenshot(_encodeString(filename))
1144 else:
1145 raise TypeError('fileobj is an invalid type: %s' % type(fileobj))
1146
1148 """Set the maximum frame rate.
1149
1150 @type frameRate: int
1151 @param frameRate: Further calls to L{tdl.flush} will limit the speed of
1152 the program to run at <frameRate> frames per second. Can
1153 also be set to 0 to run without a limit.
1154
1155 Defaults to None.
1156 """
1157 if frameRate is None:
1158 frameRate = 0
1159 assert isinstance(frameRate, _INTTYPES), 'frameRate must be an integer or None, got: %s' % repr(frameRate)
1160 _lib.TCOD_sys_set_fps(frameRate)
1161
1163 """Return the current frames per second of the running program set by
1164 L{setFPS}
1165
1166 @rtype: int
1167 @return: Returns the frameRate set by setFPS.
1168 If set to no limit, this will return 0.
1169 """
1170 return _lib.TCOD_sys_get_fps()
1171
1173 """Change the fullscreen resoulution
1174
1175 @type width: int
1176 @type height: int
1177 """
1178 _lib.TCOD_sys_force_fullscreen_resolution(width, height)
1179
1180 __all__ = [_var for _var in locals().keys() if _var[0] != '_' and _var not in ['sys', 'os', 'ctypes', 'array', 'weakref', 'itertools', 'textwrap']]
1181 __all__ += ['_MetaConsole']
1182