使用 pygame 创建滑块

问题描述

我正在创建一个 covid 模拟器并使用滑块来允许用户调整数字,例如待在家里的人数。我已经能够成功创建滑块,但是由于某种原因,当我尝试移动一个时,它们都会移动。我创建的代码如下:

def saved_sim():
    slider1 = 600
    slider2 = 600
    #size_of_gas_cloud = 400
    running = True
    while running:
        menu.fill(BACKGROUND_COLOR)
        title = Label(menu,"Editting features for simulation",1,font_title,BLACK,330,30)
        Sub_heading = Label(menu,"Please edit the features using sliders before selecting a location",font_para,5,100)

        if pygame.mouse.get_pressed()[0] != 0:
            # collision detection also needed here
            slider1 = pygame.mouse.get_pos()[0] - 5
            if slider1 < 600:
                slider1 = 600
            if slider1 > 800:
                slider1 = 800

        if pygame.mouse.get_pressed()[0] != 0:
            # collision detection also needed here
            slider2 = pygame.mouse.get_pos()[0] - 5
            if slider2 < 600:
                slider2 = 600
            if slider2 > 800:
                slider2 = 800

        pygame.draw.rect(menu,Rect(600,300,210,10))
        pygame.draw.rect(menu,RED,Rect(slider1,10,10))

        pygame.draw.rect(menu,400,Rect(slider2,10))

提前感谢您的帮助。

解决方法

这是一个滑块类,可以帮助您以更方便的方式创建滑块。代码已注释,但如果您有任何问题,请随时提问。

import pygame

d = pygame.display.set_mode((500,500))
pygame.init()

#Takes rectangle's size,position and a point. Returns true if that
#point is inside the rectangle and false if it isnt.
def pointInRectanlge(px,py,rw,rh,rx,ry):
    if px > rx and px < rx  + rw:
        if py > ry and py < ry + rh:
            return True
    return False

#Blueprint to make sliders in the game
class Slider:
    def __init__(self,position:tuple,upperValue:int=10,sliderWidth:int = 30,text:str="Editing features for simulation",outlineSize:tuple=(300,100))->None:
        self.position = position
        self.outlineSize = outlineSize
        self.text = text
        self.sliderWidth = sliderWidth
        self.upperValue = upperValue
        
    #returns the current value of the slider
    def getValue(self)->float:
        return self.sliderWidth / (self.outlineSize[0] / self.upperValue)

    #renders slider and the text showing the value of the slider
    def render(self,display:pygame.display)->None:
        #draw outline and slider rectangles
        pygame.draw.rect(display,(0,0),(self.position[0],self.position[1],self.outlineSize[0],self.outlineSize[1]),3)
        
        pygame.draw.rect(display,self.sliderWidth,self.outlineSize[1] - 10))

        #determite size of font
        self.font = pygame.font.Font(pygame.font.get_default_font(),int((15/100)*self.outlineSize[1]))

        #create text surface with value
        valueSurf = self.font.render(f"{self.text}: {round(self.getValue())}",True,(255,0))
        
        #centre text
        textx = self.position[0] + (self.outlineSize[0]/2) - (valueSurf.get_rect().width/2)
        texty = self.position[1] + (self.outlineSize[1]/2) - (valueSurf.get_rect().height/2)

        display.blit(valueSurf,(textx,texty))

    #allows users to change value of the slider by dragging it.
    def changeValue(self)->None:
        #If mouse is pressed and mouse is inside the slider
        mousePos = pygame.mouse.get_pos()
        if pointInRectanlge(mousePos[0],mousePos[1],self.outlineSize[1],self.position[0],self.position[1]):
            if pygame.mouse.get_pressed()[0]:
                #the size of the slider
                self.sliderWidth = mousePos[0] - self.position[0]

                #limit the size of the slider
                if self.sliderWidth < 1:
                    self.sliderWidth = 0
                if self.sliderWidth > self.outlineSize[0]:
                    self.sliderWidth = self.outlineSize[0]

slider = Slider((100,100))

while True:
    pygame.event.get()
    d.fill((255,255,255))

    slider.render(d)
    slider.changeValue()
    print(slider.getValue())
    
    pygame.display.update()
,

您必须检查鼠标光标是否在滑块的矩形区域内。使用 pygame.Rect 对象和 collidepoint() 测试鼠标光标是否在滑块上。鼠标光标的位置可以通过pygame.mouse.get_pos()获取。

slider_rect1 = pygame.Rect(600,300,210,10)
slider_rect2 = pygame.Rect(600,400,10)
mouse_pos = pygame.mouse.get_pos()

if slider_rect1.collidepoint(mouse_pos) and pygame.mouse.get_pressed()[0] != 0:
    # [...]

if slider_rect2.collidepoint(mouse_pos) and pygame.mouse.get_pressed()[0] != 0:
    # [...]

另见How to detect when a rectangular object,image or sprite is clicked

函数saved_sim

def saved_sim():
    slider1 = 600
    slider2 = 600
    #size_of_gas_cloud = 400

    slider_rect1 = pygame.Rect(600,10)
    slider_rect2 = pygame.Rect(600,10)

    running = True
    while running:
        menu.fill(BACKGROUND_COLOR)
        title = Label(menu,"Editting features for simulation",1,font_title,BLACK,330,30)
        Sub_heading = Label(menu,"Please edit the features using sliders before selecting a location",font_para,5,100)

        mouse_pos = pygame.mouse.get_pos()

        if slider_rect1.collidepoint(mouse_pos) and pygame.mouse.get_pressed()[0] != 0:
            # collision detection also needed here
            slider1 = pygame.mouse.get_pos()[0] - 5
            if slider1 < 600:
                slider1 = 600
            if slider1 > 800:
                slider1 = 800

        if slider_rect2.collidepoint(mouse_pos) and pygame.mouse.get_pressed()[0] != 0:
            # collision detection also needed here
            slider2 = pygame.mouse.get_pos()[0] - 5
            if slider2 < 600:
                slider2 = 600
            if slider2 > 800:
                slider2 = 800

        pygame.draw.rect(menu,slider_rect1)
        pygame.draw.rect(menu,RED,Rect(slider1,10,10))

        pygame.draw.rect(menu,slider_rect2)
        pygame.draw.rect(menu,Rect(slider2,10))