【问题标题】:Pygame Scroll Bar To Play Volume Low OR High.?Pygame 滚动条播放音量低还是高。?
【发布时间】:2021-02-22 01:41:30
【问题描述】:

所以我在我的游戏中有一个滚动条我想做的是让它如果我的鼠标在 bar1 按钮上,我们在 bar1 按钮的 moving_spot 上,然后我们可以在其 y 轴上上下移动它

我如何上下移动控制条,如果它与任何音量按钮发生碰撞,我可以将背景音乐的音量更改为 0.1 或 0.2 或 0.3,以便它控制我的游戏音量pygame.mixer.music.set_volume(0.3)

我的问题是我不确定我如何开始这个我已经准备好了一切但不知道从哪里开始***我怎样才能用我的鼠标在 moving_spot 上移动它的 y 值并且如果 bar1 结束并且音量 1 2 或 3 4 按钮然后它应该在不同级别播放音量 我不确定如何解决这个问题任何帮助表示赞赏我只需要一种方法来调整我的游戏音乐如果玩家向上或向下移动酒吧

while run:
    # Making game run with fps
    clock.tick(fps)
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False


        if event.type == pygame.MOUSEBUTTONDOWN:
            pos = pygame.mouse.get_pos()
        
              # this is our bar1 the gray part that we will be able to move
            if bar1.isOver(pos):
                bar1.y = pos
                print("WORKING{")
                

这是我的按钮和位置 move_spot 是 bar1 只能上下移动的地方 bar1是播放器可以控制音量的bar 以及音量 1 2 3 4 将设置我们背景音乐的不同音量

move_spot = button((colors),720,125,25,260, '')

bar1 = button((colors),715,125,30,60, '')
volume1 = button((colors2),715,145,30,60, '')
volume2 = button((colors2),715,210,30,60, '')
volume3 = button((colors2),715,280,30,60, '')
volume4 = button((colors2),715,350,30,60, '')


buttons = [bar1,move_spot,volume1,volume2,volume3,volume4]

这是我的按钮类

# our buttons
class button():
    def __init__(self, color, x,y,width,height, text=''):
        self.color = color
        self.x = x
        self.y = y
        self.width = width
        self.height = height
        self.text = text
        self.over = False

    def draw(self,window,outline=None):
                #Call this method to draw the button on the screen
        if outline:
            pygame.draw.rect(window, outline, (self.x-2,self.y-2,self.width+4,self.height+4),0)
                    
        pygame.draw.rect(window, self.color, (self.x,self.y,self.width,self.height),0)
                
        if self.text != '':
            font = pygame.font.SysFont('image/abya.ttf', 60)
            text = font.render(self.text, 1, (255,255,255))
            window.blit(text, (self.x + (self.width/2 - text.get_width()/2), self.y + (self.height/2 - text.get_height()/2)))

    def isOver(self, pos):
                #Pos is the mouse position or a tuple of (x,y) coordinates
        if pos[0] > self.x and pos[0] < self.x + self.width:
            if pos[1] > self.y and pos[1] < self.y + self.height:
                return True
                    
        return False

    def playSoundIfMouseIsOver(self, pos, sound):
        if self.isOver(pos):            
            if not self.over:
                click.play()
                self.over = True
        else:
            self.over = False



这里有一个你可以运行和测试的最小代码 image

这是背景音乐music

import pygame
pygame.init()

window = pygame.display.set_mode((800,800))



# our buttons
class button():
    def __init__(self, color, x,y,width,height, text=''):
        self.color = color
        self.x = x
        self.y = y
        self.width = width
        self.height = height
        self.text = text
        self.over = False

    def draw(self,window,outline=None):
                #Call this method to draw the button on the screen
        if outline:
            pygame.draw.rect(window, outline, (self.x-2,self.y-2,self.width+4,self.height+4),0)
                    
        pygame.draw.rect(window, self.color, (self.x,self.y,self.width,self.height),0)
                
        if self.text != '':
            font = pygame.font.SysFont('freesansbold.ttf', 60)
            text = font.render(self.text, 1, (255,255,255))
            window.blit(text, (self.x + (self.width/2 - text.get_width()/2), self.y + (self.height/2 - text.get_height()/2)))

    def isOver(self, pos):
                #Pos is the mouse position or a tuple of (x,y) coordinates
        if pos[0] > self.x and pos[0] < self.x + self.width:
            if pos[1] > self.y and pos[1] < self.y + self.height:
                return True
                    
        return False

    def playSoundIfMouseIsOver(self, pos, sound):
        if self.isOver(pos):            
            if not self.over:
                click.play()
                self.over = True
        else:
            self.over = False


