1 |
#! /usr/bin/env python |
2 |
# -*- coding: utf-8 -*- |
3 |
# |
4 |
# SpaceWar |
5 |
# Copyright (C) 2007 |
6 |
# Copyright (C) 2013, Alan Aguiar |
7 |
# |
8 |
# This program is free software: you can redistribute it and/or modify |
9 |
# it under the terms of the GNU General Public License as published by |
10 |
# the Free Software Foundation, either version 3 of the License, or |
11 |
# (at your option) any later version. |
12 |
# |
13 |
# This program is distributed in the hope that it will be useful, |
14 |
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
15 |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
16 |
# GNU General Public License for more details. |
17 |
# |
18 |
# You should have received a copy of the GNU General Public License |
19 |
# along with this program. If not, see <http://www.gnu.org/licenses/>. |
20 |
# |
21 |
# Contact information: |
22 |
# Alan Aguiar <alanjas@gmail.com> |
23 |
|
24 |
import gtk |
25 |
import itertools |
26 |
import pygame |
27 |
import random |
28 |
|
29 |
from gettext import gettext as _ |
30 |
|
31 |
POINTS_ENEMY = 1000 |
32 |
POINTS_SHOT = 100 |
33 |
|
34 |
class SpaceWar(): |
35 |
"""Top-level application class.""" |
36 |
|
37 |
def __init__(self): |
38 |
self.count = 0 |
39 |
self.level = 1 |
40 |
self.points = 0 |
41 |
self.old_points = 0 |
42 |
self.running = True |
43 |
self.screen = None |
44 |
|
45 |
def load_all(self): |
46 |
# Dun dun duuuuuuuun |
47 |
pygame.display.init() |
48 |
|
49 |
# Initialize the screen surface |
50 |
self.screen = pygame.display.get_surface() |
51 |
if not(self.screen): |
52 |
info = pygame.display.Info() |
53 |
size = (info.current_w, info.current_h) |
54 |
self.screen = pygame.display.set_mode(size, pygame.FULLSCREEN) |
55 |
pygame.display.set_caption(_('SpaceWar')) |
56 |
self.rect = self.screen.get_rect() |
57 |
|
58 |
# Core objects |
59 |
self.clock = pygame.time.Clock() |
60 |
|
61 |
# images |
62 |
self.ship_img = pygame.image.load('img/Space/ship1.png').convert_alpha() |
63 |
self.shot_img = pygame.image.load('img/Space/bullet4.png').convert_alpha() |
64 |
self.enemy_img = pygame.image.load('img/OldSchool/skully.png').convert_alpha() |
65 |
|
66 |
pygame.mixer.init() |
67 |
self.shot_sound = pygame.mixer.Sound('sounds/shot.wav') |
68 |
|
69 |
# game labels |
70 |
pygame.font.init() |
71 |
self._font = pygame.font.Font(None, 40) |
72 |
self.level_msg = self._font.render(_('Level: %s') % 1, 1, (255, 255, 255)) |
73 |
self.points_msg = self._font.render(_('Score: %s') % 0, 1, (255, 255, 255)) |
74 |
|
75 |
# Game objects |
76 |
self.ship = Ship(self) |
77 |
self.ship.rect.midbottom = self.rect.midbottom |
78 |
self.shots = pygame.sprite.Group() |
79 |
self.enemies = pygame.sprite.Group() |
80 |
# Add enemies |
81 |
self.add_enemies(self.level) |
82 |
|
83 |
def add_enemies(self, level): |
84 |
for l in range(level): |
85 |
enemy = Enemy(self) |
86 |
x = random.randint(0, self.rect[2]) |
87 |
y = random.randint(50, self.rect[3] - 100) |
88 |
enemy.rect.center = x, y |
89 |
enemy.direction = random.choice((-1 , 1)) |
90 |
self.enemies.add(enemy) |
91 |
|
92 |
def do_score_msg(self): |
93 |
if self.points < 0: |
94 |
p = str(abs(self.points)) |
95 |
c = (8 - len(p)) * '0' |
96 |
msg = '-' + c + p |
97 |
else: |
98 |
p = str(self.points) |
99 |
c = (8 - len(p)) * '0' |
100 |
msg = c + p |
101 |
self.points_msg = self._font.render(_('Score: %s') % msg, 1, (255, 255, 255)) |
102 |
|
103 |
def run(self): |
104 |
self.load_all() |
105 |
while self.running: |
106 |
# Timing phase |
107 |
delta = self.clock.tick(30) |
108 |
while gtk.events_pending(): |
109 |
gtk.main_iteration() |
110 |
# Event phase |
111 |
for evt in pygame.event.get(): |
112 |
if evt.type == pygame.QUIT: |
113 |
self.running = False |
114 |
elif evt.type == pygame.KEYDOWN: |
115 |
if evt.key == pygame.K_ESCAPE: |
116 |
self.running = False |
117 |
if evt.key == pygame.K_LEFT: |
118 |
self.ship.direction = -1 |
119 |
elif evt.key == pygame.K_RIGHT: |
120 |
self.ship.direction = 1 |
121 |
elif evt.key == pygame.K_SPACE: |
122 |
self.points = self.points - POINTS_SHOT |
123 |
new_shot = Shot(self) |
124 |
new_shot.rect.midbottom = self.ship.rect.midtop |
125 |
self.shots.add(new_shot) |
126 |
elif evt.type == pygame.KEYUP: |
127 |
if evt.key == pygame.K_LEFT and self.ship.direction == -1: |
128 |
self.ship.direction = 0 |
129 |
elif evt.key == pygame.K_RIGHT and self.ship.direction == 1: |
130 |
self.ship.direction = 0 |
131 |
|
132 |
# Update phase |
133 |
self.ship.update(delta) |
134 |
self.shots.update(delta) |
135 |
self.enemies.update(delta) |
136 |
# Look for shot-enemy collisions |
137 |
d = pygame.sprite.groupcollide(self.enemies, self.shots, True, True) |
138 |
# add points for each enemy killed |
139 |
for ship in d: |
140 |
self.points = self.points + POINTS_ENEMY |
141 |
# delay between killed all enemies and appears more |
142 |
if len(self.enemies) == 0: |
143 |
self.count = self.count + 1 |
144 |
if self.count > 10: |
145 |
self.count = 0 |
146 |
self.level = self.level + 1 |
147 |
self.level_msg = self._font.render(_('Level: %s') % self.level, 1, (255, 255, 255)) |
148 |
self.add_enemies(self.level) |
149 |
# update score msg |
150 |
if not(self.points == self.old_points): |
151 |
self.do_score_msg() |
152 |
self.old_points = self.points |
153 |
# Display phase |
154 |
self.screen.fill((0,0,0)) |
155 |
self.screen.blit(self.points_msg, (self.rect[2] - 250, 10)) |
156 |
self.screen.blit(self.level_msg, (10, 10)) |
157 |
for spr in self.enemies: |
158 |
self.screen.blit(spr.image, spr.rect, spr.source_rect) |
159 |
self.shots.draw(self.screen) |
160 |
self.screen.blit(self.ship.image, self.ship.rect) |
161 |
pygame.display.flip() |
162 |
|
163 |
|
164 |
class Ship(pygame.sprite.Sprite): |
165 |
"""The player-controlled ship.""" |
166 |
|
167 |
def __init__(self, parent): |
168 |
super(Ship, self).__init__() |
169 |
self.parent = parent |
170 |
self.image = parent.ship_img |
171 |
self.rect = self.image.get_rect() |
172 |
self.direction = 0 |
173 |
self.speed = 0.1 |
174 |
|
175 |
def update(self, delta): |
176 |
self.rect.move_ip(delta*self.direction*self.speed, 0) |
177 |
self.rect.clamp_ip(self.parent.rect) |
178 |
|
179 |
|
180 |
class Shot(pygame.sprite.Sprite): |
181 |
"""A single shot fired by the player.""" |
182 |
|
183 |
def __init__(self, parent): |
184 |
super(Shot, self).__init__() |
185 |
self.parent = parent |
186 |
self.image = parent.shot_img |
187 |
self.rect = self.image.get_rect() |
188 |
self.speed = 0.2 |
189 |
|
190 |
# Load and play the shot sound |
191 |
self.sound = parent.shot_sound |
192 |
self.sound.play() |
193 |
|
194 |
def update(self, delta): |
195 |
self.rect.move_ip(0, -1*delta*self.speed) |
196 |
if not self.rect.colliderect(self.parent.rect): |
197 |
self.kill() |
198 |
|
199 |
|
200 |
class Enemy(pygame.sprite.Sprite): |
201 |
"""An enemy ship.""" |
202 |
|
203 |
def __init__(self, parent): |
204 |
super(Enemy, self).__init__() |
205 |
self.parent = parent |
206 |
self.image = parent.enemy_img |
207 |
self.rect = self.image.get_rect() |
208 |
self.direction = 1 |
209 |
self.speed = 0.05 |
210 |
|
211 |
# Setup the animation frames |
212 |
self.n_frames = 2 |
213 |
self.rect.width /= self.n_frames # Make self.rect to be the size of one frame |
214 |
self.source_rects = itertools.cycle([self.rect.move(x*self.rect.width, 0) for x in xrange(self.n_frames)]) |
215 |
self.source_rect = self.source_rects.next() # Load the position of the first frame |
216 |
|
217 |
# Setup the animation timing |
218 |
self.time_per_frame = 200 # ms per frame in the animation |
219 |
self.time_left = self.time_per_frame |
220 |
|
221 |
def update(self, delta): |
222 |
self.time_left -= delta |
223 |
if self.time_left <= 0: |
224 |
self.time_left += self.time_per_frame |
225 |
self.source_rect = self.source_rects.next() |
226 |
|
227 |
self.rect.move_ip(delta*self.direction*self.speed, 0) |
228 |
if self.direction == 1 and self.rect.right >= self.parent.rect.right: |
229 |
self.direction *= -1 |
230 |
self.rect.right = self.parent.rect.right |
231 |
elif self.direction == -1 and self.rect.left <= self.parent.rect.left: |
232 |
self.direction *= -1 |
233 |
self.rect.left = self.parent.rect.left |
234 |
|
235 |
def main(): |
236 |
s = SpaceWar() |
237 |
s.run() |
238 |
|
239 |
if __name__ == '__main__': |
240 |
main() |