Advertisement
Guest User

Untitled

a guest
Apr 24th, 2018
50
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 17.91 KB | None | 0 0
  1. import pygame
  2.  
  3. import random
  4.  
  5. import sys
  6.  
  7. from pygame.locals import *  # pour K_RIGHT etc...
  8.  
  9.  
  10. SW = 800
  11.  
  12. SH = 600
  13.  
  14. NOIR = (0, 0, 0)
  15.  
  16. VERT = (0, 255, 0)
  17.  
  18.  
  19.  
  20. class Poisson(pygame.sprite.Sprite):
  21.  
  22.     def __init__(self, espece, frame_width):
  23.  
  24.  
  25.         super().__init__()
  26.  
  27.         self.vitesse_x = random.choice([-4, -2, -1, 1, 2, 4])
  28.  
  29.  
  30.         self.frame_width = frame_width
  31.  
  32.  
  33.         # initialement le premier frame de la liste est affiché
  34.  
  35.         self.image_index = 0
  36.  
  37.  
  38.         # set des 2 listes qui contiennent les frames associés au visuel de
  39.  
  40.         # l'image.
  41.  
  42.         # une liste losque le poisson_principal de deplace vers la droite et
  43.  
  44.         # l'autre pour la direction inverse
  45.  
  46.  
  47.         self.animation_frames_G, self.animation_frames_D = \
  48.  
  49.             self.load_images(espece, self.frame_width)
  50.  
  51.  
  52.         ##------initialisation du visuel
  53.  
  54.         self.image_width, self.image_height = self.set_frame_initial()
  55.  
  56.  
  57.         # initialise la position du poisson soit à gauche ou à droite
  58.  
  59.         # de l'écran dependamment de sa direction (i.e. sa vitesse qui
  60.  
  61.         # est soit positive ou negative)
  62.  
  63.  
  64.         if self.vitesse_x > 0:
  65.  
  66.             self.rect.x = 0 - self.image_width
  67.  
  68.             self.animation_frames = self.animation_frames_D[:]
  69.  
  70.         else:
  71.  
  72.             self.rect.x = SW
  73.  
  74.             self.animation_frames = self.animation_frames_G[:]
  75.  
  76.  
  77.         # position en y completement random
  78.  
  79.         self.rect.y = random.randrange(SH)
  80.  
  81.  
  82.         # pour les collisions (pp)
  83.  
  84.         self.mask = pygame.mask.from_surface(self.image)
  85.  
  86.  
  87.     def ressuscite(self):
  88.  
  89.         """Le poisson reapparait au bord de l'écran tout en gardant
  90.  
  91.         son orientation d'origine"""
  92.  
  93.  
  94.         # vitesse positive : deplacement de gauche à droite
  95.  
  96.         if self.vitesse_x > 0:
  97.  
  98.             self.rect.x = 0 - self.frame_width
  99.  
  100.         else:
  101.  
  102.             self.rect.x = SW + self.frame_width
  103.  
  104.  
  105.         self.rect.y = random.randrange(SH)
  106.  
  107.  
  108.     def load_images(self, nom_fichier, frame_width):
  109.  
  110.  
  111.         animation_frames_D = []
  112.  
  113.         animation_frames_G = []
  114.  
  115.         image = pygame.image.load(nom_fichier).convert()
  116.  
  117.         # la couleur de transparence est celle du premier pixel
  118.  
  119.         image.set_colorkey(image.get_at((0, 0)))
  120.  
  121.         image_width, image_height = image.get_size()
  122.  
  123.  
  124.         for i in range(int(image_width / frame_width)):
  125.  
  126.             animation_frames_D.append(image.subsurface((i * frame_width, 0,
  127.  
  128.                                                         frame_width, image_height)))
  129.  
  130.  
  131.         for image in animation_frames_D:
  132.  
  133.             animation_frames_G.append(pygame.transform.flip(image, True,
  134.  
  135.                                                             False))
  136.  
  137.  
  138.         return animation_frames_D, animation_frames_G
  139.  
  140.  
  141.     def set_frame_initial(self):
  142.  
  143.         # set orientation initiale
  144.  
  145.         # c'est une troisieme liste qui contient les frames courants
  146.  
  147.  
  148.         if self.vitesse_x < 0:
  149.  
  150.             self.animation_frames = self.animation_frames_G[:]
  151.  
  152.         else:
  153.  
  154.             self.animation_frames = self.animation_frames_D[:]
  155.  
  156.  
  157.         # set de l'image initiale
  158.  
  159.         self.image = self.animation_frames[0]
  160.  
  161.         self.rect = self.image.get_rect()
  162.  
  163.         image_width, image_height = self.image.get_size()
  164.  
  165.  
  166.         return image_width, image_height
  167.  
  168.  
  169.     def update(self, tick_progress):
  170.  
  171.  
  172.         # Gestion du déplacement
  173.  
  174.  
  175.         self.rect.x += self.vitesse_x
  176.  
  177.  
  178.         # À chaque tic d'horloge (i.e. changement de frame) : repositionnement
  179.  
  180.  
  181.         if tick_progress % 20 == 0:
  182.  
  183.             if self.image_index >= len(self.animation_frames):
  184.  
  185.                 self.image_index = 0
  186.  
  187.             self.image = self.animation_frames[self.image_index]
  188.  
  189.             self.image_index += 1
  190.  
  191.  
  192.         # Lorsque le poisson sort de l'image, on repositionne le même
  193.  
  194.         # poisson
  195.  
  196.         # à l'interieur des limites de l'écran.
  197.  
  198.         if self.rect.x > SW or self.rect.x + self.frame_width < 0:
  199.  
  200.             self.ressuscite()
  201.  
  202.  
  203.  
  204. class MainFish(Poisson):
  205.  
  206.     def __init__(self):
  207.  
  208.  
  209.         self.images = [("main_poisson_1.png", 60), ("main_poisson_2.png", 80),
  210.  
  211.                        ("main_poisson_3.png", 110), ("main_poisson_4.png", 160),
  212.  
  213.                        ("main_poisson_5.png", 180), ("main_poisson_6.png", 200)]
  214.  
  215.         self.poisson_status = 0  # correspond à l'index du tableau images
  216.  
  217.  
  218.         self.taille = 10
  219.  
  220.         self.inflate = False
  221.  
  222.  
  223.         # set vitesse initiale ?!
  224.  
  225.         self.vitesse_x = -1  # > 0 = de gauche à droite
  226.  
  227.         self.vitesse_y = 1  # > 0 = de haut à bas
  228.  
  229.  
  230.         # Call the parent class constructor
  231.  
  232.         super().__init__(self.images[self.poisson_status][0],
  233.  
  234.                          self.images[self.poisson_status][1])
  235.  
  236.  
  237.         # using a mask so we can use pixel perfect collision
  238.  
  239.         self.mask_D, self.mask_G = self.make_masks()
  240.  
  241.  
  242.         # set position initiale de l'image au milieu de l'ecran
  243.  
  244.  
  245.         self.rect.x = SW / 2
  246.  
  247.         self.rect.y = SH / 2
  248.  
  249.  
  250.         # garde en mémoire la position de l'image pour les inflations
  251.  
  252.         self.pos_x = self.rect.x
  253.  
  254.         self.pos_y = self.rect.y
  255.  
  256.  
  257.     def make_masks(self):
  258.  
  259.         """
  260.  
  261.         Create a collision mask slightly smaller than our sprite so that
  262.  
  263.         the sprite's head can overlap obstacles; adding depth.
  264.  
  265.         """
  266.  
  267.         mask_surface_D = pygame.Surface(self.rect.size).convert_alpha()
  268.  
  269.         mask_surface_G = pygame.Surface(self.rect.size).convert_alpha()
  270.  
  271.  
  272.         mask_surface_D.fill((0, 0, 0, 0))
  273.  
  274.         mask_surface_G.fill((0, 0, 0, 0))
  275.  
  276.  
  277.         mask_surface_G.fill(VERT, (0, self.image_height / 3, self.image_width / 4,
  278.  
  279.                                    self.image_width / 4))
  280.  
  281.         mask_surface_D.fill(NOIR, (self.image_width - self.image_width / 4,
  282.  
  283.                                    self.image_height / 3, self.image_width / 4,
  284.  
  285.                                    self.image_width / 4))
  286.  
  287.  
  288.         mask_D = pygame.mask.from_surface(mask_surface_D)
  289.  
  290.         mask_G = pygame.mask.from_surface(mask_surface_G)
  291.  
  292.  
  293.         return mask_D, mask_G
  294.  
  295.  
  296.     def do_inflate(self):
  297.  
  298.         self.pos_x = self.rect.centerx
  299.  
  300.         self.pos_y = self.rect.centery
  301.  
  302.         print("INFLATION")
  303.  
  304.         self.poisson_status += 1
  305.  
  306.         self.animation_frames_G, self.animation_frames_D = \
  307.  
  308.             self.load_images(self.images[self.poisson_status][0],
  309.  
  310.                              self.images[self.poisson_status][1])
  311.  
  312.  
  313.         ##------initialisation du visuel
  314.  
  315.         # set orientation initiale
  316.  
  317.         # c'est une troisieme liste qui contient les frames courants
  318.  
  319.         if self.vitesse_x < 0:
  320.  
  321.             self.animation_frames = self.animation_frames_G[:]
  322.  
  323.         else:
  324.  
  325.             self.animation_frames = self.animation_frames_D[:]
  326.  
  327.  
  328.         self.image_index = 0
  329.  
  330.         self.image = self.animation_frames[self.image_index]
  331.  
  332.         self.rect = self.image.get_rect()
  333.  
  334.         self.image_width, self.image_height = self.image.get_size()
  335.  
  336.         self.rect.centerx = self.pos_x
  337.  
  338.         self.rect.centery = self.pos_y
  339.  
  340.  
  341.         # remise à la taille pour le mask de la bouche
  342.  
  343.         self.mask_D, self.mask_G = self.make_masks()
  344.  
  345.  
  346.         self.inflate = False
  347.  
  348.  
  349.     def update(self, keys, tick_progress):
  350.  
  351.  
  352.         # animation principale
  353.  
  354.         # change les frames du main_fish une fois de temps en temps
  355.  
  356.  
  357.         if tick_progress % 10 == 0:
  358.  
  359.             if self.image_index >= len(self.animation_frames):
  360.  
  361.                 self.image_index = 0
  362.  
  363.             self.image = self.animation_frames[self.image_index]
  364.  
  365.             self.image_index += 1
  366.  
  367.  
  368.         # fait grossir le poisson principal apres une capture
  369.  
  370.  
  371.         if self.inflate:
  372.  
  373.             self.do_inflate()
  374.  
  375.  
  376.         # gestion du déplacement en fonction de la touche enfoncee
  377.  
  378.         # gestion des bornes de l'écran
  379.  
  380.  
  381.         if keys:
  382.  
  383.             if keys[K_LEFT]:
  384.  
  385.  
  386.                 if self.vitesse_x >= 0:
  387.  
  388.                     self.vitesse_x = -2
  389.  
  390.                     self.animation_frames = self.animation_frames_G[:]
  391.  
  392.                     self.mask = self.mask_G
  393.  
  394.                 self.rect.x += self.vitesse_x
  395.  
  396.  
  397.             if keys[K_RIGHT]:
  398.  
  399.  
  400.                 if self.vitesse_x < 0:
  401.  
  402.                     self.vitesse_x = 2
  403.  
  404.                     self.animation_frames = self.animation_frames_D[:]
  405.  
  406.                     self.mask = self.mask_D
  407.  
  408.  
  409.                 self.rect.x += self.vitesse_x
  410.  
  411.  
  412.             if keys[K_UP]:
  413.  
  414.                 if self.vitesse_y >= 0:
  415.  
  416.                     self.vitesse_y = -1
  417.  
  418.  
  419.                 self.rect.y += self.vitesse_y
  420.  
  421.  
  422.             if keys[K_DOWN]:
  423.  
  424.  
  425.                 if self.vitesse_y < 0:
  426.  
  427.                     self.vitesse_y = 2
  428.  
  429.                 self.rect.y += self.vitesse_y
  430.  
  431.  
  432.             # -------------------- gestion du bord de l'ecran
  433.  
  434.             if self.rect.x < 0 - self.image_width:
  435.  
  436.                 self.rect.x = SW
  437.  
  438.  
  439.             if self.rect.x > SW:
  440.  
  441.                 self.rect.x = 0 - self.image_width
  442.  
  443.  
  444.             if self.rect.y < 0:
  445.  
  446.                 self.rect.y = 0
  447.  
  448.  
  449.             if self.rect.y > SH - self.image_height:
  450.  
  451.                 self.rect.y = SH - self.image_height
  452.  
  453.  
  454.  
  455. class Algae(pygame.sprite.Sprite):
  456.  
  457.     def __init__(self, x, y):
  458.  
  459.         super().__init__()
  460.  
  461.         self.images = [pygame.image.load("algae_1.png"), pygame.image.load("algae_2.png")]
  462.  
  463.         self.index = 0
  464.  
  465.         self.ticker = 0
  466.  
  467.         self.x = x
  468.  
  469.         self.y = y
  470.  
  471.  
  472.     def update(self):
  473.  
  474.         if self.ticker == 60:
  475.  
  476.             self.ticker = 0
  477.  
  478.         elif self.ticker > 30:
  479.  
  480.             self.index = 0
  481.  
  482.         elif self.ticker < 30:
  483.  
  484.             self.index = 1
  485.  
  486.         self.ticker += 1
  487.  
  488.  
  489.     def draw(self, screen):
  490.  
  491.         screen.blit(self.images[self.index], (self.x, self.y))
  492.  
  493.  
  494.  
  495. class App():
  496.  
  497.     """
  498.  
  499.     A class to manage our event, game loop, and overall program flow.
  500.  
  501.     """
  502.  
  503.  
  504.     def __init__(self):
  505.  
  506.         """
  507.  
  508.         Get a reference to the display surface; set up required attributes;
  509.  
  510.         and create a Player instance.
  511.  
  512.         """
  513.  
  514.  
  515.         pygame.init()
  516.  
  517.  
  518.         # gestion de la vitesse de rafraichissement de l'ecran
  519.  
  520.         self.clock = pygame.time.Clock()
  521.  
  522.         self.tick_progress = 0
  523.  
  524.  
  525.         # Creation de la surface d'affichage principale
  526.  
  527.         self.screen = pygame.display.set_mode([SW, SH])
  528.  
  529.         pygame.display.set_caption("Exemple_E2_Cedric")
  530.  
  531.  
  532.         # ajout du background
  533.  
  534.         # Load and set up graphics.
  535.  
  536.         self.background_image = pygame.image.load("bg_1.png").convert()
  537.  
  538.         bg_image_width, bg_image_height = self.background_image.get_size()
  539.  
  540.         # Copy background image to screen:
  541.  
  542.         self.screen.blit(self.background_image, (0, 0))
  543.  
  544.  
  545.         # ---------- Groupes de sprites
  546.  
  547.         self.sprites = pygame.sprite.Group()  # tous les sprites
  548.  
  549.         self.liste_poissons = pygame.sprite.Group()  # tous les ennemis
  550.  
  551.  
  552.         self.score = 0
  553.  
  554.         self.quit = False
  555.  
  556.  
  557.         # ---------- creation des poissons à bouffer
  558.  
  559.         self.liste_especes = [("poisson_1.png", 40), ("poisson_2.png", 56),
  560.  
  561.                               ("poisson_4.png", 110), ("poisson_7.png", 200)]
  562.  
  563.  
  564.         for i in range(12):
  565.  
  566.             espece, FW = random.choice(self.liste_especes)
  567.  
  568.             poisson = Poisson(espece, FW)
  569.  
  570.  
  571.             self.liste_poissons.add(poisson)
  572.  
  573.             self.sprites.add(poisson)
  574.  
  575.  
  576.         # ----------- Creation du hero
  577.  
  578.         self.main_fish = MainFish()
  579.  
  580.         self.sprites.add(self.main_fish)
  581.  
  582.  
  583.         # Creation algues
  584.  
  585.         self.algues = [Algae(50, 500), Algae(400, 500), Algae(600, 500)]
  586.  
  587.  
  588.         # liste des touches enfoncées pour la gestion du deplacement
  589.  
  590.         # du Hero
  591.  
  592.         self.keys = pygame.key.get_pressed()
  593.  
  594.  
  595.     def run_logic(self):
  596.  
  597.         """
  598.  
  599.         Mise à jour des positions des sprites et détection/gestion collisions
  600.  
  601.         """
  602.  
  603.         collideRect = (0, 0, 100, 100)
  604.  
  605.         self.inflate = False
  606.  
  607.         # ------------ Update des états de chaque objet
  608.  
  609.         self.liste_poissons.update(self.tick_progress)
  610.  
  611.         self.main_fish.update(self.keys, self.tick_progress)
  612.  
  613.  
  614.         # ------------ Gestion des Collisions
  615.  
  616.  
  617.         # Verification des collisions (Hero vs Poisson(s))
  618.  
  619.         poissons_touches = pygame.sprite.spritecollide(self.main_fish,
  620.  
  621.                                                        self.liste_poissons,
  622.  
  623.                                                        True,
  624.  
  625.                                                        pygame.sprite.collide_mask)
  626.  
  627.  
  628.         # Pour chaque collision :
  629.  
  630.         for poisson in poissons_touches:
  631.  
  632.  
  633.             print("Hero : " + str(self.main_fish.image_width) + " vs  Poisson: " + str(poisson.frame_width))
  634.  
  635.  
  636.             if poisson.frame_width > self.main_fish.image_width:
  637.  
  638.                 # si le poisson est plus gros que le hero
  639.  
  640.                 # le hero perd
  641.  
  642.  
  643.                 self.quit = True
  644.  
  645.                 on_quit()
  646.  
  647.  
  648.             else:
  649.  
  650.                 # remplacement du poisson mangé
  651.  
  652.                 espece, frame_width = random.choice(self.liste_especes)
  653.  
  654.                 new_poisson = Poisson(espece, frame_width)
  655.  
  656.                 self.liste_poissons.add(new_poisson)
  657.  
  658.                 self.sprites.add(new_poisson)
  659.  
  660.                 self.score += 1
  661.  
  662.             if self.score % 1 == 0 and self.score < 6:  # on grossit à
  663.  
  664.                 # chaque x captures
  665.  
  666.                 self.main_fish.inflate = True
  667.  
  668.  
  669.         # Update algues
  670.  
  671.         for algue in self.algues:
  672.  
  673.             algue.update()
  674.  
  675.  
  676.     def event_handler(self):
  677.  
  678.         """
  679.  
  680.         gestion des evenements qui boucle en attente de facon continue
  681.  
  682.         """
  683.  
  684.         for event in pygame.event.get():
  685.  
  686.             if event.type == pygame.QUIT:
  687.  
  688.                 self.quit = True
  689.  
  690.             elif event.type == pygame.KEYDOWN:
  691.  
  692.                 self.keys = pygame.key.get_pressed()
  693.  
  694.  
  695.     def update_frame(self):
  696.  
  697.         """
  698.  
  699.         Appelée à chaque changement de frame: update + redraw + gest.
  700.  
  701.         defilement
  702.  
  703.         """
  704.  
  705.         self.run_logic()
  706.  
  707.         self.draw_frame()
  708.  
  709.  
  710.     def display_info(self):
  711.  
  712.  
  713.         font = pygame.font.SysFont("arial", 20)
  714.  
  715.         info = "Score : " + str(self.score) + " Taille : " + str(self.main_fish.taille)
  716.  
  717.  
  718.         self.screen.blit(font.render(info, True, NOIR), (SW / 3, 10))
  719.  
  720.  
  721.         font = pygame.font.SysFont("arial", 20)
  722.  
  723.         fps = "FPS : %0.1f" % (self.clock.get_fps())
  724.  
  725.         self.screen.blit(font.render(fps, True, NOIR), (SW / 10, 10))
  726.  
  727.  
  728.  
  729.     def draw_frame(self):
  730.  
  731.         """
  732.  
  733.         Redraw de l'écran visible
  734.  
  735.         """
  736.  
  737.         # efface tout, i.e. affiche juste le background
  738.  
  739.         self.screen.blit(self.background_image, (0, 0))
  740.  
  741.  
  742.         # Draw algues
  743.  
  744.         for algue in self.algues:
  745.  
  746.             algue.draw(self.screen)
  747.  
  748.  
  749.         # affiche sur le background, infos divers (score e.g.)
  750.  
  751.         self.display_info()
  752.  
  753.  
  754.         # -- Redessine tous les sprites
  755.  
  756.         self.sprites.draw(self.screen)
  757.  
  758.         print(len(self.liste_poissons))
  759.  
  760.  
  761.         # Flip
  762.  
  763.         pygame.display.flip()
  764.  
  765.         # Todo : pygame.display.update(liste_rect retournée par les blit())
  766.  
  767.  
  768.  
  769.     def main_loop(self):
  770.  
  771.         """
  772.  
  773.         main loop : appel du event_manager + update
  774.  
  775.         """
  776.  
  777.         while not self.quit:
  778.  
  779.             self.event_handler()
  780.  
  781.             self.update_frame()
  782.  
  783.             self.clock.tick(80)
  784.  
  785.  
  786.             # pour pouvoir faire un modulo et rafraichir
  787.  
  788.             # le frame moins souvent qu'à chaque changement de frame
  789.  
  790.             self.tick_progress += 1
  791.  
  792.  
  793.  
  794. def on_quit():
  795.  
  796.     """
  797.  
  798.     clean good bye
  799.  
  800.     """
  801.  
  802.     print("Good riddance...")
  803.  
  804.     pygame.quit()
  805.  
  806.     sys.exit()
  807.  
  808.  
  809.  
  810. def main():
  811.  
  812.     """
  813.  
  814.     Initialisation et lancement programme
  815.  
  816.     """
  817.  
  818.  
  819.     pygame.init()
  820.  
  821.     App().main_loop()
  822.  
  823.     on_quit()
  824.  
  825.  
  826.  
  827. if __name__ == "__main__":
  828.  
  829.     main()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement