listing29-3.py 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. import pygame, config, os
  2. from random import randrange
  3. "This module contains the game objects of the Squish game."
  4. class SquishSprite(pygame.sprite.Sprite):
  5. """
  6. Generic superclass for all sprites in Squish. The constructor
  7. takes care of loading an image, setting up the sprite rect, and
  8. the area within which it is allowed to move. That area is governed
  9. by the screen size and the margin.
  10. """
  11. def __init__(self, image):
  12. super().__init__()
  13. self.image = pygame.image.load(image).convert()
  14. self.rect = self.image.get_rect()
  15. screen = pygame.display.get_surface()
  16. shrink = -config.margin * 2
  17. self.area = screen.get_rect().inflate(shrink, shrink)
  18. class Weight(SquishSprite):
  19. """
  20. A falling weight. It uses the SquishSprite constructor to set up
  21. its weight image, and will fall with a speed given as a parameter
  22. to its constructor.
  23. """
  24. def __init__(self, speed):
  25. super().__init__(config.weight_image)
  26. self.speed = speed
  27. self.reset()
  28. def reset(self):
  29. """
  30. Move the weight to the top of the screen (just out of sight)
  31. and place it at a random horizontal position.
  32. """
  33. x = randrange(self.area.left, self.area.right)
  34. self.rect.midbottom = x, 0
  35. def update(self):
  36. """
  37. Move the weight vertically (downwards) a distance
  38. corresponding to its speed. Also set the landed attribute
  39. according to whether it has reached the bottom of the screen.
  40. """
  41. self.rect.top += self.speed
  42. self.landed = self.rect.top >= self.area.bottom
  43. class Banana(SquishSprite):
  44. """
  45. A desperate banana. It uses the SquishSprite constructor to set up
  46. its banana image, and will stay near the bottom of the screen,
  47. with its horizontal position governed by the current mouse
  48. position (within certain limits).
  49. """
  50. def __init__(self):
  51. super().__init__(config.banana_image)
  52. self.rect.bottom = self.area.bottom
  53. # These paddings represent parts of the image where there is
  54. # no banana. If a weight moves into these areas, it doesn't
  55. # constitute a hit (or, rather, a squish):
  56. self.pad_top = config.banana_pad_top
  57. self.pad_side = config.banana_pad_side
  58. def update(self):
  59. """
  60. Set the Banana's center x-coordinate to the current mouse
  61. x-coordinate, and then use the rect method clamp to ensure
  62. that the Banana stays within its allowed range of motion.
  63. """
  64. self.rect.centerx = pygame.mouse.get_pos()[0]
  65. self.rect = self.rect.clamp(self.area)
  66. def touches(self, other):
  67. """
  68. Determines whether the banana touches another sprite (e.g., a
  69. Weight). Instead of just using the rect method colliderect, a
  70. new rectangle is first calculated (using the rect method
  71. inflate with the side and top paddings) that does not include
  72. the 'empty' areas on the top and sides of the banana.
  73. """
  74. # Deflate the bounds with the proper padding:
  75. bounds = self.rect.inflate(-self.pad_side, -self.pad_top)
  76. # Move the bounds so they are placed at the bottom of the Banana:
  77. bounds.bottom = self.rect.bottom
  78. # Check whether the bounds intersect with the other object's rect:
  79. return bounds.colliderect(other.rect)