-
Notifications
You must be signed in to change notification settings - Fork 14
Expand file tree
/
Copy pathlisting29-2.py
More file actions
123 lines (102 loc) · 4.07 KB
/
listing29-2.py
File metadata and controls
123 lines (102 loc) · 4.07 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
# Configuration file for Squish
# -----------------------------
# Feel free to modify the configuration variables below to taste.
# If the game is too fast or too slow, try to modify the speed
# variables.
# Change these to use other images in the game:
banana_image = 'banana.png'
weight_image = 'weight.png'
splash_image = 'weight.png'
# Change these to affect the general appearance:
screen_size = 800, 600
background_color = 255, 255, 255
margin = 30
full_screen = 1
font_size = 48
# These affect the behavior of the game:
drop_speed = 5
banana_speed = 10
speed_increase = 1
weights_per_level = 10
banana_pad_top = 40
banana_pad_side = 20
Listing 29-3. The Squish Game Objects (objects.py)
import pygame, config, os
from random import randrange
"This module contains the game objects of the Squish game."
class SquishSprite(pygame.sprite.Sprite):
"""
Generic superclass for all sprites in Squish. The constructor
takes care of loading an image, setting up the sprite rect, and
the area within which it is allowed to move. That area is governed
by the screen size and the margin.
"""
def __init__(self, image):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load(image).convert()
self.rect = self.image.get_rect()
screen = pygame.display.get_surface()
shrink = -config.margin * 2
self.area = screen.get_rect().inflate(shrink, shrink)
class Weight(SquishSprite):
"""
A falling weight. It uses the SquishSprite constructor to set up
its weight image, and will fall with a speed given as a parameter
to its constructor.
"""
def __init__(self, speed):
SquishSprite.__init__(self, config.weight_image)
self.speed = speed
self.reset()
def reset(self):
"""
Move the weight to the top of the screen (just out of sight)
and place it at a random horizontal position.
"""
x = randrange(self.area.left, self.area.right)
self.rect.midbottom = x, 0
def update(self):
"""
Move the weight vertically (downwards) a distance
corresponding to its speed. Also set the landed attribute
according to whether it has reached the bottom of the screen.
"""
self.rect.top += self.speed
self.landed = self.rect.top >= self.area.bottom
class Banana(SquishSprite):
"""
A desperate banana. It uses the SquishSprite constructor to set up
its banana image, and will stay near the bottom of the screen,
with its horizontal position governed by the current mouse
position (within certain limits).
"""
def __init__(self):
SquishSprite.__init__(self, config.banana_image)
self.rect.bottom = self.area.bottom
# These paddings represent parts of the image where there is
# no banana. If a weight moves into these areas, it doesn't
# constitute a hit (or, rather, a squish):
self.pad_top = config.banana_pad_top
self.pad_side = config.banana_pad_side
def update(self):
"""
Set the Banana's center x-coordinate to the current mouse
x-coordinate, and then use the rect method clamp to ensure
that the Banana stays within its allowed range of motion.
"""
self.rect.centerx = pygame.mouse.get_pos()[0]
self.rect = self.rect.clamp(self.area)
def touches(self, other):
"""
Determines whether the banana touches another sprite (e.g., a
Weight). Instead of just using the rect method colliderect, a
new rectangle is first calculated (using the rect method
inflate with the side and top paddings) that does not include
the 'empty' areas on the top and sides of the banana.
"""
# Deflate the bounds with the proper padding:
bounds = self.rect.inflate(-self.pad_side, -self.pad_top)
# Move the bounds so they are placed at the bottom of the Banana:
bounds.bottom = self.rect.bottom
# Check whether the bounds intersect with the other object's rect:
return bounds.colliderect(other.rect)