colors = 0,23,56
colors2 = 0,123,56

bar11 = pygame.image.load("bar.png").convert_alpha()


move_spot = button((colors),720,125,25,260, '')

bar1 = button((colors),715,125,30,60, '')
volume1 = button((colors2),715,145,30,60, '')
volume2 = button((colors2),715,210,30,60, '')
volume3 = button((colors2),715,280,30,60, '')
volume4 = button((colors2),715,350,30,60, '')


buttons = [bar1,move_spot,volume1,volume2,volume3,volume4]



# fos
fps = 60
clock = pygame.time.Clock()


# redraw
def redraw():
    window.fill((40,100,200))
    for button in buttons:
        button.draw(window)
    window.blit(bar11,(bar1.x,bar1.y))

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



    redraw()

    pygame.display.update()

pygame.quit()

【问题讨论】:

  • 我发现无法获得当前的音频电平,pygame.mixer.music.get_volume() 无论音量设置为多少,都只返回 99%。没有这个,你就不知道在哪里画滑块旋钮。我在虚拟机中工作,其他人可能运气更好。

标签: python pygame


【解决方案1】:

作为一般的经验法则,您希望将所有繁重的工作委托给类,并将“好”的东西留给程序的主循环。我在这里创建了一个简单的类,它接受一些输入(宽度、高度、滑块选项的数量),并将为您处理所有的绘图、定位等。它还具有self.chosen 选项,它会告诉您选择了哪个选项。然后,我根据在 update() 函数中选择的选项,使用它来设置混音器输出的音量:

class VolumeBar(pygame.sprite.Sprite):
    def __init__(self, options, width, height):

        # Store these useful variables to the class
        self.options = options
        self.width = width
        self.height = height

        # The slider
        self.slider = pygame.image.load('slider.png')
        self.slider_rect = self.slider.get_rect()
        
        # The background "green" rectangles, mostly for decoration
        self.back = []
        objectHeight = (height-options*6)/(options-1)
        self.backHeight = objectHeight
        
        for index in range(options-1):
            self.back.append(pygame.Rect((0, rint((6*index+6)+index*objectHeight)), (width, rint(objectHeight))))

        # The foreground "blue" rectangles, mostly for decoration
        self.fore = []

        for index in range(options):
            self.fore.append(pygame.Rect((0, rint(index*(objectHeight+6))), (width, 6)))

        # Get list of possible "snaps", which the slider can be dragged to
        self.snaps = []
        
        for index in range(options):
            self.snaps.append((width/2, 3+(index*(objectHeight+6))))
            
        # A simple variable to tell you which option has been chosen
        self.chosen = 0

        # Generate the image surface, then render the bar to it
        self.image = pygame.Surface((width, height))
        self.rect = self.image.get_rect()
        self.render()

        self.focus = False

    def render(self):
        self.image.fill([255, 255, 255])
        
        for back in self.back:
            pygame.draw.rect(self.image, [0, 192, 0], back)

        for fore in self.fore:
            pygame.draw.rect(self.image, [0, 0, 0], fore)

        self.image.blit(self.slider, (rint((self.width-self.slider_rect.width)/2),
                        rint(self.snaps[self.chosen][1]-(self.slider_rect.height/2))))

    def draw(self, surface):
        surface.blit(self.image, self.rect.topleft)

    def mouseDown(self, pos):
        if self.rect.collidepoint(pos):
            self.focus = True
            return True
        return False

    def mouseUp(self, pos):
        if not self.focus:
            return

        self.focus = False

        if not self.rect.collidepoint(pos):
            return

        pos = list(pos)

        # We've made sure the mouse started in our widget (self.focus), and ended in our widget (collidepoint)
        # So there is no reason to care about the exact position of the mouse, only where it is relative
        # to this widget
        pos[0] -= self.rect.x
        pos[1] -= self.rect.y

        # Calculating max distance from a given selection, then comparing that to mouse pos
        dis = self.backHeight/2 + 3

        for index, snap in enumerate(self.snaps):
            if abs(snap[1]-pos[1]) <= dis:
                self.chosen = index
                break

        self.render()

    def update(self):
        pygame.mixer.music.set_volume((self.options-self.chosen)*0.1)

