#! /usr/bin/env python
# -*- coding: utf-8 -*-
#
# SpaceWar
# Copyright (C) 2007
# Copyright (C) 2013, Alan Aguiar
#
# 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 .
#
# Contact information:
# Alan Aguiar
import os
import gtk
import itertools
import pygame
import random
from gettext import gettext as _
POINTS_ENEMY = 1000
POINTS_SHOT = 100
class SpaceWar():
"""Top-level application class."""
def __init__(self, parent=None):
self.parent = parent
self.count = 0
self.level = 1
self.points = 0
self.old_points = 0
self.running = True
self.screen = None
self._points_large = 250
def get_stats(self):
msg = str(self.level) + '\n'
msg = msg + str(self.points)
return msg
def set_stats(self, stats):
l = stats.split('\n')
if len(l) == 2:
self.level = int(l[0])
self.points = int(l[1])
def calc_points_large(self):
msg = 9 * '0'
points_msg = self._font.render(_('Score: %s') % msg, 1, (255, 255, 255))
self._points_large = points_msg.get_width() + 10
def load_all(self):
# Dun dun duuuuuuuun
pygame.display.init()
# Initialize the screen surface
self.screen = pygame.display.get_surface()
if not(self.screen):
info = pygame.display.Info()
size = (info.current_w, info.current_h)
self.screen = pygame.display.set_mode(size, pygame.FULLSCREEN)
pygame.display.set_caption(_('SpaceWar'))
self.rect = self.screen.get_rect()
# Core objects
self.clock = pygame.time.Clock()
# images
self.ship_img = pygame.image.load('img/Space/ship1.png').convert_alpha()
self.shot_img = pygame.image.load('img/Space/bullet4.png').convert_alpha()
self.enemy_img = pygame.image.load('img/OldSchool/skully.png').convert_alpha()
pygame.mixer.init()
self.shot_sound = pygame.mixer.Sound('sounds/shot.wav')
# game labels
pygame.font.init()
self._font = pygame.font.Font(None, 40)
self.level_msg = self._font.render(_('Level: %s') % self.level, 1, (255, 255, 255))
self.do_score_msg()
# Game objects
self.ship = Ship(self)
self.ship.rect.midbottom = self.rect.midbottom
self.shots = pygame.sprite.Group()
self.enemies = pygame.sprite.Group()
# Add enemies
self.add_enemies(self.level)
self.calc_points_large()
def add_enemies(self, level):
for l in range(level):
enemy = Enemy(self)
x = random.randint(0, self.rect[2])
y = random.randint(50, self.rect[3] - 100)
enemy.rect.center = x, y
enemy.direction = random.choice((-1 , 1))
self.enemies.add(enemy)
def do_score_msg(self):
if self.points < 0:
p = str(abs(self.points))
c = (8 - len(p)) * '0'
msg = '-' + c + p
else:
p = str(self.points)
c = (8 - len(p)) * '0'
msg = c + p
self.points_msg = self._font.render(_('Score: %s') % msg, 1, (255, 255, 255))
def run(self):
self.load_all()
while self.running:
# Timing phase
delta = self.clock.tick(30)
while gtk.events_pending():
gtk.main_iteration()
# Event phase
for evt in pygame.event.get():
if evt.type == pygame.QUIT:
self.running = False
elif evt.type == pygame.KEYDOWN:
if evt.key == pygame.K_ESCAPE:
self.running = False
if evt.key == pygame.K_LEFT:
self.ship.direction = -1
elif evt.key == pygame.K_RIGHT:
self.ship.direction = 1
elif evt.key == pygame.K_SPACE:
self.points = self.points - POINTS_SHOT
new_shot = Shot(self)
new_shot.rect.midbottom = self.ship.rect.midtop
self.shots.add(new_shot)
elif evt.type == pygame.KEYUP:
if evt.key == pygame.K_LEFT and self.ship.direction == -1:
self.ship.direction = 0
elif evt.key == pygame.K_RIGHT and self.ship.direction == 1:
self.ship.direction = 0
# Update phase
self.ship.update(delta)
self.shots.update(delta)
self.enemies.update(delta)
# Look for shot-enemy collisions
d = pygame.sprite.groupcollide(self.enemies, self.shots, True, True)
# add points for each enemy killed
for ship in d:
self.points = self.points + POINTS_ENEMY
# delay between killed all enemies and appears more
if len(self.enemies) == 0:
self.count = self.count + 1
if self.count > 10:
self.count = 0
self.level = self.level + 1
self.level_msg = self._font.render(_('Level: %s') % self.level, 1, (255, 255, 255))
self.add_enemies(self.level)
# update score msg
if not(self.points == self.old_points):
self.do_score_msg()
self.old_points = self.points
# Display phase
self.screen.fill((0,0,0))
self.screen.blit(self.points_msg, (self.rect[2] - self._points_large, 10))
self.screen.blit(self.level_msg, (10, 10))
for spr in self.enemies:
self.screen.blit(spr.image, spr.rect, spr.source_rect)
self.shots.draw(self.screen)
self.screen.blit(self.ship.image, self.ship.rect)
pygame.display.flip()
class Ship(pygame.sprite.Sprite):
"""The player-controlled ship."""
def __init__(self, parent):
super(Ship, self).__init__()
self.parent = parent
self.image = parent.ship_img
self.rect = self.image.get_rect()
self.direction = 0
self.speed = 0.1
def update(self, delta):
self.rect.move_ip(delta*self.direction*self.speed, 0)
self.rect.clamp_ip(self.parent.rect)
class Shot(pygame.sprite.Sprite):
"""A single shot fired by the player."""
def __init__(self, parent):
super(Shot, self).__init__()
self.parent = parent
self.image = parent.shot_img
self.rect = self.image.get_rect()
self.speed = 0.2
# Load and play the shot sound
self.sound = parent.shot_sound
self.sound.play()
def update(self, delta):
self.rect.move_ip(0, -1*delta*self.speed)
if not self.rect.colliderect(self.parent.rect):
self.kill()
class Enemy(pygame.sprite.Sprite):
"""An enemy ship."""
def __init__(self, parent):
super(Enemy, self).__init__()
self.parent = parent
self.image = parent.enemy_img
self.rect = self.image.get_rect()
self.direction = 1
self.speed = 0.05
# Setup the animation frames
self.n_frames = 2
self.rect.width /= self.n_frames # Make self.rect to be the size of one frame
self.source_rects = itertools.cycle([self.rect.move(x*self.rect.width, 0) for x in xrange(self.n_frames)])
self.source_rect = self.source_rects.next() # Load the position of the first frame
# Setup the animation timing
self.time_per_frame = 200 # ms per frame in the animation
self.time_left = self.time_per_frame
def update(self, delta):
self.time_left -= delta
if self.time_left <= 0:
self.time_left += self.time_per_frame
self.source_rect = self.source_rects.next()
self.rect.move_ip(delta*self.direction*self.speed, 0)
if self.direction == 1 and self.rect.right >= self.parent.rect.right:
self.direction *= -1
self.rect.right = self.parent.rect.right
elif self.direction == -1 and self.rect.left <= self.parent.rect.left:
self.direction *= -1
self.rect.left = self.parent.rect.left
def main():
s = SpaceWar()
s.run()
if __name__ == '__main__':
main()