pygame_terminal_ii
Differences
This shows you the differences between two versions of the page.
Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
pygame_terminal_ii [2023/11/06 00:34] – appledog | pygame_terminal_ii [2023/11/06 01:58] (current) – appledog | ||
---|---|---|---|
Line 11: | Line 11: | ||
< | < | ||
+ | import pygame | ||
+ | |||
class Game: | class Game: | ||
def __init__(self, | def __init__(self, | ||
self.window = window | self.window = window | ||
self.screen = window.screen | self.screen = window.screen | ||
- | self.font = window.font | ||
self.logo = window.logo | self.logo = window.logo | ||
+ | self.font = window.font | ||
# Game Data | # Game Data | ||
self.FPS = 60 | self.FPS = 60 | ||
self.clock = pygame.time.Clock() | self.clock = pygame.time.Clock() | ||
- | |||
- | self.maze = Maze(19, 14, 30, 30) | ||
- | self.maze.set_wall(3, | ||
- | self.maze.cwidth = 40 | ||
- | self.maze.cheight = 40 | ||
- | |||
def start(self): | def start(self): | ||
Line 34: | Line 30: | ||
self.draw() | self.draw() | ||
self.clock.tick(self.FPS) | self.clock.tick(self.FPS) | ||
+ | |||
+ | def draw(self): | ||
+ | self.screen.fill((0, | ||
+ | self.drawText(0, | ||
+ | pygame.display.flip() | ||
def update(self): | def update(self): | ||
pass | pass | ||
- | def draw(self): | + | def checkEvents(self): |
- | self.screen.fill((0, 0, 0)) # Clear the screen. | + | |
+ | for event in pygame.event.get(): | ||
+ | if event.type == pygame.QUIT: | ||
+ | | ||
+ | return | ||
+ | |||
+ | if event.type == pygame.KEYDOWN: | ||
+ | # key down event, process keys. | ||
+ | |||
+ | if event.key == pygame.K_q: | ||
+ | self.quit() | ||
+ | |||
+ | def drawText(self, at_x, at_y, text, color): | ||
+ | text_surface = self.font.render(text, | ||
+ | x = self.window.fontwidth * at_x | ||
+ | y = self.window.fontheight * at_y | ||
+ | self.screen.blit(text_surface, | ||
- | pygame.display.flip() | ||
- | | ||
def quit(self): | def quit(self): | ||
quit() | quit() | ||
Line 49: | Line 64: | ||
As you can see we have moved to using self.clock.tick(self.FPS), | As you can see we have moved to using self.clock.tick(self.FPS), | ||
+ | |||
+ | update() is important because, until now, we have been responding to the user's input as it happens, and we have been ' | ||
+ | |||
+ | == Game state and update() | ||
+ | Since we are going to have a game state that will be update()' | ||
+ | |||
+ | First let's add and discuss the class, then we will integrate it into the Game class. | ||
+ | |||
+ | == Class Character | ||
+ | You will first need a simple Character class for Class Terminal: | ||
+ | |||
+ | < | ||
+ | class Character: | ||
+ | def __init__(self, | ||
+ | self.ch = ch | ||
+ | self.color = color | ||
+ | </ | ||
+ | |||
+ | This just allows us to move color data to a per-color basis. Later we can add a background color or define ANSI colors. We will save that for Pygame Terminal III. | ||
+ | |||
+ | == Class Terminal | ||
+ | < | ||
+ | from Character import Character | ||
+ | import threading | ||
+ | |||
+ | class Terminal: | ||
+ | def __init__(self, | ||
+ | self.cols = cols | ||
+ | self.rows = rows | ||
+ | self.cx=0 | ||
+ | self.cy=0 | ||
+ | self.interval = 0.535 # 535ms | ||
+ | self.cc=False | ||
+ | self.repeat_timer() | ||
+ | |||
+ | self.buf = [[0 for x in range(cols)] for y in range(rows)] | ||
+ | |||
+ | for y in range(rows): | ||
+ | for x in range(cols): | ||
+ | self.buf[y][x] = Character() | ||
+ | |||
+ | def setch(self, x, y, ch, color): | ||
+ | self.buf[y][x].ch = ch | ||
+ | self.buf[y][x].color = color | ||
+ | |||
+ | def putch(self, ch, color): | ||
+ | self.buf[self.cy][self.cx].ch = ch | ||
+ | self.buf[self.cy][self.cx].color = color | ||
+ | self.cx = self.cx + 1 | ||
+ | if self.cx >= (self.cols-1): | ||
+ | self.cx = 0 | ||
+ | self.cy = self.cy + 1 | ||
+ | |||
+ | if self.cy >= (self.rows-1): | ||
+ | print(" | ||
+ | |||
+ | def delch(self): | ||
+ | self.cx = self.cx - 1 | ||
+ | if self.cx < 0: | ||
+ | self.cx = 0 | ||
+ | |||
+ | self.buf[self.cy][self.cx].ch = ' ' | ||
+ | self.buf[self.cy][self.cx].color = ' | ||
+ | |||
+ | # Function to schedule the timer to repeat | ||
+ | def repeat_timer(self): | ||
+ | self.cc = not self.cc | ||
+ | # | ||
+ | if self.interval > 0.1: | ||
+ | threading.Timer(self.interval, | ||
+ | </ | ||
+ | |||
+ | === Cursor | ||
+ | One notable addition here is the cursor. I believe that 535ms is the speed of the original IBM-PC DOS terminal. On WIN11 systems today (2023) and on some ubuntu systems it is shown as 530ms. On a C-64 I believe the speed was 750ms. | ||
+ | |||
+ | We couldn' | ||
+ | |||
+ | === draw() in Terminal | ||
+ | If you have been following along from [[Pygame Terminal]] you will see that drawText() is in Game, and no draw() function was provided by Terminal. However, one should be. | ||
+ | |||
+ | In an early version of [[PyHack]] I copied the levelmap into the buf before drawing it: | ||
+ | |||
+ | < | ||
+ | def drawGame(self): | ||
+ | for y in range(self.level.h): | ||
+ | for x in range(self.level.w): | ||
+ | self.term.setch(x, | ||
+ | |||
+ | for y in range(self.term.rows): | ||
+ | for x in range(self.term.cols): | ||
+ | ch = self.term.buf[y][x].ch | ||
+ | color = self.term.buf[y][x].color | ||
+ | self.drawText(x, | ||
+ | |||
+ | # draw cursor | ||
+ | if self.term.cc: | ||
+ | self.drawText(self.term.cx, | ||
+ | </ | ||
+ | |||
+ | This was the initial integration, | ||
+ | |||
+ | First, add this to Terminal: | ||
+ | |||
+ | < | ||
+ | def draw(self, window): | ||
+ | for y in range(self.rows): | ||
+ | for x in range(self.cols): | ||
+ | ch = self.buf[y][x].ch | ||
+ | color = self.buf[y][x].color | ||
+ | window.drawText(x, | ||
+ | |||
+ | # draw cursor | ||
+ | if self.cc: | ||
+ | window.drawText(self.cx, | ||
+ | </ | ||
+ | |||
+ | Next, you can add this to Window: | ||
+ | |||
+ | < | ||
+ | def drawText(self, | ||
+ | text_surface = self.font.render(text, | ||
+ | x = self.fontwidth * at_x | ||
+ | y = self.fontheight * at_y | ||
+ | self.screen.blit(text_surface, | ||
+ | < | ||
+ | |||
+ | After you delete drawText() from Game, The terminal will have been fully abstracted out of the Game class. The Game class makes updates using term.setch or term.putch, and there is no special thing done other than to draw it. If a special draw function is needed one could be constructed. But in general Game no longer needs to call drawText() as if it was managing the screen instead of Terminal. | ||
+ | |||
+ | == Creating a LP/TTY device | ||
+ | The first thing we need to do is create a lp-style output device. This will require the function putch and the helper functions cr and lf. | ||
+ | |||
+ | Secondly we will need to add functions such as " | ||
pygame_terminal_ii.1699230873.txt.gz · Last modified: 2023/11/06 00:34 by appledog