如何检查特定图块周围的图块?

时间:2018-12-01 20:07:26

标签: python pygame

我在做游戏。

游戏世界由图块地图表示。这些图块对应于2D数组中的值。

如果任何三个墙砖都呈L形,我想使用特殊的“角”墙精灵。也就是说,

V
##      #    >##
#      ##     #
        ^

用箭头指示的图块应为边角图块。

我有用于搜索墙的代码,但是我不知道如何识别哪些砖是角砖。

我的代码是:

import pygame, sys
import Sprites
import random

from pygame.locals import *

pygame.init()


fpsClock = pygame.time.Clock()

cloudx = -200
cloudy = 0

infoObject = pygame.display.Info()

DIRT = 0
GRASS = 1
WATER = 2
COAL = 3
CLOUD = 4
WALL = 5
CWALL = 6

controls = {
    DIRT : 49,
    GRASS: 50,
    WATER: 51,
    COAL : 52,
    WALL : 53
}

infoObject = pygame.display.Info()

w = infoObject.current_w
h = infoObject.current_h

TILESIZE  = 40
MAPWIDTH  = 15
MAPHEIGHT = 15

WHITE = (255,255,255)
BLACK = (0,0,0)

resources = [DIRT, GRASS, WATER, COAL]

textures =  {
            DIRT  : pygame.image.load('Sprites/Dirt.png'),
            GRASS : pygame.image.load('Sprites/tile130.png'),
            WATER : pygame.image.load('Sprites/Water.png'),
            COAL  : pygame.image.load('Sprites/Coal.png'),
            CLOUD : pygame.image.load('Sprites/Cloud.png'),
            WALL  : pygame.image.load('Sprites/Swall.png'),
            CWALL : pygame.image.load('Sprites/Swall.png')
          }

playerPos = [0,0]

inventory = {
            DIRT   :  0,
            GRASS  :  0,
            WATER  :  0,
            COAL   :  0,
            WALL   :  10,
            }

tilemap = [[DIRT for w in range(MAPWIDTH)] for h in range(MAPHEIGHT)]



DISPLAYSURF = pygame.display.set_mode((MAPWIDTH*TILESIZE,MAPHEIGHT*TILESIZE + 50))

pygame.display.set_caption('M I N E C R A F T -- 2D')
pygame.display.set_icon(pygame.image.load('Sprites/player.png'))

PLAYER = pygame.image.load('Sprites/Player.png').convert_alpha()

for rw in range(MAPHEIGHT):
    for cl in range(MAPWIDTH):
        randomNumber = random.randint(0,15)
        if randomNumber == 0:
            tile = COAL
        elif randomNumber == 1 or randomNumber == 2:
            tile = WATER
        elif randomNumber >= 3 and randomNumber <=7:
            tile = GRASS
        else:
            tile = DIRT

        tilemap[rw][cl] = tile

INVFONT = pygame.font.Font('freesansbold.ttf', 18)

print(tilemap)

while True:

    currentTile = tilemap[playerPos[1]][playerPos[0]]

    DISPLAYSURF.fill(BLACK)

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

            pygame.quit()
            sys.exit()

        elif event.type == KEYDOWN:

            for key in controls:


                if (event.key == controls[key]):

                    if inventory[key] > 0:

                        inventory[key] -=1

                        inventory[currentTile] += 1

                        tilemap[playerPos[1]][playerPos[0]] = key

            if(event.key == K_RIGHT) and playerPos[0] < MAPWIDTH - 1:
                playerPos[0]+=1

            elif(event.key == K_LEFT) and playerPos[0] > 0:
                playerPos[0]-=1

            elif(event.key == K_DOWN) and playerPos[1] < MAPHEIGHT - 1:
                playerPos[1]+=1

            elif(event.key == K_UP) and playerPos[1] > 0:
                playerPos[1]-=1

            if event.key == K_SPACE:
                currentTile = tilemap[playerPos[1]][playerPos[0]]
                inventory[currentTile] += 1
                tilemap[playerPos[1]][playerPos[0]] = DIRT

    for row in range(MAPHEIGHT):
        for column in range(MAPWIDTH):
                DISPLAYSURF.blit(textures[tilemap[row][column]],(column*TILESIZE, row*TILESIZE, TILESIZE, TILESIZE))
                DISPLAYSURF.blit(PLAYER,(playerPos[0]*TILESIZE,playerPos[1]*TILESIZE))


    DISPLAYSURF.blit(textures[CLOUD].convert_alpha(),(cloudx,cloudy))
    cloudx +=1

    if cloudx > MAPWIDTH*TILESIZE:
        cloudy = random.randint(0, MAPHEIGHT*TILESIZE)
        cloudx = -200


    placePosition = 10
    for item in resources:
        DISPLAYSURF.blit(textures[item],(placePosition, MAPHEIGHT*TILESIZE+10))
        placePosition+=50
        textObj = INVFONT.render(str(inventory[item]), True, WHITE, BLACK)
        DISPLAYSURF.blit(textObj,(placePosition, MAPHEIGHT*TILESIZE+20))
        placePosition += 50

    pygame.display.update()
    fpsClock.tick(24)

    for x in range(MAPWIDTH):
        for y in range(MAPHEIGHT):
            if tilemap[x][y] == WALL:
                go_left = x > 1
                go_right = x < MAPWIDTH - 1
                go_up = y > 1
                go_down = y < MAPHEIGHT - 1
                if go_left:
                    tilemap[x - 1][y] = CWALL
                    if go_up:
                        pass
                if go_right:
                    tilemap[x + 1][y] = WALL 
                if go_up:
                    pass
                if go_down:
                    pass
                print('WALL')


    pygame.display.update()

