Python: создание системы инвентаря на основе слотов - PullRequest
1 голос
/ 13 марта 2019

Я пытаюсь создать систему инвентаризации в Python, используя модуль pygame. Система инвентаря похожа на Minecraft. Это система инвентаря, основанная на слотах, то есть каждый предмет прикреплен к слоту и может перемещаться по инвентарю.

Это код:

#Module that allows me to create a screen and add images to the screen
import pygame
pygame.init()
win = pygame.display.set_mode((800,600))

#Variable that will keep track of the index of what slot the player is 
#selecting
selectedSlot = None

#Function that checks whether there is collision or not 
def collision(x,y,x2,y2,w):
    if x + w > x2 > x and y+w > y2 > y:
        return True
    else:
        return False

#Slot Class
class slotClass:
    def __init__(self,x,y):
        self.x = x
        self.y = y

    def draw(self,win):
        #Draws the slots using the x and y values 
        pygame.draw.rect(win,(255,0,0),(self.x,self.y,50,50))

        #Uses a function to test for collision with the mouse's x and y values 
        if collision(self.x,self.y,mx,my,66):
            global selectedSlot
            pygame.draw.rect(win,(128,0,0),(self.x,self.y,50,50))

            #This will set an integer value to a varaible, dependent on what the index of the element the player selecting is 
            selectedSlot = slotArray.index(self)

        #Problem with code: 
        #When the following 2 lines are uncommmented, the variable selectedSlot is set to "None", regardless of whether there is collision or not
        #else:
            #selectedSlot = None

#Slot array 
slotArray = []
#Slot information
slotCount = 9


#Populates the slotArray with the desired slotCount
while len(slotArray) != slotCount:
    slotArray.append(slotClass(100+len(slotArray)*70,50))

#main loop
run = True
while run:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False

    print(selectedSlot)

    #Mouse x and y value to set to the vars mx and my
    mx,my = pygame.mouse.get_pos()
    win.fill((0,0,0))


    #For every element in the slotArray, the function draw is called from the slotClass
    for i in slotArray:
        i.draw(win)

    pygame.display.update()
pygame.quit()

Как это работает, у меня есть класс, который будет хранить информацию для каждого слота. Например, значение x, значение y и какой элемент есть в каждом слоте. Тогда у меня есть массив, который будет содержать каждый экземпляр слота. Я также определил, сколько слотов я хочу целиком.

Чтобы заполнить этот массив слотами, я сначала начал с постоянного добавления к этому массиву слотов, пока он не будет равен желаемому количеству слотов в каждом ряду. Я умножаю 55 на количество элементов в массиве, чтобы разделить слоты.

Проблема, с которой я сталкиваюсь, возникает, когда я пытаюсь создать для игрока возможность навести курсор мыши на каждый слот. Я хочу, чтобы игрок просто мог навести курсор на слот, этот слот станет другого цвета, и тогда игрок сможет выбрать предмет из указанного слота.

Я создал для этого функцию столкновения, и я вызываю эту функцию в функции рисования внутри slotClass. У меня также есть переменная slotSelected, которая отслеживает индекс слота, над которым игрок наводит курсор или зависает над ним.

Проблема, с которой я сталкиваюсь, заключается в том, что всякий раз, когда игрок наводит курсор на слот, а затем перестает зависать на любых слотах, устанавливаемый мной индекс слота по-прежнему остается индексом слота, на котором был только что игрок. Когда я добавляю оператор else, чтобы проверить, нет ли столкновения со слотом, и устанавливаю для var slotSelected что-то вроде None, например (чтобы показать, что плеер не сталкивается ни с одним слотом), var slotSelected постоянно устанавливается на None Независимо от того, есть столкновение или нет. У меня есть оператор печати, который печатает значение slotSelected. Вы заметите, что он печатает индекс слота, с которым сталкивается игрок. Однако, когда вы раскомментируете оператор else, который я содержал в slotClass, var slotSelected всегда будет иметь значение None.

Есть предложения, как это исправить?

1 Ответ

1 голос
/ 13 марта 2019

Возможно, вы могли бы попробовать проверить еще одно столкновение с фоном. Я не эксперт в pygame, но я бы использовал этот псевдокод:

if collision("with game window"): # If mouse is within your game screen
    global selectedSlot
    if collision(self.x, self.y, mx, my, 66): # mouse is on screen AND on a box
        selectedSlot = slotArray.index(self) 
    else: # mouse on screen, but not on box -> return None
      selectedSlot = None

Так что вы можете назначить None, когда мышь находится в окне вашей игры, но не в слоте предмета.

EDIT

Я понял, почему он так реагирует. У вас есть строки:

for i in slotArray:
    i.draw(win)

Который перейдет в слот 0, увидите, что он выбран -> установить selectedSlot = 0, затем перейдите в слот 1, увидите, что он не выбран -> установить selectedSlot = None ПЕРЕЗАПИСЬ значение, которое вы ранее установили , Вам нужно будет break ваш цикл, если selectedSlot не None !! Вот код для решения этой проблемы:

#Module that allows me to create a screen and add images to the screen
import pygame
pygame.init()
win = pygame.display.set_mode((800,600))

#Variable that will keep track of the index of what slot the player is
#selecting
selectedSlot = None

#Function that checks whether there is collision or not
def collision(x,y,x2,y2,w):
    if x + w > x2 > x and y+w > y2 > y:
        return True
    else:
        return False

#Slot Class
class slotClass:
    def __init__(self,x,y):
        self.x = x
        self.y = y

    def draw(self, win):
        #Draws the slots using the x and y values
        pygame.draw.rect(win, (255, 0, 0), (self.x, self.y, 50, 50))

        #Uses a function to test for collision with the mouse's x and y values
        if collision(self.x, self.y, mx, my, 66):
            global selectedSlot
            pygame.draw.rect(win, (128, 0, 0), (self.x, self.y, 50, 50))

            #This will set an integer value to a varaible, dependent on what the index of the element the player selecting is
            selectedSlot = slotArray.index(self)

        #Problem with code:
        #When the following 2 lines are uncommmented, the variable selectedSlot is set to "None", regardless of whether there is collision or not
        else:
            selectedSlot = None

#Slot array
slotArray = []
#Slot information
slotCount = 9


#Populates the slotArray with the desired slotCount
while len(slotArray) != slotCount:
    slotArray.append(slotClass(100+len(slotArray)*70,50))

#main loop
run = True
while run:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False

    #Mouse x and y value to set to the vars mx and my
    mx,my = pygame.mouse.get_pos()
    win.fill((0,0,0))


    #For every element in the slotArray, the function draw is called from the slotClass
    selectedSlot = None
    for i in slotArray:
        i.draw(win)
        if selectedSlot is not None:
            break

    print(selectedSlot)

    pygame.display.update()
pygame.quit()

Проблема в том, что вы объединили рисование элементов и выделение их в одну функцию (очень плохо). Так что теперь, когда цикл разорван, остальные поля не нарисованы !!

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