Ejecutando una sentencia if solo una vez en pygame

Tengo un juego de carrera donde puedes moverte y recoger monedas. Para cada moneda tengo una statement if:

if cn1+25  x: cn1 = -1000 if cn1 < -3: coincount += 1 textObj = INVFONT.render(str(coincount+1), True, WHITE, BLACK) 

Esta instrucción if sigue ocurriendo una y otra vez, agregando cientos de monedas a la variable coincount . Más adelante, en mi código, abro el número de monedas que coinciden con la pantalla.

¿Hay una manera de asegurarse de que esto solo se ejecuta una vez?

(Aquí está el rest de mi código, podría ser útil)

 import pygame,sys,random pygame.init() width = 900 height = 300 screenDim = (width,height) green=(0,255,0) yellow=(255,255,0) red=(255,0,0) WHITE = (0,0,0) BLACK = (255,255,255) screen = pygame.display.set_mode(screenDim) placePlatformX = 0 placePlatformY = 275 coin = pygame.image.load('C:\\Users\\eliya_s1suf2x\\Desktop\\coin.png').convert_alpha() coin = pygame.transform.scale(coin, (25,25)) background = pygame.image.load('C:\\Users\\eliya_s1suf2x\\Desktop\\background.jpg').convert_alpha() background = pygame.transform.scale(background, (width,height)) guy = pygame.image.load('C:\\Users\\eliya_s1suf2x\\Desktop\\guy.png').convert_alpha() guy = pygame.transform.rotate(guy,90) cloud1 = pygame.image.load('C:\\Users\\eliya_s1suf2x\\Downloads\\cloud.png').convert_alpha() cloud1 = pygame.transform.scale(cloud1,(156,88)) cloud2 = pygame.image.load('C:\\Users\\eliya_s1suf2x\\Downloads\\cloud.png').convert_alpha() cloud2 = pygame.transform.scale(cloud1,(131,53)) cloud3 = pygame.image.load('C:\\Users\\eliya_s1suf2x\\Downloads\\cloud.png').convert_alpha() cloud3 = pygame.transform.scale(cloud1,(200,100)) cloud4 = pygame.image.load('C:\\Users\\eliya_s1suf2x\\Downloads\\cloud.png').convert_alpha() cloud4 = pygame.transform.scale(cloud1,(39,20)) bplatform = pygame.image.load('C:\\Users\\eliya_s1suf2x\\Desktop\\platform.jpg').convert_alpha() coincount = 0 x = 450 y = -20 block = 1000 cn1 = 100 cn2 = 100 cn3 = 100 cn4 = 100 cn5 = 100 cloudmove = 20 INVFONT = pygame.font.Font('C:\\Users\\eliya_s1suf2x\\Desktop\\MINECRAFT\\Raleway-ExtraBold.ttf', 18) textObj = INVFONT.render(str(coincount), True, WHITE, BLACK) def update(): screen.blit(background,(0,0)) screen.blit(textObj,(860,0)) screen.blit(cloud1,(cloudmove,0)) screen.blit(cloud2,(cloudmove+120,30)) screen.blit(cloud3, (cloudmove+500,10)) screen.blit(cloud4, (cloudmove + 340,20)) screen.blit(bplatform,(placePlatformX,placePlatformY)) screen.blit(bplatform,(placePlatformX+190,placePlatformY)) screen.blit(bplatform,(placePlatformX+380,placePlatformY)) screen.blit(bplatform,(placePlatformX+570,placePlatformY)) screen.blit(bplatform,(placePlatformX+760,placePlatformY)) screen.blit(bplatform,(placePlatformX+1760,placePlatformY+100)) #block list update screen.blit(bplatform,(block-500,190)) screen.blit(bplatform,(block,100)) screen.blit(bplatform,(block+250,200)) screen.blit(bplatform,(block+500,210)) screen.blit(bplatform,(block+830,190)) screen.blit(bplatform,(block+1000,140)) screen.blit(coin,(cn1 + 40,245)) screen.blit(coin,(cn2 + 80,245)) screen.blit(coin,(cn3 + 120,245)) screen.blit(coin,(cn4+ 160,245)) screen.blit(coin,(cn5 + 200,245)) screen.blit(coin,(830,0)) screen.blit(guy,(x,y)) #pygame.sprite.spritecollide() standOnBrick = 255 speed = 2 gravity = 3 pygame.display.set_caption("Run") finished = False while finished == False: #processing all the events for event in pygame.event.get(): # event1, event2,.. if event.type == pygame.QUIT: finished = True pygame.quit() sys.exit() if y < standOnBrick: y += gravity update() #where the block #where the block #starts #ends elif cn1+25  x: cn1 = -1000 if cn1 < -3: coincount += 1 textObj = INVFONT.render(str(coincount+1), True, WHITE, BLACK) #WORK ON THIS elif cn2 + 50  x: cn2 = -1025 if cn2 < -3: coincount += 1 print('coincount',coincount) textObj = INVFONT.render(str(coincount+1), True, WHITE, BLACK) elif cn3 + 75  x: cn3 = -1050 if cn3 < -3: coincount += 1 print('coincount',coincount) textObj = INVFONT.render(str(coincount+1), True, WHITE, BLACK) elif cn4 + 100  x: cn4 = -1000 if cn4 < -3: coincount += 1 print('coincount',coincount) textObj = INVFONT.render(str(coincount+1), True, WHITE, BLACK) elif cn5 + 125  x: cn5 = -1000 if cn5 < -3: coincount += 1 print('coincount',coincount) print('hello') textObj = INVFONT.render(str(coincount+1), True, WHITE, BLACK) elif block-525  x: #how high guy is standOnBrick = 167 elif block-16  x: standOnBrick = 79 elif block + 230  x: standOnBrick = 179 elif block + 480 x: standOnBrick = 189 elif block + 810  x: standOnBrick = 169 elif block + 980  x: standOnBrick = 119 else: standOnBrick = 255 pressedKeys = pygame.key.get_pressed() if pressedKeys[pygame.K_LEFT] == 1: x -= speed print(x) update() elif pressedKeys[pygame.K_RIGHT] == 1: block -= 0.5 cn1 -= 0.5 cn2 -= 0.5 cn3 -= 0.5 cn4 -= 0.5 cn5 -= 0.5 cloudmove -= 0.2 update() if x < 450: cloudmove += 0.25 x+=speed cn1 += 0.5 cn2 += 0.5 cn3 += 0.5 cn4 += 0.5 cn5 += 0.5 update() print(x) block += 0.5 elif pressedKeys[pygame.K_UP] == 1: y -= 5 print(y) update() #bounderies if x < 2: x += 2.1 pygame.display.flip()#Update method/load next frame #pygame.quit() 