__init__ 函数的大部分时间用于计算每个绿色和黑色矩形的位置,这些矩形在 render() 中绘制并在 draw() 中显示。其他函数用于鼠标输入,首先检查mouseDown是否发生在所述按钮上,如果发生,它将self.focus设置为True,以便mouseUp处理程序知道它应该改变滑块位置。

所有这些共同构成了一个有效的VolumeBar。以下是如何在主循环中使用它的示例:

import pygame
pygame.init()

rint = lambda x: int(round(x, 0)) # Rounds to the nearest integer. Very useful.

class VolumeBar(pygame.sprite.Sprite):
    def __init__(self, options, width, height):

        # Store these useful variables to the class
        self.options = options
        self.width = width
        self.height = height

        # The slider
        self.slider = pygame.image.load('slider.png')
        self.slider_rect = self.slider.get_rect()
        
        # The background "green" rectangles, mostly for decoration
        self.back = []
        objectHeight = (height-options*6)/(options-1)
        self.backHeight = objectHeight
        
        for index in range(options-1):
            self.back.append(pygame.Rect((0, rint((6*index+6)+index*objectHeight)), (width, rint(objectHeight))))

        # The foreground "blue" rectangles, mostly for decoration
        self.fore = []

        for index in range(options):
            self.fore.append(pygame.Rect((0, rint(index*(objectHeight+6))), (width, 6)))

        # Get list of possible "snaps", which the slider can be dragged to
        self.snaps = []
        
        for index in range(options):
            self.snaps.append((width/2, 3+(index*(objectHeight+6))))
            
        # A simple variable to tell you which option has been chosen
        self.chosen = 0

        # Generate the image surface, then render the bar to it
        self.image = pygame.Surface((width, height))
        self.rect = self.image.get_rect()
        self.render()

        self.focus = False

    def render(self):
        self.image.fill([255, 255, 255])
        
        for back in self.back:
            pygame.draw.rect(self.image, [0, 192, 0], back)

        for fore in self.fore:
            pygame.draw.rect(self.image, [0, 0, 0], fore)

        self.image.blit(self.slider, (rint((self.width-self.slider_rect.width)/2),
                        rint(self.snaps[self.chosen][1]-(self.slider_rect.height/2))))

    def draw(self, surface):
        surface.blit(self.image, self.rect.topleft)

    def mouseDown(self, pos):
        if self.rect.collidepoint(pos):
            self.focus = True
            return True
        return False

    def mouseUp(self, pos):
        if not self.focus:
            return

        self.focus = False

        if not self.rect.collidepoint(pos):
            return

        pos = list(pos)

        # We've made sure the mouse started in our widget (self.focus), and ended in our widget (collidepoint)
        # So there is no reason to care about the exact position of the mouse, only where it is relative
        # to this widget
        pos[0] -= self.rect.x
        pos[1] -= self.rect.y

        # Calculating max distance from a given selection, then comparing that to mouse pos
        dis = self.backHeight/2 + 3

        for index, snap in enumerate(self.snaps):
            if abs(snap[1]-pos[1]) <= dis:
                self.chosen = index
                break

        self.render()

    def update(self):
        pygame.mixer.music.set_volume((self.options-self.chosen)*0.1)

screen = pygame.display.set_mode([500, 500])

test = VolumeBar(10, 30, 300)
test.rect.x = 50
test.rect.y = 50

clock = pygame.time.Clock()

game = True
while game:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            game = False

        if event.type == pygame.MOUSEBUTTONDOWN:
            test.mouseDown(pygame.mouse.get_pos())

        if event.type == pygame.MOUSEBUTTONUP:
            test.mouseUp(pygame.mouse.get_pos())

    if not game:
        break

    screen.fill([255, 255, 255])

    test.update()
    test.draw(screen)
    
    pygame.display.update()

    clock.tick(60)

最终产品:

https://i.gyazo.com/f6c2b5ede828f7715e5fd53a65c32c13.mp4

只要您的mouseDown 出现在这个小部件上,mouseUp 就会确定滑块的最终位置。因此,您可以在滑块上的任意位置单击、拖动或点击滑块,滑块将转到正确的位置。

访问滑块的位置很简单,看self.chosen就可以了。它默认为 0(因为它在 __init__ 中设置为 0)函数,它位于最顶部。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-02-25
    • 1970-01-01
    • 1970-01-01
    • 2018-08-11
    • 1970-01-01
    • 2020-12-05
    • 2012-05-17
    相关资源
    最近更新 更多