Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import pygame
- import random
- import sys
- from pygame.locals import * # pour K_RIGHT etc...
- SW = 800
- SH = 600
- NOIR = (0, 0, 0)
- VERT = (0, 255, 0)
- class Poisson(pygame.sprite.Sprite):
- def __init__(self, espece, frame_width):
- super().__init__()
- self.vitesse_x = random.choice([-4, -2, -1, 1, 2, 4])
- self.frame_width = frame_width
- # initialement le premier frame de la liste est affiché
- self.image_index = 0
- # set des 2 listes qui contiennent les frames associés au visuel de
- # l'image.
- # une liste losque le poisson_principal de deplace vers la droite et
- # l'autre pour la direction inverse
- self.animation_frames_G, self.animation_frames_D = \
- self.load_images(espece, self.frame_width)
- ##------initialisation du visuel
- self.image_width, self.image_height = self.set_frame_initial()
- # initialise la position du poisson soit à gauche ou à droite
- # de l'écran dependamment de sa direction (i.e. sa vitesse qui
- # est soit positive ou negative)
- if self.vitesse_x > 0:
- self.rect.x = 0 - self.image_width
- self.animation_frames = self.animation_frames_D[:]
- else:
- self.rect.x = SW
- self.animation_frames = self.animation_frames_G[:]
- # position en y completement random
- self.rect.y = random.randrange(SH)
- # pour les collisions (pp)
- self.mask = pygame.mask.from_surface(self.image)
- def ressuscite(self):
- """Le poisson reapparait au bord de l'écran tout en gardant
- son orientation d'origine"""
- # vitesse positive : deplacement de gauche à droite
- if self.vitesse_x > 0:
- self.rect.x = 0 - self.frame_width
- else:
- self.rect.x = SW + self.frame_width
- self.rect.y = random.randrange(SH)
- def load_images(self, nom_fichier, frame_width):
- animation_frames_D = []
- animation_frames_G = []
- image = pygame.image.load(nom_fichier).convert()
- # la couleur de transparence est celle du premier pixel
- image.set_colorkey(image.get_at((0, 0)))
- image_width, image_height = image.get_size()
- for i in range(int(image_width / frame_width)):
- animation_frames_D.append(image.subsurface((i * frame_width, 0,
- frame_width, image_height)))
- for image in animation_frames_D:
- animation_frames_G.append(pygame.transform.flip(image, True,
- False))
- return animation_frames_D, animation_frames_G
- def set_frame_initial(self):
- # set orientation initiale
- # c'est une troisieme liste qui contient les frames courants
- if self.vitesse_x < 0:
- self.animation_frames = self.animation_frames_G[:]
- else:
- self.animation_frames = self.animation_frames_D[:]
- # set de l'image initiale
- self.image = self.animation_frames[0]
- self.rect = self.image.get_rect()
- image_width, image_height = self.image.get_size()
- return image_width, image_height
- def update(self, tick_progress):
- # Gestion du déplacement
- self.rect.x += self.vitesse_x
- # À chaque tic d'horloge (i.e. changement de frame) : repositionnement
- if tick_progress % 20 == 0:
- if self.image_index >= len(self.animation_frames):
- self.image_index = 0
- self.image = self.animation_frames[self.image_index]
- self.image_index += 1
- # Lorsque le poisson sort de l'image, on repositionne le même
- # poisson
- # à l'interieur des limites de l'écran.
- if self.rect.x > SW or self.rect.x + self.frame_width < 0:
- self.ressuscite()
- class MainFish(Poisson):
- def __init__(self):
- self.images = [("main_poisson_1.png", 60), ("main_poisson_2.png", 80),
- ("main_poisson_3.png", 110), ("main_poisson_4.png", 160),
- ("main_poisson_5.png", 180), ("main_poisson_6.png", 200)]
- self.poisson_status = 0 # correspond à l'index du tableau images
- self.taille = 10
- self.inflate = False
- # set vitesse initiale ?!
- self.vitesse_x = -1 # > 0 = de gauche à droite
- self.vitesse_y = 1 # > 0 = de haut à bas
- # Call the parent class constructor
- super().__init__(self.images[self.poisson_status][0],
- self.images[self.poisson_status][1])
- # using a mask so we can use pixel perfect collision
- self.mask_D, self.mask_G = self.make_masks()
- # set position initiale de l'image au milieu de l'ecran
- self.rect.x = SW / 2
- self.rect.y = SH / 2
- # garde en mémoire la position de l'image pour les inflations
- self.pos_x = self.rect.x
- self.pos_y = self.rect.y
- def make_masks(self):
- """
- Create a collision mask slightly smaller than our sprite so that
- the sprite's head can overlap obstacles; adding depth.
- """
- mask_surface_D = pygame.Surface(self.rect.size).convert_alpha()
- mask_surface_G = pygame.Surface(self.rect.size).convert_alpha()
- mask_surface_D.fill((0, 0, 0, 0))
- mask_surface_G.fill((0, 0, 0, 0))
- mask_surface_G.fill(VERT, (0, self.image_height / 3, self.image_width / 4,
- self.image_width / 4))
- mask_surface_D.fill(NOIR, (self.image_width - self.image_width / 4,
- self.image_height / 3, self.image_width / 4,
- self.image_width / 4))
- mask_D = pygame.mask.from_surface(mask_surface_D)
- mask_G = pygame.mask.from_surface(mask_surface_G)
- return mask_D, mask_G
- def do_inflate(self):
- self.pos_x = self.rect.centerx
- self.pos_y = self.rect.centery
- print("INFLATION")
- self.poisson_status += 1
- self.animation_frames_G, self.animation_frames_D = \
- self.load_images(self.images[self.poisson_status][0],
- self.images[self.poisson_status][1])
- ##------initialisation du visuel
- # set orientation initiale
- # c'est une troisieme liste qui contient les frames courants
- if self.vitesse_x < 0:
- self.animation_frames = self.animation_frames_G[:]
- else:
- self.animation_frames = self.animation_frames_D[:]
- self.image_index = 0
- self.image = self.animation_frames[self.image_index]
- self.rect = self.image.get_rect()
- self.image_width, self.image_height = self.image.get_size()
- self.rect.centerx = self.pos_x
- self.rect.centery = self.pos_y
- # remise à la taille pour le mask de la bouche
- self.mask_D, self.mask_G = self.make_masks()
- self.inflate = False
- def update(self, keys, tick_progress):
- # animation principale
- # change les frames du main_fish une fois de temps en temps
- if tick_progress % 10 == 0:
- if self.image_index >= len(self.animation_frames):
- self.image_index = 0
- self.image = self.animation_frames[self.image_index]
- self.image_index += 1
- # fait grossir le poisson principal apres une capture
- if self.inflate:
- self.do_inflate()
- # gestion du déplacement en fonction de la touche enfoncee
- # gestion des bornes de l'écran
- if keys:
- if keys[K_LEFT]:
- if self.vitesse_x >= 0:
- self.vitesse_x = -2
- self.animation_frames = self.animation_frames_G[:]
- self.mask = self.mask_G
- self.rect.x += self.vitesse_x
- if keys[K_RIGHT]:
- if self.vitesse_x < 0:
- self.vitesse_x = 2
- self.animation_frames = self.animation_frames_D[:]
- self.mask = self.mask_D
- self.rect.x += self.vitesse_x
- if keys[K_UP]:
- if self.vitesse_y >= 0:
- self.vitesse_y = -1
- self.rect.y += self.vitesse_y
- if keys[K_DOWN]:
- if self.vitesse_y < 0:
- self.vitesse_y = 2
- self.rect.y += self.vitesse_y
- # -------------------- gestion du bord de l'ecran
- if self.rect.x < 0 - self.image_width:
- self.rect.x = SW
- if self.rect.x > SW:
- self.rect.x = 0 - self.image_width
- if self.rect.y < 0:
- self.rect.y = 0
- if self.rect.y > SH - self.image_height:
- self.rect.y = SH - self.image_height
- class Algae(pygame.sprite.Sprite):
- def __init__(self, x, y):
- super().__init__()
- self.images = [pygame.image.load("algae_1.png"), pygame.image.load("algae_2.png")]
- self.index = 0
- self.ticker = 0
- self.x = x
- self.y = y
- def update(self):
- if self.ticker == 60:
- self.ticker = 0
- elif self.ticker > 30:
- self.index = 0
- elif self.ticker < 30:
- self.index = 1
- self.ticker += 1
- def draw(self, screen):
- screen.blit(self.images[self.index], (self.x, self.y))
- class App():
- """
- A class to manage our event, game loop, and overall program flow.
- """
- def __init__(self):
- """
- Get a reference to the display surface; set up required attributes;
- and create a Player instance.
- """
- pygame.init()
- # gestion de la vitesse de rafraichissement de l'ecran
- self.clock = pygame.time.Clock()
- self.tick_progress = 0
- # Creation de la surface d'affichage principale
- self.screen = pygame.display.set_mode([SW, SH])
- pygame.display.set_caption("Exemple_E2_Cedric")
- # ajout du background
- # Load and set up graphics.
- self.background_image = pygame.image.load("bg_1.png").convert()
- bg_image_width, bg_image_height = self.background_image.get_size()
- # Copy background image to screen:
- self.screen.blit(self.background_image, (0, 0))
- # ---------- Groupes de sprites
- self.sprites = pygame.sprite.Group() # tous les sprites
- self.liste_poissons = pygame.sprite.Group() # tous les ennemis
- self.score = 0
- self.quit = False
- # ---------- creation des poissons à bouffer
- self.liste_especes = [("poisson_1.png", 40), ("poisson_2.png", 56),
- ("poisson_4.png", 110), ("poisson_7.png", 200)]
- for i in range(12):
- espece, FW = random.choice(self.liste_especes)
- poisson = Poisson(espece, FW)
- self.liste_poissons.add(poisson)
- self.sprites.add(poisson)
- # ----------- Creation du hero
- self.main_fish = MainFish()
- self.sprites.add(self.main_fish)
- # Creation algues
- self.algues = [Algae(50, 500), Algae(400, 500), Algae(600, 500)]
- # liste des touches enfoncées pour la gestion du deplacement
- # du Hero
- self.keys = pygame.key.get_pressed()
- def run_logic(self):
- """
- Mise à jour des positions des sprites et détection/gestion collisions
- """
- collideRect = (0, 0, 100, 100)
- self.inflate = False
- # ------------ Update des états de chaque objet
- self.liste_poissons.update(self.tick_progress)
- self.main_fish.update(self.keys, self.tick_progress)
- # ------------ Gestion des Collisions
- # Verification des collisions (Hero vs Poisson(s))
- poissons_touches = pygame.sprite.spritecollide(self.main_fish,
- self.liste_poissons,
- True,
- pygame.sprite.collide_mask)
- # Pour chaque collision :
- for poisson in poissons_touches:
- print("Hero : " + str(self.main_fish.image_width) + " vs Poisson: " + str(poisson.frame_width))
- if poisson.frame_width > self.main_fish.image_width:
- # si le poisson est plus gros que le hero
- # le hero perd
- self.quit = True
- on_quit()
- else:
- # remplacement du poisson mangé
- espece, frame_width = random.choice(self.liste_especes)
- new_poisson = Poisson(espece, frame_width)
- self.liste_poissons.add(new_poisson)
- self.sprites.add(new_poisson)
- self.score += 1
- if self.score % 1 == 0 and self.score < 6: # on grossit à
- # chaque x captures
- self.main_fish.inflate = True
- # Update algues
- for algue in self.algues:
- algue.update()
- def event_handler(self):
- """
- gestion des evenements qui boucle en attente de facon continue
- """
- for event in pygame.event.get():
- if event.type == pygame.QUIT:
- self.quit = True
- elif event.type == pygame.KEYDOWN:
- self.keys = pygame.key.get_pressed()
- def update_frame(self):
- """
- Appelée à chaque changement de frame: update + redraw + gest.
- defilement
- """
- self.run_logic()
- self.draw_frame()
- def display_info(self):
- font = pygame.font.SysFont("arial", 20)
- info = "Score : " + str(self.score) + " Taille : " + str(self.main_fish.taille)
- self.screen.blit(font.render(info, True, NOIR), (SW / 3, 10))
- font = pygame.font.SysFont("arial", 20)
- fps = "FPS : %0.1f" % (self.clock.get_fps())
- self.screen.blit(font.render(fps, True, NOIR), (SW / 10, 10))
- def draw_frame(self):
- """
- Redraw de l'écran visible
- """
- # efface tout, i.e. affiche juste le background
- self.screen.blit(self.background_image, (0, 0))
- # Draw algues
- for algue in self.algues:
- algue.draw(self.screen)
- # affiche sur le background, infos divers (score e.g.)
- self.display_info()
- # -- Redessine tous les sprites
- self.sprites.draw(self.screen)
- print(len(self.liste_poissons))
- # Flip
- pygame.display.flip()
- # Todo : pygame.display.update(liste_rect retournée par les blit())
- def main_loop(self):
- """
- main loop : appel du event_manager + update
- """
- while not self.quit:
- self.event_handler()
- self.update_frame()
- self.clock.tick(80)
- # pour pouvoir faire un modulo et rafraichir
- # le frame moins souvent qu'à chaque changement de frame
- self.tick_progress += 1
- def on_quit():
- """
- clean good bye
- """
- print("Good riddance...")
- pygame.quit()
- sys.exit()
- def main():
- """
- Initialisation et lancement programme
- """
- pygame.init()
- App().main_loop()
- on_quit()
- if __name__ == "__main__":
- main()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement