主屏幕上的按钮在 pygame 中闪烁
Button on main screen flickering in pygame
我正在制作游戏。因此,在我的主菜单上,我有两个用于播放和退出的按钮。
但是,无论我稍后调用哪个按钮,即,如果我调用开始按钮的功能然后调用退出按钮,反之亦然,第二个调用的按钮开始闪烁。
这是我的代码:
import math
import pygame
import random
import time
from pygame import mixer
# Initialising PyGame
pygame.init()
# Creating Screen
screen = pygame.display.set_mode((800, 600))
pygame.display.set_caption('Space Invaders')
# Global Variables
playerIMG = pygame.image.load('player.png')
alienIMG = []
bulletIMG = pygame.image.load('bullet.png')
bullet_state = 'ready'
clock = pygame.time.Clock()
start_count = 0
exit_count = 0
# Background
bgIMG = pygame.image.load('C:bgIMG.png')
bgIMG = pygame.transform.scale(bgIMG, (800, 600))
# Font
def text_on_screen(text, colour, x, y, size):
font = pygame.font.Font('Stargaze Regular.otf', size)
screen_text = font.render(text, True, colour)
screen.blit(screen_text, [x, y])
def player(x, y):
screen.blit(playerIMG, (x, y))
def alien(x, y, i):
screen.blit(alienIMG[i], (x, y))
def fire_bullet(x, y):
global bullet_state
bulletSound = mixer.Sound('laser.wav')
bulletSound.play()
bullet_state = 'fire'
screen.blit(bulletIMG, (x + 15, y - 30))
def isCollision(x1, x2, y2, y1):
dist = math.sqrt(((x1 - x2) ** 2) + ((y1 - y2) ** 2))
if dist < 23:
collisionSound = mixer.Sound('explosion.wav')
collisionSound.set_volume(120)
collisionSound.play()
return True
else:
return False
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
def draw(self, win, font_size, outline=None):
# Call this method to draw the button on the screen
if outline:
pygame.draw.rect(win, outline, (self.x - 2, self.y - 2, self.width + 4, self.height + 4), 0)
pygame.draw.rect(win, self.color, (self.x, self.y, self.width, self.height), 0)
if self.text != '':
font = pygame.font.Font('Stargaze Regular.otf', font_size)
text = font.render(self.text, 1, (0, 0, 0))
win.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 self.x < pos[0] < self.x + self.width:
if self.y < pos[1] < self.y + self.height:
return True
return False
# Game Over
def game_over():
for i in range(3000):
text_on_screen('GAME OVER!', (255, 255, 0), 190, 220, 60)
text_on_screen('PRESS R TO RESTART', (255, 255, 0), 270, 310, 20)
text_on_screen('PRESS Q TO QUIT', (255, 255, 0), 300, 335, 20)
pygame.display.update()
for e in pygame.event.get():
if e.type == pygame.KEYDOWN:
if e.key == pygame.K_r:
gameloop()
break
elif e.key == pygame.K_q:
pygame.quit()
quit()
def Start_button():
global start_count
mouse = pygame.mouse.get_pos()
start_button = Button((255, 0, 255), 10, 370, 80, 40, 'PLAY')
startwidth = start_button.width
startheight = start_button.height
start_text = start_button.text
if start_button.isOver(mouse):
start_button.color = (255, 255, 255)
start_button.width += 10
start_button.height += 10
loop = 0
i = 1
if start_count == 0:
while loop < 4 and i < 5:
start_button.text = start_text[:i]
start_button.draw(screen, 23)
time.sleep(0.08)
loop += 1
i += 1
start_count += 1
pygame.display.update()
else:
start_button.draw(screen, 23)
pygame.display.update()
else:
start_button.height = startheight
start_button.width = startwidth
start_button.draw(screen, 20)
pygame.display.update()
if not start_button.isOver(mouse):
start_count = 0
for event in pygame.event.get():
if event.type == pygame.MOUSEBUTTONDOWN and start_button.isOver(mouse):
gameloop()
def Exit_Button():
global exit_count
mouse = pygame.mouse.get_pos()
exit_button = Button((255, 0, 255), 10, 425, 80, 40, 'EXIT')
exitwidth = exit_button.width
exitheight = exit_button.height
exit_text = exit_button.text
if exit_button.isOver(mouse):
exit_button.color = (255, 255, 255)
exit_button.width += 10
exit_button.height += 10
loop = 0
i = 1
if exit_count == 0:
while i < 5:
exit_button.text = exit_text[:i]
exit_button.draw(screen, 23)
time.sleep(0.08)
loop += 1
i += 1
exit_count += 1
pygame.display.update()
else:
exit_button.draw(screen, 23)
pygame.display.update()
else:
exit_button.height = exitheight
exit_button.width = exitwidth
exit_button.draw(screen, 20)
pygame.display.update()
if not exit_button.isOver(mouse):
exit_count = 0
for event in pygame.event.get():
if event.type == pygame.MOUSEBUTTONDOWN and exit_button.isOver(mouse):
pygame.quit()
quit()
# Welcome
def welcome():
run = True
global clock
while run:
screen.fill((0, 0, 0))
Start_button()
Exit_Button()
pygame.display.update()
clock.tick(60)
# Pause
def pause_game():
pause = True
while pause:
mixer.music.pause()
screen.fill((0, 0, 0))
text_on_screen('PAUSE', (255, 255, 255), 0, 0, 40)
pygame.display.update()
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
mixer.music.unpause()
pause = False
# Game Loop
def gameloop():
mixer.music.load('background.wav')
mixer.music.set_volume(50)
mixer.music.play(-1)
# Player
global bullet_state
playerX = 370
playerY = 500
player_changeX = 0
fps = 30
# Alien Invader
alienX = []
alienY = []
alien_changeX = []
number_of_aliens = 5
for i in range(number_of_aliens):
alienIMG.append(pygame.image.load('alien.png'))
alienX.append(random.randint(0, 735))
alienY.append(random.randint(0, 100))
alien_changeX.append(7)
# Bullet
bulletX = 0
bulletY = 500
bullet_changeY = 20
score = 0
running = True
while running:
screen.fill((0, 0, 0))
screen.blit(bgIMG, (0, 0))
for e in pygame.event.get():
if e.type == pygame.QUIT:
running = False
if e.type == pygame.KEYDOWN:
if e.key == pygame.K_F4 and pygame.key.get_mods() & pygame.KMOD_ALT:
running = False
if e.key == pygame.K_LEFT or e.key == pygame.K_a:
player_changeX = -7
if e.key == pygame.K_RIGHT or e.key == pygame.K_d:
player_changeX = 7
if e.key == pygame.K_SPACE or e.key == pygame.K_RETURN:
bulletX = playerX
fire_bullet(bulletX, bulletY)
if e.key == pygame.K_ESCAPE:
pause_game()
if e.type == pygame.KEYUP:
if e.key == pygame.K_LEFT or e.key == pygame.K_RIGHT or e.key == pygame.K_a or e.key == pygame.K_d:
player_changeX = 0
playerX += player_changeX
if playerX < 0:
playerX = 0
elif playerX >= 736:
playerX = 736
if bulletY <= 0:
bulletY = 500
bullet_state = 'ready'
if bullet_state == 'fire':
fire_bullet(bulletX, bulletY)
bulletY -= bullet_changeY
for i in range(number_of_aliens):
if abs(alienY[i] - playerY) < 50 and abs(alienX[i] - playerX) < 67:
for h in range(number_of_aliens):
alienY[h] = 2000
game_over()
break
alienX[i] += alien_changeX[i]
if alienX[i] < 0:
alienX[i] = 0
alien_changeX[i] = 7
alienY[i] += 40
elif alienX[i] > 736:
alienX[i] = 736
alien_changeX[i] = -7
alienY[i] += 40
collisionbullet = isCollision(alienX[i], bulletX, alienY[i], bulletY)
if collisionbullet:
bulletY = 480
bullet_state = 'ready'
alienX[i] = random.randint(0, 735)
alienY[i] = random.randint(0, 120)
score += 10
alien(alienX[i], alienY[i], i)
player(playerX, playerY)
text_on_screen('Score:' + str(score), (0, 255, 0), 0, 0, 20)
clock.tick(fps)
pygame.display.update()
pygame.quit()
quit()
welcome()
关于如何解决这个问题或问题出在哪里有什么想法吗?
仅在应用程序循环结束时执行一次显示更新,而不是在帧期间执行多次更新。显示的多次更新会导致闪烁。帧末尾一个pygame.display.update()
or pygame.display.flip()
就足够了。
删除 Start_button
Exit_Button
对 pygame.display.update()
的所有 (6) 次调用,并在 welcome
.
中调用一次 pygame.display.update()
Start_button
Exit_Button
中的代码重复是一种代码味道。避开他们。实现一个按钮 class,它可以表示按钮并为其设置动画。删除 start_count
和 exit_count
,但将 count
属性添加到 Button
:
class Button:
def __init__(self, color, x, y, width, height, text=''):
self.color = color
self.text = text
self.rect = pygame.Rect(x, y, width, height)
self.normal = pygame.Surface((width, height))
self.normal.fill(self.color)
self.highlight = [pygame.Surface((width, height)), pygame.Surface((width + 10, height + 10))]
self.highlight[0].fill((255, 255, 255))
self.highlight[1].fill((255, 255, 255))
small_font = pygame.font.Font('Stargaze Regular.otf', 20)
large_font = pygame.font.Font('Stargaze Regular.otf', 23)
text_small = small_font.render(self.text, 1, (0, 0, 0))
text_large = large_font.render(self.text, 1, (0, 0, 0))
self.normal.blit(text_small, text_small.get_rect(center = self.normal.get_rect().center))
self.highlight[0].blit(text_small, text_small.get_rect(center = self.highlight[0].get_rect().center))
self.highlight[1].blit(text_large, text_large.get_rect(center = self.highlight[1].get_rect().center))
self.count = 0
def draw(self, win, pos, outline = None):
text_surf = self.normal
if self.isOver(pos):
text_surf = self.highlight[0]
self.count += 1
if self.count < 200:
text_surf = self.highlight[self.count // 20 % len(self.highlight)]
else:
self.count = 0
text_rect = text_surf.get_rect(center = self.rect.center)
if outline:
pygame.draw.rect(win, outline, text_rect.inflate(2, 2), 2)
win.blit(text_surf, text_rect)
def isOver(self, pos):
return self.rect.collidepoint(pos)
有了这个 class 你可以简化函数 welcome
而你根本不需要函数 Start_button
Exit_Button
:
def welcome():
exit_button = Button((255, 0, 255), 10, 425, 80, 40, 'EXIT')
start_button = Button((255, 0, 255), 10, 370, 80, 40, 'PLAY')
run = True
while run:
clock.tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
if event.type == pygame.MOUSEBUTTONDOWN:
if exit_button.isOver(event.pos):
run = False
if start_button.isOver(event.pos):
gameloop()
mouse = pygame.mouse.get_pos()
screen.fill((0, 0, 0))
exit_button.draw(screen, mouse)
start_button.draw(screen, mouse)
pygame.display.update()
pygame.quit()
quit()
我正在制作游戏。因此,在我的主菜单上,我有两个用于播放和退出的按钮。 但是,无论我稍后调用哪个按钮,即,如果我调用开始按钮的功能然后调用退出按钮,反之亦然,第二个调用的按钮开始闪烁。 这是我的代码:
import math
import pygame
import random
import time
from pygame import mixer
# Initialising PyGame
pygame.init()
# Creating Screen
screen = pygame.display.set_mode((800, 600))
pygame.display.set_caption('Space Invaders')
# Global Variables
playerIMG = pygame.image.load('player.png')
alienIMG = []
bulletIMG = pygame.image.load('bullet.png')
bullet_state = 'ready'
clock = pygame.time.Clock()
start_count = 0
exit_count = 0
# Background
bgIMG = pygame.image.load('C:bgIMG.png')
bgIMG = pygame.transform.scale(bgIMG, (800, 600))
# Font
def text_on_screen(text, colour, x, y, size):
font = pygame.font.Font('Stargaze Regular.otf', size)
screen_text = font.render(text, True, colour)
screen.blit(screen_text, [x, y])
def player(x, y):
screen.blit(playerIMG, (x, y))
def alien(x, y, i):
screen.blit(alienIMG[i], (x, y))
def fire_bullet(x, y):
global bullet_state
bulletSound = mixer.Sound('laser.wav')
bulletSound.play()
bullet_state = 'fire'
screen.blit(bulletIMG, (x + 15, y - 30))
def isCollision(x1, x2, y2, y1):
dist = math.sqrt(((x1 - x2) ** 2) + ((y1 - y2) ** 2))
if dist < 23:
collisionSound = mixer.Sound('explosion.wav')
collisionSound.set_volume(120)
collisionSound.play()
return True
else:
return False
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
def draw(self, win, font_size, outline=None):
# Call this method to draw the button on the screen
if outline:
pygame.draw.rect(win, outline, (self.x - 2, self.y - 2, self.width + 4, self.height + 4), 0)
pygame.draw.rect(win, self.color, (self.x, self.y, self.width, self.height), 0)
if self.text != '':
font = pygame.font.Font('Stargaze Regular.otf', font_size)
text = font.render(self.text, 1, (0, 0, 0))
win.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 self.x < pos[0] < self.x + self.width:
if self.y < pos[1] < self.y + self.height:
return True
return False
# Game Over
def game_over():
for i in range(3000):
text_on_screen('GAME OVER!', (255, 255, 0), 190, 220, 60)
text_on_screen('PRESS R TO RESTART', (255, 255, 0), 270, 310, 20)
text_on_screen('PRESS Q TO QUIT', (255, 255, 0), 300, 335, 20)
pygame.display.update()
for e in pygame.event.get():
if e.type == pygame.KEYDOWN:
if e.key == pygame.K_r:
gameloop()
break
elif e.key == pygame.K_q:
pygame.quit()
quit()
def Start_button():
global start_count
mouse = pygame.mouse.get_pos()
start_button = Button((255, 0, 255), 10, 370, 80, 40, 'PLAY')
startwidth = start_button.width
startheight = start_button.height
start_text = start_button.text
if start_button.isOver(mouse):
start_button.color = (255, 255, 255)
start_button.width += 10
start_button.height += 10
loop = 0
i = 1
if start_count == 0:
while loop < 4 and i < 5:
start_button.text = start_text[:i]
start_button.draw(screen, 23)
time.sleep(0.08)
loop += 1
i += 1
start_count += 1
pygame.display.update()
else:
start_button.draw(screen, 23)
pygame.display.update()
else:
start_button.height = startheight
start_button.width = startwidth
start_button.draw(screen, 20)
pygame.display.update()
if not start_button.isOver(mouse):
start_count = 0
for event in pygame.event.get():
if event.type == pygame.MOUSEBUTTONDOWN and start_button.isOver(mouse):
gameloop()
def Exit_Button():
global exit_count
mouse = pygame.mouse.get_pos()
exit_button = Button((255, 0, 255), 10, 425, 80, 40, 'EXIT')
exitwidth = exit_button.width
exitheight = exit_button.height
exit_text = exit_button.text
if exit_button.isOver(mouse):
exit_button.color = (255, 255, 255)
exit_button.width += 10
exit_button.height += 10
loop = 0
i = 1
if exit_count == 0:
while i < 5:
exit_button.text = exit_text[:i]
exit_button.draw(screen, 23)
time.sleep(0.08)
loop += 1
i += 1
exit_count += 1
pygame.display.update()
else:
exit_button.draw(screen, 23)
pygame.display.update()
else:
exit_button.height = exitheight
exit_button.width = exitwidth
exit_button.draw(screen, 20)
pygame.display.update()
if not exit_button.isOver(mouse):
exit_count = 0
for event in pygame.event.get():
if event.type == pygame.MOUSEBUTTONDOWN and exit_button.isOver(mouse):
pygame.quit()
quit()
# Welcome
def welcome():
run = True
global clock
while run:
screen.fill((0, 0, 0))
Start_button()
Exit_Button()
pygame.display.update()
clock.tick(60)
# Pause
def pause_game():
pause = True
while pause:
mixer.music.pause()
screen.fill((0, 0, 0))
text_on_screen('PAUSE', (255, 255, 255), 0, 0, 40)
pygame.display.update()
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
mixer.music.unpause()
pause = False
# Game Loop
def gameloop():
mixer.music.load('background.wav')
mixer.music.set_volume(50)
mixer.music.play(-1)
# Player
global bullet_state
playerX = 370
playerY = 500
player_changeX = 0
fps = 30
# Alien Invader
alienX = []
alienY = []
alien_changeX = []
number_of_aliens = 5
for i in range(number_of_aliens):
alienIMG.append(pygame.image.load('alien.png'))
alienX.append(random.randint(0, 735))
alienY.append(random.randint(0, 100))
alien_changeX.append(7)
# Bullet
bulletX = 0
bulletY = 500
bullet_changeY = 20
score = 0
running = True
while running:
screen.fill((0, 0, 0))
screen.blit(bgIMG, (0, 0))
for e in pygame.event.get():
if e.type == pygame.QUIT:
running = False
if e.type == pygame.KEYDOWN:
if e.key == pygame.K_F4 and pygame.key.get_mods() & pygame.KMOD_ALT:
running = False
if e.key == pygame.K_LEFT or e.key == pygame.K_a:
player_changeX = -7
if e.key == pygame.K_RIGHT or e.key == pygame.K_d:
player_changeX = 7
if e.key == pygame.K_SPACE or e.key == pygame.K_RETURN:
bulletX = playerX
fire_bullet(bulletX, bulletY)
if e.key == pygame.K_ESCAPE:
pause_game()
if e.type == pygame.KEYUP:
if e.key == pygame.K_LEFT or e.key == pygame.K_RIGHT or e.key == pygame.K_a or e.key == pygame.K_d:
player_changeX = 0
playerX += player_changeX
if playerX < 0:
playerX = 0
elif playerX >= 736:
playerX = 736
if bulletY <= 0:
bulletY = 500
bullet_state = 'ready'
if bullet_state == 'fire':
fire_bullet(bulletX, bulletY)
bulletY -= bullet_changeY
for i in range(number_of_aliens):
if abs(alienY[i] - playerY) < 50 and abs(alienX[i] - playerX) < 67:
for h in range(number_of_aliens):
alienY[h] = 2000
game_over()
break
alienX[i] += alien_changeX[i]
if alienX[i] < 0:
alienX[i] = 0
alien_changeX[i] = 7
alienY[i] += 40
elif alienX[i] > 736:
alienX[i] = 736
alien_changeX[i] = -7
alienY[i] += 40
collisionbullet = isCollision(alienX[i], bulletX, alienY[i], bulletY)
if collisionbullet:
bulletY = 480
bullet_state = 'ready'
alienX[i] = random.randint(0, 735)
alienY[i] = random.randint(0, 120)
score += 10
alien(alienX[i], alienY[i], i)
player(playerX, playerY)
text_on_screen('Score:' + str(score), (0, 255, 0), 0, 0, 20)
clock.tick(fps)
pygame.display.update()
pygame.quit()
quit()
welcome()
关于如何解决这个问题或问题出在哪里有什么想法吗?
仅在应用程序循环结束时执行一次显示更新,而不是在帧期间执行多次更新。显示的多次更新会导致闪烁。帧末尾一个pygame.display.update()
or pygame.display.flip()
就足够了。
删除 Start_button
Exit_Button
对 pygame.display.update()
的所有 (6) 次调用,并在 welcome
.
pygame.display.update()
Start_button
Exit_Button
中的代码重复是一种代码味道。避开他们。实现一个按钮 class,它可以表示按钮并为其设置动画。删除 start_count
和 exit_count
,但将 count
属性添加到 Button
:
class Button:
def __init__(self, color, x, y, width, height, text=''):
self.color = color
self.text = text
self.rect = pygame.Rect(x, y, width, height)
self.normal = pygame.Surface((width, height))
self.normal.fill(self.color)
self.highlight = [pygame.Surface((width, height)), pygame.Surface((width + 10, height + 10))]
self.highlight[0].fill((255, 255, 255))
self.highlight[1].fill((255, 255, 255))
small_font = pygame.font.Font('Stargaze Regular.otf', 20)
large_font = pygame.font.Font('Stargaze Regular.otf', 23)
text_small = small_font.render(self.text, 1, (0, 0, 0))
text_large = large_font.render(self.text, 1, (0, 0, 0))
self.normal.blit(text_small, text_small.get_rect(center = self.normal.get_rect().center))
self.highlight[0].blit(text_small, text_small.get_rect(center = self.highlight[0].get_rect().center))
self.highlight[1].blit(text_large, text_large.get_rect(center = self.highlight[1].get_rect().center))
self.count = 0
def draw(self, win, pos, outline = None):
text_surf = self.normal
if self.isOver(pos):
text_surf = self.highlight[0]
self.count += 1
if self.count < 200:
text_surf = self.highlight[self.count // 20 % len(self.highlight)]
else:
self.count = 0
text_rect = text_surf.get_rect(center = self.rect.center)
if outline:
pygame.draw.rect(win, outline, text_rect.inflate(2, 2), 2)
win.blit(text_surf, text_rect)
def isOver(self, pos):
return self.rect.collidepoint(pos)
有了这个 class 你可以简化函数 welcome
而你根本不需要函数 Start_button
Exit_Button
:
def welcome():
exit_button = Button((255, 0, 255), 10, 425, 80, 40, 'EXIT')
start_button = Button((255, 0, 255), 10, 370, 80, 40, 'PLAY')
run = True
while run:
clock.tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
if event.type == pygame.MOUSEBUTTONDOWN:
if exit_button.isOver(event.pos):
run = False
if start_button.isOver(event.pos):
gameloop()
mouse = pygame.mouse.get_pos()
screen.fill((0, 0, 0))
exit_button.draw(screen, mouse)
start_button.draw(screen, mouse)
pygame.display.update()
pygame.quit()
quit()