Как проверить наличие плиток вокруг конкретной плитки? - PullRequest
0 голосов
/ 01 декабря 2018

Я создаю игру.

Мир игры представлен плиткой.Плитки соответствуют значениям в двумерном массиве.

Я хотел бы использовать специальный «угловой» спрайт стены, если какие-либо три настенных плитки имеют форму 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 голосов
/ 02 декабря 2018

Я бы начал с создания набора смещений

// 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`
0 голосов
/ 02 декабря 2018

Из комментариев я не уверен, в чем проблема ... позвольте мне показать вам, что я хотел бы сделать, чтобы мы могли обсудить далее, если это необходимо:

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),
          }

Я создал стенограмму, чтобы быстро проверить все 6 возможностей для стен с помощью in walls

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-формы ...), но для этого потребуются дополнительные спрайты.

Полный код, который я использовал, можно найти здесь

EDIT2 примечаниечто вам нужно будет обновить еще несколько вещей, чтобы все работало гладко (например,Инвентаризация) Кроме того, выполнение этой проверки означает, что каждый цикл является дорогостоящим, поэтому вы должны объявить логическое значение env_changed, чтобы выполнять тест только при внесении изменений в среду.

Для инвентаризации вам потребуется

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

это делает VWALL стеной по умолчанию в инвентаре, и цикл заботится о том, чтобы переключить ее на подходящую для дисплея.В остальном, ну ... это твоя игра, поэтому я позволю тебе разобраться;)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...