-
Notifications
You must be signed in to change notification settings - Fork 6
/
world.py
190 lines (158 loc) · 6.34 KB
/
world.py
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
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
import os
import math
import random
import sys
import pygame
from pygame import mixer
import util
import sprite
import particle
import text
import alien
import ship
import asteroid
class World(object):
def __init__(self, surface):
self.surface = surface
self.width = surface.get_width()
self.height = surface.get_height()
self.sprites = []
self.particle = particle.Particle(surface)
self.score = 0
self.n_asteroids = 0
self.text_y = 100
# input state
self.quit = False
self.rotate_left = False
self.rotate_right = False
self.rotate_by = 0
self.thrust = False
self.info = False
self.fire = False
self.spawn = False
self.show_particles = True
self.enter = False
self.next_level = False
# the ship ... or none for no ship on screen
self.player = None
# countdown timer until next alien
self.alien_time = random.randint(1000, 2000)
self.music_playing = True
self.background_music = mixer.Sound(os.path.join("sounds", "hoarse_space_cadet.ogg"))
self.background_channel = pygame.mixer.Channel(0)
self.background_channel.play(self.background_music, loops = -1)
def n_objects(self):
return len(self.sprites)
def play_music(self, play):
if play:
self.background_channel.unpause()
else:
self.background_channel.pause()
def reset(self):
self.sprites = []
self.n_asteroids = 0
self.particle.remove_all()
self.text_y = 100
self.score = 0
self.player = None
def remove_asteroids(self):
self.sprites = [x for x in self.sprites
if not isinstance(x, asteroid.Asteroid)]
def add(self, sprite):
self.sprites.append(sprite)
def add_player(self):
if not self.player:
self.player = ship.Ship(self)
def add_text(self, string, scale = 10):
text.Character.string(self, string,
[self.width / 2, self.text_y], scale)
self.text_y += scale * 5
def update(self):
for event in pygame.event.get():
if event.type == pygame.QUIT:
self.quit = True
if event.type == pygame.KEYDOWN or event.type == pygame.KEYUP:
if event.key == pygame.K_ESCAPE:
self.quit = event.type == pygame.KEYDOWN
elif event.key == pygame.K_LEFT:
self.rotate_left = event.type == pygame.KEYDOWN
elif event.key == pygame.K_RIGHT:
self.rotate_right = event.type == pygame.KEYDOWN
elif event.key == pygame.K_UP:
self.thrust = event.type == pygame.KEYDOWN
elif event.key == pygame.K_SPACE:
self.fire = event.type == pygame.KEYDOWN
elif event.key == pygame.K_s:
self.spawn = event.type == pygame.KEYDOWN
elif event.key == pygame.K_n:
self.next_level = event.type == pygame.KEYDOWN
elif event.key == pygame.K_m and event.type == pygame.KEYDOWN:
self.music_playing = not self.music_playing
self.play_music(self.music_playing)
elif event.key == pygame.K_p:
if event.type == pygame.KEYDOWN:
self.show_particles = not self.show_particles
elif event.key == pygame.K_i:
self.info = event.type == pygame.KEYDOWN
elif event.key == pygame.K_RETURN:
self.enter = event.type == pygame.KEYDOWN
elif event.key == pygame.K_f:
if self.player:
self.player.shield_on()
elif event.type == pygame.MOUSEBUTTONDOWN or event.type == pygame.MOUSEBUTTONUP:
if event.button == 3:
self.thrust = event.type == pygame.MOUSEBUTTONDOWN
elif event.button == 1:
self.fire = event.type == pygame.MOUSEBUTTONDOWN
self.particle.show(self.show_particles)
x, y = pygame.mouse.get_rel()
self.rotate_by = x / 5.0
if self.rotate_left:
self.rotate_by = -3
elif self.rotate_right:
self.rotate_by = 3
if self.player:
self.player.thrust(self.thrust)
if self.fire:
self.player.fire();
self.player.rotate_by(self.rotate_by)
for i in self.sprites:
i.update()
self.particle.update()
self.alien_time -= 1
if self.alien_time < 0:
self.alien_time = random.randint(1000, 2000)
alien.Alien(self)
if self.player and self.player.kill:
self.player = None
self.sprites = [x for x in self.sprites if not x.kill]
# split the world into a map of 100x100 squares, put a note in each
# square of each sprite which intersects with that square ... then when
# we test for collisions, we only need to test against the sprites in
# that map square
# 100 is the max radius of the asteroids we make
map_spacing = 100
map_width = int(math.ceil(float(self.width) / map_spacing))
map_height = int(math.ceil(float(self.height) / map_spacing))
world_map = []
for x in range(map_width):
map_row = [[] for y in range(map_height)]
world_map.append(map_row)
for i in self.sprites:
i.tested_collision = False
x = int(i.position[0] / map_spacing) % map_width
y = int(i.position[1] / map_spacing) % map_height
for a in range(x - 1, x + 2):
for b in range(y - 1, y + 2):
world_map[a % map_width][b % map_height].append(i)
for i in self.sprites:
x = int(i.position[0] / map_spacing) % map_width
y = int(i.position[1] / map_spacing) % map_height
i.test_collisions(world_map[x][y])
# now we've tested i against everything it could possibly touch,
# we no longer need to test anything against i
i.tested_collision = True
def draw(self):
self.particle.draw()
for i in self.sprites:
i.draw()