Lo que falta en tu código es la abstracción .

En lugar de un montón de screen.blit y muchas declaraciones if , usa listas.
En lugar de valores codificados (como cn1+25 < x and cn1 + 50 > x ), use estructuras de datos (en su caso, objetos) que contengan toda la información que necesitan.

Aquí hay un ejemplo simple.

Digamos que tenemos este bonito mundo donde las nubes se mueven en un día soleado:

 import pygame screen = pygame.display.set_mode((300, 300)) clock = pygame.time.Clock() cloud = pygame.Surface((50, 20)) cloud.set_colorkey((11, 12, 13)) cloud.fill((11, 12, 13)) pygame.draw.ellipse(cloud, pygame.Color('white'), cloud.get_rect()) cloudmove = 20 while True: for e in pygame.event.get(): if e.type == pygame.QUIT: quit() screen.fill(pygame.Color('lightblue')) screen.blit(cloud, (cloudmove+120,30)) cloudmove += 1 pygame.display.flip() clock.tick(30) 

introduzca la descripción de la imagen aquí

Pero, por supuesto, queremos más de una sola nube. Lo que no queremos es duplicar el código y boost la complejidad. Podríamos hacer algo como esto:

 import pygame screen = pygame.display.set_mode((300, 300)) clock = pygame.time.Clock() cloud = pygame.Surface((50, 20)) cloud.set_colorkey((11, 12, 13)) cloud.fill((11, 12, 13)) pygame.draw.ellipse(cloud, pygame.Color('white'), cloud.get_rect()) cloud2 = pygame.Surface((50, 20)) cloud2.set_colorkey((11, 12, 13)) cloud2.fill((11, 12, 13)) pygame.draw.ellipse(cloud2, pygame.Color('white'), cloud2.get_rect()) cloud3 = pygame.Surface((50, 20)) cloud3.set_colorkey((11, 12, 13)) cloud3.fill((11, 12, 13)) pygame.draw.ellipse(cloud3, pygame.Color('white'), cloud3.get_rect()) cloudmove = 20 while True: for e in pygame.event.get(): if e.type == pygame.QUIT: quit() screen.fill(pygame.Color('lightblue')) screen.blit(cloud, (cloudmove-120,30)) screen.blit(cloud2, (cloudmove-220,40)) screen.blit(cloud3, (cloudmove-170,50)) cloudmove += 1 pygame.display.flip() clock.tick(30) 

