【问题标题】:Tile based game using pygame questions / problems使用 pygame 问题/问题的基于瓷砖的游戏
【发布时间】:2012-08-06 04:17:43
【问题描述】:

感谢您抽出宝贵时间阅读本文。我正在尝试使用 pygame 创建一个非常基本的瓷砖游戏系统。我不是最擅长 pygame,所以我可能遗漏了一些相当明显的东西。到目前为止,我将所有内容都放在一个文件中。我现在所拥有的似乎真的很草率,可能有一种更有效的方法,但现在我只是使用二维数组,其数字等于特定类型的瓷砖(草、水等)。为此,我正在使用 numpy,因为这是有人向我推荐的。虽然我不知道我是否喜欢这种方法,因为如果将来我有一些不仅仅是图形的图块,并且有更具体的属性怎么办?例如宝箱或陷阱?您将如何构建它?

但无论如何,我的问题是现在屏幕只是黑色的,并且没有绘制草砖。

代码如下:

import numpy
import pygame
import sys
from pygame.locals import *

pygame.init()

fpsClock = pygame.time.Clock()

windowWi = 800
windowHi = 608

mapWi = 50 # *16 = 800, etc
mapHi = 38

# ----- all of the images ------------------------------

grass1 = pygame.image.load('pictures\(Grass\grass1.png')


#-------------------------------------------------------
screen = pygame.display.set_mode((windowWi, windowHi))
pygame.display.set_caption("Tile Testing!")

gameRunning = True

groundArray = numpy.ones((mapWi,mapHi))

def drawMapArray(maparray):
    for x in range(mapWi,1):
        for y in range(mapHi,1):
            #Determines tile type.
            if maparray[y,x] == 1:
                screen.blit(grass1, (x*16, y*16))
            else:
                print "Nothing is here!"

while gameRunning:
    drawMapArray(groundArray)

    for event in pygame.event.get():
        if event.type == "QUIT":
            pygame.quit()
            sys.exit()



    #Updates display and then sets FPS to 30 FPS. 
    pygame.display.update()
    fpsClock.tick(30)

请随时引导我朝着更好的结构方向前进,因为我是游戏设计的新手,希望得到任何反馈!

谢谢, 瑞恩

编辑: 我已经尝试过了,这在逻辑上是有道理的,但是我得到了一个超出范围的索引错误。

def drawMapArray(maparray):
    for x in range(0,mapWi,1):
        for y in range(0,mapHi,1):
            #Determines tile type.
            if maparray[y,x] == 1:
                screen.blit(grass1, (x*16, y*16))
            else:
                print "Nothing is here!"

【问题讨论】:

  • 你的意思是在文件名pictures\(Grass\grass1.png中有一个“(”吗?
  • 我认为您的range() 调用可能是错误的方法,请尝试for x in range(1, mapWi):
  • 文件就是这样命名的哈哈,这些只是我用于测试目的的一些开源 16 位平铺图像。我会尽快更改它,因为它看起来很混乱。
  • 但是每当我似乎更改 range() 调用时,我都会得到索引超出范围的错误。
  • 我的意思是人们可能会,而不是请可能当然:-)

标签: python pygame


【解决方案1】:

当您添加更多图块类型时,一种可能会更好地扩展的解决方案是使用字典从数组中的数字获取图像,例如:

tile_dict = {1 : pygame.image.load('pictures\(Grass\grass1.png'),
             2 : pygame.image.load('pictures\rock.png')
            }

然后在你的绘图函数中从字典中绘制相关条目

def drawMapArray(maparray):
    for x in range(0, mapWi):
        for y in range(0, mapHi):
            #Determines tile type.
            current_tile = tile_dict[maparray[x, y]]
            screen.blit(current_tile, (x*16, y*16))

【讨论】:

  • 谢谢!这比我所拥有的要干净得多,并且将使我免于编写太多 if else 语句。但是,如果我有代表更复杂事物的图块,例如装有物品的箱子,或者玩家无法通过的图块,您有什么建议?我可以在这个方法的范围内做到这一点,还是必须转向 Tile 类之类的东西?
  • 是的,一旦你开始添加那种复杂的行为,你可能不得不开始考虑类。如果您对运算符重载感到满意,您可能需要考虑创建自己的数组类,将映射实现为列表列表,并通过重载__getitem__ 支持[x, y] 索引。这将允许您将自己的类/数据类型存储在数组中,而不是数字。
【解决方案2】:

你的draw方法不对。

def drawMapArray(maparray):
    for x in range(mapWi,1):
        for y in range(mapHi,1):
            #Determines tile type.
            if maparray[y,x] == 1:
                screen.blit(grass1, (x*16, y*16))

第一个错误是for x in range(mapWi,1)

看看range 函数。您使用了两个参数,因此您从mapWi 循环到1,这不是您想要的。

你想从0循环到mapWi,所以你必须使用

for x in range(mapWi):
    for y in range(mapHi):

(使用xrange 会更好,但这只是一个很小的改进)

否则,屏幕上不会绘制任何内容。


第二个错误是这一行:

if maparray[y,x] == 1:

你会得到一个IndexError,因为你混淆了数组的初始化。它实际上是 mapWi highmapHi wide。因此,您应该使用

对其进行初始化
groundArray = numpy.ones((mapHi,mapWi))

而不是

groundArray = numpy.ones((mapWi,mapHi))

为了说明,做个小测试:

>>> numpy.ones((10,5))
array([[ 1.,  1.,  1.,  1.,  1.],
       [ 1.,  1.,  1.,  1.,  1.],
       [ 1.,  1.,  1.,  1.,  1.],
       [ 1.,  1.,  1.,  1.,  1.],
       [ 1.,  1.,  1.,  1.,  1.],
       [ 1.,  1.,  1.,  1.,  1.],
       [ 1.,  1.,  1.,  1.,  1.],
       [ 1.,  1.,  1.,  1.,  1.],
       [ 1.,  1.,  1.,  1.,  1.],
       [ 1.,  1.,  1.,  1.,  1.]])
>>>

您会看到使用(10, 5) 为我们提供了height = 10width = 5 的数组。


旁注:

for event in pygame.event.get():
    if event.type == "QUIT":

什么都不做。 event.type 绝不是字符串 "QUIT"。退出事件的类型为12,或者更好:pygame.QUIT;所以它应该是:

for event in pygame.event.get():
    if event.type == pygame.QUIT:

像这样重写你的主循环:

while gameRunning:
    drawMapArray(groundArray)
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            gameRunning = False
            break

    #Updates display and then sets FPS to 30 FPS. 
    pygame.display.update()
    fpsClock.tick(30)

pygame.quit()

避免调用sys.exit

更好:将主循环拆分为通常在主循环中执行的三个步骤。

while gameRunning:
    draw()         # do all the drawing stuff in this function
    handle_input() # handle all input stuff in this function
    update()       # update the game state in this function

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多