Skip to content

Commit c5f4847

Browse files
author
Anuj Kumar
authored
I make A Game Called Asteroids-RiceRocks
1 parent ada03d5 commit c5f4847

File tree

1 file changed

+389
-0
lines changed

1 file changed

+389
-0
lines changed

Asteroids-RiceRocks.py

Lines changed: 389 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,389 @@
1+
#-------------------------------------------------------------------
2+
3+
# implementation of Spaceship - program template for RiceRocks
4+
import simplegui
5+
import math
6+
import random
7+
8+
#-------------------------------------------------------------------
9+
10+
11+
# helper classes
12+
13+
class ImageInfo:
14+
def __init__(self, center, size, radius = 0, lifespan = None, animated = False):
15+
self.center = center
16+
self.size = size
17+
self.radius = radius
18+
if lifespan:
19+
self.lifespan = lifespan
20+
else:
21+
self.lifespan = float('inf')
22+
self.animated = animated
23+
24+
def get_center(self):
25+
return self.center
26+
27+
def get_size(self):
28+
return self.size
29+
30+
def get_radius(self):
31+
return self.radius
32+
33+
def get_lifespan(self):
34+
return self.lifespan
35+
36+
def get_animated(self):
37+
return self.animated
38+
39+
40+
#-------------------------------------------------------------------
41+
#-------------------------------------------------------------------
42+
43+
# art assets created by Kim Lathrop, may be freely re-used in non-commercial projects, please credit Kim
44+
45+
# debris images - debris1_brown.png, debris2_brown.png, debris3_brown.png, debris4_brown.png
46+
# debris1_blue.png, debris2_blue.png, debris3_blue.png, debris4_blue.png, debris_blend.png
47+
debris_info = ImageInfo([320, 240], [640, 480])
48+
debris_image = simplegui.load_image("http://commondatastorage.googleapis.com/codeskulptor-assets/lathrop/debris2_blue.png")
49+
50+
# nebula images - nebula_brown.png, nebula_blue.png
51+
nebula_info = ImageInfo([400, 300], [800, 600])
52+
nebula_image = simplegui.load_image("http://commondatastorage.googleapis.com/codeskulptor-assets/lathrop/nebula_blue.f2014.png")
53+
54+
# splash image
55+
splash_info = ImageInfo([200, 150], [400, 300])
56+
splash_image = simplegui.load_image("http://commondatastorage.googleapis.com/codeskulptor-assets/lathrop/splash.png")
57+
58+
# ship image
59+
ship_info = ImageInfo([45, 45], [90, 90], 35)
60+
ship_image = simplegui.load_image("http://commondatastorage.googleapis.com/codeskulptor-assets/lathrop/double_ship.png")
61+
62+
# missile image - shot1.png, shot2.png, shot3.png
63+
missile_info = ImageInfo([5,5], [10, 10], 3, 50)
64+
missile_image = simplegui.load_image("http://commondatastorage.googleapis.com/codeskulptor-assets/lathrop/shot2.png")
65+
66+
# asteroid images - asteroid_blue.png, asteroid_brown.png, asteroid_blend.png
67+
asteroid_info = ImageInfo([45, 45], [90, 90], 40)
68+
asteroid_image = simplegui.load_image("http://commondatastorage.googleapis.com/codeskulptor-assets/lathrop/asteroid_blue.png")
69+
70+
# animated explosion - explosion_orange.png, explosion_blue.png, explosion_blue2.png, explosion_alpha.png
71+
explosion_info = ImageInfo([64, 64], [128, 128], 17, 24, True)
72+
explosion_image = simplegui.load_image("http://commondatastorage.googleapis.com/codeskulptor-assets/lathrop/explosion_alpha.png")
73+
74+
# sound assets purchased from sounddogs.com, please do not redistribute
75+
# .ogg versions of sounds are also available, just replace .mp3 by .ogg
76+
soundtrack = simplegui.load_sound("http://commondatastorage.googleapis.com/codeskulptor-assets/sounddogs/soundtrack.mp3")
77+
missile_sound = simplegui.load_sound("http://commondatastorage.googleapis.com/codeskulptor-assets/sounddogs/missile.mp3")
78+
ship_thrust_sound = simplegui.load_sound("http://commondatastorage.googleapis.com/codeskulptor-assets/sounddogs/thrust.mp3")
79+
explosion_sound = simplegui.load_sound("http://commondatastorage.googleapis.com/codeskulptor-assets/sounddogs/explosion.mp3")
80+
81+
# alternative upbeat soundtrack by composer and former IIPP student Emiel Stopler
82+
# please do not redistribute without permission from Emiel at http://www.filmcomposer.nl
83+
#soundtrack = simplegui.load_sound("https://storage.googleapis.com/codeskulptor-assets/ricerocks_theme.mp3")
84+
85+
86+
#-------------------------------------------------------------------
87+
#-------------------------------------------------------------------
88+
#-------------------------------------------------------------------
89+
90+
91+
# globals for user interface
92+
WIDTH = 800
93+
HEIGHT = 600
94+
score = 0
95+
lives = 3
96+
time = 0
97+
started = False
98+
99+
#-------------------------------------------------------------------
100+
#-------------------------------------------------------------------
101+
102+
103+
# helper functions to handle transformations
104+
def angle_to_vector(ang):
105+
return [math.cos(ang), math.sin(ang)]
106+
107+
def dist(p, q):
108+
return math.sqrt((p[0] - q[0]) ** 2 + (p[1] - q[1]) ** 2)
109+
110+
def process_sprite_group(s_group, canvas):
111+
for x in set(s_group):
112+
x.draw(canvas)
113+
if x.update():
114+
s_group.remove(x)
115+
116+
117+
def group_collide(s_group, other_object):
118+
has_collide = False
119+
120+
for x in set(s_group):
121+
if (x.collide(other_object)):
122+
a_explosion = Sprite(x.get_position(), [0, 0], 0, 0, explosion_image, explosion_info, explosion_sound)
123+
explosion_group.add(a_explosion)
124+
s_group.remove(x)
125+
has_collide = True
126+
127+
return has_collide
128+
129+
130+
def group_group_collide(group1, group2):
131+
total_collisions = 0
132+
133+
for x in set(group1):
134+
if group_collide(group2, x):
135+
group1.discard(x)
136+
total_collisions += 1
137+
138+
return total_collisions
139+
140+
#-------------------------------------------------------------------
141+
# Ship class
142+
class Ship:
143+
144+
def __init__(self, pos, vel, angle, image, info):
145+
self.pos = [pos[0], pos[1]]
146+
self.vel = [vel[0], vel[1]]
147+
self.thrust = False
148+
self.angle = angle
149+
self.angle_vel = 0
150+
self.image = image
151+
self.image_center = info.get_center()
152+
self.image_size = info.get_size()
153+
self.radius = info.get_radius()
154+
155+
def get_position(self):
156+
return self.pos
157+
158+
def get_radius(self):
159+
return self.radius
160+
161+
def draw(self,canvas):
162+
if self.thrust:
163+
canvas.draw_image(self.image, [self.image_center[0] + self.image_size[0], self.image_center[1]] , self.image_size,
164+
self.pos, self.image_size, self.angle)
165+
else:
166+
canvas.draw_image(self.image, self.image_center, self.image_size,
167+
self.pos, self.image_size, self.angle)
168+
169+
def update(self):
170+
# update angle
171+
self.angle += self.angle_vel
172+
173+
# update position
174+
self.pos[0] = (self.pos[0] + self.vel[0]) % WIDTH
175+
self.pos[1] = (self.pos[1] + self.vel[1]) % HEIGHT
176+
177+
# update velocity
178+
if self.thrust:
179+
acc = angle_to_vector(self.angle)
180+
self.vel[0] += acc[0] * .1
181+
self.vel[1] += acc[1] * .1
182+
183+
self.vel[0] *= .99
184+
self.vel[1] *= .99
185+
186+
def set_thrust(self, on):
187+
self.thrust = on
188+
if on:
189+
ship_thrust_sound.rewind()
190+
ship_thrust_sound.play()
191+
else:
192+
ship_thrust_sound.pause()
193+
194+
def increment_angle_vel(self):
195+
self.angle_vel += .05
196+
197+
def decrement_angle_vel(self):
198+
self.angle_vel -= .05
199+
200+
def shoot(self):
201+
forward = angle_to_vector(self.angle)
202+
missile_pos = [self.pos[0] + self.radius * forward[0], self.pos[1] + self.radius * forward[1]]
203+
missile_vel = [self.vel[0] + 6 * forward[0], self.vel[1] + 6 * forward[1]]
204+
a_missile = Sprite(missile_pos, missile_vel, self.angle, 0, missile_image, missile_info, missile_sound)
205+
206+
missile_group.add(a_missile)
207+
208+
#-------------------------------------------------------------------
209+
#-------------------------------------------------------------------
210+
211+
# Sprite class
212+
class Sprite:
213+
def __init__(self, pos, vel, ang, ang_vel, image, info, sound = None):
214+
self.pos = [pos[0],pos[1]]
215+
self.vel = [vel[0],vel[1]]
216+
self.angle = ang
217+
self.angle_vel = ang_vel
218+
self.image = image
219+
self.image_center = info.get_center()
220+
self.image_size = info.get_size()
221+
self.radius = info.get_radius()
222+
self.lifespan = info.get_lifespan()
223+
self.animated = info.get_animated()
224+
self.age = 0
225+
if sound:
226+
sound.rewind()
227+
sound.play()
228+
229+
def get_position(self):
230+
return self.pos
231+
232+
def get_radius(self):
233+
return self.radius
234+
235+
def draw(self, canvas):
236+
if self.animated:
237+
canvas.draw_image(self.image, [self.image_center[0] + self.age*self.image_size[0] ,self.image_center[1]] , self.image_size,
238+
self.pos, self.image_size, self.angle)
239+
else:
240+
canvas.draw_image(self.image, self.image_center, self.image_size,
241+
self.pos, self.image_size, self.angle)
242+
243+
def update(self):
244+
# update angle
245+
self.angle += self.angle_vel
246+
247+
# update position
248+
self.pos[0] = (self.pos[0] + self.vel[0]) % WIDTH
249+
self.pos[1] = (self.pos[1] + self.vel[1]) % HEIGHT
250+
251+
self.age += 1
252+
return (self.age >= self.lifespan)
253+
254+
255+
def collide(self,other_object):
256+
return ( dist(self.get_position(), other_object.get_position()) <= (self.radius + other_object.radius) )
257+
258+
#-------------------------------------------------------------------
259+
#-------------------------------------------------------------------
260+
261+
# key handlers to control ship
262+
def keydown(key):
263+
if key == simplegui.KEY_MAP['left']:
264+
my_ship.decrement_angle_vel()
265+
elif key == simplegui.KEY_MAP['right']:
266+
my_ship.increment_angle_vel()
267+
elif key == simplegui.KEY_MAP['up']:
268+
my_ship.set_thrust(True)
269+
elif key == simplegui.KEY_MAP['space']:
270+
my_ship.shoot()
271+
272+
def keyup(key):
273+
if key == simplegui.KEY_MAP['left']:
274+
my_ship.increment_angle_vel()
275+
elif key == simplegui.KEY_MAP['right']:
276+
my_ship.decrement_angle_vel()
277+
elif key == simplegui.KEY_MAP['up']:
278+
my_ship.set_thrust(False)
279+
280+
#-------------------------------------------------------------------
281+
#-------------------------------------------------------------------
282+
283+
# mouseclick handlers that reset UI and conditions whether splash image is drawn
284+
def click(pos):
285+
global started, lives, score
286+
center = [WIDTH / 2, HEIGHT / 2]
287+
size = splash_info.get_size()
288+
inwidth = (center[0] - size[0] / 2) < pos[0] < (center[0] + size[0] / 2)
289+
inheight = (center[1] - size[1] / 2) < pos[1] < (center[1] + size[1] / 2)
290+
if (not started) and inwidth and inheight:
291+
started = True
292+
lives = 3
293+
score = 0
294+
soundtrack.rewind()
295+
soundtrack.play()
296+
297+
298+
#-------------------------------------------------------------------
299+
#-------------------------------------------------------------------
300+
def draw(canvas):
301+
global time, started, lives, score, rock_group
302+
303+
# animiate background
304+
time += 1
305+
wtime = (time / 4) % WIDTH
306+
center = debris_info.get_center()
307+
size = debris_info.get_size()
308+
canvas.draw_image(nebula_image, nebula_info.get_center(), nebula_info.get_size(), [WIDTH / 2, HEIGHT / 2], [WIDTH, HEIGHT])
309+
canvas.draw_image(debris_image, center, size, (wtime - WIDTH / 2, HEIGHT / 2), (WIDTH, HEIGHT))
310+
canvas.draw_image(debris_image, center, size, (wtime + WIDTH / 2, HEIGHT / 2), (WIDTH, HEIGHT))
311+
312+
# draw UI
313+
canvas.draw_text("Lives", [50, 50], 22, "White")
314+
canvas.draw_text("Score", [680, 50], 22, "White")
315+
canvas.draw_text(str(lives), [50, 80], 22, "White")
316+
canvas.draw_text(str(score), [680, 80], 22, "White")
317+
318+
# draw and update ship and sprites
319+
my_ship.draw(canvas)
320+
my_ship.update()
321+
322+
process_sprite_group(rock_group,canvas)
323+
process_sprite_group(missile_group,canvas)
324+
process_sprite_group(explosion_group,canvas)
325+
326+
# update lives
327+
if group_collide(rock_group, my_ship):
328+
lives -= 1
329+
330+
# update score
331+
score += group_group_collide(rock_group, missile_group)
332+
333+
if lives == 0:
334+
started = False
335+
rock_group = set()
336+
337+
338+
# draw splash screen if not started
339+
if not started:
340+
canvas.draw_image(splash_image, splash_info.get_center(),
341+
splash_info.get_size(), [WIDTH / 2, HEIGHT / 2],
342+
splash_info.get_size())
343+
344+
#-------------------------------------------------------------------
345+
#-------------------------------------------------------------------
346+
347+
# timer handler that spawns a rock
348+
def rock_spawner():
349+
350+
if started:
351+
if len(rock_group) != 12:
352+
rock_pos = [random.randrange(0, WIDTH), random.randrange(0, HEIGHT)]
353+
354+
if not (dist(my_ship.get_position(), rock_pos) <= 10):
355+
rock_vel = [(random.random() * .6 - .3) + score/5.0 , (random.random() * .6 - .3) + score/5.0]
356+
rock_avel = random.random() * .2 - .1
357+
a_rock = Sprite(rock_pos, rock_vel, 0, rock_avel, asteroid_image, asteroid_info)
358+
359+
rock_group.add(a_rock)
360+
361+
#-------------------------------------------------------------------
362+
#-------------------------------------------------------------------
363+
364+
# initialize stuff
365+
frame = simplegui.create_frame("Asteroids", WIDTH, HEIGHT)
366+
367+
#-------------------------------------------------------------------
368+
369+
# initialize ship and two sprites
370+
my_ship = Ship([WIDTH / 2, HEIGHT / 2], [0, 0], 0, ship_image, ship_info)
371+
rock_group = set([])
372+
missile_group = set([])
373+
explosion_group = set([])
374+
#-------------------------------------------------------------------
375+
376+
377+
# register handlers
378+
frame.set_keyup_handler(keyup)
379+
frame.set_keydown_handler(keydown)
380+
frame.set_mouseclick_handler(click)
381+
frame.set_draw_handler(draw)
382+
#-------------------------------------------------------------------
383+
384+
timer = simplegui.create_timer(1000.0, rock_spawner)
385+
386+
#-------------------------------------------------------------------
387+
# get things rolling
388+
timer.start()
389+
frame.start()

0 commit comments

Comments
 (0)