/ Published in: Python
Code is GPL
Left/Right to rotate ship, Up for thrust, z to fire.
a to toggle anti-aliasing
debug - f for FPS
by Avinash Vora
Left/Right to rotate ship, Up for thrust, z to fire.
a to toggle anti-aliasing
debug - f for FPS
by Avinash Vora
Expand |
Embed | Plain Text
Copy this code and paste it in your HTML
# spaceship shooter test # # Copyright (c) 2007, Avinash Vora # http://www.avinashv.net # # Source code is protected by the GNU GPL # # May 26 # - added randomly generated enemies # - added engine class # May 25 # - added maximum ship speed # - added anti-aliasing toggle # - changed friction from 0.0075 to 0.01 # - implemented bullets and physics # - fully object-oriented code # May 24 # - added FPS read-out # - implemented ship and physics import pygame, math, sys, random from pygame.locals import * black = 0, 0, 0 white = 255, 255, 255 red = 255, 0, 0 green = 0, 255, 0 d2p = lambda x1, y1, x2, y2: math.sqrt((x1 - x2) ** 2 + (y1 - y2) ** 2) class engine: def __init__(self, width, height): self.size = self.width, self.height = width, height self.running = True self.show_fps = False self.aaline = False self.enemies = [] self.ships = [] # state of keypresses self.right_pressed, self.left_pressed, self.up_pressed = False, False, False self.firing = False pygame.init() self.window = pygame.display.set_mode(self.size) self.window.fill(black) def global_draw(self): for ship in self.ships: ship.draw() for bullet in ship.bullets: bullet.draw() for enemy in self.enemies: enemy.draw() def global_physics(self): # apply physics to every ship and bullet for ship in self.ships: ship.physics() for bullet in ship.bullets: bullet.physics() # check boundaries and destroy bullet if outside if (bullet.x > self.width) or (bullet.x < 0) or (bullet.y > self.height) or (bullet.y < 0): ship.bullets.remove(bullet) continue # destroy bullets if they are older than 1000 ms if bullet.death <= pygame.time.get_ticks(): ship.bullets.remove(bullet) continue # check for collision for enemy in self.enemies: if d2p(bullet.x, bullet.y, enemy.x, enemy.y) < (bullet.radius + enemy.radius): enemy.health = enemy.health - bullet.strength ship.bullets.remove(bullet) if enemy.health <= 0: self.enemies.remove(enemy) class bullet_class: def __init__(self, engine, parent): self.engine = engine self.parent = parent self.x_comp, self.y_comp = 0, 0 self.x, self.y = self.parent.x, self.parent.y self.heading = self.parent.heading self.facing = self.parent.facing self.speed = 4.5 self.radius = 4 self.decay = 1000 self.death = pygame.time.get_ticks() + self.decay self.strength = 3 # calculate resultant x and y components self.x_comp = self.parent.speed * math.sin(self.heading) + self.speed * math.sin(self.facing) self.y_comp = self.parent.speed * math.cos(self.heading) + self.speed * math.cos(self.facing) # determine resultant speed self.speed= math.sqrt(self.x_comp ** 2 + self.y_comp ** 2) # calculate resultant heading if self.y_comp >= 0: self.heading = math.atan(self.x_comp / self.y_comp) elif self.y_comp < 0: self.heading = math.atan(self.x_comp / self.y_comp) + math.pi def draw(self): if self.engine.aaline: pygame.draw.circle(self.engine.window, green, (int(self.x), int(self.y)), self.radius, 1) else: pygame.draw.circle(self.engine.window, green, (int(self.x), int(self.y)), self.radius, 2) def physics(self): # adjust (x, y) according to speed self.x = self.x + self.speed * math.sin(self.heading) self.y = self.y - self.speed * math.cos(self.heading) class enemy_class: def __init__(self, engine, health): self.engine = engine self.x, self.y = random.randint(1, self.engine.width), random.randint(1, self.engine.height) self.health = health self.radius = self.health def draw(self): if self.engine.aaline: pygame.draw.circle(self.engine.window, white, (int(self.x), int(self.y)), self.radius, 1) else: pygame.draw.circle(self.engine.window, white, (int(self.x), int(self.y)), self.radius, 2) class spaceship_class: def __init__(self, engine): self.engine = engine self.accel = 0.06 self.friction = 0.01 self.max_speed = 4 self.rotation_rate = 5 self.x, self.y = self.engine.width / 2, self.engine.height / 2 self.x_comp, self.y_comp = 0, 0 self.facing = 0 self.heading = 0 self.speed = 0 self.radius = 10 self.bullet_delay = 200 self.last_bullet_time = 0 # holds all the bullets created by this instance self.bullets = [] def draw(self): # calculate vertices of the ship vertices = [ (self.x + self.radius * math.sin(self.facing), self.y - self.radius * math.cos(self.facing)), (self.x + self.radius * math.sin(self.facing + 2 * math.pi / 3), self.y - self.radius * math.cos(self.facing + 2 * math.pi / 3)), (self.x + self.radius * math.sin(self.facing + 4 * math.pi / 3), self.y - self.radius * math.cos(self.facing + 4 * math.pi / 3)) ] # draw lines with the back of the ship as red (anti-aliased if needed) if self.engine.aaline: pygame.draw.aaline(self.engine.window, white, vertices[0], vertices[1]) pygame.draw.aaline(self.engine.window, white, vertices[2], vertices[0]) pygame.draw.aaline(self.engine.window, red, vertices[1], vertices[2]) else: pygame.draw.line(self.engine.window, white, vertices[0], vertices[1], 2) pygame.draw.line(self.engine.window, white, vertices[2], vertices[0], 2) pygame.draw.line(self.engine.window, red, vertices[1], vertices[2], 2) def physics(self): if self.engine.right_pressed: # determine new direction self.facing = self.facing + (self.rotation_rate * math.pi) / 180 if self.engine.left_pressed: # determine new direction self.facing = self.facing - (self.rotation_rate * math.pi) / 180 if self.engine.up_pressed: # determine resultant x and y components self.x_comp = self.speed * math.sin(self.heading) + self.accel * math.sin(self.facing) self.y_comp = self.speed * math.cos(self.heading) + self.accel * math.cos(self.facing) # determine resultant speed if self.speed < self.max_speed: self.speed = math.sqrt(self.x_comp ** 2 + self.y_comp ** 2) else: self.speed = self.max_speed # calculate resultant heading if self.y_comp >= 0: self.heading = math.atan(self.x_comp / self.y_comp) elif self.y_comp < 0: self.heading = math.atan(self.x_comp / self.y_comp) + math.pi # create new bullet if self.engine.firing: if pygame.time.get_ticks() >= (self.last_bullet_time + self.bullet_delay): self.bullets.append(bullet_class(self.engine, self)) self.last_bullet_time = pygame.time.get_ticks() # adjust speed for friction if self.speed > 0: self.speed = self.speed - self.friction # adjust (x, y) according to speed self.x = self.x + self.speed * math.sin(self.heading) self.y = self.y - self.speed * math.cos(self.heading) # check boundaries if self.x > self.engine.width: self.x = 0 if self.x < 0: self.x = self.engine.width if self.y > self.engine.height: self.y = 0 if self.y < 0: self.y = self.engine.height if __name__ == '__main__': if not pygame.font: print 'Fonts disabled!' if not pygame.mixer: print 'Sound disabled!' game = engine(640, 480) clock = pygame.time.Clock() pygame.display.set_caption('shooter test') game.ships.append(spaceship_class(game)) for item in range(1, random.randint(5, 15)): game.enemies.append(enemy_class(game, random.randint(5, 15))) while game.running: # limit fps to 60 clock.tick(60) # clear screen game.window.fill(black) # show fps if pygame.font and game.show_fps: font = pygame.font.Font(None, 16) text = font.render('fps ' + str(int(clock.get_fps())), 1, (150, 150, 150)) text_position = text.get_rect(centerx = game.width / 2) game.window.blit(text, text_position) # handle physics and drawing game.global_physics() game.global_draw() # flip the screen pygame.display.update() # handle input for event in pygame.event.get(): if event.type == QUIT: running = False # key down elif event.type == KEYDOWN: if event.key == K_ESCAPE: game.running = False elif event.key == K_RIGHT: game.right_pressed = True elif event.key == K_LEFT: game.left_pressed = True elif event.key == K_UP: game.up_pressed = True elif event.key == K_z: game.firing = True elif event.key == K_f: game.show_fps = not game.show_fps elif event.key == K_a: game.aaline = not game.aaline # key up elif event.type == KEYUP: if event.key == K_RIGHT: game.right_pressed = False elif event.key == K_LEFT: game.left_pressed = False elif event.key == K_UP: game.up_pressed = False elif event.key == K_z: game.firing = False