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