introduzca la descripción de la imagen aquí

Ya puede ver dónde terminará si agregamos una docena de objetos más.

Así que intentemos usar objetos que representan las nubes:

 import pygame screen = pygame.display.set_mode((300, 300)) clock = pygame.time.Clock() class Cloud: def __init__(self, x, y): self.image = pygame.Surface((50, 20)) self.image.set_colorkey((11, 12, 13)) self.image.fill((11, 12, 13)) pygame.draw.ellipse(self.image, pygame.Color('white'), self.image.get_rect()) self.x = x self.y = y def update(self): self.x += 1 if self.x > 300: self.x = 0 clouds = [Cloud(0, 30), Cloud(100, 40), Cloud(50, 50)] while True: for e in pygame.event.get(): if e.type == pygame.QUIT: quit() screen.fill(pygame.Color('lightblue')) for cloud in clouds: screen.blit(cloud.image, (cloud.x, cloud.y)) cloud.update() pygame.display.flip() clock.tick(30) 

(No hay nueva imagen aquí porque básicamente se ve igual)

¡Mucho mejor! Ahora, para agregar más nubes, simplemente agregaríamos una nueva instancia de Cloud a la lista de clouds . Vea cómo no solo almacenamos la imagen de una nube en la clase, sino también la posición. Y hemos puesto el comportamiento de la nube (moviéndonos a lo largo del cielo y comenzando desde la izquierda una vez que salimos de la pantalla ) en la clase.

¡Pero todavía podemos hacerlo mejor! Pygame ofrece algunas clases prácticas y funciones que podemos usar. Echa un vistazo al siguiente código:

 import pygame screen = pygame.display.set_mode((300, 300)) clock = pygame.time.Clock() class Coin(pygame.sprite.Sprite): def __init__(self, x, y): super().__init__() self.image = pygame.Surface((44, 40)) self.image.set_colorkey((11, 12, 13)) self.image.fill((11, 12, 13)) cx, cy = self.image.get_rect().center pygame.draw.circle(self.image, pygame.Color('grey'), (cx + 2, cy), 20) pygame.draw.circle(self.image, pygame.Color('orange'), (cx - 2, cy), 20) self.rect = self.image.get_rect(topleft=(x, y)) def update(self): mouse_pos = pygame.mouse.get_pos() if self.rect.collidepoint(mouse_pos) and pygame.mouse.get_pressed()[0]: self.kill() class Cloud(pygame.sprite.Sprite): def __init__(self, x, y): super().__init__() self.image = pygame.Surface((50, 20)) self.image.set_colorkey((11, 12, 13)) self.image.fill((11, 12, 13)) pygame.draw.ellipse(self.image, pygame.Color('white'), self.image.get_rect()) self.rect = self.image.get_rect(topleft=(x, y)) def update(self): self.rect.move_ip(1, 0) if not pygame.display.get_surface().get_rect().colliderect(self.rect): self.rect.right = 0 stuff = pygame.sprite.Group(Cloud(0, 30), Cloud(100, 40), Cloud(50, 50), Coin(100, 100), Coin(150, 180), Coin(80, 200)) while True: for e in pygame.event.get(): if e.type == pygame.QUIT: quit() screen.fill(pygame.Color('lightblue')) stuff.draw(screen) stuff.update() pygame.display.flip() clock.tick(30) 

introduzca la descripción de la imagen aquí

Extrajimos el dibujo y la actualización de nuestros objetos mediante el uso de las clases de Group y Sprite pygame.

Y vea lo fácil que es agregar cosas nuevas a nuestro pequeño juego. Agregué monedas en las que puede hacer clic wo coleccionar, y todo el comportamiento de las monedas se encuentra en la clase de Coin . Una vez que haces clic en una moneda, se llama al método de kill de la clase Sprite , que simplemente elimina el objeto de todos sus grupos, por lo que ya no está en el grupo de objetos, y ya no se dibuja en la pantalla y se elimina de forma efectiva el juego (y responder a su pregunta de “Ejecutar una instrucción if solo una vez”).

También es posible usar una tupla para ejecutar una sentencia if solo una vez. Al crear el switch = [0] tupla switch = [0] fuera del bucle while, esta tranquilidad de código puede ser suficiente.

 if Your conditions: if switch[0] == 0: switch[0] += 1 

todo lo que necesita de aquí es algo que se ejecuta (o no) porque el switch[0] = 1 . Al tener que agregar solo 1, se podría agregar un código de tranquilidad similar para deshacer.