Passed
Push — master ( b6fdd8...a60f45 )
by Yohann
01:13
created

game.Game.__del__()   A

Complexity

Conditions 1

Size

Total Lines 4
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 4
nop 1
dl 0
loc 4
rs 10
c 0
b 0
f 0
1
import pygame
2
3
from src.components.bullet import Bullet
4
from src.components.platform import Platform
5
from src.components.player import Player
6
from src.components.scrolling_background import ScrollingBackground
7
from src.utils import load, get_text
8
9
ASSETS_DIR = "src/assets/"
10
MUSIC_PATH = f"{ASSETS_DIR}musics/music.mp3"
11
ICON_PATH = f"{ASSETS_DIR}images/icon.png"
12
FONT_PATH = f"{ASSETS_DIR}fonts/setbackt.ttf"
13
14
TITLE = "Duck Jump 2"
15
CAP_FPS = 100
16
17
SCREEN_WIDTH = 1280
18
SCREEN_HEIGHT = 720
19
SCREEN_SIZE = (SCREEN_WIDTH, SCREEN_HEIGHT)
20
21
22
class Game:
23
24
    def __init__(self):
25
        pygame.init()
26
        pygame.mixer.init()
27
28
        self.clock = pygame.time.Clock()
29
        
30
        self.screen = pygame.display.set_mode(SCREEN_SIZE)
31
        pygame.display.set_icon(load(ICON_PATH))
32
33
        self.fonts = {
34
            size: pygame.font.Font(FONT_PATH, size) for size in (48, 64, 96)
35
        }
36
37
        self.show_fps = True
38
        self.player = Player()
39
40
        self.run = True
41
        self.pause = False
42
        self.over = False
43
44
        self.events = {
45
            pygame.K_ESCAPE: self.pause_screen,
46
            pygame.K_SPACE: self.player.jump,
47
            pygame.K_d: self.player.accelerate,
48
            pygame.K_a: self.player.decelerate,
49
            pygame.K_f: self.toggle_fps
50
        }
51
52
        self.platforms = []
53
        self.bullets = []
54
        self.backgrounds = []
55
        self.limit = 4000
56
        self.score = 0
57
58
    def __del__(self):
59
        pygame.mixer.quit()
60
        pygame.display.quit()
61
        pygame.quit()
62
63
    def setup(self):
64
        pygame.mixer.music.load(MUSIC_PATH)
65
        pygame.mixer.music.set_volume(0.4)
66
        pygame.mixer.music.play()
67
68
        self.platforms = [
69
            Platform(x, y) for x, y in ((280, 620), (960, 640), (1620, 660))
70
        ]
71
72
        self.bullets = [Bullet() for _ in range(3)]
73
74
        self.backgrounds = [
75
            ScrollingBackground(0), ScrollingBackground(SCREEN_WIDTH)
76
        ]
77
78
        self.player.reset()
79
80
        self.over = False
81
        self.limit = 4000
82
        self.score = 0
83
84
    def toggle_fps(self):
85
        self.show_fps = not self.show_fps
86
87
    def update(self):
88
        self.screen.fill((121, 201, 249), ((0, 0), (SCREEN_WIDTH, 360)))
89
        self.screen.fill((127, 173, 113), ((0, 593), SCREEN_SIZE))
90
91
        for background in self.backgrounds:
92
            background.update()
93
            self.screen.blit(
94
                background.texture,
95
                (background.rect.x, 350),
96
                (0, 0, SCREEN_WIDTH, 360)
97
            )
98
99
        for platform in self.platforms:
100
            platform.check_hit_box(self)
101
            platform.move(self)
102
            self.screen.blit(platform.texture, platform.rect)
103
104
        self.player.move()
105
        self.player.apply_gravity()
106
107
        if self.player.above(SCREEN_HEIGHT):
108
            self.over = True
109
110
        self.screen.blit(self.player.texture, self.player.rect)
111
112
        for bullet in self.bullets:
113
            bullet.move(self)
114
            self.screen.blit(bullet.texture, bullet.rect)
115
116
            if bullet.check_hit_box(self.player):
117
                self.over = True
118
                break
119
120
        if len(self.bullets) < 3:
121
            self.bullets.append(Bullet())
122
123
        pygame.draw.rect(
124
            self.screen, (255, 255, 255), ((5, 5), (1270, 710)), 3
125
        )
126
127
    def handle_events(self):
128
        for event in pygame.event.get():
129
            if event.type == pygame.QUIT:
130
                self.run = False
131
                return
132
133
            if event.type == pygame.KEYDOWN:
134
                if event.key in self.events:
135
                    self.events[event.key]()
136
137
            elif event.type == pygame.KEYUP:
138
                if event.key == pygame.K_SPACE:
139
                    self.player.jump_available = True
140
141
                elif event.key in [pygame.K_a, pygame.K_d]:
142
                    self.player.walk()
143
144
    def main(self):
145
        self.setup()
146
147
        while self.run:
148
            self.update()
149
            self.handle_events()
150
151
            if self.over:
152
                self.over_screen()
153
154
            else:
155
                self.draw()
156
157
    def draw(self):
158
        pygame.display.set_caption(
159
            f"{TITLE} | score : {self.score}"
160
            + (f" | {self.clock.get_fps():,.3f} " * self.show_fps)
161
        )
162
163
        pygame.display.update()
164
        self.score += int(self.player.ax)
165
        self.clock.tick(CAP_FPS)
166
167
    def pause_screen(self):
168
        pygame.mixer.music.pause()
169
        self.fade((0, 128, 255, 1), 64)
170
        pygame.display.set_caption(f"{TITLE} | score: {self.score} | Paused")
171
172
        self.screen.blit(
173
            *get_text(
174
                "Paused",
175
                self.fonts[96],
176
                (255, 255, 255),
177
                (640, 300),
178
                centered=True)
179
        )
180
181
        self.screen.blit(
182
            *get_text(
183
                "press escape to unpause",
184
                self.fonts[48],
185
                (255, 255, 255),
186
                (640, 400),
187
                centered=True
188
            )
189
        )
190
        pygame.display.update()
191
192
        self.pause = True
193
        while self.pause:
194
            event = pygame.event.wait()
195
            if event.type == pygame.KEYDOWN:
196
                if event.key == pygame.K_ESCAPE:
197
                    pygame.mixer.music.unpause()
198
                    pygame.event.clear()
199
                    self.pause = False
200
201
            elif event.type == pygame.QUIT:
202
                self.pause = False
203
                self.run = False
204
205
    def over_screen(self):
206
        pygame.mixer.music.pause()
207
        self.fade((255, 32, 32, 1), 128)
208
        pygame.display.set_caption(f"{TITLE} | GameOver")
209
210
        self.screen.blit(
211
            *get_text(
212
                "Game Over",
213
                self.fonts[96],
214
                (255, 255, 255),
215
                (640, 300),
216
                centered=True
217
            )
218
        )
219
220
        self.screen.blit(
221
            *get_text(
222
                "press space to retry",
223
                self.fonts[48],
224
                (255, 255, 255),
225
                (640, 400),
226
                centered=True
227
            )
228
        )
229
230
        pygame.display.update()
231
232
        self.pause = True
233
        while self.pause:
234
            event = pygame.event.wait()
235
            if event.type == pygame.KEYDOWN:
236
                if event.key == pygame.K_SPACE:
237
                    self.setup()
238
                    self.pause = False
239
240
            elif event.type == pygame.QUIT:
241
                self.pause = False
242
                self.run = False
243
244
    def fade(self, c, iterations):
245
        alpha_layer = pygame.Surface(SCREEN_SIZE, pygame.SRCALPHA)
246
        alpha_layer.fill(c)
247
248
        for _ in range(iterations):
249
            self.screen.blit(alpha_layer, (0, 0))
250
251
            pygame.draw.rect(
252
                self.screen, (255, 255, 255), ((5, 5), (1270, 710)), 3
253
            )
254
255
            for e in pygame.event.get():
256
                if e.type == pygame.QUIT:
257
                    break
258
259
            pygame.display.update()
260