Last active
October 21, 2024 16:54
-
-
Save horstjens/8fbb7dc3b4c94dc1084e3774d32db811 to your computer and use it in GitHub Desktop.
asteroid16
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import pygame | |
import random | |
import os.path | |
W, H = 1280, 720 | |
class TextSprite(pygame.sprite.DirtySprite): | |
def __init__(self, pos, color, textsize, text, age_max, anchor="center" ): | |
self.dirty = True | |
self.visible = True | |
self.blendmode = 0 | |
self._layer = 9 | |
self.anchor = anchor | |
pygame.sprite.DirtySprite.__init__(self, Game.uigroup, Game.allgroup) | |
self.pos = pygame.Vector2(pos[0],pos[1]) | |
self.color = color | |
self.textsize = textsize | |
self.text = text | |
self.age = 0 | |
self.age_max = age_max | |
self.change_color = False | |
self.move = pygame.Vector2(0, 0) | |
self.bounce = False | |
self.create_text(self.text) | |
def create_text(self, text): | |
font = pygame.font.SysFont("System", self.textsize) | |
if self.change_color: | |
r,g,b = self.color | |
new_colors = [] | |
for old_color in r,g,b: | |
new_color = old_color + random.randint(-100,100) | |
new_color = max(10, new_color) | |
new_color = min(255, new_color) | |
new_colors.append(new_color) | |
else: | |
new_colors = self.color | |
self.image = font.render(text, True, new_colors) | |
self.rect = self.image.get_rect() | |
self.image.set_colorkey((0,0,0)) | |
self.image = self.image.convert_alpha() | |
self.rect.center = self.pos | |
def update(self, dt): | |
self.age += dt | |
if self.age_max is not None: | |
if self.age > self.age_max: | |
self.kill() | |
self.pos += self.move * dt | |
if self.change_color: | |
self.create_text(self.text) | |
if self.bounce: | |
if self.pos.x < 0: | |
self.pos.x = 0 | |
self.move.x *= -1 | |
if self.pos.x > W: | |
self.pos.x = W | |
self.move.x *= -1 | |
if self.pos.y < 0: | |
self.pos.y = 0 | |
self.move.y *= -1 | |
if self.pos.y > H: | |
self.pos.y = H | |
self.move.y *= -1 | |
if self.anchor == "center": | |
self.rect.center = self.pos | |
elif self.anchor == "topleft": | |
self.rect.topleft = self.pos | |
class Rocket(pygame.sprite.DirtySprite): | |
def __init__(self, shooter ): | |
self.dirty = True | |
self.visible = True | |
self.blendmode = 0 | |
self._layer=6 | |
pygame.sprite.DirtySprite.__init__(self, Game.rocketgroup, Game.allgroup, Game.scrollgroup) | |
self.pos = pygame.Vector2(shooter.pos.x, shooter.pos.y) | |
try: | |
self.victim = random.choice(Game.playergroup.sprites()) | |
except IndexError: | |
self.kill() | |
self.hitpoints = 20 | |
self.age = 0 | |
self.age_max = 20 | |
self.speed = 100 | |
self.speed_max = 200 | |
self.image = pygame.surface.Surface((100, 20)) | |
pygame.draw.polygon(self.image, (64,255,0), | |
((0,0), (10,5),(50,5),(50,0),(55,5), | |
(80,5),(90,10), | |
(80,15), | |
(55,15),(50,20),(50,15),(10,15),(0,20), | |
(5,10)) | |
) | |
self.image.set_colorkey((0,0,0)) | |
self.image= pygame.transform.scale(self.image, (50,10)) | |
self.image = self.image.convert_alpha() | |
self.image0 = self.image.copy() | |
self.rect = self.image.get_rect() | |
self.rect.center = self.pos | |
self.move = pygame.Vector2(0,0) | |
def update(self, dt): | |
if self.hitpoints <= 0: | |
self.kill() | |
self.age += dt | |
if self.age > self.age_max: | |
self.kill() | |
if self.victim not in Game.playergroup: | |
self.kill() | |
# rotate toward victim | |
m = self.victim.pos - self.pos | |
m.normalize_ip() | |
winkel = m.angle_to(pygame.Vector2(1,0)) | |
self.image = pygame.transform.rotate(self.image0, winkel) | |
self.rect = self.image.get_rect() | |
self.rect.center = self.pos | |
#if self.speed < self.speed_max: | |
# self.speed *= 1.01 | |
# self.speed = min(self.speed_max, self.speed) | |
# verfolgung | |
m = pygame.math.Vector2(self.speed, 0) | |
m.rotate_ip(-winkel) | |
self.move += m * dt | |
self.pos += self.move * dt | |
self.rect.center = self.pos | |
if random.random() < 0.5: | |
v = pygame.Vector2(-25,0) | |
v.rotate_ip(-winkel) | |
Bubble(self.pos+v, | |
v*5, | |
acc = 0.99, | |
color_start=(64,255,0), | |
color_end=(0,64,0), | |
age_max=1, | |
radius_start=1, | |
radius_end=6, | |
) | |
class Ufo(pygame.sprite.DirtySprite): | |
def __init__(self): | |
self.dirty = True | |
self.visible = True | |
self.blendmode = 0 | |
self._layer = 4 | |
pygame.sprite.DirtySprite.__init__(self, Game.aliengroup, Game.allgroup, Game.scrollgroup) | |
self.hitpoints = 10 | |
self.image = pygame.surface.Surface((100,100)) | |
#pygame.draw.polygon(self.image, (64,64,64), ((30,20),(50,60), (70,40),(110,40),(160,90),(160,100), | |
# (150,110),(110,110),(110,120),(160,160),(110,120),(110,110), | |
# (70,110),(70,120),(20,160),(70,120),(70,110),(30,110),(20,100), | |
# (20,90),(50,60))) | |
pygame.draw.polygon(self.image, (0,128,0), ((10,50), (30,20), (70,20), (90,50), (80,65), (20,65))) # fill | |
pygame.draw.polygon(self.image, (0, 172, 0), ((10, 50), (30, 20), (70, 20), (90, 50), (80, 65), (20, 65)), 4) # line | |
pygame.draw.line(self.image, (0,172,0), (10,50),(90,50),5) | |
for x in (30,50,70): | |
#pygame.draw.circle(self.image, (0,0,0), (x, 40), 6) | |
pygame.draw.polygon(self.image, | |
(0,0,0), | |
[(x,30),(x-10, 40),(x+10,40)]) | |
self.image.set_colorkey((0,0,0)) | |
self.image = self.image.convert_alpha() | |
self.rect = self.image.get_rect() | |
self.w, self.h = self.rect.width, self.rect.height | |
ok = False | |
while not ok: | |
self.pos = pygame.Vector2(random.randint(0,W), | |
random.randint(0,H)) | |
# too close to player? | |
ok = True | |
for player in Game.playergroup: | |
distance = self.pos - player.pos | |
if distance.length() < 200: | |
ok = False | |
break | |
self.rect.center = self.pos | |
self.move = pygame.Vector2(random.uniform(50,100)) | |
self.move.rotate_ip(random.uniform(0,360)) | |
def update(self, dt): | |
if random.random() < 1/120: | |
Rocket(self) | |
if self.hitpoints <= 0: | |
for _ in range(250): | |
m = pygame.Vector2(random.uniform(300, 350), 0) | |
m.rotate_ip(random.random() * 360) | |
p = pygame.Vector2(self.pos.x, self.pos.y) | |
Bubble(p, m, color_start=(0,64,0), | |
color_end=(0,255,0), | |
age_max=4, | |
radius_start=5, | |
radius_end=20, | |
acc=0.995) | |
Game.sounds["ufokill"].play() | |
self.kill() | |
self.pos += self.move * dt | |
if random.random() < 0.01: | |
# change direction | |
self.move = pygame.Vector2(random.uniform(50, 200)) | |
self.move.rotate_ip(random.uniform(0, 360)) | |
# wrap at screen edge | |
# wrap | |
#if self.pos.x > W + self.w: | |
# self.pos.x = -self.w | |
#if self.pos.x < -self.w: | |
# self.pos.x = W + self.w# | |
#if self.pos.y > H + self.w: | |
# self.pos.y = -self.w | |
#if self.pos.y < -self.w: | |
# self.pos.y = H + self.w | |
# center | |
self.rect.center = self.pos | |
class Rock(pygame.sprite.DirtySprite): | |
def __init__(self, pos, size=1): | |
self.dirty = True | |
self.visible = True | |
self.blendmode = 0 | |
self._layer = 4 | |
pygame.sprite.DirtySprite.__init__(self, Game.rockgroup, Game.allgroup, Game.scrollgroup) | |
self.alpha = 255 | |
self.pos = pos | |
self.size = size | |
self.winkel = 0 | |
self.image = self.create_image() | |
self.image0 = self.image.copy() | |
self.rect = self.image.get_rect() | |
self.rect.center = self.pos | |
self.rotation_speed = random.uniform(1,100) * random.choice((1,-1)) | |
match size: | |
case 1: | |
self.hitpoints = 100 | |
self.hitpointsfull = 100 | |
low, high = 25,50 | |
case 2: | |
self.hitpoints = 50 | |
self.hitpointsfull = 50 | |
low, high = 55,100 | |
case 3: | |
self.hitpoints = 10 | |
self.hitpointsfull = 10 | |
low, high = 105,150 | |
case 4: | |
self.hitpoints = 5 | |
self.hitpointsfull = 5 | |
low, high = 155, 175 | |
if size == 1: | |
m = pygame.Vector2(W/2, H/2) | |
self.move = m - self.pos | |
self.move.normalize_ip() | |
self.move *= random.uniform(low, high) | |
else: | |
self.move = pygame.Vector2(random.uniform(low, high), 0) | |
self.move.rotate_ip(random.randint(0, 360)) | |
def create_image(self): | |
match self.size: | |
case 1: | |
self.w = 128 | |
case 2: | |
self.w = 64 | |
case 3: | |
self.w = 32 | |
case 4: | |
self.w = 16 | |
img = pygame.surface.Surface((self.w, self.w)) | |
points = [] | |
for winkel in range(0, 360, 360//12): | |
v = pygame.Vector2(random.uniform(0.6, 0.95),0) | |
v *= self.w // 2 | |
v.rotate_ip(winkel) | |
v += pygame.Vector2(self.w //2, self.w//2) | |
points.append((v.x, v.y)) | |
#points.append(points[0]) | |
farbe = (random.randint(170,210), | |
random.randint(120,160), | |
0) | |
pygame.draw.polygon(img,farbe, points) | |
img.set_colorkey((0,0,0)) | |
img = img.convert_alpha() | |
return img | |
def explode(self): | |
if self.size < 4: | |
for _ in range(3): | |
pos = self.pos.copy() | |
Rock(pos,self.size +1) | |
Game.sounds["rockkill"].play() | |
self.kill() | |
def update(self, dt): | |
# rotate | |
self.winkel += self.rotation_speed * dt | |
self.image = pygame.transform.rotate(self.image0, self.winkel) | |
self.rect = self.image.get_rect() | |
self.pos += self.move * dt | |
# wrap at screen edge | |
# wrap | |
#if self.pos.x > W + self.w: | |
# self.pos.x = -self.w | |
##if self.pos.x < -self.w: | |
# self.pos.x = W + self.w# | |
#if self.pos.y > H + self.w: | |
# self.pos.y = -self.w | |
#if self.pos.y < -self.w: | |
# self.pos.y = H + self.w | |
# center | |
#self.rect.center = self.pos | |
#print(self.rect.center) | |
class Bullet(pygame.sprite.DirtySprite): | |
def __init__(self, shooter): | |
Game.sounds["laser1"].play() | |
self.dirty = True | |
self.visible = True | |
self.blendmode = 0 | |
pygame.sprite.DirtySprite.__init__(self, Game.bulletgroup, Game.allgroup, Game.scrollgroup) | |
self.v0 = 300 | |
self.damage = 1 | |
self.shooter = shooter | |
self.pos = self.shooter.pos + shooter.nose | |
self.image = pygame.Surface((15,3)) | |
#self.image.fill((255,0,0)) # red | |
pygame.draw.line(self.image, (255,0,0), (0,1), (15,1),1) | |
self.image = pygame.transform.rotate(self.image, shooter.direction) | |
self.image.set_colorkey((0,0,0)) # make black transparent | |
self.image = self.image.convert_alpha() # no alpha necessary | |
self.mask = pygame.mask.from_surface(self.image) | |
self.rect = self.image.get_rect() | |
self.rect.center = self.pos | |
self.age = 0 | |
self.age_max = 4 | |
self.move = pygame.Vector2(self.v0, 0 ) | |
self.move.rotate_ip(-self.shooter.direction) | |
self.move += self.shooter.move.copy() | |
#print("bullet created") | |
def update(self, dt): | |
self.age += dt | |
if self.age > self.age_max: | |
self.kill() | |
self.pos += self.move * dt | |
# wrap at screen edge | |
# wrap | |
#if self.pos.x > W + 32: | |
# self.pos.x = -32 | |
#if self.pos.x < -32: | |
# self.pos.x = W + 32# | |
#if self.pos.y > H + 32: | |
# self.pos.y = -32 | |
#if self.pos.y < -32: | |
# self.pos.y = H + 32 | |
# center | |
self.rect.center = self.pos | |
#print(self.rect.center) | |
class Star(pygame.sprite.DirtySprite): | |
def __init__(self): | |
self.dirty = True | |
self.visible = True | |
self.blendmode = 0 | |
self._layer = 4 | |
pygame.sprite.DirtySprite.__init__(self, | |
Game.allgroup, Game.stargroup) | |
x = random.random() * W * 2 | |
y = random.random() * H * 2 | |
z = random.random() # 0...1 | |
self.pos = pygame.Vector3(x, y, z) | |
self.create_image() | |
def create_image(self): | |
size = int(self.pos.z * 5) + 1 | |
self.image = pygame.Surface((size,size)) | |
if size <= 2: | |
self.image.fill((255,255,255)) | |
else: | |
pygame.draw.circle(self.image, | |
(255,255,255), | |
(size/2, size/2), | |
size/2) | |
self.image.set_colorkey((0,0,0)) | |
self.image = self.image.convert_alpha() | |
self.rect = self.image.get_rect() | |
class Bubble(pygame.sprite.DirtySprite): | |
def __init__(self, | |
pos, | |
move=pygame.Vector2(0,0), | |
radius_start = 1, | |
radius_end = 10, | |
radius_plusminus = 3, | |
color_start=(0,0,200), | |
color_end=(0,0,200), | |
#colordelta=30, | |
acc=1.0, | |
age_min = 2.0, | |
age_max = 4.0, | |
age_max_plusminus = 1.0, | |
alpha_start=255, | |
alpha_end=0, | |
): | |
self.dirty = True | |
self.visible = True | |
self.blendmode = 0 | |
self._layer = 2 | |
pygame.sprite.DirtySprite.__init__(self, Game.allgroup, Game.scrollgroup) | |
self.pos = pygame.Vector2(pos[0],pos[1]) | |
self.move = pygame.Vector2(move[0], move[1]) | |
self.image = pygame.Surface((radius_end*2, radius_end*2)) | |
self.radius = radius_start | |
self.radius_start = radius_start | |
self.radius_end = radius_end + random.randint(-radius_plusminus, radius_plusminus) | |
self.color = [color_start[0], color_start[1], color_start[2]] | |
self.color_start = color_start | |
self.color_end = color_end | |
self.alpha = alpha_start | |
self.alpha_start = alpha_start | |
self.alpha_end = alpha_end | |
self.acc = acc | |
#self.age_max_plusminus = age_max_plusminus | |
self.age_max = age_max + random.uniform(-age_max_plusminus, age_max_plusminus) | |
self.age = 0 | |
self.draw_image() | |
self.rect = self.image.get_rect() | |
self.rect.center = self.pos | |
def draw_image(self): | |
pygame.draw.circle(self.image, # surface | |
self.color, # color | |
(self.radius_end, self.radius_end), # pos | |
self.radius, # radius | |
) | |
self.image.set_colorkey((0, 0, 0)) # black is transparent | |
self.image.set_alpha(self.alpha) | |
self.image = self.image.convert_alpha() | |
def update(self, dt): | |
self.age += dt | |
if self.age > self.age_max: | |
self.kill() | |
self.pos += self.move * dt | |
self.move *= self.acc | |
# kill on screen edge | |
if self.pos.x < 0 or self.pos.y < 0 or self.pos.x > W or self.pos.y > H: | |
self.kill() | |
self.age_percent = self.age / self.age_max | |
#self.color = [0,0,0] | |
for i in (0,1,2): | |
self.color[i] = int(self.color_start[i] + self.age_percent * (self.color_end[i] - self.color_start[i])) | |
self.color[i] = max(0, self.color[i]) | |
self.color[i] = min(255, self.color[i]) | |
#print(i, self.color[i]) | |
#print(self.age_percent, self.color) | |
# alpha: 0 is fully transparent, 255 is fully opaque | |
self.alpha = self.alpha_start + (self.alpha_end - self.alpha_start) * self.age_percent | |
self.image.fill((0,0,0)) # black | |
self.radius = self.radius_start + self.age_percent * (self.radius_end - self.radius_start) | |
self.draw_image() | |
self.rect.center = self.pos | |
class Player(pygame.sprite.DirtySprite): | |
def __init__(self, pos=pygame.Vector2(W/2,H/2)): | |
self.age = 0 | |
self.energy = 500 | |
self.energy_max = 500 | |
self.generator = 50 # energy per second | |
self.energy_per_shot = 10 | |
self.energy_per_shield = 100 # for each second with shield | |
self.energy_per_forward = 10 | |
self.energy_per_rotate = 5 | |
self.lives = 4 | |
self.dirty = True | |
self.visible = True | |
self.blendmode = 0 | |
self._layer = 5 | |
pygame.sprite.DirtySprite.__init__(self, Game.playergroup, Game.allgroup) | |
self.score = 0 | |
self.hitpoints = 100 | |
self.grace = 10.0 | |
self.unverwundbar = self.grace | |
self.number = len(Game.playergroup) + 1 | |
self.image = pygame.Surface((100,100)) | |
points = ((25, 25), (80, 50), (25, 75), (35, 50)) # looking to right | |
pygame.draw.polygon(self.image, "#ffffff", points, 0) | |
self.image.set_colorkey("#000000") | |
self.image = self.image.convert_alpha() | |
self.image0 = self.image.copy() | |
self.image1 = self.image.copy() | |
self.rect = self.image.get_rect() | |
self.move = pygame.Vector2(0,0) | |
self.rotation_speed = 180 # grad/second | |
self.speed_limit = 400 # pixel/second | |
self.moving_speed = 50 | |
self.direction = 0 | |
self.mass = 1000 | |
#self.pos = pygame.Vector2(W / 2, H / 2) | |
self.pos = pos | |
self.vec_nose = pygame.Vector2(32,0) # from center | |
self.vec_upper_engine = pygame.Vector2(-25,-25) # from center | |
self.vec_lower_engine = pygame.Vector2(-25,25) # from center | |
self.nose = self.vec_nose.copy() | |
self.upper_engine = self.vec_upper_engine.copy() | |
self.lower_engine = self.vec_lower_engine.copy() | |
self.schutzschild() | |
self.timeout_bullet = 0.1 | |
self.time_since_last_bullet = 0 | |
def forward(self, dt, power=2.8): | |
if self.energy < self.energy_per_forward * dt: | |
return | |
self.energy -= self.energy_per_forward * dt | |
new_move = pygame.Vector2(self.moving_speed, 0) * dt * power | |
# new_move += pygame.Vector2(player_moving_speed, 0) * dt | |
new_move.rotate_ip(-self.direction) | |
self.move += new_move | |
if random.random() < 0.3: | |
bubblemove = pygame.Vector2(2, 0) | |
bubblemove.rotate_ip(-self.direction) | |
bubblemove *= (1 + self.move.length()) | |
bubblemove *= 0 | |
Bubble(self.pos + self.upper_engine, -bubblemove, color_start=(255,255,0), color_end=(255,0,0), age_max=2) | |
Bubble(self.pos + self.lower_engine, -bubblemove, color_start=(255,255,0), color_end=(255,0,0), age_max=2 ) | |
def rotate(self, dt, clockwise=True, power=1.5): | |
if self.energy < self.energy_per_rotate * dt: | |
return | |
self.energy -= self.energy_per_rotate * dt | |
if clockwise: | |
sign = -1 | |
else: | |
sign = 1 | |
self.direction += self.rotation_speed * dt * sign * power | |
self.image1 = pygame.transform.rotate(self.image0, self.direction) | |
self.rect = self.image1.get_rect() | |
self.rect.center = self.pos | |
# player1.rect = player1.image.get_rect() | |
self.nose = self.vec_nose.rotate(-self.direction) | |
self.upper_engine = self.vec_upper_engine.rotate(-self.direction) | |
self.lower_engine = self.vec_lower_engine.rotate(-self.direction) | |
# make bubbles | |
if random.random() < 0.4: | |
bubblemove = pygame.Vector2(110, 0) | |
bubblemove.rotate_ip(-self.direction + 90) | |
# HIER WEITERMACHEN! | |
Bubble(self.pos + self.upper_engine, -bubblemove, color_start=(255,255,0), color_end=(255,0,0), age_max=1, radius_start=1, radius_end=4 ) | |
Bubble(self.pos + self.lower_engine, -bubblemove, color_start=(255,255,0), color_end=(255,0,0), age_max=1, radius_start=1, radius_end=4) | |
bubblemove = pygame.Vector2(110, 0) | |
bubblemove.rotate_ip(-self.direction - 90) | |
Bubble(self.pos + self.nose, -bubblemove, color_start=(255,255,0), color_end=(255,0,0), age_max=1, radius_start=1, radius_end=4) | |
def schutzschild(self): | |
self.schild = pygame.Surface((100, 100)) | |
pygame.draw.circle(self.schild, | |
(0,0,255), # blau | |
(50,50), # center | |
40 # radius | |
) | |
self.schild.set_colorkey((0,0,0)) # schwarz | |
if self.unverwundbar > self.age: | |
#if self.unverwundbar < self.grace: | |
p = (self.unverwundbar-self.age) / self.grace | |
self.schild.set_alpha(p * 250) | |
self.schild = self.schild.convert_alpha() | |
def shoot(self): | |
if self.time_since_last_bullet > self.timeout_bullet: | |
if self.energy < self.energy_per_shot: | |
return | |
self.energy -= self.energy_per_shot | |
self.time_since_last_bullet = 0 | |
Bullet(self) | |
def activate_shield(self): | |
if self.energy < self.energy_per_shield : | |
return | |
if self.unverwundbar > self.age: | |
return | |
self.unverwundbar = self.age + 1 # shield for 1 second | |
self.unverwundbar = min(self.grace, self.unverwundbar) | |
def update(self, dt ): | |
self.age += dt | |
self.energy += self.generator * dt | |
self.time_since_last_bullet += dt | |
# friction | |
if self.unverwundbar <= self.age: | |
self.image = self.image1.copy() | |
else: | |
self.energy -= self.energy_per_shield * dt | |
if self.energy <= 0: | |
self.unverwundbar = 0 | |
self.unverwundbar -= dt | |
if self.unverwundbar < 0: | |
self.unverwundbar = 0 | |
#self.unverwundbar = max(self.unverwundbar, 0) | |
self.image = self.image1.copy() | |
x = self.rect.width // 2 | |
y = self.rect.height // 2 | |
self.schutzschild() | |
self.image.blit(self.schild, | |
(x-self.schild.get_width()//2, | |
y-self.schild.get_height()//2)) | |
self.move *= 0.95 | |
# speed limit | |
if self.move.length() > self.speed_limit: | |
self.move = self.move.normalize() * self.speed_limit | |
self.pos += self.move * dt | |
Game.screenpos = pygame.Vector2(self.pos.x - W/2, self.pos.y - H/2) | |
# wrap | |
#if self.pos.x > W + 32: | |
# self.pos.x = -32 | |
#if self.pos.x < -32: | |
# self.pos.x = W + 32# | |
#if self.pos.y > H + 32: | |
# self.pos.y = -32 | |
#if self.pos.y < -32: | |
# self.pos.y = H + 32 | |
# pos | |
#self.rect.center = self.pos | |
self.rect.center = (W//2, H//2) | |
#self.draw() | |
class Game: | |
background = None | |
screen = None | |
player1 = None | |
player2 = None | |
clock = None | |
sounds = {} | |
joysticks = {} | |
scoretext1 = "" | |
scoretext2 = "" | |
ufo_timeout = 30 | |
FPS = 60 | |
# sprite groups | |
playergroup = pygame.sprite.Group() | |
aliengroup = pygame.sprite.Group() | |
bulletgroup = pygame.sprite.Group() | |
rocketgroup = pygame.sprite.Group() | |
rockgroup = pygame.sprite.Group() | |
uigroup = pygame.sprite.Group() | |
# allgroup = pygame.sprite.RenderUpdates() | |
scrollgroup = pygame.sprite.Group() | |
stargroup = pygame.sprite.Group() | |
allgroup = pygame.sprite.LayeredDirty() | |
screenpos = (0,0) | |
def create_background(): | |
Game.background = pygame.Surface((W * 2, H *2)) | |
for _ in range(200): | |
Star() | |
#light = random.randint(64, 172) | |
#radius_max = 5 | |
#pygame.draw.circle(Game.background, (light, light, light), (random.randint(0, W), random.randint(0, H)), | |
# random.randint(1, radius_max)) | |
# big Asteroids font on center of background | |
font = pygame.font.SysFont("System", 256) | |
textsurface = font.render("Asteroids", # text | |
True, # antialias | |
(32, 32, 32), # color | |
) | |
w, h = textsurface.get_rect().size | |
Game.background.blit(textsurface, (W / 2 - w / 2, H / 2 - h / 2)) | |
# little "created by" font on right bottom corner of background | |
font = pygame.font.SysFont("System", 32) | |
textsurface = font.render("created 2024 by spielend-programmieren.at", # text | |
True, # antialias | |
(64, 64, 0), # color | |
) | |
w, h = textsurface.get_rect().size | |
Game.background.blit(textsurface, (W - w - 10, H - h - 5)) | |
def create_ui_layer(): | |
# left top corner | |
# a lot of Textsprites | |
#layer = pygame.Surface((W,H)) | |
TextSprite(pos=(0,0), color=(255,255,255), textsize=32, text="Player One", age_max=None, anchor="topleft") | |
Game.text_lives_1 = TextSprite(pos=(0,25), color=(255,255,255), textsize=24, text="Lives:", age_max=None, anchor="topleft") | |
Game.text_shield_1 = TextSprite(pos=(0,50), color=(0,0,255), textsize=24, text="Shield:", age_max=None, anchor="topleft" ) | |
Game.text_energy_1 = TextSprite(pos=(0,75), color=(255,255,0), textsize=24, text="Energy:", age_max=None, anchor="topleft") | |
Game.text_score_1 = TextSprite(pos=(0,100), color=(255,255,255), textsize=24, text="Score:", age_max=None, anchor="topleft") | |
#font = pygame.font.SysFont("System", 32) | |
#text = font.render("Player One", | |
# True, | |
# (255, 255, 255)) | |
#layer.blit(text, (0, 0)) | |
#text = font.render("Lives:", True, (255,255,255)) | |
#layer.blit(text,(0, 25)) | |
#text = font.render("Shield:", True, (0,255,0)) | |
#layer.blit(text,(0, 50)) | |
#text = font.render("Energy:", True, (255,255,0)) | |
#layer.blit(text,(0,75)) | |
#text = font.render("Score:", True, (255,255,255)) | |
#layer.blit(text,(0,100)) | |
#layer.set_colorkey((0,0,0)) | |
#layer.convert_alpha() | |
#Game.ui_layer = layer | |
def new_wave(): | |
Rock(pygame.Vector2(0, 0), 1, ) | |
Rock(pygame.Vector2(W, 0), 1, ) | |
Rock(pygame.Vector2(W, H), 1, ) | |
Rock(pygame.Vector2(0, H), 1, ) | |
def load_assets(): # (os.path.join("Sounds", "laser1.wav") | |
Game.sounds["laser1"] = pygame.mixer.Sound("soundeffect_laser1.wav") | |
Game.sounds["impact1"] = pygame.mixer.Sound("soundeffect_impact1.wav") | |
Game.sounds["ufo"] = pygame.mixer.Sound("soundeffect_ufohit.wav") | |
Game.sounds["ufokill"] = pygame.mixer.Sound("soundeffect_ufokill.wav") | |
Game.sounds["rockkill"] = pygame.mixer.Sound("soundeffect_rockkill.wav") | |
def setup(): | |
# pygame setup | |
pygame.init() | |
#print("joystick:", pygame.joystick.get_init()) | |
#FPS = 60 # frames per seconds that we wish for (reality will be sometimes lower) | |
Game.screen = pygame.display.set_mode((W, H)) | |
Game.clock = pygame.time.Clock() | |
running = True | |
#dt = 0 | |
# sterne malen | |
create_background() | |
# sprites | |
Game.player1 = Player() | |
create_ui_layer() | |
#player1 = Player() | |
#ufo1 = Ufo(aliengroup, allgroup) | |
score = 0 | |
#time_without_ufo = 0 | |
#ufo_timeout = 10 | |
#Game.scoretext1 = TextSprite((0,0),(0,255,0),32, | |
# "Score: 0 Shield: 5 s",None) | |
#w, h = Game.scoretext1.image.get_rect().size | |
#Game.scoretext1.pos = pygame.Vector2(w/2,h/2) | |
#new_wave() | |
#Game.energytext1 = TextSprite((0,40), (255,255,0), 32, f"energy: {int(Game.player1.energy/5000*50)}",None) | |
#w, h = Game.energytext1.image.get_rect().size | |
#Game.energytext1.pos = pygame.Vector2(w/2, h/2+20) | |
def mainloop(): | |
running = True | |
dt = 0 | |
time_without_ufo = 0 | |
Game.screen.blit(Game.background, (0,0)) | |
pygame.display.flip() # once! | |
while running: | |
#Game.scoretext1.create_text(f"Lives: {"@"*Game.player1.lives} Shield: {Game.player1.unverwundbar:.1f} {int(Game.player1.unverwundbar)*'-'} Score: {Game.player1.score}") | |
#w,h = Game.scoretext1.image.get_rect().width, Game.scoretext1.image.get_rect().height | |
#Game.scoretext1.pos = (w/2,h/2) | |
# energy bar (a bit less than half screen): | |
#Game.energytext1.create_text(f"energy: {Game.player1.energy:.0f} {int(Game.player1.energy / 5000 * 35)*"~"}") | |
#w, h = Game.energytext1.image.get_rect().size | |
#Game.energytext1.pos = pygame.Vector2(w / 2, h / 2 + 20) | |
Game.text_lives_1.create_text(f"Lives: {Game.player1.lives * '@'}") | |
Game.text_shield_1.create_text(f"Shield: {int(Game.player1.unverwundbar * 6) * '='}") | |
Game.text_energy_1.create_text(f"Energy: {int(Game.player1.energy/5) * '~'}") | |
if len(Game.rockgroup) == 0: | |
new_wave() | |
# collision detection bullet vs Rocket | |
for rocket in Game.rocketgroup: | |
crashgroup = pygame.sprite.spritecollide(rocket, Game.bulletgroup, False) | |
for b in crashgroup: | |
impactpoint = pygame.sprite.collide_mask(rocket, b) | |
if impactpoint is not None: | |
b.kill() | |
rocket.hitpoints -= 1 | |
# collision detection player vs Rocket | |
for player in Game.playergroup: | |
if player.lives <= 0: | |
continue | |
crashgroup = pygame.sprite.spritecollide(player, Game.rocketgroup, False) | |
for r in crashgroup: | |
impactpoint = pygame.sprite.collide_mask(player, r) | |
if impactpoint is not None: | |
if player.unverwundbar <= 0: | |
player.hitpoints -= 1 | |
else: | |
#player.unverwundbar = 0 | |
player.energy = 0 | |
# in any case | |
r.kill() | |
# collision detection rocket vs rock | |
for rock in Game.rockgroup: | |
crashgroup = pygame.sprite.spritecollide(rock, Game.rocketgroup, False) | |
for r in crashgroup: | |
impactpoint = pygame.sprite.collide_mask(rock, r) | |
if impactpoint is not None: | |
r.kill() | |
# collision detection player vs Rock | |
for player in Game.playergroup: | |
if player.lives <= 0: | |
continue | |
if player.unverwundbar <= 0: | |
crashgroup = pygame.sprite.spritecollide(player, Game.rockgroup, False) | |
for c in crashgroup: | |
impactpoint = pygame.sprite.collide_mask(player, c) | |
if impactpoint is not None: | |
player.unverwundbar = 0 + player.grace | |
player.move = pygame.Vector2(0,0) | |
player.lives -= 1 | |
# explosion | |
for _ in range(250): | |
m = pygame.Vector2(random.uniform(300, 350), 0) | |
m.rotate_ip(random.random() * 360) | |
p = pygame.Vector2(player.pos.x, player.pos.y) | |
Bubble(p, m, color_start=(255, 255, 255), | |
color_end=(10, 10, 10), | |
age_max=5, | |
radius_start=8, | |
radius_end=25, | |
acc=0.991) | |
if player.lives > 0: | |
player.pos = pygame.Vector2(W/2,H/2) | |
else: | |
for _ in range(500): | |
p = pygame.Vector2(player.pos.x, player.pos.y) | |
m = pygame.Vector2(random.uniform(50,400),0) | |
m.rotate_ip(random.random() * 360) | |
Bubble(p,m,color_start=(0,0,128),color_end=(0,0,255), acc=0.99) | |
player.kill() | |
if len(Game.playergroup) == 0: | |
gosprite = TextSprite((100,100), # pos | |
(255,0,0), # color | |
200, | |
"Game Over", | |
None, | |
) | |
gosprite.change_color = True | |
gosprite.move = pygame.Vector2(300, 50) | |
gosprite.bounce = True | |
# collision between Bullet and Ufo | |
for ufo in Game.aliengroup: | |
crashgroup = pygame.sprite.spritecollide(ufo, Game.bulletgroup, False) | |
for b in crashgroup: | |
impactpoint = pygame.sprite.collide_mask(ufo, b) | |
if impactpoint is None: | |
continue | |
else: | |
b.shooter.score += 5 | |
#Game.scoretext1.create_text(f"Score: {b.shooter.score}") | |
ufo.hitpoints -= 1 | |
Game.sounds["ufo"].play() | |
b.kill() | |
# collision detection Bullet vs Rock | |
for rock in Game.rockgroup: | |
crashgroup = pygame.sprite.spritecollide(rock, Game.bulletgroup, False) | |
for b in crashgroup: | |
impactpoint = pygame.sprite.collide_mask(rock, b) | |
if impactpoint is None: | |
continue | |
else: | |
# impact bubble | |
reflection = b.move.copy() | |
reflection *= -0.75 # invert direction and slow | |
reflection.rotate_ip(random.gauss(0,20)) | |
Bubble(pos=b.pos.copy(),age_min=0.3, age_max=1.2, | |
color_start=(random.randint(128,255),0,0), color_end=(random.randint(64,128),0,0), | |
radius_start=1,radius_end=8, | |
move=reflection, | |
acc = 0.6) | |
b.shooter.score += 1 | |
rock.hitpoints -= b.damage | |
percent = rock.hitpoints / rock.hitpointsfull | |
percent = 0.25 + percent * 0.75 | |
rock.image0.set_alpha(int(percent * 255)) | |
# move rock a bit | |
rock.move += b.move.normalize() * 1 | |
if rock.hitpoints <= 0: | |
rock.explode() | |
#Game.player1.score += 1 | |
b.shooter.score += 100 | |
Game.scoretext1.create_text(f"Score: {Game.player1.score}") | |
b.kill() | |
Game.sounds["impact1"].play() | |
# poll for events | |
# pygame.QUIT event means the user clicked X to close your window | |
for event in pygame.event.get(): | |
if event.type == pygame.QUIT: | |
running = False | |
if event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE: | |
running = False | |
if event.type == pygame.KEYDOWN and event.key == pygame.K_LSHIFT: | |
if Game.player1.energy > 1000: | |
Game.player1.energy -= 1000 | |
Game.player1.unverwundbar += 1 | |
Game.player1.unverwundbar = min(Game.player1.grace, Game.player1.unverwundbar) | |
Game.player1.score -= 100 | |
# Handle hotplugging joysticks | |
if event.type == pygame.JOYDEVICEADDED: | |
# This event will be generated when the program starts for every | |
# joystick, filling up the list without needing to create them manually. | |
joy = pygame.joystick.Joystick(event.device_index) | |
Game.joysticks[joy.get_instance_id()] = joy | |
print(f"Joystick {joy.get_instance_id()} connencted") | |
# handle removing josticks | |
if event.type == pygame.JOYDEVICEREMOVED: | |
del Game.joysticks[event.instance_id] | |
print(f"Joystick {event.instance_id} disconnected") | |
keys = pygame.key.get_pressed() | |
if Game.player1.lives > 0: | |
if keys[pygame.K_SPACE]: | |
Game.player1.shoot() | |
if keys[pygame.K_w] or keys[pygame.K_UP]: | |
Game.player1.forward(dt) | |
if keys[pygame.K_a] or keys[pygame.K_LEFT]: | |
Game.player1.rotate(dt, clockwise=False) | |
if keys[pygame.K_d] or keys[pygame.K_RIGHT]: | |
Game.player1.rotate(dt, clockwise=True) | |
if keys[pygame.K_LSHIFT]: | |
Game.player1.activate_shield() | |
# For each joystick: | |
for nr, joystick in enumerate(Game.joysticks.values()): | |
jid = joystick.get_instance_id() | |
hats = joystick.get_numhats() | |
for i in range(hats): | |
hat = joystick.get_hat(i) # tuple x,y with values -1, 0, 1 | |
buttons = joystick.get_numbuttons() | |
axes = joystick.get_numaxes() | |
#print(i, hat) | |
if nr == 0 and Game.player1.lives > 0: # player1 | |
x,y = hat | |
if x==-1: # turn left | |
Game.player1.rotate(dt, clockwise=False) | |
if x==1: # turn right | |
Game.player1.rotate(dt, clockwise=True) | |
if y == 1: # forward | |
Game.player1.forward(dt) | |
#for i in range(buttons): | |
# button = joystick.get_button(i) | |
# #print(i, button) | |
if joystick.get_button(0): | |
# blue button is pressed | |
#Bullet(Game.player1) | |
Game.player1.shoot() | |
# print axes | |
#for i in range(axes): | |
# axis = joystick.get_axis(i) | |
# print(i, axis) | |
deadzone = 0.1 | |
# rotate | |
power = joystick.get_axis(0) | |
if power > deadzone: | |
Game.player1.rotate(dt, clockwise=True, power=abs(power)) | |
elif power < -deadzone: | |
Game.player1.rotate(dt, clockwise=False, power=abs(power)) | |
# forward | |
power = joystick.get_axis(1) | |
if power < -deadzone: | |
Game.player1.forward(dt, abs(power)) | |
# move everything in scrollgroup according to player.move | |
for thing in Game.scrollgroup: | |
#thing.pos -= Game.player1.move | |
thing.rect.topleft = thing.pos - Game.screenpos | |
# stars | |
for star in Game.stargroup: | |
star.pos.x += Game.player1.move.x * star.pos.z | |
star.pos.y += Game.player1.move.y * star.pos.z | |
star.rect.center = pygame.Vector2(star.pos.x, star.pos.y) - Game.screenpos | |
# spritegroups | |
if len(Game.playergroup) > 0: # at least one player is alive | |
#if keys[pygame.K_0]: | |
Game.allgroup.clear(Game.screen, Game.background) | |
Game.allgroup.update(dt) | |
for s in Game.allgroup: | |
s.dirty = True | |
dirty = Game.allgroup.draw(Game.screen) | |
pygame.display.update(dirty) | |
##Game.screen.blit(Game.ui_layer, (0,0)) | |
else: # all players are dead -> Game Over mode | |
Game.allgroup.update(dt) | |
#for s in allgroup: | |
# s.dirty = True | |
#dirty= allgroup.draw(screen) | |
for s in Game.allgroup: | |
topleft = s.rect.topleft | |
Game.screen.blit(s.image, topleft) | |
#pygame.display.update(dirty) | |
#allgroup.repaint_rect(screen.get_rect()) | |
##Game.screen.blit(Game.ui_layer, (0, 0)) | |
pygame.display.flip() | |
#pygame.display.flip() | |
if len(Game.aliengroup) == 0: | |
time_without_ufo += dt | |
if time_without_ufo > Game.ufo_timeout: | |
time_without_ufo = 0 | |
Ufo() | |
# limits FPS to 60 | |
# dt is delta time in seconds since last frame, used for framerate- | |
# independent physics. | |
dt = Game.clock.tick(Game.FPS) / 1000 | |
pygame.display.set_caption(f"fps: {Game.clock.get_fps():.2f} resolution: {W}x{H} lives: {Game.player1.lives} u:{Game.player1.unverwundbar:.2f}") | |
if __name__ == "__main__": | |
setup() | |
load_assets() | |
mainloop() | |
pygame.quit() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment