nebula_info = ImageInfo((400, 300), (800, 600)) ship_info = ImageInfo((45, 45), (90, 90), 35) # Sounds from http://www.sounddogs.com/ (not free) loader.add_sound( 'http://commondatastorage.googleapis.com/codeskulptor-assets/sounddogs/missile.ogg', 'missile') loader.add_sound( 'http://commondatastorage.googleapis.com/codeskulptor-assets/sounddogs/thrust.ogg', 'ship_thrust') loader.load() # Initialize ship and rock my_ship = Ship((0, SCREEN_HEIGHT / 2.0), (10, 0), 0, loader.get_image('ship'), ship_info) # Register event handlers frame.set_keydown_handler(keydown) frame.set_keyup_handler(keyup) button_fps = frame.add_button('FPS on', fps_on_off) frame.add_label('') frame.add_button('Quit', quit_prog) loader.wait_loaded() loader.get_sound('missile').set_volume(.5) frame.start()
class RiceRocks: """ General class dealing the game. """ def __init__(self): """ Set elements of the game. """ self.loaded = False self.keydown_left = False self.keydown_right = False self.lives = 3 self.my_ship = None self.nb_bombs = None self.score = 0 self.started = False self.time = 0 self.explosions = [] self.live_explosions = [] self.missiles = [] self.rocks = [] self.animate_background_active = True self.music_active = True self.sounds_active = True self.timer = simplegui.create_timer(1000, self.rock_spawner) self.img_infos = None self.medias = None def bomb_explode(self): """ If it remains bomb then detonated a bomb that destroys all asteroids. """ if self.nb_bombs: self.nb_bombs -= 1 if self.sounds_active: self.medias.get_sound('bomb_explode').rewind() self.medias.get_sound('bomb_explode').play() for rock in self.rocks: self.explosions.append(Sprite(rock.position, rock.velocity, 0, rock.angle_velocity, 'asteroid_explosion')) self.rocks = [] def draw_and_update(self, canvas): """ Draw and update all stuffs in each FPS cycle. :param canvas: simplegui.Canvas """ self.time += 1 # Draw static background if not SIMPLEGUICS2PYGAME: canvas.draw_image(self.medias.get_image('nebula'), self.img_infos['nebula'].get_center(), self.img_infos['nebula'].get_size(), (SCREEN_WIDTH/2.0, SCREEN_HEIGHT/2.0), (SCREEN_WIDTH, SCREEN_HEIGHT)) # Draw animated background if self.animate_background_active: center = self.img_infos['debris'].get_center() size = self.img_infos['debris'].get_size() wtime = (self.time/4.0) % SCREEN_WIDTH canvas.draw_image(self.medias.get_image('debris'), center, size, (wtime - SCREEN_WIDTH/2.0, SCREEN_HEIGHT/2.0), (SCREEN_WIDTH, SCREEN_HEIGHT)) canvas.draw_image(self.medias.get_image('debris'), center, size, (wtime + SCREEN_WIDTH/2.0, SCREEN_HEIGHT/2.0), (SCREEN_WIDTH, SCREEN_HEIGHT)) # Draw missiles, ship, asteroids and explosions for missile in self.missiles: missile.draw(canvas) if self.lives > 0: self.my_ship.draw(canvas) for rock in self.rocks: rock.draw(canvas) for i in range(len(self.explosions) - 1, -1, -1): explosion = self.explosions[i] explosion.draw(canvas) explosion.update() if explosion.lifespan <= 0: # explosion finished del self.explosions[i] # Update ship self.my_ship.update() # Update missiles for i in range(len(self.missiles) - 1, -1, -1): missile = self.missiles[i] missile.update() if missile.lifespan <= 0: # missile disappear del self.missiles[i] else: # active missile for j in range(len(self.rocks) - 1, -1, -1): # Check collide with asteroids rock = self.rocks[j] if missile.collide(rock): # collide del self.missiles[i] del self.rocks[j] if not rock.little: # Divide in two little asteroids angle = vector_to_angle(missile.velocity) mvel = math.sqrt( (rock.velocity[0]*rock.velocity[0] + rock.velocity[1]*rock.velocity[1])/2.0) vel = list(angle_to_vector(angle - math.pi/4)) vel[0] *= mvel vel[1] *= mvel little1 = Asteroid(rock.position, vel, rock.angle_velocity*2, rock.num, True) vel = list(angle_to_vector(angle + math.pi/4)) vel[0] *= mvel vel[1] *= mvel little2 = Asteroid(rock.position, vel, -rock.angle_velocity*2, rock.num, True) while True: little1.position[0] += little1.velocity[0] little1.position[1] += little1.velocity[1] little2.position[0] += little2.velocity[0] little2.position[1] += little2.velocity[1] if not little1.collide(little2): break self.rocks.extend((little1, little2)) self.score += 1 if self.score % 10 == 0: # add a new bomb self.nb_bombs += 1 if self.sounds_active: self.medias.get_sound('bomb_extra').rewind() self.medias.get_sound('bomb_extra').play() if self.score % 50 == 0: # add a new live self.lives += 1 self.explosions.append(Sprite(rock.position, rock.velocity, 0, rock.angle_velocity, 'asteroid_explosion')) break # Update asteroids for i in range(len(self.rocks) - 1, -1, -1): rock = self.rocks[i] rock.update() if self.my_ship.collide(rock): # collide with ship del self.rocks[i] self.explosions.append(Sprite(rock.position, rock.velocity, 0, rock.angle_velocity, 'asteroid_collide_explosion')) self.live_explosions.append(Sprite((self.lives*40, 40), (0, 0), -math.pi/2, 0, 'live_explosion')) self.lives = max(0, self.lives - 1) if self.lives <= 0: # game over self.stop() self.explosions.append(Sprite(self.my_ship.position, self.my_ship.velocity, 0, self.my_ship.angle_velocity, 'ship_explosion')) if self.sounds_active: self.medias.get_sound('death').rewind() self.medias.get_sound('death').play() break else: if self.sounds_active: self.medias.get_sound('collide').rewind() self.medias.get_sound('collide').play() else: for j in range(0, i): other = self.rocks[j] if rock.collide(other): rock.position[0] = (rock.position[0] - rock.velocity[0]) % SCREEN_WIDTH rock.position[1] = (rock.position[1] - rock.velocity[1]) % SCREEN_HEIGHT other.position[0] = ((other.position[0] - other.velocity[0]) % SCREEN_WIDTH) other.position[1] = ((other.position[1] - other.velocity[1]) % SCREEN_HEIGHT) # Elastic collision (with radius*3 as mass) # https://en.wikipedia.org/wiki/Elastic_collision tmp_sum = (rock.radius + other.radius)*3 tmp_diff = (rock.radius - other.radius)*3 double = 2*3*other.radius new_x = (float(tmp_diff*rock.velocity[0] + double*other.velocity[0])/tmp_sum) new_y = (float(tmp_diff*rock.velocity[1] + double*other.velocity[1])/tmp_sum) double = 2*3*rock.radius other.velocity[0] = float( double*rock.velocity[0] - tmp_diff*other.velocity[0])/tmp_sum other.velocity[1] = float( double*rock.velocity[1] - tmp_diff*other.velocity[1])/tmp_sum rock.velocity[0] = new_x rock.velocity[1] = new_y # Display number of lives if self.started: info = self.img_infos['ship'] for i in range(self.lives): canvas.draw_image(self.medias.get_image('ship'), info.get_center(), info.get_size(), (40 + i*40, 40), (40, 40), -math.pi/2) # Draw and update live explosions for i in range(len(self.live_explosions) - 1, -1, -1): live_explosion = self.live_explosions[i] canvas.draw_image(live_explosion.image, live_explosion.image_center, live_explosion.image_size, live_explosion.position, (40, 40), -math.pi/2) live_explosion.update() if live_explosion.lifespan <= 0: # explosion finished del self.live_explosions[i] # Display number of bombs if self.started and self.nb_bombs: info = self.img_infos['bomb'] for i in range(self.nb_bombs): canvas.draw_image(self.medias.get_image('bomb'), info.get_center(), info.get_size(), (40 + i*40, 80), (20, 40), -math.pi/2) # Display score size = 36 font = 'sans-serif' text1 = 'Score' width1 = frame.get_canvas_textwidth(text1, size, font) text2 = str(self.score) width2 = frame.get_canvas_textwidth(text2, size, font) canvas.draw_text(text1, (SCREEN_WIDTH - 22 - width1, 22 + size*3.0/4), size, 'Gray', font) canvas.draw_text(text2, (SCREEN_WIDTH - 22 - width2, 22 + size*7.0/4), size, 'Gray', font) canvas.draw_text(text1, (SCREEN_WIDTH - 20 - width1, 20 + size*3.0/4), size, 'White', font) canvas.draw_text(text2, (SCREEN_WIDTH - 20 - width2, 20 + size*7.0/4), size, 'White', font) # Draw splash screen if game not started if not self.started: size = self.img_infos['splash'].get_size() canvas.draw_image(self.medias.get_image('splash'), self.img_infos['splash'].get_center(), size, (SCREEN_WIDTH/2.0, SCREEN_HEIGHT/2.0), size) # Update and draw FPS (if started) fps.draw_fct(canvas) def load_medias(self): """ Load images and sounds and waiting all is loaded, the set the general draw handler. """ self.img_infos = {'asteroid-1': ImageInfo((45, 45), (90, 90), 40), 'asteroid-2': ImageInfo((45, 45), (90, 90), 40), 'asteroid-3': ImageInfo((45, 45), (90, 90), 38), 'asteroid_explosion': ImageInfo((64, 64), (128, 128), 17, 24, True), 'asteroid_collide_explosion': ImageInfo((64, 64), (128, 128), 17, 24, True), 'bomb': ImageInfo((10, 10), (20, 20)), 'debris': ImageInfo((320, 240), (640, 480)), 'little-asteroid-1': ImageInfo((45, 45), (90, 90), 27, None, False, (60, 60)), 'little-asteroid-2': ImageInfo((45, 45), (90, 90), 27, None, False, (60, 60)), 'little-asteroid-3': ImageInfo((45, 45), (90, 90), 26, None, False, (60, 60)), 'live_explosion': ImageInfo((64, 64), (128, 128), 17, 24, True), 'missile': ImageInfo((5, 5), (10, 10), 3, 50), 'nebula': ImageInfo((400, 300), (800, 600)), 'ship': ImageInfo((45, 45), (90, 90), 35), 'ship_explosion': ImageInfo((64, 64), (128, 128), 17, 24, True), 'splash': ImageInfo((200, 150), (400, 300))} def init(): """ Init the game after medias loaded. """ if SIMPLEGUICS2PYGAME: frame._set_canvas_background_image( self.medias.get_image('nebula')) self.medias._images['live_explosion'] = \ self.medias._images['ship_explosion'] for i in range(1, 4): self.medias._images['little-asteroid-' + str(i)] = \ self.medias._images['asteroid-' + str(i)] self.medias._sounds['asteroid_collide_explosion'] = \ self.medias._sounds['asteroid_explosion'] self.medias.get_sound('missile').set_volume(.5) self.my_ship = Ship((SCREEN_WIDTH/2.0, SCREEN_HEIGHT/2.0), (0, 0), -math.pi/2, 'ship') frame.set_draw_handler(self.draw_and_update) frame.set_keydown_handler(keydown) frame.set_keyup_handler(keyup) frame.set_mouseclick_handler(click) if self.music_active: self.medias.get_sound('intro').play() self.loaded = True self.medias = Loader(frame, SCREEN_WIDTH, init) # Images by Kim Lathrop self.medias.add_image('http://commondatastorage.googleapis.com/codeskulptor-assets/lathrop/asteroid_blend.png', 'asteroid-1') self.medias.add_image('http://commondatastorage.googleapis.com/codeskulptor-assets/lathrop/asteroid_blue.png', 'asteroid-2') self.medias.add_image('http://commondatastorage.googleapis.com/codeskulptor-assets/lathrop/asteroid_brown.png', 'asteroid-3') self.medias.add_image('http://commondatastorage.googleapis.com/codeskulptor-assets/lathrop/explosion_alpha.png', 'asteroid_explosion') self.medias.add_image('http://commondatastorage.googleapis.com/codeskulptor-assets/lathrop/explosion_alpha2.png', 'asteroid_collide_explosion') self.medias.add_image('http://commondatastorage.googleapis.com/codeskulptor-assets/lathrop/shot3.png', 'bomb') self.medias.add_image('http://commondatastorage.googleapis.com/codeskulptor-assets/lathrop/debris2_blue.png', 'debris') self.medias.add_image('http://commondatastorage.googleapis.com/codeskulptor-assets/lathrop/shot2.png', 'missile') self.medias.add_image('http://commondatastorage.googleapis.com/codeskulptor-assets/lathrop/nebula_brown.png', 'nebula') self.medias.add_image('http://commondatastorage.googleapis.com/codeskulptor-assets/lathrop/double_ship.png', 'ship') self.medias.add_image('http://commondatastorage.googleapis.com/codeskulptor-assets/lathrop/explosion_orange.png', 'ship_explosion') self.medias.add_image('http://commondatastorage.googleapis.com/codeskulptor-assets/lathrop/splash.png', 'splash') # Sounds from http://www.sounddogs.com/ (not free) self.medias.add_sound('http://commondatastorage.googleapis.com/codeskulptor-assets/sounddogs/explosion.ogg', 'asteroid_explosion') self.medias.add_sound('http://rpg.hamsterrepublic.com/wiki-images/f/f4/StormMagic.ogg', 'bomb_explode') self.medias.add_sound('http://commondatastorage.googleapis.com/codeskulptor-demos/pyman_assets/extralife.ogg', 'bomb_extra') self.medias.add_sound('http://commondatastorage.googleapis.com/codeskulptor-demos/pyman_assets/eatedible.ogg', 'collide') self.medias.add_sound('http://rpg.hamsterrepublic.com/wiki-images/5/58/Death.ogg', 'death') self.medias.add_sound('http://commondatastorage.googleapis.com/codeskulptor-demos/pyman_assets/intromusic.ogg', 'intro') self.medias.add_sound('http://commondatastorage.googleapis.com/codeskulptor-assets/sounddogs/soundtrack.ogg', 'soundtrack') self.medias.add_sound('http://commondatastorage.googleapis.com/codeskulptor-assets/sounddogs/missile.ogg', 'missile') self.medias.add_sound('http://commondatastorage.googleapis.com/codeskulptor-assets/sounddogs/thrust.ogg', 'ship_thrust') self.medias.load() self.medias.wait_loaded() def rock_spawner(self): """ If the maximum is not reached then spawns a rock (not too close to the ship). """ if len(self.rocks) < 10: too_close = True def random_vel(): """ :return: int or float """ return (min(2, (random.random()*(self.score/10.0 + 0.1))) * random.choice((-1, 1))) for _ in range(10): # try 10 times rock_pos = (random.randrange(0, SCREEN_WIDTH), random.randrange(0, SCREEN_HEIGHT)) rock_vel = (random_vel(), random_vel()) rock_ang_vel = random.choice((-1, 1))*(random.random()*0.05 + 0.01) rock = Asteroid(rock_pos, rock_vel, rock_ang_vel, random.randint(1, 3)) too_close = False for rock2 in self.rocks: if rock2.collide(rock): too_close = True break too_close = (too_close or (self.my_ship.distance(rock) < (self.my_ship.radius + rock.radius)*3)) if not too_close: break if not too_close: self.rocks.append(rock) def start(self): """ Start the game. """ if self.music_active: self.medias.get_sound('intro').rewind() self.medias.get_sound('soundtrack').play() self.keydown_left = False self.keydown_right = False self.lives = 3 self.nb_bombs = 0 self.score = 0 self.my_ship = Ship((SCREEN_WIDTH/2.0, SCREEN_HEIGHT/2.0), (0, 0), -math.pi/2, 'ship') self.explosions = [] self.missiles = [] self.rocks = [] self.timer.start() self.rock_spawner() self.started = True def stop(self): """ Stop the game. """ self.timer.stop() self.nb_bombs = None self.missiles = [] self.rocks = [] self.started = False self.my_ship.stop() if self.music_active: self.medias.get_sound('soundtrack').rewind() self.medias.get_sound('intro').play()
debris_info = ImageInfo((320, 240), (640, 480)) missile_info = ImageInfo((5, 5), (10, 10), 3, 50) nebula_info = ImageInfo((400, 300), (800, 600)) ship_info = ImageInfo((45, 45), (90, 90), 35) # Sounds from http://www.sounddogs.com/ (not free) loader.add_sound('http://commondatastorage.googleapis.com/codeskulptor-assets/sounddogs/missile.ogg', 'missile') loader.add_sound('http://commondatastorage.googleapis.com/codeskulptor-assets/sounddogs/thrust.ogg', 'ship_thrust') loader.load() # Initialize ship and rock my_ship = Ship((0, SCREEN_HEIGHT/2.0), (10, 0), 0, loader.get_image('ship'), ship_info) # Register event handlers frame.set_keydown_handler(keydown) frame.set_keyup_handler(keyup) button_fps = frame.add_button('FPS on', fps_on_off) frame.add_label('') frame.add_button('Quit', quit_prog) loader.wait_loaded() loader.get_sound('missile').set_volume(.5) frame.start()
class RiceRocks: """ General class dealing the game. """ def __init__(self): """ Set elements of the game. """ self.loaded = False self.keydown_left = False self.keydown_right = False self.lives = 3 self.my_ship = None self.nb_bombs = None self.score = 0 self.started = False self.time = 0 self.explosions = [] self.live_explosions = [] self.missiles = [] self.rocks = [] self.animate_background_active = True self.music_active = True self.sounds_active = True self.timer = simplegui.create_timer(1000, self.rock_spawner) self.img_infos = None self.medias = None def bomb_explode(self): """ If it remains bomb then detonated a bomb that destroys all asteroids. """ if self.nb_bombs: self.nb_bombs -= 1 if self.sounds_active: self.medias.get_sound('bomb_explode').rewind() self.medias.get_sound('bomb_explode').play() for rock in self.rocks: self.explosions.append( Sprite(rock.position, rock.velocity, 0, rock.angle_velocity, 'asteroid_explosion')) self.rocks = [] def draw_and_update(self, canvas): """ Draw and update all stuffs in each FPS cycle. :param canvas: simplegui.Canvas """ self.time += 1 # Draw static background if not SIMPLEGUICS2PYGAME: canvas.draw_image(self.medias.get_image('nebula'), self.img_infos['nebula'].get_center(), self.img_infos['nebula'].get_size(), (SCREEN_WIDTH / 2.0, SCREEN_HEIGHT / 2.0), (SCREEN_WIDTH, SCREEN_HEIGHT)) # Draw animated background if self.animate_background_active: center = self.img_infos['debris'].get_center() size = self.img_infos['debris'].get_size() wtime = (self.time / 4.0) % SCREEN_WIDTH canvas.draw_image( self.medias.get_image('debris'), center, size, (wtime - SCREEN_WIDTH / 2.0, SCREEN_HEIGHT / 2.0), (SCREEN_WIDTH, SCREEN_HEIGHT)) canvas.draw_image( self.medias.get_image('debris'), center, size, (wtime + SCREEN_WIDTH / 2.0, SCREEN_HEIGHT / 2.0), (SCREEN_WIDTH, SCREEN_HEIGHT)) # Draw missiles, ship, asteroids and explosions for missile in self.missiles: missile.draw(canvas) if self.lives > 0: self.my_ship.draw(canvas) for rock in self.rocks: rock.draw(canvas) for i in range(len(self.explosions) - 1, -1, -1): explosion = self.explosions[i] explosion.draw(canvas) explosion.update() if explosion.lifespan <= 0: # explosion finished del self.explosions[i] # Update ship self.my_ship.update() # Update missiles for i in range(len(self.missiles) - 1, -1, -1): missile = self.missiles[i] missile.update() if missile.lifespan <= 0: # missile disappear del self.missiles[i] else: # active missile for j in range(len(self.rocks) - 1, -1, -1): # Check collide with asteroids rock = self.rocks[j] if missile.collide(rock): # collide del self.missiles[i] del self.rocks[j] if not rock.little: # Divide in two little asteroids angle = vector_to_angle(missile.velocity) mvel = math.sqrt( (rock.velocity[0] * rock.velocity[0] + rock.velocity[1] * rock.velocity[1]) / 2.0) vel = list(angle_to_vector(angle - math.pi / 4)) vel[0] *= mvel vel[1] *= mvel little1 = Asteroid(rock.position, vel, rock.angle_velocity * 2, rock.num, True) vel = list(angle_to_vector(angle + math.pi / 4)) vel[0] *= mvel vel[1] *= mvel little2 = Asteroid(rock.position, vel, -rock.angle_velocity * 2, rock.num, True) while True: little1.position[0] += little1.velocity[0] little1.position[1] += little1.velocity[1] little2.position[0] += little2.velocity[0] little2.position[1] += little2.velocity[1] if not little1.collide(little2): break self.rocks.extend((little1, little2)) self.score += 1 if self.score % 10 == 0: # add a new bomb self.nb_bombs += 1 if self.sounds_active: self.medias.get_sound('bomb_extra').rewind() self.medias.get_sound('bomb_extra').play() if self.score % 50 == 0: # add a new live self.lives += 1 self.explosions.append( Sprite(rock.position, rock.velocity, 0, rock.angle_velocity, 'asteroid_explosion')) break # Update asteroids for i in range(len(self.rocks) - 1, -1, -1): rock = self.rocks[i] rock.update() if self.my_ship.collide(rock): # collide with ship del self.rocks[i] self.explosions.append( Sprite(rock.position, rock.velocity, 0, rock.angle_velocity, 'asteroid_collide_explosion')) self.live_explosions.append( Sprite((self.lives * 40, 40), (0, 0), -math.pi / 2, 0, 'live_explosion')) self.lives = max(0, self.lives - 1) if self.lives <= 0: # game over self.stop() self.explosions.append( Sprite(self.my_ship.position, self.my_ship.velocity, 0, self.my_ship.angle_velocity, 'ship_explosion')) if self.sounds_active: self.medias.get_sound('death').rewind() self.medias.get_sound('death').play() break else: if self.sounds_active: self.medias.get_sound('collide').rewind() self.medias.get_sound('collide').play() else: for j in range(0, i): other = self.rocks[j] if rock.collide(other): rock.position[0] = (rock.position[0] - rock.velocity[0]) % SCREEN_WIDTH rock.position[1] = (rock.position[1] - rock.velocity[1]) % SCREEN_HEIGHT other.position[0] = ( (other.position[0] - other.velocity[0]) % SCREEN_WIDTH) other.position[1] = ( (other.position[1] - other.velocity[1]) % SCREEN_HEIGHT) # Elastic collision (with radius*3 as mass) # https://en.wikipedia.org/wiki/Elastic_collision tmp_sum = (rock.radius + other.radius) * 3 tmp_diff = (rock.radius - other.radius) * 3 double = 2 * 3 * other.radius new_x = (float(tmp_diff * rock.velocity[0] + double * other.velocity[0]) / tmp_sum) new_y = (float(tmp_diff * rock.velocity[1] + double * other.velocity[1]) / tmp_sum) double = 2 * 3 * rock.radius other.velocity[0] = float(double * rock.velocity[0] - tmp_diff * other.velocity[0]) / tmp_sum other.velocity[1] = float(double * rock.velocity[1] - tmp_diff * other.velocity[1]) / tmp_sum rock.velocity[0] = new_x rock.velocity[1] = new_y # Display number of lives if self.started: info = self.img_infos['ship'] for i in range(self.lives): canvas.draw_image(self.medias.get_image('ship'), info.get_center(), info.get_size(), (40 + i * 40, 40), (40, 40), -math.pi / 2) # Draw and update live explosions for i in range(len(self.live_explosions) - 1, -1, -1): live_explosion = self.live_explosions[i] canvas.draw_image(live_explosion.image, live_explosion.image_center, live_explosion.image_size, live_explosion.position, (40, 40), -math.pi / 2) live_explosion.update() if live_explosion.lifespan <= 0: # explosion finished del self.live_explosions[i] # Display number of bombs if self.started and self.nb_bombs: info = self.img_infos['bomb'] for i in range(self.nb_bombs): canvas.draw_image(self.medias.get_image('bomb'), info.get_center(), info.get_size(), (40 + i * 40, 80), (20, 40), -math.pi / 2) # Display score size = 36 font = 'sans-serif' text1 = 'Score' width1 = frame.get_canvas_textwidth(text1, size, font) text2 = str(self.score) width2 = frame.get_canvas_textwidth(text2, size, font) canvas.draw_text(text1, (SCREEN_WIDTH - 22 - width1, 22 + size * 3.0 / 4), size, 'Gray', font) canvas.draw_text(text2, (SCREEN_WIDTH - 22 - width2, 22 + size * 7.0 / 4), size, 'Gray', font) canvas.draw_text(text1, (SCREEN_WIDTH - 20 - width1, 20 + size * 3.0 / 4), size, 'White', font) canvas.draw_text(text2, (SCREEN_WIDTH - 20 - width2, 20 + size * 7.0 / 4), size, 'White', font) # Draw splash screen if game not started if not self.started: size = self.img_infos['splash'].get_size() canvas.draw_image(self.medias.get_image('splash'), self.img_infos['splash'].get_center(), size, (SCREEN_WIDTH / 2.0, SCREEN_HEIGHT / 2.0), size) # Update and draw FPS (if started) fps.draw_fct(canvas) def load_medias(self): """ Load images and sounds and waiting all is loaded, the set the general draw handler. """ self.img_infos = { 'asteroid-1': ImageInfo((45, 45), (90, 90), 40), 'asteroid-2': ImageInfo((45, 45), (90, 90), 40), 'asteroid-3': ImageInfo((45, 45), (90, 90), 38), 'asteroid_explosion': ImageInfo((64, 64), (128, 128), 17, 24, True), 'asteroid_collide_explosion': ImageInfo((64, 64), (128, 128), 17, 24, True), 'bomb': ImageInfo((10, 10), (20, 20)), 'debris': ImageInfo((320, 240), (640, 480)), 'little-asteroid-1': ImageInfo((45, 45), (90, 90), 27, None, False, (60, 60)), 'little-asteroid-2': ImageInfo((45, 45), (90, 90), 27, None, False, (60, 60)), 'little-asteroid-3': ImageInfo((45, 45), (90, 90), 26, None, False, (60, 60)), 'live_explosion': ImageInfo((64, 64), (128, 128), 17, 24, True), 'missile': ImageInfo((5, 5), (10, 10), 3, 50), 'nebula': ImageInfo((400, 300), (800, 600)), 'ship': ImageInfo((45, 45), (90, 90), 35), 'ship_explosion': ImageInfo((64, 64), (128, 128), 17, 24, True), 'splash': ImageInfo((200, 150), (400, 300)) } def init(): """ Init the game after medias loaded. """ if SIMPLEGUICS2PYGAME: frame._set_canvas_background_image( self.medias.get_image('nebula')) self.medias._images['live_explosion'] = \ self.medias._images['ship_explosion'] for i in range(1, 4): self.medias._images['little-asteroid-' + str(i)] = \ self.medias._images['asteroid-' + str(i)] self.medias._sounds['asteroid_collide_explosion'] = \ self.medias._sounds['asteroid_explosion'] self.medias.get_sound('missile').set_volume(.5) self.my_ship = Ship((SCREEN_WIDTH / 2.0, SCREEN_HEIGHT / 2.0), (0, 0), -math.pi / 2, 'ship') frame.set_draw_handler(self.draw_and_update) frame.set_keydown_handler(keydown) frame.set_keyup_handler(keyup) frame.set_mouseclick_handler(click) if self.music_active: self.medias.get_sound('intro').play() self.loaded = True self.medias = Loader(frame, SCREEN_WIDTH, init) # Images by Kim Lathrop self.medias.add_image( 'http://commondatastorage.googleapis.com/codeskulptor-assets/lathrop/asteroid_blend.png', 'asteroid-1') self.medias.add_image( 'http://commondatastorage.googleapis.com/codeskulptor-assets/lathrop/asteroid_blue.png', 'asteroid-2') self.medias.add_image( 'http://commondatastorage.googleapis.com/codeskulptor-assets/lathrop/asteroid_brown.png', 'asteroid-3') self.medias.add_image( 'http://commondatastorage.googleapis.com/codeskulptor-assets/lathrop/explosion_alpha.png', 'asteroid_explosion') self.medias.add_image( 'http://commondatastorage.googleapis.com/codeskulptor-assets/lathrop/explosion_alpha2.png', 'asteroid_collide_explosion') self.medias.add_image( 'http://commondatastorage.googleapis.com/codeskulptor-assets/lathrop/shot3.png', 'bomb') self.medias.add_image( 'http://commondatastorage.googleapis.com/codeskulptor-assets/lathrop/debris2_blue.png', 'debris') self.medias.add_image( 'http://commondatastorage.googleapis.com/codeskulptor-assets/lathrop/shot2.png', 'missile') self.medias.add_image( 'http://commondatastorage.googleapis.com/codeskulptor-assets/lathrop/nebula_brown.png', 'nebula') self.medias.add_image( 'http://commondatastorage.googleapis.com/codeskulptor-assets/lathrop/double_ship.png', 'ship') self.medias.add_image( 'http://commondatastorage.googleapis.com/codeskulptor-assets/lathrop/explosion_orange.png', 'ship_explosion') self.medias.add_image( 'http://commondatastorage.googleapis.com/codeskulptor-assets/lathrop/splash.png', 'splash') # Sounds from http://www.sounddogs.com/ (not free) self.medias.add_sound( 'http://commondatastorage.googleapis.com/codeskulptor-assets/sounddogs/explosion.ogg', 'asteroid_explosion') self.medias.add_sound( 'http://rpg.hamsterrepublic.com/wiki-images/f/f4/StormMagic.ogg', 'bomb_explode') self.medias.add_sound( 'http://commondatastorage.googleapis.com/codeskulptor-demos/pyman_assets/extralife.ogg', 'bomb_extra') self.medias.add_sound( 'http://commondatastorage.googleapis.com/codeskulptor-demos/pyman_assets/eatedible.ogg', 'collide') self.medias.add_sound( 'http://rpg.hamsterrepublic.com/wiki-images/5/58/Death.ogg', 'death') self.medias.add_sound( 'http://commondatastorage.googleapis.com/codeskulptor-demos/pyman_assets/intromusic.ogg', 'intro') self.medias.add_sound( 'http://commondatastorage.googleapis.com/codeskulptor-assets/sounddogs/soundtrack.ogg', 'soundtrack') self.medias.add_sound( 'http://commondatastorage.googleapis.com/codeskulptor-assets/sounddogs/missile.ogg', 'missile') self.medias.add_sound( 'http://commondatastorage.googleapis.com/codeskulptor-assets/sounddogs/thrust.ogg', 'ship_thrust') self.medias.load() self.medias.wait_loaded() def rock_spawner(self): """ If the maximum is not reached then spawns a rock (not too close to the ship). """ if len(self.rocks) < 10: too_close = True def random_vel(): """ :return: int or float """ return (min(2, (random.random() * (self.score / 10.0 + 0.1))) * random.choice((-1, 1))) for _ in range(10): # try 10 times rock_pos = (random.randrange(0, SCREEN_WIDTH), random.randrange(0, SCREEN_HEIGHT)) rock_vel = (random_vel(), random_vel()) rock_ang_vel = random.choice( (-1, 1)) * (random.random() * 0.05 + 0.01) rock = Asteroid(rock_pos, rock_vel, rock_ang_vel, random.randint(1, 3)) too_close = False for rock2 in self.rocks: if rock2.collide(rock): too_close = True break too_close = (too_close or (self.my_ship.distance(rock) < (self.my_ship.radius + rock.radius) * 3)) if not too_close: break if not too_close: self.rocks.append(rock) def start(self): """ Start the game. """ if self.music_active: self.medias.get_sound('intro').rewind() self.medias.get_sound('soundtrack').play() self.keydown_left = False self.keydown_right = False self.lives = 3 self.nb_bombs = 0 self.score = 0 self.my_ship = Ship((SCREEN_WIDTH / 2.0, SCREEN_HEIGHT / 2.0), (0, 0), -math.pi / 2, 'ship') self.explosions = [] self.missiles = [] self.rocks = [] self.timer.start() self.rock_spawner() self.started = True def stop(self): """ Stop the game. """ self.timer.stop() self.nb_bombs = None self.missiles = [] self.rocks = [] self.started = False self.my_ship.stop() if self.music_active: self.medias.get_sound('soundtrack').rewind() self.medias.get_sound('intro').play()