#! /usr/bin/env python # The above line makes this executible in unix systems # Asteroids Infinity # Inspired by the classic Atari arcade game "Asteroids" # Copyright (C) 2009 Ben Whittaker # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . import pygame import random import math import os import sys import string from pygame.locals import * pygame.init() #joystick or gamepad init pygame.joystick.init() print ("Joystics: ", pygame.joystick.get_count()) js = pygame.joystick.Joystick(0) js.init() try: os.chdir(sys.argv[0][:sys.argv[0].rindex("AsteroidsInfinity.py")]) except: pass screensize = (640, 480) playarea = (700, 540) viewpoint = [350, 270] forecolor = (255, 255, 255) backcolor = (0, 0, 0) Objects = pygame.sprite.Group() ProtoObjs = pygame.sprite.Group() Saucers = pygame.sprite.Group() Asteroids = pygame.sprite.Group() Particles = pygame.sprite.Group() Collidable = pygame.sprite.Group() Bullets = pygame.sprite.Group() ShipGroup = pygame.sprite.GroupSingle() TextGroup = pygame.sprite.RenderUpdates() def loadsounds(): global explosion_sound global shot_sound global thrust_sound global beat1_sound global beat2_sound global life_sound global saucer_sound explosion_sound = Sound("sounds/explosion.wav") shot_sound = Sound("sounds/shot.wav") thrust_sound = Sound("sounds/thrust.wav") beat1_sound = Sound("sounds/beat1.wav") beat2_sound = Sound("sounds/beat2.wav") life_sound = Sound("sounds/life.wav") saucer_sound = Sound("sounds/saucer.wav") if pygame.mixer.get_init() <> None: pygame.mixer.set_reserved(2) # reserves channels for the thrust sound and the saucer sound pygame.mixer.Channel(1).set_volume(0.5) def set_volume(volume): explosion_sound.set_volume(volume) shot_sound.set_volume(volume) thrust_sound.set_volume(volume) beat1_sound.set_volume(volume) beat2_sound.set_volume(volume) life_sound.set_volume(volume) saucer_sound.set_volume(volume) def get_highscores(): if os.access("highscores.txt", os.F_OK) == True: try: scores_file = open("highscores.txt","r") highscores = [] lines = scores_file.readlines() scores_file.close() for line in lines: line = line.strip() line = line.split(":") if len(line) < 2: break highscores += [(int(line[0]), line[1])] while len(highscores) < 10: highscores += [(0,"")] return highscores except: print "Could not open highscores and/or could not parse highscores." print "Using default highscores." highscores = [ (8128, "PERFECT"), (6173, "PRIME"), (4540, "11BC"), (3798, "RAND"), (3141, "PI"), (2718, "E"), (1764, "LIFE^2"), (1024, "10^1010"), (525, "BAR"), (325, "FOO") ] return highscores def save_highscores(highscores): scores_file = open("highscores.txt","w") for score in highscores: scores_file.write(str(score[0]) + ":" + score[1] + "\n") scores_file.close() def get_controls(): controls = {"left":pygame.K_LEFT, "right":pygame.K_RIGHT, "up":pygame.K_UP, "down":pygame.K_DOWN, "shoot":pygame.K_SPACE, "shield":pygame.K_LCTRL} if os.access("controls.txt", os.F_OK) == True: controls_file = open("controls.txt", "r") for a in ("up", "down", "left", "right", "shoot", "shield"): line = controls_file.readline()[:-1] if line.isdigit() == True: controls[a] = int(line) controls_file.close() return controls def save_controls(controls): controls_file = open("controls.txt","w") for a in ("up", "down", "left", "right", "shoot", "shield"): controls_file.write(str(controls[a]) + "\n") controls_file.close() class DummySound(): def __init__(self, filename): pass def play(self, loops=0, maxtime=0, fade_ms=0): pass def stop(self): pass def fadeout(self, time): pass def set_volume(self, value): pass def get_volume(self): return 1 def get_num_channels(self): return 0 def get_length(self): return 0 def Sound(filename): if pygame.mixer.get_init() == None: return DummySound(filename) else: return pygame.mixer.Sound(filename) class DummyChannel(): def __init__(self, ID): pass def play(self, Sound, loops=0, maxtime=0, fade_ms=0): pass def stop(self): pass def set_volume(self, value): pass def get_volume(self): return 1 def get_busy(self): return False def queue(self, Sound): pass def Channel(ID): if pygame.mixer.get_init() == None: return DummyChannel(ID) else: return pygame.mixer.Channel(ID) class Text(pygame.sprite.Sprite): # A class of objects for displaying text def __init__(self, text, font, pos, align = "left"): pygame.sprite.Sprite.__init__(self, TextGroup) self.align = align # short for alignment, and can be "left", "right", or "center" self.pos = pos self.font = font self.change(text) def change(self, text): self.image = self.font.render(text, 1, (forecolor)) # make the text graphic for a in range(2): self.image.blit(self.image, (0, 0)) # copy the text graphic onto itself to make it brighter self.text = text width = self.image.get_width() height = self.image.get_height() if self.align == "left": self.rect = pygame.Rect(self.pos[0], self.pos[1], width, height) elif self.align == "center": self.rect = pygame.Rect(self.pos[0] - width / 2, self.pos[1], width, height) else: self.rect = pygame.Rect(self.pos[0] - width, self.pos[1], width, height) def wrap(num, start, end): while num < start: num += end - start while num > end: num -= end - start return num def explosion(pos, rel_speed, particles, added_speed = 200): for a in range(0, particles): angle = random.uniform(0, math.pi * 2) speed = random.uniform(0, added_speed) Particle(pos, (rel_speed[0] + math.sin(angle) * speed, rel_speed[1] + math.cos(angle) * speed)) explosion_sound.play() class Obj(pygame.sprite.Sprite): angle = 0 spin = 0 def __init__(self, pos, speed, groups = []): pygame.sprite.Sprite.__init__(self, groups + [Objects]) self.pos = list(pos) self.speed = list(speed) self.set_pos_screen() #self.image = image #self.image.set_colorkey((66, 66, 66)) #self.rect = pygame.Rect((self.pos[0] - self.image.get_width() / 2, self.pos[1] - self.image.get_height() / 2), image.get_size()) def update(self): self.angle += self.spin / fps self.pos[0] += self.speed[0] / fps self.pos[1] += self.speed[1] / fps if self.pos[0] > playarea[0]: self.pos[0] -= playarea[0] elif self.pos[0] < 0: self.pos[0] += playarea[0] if self.pos[1] > playarea[1]: self.pos[1] -= playarea[1] elif self.pos[1] < 0: self.pos[1] += playarea[1] self.set_pos_screen() #self.pos_screen = (self.rect.x + self.rect.w / 2, self.rect.y + self.rect.h / 2) ## def render(self): ## render_pos = (self.image.get_height() / 2, self.image.get_width() / 2) ## temp_points = [] ## for point in self.image_points: ## temp_points.append((math.sin(point[0] + self.angle) * point[1] + render_pos[0], math.cos(point[0] + self.angle) * point[1] + render_pos[1])) ## self.image.fill((66, 66, 66)) ## pygame.draw.polygon(self.image, (0, 0, 0), temp_points) ## pygame.draw.aalines(self.image, (255, 255, 255), 1, temp_points) ## ## #pygame.draw.circle(self.image, (100, 100, 100), render_pos, self.radius, 1) def set_pos_screen(self): self.pos_screen = [self.pos[0] - viewpoint[0], self.pos[1] - viewpoint[1]] max_radius_x = (playarea[0] - screensize[0]) / 2 max_radius_y = (playarea[1] - screensize[1]) / 2 #if self.pos_screen[0] - max_radius_x > screensize[0]: # self.pos_screen[0] -= playarea[0] #elif self.pos_screen[0] + max_radius_x < 0: # self.pos_screen[0] += playarea[0] #if self.pos_screen[1] - max_radius_y > screensize[1]: # self.pos_screen[1] -= playarea[1] #elif self.pos_screen[1] + max_radius_y < 0: # self.pos_screen[1] += playarea[1] self.pos_screen[0] = wrap(self.pos_screen[0], -max_radius_x, screensize[0] + max_radius_x) self.pos_screen[1] = wrap(self.pos_screen[1], -max_radius_y, screensize[1] + max_radius_y) def draw(self, surface): render_pos = (self.pos_screen[0], self.pos_screen[1]) dirtyrects = [] for points_list in self.image_points: color = forecolor if len(points_list[0]) > 2: color = points_list[0] points_list = points_list[1:] temp_points = [] for point in points_list: temp_points.append((math.sin(point[0] + self.angle) * point[1] + render_pos[0], math.cos(point[0] + self.angle) * point[1] + render_pos[1])) pygame.draw.polygon(surface, backcolor, temp_points) dirtyrects.append(pygame.draw.aalines(surface, color, 1, temp_points).inflate(2, 2)) #pygame.draw.circle(surface, (100, 100, 100), render_pos, self.radius, 1) return dirtyrects class Asteroid(Obj): def __init__(self, pos, speed, size, groups = []): self.size = size self.radius = 3 * pow(2, size) self.spin = random.uniform(math.pi * -2, math.pi * -2) #image = pygame.Surface((self.radius * 4, self.radius * 4)) self.image_points = [[]] for a in range(0, 10): angle = a * math.pi / 5 + random.uniform(0, math.pi / 5) dist = random.uniform(self.radius * 0.7, self.radius * 1.4) self.image_points[0].append((angle, dist)) Obj.__init__(self, pos, speed, groups + [Asteroids, Collidable]) self.collision_type = "hard" #self.render() def collide(self, victim): global score if victim.collision_type == "Explosive": #for a in range(50): # angle = random.uniform(0, math.pi * 2) # speed = random.uniform(0, 10) # Particle(self.pos, (self.speed[0] + math.sin(angle) * speed, self.speed[1] + math.cos(angle) * speed)) explosion(self.pos, self.speed, 50) for a in range(2): if self.size > 1: angle = random.uniform(0, math.pi * 2) speed = random.uniform(0, 100) Asteroid(self.pos, (self.speed[0] + math.sin(angle) * speed, self.speed[1] + math.cos(angle) * speed), self.size - 1) raise_score(25 * pow(2, 3 - self.size), victim) if random.randint(0, 50) == 0: if random.randint(1, 3) == 1: SmallSaucer((random.randint(0, screensize[0]), random.randint(0, screensize[1]))) else: BigSaucer((random.randint(0, screensize[0]), random.randint(0, screensize[1]))) self.kill() class Ship(Obj): def __init__(self, pos, speed, radius, movement_keys, groups = []): self.radius = radius self.movement_keys = movement_keys #image = pygame.Surface((self.radius * 4, self.radius * 4)) ## self.image_points = [[ ## (0, radius * 1.3), ## (math.pi / 3, radius), ## (math.pi * 5 / 6, radius * 1.2), ## (math.pi, radius / 2), ## (math.pi * 7 / 6, radius * 1.2), ## (math.pi * 5 / 3, radius) ## ]] self.normal_points = [[ (0, radius * 1.3), (math.pi / 2, radius / 2), (math.pi / 2, radius * 1.2), (math.pi * 5 / 6, radius), (math.pi * 7 / 6, radius), (math.pi * 3 / 2, radius * 1.2), (math.pi * 3 / 2, radius / 2) ]] self.shield_points = [(math.pi / 10 * a, self.radius * 1.5) for a in range(20)] self.image_points = self.normal_points Obj.__init__(self, pos, speed, groups + [Collidable]) self.collision_type = "Explosive" #self.render() self.gunheat = 0 self.reloading = 0 self.bullets = pygame.sprite.Group() self.activate_shield(2) self.shield = 5 def control(self, keys): self.thrustvolume = 0 self.spin = 0 factor = 1 if keys[self.movement_keys["left"]] == 1: self.spin += factor*math.pi if random.random() < 20 / fps: self.exaust(math.pi, (math.pi * 1 / 2, self.radius * 1.2), 1) self.thrustvolume = 0.25 if keys[self.movement_keys["right"]] == 1: self.spin -= factor*math.pi if random.random() < 20 / fps: self.exaust(math.pi, (math.pi * 3 / 2, self.radius * 1.2), 1) self.thrustvolume = 0.25 if keys[self.movement_keys["down"]] == 1: self.speed[0] -= math.sin(self.angle) * 400 / 3 / fps self.speed[1] -= math.cos(self.angle) * 400 / 3 / fps if random.random() < 20 / fps: self.exaust(math.pi, (math.pi * 1 / 2, self.radius * 1.2), 1) self.exaust(math.pi, (math.pi * 3 / 2, self.radius * 1.2), 1) self.thrustvolume = 0.75 if keys[self.movement_keys["up"]] == 1: self.speed[0] += factor*math.sin(self.angle) * 800 / 3 / fps self.speed[1] += factor*math.cos(self.angle) * 800 / 3 / fps if random.random() < 60 / fps: self.exaust(0, (0, -self.radius / 2), 1) self.thrustvolume = 1 Channel(0).set_volume(self.thrustvolume) Channel(0).queue(thrust_sound) if keys[self.movement_keys["shoot"]] == 1 and self.gunheat < 40 and self.reloading <= 0: Bullet(self.pos, (self.speed[0] + math.sin(self.angle) * 400, self.speed[1] + math.cos(self.angle) * 400), self.angle, 4, creator = self, groups = [self.bullets]) self.gunheat += 10 self.reloading += 1 if self.reloading > 0: self.reloading -= 20.0 / fps if self.gunheat > 0: self.gunheat -= 20.0 / fps if self.start_shield > 0: self.start_shield -= 1.0 / fps elif self.collision_type == "Hard": self.collision_type = "Explosive" self.image_points = self.normal_points if keys[self.movement_keys["shield"]] == 1 and self.shield > 0: if self.shield > 5: self.shield = 5.0 self.collision_type = "Hard" s = self.shield / 5 self.image_points = [[[int(s * forecolor[n] + (1 - s) * backcolor[n]) for n in (0,1,2)]] + self.shield_points] + self.normal_points self.shield -= 2.5 / fps elif self.shield < 5: self.shield += 0.5 / fps self.collision_type = "Explosive" self.image_points = self.normal_points def exaust(self, rel_angle, rel_pos, amount): for a in range(amount): angle = self.angle + rel_angle + random.uniform(math.pi / -12, math.pi / 12) speed = random.uniform(100, 200) pos = [self.pos[0] + math.sin(rel_pos[0] + self.angle) * rel_pos[1], self.pos[1] + math.cos(rel_pos[0] + self.angle) * rel_pos[1]] Particle(pos, (self.speed[0] + math.sin(angle) * -speed, self.speed[1] + math.cos(angle) * -speed)) def activate_shield(self, timer): self.start_shield = timer self.collision_type = "Hard" self.image_points = [self.shield_points] + self.normal_points def collide(self, victim): if victim not in self.bullets.sprites() and self.collision_type == "Explosive": for a in range(0, 7): angle = random.uniform(0, math.pi * 2) speed = random.uniform(0, 200) Stick(self.pos, (self.speed[0] + math.sin(angle) * speed, self.speed[1] + math.cos(angle) * speed), 7) explosion(self.pos, self.speed, 25) self.kill() class Saucer(Obj): def __init__(self, pos, radius, groups = []): Obj.__init__(self, pos, [0, 0], groups + [Particles, ProtoObjs, Saucers]) self.remove(Objects) self.real_radius = radius self.radius = 0.5 self.make_image_points(self.radius) self.collision_type = "Explosive" angle = random.uniform(0, math.pi * 2) speed = random.randint(40, 160) self.speed[0] += math.sin(angle) * speed self.speed[1] += math.cos(angle) * speed self.bullets = pygame.sprite.Group() if Saucers.sprites() == [self]: #print 1 Channel(1).play(saucer_sound, -1) #else: #print 0 def update(self): global viewpoint if self.radius < self.real_radius: self.radius *= 7**(1 / fps) self.make_image_points(self.radius) else: self.radius = self.real_radius self.remove(ProtoObjs) self.add(Objects) self.add(Collidable) if random.random() > 0.35**(1/fps): self.speed = list(viewpointspeed) angle = random.uniform(0, math.pi * 2) speed = random.randint(40, 160) self.speed[0] += math.sin(angle) * speed self.speed[1] += math.cos(angle) * speed # The following commented out chunk off code was an attempt to make saucers avoid asteroids. It didn't work. ## for a in range(10): ## self.speed = list(viewpointspeed) ## angle = random.uniform(0, math.pi * 2) ## speed = random.randint(40, 160) ## self.speed[0] += math.sin(angle) * speed ## self.speed[1] += math.cos(angle) * speed ## danger = 0 ## for asteroid in Asteroids.sprites(): ## rel_speed = (asteroid.speed[0] - self.speed[0], asteroid.speed[1] - self.speed[1]) ## rel_pos = (wrap(asteroid.pos[0] - self.pos[0], -playarea[0]/2, playarea[0]/2), wrap(asteroid.pos[1] - self.pos[1], -playarea[1]/2, playarea[1]/2)) ## rel_angle = math.atan2(rel_pos[0], rel_pos[1]) - 180 ## clearance = math.atan2(asteroid.radius + self.radius, math.hypot(rel_pos[0], rel_pos[1])) ## #print clearance ## ras = math.atan2(rel_speed[0], rel_speed[1]) ## #print ras ## #angle = rel_angle ## #speed = 200 ## #Stick(self.pos, (self.speed[0] + math.sin(angle) * speed, self.speed[1] + math.cos(angle) * speed), 5) ## if wrap(rel_angle - clearance, ras - math.pi, ras + math.pi) < ras < wrap(rel_angle + clearance, ras - math.pi, ras + math.pi): ## danger = 1 ## #print "not there" ## if a == 9: ## print "Aaaaaaaa!!!!!" ## break ## if danger == 0: ## break Obj.update(self) def collide(self, victim): if victim not in self.bullets.sprites(): explosion(self.pos, self.speed, 25) for a in range(0, 10): angle = random.uniform(0, math.pi * 2) speed = random.uniform(0, 200) Stick(self.pos, (self.speed[0] + math.sin(angle) * speed, self.speed[1] + math.cos(angle) * speed), self.radius / 2) self.kill() def make_image_points(self, r): self.image_points = [[ (math.pi / 2, r * 4 / 3), (math.pi / 4, r * 3 / 4), (-math.pi / 4, r * 3 / 4), (-math.pi / 2, r * 4 / 3) ], [ (math.pi * 3 / 4, r * 3 / 4), (math.pi / 2, r * 4 / 3), (-math.pi / 2, r * 4 / 3), (-math.pi * 3 / 4, r * 3 / 4) ], [ (math.pi * 11 / 12, r), (math.pi * 3 / 4, r * 3 / 4), (-math.pi * 3 / 4, r * 3 / 4), (-math.pi * 11 / 12, r) ]] def kill(self): pygame.sprite.Sprite.kill(self) if Saucers.sprites() == []: Channel(1).stop() class BigSaucer(Saucer): def __init__(self, pos): Saucer.__init__(self, pos, 15) def update(self): Saucer.update(self) if random.random() > 0.6**(1/fps) and Objects in self.groups(): angle = random.uniform(0, math.pi * 2) speed = (self.speed[0] + math.sin(angle) * 400, self.speed[1] + math.cos(angle) * 400) Bullet([self.pos[0], self.pos[1]], speed, angle, 4, creator = self, groups = [self.bullets]) def collide(self, victim): global score Saucer.collide(self, victim) raise_score(250, victim) class SmallSaucer(Saucer): def __init__(self, pos): Saucer.__init__(self, pos, 10) def update(self): Saucer.update(self) if ShipGroup.sprite <> None: target = ShipGroup.sprite elif Asteroids.sprites() <> []: target = Asteroids.sprites()[0] if random.random() > 0.6**(1/fps) and Objects in self.groups(): angle = math.atan2(target.pos_screen[0] - self.pos_screen[0], target.pos_screen[1] - self.pos_screen[1]) + random.uniform(math.pi / -4, math.pi / 4) speed = (self.speed[0] + math.sin(angle) * 400, self.speed[1] + math.cos(angle) * 400) Bullet([self.pos[0], self.pos[1]], speed, angle, 4, creator = self, groups = [self.bullets]) def collide(self, victim): global score Saucer.collide(self, victim) raise_score(1000, victim) class Particle(Obj): def __init__(self, pos, speed, groups = []): #image = pygame.Surface((1, 1)) #image.fill((200, 200, 200)) Obj.__init__(self, pos, speed, groups + [Particles]) def update(self): if random.random() > 0.35**(1/fps): self.kill() Obj.update(self) def draw(self, surface): pos_screen_int = [int(self.pos_screen[0]), int(self.pos_screen[1])] surface.set_at(pos_screen_int, forecolor) return [pygame.Rect(pos_screen_int, (1, 1))] class Stick(Obj): def __init__(self, pos, speed, radius, groups = []): self.radius = radius #image = pygame.Surface((radius * 2, radius * 2)) self.spin = random.uniform(math.pi * -2, math.pi * 2) self.image_points = [[(0, 0), (0, radius), (math.pi, radius)]] Obj.__init__(self, pos, speed, groups + [Particles]) def update(self): if random.random() > 0.50**(1/fps): self.kill () Obj.update(self) class Bullet(Obj): def __init__(self, pos, speed, angle, radius, creator = None, groups = []): self.creator = creator self.radius = radius self.angle = angle #image = pygame.Surface((radius * 2, radius * 2)) self.image_points = [[(0, radius), (math.pi * 8 / 9, radius), (math.pi * 10 / 9, radius)]] self.collision_type = "Explosive" Obj.__init__(self, pos, speed, groups + [Collidable, Bullets]) #self.render() self.lifetime = 1 shot_sound.play() def update(self): self.lifetime -= 1.0 / fps if self.lifetime <= 0: self.kill() Obj.update(self) def collide(self, victim): if victim <> self.creator: if not (Bullets in victim.groups() and victim.creator == self.creator): explosion(self.pos, [(self.speed[a] + victim.speed[a]) / 2 for a in range(2)], 25, 100) self.kill() def raise_score(amount, attacker = None): global score if attacker == None: score += amount elif attacker == ShipGroup.sprite: score += amount elif attacker.__class__ == Bullet and attacker.creator == ShipGroup.sprite: score += amount def main(): global viewpoint global viewpointspeed global score global fps font = pygame.font.Font("font/Vectorb.ttf", 20) small_font = pygame.font.Font("font/Vectorb.ttf", 10) large_font = pygame.font.Font("font/Vectorb.ttf", 40) loadsounds() screen = pygame.display.set_mode(screensize) screen.fill(backcolor) pygame.display.flip() fullscreen = 0 pygame.display.set_caption("Asteroids Infinity") volume = 100 clock = pygame.time.Clock() highscores = get_highscores() controls = get_controls() # Asteroid([random.randint(0, 1000), random.randint(0, 1000)], (random.randint(-5, 5), random.randint(-5, 5)), 3) #Ship([playarea[0] / 2, playarea[1] / 2], [0, 0], 10, {"left":pygame.K_LEFT, "right":pygame.K_RIGHT, "up":pygame.K_UP, "down":pygame.K_DOWN, "shoot":pygame.K_SPACE, "shield":pygame.K_LCTRL}, groups = [ShipGroup]) viewpointspeed = [0, 0] score = 0 lives = 0 #lives_text = font.render("Lives : " + str(lives), 1, (255, 255, 255)) lives_text = Text("Lives : " + str(lives), font, (20, 20)) level_text = Text("Level N/A", font, (screensize[0] / 2, 20), align = "center") score_text = Text("", font, (screensize[0] - 20, 20), align = "right") fps_counter = 0 respawn_time = 2 running = 1 for a in range(random.randrange(1, 10)): Asteroid((random.randint(0, playarea[0]), random.randint(0, playarea[1])), (random.randint(-100, 100), random.randint(-100, 100)), random.randint(1, 3)) lastbeat = pygame.time.get_ticks() beattype = 1 mode = "menustart" olddirtyrects = [] #for joystick moves k_left = 0 k_right = 0 k_up = 0 k_down = 0 k_shoot = 0 k_shield = 0 while running == 1: fps = 1000.0 / clock.tick(100) if fps_counter == 1: fps_text.change("FPS : " + str(clock.get_fps())) keys = pygame.key.get_pressed() #if keys[pygame.K_ESCAPE] == True: # break events = pygame.event.get() lst = list(keys) #A if (js.get_button(1) == 1): lst[controls["shoot"]]= 1 k_shoot = 1 else: k_shoot = 0 #B if (js.get_button(0) == 1): lst[controls["shield"]] = 1 k_shield = 1 #left if (js.get_axis(0) < 0 ): lst[controls["left"]] = 1 k_left = 1 #right if (js.get_axis(0) > 0 ): lst[controls["right"]] = 1 k_right = 1 #up if (js.get_axis(1) < 0 ): lst[controls["up"]] = 1 #down if (js.get_axis(1) > 0 ): lst[controls["down"]] = 1 keys = tuple(lst) for event in events: if event.type == pygame.QUIT: running = 0 elif event.type == JOYBUTTONDOWN: # Button A if (js.get_button(1) == 1): if mode == "menu": if selected == 0: for item in menu_items: item.kill() mode = "playstart" elif event.type == pygame.KEYDOWN: #print event.unicode if event.key == pygame.K_ESCAPE: if mode == "play": mode = "gameoverstart" elif mode == "menu": running = 0 elif mode == "controls" or mode == "setcontrol": for text in controls_text + menu_items: text.kill() mode = "optionsstart" elif mode <> "gameover": for text in menu_items: text.kill() if mode == "sethighscore": name_text.kill() mode = "menustart" if event.key == pygame.K_p and mode == "play": # Pause pause_text1 = Text("PAUSED", large_font, (screensize[0] / 2, screensize[1] / 2 - 65), align = "center") pause_text2 = Text("Press any key to continue", font, (screensize[0] / 2, screensize[1] / 2 + 20), align = "center") TextGroup.draw(screen) pygame.display.flip() while 1: event = pygame.event.wait() if event.type == pygame.KEYDOWN: pause_text1.kill() pause_text2.kill() break if event.type == pygame.QUIT: running = 0 break clock.tick() if mode == "menu" or mode == "options" or mode == "controls": if event.key == pygame.K_UP or event.key == pygame.K_DOWN: menu_items[selected].change(menu_items[selected].text[1:-1]) if event.key == pygame.K_UP: if selected == 0: selected = len(menu_items) - 1 else: selected -= 1 else: if selected == len(menu_items) - 1: selected = 0 else: selected += 1 menu_items[selected].change("<" + menu_items[selected].text + ">") if mode == "menu": if event.key == pygame.K_RETURN: if selected == 0: for item in menu_items: item.kill() mode = "playstart" elif selected == 1: for item in menu_items: item.kill() mode = "highscoresstart" elif selected == 2: for item in menu_items: item.kill() mode = "optionsstart" elif selected == 3: running = 0 #title_text.kill() if mode == "options": if event.key == pygame.K_RETURN: if selected == 0: if fullscreen == 0: pygame.display.set_mode(screensize, pygame.FULLSCREEN) pygame.mouse.set_visible(False) screen.fill((backcolor)) pygame.display.flip() fullscreen = 1 menu_items[0].change("") else: pygame.display.set_mode(screensize) pygame.mouse.set_visible(True) screen.fill((backcolor)) pygame.display.flip() fullscreen = 0 menu_items[0].change("") elif selected == 2: if fps_counter == 0: fps_counter = 1 fps_text = Text("", small_font, (2, screensize[1] - 13)) menu_items[2].change("") else: fps_counter = 0 fps_text.kill() menu_items[2].change("") elif selected == 3: for item in menu_items: item.kill() mode = "controlsstart" elif selected == 4: for item in menu_items: item.kill() mode = "menustart" if selected == 1: if event.key == pygame.K_LEFT and volume > 0: volume -= 10 set_volume(volume / 100.0) menu_items[1].change("") elif event.key == pygame.K_RIGHT and volume < 100: volume += 10 set_volume(volume / 100.0) menu_items[1].change("") if mode == "controls": if event.key == pygame.K_RETURN: if selected < 6: menu_items[selected].change("< >") mode = "setcontrol" if selected == 6: for text in controls_text + menu_items: text.kill() mode = "optionsstart" elif mode == "setcontrol": menu_items[selected].change("<" + pygame.key.name(event.key) + ">") if selected == 0: controls["up"] = event.key elif selected == 1: controls["down"] = event.key elif selected == 2: controls["left"] = event.key elif selected == 3: controls["right"] = event.key elif selected == 4: controls["shoot"] = event.key elif selected == 5: controls["shield"] = event.key save_controls(controls) mode = "controls" if mode == "sethighscore": if event.unicode in string.printable[:95] and len(name) < 10: name += event.unicode name_text.change(name + "_") elif event.key == pygame.K_BACKSPACE: name = name[:-1] name_text.change(name + "_") elif event.key == pygame.K_RETURN: highscores += [(score, name.upper())] highscores.sort(reverse = True) highscores = highscores[:10] save_highscores(highscores) for text in menu_items: text.kill() name_text.kill() mode = "highscoresstart" if mode == "gameover": for text in gameover_text: text.kill() mode = "highscorecheck" if mode == "highscores": for text in menu_items: text.kill() mode = "menustart" if event.type == pygame.MOUSEBUTTONDOWN and event.pos == (0, 0): pygame.display.set_mode(screensize) pygame.mouse.set_visible(True) fullscreen = 0 if mode == "options": menu_items[0].change("") #pygame.event.pump() a = 0 if Asteroids.sprites() == []: if mode == "play": level += 1 for obj in Objects.sprites(): obj.speed[0] -= viewpointspeed[0] obj.speed[1] -= viewpointspeed[1] for a in range(level): Asteroid([random.randint(0, playarea[0]), random.randint(0, playarea[1])], (random.randint(-100, 100), random.randint(-100, 100)), 3) #level_text = font.render("Level " + str(level), 1, (255, 255, 255)) level_text.change("Level " + str(level)) if ShipGroup.sprite <> None: ShipGroup.sprite.activate_shield(2) viewpointspeed = [0, 0] else: for a in range(random.randrange(1, 10)): Asteroid((random.randint(0, playarea[0]), random.randint(0, playarea[1])), (random.randint(-100, 100), random.randint(-100, 100)), random.randint(1, 3)) viewpointspeed = [0, 0] while a < len(Collidable.sprites()): obj1 = Collidable.sprites()[a] pos1 = list(obj1.pos) for obj2 in Collidable.sprites()[a + 1:]: pos2 = list(obj2.pos) if pos1[0] - pos2[0] > playarea[0] / 2: pos1[0] -= playarea[0] if pos2[0] - pos1[0] > playarea[0] / 2: pos2[0] -= playarea[0] if pos1[1] - pos2[1] > playarea[1] / 2: pos1[1] -= playarea[1] if pos2[1] - pos1[1] > playarea[1] / 2: pos2[1] -= playarea[1] if math.hypot(pos1[0] - pos2[0], pos1[1] - pos2[1]) < obj1.radius + obj2.radius: obj1.collide(obj2) obj2.collide(obj1) if obj1.groups() == []: break a += 1 if mode == "menustart": #title_text = Text("ASTEROIDS INFINITY", large_font, (screensize[0] / 2, screensize[1] / 2 - 180), align = "center") menu_items = ( Text("", large_font, (screensize[0] / 2, screensize[1] / 2 - 80), align = "center"), Text("HIGHSCORES", large_font, (screensize[0] / 2, screensize[1] / 2), align = "center"), Text("OPTIONS", large_font, (screensize[0] / 2, screensize[1] / 2 + 80), align = "center"), Text("QUIT", large_font, (screensize[0] / 2, screensize[1] / 2 + 160), align = "center") ) selected = 0 mode = "menu" if mode == "optionsstart": if fullscreen == 0: item0 = "" else: item0 = "" item1 = "VOLUME: " + str(volume) + "%" if fps_counter == 0: item2 = "FPS COUNTER ON" else: item2 = "FPS COUNTER OFF" menu_items = ( Text(item0, large_font, (screensize[0] / 2, screensize[1] / 2 - 180), align = "center"), Text(item1, large_font, (screensize[0] / 2, screensize[1] / 2 - 100), align = "center"), Text(item2, large_font, (screensize[0] / 2, screensize[1] / 2 - 20), align = "center"), Text("CONTROLS", large_font, (screensize[0] / 2, screensize[1] / 2 + 60), align = "center"), Text("BACK", large_font, (screensize[0] / 2, screensize[1] / 2 + 140), align = "center") ) selected = 0 mode = "options" if mode == "controlsstart": controls_text = ( Text("UP: ", font, (screensize[0] / 2, screensize[1] / 2 - 140), align = "right"), Text("DOWN: ", font, (screensize[0] / 2, screensize[1] / 2 - 100), align = "right"), Text("LEFT: ", font, (screensize[0] / 2, screensize[1] / 2 - 60), align = "right"), Text("RIGHT: ", font, (screensize[0] / 2, screensize[1] / 2 - 20), align = "right"), Text("SHOOT: ", font, (screensize[0] / 2, screensize[1] / 2 + 20), align = "right"), Text("SHIELD: ", font, (screensize[0] / 2, screensize[1] / 2 + 60), align = "right") ) menu_items = ( Text("<" + pygame.key.name(controls["up"]) + ">", font, (screensize[0] / 2, screensize[1] / 2 - 140), align = "left"), Text(pygame.key.name(controls["down"]), font, (screensize[0] / 2, screensize[1] / 2 - 100), align = "left"), Text(pygame.key.name(controls["left"]), font, (screensize[0] / 2, screensize[1] / 2 - 60), align = "left"), Text(pygame.key.name(controls["right"]), font, (screensize[0] / 2, screensize[1] / 2 - 20), align = "left"), Text(pygame.key.name(controls["shoot"]), font, (screensize[0] / 2, screensize[1] / 2 + 20), align = "left"), Text(pygame.key.name(controls["shield"]), font, (screensize[0] / 2, screensize[1] / 2 + 60), align = "left"), Text("BACK", large_font, (screensize[0] / 2, screensize[1] / 2 + 100), align = "center") ) selected = 0 setting_key = 0 mode = "controls" if mode == "highscoresstart": menu_items = [Text("HIGHSCORES", large_font, (screensize[0] / 2, 40), align = "center")] a = -130 n = 1 for highscore in highscores: menu_items.append(Text(str(n) + ". ", font, (200, screensize[1] / 2 + a), align = "right")) menu_items.append(Text(highscore[1], font, (200, screensize[1] / 2 + a), align = "left")) menu_items.append(Text(str(highscore[0]), font, (screensize[0] - 150, screensize[1] / 2 + a), align = "right")) a += 30 n += 1 menu_items.append(Text("PRESS ANY KEY TO CONTINUE", font, (screensize[0] / 2, screensize[1] - 60), align = "center")) mode = "highscores" if mode == "highscorecheck": if score > highscores[-1][0]: menu_items = [] menu_items.append(Text("YOU SET A NEW HIGHSCORE WITH " + str(score) + " POINTS", font, (screensize[0] / 2, screensize[1] / 2 - 40), align = "center")) menu_items.append(Text("PLEASE ENTER YOUR NAME", font, (screensize[0] / 2, screensize[1] / 2), align = "center")) name_text = Text("_", font, (screensize[0] / 2, screensize[1] / 2 + 40), align = "center") name = "" mode = "sethighscore" else: mode = "highscoresstart" if mode == "playstart": for sprite in Collidable.sprites(): sprite.kill() Ship([random.randint(0, playarea[0]), random.randint(0, playarea[0])], [0, 0], 10, controls, groups = [ShipGroup]) viewpoint = [playarea[0] / 2 - screensize[0] /2, playarea[1] / 2 - screensize[1] /2] viewpointspeed = [0, 0] score = 0 lives = 4 lives_text.change("Lives : " + str(lives)) level = 0 next_life = 10000 mode = "play" if mode == "play": if score >= next_life: lives += 1 lives_text.change("Lives : " + str(lives)) life_sound.play() next_life += 10000 if ShipGroup.sprite <> None: ship = ShipGroup.sprite ship.control(keys) #viewpoint[0] = ship.pos[0] - screensize[0] / 2 + ship.speed[0] / fps #viewpoint[1] = ship.pos[1] - screensize[1] / 2 + ship.speed[1] / fps rel_x = wrap(viewpoint[0] - ship.pos[0], -playarea[0], 0) + screensize[0] / 2 rel_y = wrap(viewpoint[1] - ship.pos[1], -playarea[1], 0) + screensize[1] / 2 px = math.fabs(rel_x / (screensize[0] / 8)) if px > 1: px = 1.0 py = math.fabs(rel_y / (screensize[1] / 8)) if py > 1: py = 1.0 viewpointspeed[0] -= (viewpointspeed[0] - ship.speed[0]) * (1 - ((1-px)**(1 / fps))) viewpointspeed[1] -= (viewpointspeed[1] - ship.speed[1]) * (1 - ((1-py)**(1 / fps))) p = (1 - (0.1**(1 / fps))) viewpoint[0] += -rel_x * p viewpoint[1] += -rel_y * p viewpoint[0] = wrap(viewpoint[0], 0, playarea[0]) viewpoint[1] = wrap(viewpoint[1], 0, playarea[1]) #if not -screensize[0] / 4 < rel_x < screensize[0] / 4: # viewpointspeed[0] = ship.speed[0] #if not -screensize[1] / 4 < rel_y < screensize[1] / 4: # viewpointspeed[1] = ship.speed[1] elif lives == 0: mode = "gameoverstart" elif respawn_time <= 0: Ship([random.randint(0, playarea[0]), random.randint(0, playarea[1])], [0, 0], 10, controls, groups = [ShipGroup]) lives -= 1 #lives_text = font.render("Lives : " + str(lives), 1, (255, 255, 255)) lives_text.change("Lives : " + str(lives)) respawn_time = 2 else: respawn_time -= 1.0 / fps else: if random.random() > 0.98**(1/fps): if random.randint(1, 3) == 1: SmallSaucer((random.randint(0, screensize[0]), random.randint(0, screensize[1]))) else: BigSaucer((random.randint(0, screensize[0]), random.randint(0, screensize[1]))) if mode == "gameoverstart": if ShipGroup.sprite <> None: ShipGroup.sprite.kill() gameover_text = ( Text("GAME OVER", large_font, (screensize[0] / 2, screensize[1] / 2 - 40), align = "center"), Text("Press any key to continue", font, (screensize[0] / 2, screensize[1] / 2 + 10), align = "center") ) mode = "gameover" if pygame.time.get_ticks() >= lastbeat + 10000 / (len(Asteroids.sprites()) + 10): lastbeat = pygame.time.get_ticks() if beattype == 1: beat1_sound.play() beattype = 2 else: beat2_sound.play() beattype = 1 viewpoint[0] += viewpointspeed[0] / fps viewpoint[1] += viewpointspeed[1] / fps Objects.update() ProtoObjs.update() screen.fill((backcolor)) #Objects.draw(screen) dirtyrects = [] for sprite in ProtoObjs.sprites(): dirtyrects += sprite.draw(screen) for sprite in Objects.sprites(): dirtyrects += sprite.draw(screen) #screen.blit(level_text, (screensize[0] / 2 - level_text.get_width() / 2, 5)) #score_text = font.render(str(score), 1, (255, 255, 255)) score_text.change(str(score)) #screen.blit(score_text, (screensize[0] - score_text.get_width() - 5, 5)) #screen.blit(lives_text, (5, 5)) dirtyrects += TextGroup.draw(screen) pygame.display.update(dirtyrects + olddirtyrects) olddirtyrects = dirtyrects main() pygame.quit()