这是精灵的链接: https://framadrop.org/r/fmReup_rTK#bMSywSUa7nxb1qL/a4FIbns+VaspgE0c/FU+9f1drHI=

https://framadrop.org/r/pBOfrnKcdT#eNEZQ9QjX5Cl6X4gH4UwdIg3eBPnY/L4WcSGYtUR5PE=

https://framadrop.org/r/ZFfTz_Lq9V#2Nd5ba1iE7miyFg8JpPFvwabAkdnHds/GfVkSAQeJaQ=

https://framadrop.org/r/gN9Y748L9G#Z552pPpgjTcSubt9tn74mZ0tT1COv7UCFdkUq2DorAU=

https://framadrop.org/r/d9k4hyCUni#OTza8UbsR8Am/R1PA9MAWkLDPRDBsT1rAHMgr61jusc=

https://framadrop.org/r/1mv777OR6d#pkqwaQrmVRElUPcdEV5K4UhmALsJSYX7z3WtrZXl4TE=

https://framadrop.org/r/CyF-tk7yUb#IFexcePe418JizElZzCJzDENTJPDfz7i1nr+lGns0rU=

https://framadrop.org/r/VzVfAz6bnL#oLHivyHPtTD8+IxliDD4yc+6LS9kpGyEp1HNFGUsBHo=

https://framadrop.org/r/0V0ShMH0uq#PZHdPSQNbgL7QqH2niwdS4HO34ZRMfIlhpvpRqbWwng=

2 个答案:

答案 0 :(得分:0)

根据评论,我不确定是什么问题...让我向您展示我将要做什么,以便我们可以在需要时进行进一步讨论:

for x in range(MAPWIDTH):
    for y in range(MAPHEIGHT):
        if tilemap[x][y] == WALL:
            # there is a wall at indices x and y
            # get neighbouring tiles (check for limits)
            go_left  = x > 1
            go_right = x < MAPWIDTH - 1
            go_up    = y > 1
            go_down  = y < MAPHEIGHT - 1

            if go_left:
                # you can use x-1
                tilemap[x-1][y] = WALL  # set left tile to WALL
                if go_up:
                    # do something in the diagonal with x-1 y-1?
                    pass
            if go_right:
                # you can use x+1
                tilemap[x+1][y] = WALL  # set right tile to WALL
            if go_up:
                pass # same story
            if go_down:
                pass # and again

编辑,这是一种简单的方法(因此希望很容易理解)

为了使纹理清洁,我首先必须旋转墙壁和角落以获得所有可能的配置(墙壁的垂直/水平以及角落的所有四种可能性)

VWALL = 5
HWALL = 6
CORNERLD = 7
CORNERRD = 8
CORNERLU = 9
CORNERRU = 10

controls = {
    DIRT  : 49,
    GRASS : 50,
    WATER : 51,
    COAL  : 52,
    VWALL : 53,
    HWALL : 54,
    CORNERLD: 55,
    CORNERRD: 56,
    CORNERLU: 57,
    CORNERRU: 58,
}

tex_wall   = pygame.image.load('Sprites/Swall.png')
tex_corner = pygame.image.load('Sprites/Corner.png')

textures =  {
            DIRT    : pygame.image.load('Sprites/Dirt.png'),
            GRASS   : pygame.image.load('Sprites/tile130.png'),
            WATER   : pygame.image.load('Sprites/Water.png'),
            COAL    : pygame.image.load('Sprites/Coal.png'),
            CLOUD   : pygame.image.load('Sprites/Cloud.png'),
            HWALL   : pygame.transform.rotate(tex_wall, 90),
            VWALL   : tex_wall,
            CORNERRD: tex_corner,
            CORNERLD: pygame.transform.flip(tex_corner, True, False),
            CORNERLU: pygame.transform.flip(tex_corner, True, True),
            CORNERRU: pygame.transform.flip(tex_corner, False, True),
          }

我创建了墙字典,以in walls

快速检查墙的所有6种可能性
walls = {
    VWALL : None,
    HWALL : None,
    CORNERLD: None,
    CORNERRD: None,
    CORNERLU: None,
    CORNERRU: None,
} 

然后我检查地图

for x in range(MAPWIDTH):
    for y in range(MAPHEIGHT):
        if tilemap[x][y] in walls:
            # there is a wall at indices x and y
            # get neighbouring tiles (check for limits)
            go_left  = x > 1
            go_right = x < MAPWIDTH - 1
            go_up    = y > 1
            go_down  = y < MAPHEIGHT - 1

            l_wall = False
            r_wall = False
            u_wall = False
            d_wall = False

            if go_left and tilemap[x-1][y] in walls:
                # left tile is WALL
                l_wall = True
            if go_right and tilemap[x+1][y] in walls:
                # right tile is WALL
                r_wall = True
            if go_up and tilemap[x][y-1] in walls:
                u_wall = True
            if go_down and tilemap[x][y+1] in walls:
                d_wall = True

            if l_wall and u_wall:
                # upper left corner
                tilemap[x][y] = CORNERLU
            elif l_wall and d_wall:
                # down left corner
                tilemap[x][y] = CORNERRU
            elif r_wall and u_wall:
                # upper left corner
                tilemap[x][y] = CORNERLD
            elif r_wall and d_wall:
                # down left corner
                tilemap[x][y] = CORNERRD
            elif (l_wall or r_wall) and not (u_wall or d_wall):
                # tiles in a vertical wall, use VWALL
                tilemap[x][y] = VWALL
            elif (u_wall or d_wall) and not (l_wall or r_wall):
                # tiles in a horizontal wall, use HWALL
                tilemap[x][y] = HWALL

我们得到

Your new Minecraft 2D

请注意,虽然墙的一些随机配置看起来不太好,但是(T形...),但这些墙需要额外的精灵。

我使用的完整代码可以找到here

EDIT2 请注意,您将不得不更新一些其他内容,以使一切顺利进行(例如,库存中的墙壁吸收量) 另外,每个循环都要运行此检查,因此代价很高,因此,您应该声明一个env_changed布尔值以仅在对环境进行更改时进行测试。

对于库存,您将需要

if currentTile in walls:
    inventory[VWALL] += 1

这使VWALL成为库存中的默认墙,并且循环会注意将其切换为适合显示的墙。 剩下的,好吧...这是你的游戏,所以我让你弄清楚;)

答案 1 :(得分:0)

我将从生成一个偏移量开始

// 1
//0 2  Neighbour directions
// 3
//       0  1  2  3  Corresponding offsets
dx   = [-1, 0, 1, 0]
dy   = [0, -1, 0, 1]
Nmax = 4

现在,我可以得到相邻墙的n值,就像这样:

nwalls = []
for n in range(Nmax):    #n is the direction of the neighbour
  #Ensure that the neighbour tile, identified as (x+dx[n], y+dy[n])
  #is in the map and check to see if it is a wall
  if 1<x+dx[n]<WIDTH and 1<y+dy[n]<HEIGHT and tilemap[x+dx[n]][y+dy[n]]==WALL:  
    nwalls.append(n) #Neighbour was a wall, add its direction to this list

现在,我可以将列表转换为图块名称:

#nwalls is a list of all the directions pointing to a wall
nwalls.sort()            #Sort list, e.g. 3,1,2 -> 1,2,3
nwalls = map(str,nwalls) #Convert from numbers to strings
nwalls = ''.join(nwalls) #Append strings together: ['1','2','3'] -> '123'
if nwalls:               #If the string is not empty
  nwalls = 'corner_tile_{0}.jpg'.format(nwalls) #Convert string to tile name

现在我只需要一堆名为,例如:

corner_tile_01.jpg
corner_tile_013.jpg

那我可以说:

if nwalls: #Only true if this was a corner
  Code to display the tile whose name is stored in `nwalls`