Python: создание системы инвентаризации на основе слотов

#python #inventory

#python #инвентаризация

Вопрос:

Я пытаюсь создать систему инвентаризации на 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 на количество элементов в массиве, чтобы распределить слоты.

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

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

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

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

Комментарии:

1. Я думаю, стоит отметить, что когда я раскомментирую две упомянутые вами строки, 8 окно работает. Это может быть полезной подсказкой

2. Что вы подразумеваете под works? Да, они все равно будут менять цвет, но это не моя проблема. Вы заметите, что в журнале вывода печатается индекс слота. Сначала будет указано None, пока вы не наведете курсор на слот. В этот момент постоянно печатается индекс слота, на который вы наводите курсор. Моя проблема в том, что когда вы перестаете наводить курсор на этот слот, моя программа по-прежнему думает, что вы касаетесь слота, поскольку она по-прежнему печатает индекс слота, к которому вы прикасались в последний раз. Когда я вставляю оператор else, чтобы превратить var в None, то selectedSlot всегда устанавливается в None, независимо от столкновения.

3. Как я уже сказал, если вы раскомментируете две строки else: ; selectedSlot = None , ваш код обнаружит коллизии, но только в поле в крайнем правом углу, которое выводит 8 . Я думаю, это должно быть полезной информацией для вас, чтобы выяснить, что происходит не так

4. О, теперь я понимаю, что ты имеешь в виду. Да, последний элемент в массиве всегда работает, когда эти 2 строки раскомментированы, но ни один другой элемент в массиве не будет реагировать должным образом.

5. Я обновил свой пост, чтобы решить вашу проблему, с которой вы столкнулись

Ответ №1:

Возможно, вы могли бы попробовать протестировать и другое столкновение с фоном. Я не эксперт в 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, когда мышь находится в вашем игровом окне, но не в слоте для предметов.

Редактировать

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

 for i in slotArray:
    i.draw(win)
  

Которая перейдет в слот 0, смотрите, что она выбрана -> установить selectedSlot = 0 , затем перейдите в слот 1, видите, что она не выбрана -> установите, что она selectedSlot = None ПЕРЕЗАПИСЫВАЕТ ранее установленное вами значение. Вам нужно будет break создать свой цикл, если выбранный слот не равен 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()
  

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

Комментарии:

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

2. Есть ли в pygame просто функция «мышь внутри окна»? Я полагаю, что она есть, и она будет работать таким же образом, но не будет сбоить при добавлении большего количества спрайтов

3. Я думаю, вы неправильно поняли вопрос. Проблема, с которой я сталкиваюсь, заключается не в том, когда мышь выходит из фактического окна. Это когда курсор мыши не касается ни одного из слотов, и я хочу, чтобы для параметра var selectedSlot было установлено значение None, а не индекс слота, к которому игрок в последний раз прикасался курсором. Вы заметите, что если оператор else, который я прокомментировал, раскомментирован, то для параметра var selectedSlot постоянно устанавливается значение None, независимо от того, имеет ли место столкновение со слотом. Вот в чем проблема, с которой я столкнулся.

4. Возможно, мой пост был неясен. Я отредактировал некоторые комментарии, которые, возможно, могут объяснить мою логику?

5. Я только что создал новую функцию, отвечающую за столкновение слотов в slotClass, а также создал новый цикл for для вызова этой функции, чтобы решить проблему, из-за которой поля не были нарисованы.