Created
November 12, 2024 08:08
-
-
Save horstjens/23c1256ad45d0dc7488a6c9c332068c4 to your computer and use it in GitHub Desktop.
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 math | |
class Game: | |
W, H = 1500, 751 | |
FPS = 60 | |
scrollspeed = -2 | |
stargroup = pygame.sprite.Group() | |
playergroup = pygame.sprite.Group() | |
lasergroup = pygame.sprite.Group() | |
enemygroup = pygame.sprite.Group() | |
plasmagroup = pygame.sprite.Group() | |
allgroup = pygame.sprite.LayeredDirty() | |
class Enemy1(pygame.sprite.DirtySprite): | |
def __init__(self, pos): | |
self.pos = pos | |
self.move = pygame.Vector2(random.randint(-100,-50), | |
random.randint(-20,20)) | |
#self.dirty = True | |
#self.visible = True | |
#self.blendmode = 0 | |
self._layer = 8 | |
pygame.sprite.DirtySprite.__init__(self, | |
Game.allgroup, | |
Game.enemygroup) | |
self.color = (random.randint(128, 255), 0, random.randint(128, 255)) | |
self.image = self.create_image() | |
self.rect = self.image.get_rect() | |
self.rect.center = self.pos | |
def create_image(self): | |
image = pygame.Surface((50,30)) | |
pygame.draw.polygon(image, | |
self.color, | |
((50,0),(0,15),(50,30),(40,15),(50,0))) | |
image.set_colorkey((0,0,0)) | |
image = image.convert_alpha() | |
return image | |
def update(self, dt): | |
self.pos += self.move * dt | |
if self.pos.x < 0: | |
self.kill() | |
if self.pos.y < 0: | |
self.pos.y = 0 | |
self.move.y *= -1 | |
if self.pos.y > Game.H: | |
self.pos.y = Game.H | |
self.move.y *= -1 | |
self.rect.center = self.pos | |
if random.random() < 1/Game.FPS / 10: | |
Plasma(self) | |
class Enemy2(pygame.sprite.DirtySprite): | |
def __init__(self, pos, dx=-50, yf=50, age=0): | |
self.y_factor = yf | |
self.pos = pos | |
self.age = age | |
self.dx = dx | |
#self.dirty = True | |
#self.visible = True | |
#self.blendmode = 0 | |
self._layer = 8 | |
pygame.sprite.DirtySprite.__init__(self, | |
Game.allgroup, | |
Game.enemygroup) | |
self.color = (random.randint(128, 255), 0, random.randint(128, 255)) | |
self.image = self.create_image() | |
self.rect = self.image.get_rect() | |
self.rect.center = self.pos | |
def create_image(self): | |
image = pygame.Surface((50,50)) | |
pygame.draw.circle(image,self.color,(25,25),25) | |
pygame.draw.circle(image, (0,0,0), (25, 25), 18) | |
image.set_colorkey((0,0,0)) | |
image = image.convert_alpha() | |
return image | |
def update(self, dt): | |
self.age += dt | |
self.dy = math.sin(self.age) * self.y_factor | |
self.move = pygame.Vector2(self.dx, self.dy) | |
self.pos += self.move * dt | |
if self.pos.x < 0: | |
self.kill() | |
self.rect.center = self.pos | |
#if random.random() < 1/Game.FPS / 10: | |
# Plasma(self) | |
class Player(pygame.sprite.DirtySprite): | |
def __init__(self, pos): | |
self.pos = pos | |
self.speed = 55 | |
self.move = pygame.Vector2(0,0) | |
self.dirty = True | |
self.visible = True | |
self.blendmode = 0 | |
self._layer = 1 | |
self.hitpoints = 100 | |
self.hitpoints_full = 100 | |
pygame.sprite.DirtySprite.__init__(self, | |
Game.allgroup, | |
Game.playergroup) | |
self.create_image() | |
self.rect = self.image.get_rect() | |
self.rect.center = self.pos | |
self.laser_cooldown = 0.25 | |
self.laser_blocked = 0 | |
self.age = 0 | |
self.laser_version = 1 | |
self.wounds = [(0,0),(50,0),(-50,25)] | |
def fire_laser(self): | |
if self.age > self.laser_blocked: | |
#if self.laser_version == 1: | |
# pass | |
#elif self.laser_version == 2: | |
# pass | |
self.laser_blocked = self.age + self.laser_cooldown | |
match self.laser_version: | |
case 1: | |
Laser(self, move_direction=pygame.Vector2(5, 0)) | |
case 2: | |
Laser(self, move_direction=pygame.Vector2(15, 1)) | |
Laser(self, move_direction=pygame.Vector2(15, -1)) | |
case 3: | |
Laser(self, move_direction=pygame.Vector2(5, 1)) | |
Laser(self, move_direction=pygame.Vector2(5, 0)) | |
Laser(self, move_direction=pygame.Vector2(5, -1)) | |
case 4: | |
Laser(self, move_direction=pygame.Vector2(5, 2)) | |
Laser(self, move_direction=pygame.Vector2(15, 1)) | |
Laser(self, move_direction=pygame.Vector2(15, -1)) | |
Laser(self, move_direction=pygame.Vector2(5, -2)) | |
case 5: | |
Laser(self, move_direction=pygame.Vector2(5, 2)) | |
Laser(self, move_direction=pygame.Vector2(5, 1)) | |
Laser(self, move_direction=pygame.Vector2(5, 0)) | |
Laser(self, move_direction=pygame.Vector2(5, -1)) | |
Laser(self, move_direction=pygame.Vector2(5, -2)) | |
def create_image(self): | |
self.image = pygame.Surface((100,50)) | |
pygame.draw.polygon(self.image, | |
(100,100,255), | |
[(0,0),(100,25),(0,50),(15,25)]) | |
self.image.set_colorkey((0,0,0)) | |
self.image = self.image.convert_alpha() | |
def update(self, dt): | |
self.age += dt | |
pressed_keys = pygame.key.get_pressed() | |
self.move = pygame.Vector2(0,0) | |
if pressed_keys[pygame.K_w] or pressed_keys[pygame.K_UP]: | |
self.move.y -= self.speed | |
if pressed_keys[pygame.K_s] or pressed_keys[pygame.K_DOWN]: | |
self.move.y += self.speed | |
if pressed_keys[pygame.K_a] or pressed_keys[pygame.K_LEFT]: | |
self.move.x -= self.speed | |
if pressed_keys[pygame.K_d] or pressed_keys[pygame.K_RIGHT]: | |
self.move.x += self.speed | |
# bubble | |
#if self.move.x != 0 or self.move.y != 0: | |
# if random.random() < 0.25: | |
# # left top corner | |
# Bubble(pos=pygame.Vector2(self.pos.x - 50, self.pos.y-50), | |
# #move=pygame.Vector2(-self.speed * random.uniform(0.5, 1.5), 0), | |
# move = pygame.Vector2(-self.move.x, -self.move.y), | |
# radius_start=1, | |
# radius_end=5, | |
# radius_plusminus=5, | |
# color_start=(255, 255, 0), # gelb | |
# color_end=(255, 0, 0), # rot | |
# ) | |
# # left bottom corner | |
# Bubble(pos=pygame.Vector2(self.pos.x - 50, self.pos.y + 50), | |
# # move=pygame.Vector2(-self.speed * random.uniform(0.5, 1.5), 0), | |
# move=pygame.Vector2(-self.move.x, -self.move.y), | |
# radius_start=1, | |
# radius_end=5, | |
# radius_plusminus=5, | |
# color_start=(255, 255, 0), # gelb | |
# color_end=(255, 0, 0), # rot | |
# ) | |
# bewegung | |
self.pos += self.move * dt | |
self.rect.center = self.pos | |
# --- wounds --- | |
for w_pos in self.wounds: | |
c = (255, random.randint(0,255),0) # red or yellow | |
if random.random() < 3*1/Game.FPS: | |
Bubble(pos=(self.pos.x + w_pos[0], self.pos.y+w_pos[1]), | |
move=pygame.Vector2(Game.scrollspeed*5*random.uniform(0.9,1.1),random.uniform(-0.2,0.2)), | |
color_start=c, | |
color_end = (32,32,32), | |
alpha_end = 128, | |
radius_end=random.randint(5,10)) | |
# hp | |
if self.hitpoints <= 0: | |
self.kill() | |
class Plasma(pygame.sprite.DirtySprite): | |
x_speed = -80 | |
def __init__(self, | |
shooter, | |
): | |
pygame.sprite.DirtySprite.__init__(self, | |
Game.allgroup, | |
Game.plasmagroup) | |
self.image = self.create_image() | |
self.rect = self.image.get_rect() | |
self.pos = pygame.Vector2(shooter.pos.x, | |
shooter.pos.y) | |
self.rect.center = self.pos | |
self.x_speed += random.randint(-20,20) | |
def update(self, dt): | |
self.pos.x += self.x_speed * dt | |
self.image = self.create_image() | |
self.rect.center = self.pos | |
if self.pos.x < 0: | |
self.kill() | |
def create_image(self): | |
# green pulsating balls | |
image = pygame.Surface((100,50)) | |
for n,x in enumerate((20,30,40,50)): | |
c = (0,random.randint(128,255),0) | |
if n == 0: | |
r = random.randint(7,11) | |
elif n == 1: | |
r = random.randint(6,10) | |
elif n == 2: | |
r = random.randint(5,9) | |
elif n == 3: | |
r = random.randint(4,8) | |
pygame.draw.circle(image,c,(x,25),r) | |
image.set_colorkey((0,0,0)) | |
image = image.convert_alpha() | |
return image | |
class Laser(pygame.sprite.DirtySprite): | |
x_speed = 250 | |
def __init__(self, | |
shooter, | |
move_direction=pygame.Vector2(2,0), | |
color=(255, 0, 0), | |
speed_plusminus = 25, | |
): | |
pygame.sprite.DirtySprite.__init__(self, | |
Game.allgroup, | |
Game.lasergroup) | |
self.speed_plusminus = speed_plusminus | |
self.pos = pygame.Vector2(shooter.pos.x+50,shooter.pos.y) | |
move = move_direction.normalize() | |
self.move = move * (self.x_speed + random.randint(-self.speed_plusminus, self.speed_plusminus)) | |
self.color = color | |
self.image = self.create_image() | |
# rotate image ? | |
self.rect = self.image.get_rect() | |
self.rect.center = self.pos | |
def create_image(self): | |
image = pygame.Surface((10,10)) | |
#image.fill(self.color) | |
pygame.draw.rect(image, self.color,((0,6),(10,8))) | |
image.set_colorkey((0,0,0)) | |
image = image.convert_alpha() | |
image = pygame.transform.rotate(image, self.move.angle_to(pygame.Vector2(1,0))) | |
return image | |
def update(self,dt): | |
self.pos += self.move * dt | |
self.rect.center = self.pos | |
if self.pos.x > Game.W or self.pos.x < 0 or self.pos.y > Game.H or self.pos.y < 0: | |
self.kill() | |
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,) | |
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 > Game.W or self.pos.y > Game.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 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 > Game.W: | |
self.pos.x = Game.W | |
self.move.x *= -1 | |
if self.pos.y < 0: | |
self.pos.y = 0 | |
self.move.y *= -1 | |
if self.pos.y > Game.H: | |
self.pos.y = Game.H | |
self.move.y *= -1 | |
if self.anchor == "center": | |
self.rect.center = self.pos | |
elif self.anchor == "topleft": | |
self.rect.topleft = self.pos | |
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() * Game.W | |
y = random.random() * Game.H | |
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() | |
def create_background(): | |
Game.background = pygame.Surface((Game.W, Game.H)) | |
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("Shooter", # text | |
True, # antialias | |
(32, 32, 32), # color | |
) | |
w, h = textsurface.get_rect().size | |
Game.background.blit(textsurface, | |
(Game.W / 2 - w / 2, Game.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, (Game.W - w - 10, Game.H - h - 5)) | |
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((Game.W, Game.H)) | |
Game.clock = pygame.time.Clock() | |
running = True | |
#dt = 0 | |
# sterne malen | |
create_background() | |
# sprites | |
Game.player1 = Player(pos=pygame.Vector2(200,400)) | |
#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 | |
Game.screen.blit(Game.background, (0,0)) | |
pygame.display.flip() # once! | |
while running: | |
dt = Game.clock.tick(Game.FPS) / 1000 | |
pygame.display.set_caption(f"player one hp: {Game.player1.hitpoints} fps: {Game.clock.get_fps():.2f} ") | |
#pygame.display.flip() | |
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 | |
# --- cheats ---- | |
if event.type == pygame.KEYDOWN and event.key == pygame.K_1: | |
Game.player1.laser_version = 1 | |
if event.type == pygame.KEYDOWN and event.key == pygame.K_2: | |
Game.player1.laser_version = 2 | |
if event.type == pygame.KEYDOWN and event.key == pygame.K_3: | |
Game.player1.laser_version = 3 | |
if event.type == pygame.KEYDOWN and event.key == pygame.K_4: | |
Game.player1.laser_version = 4 | |
if event.type == pygame.KEYDOWN and event.key == pygame.K_5: | |
Game.player1.laser_version = 5 | |
pressed_keys = pygame.key.get_pressed() | |
# stars bewegen | |
for star in Game.stargroup: | |
star.pos.x += Game.scrollspeed * star.pos.z | |
if star.pos.x < 0: | |
star.pos.y = random.random() * Game.H | |
star.pos.x = (1+random.random()) * Game.W | |
#star.pos.y += Game.player1.move.y * star.pos.z | |
star.rect.center = pygame.Vector2(star.pos.x, star.pos.y) # - Game.screenpos | |
# enemy1 spawn | |
if random.random() < 1/Game.FPS /10 : | |
for _ in range(5): | |
Enemy1(pos=pygame.Vector2(Game.W + 10, | |
random.randint(10, Game.H-10))) | |
# enemy2 spawn | |
if random.random() < 1/Game.FPS / 5: | |
yf = random.randint(-100,100) | |
y = random.randint(50, Game.H - 50) | |
dx = random.randint(15,25) | |
delta_age = random.uniform(0.1, 0.3) | |
dx = random.uniform(10,30) * -1 | |
for x in range(10): | |
Enemy2(pygame.Vector2(Game.W * 1.5 + dx*x, y), | |
dx, | |
yf, | |
x * delta_age) | |
# enemy bewegen | |
for e in Game.enemygroup: | |
e.update(dt) | |
# plasma bewegen | |
for p in Game.plasmagroup: | |
p.update(dt) | |
# player bewegen | |
for p in Game.playergroup: | |
p.update(dt) | |
# fire Laser | |
if pressed_keys[pygame.K_SPACE]: | |
Game.player1.fire_laser() | |
# collide player and enemy | |
for player in Game.playergroup: | |
crashgroup = pygame.sprite.spritecollide(player, Game.enemygroup, False) | |
for enemy in crashgroup: | |
enemy.kill() | |
player.hitpoints -= 1 | |
# collide laser and enemy | |
for beam in Game.lasergroup: | |
crashgroup = pygame.sprite.spritecollide(beam, Game.enemygroup, False) | |
for enemy in crashgroup: | |
for _ in range(20): | |
m = pygame.Vector2(1 + random.random() * 40, 0) | |
m.rotate_ip(random.random() * 360) | |
Bubble(enemy.pos, m,color_start=enemy.color, color_end=(0,0,255 )) | |
enemy.kill() | |
beam.kill() | |
# sprites zeichnen | |
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 over: | |
if len(Game.playergroup) == 0: | |
running = False | |
pygame.quit() | |
if __name__ == "__main__": | |
setup() | |
mainloop() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment