Python curses:addstr()从文件为lin的其余部分打印空白

2024-05-29 00:14:32 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在用Python编写一个非常简单的农业游戏,使用curses。在这一点上,我已经成功地允许玩家(只是一个“@”字符)在窗口中移动。在

我有一些ascii艺术的文件,我打印到窗口,作为填充世界的东西,在其中玩家可以移动。例如,我有一个名为“house”的文件,其中包含:

 _ . ^ . _
/____.____\
|         |
| ## _ ## |
|_""_H_""_|

我有一个事物类,如下所示:

^{pr2}$

因此,Thing类的构造函数将文件名作为参数(looksLike),draw方法打开文件,读取文件,并将其内容打印到窗口中。然后,我可以创建一个house对象,将我的“house”文件作为参数传递,我的ascii house将被打印到窗口中。在

问题是一旦对象被打印到窗口,当我将播放器移到打印对象的右侧时,播放器就会消失。然而,在打印对象的上方、下方和左侧,播放机始终处于视野中。例如

 _ . ^ . _
/____.____\
|         |
| ## _ ## |
|_""_H_""_|
                  @

在这个位置“@”字符是可见的,但是如果我向上移动一个空格,它就会消失。如果我继续向上移动播放器,“@”会在它移动到房子最上面的角色之后重新出现。在

我假设这个问题是由于addstr()和addch()在窗口结束之前都打印空白的特性造成的,但是我找不到任何关于这个的文档。在

我考虑过为每个打印的对象创建一个新窗口,但是当多个对象被打印到窗口时,这似乎会变得非常麻烦。另外,我希望在屏幕上打印的对象周围定义边框,而不是正方形或矩形。在

有没有办法从一个文件打印到窗口,而不需要为每个打印对象创建一个新窗口?在


Tags: 文件对象游戏ascii玩家世界字符播放器
2条回答

I assume this issue is due to the nature of both addstr() and addch() ( I have tried both) printing whitespace until the end of the window,

你为什么这么想?在

首先,在您展示给我们的代码中,您从未实际调用addstr,因此不可能是这样。在

至于addch,它绝对不应该像你看到的那样做,比如从右向左画。或者运行这个简单的测试代码:

# usual curses setup
stdscr.addch(10, 10, 'a')
stdscr.addch(10, 9, 'b')

如果您在测试程序中没有看到a,则说明您的终端有问题。但如果你是,那么你的假设是错误的,它与addch无关。在


几乎可以肯定的是,您的家庭文件中实际上有空格。在诅咒中,如果你在另一个字符上画一个字符,它会替换原来的字符,它不会试图合并它们,也不会将它们重写或类似的事情。(这很好,因为大多数游戏机都没有办法做到这一点……)

如果新字符是空格,它只是用空格替换旧字符。就像你看到的一样。在


所以,解决方法是删除每行末尾的空格,对吗?好吧,你可以的。或者你可以每行rstrip()。(您不需要\n;您可以通过遍历整行来判断您已经到达了一行的末尾,对吗?好吧,你可以在你的file = open(…).readlines()代码中,或者在那些不需要readlines()的代码中循环;你不能在不同的file = open(…).read()代码中使用,但是我不知道你为什么在一开始就用不同的方法来做。)

或者,由于您的find_boundries函数非常小心地跳过空格,所以您可能想在draw中执行相同的操作,但却忘记了?如果是这样,只需编写您打算跳过空格的代码。在

但是对于整个问题有一个更简单的解决方案:只要在房子后面画@,而不是在房子前面,这根本就不是问题。当然,这意味着如果玩家和房子在同一个地方,他会出现在房子的“外面”,而不是隐藏在“里面”-但是你似乎已经有了防止这种情况发生的代码,所以如果发生这种情况,它看起来像谁并不重要。在

幸运的是我从来没用过咒语,而且我看不到你的玩家等级。在

尽管如此,这个片段可能会给你一些想法(按“x”退出游戏)(使用WASD移动播放器)(需要启用ANSI的控制台:

#! /usr/bin/python3

class _GetchUnix:
    def __init__(self):
        import tty, sys

    def __call__(self):
        import sys, tty, termios
        fd = sys.stdin.fileno()
        old_settings = termios.tcgetattr(fd)
        try:
            tty.setraw(sys.stdin.fileno())
            ch = sys.stdin.read(1)
        finally:
            termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
        return ch

getch = _GetchUnix ()

house = ''' _ . ^ . _ 
/____.____\\
|         |
| ## _ ## |
|_""_H_""_|'''

class Screen:
    def __init__ (self, width, height, background):
        self.width = width
        self.height = height
        self.bg = '\x1b[{}m'.format (40 + background)
        self.clear = '\x1b[0m'
        self.objects = []

    def __iadd__ (self, obj):
        self.objects.append (obj)
        obj.screen = self
        return self

    def render (self):
        print ('\x1b[1;1H', end = '')
        for y in range (self.height):
            for x in range (self.width):
                print (self.bg + ' ' + self.clear, end = '')
            print ()
        for obj in self.objects: obj.render ()
        print ('\x1b[{};1H'.format (self.height) )

class Object:
    def __init__ (self, graphics, foreground, background, x, y):
        self.graphics = graphics.split ('\n')
        self.fg = '\x1b[{}m'.format (30 + foreground)
        self.bg = '\x1b[{}m'.format (40 + background)
        self.clear = '\x1b[0m'
        self.x = x
        self.y = y

    def render (self):
        for y, line in enumerate (self.graphics):
            print ('\x1b[{};{}H'.format (self.y + y, self.x), end = '')
            print (self.fg + self.bg + line + self.clear)

    def collide (self, x, y):
        if y < self.y: return False
        if x < self.x: return False
        if y > self.y + len (self.graphics) - 1: return False
        if x > self.x + len (self.graphics [y - self.y] ): return False
        return True

    def move (self, dx, dy):
        nx, ny = self.x + dx, self.y + dy
        if ny < 1: return
        if ny > self.screen.height: return
        if nx < 1: return
        if nx > self.screen.width: return
        for obj in self.screen.objects:
            if obj == self: continue
            if obj.collide (nx, ny): return
        self.x, self.y = nx, ny

house = Object (house, 0, 7, 6, 3)
player = Object ('@', 1, 3, 10, 10)
s = Screen (40, 20, 3)
s += house
s += player
while True:
    c = getch ()
    if c == 'x': break
    if c == 'w': player.move (0, -1)
    if c == 's': player.move (0, 1)
    if c == 'a': player.move (-1, 0)
    if c == 'd': player.move (1, 0)
    s.render ()

这里有一个屏幕截图:

{1美元^

相关问题 更多 >

    热门问题