РЕДАКТИРОВАТЬ 1 : Извините за случай. Ответ в первой части .Остальное - лишь некоторые заметки о более стандартном способе сделать то, что вы просили в PyGame.В конце концов, ответ не только для ОП, но и для всех, кто посещает эту страницу.
РЕДАКТИРОВАТЬ 2 : Обратите внимание, что мне пришлось изменить код, чтобы понизить FPS до 5 дляэто работать нормально.То, как вы проверяли наличие клика, означало, что кнопка мыши была нажата примерно на 30-40 кадров каждый клик на моей машине, что привело к переключению 30-40 кнопок, когда нужен был только один, поэтому мне пришлось снизить FPS до 5в коде.Это еще одна причина, по которой вы можете использовать другой метод, описанный мной для обработки событий.
Ответ:
Я искренне ценю простую логику, которую вы использовали для проверки щелчка мышьюбыл в пределах досягаемости объекта.
Я мог бы немного расширить ваш код, чтобы получить нужную кнопку типа «переключатель» (т. Е. При щелчке изображение и звук изменятся. Нажмите еще раз, и изображение и звук вернутся в нормальное состояние).
Однако я также хотел бы показать вам некоторые более эффективные способы обработки событий щелчков мышью и обнаружения щелчков, доступных в модуле Pygame, для улучшения вашего кода.Если вы заинтересованы и хотите знать, что я имею в виду, пожалуйста, прочитайте код ниже.Если вы просто хотите взять код и уйти, я это полностью уважаю (я тоже много этим занимался).
Вот ваш код, измененный в соответствии с вашими требованиями к переключателю (если я понял, что вы хотите сделать правильно).Замените его частью кода, которую вы указали в ответе, но имейте в виду, что это может не сработать, поскольку у меня нет вашего полного кода или использованных вами изображений / звуковых дорожек:
toggle = False
pygame.mixer.music.load("sounds\se_beep.mp3")
pygame.mixer.music.play(-1)
pygame.mixer.music.pause()
clock = pygame.time.Clock()
while True:
mousepos = pygame.mouse.get_pos()
mouseclk = pygame.mouse.get_pressed()
game.fill((0, 0, 0))
game.blit(cic, (0, 0))
if mouseclk[0] and 1227 > mousepos[0] > 1120 and 485 > mousepos[1] > 413:
if toggle:
toggle = False
pygame.mixer.music.pause()
else:
toggle = True
pygame.mixer.music.unpause()
if toggle:
game.blit(pbut_rgm84, (1120, 413))
current_weaponinf = font.render(current_weapon[1], True, (255, 0, 0))
game.blit(current_weaponinf, (930,45))
else:
game.blit(but_rgm84, (1120,413))
clock.tick(5)
Лучший способ: обработка событий
Обработка событий щелчка мышью и фактически всех других событий проста с помощью так называемого цикла событий .Хотя в этом есть немного больше, чем сейчас, сейчас мы можем сказать, что цикл обработки событий проверяет определенные события, инициируемые (например, нажатие клавиши, щелчок мыши, выход из игровых событий) в каждом кадре, а затем запускает функцию обратного вызова.
У вас уже есть один в вашем коде!- В каждом цикле в цикле while вы проверяете, была ли нажата мышь, используя mouseclk = pygame.mouse.get_pressed()
Однако это неполно и не является стандартным способом реализации циклов событий с использованием модуля Pygame.Вот как вы это делаете ( прочитайте комментарий над каждой строкой, чтобы понять, что он делает ):
import pygame
from pygame.locals import *
...
# Main game loop - this is the while loop you have in your code. This is where frames are rendered on every new loop
while True:
#Get all event that have been triggered from the last frame
events = pygame.event.get()
# Now we go through each event separately
for event in events:
#Use an if statement to check what the event is. For example...
if event.type == MOUSEBUTTONDOWN: #If this event was a mouse button click
print("Clicked") #Do whatever function
elif event.type == QUIT: #If this event was quitting the game, i.e: pressing the X button on the game window
pygame.quit() #Close the game
#and so on. You can have as many elifs to check all the events you need
game.fill((0,0,0)) #... The rest of your code goes after the for loop (event loop)
Итак, по сути, в вашем основном игровом цикле (вашем цикле while) у вас естьвнутри него цикл for (цикл обработки событий), а затем после его возврата в основной цикл while у вас есть оставшаяся часть кода, которую необходимо выполнить для каждого кадра, такого как рендеринг изображений и анимация спрайтов.
A Better Way: Rect Objects
Вы обнаружите, что, чтобы увидеть, находится ли позиция щелчка мыши (x, y) в пределах диапазона кнопки мыши, вы должны были проверить, было ли значение x щелчка мыши в пределах диапазонаот X1 до X2 объекта, на который вы щелкаете (верхний правый и верхний левый углы), и в то же время он также должен находиться в диапазоне от Y1 до Y2 объекта (верхний правый и нижний правый углы), что эффективноозначает, что мышь находилась где-то на объекте, когда было вызвано событие щелчка мыши
. Для этого Pygame реализует Rect объекты.Прямоугольник можно объяснить как воображаемый прямоугольник с шириной и высотой, которые вы определяете при его создании (я покажу вам, как это делается в приведенном ниже коде).Чтобы быть более реалистичным, это объект-пигмейм для хранения прямоугольных координат (диапазон всех точек в этом прямоугольнике).
Теперь дело в том, что у этого прямоугольного объекта есть методы, подобные Rect.collidepoint
, которые будут возвращать True, если позиция щелчка мыши находится внутри прямоугольника.Это более простой и понятный способ определения, находится ли позиция щелчка мыши внутри прямоугольника или вне его.
Итак.
# Constructing a rect at position (0, 0) with width 100 and height 500
r = pygame.Rect(0, 0, 100, 50)
# Now lets assume that above there is code where a mouse click is detect and the position is stored in `mousepos`, where `mousepos[0]` is the X and `mousepos[1]` is the Y
# All we have to do now is tell pygame to check if this position is inside our Rect object *r* or not
if r.collidepoint(mousepos):
print("You clicked inside an imaginary box")
else:
print("You clicked outside my imaginary box")
# Simple!!!
Намного проще и удобочитаемее!(особенно после того, как вы удалите комментарии, вы будете ошеломлены простотой этого (точка столкновения означает внутри прямоугольника).
В действительности это не то, как вы обычно используете rects , хотя этодает базовое представление о том, что они из себя представляют. Rects используются в более объектно-ориентированном методе, где кнопка является дочерним классом класса Pygame.sprite.Sprite. Затем вы можете назначить объект rect как его self.image.rectсвойство и использовать его оттуда. ПРИМЕЧАНИЕ: это не очень подробно: D.
Кроме того, это не единственное использование rects. Вы можете проверить, находится ли один прямоугольник внутри другого. Вы можете проверить, если группаобъектов внутри прямоугольника. Вы можете даже с помощью только одной строки кода проверить, находится ли один объект группы внутри определенного прямоугольника, и если это так, удалить его!
Чтобы понять, каккодировать Pygame от начала до конца (так как дополнительная часть этого ответа, говорящая о событиях и ритах, очень неполна и только там как отправная точка), я бы предложилэто превосходная, но очень простая и понятная книга .И все, что вам нужно, это базовое понимание синтаксиса Python.