Advertisement
ansakoy

RiceRocks

Nov 12th, 2014
105
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 12.21 KB | None | 0 0
  1. # RiceRocks
  2. import simplegui
  3. import math
  4. import random
  5.  
  6. # globals for user interface
  7. WIDTH = 800
  8. HEIGHT = 600
  9. DIMENSIONS = 2
  10. score = 0
  11. lives = 3
  12. time = 0.5
  13. started = False
  14.  
  15. class ImageInfo:
  16.     def __init__(self, center, size, radius = 0, lifespan = None, animated = False):
  17.         self.center = center
  18.         self.size = size
  19.         self.radius = radius
  20.         if lifespan:
  21.             self.lifespan = lifespan
  22.         else:
  23.             self.lifespan = float('inf')
  24.         self.animated = animated
  25.  
  26.     def get_center(self):
  27.         return self.center
  28.  
  29.     def get_size(self):
  30.         return self.size
  31.  
  32.     def get_radius(self):
  33.         return self.radius
  34.  
  35.     def get_lifespan(self):
  36.         return self.lifespan
  37.  
  38.     def get_animated(self):
  39.         return self.animated
  40.  
  41.    
  42. # art assets created by Kim Lathrop, may be freely re-used in non-commercial projects, please credit Kim
  43.    
  44. # debris images - debris1_brown.png, debris2_brown.png, debris3_brown.png, debris4_brown.png
  45. #                 debris1_blue.png, debris2_blue.png, debris3_blue.png, debris4_blue.png, debris_blend.png
  46. debris_info = ImageInfo([320, 240], [640, 480])
  47. debris_image = simplegui.load_image("http://commondatastorage.googleapis.com/codeskulptor-assets/lathrop/debris2_blue.png")
  48.  
  49. # nebula images - nebula_brown.png, nebula_blue.png
  50. nebula_info = ImageInfo([400, 300], [800, 600])
  51. nebula_image = simplegui.load_image("http://commondatastorage.googleapis.com/codeskulptor-assets/lathrop/nebula_blue.f2014.png")
  52.  
  53. # splash image
  54. splash_info = ImageInfo([200, 150], [400, 300])
  55. splash_image = simplegui.load_image("http://commondatastorage.googleapis.com/codeskulptor-assets/lathrop/splash.png")
  56.  
  57. # ship image
  58. ship_info = ImageInfo([45, 45], [90, 90], 35)
  59. ship_image = simplegui.load_image("http://commondatastorage.googleapis.com/codeskulptor-assets/lathrop/double_ship.png")
  60.  
  61. # missile image - shot1.png, shot2.png, shot3.png
  62. missile_info = ImageInfo([5,5], [10, 10], 3, 30)
  63. missile_image = simplegui.load_image("http://commondatastorage.googleapis.com/codeskulptor-assets/lathrop/shot2.png")
  64.  
  65. # asteroid images - asteroid_blue.png, asteroid_brown.png, asteroid_blend.png
  66. asteroid_info = ImageInfo([45, 45], [90, 90], 40)
  67. asteroid_image = simplegui.load_image("http://commondatastorage.googleapis.com/codeskulptor-assets/lathrop/asteroid_blue.png")
  68.  
  69. # animated explosion - explosion_orange.png, explosion_blue.png, explosion_blue2.png, explosion_alpha.png
  70. explosion_info = ImageInfo([64, 64], [128, 128], 17, 24, True)
  71. explosion_image = simplegui.load_image("http://commondatastorage.googleapis.com/codeskulptor-assets/lathrop/explosion_alpha.png")
  72.  
  73. # sound assets purchased from sounddogs.com, please do not redistribute
  74. soundtrack = simplegui.load_sound("http://commondatastorage.googleapis.com/codeskulptor-assets/sounddogs/soundtrack.mp3")
  75. missile_sound = simplegui.load_sound("http://commondatastorage.googleapis.com/codeskulptor-assets/sounddogs/missile.mp3")
  76. missile_sound.set_volume(.5)
  77. ship_thrust_sound = simplegui.load_sound("http://commondatastorage.googleapis.com/codeskulptor-assets/sounddogs/thrust.mp3")
  78. explosion_sound = simplegui.load_sound("http://commondatastorage.googleapis.com/codeskulptor-assets/sounddogs/explosion.mp3")
  79.  
  80. # helper functions to handle transformations
  81. def angle_to_vector(ang):
  82.     return [math.cos(ang), math.sin(ang)]
  83.  
  84. def dist(p,q):
  85.     return math.sqrt((p[0] - q[0]) ** 2+(p[1] - q[1]) ** 2)
  86.  
  87.  
  88. # Ship class
  89. class Ship:
  90.     def __init__(self, pos, vel, angle, image, info):
  91.         self.pos = [pos[0],pos[1]]
  92.         self.vel = [vel[0],vel[1]]
  93.         self.thrust = False
  94.         self.angle = angle
  95.         self.angle_vel = 0
  96.         self.image = image
  97.         self.image_center = info.get_center()
  98.         self.image_size = info.get_size()
  99.         self.image_center_thrust = [(self.image_center[0] + self.image_size[0]), self.image_center[1]]
  100.         self.radius = info.get_radius()
  101.    
  102.     def rotate_right(self):
  103.         self.angle_vel += 0.09
  104.        
  105.     def rotate_left(self):
  106.         self.angle_vel -= 0.09
  107.        
  108.     def rotate_stop(self):
  109.         self.angle_vel = 0
  110.            
  111.     def draw(self,canvas):
  112.         if self.thrust:
  113.             canvas.draw_image(self.image, self.image_center_thrust, self.image_size, self.pos, self.image_size, self.angle)
  114.         else:  
  115.             canvas.draw_image(self.image, self.image_center, self.image_size, self.pos, self.image_size, self.angle)
  116.  
  117.     def update(self):
  118.         self.pos[0] = (self.pos[0] + self.vel[0]) % WIDTH
  119.         self.pos[1] = (self.pos[1] + self.vel[1]) % HEIGHT
  120.         self.angle += self.angle_vel
  121.         friction = 0.01
  122.         for dim in range(DIMENSIONS):
  123.             self.vel[dim] *= 1 - friction
  124.         if self.thrust:
  125.             for dim in range(DIMENSIONS):
  126.                 self.vel[dim] += angle_to_vector(self.angle)[dim] / 10
  127.  
  128.     def shoot(self):
  129.         for_vec = angle_to_vector(self.angle)
  130.         mis_pos = list(self.pos)
  131.         mis_vel = list(self.vel)
  132.         for dim in range(DIMENSIONS):
  133.             mis_pos[dim] += for_vec[dim] * self.radius
  134.             mis_vel[dim] += for_vec[dim] * 12
  135.        
  136.         a_missile = Sprite(mis_pos, mis_vel, self.angle, 0, missile_image, missile_info, missile_sound)
  137.         missile_group.add(a_missile)
  138.    
  139.     def get_position(self):
  140.         return self.pos
  141.        
  142.    
  143. # Sprite class
  144. class Sprite:
  145.     def __init__(self, pos, vel, ang, ang_vel, image, info, sound = None):
  146.         self.pos = [pos[0],pos[1]]
  147.         self.vel = [vel[0],vel[1]]
  148.         self.angle = ang
  149.         self.angle_vel = ang_vel
  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.         self.lifespan = info.get_lifespan()
  155.         self.animated = info.get_animated()
  156.         self.age = 0
  157.         if sound:
  158.             sound.rewind()
  159.             sound.play()
  160.    
  161.     def draw(self, canvas):
  162.         if self.animated:
  163.             explosion_dim = [24, 1]
  164.             explosion_index = [self.age % explosion_dim[0], (self.age // explosion_dim[0]) % explosion_dim[1]]
  165.  
  166.             canvas.draw_image(self.image, [self.image_center[0] + explosion_index[0] * self.image_size[0],
  167.                                        self.image_center[1] + explosion_index[1] * self.image_size[1]],
  168.                                        self.image_size, self.pos, self.image_size, self.angle)          
  169.            
  170.         else:
  171.             canvas.draw_image(self.image, self.image_center, self.image_size, self.pos, self.image_size, self.angle)
  172.        
  173.            
  174.    
  175.     def update(self):
  176.         self.angle += self.angle_vel
  177.         self.pos[0] = (self.pos[0] + self.vel[0]) % WIDTH
  178.         self.pos[1] = (self.pos[1] + self.vel[1]) % HEIGHT
  179.         self.age += 1
  180.         if self.age >= self.lifespan:
  181.             return True
  182.    
  183.     def get_position(self):
  184.         return self.pos
  185.    
  186.     def collide(self, other_object):
  187.         zero_distance = self.radius + other_object.radius
  188.         distance = dist(other_object.get_position(), self.pos)
  189.         if distance <= zero_distance:
  190.             return True
  191.          
  192. def draw(canvas):
  193.     global time, lives, score, started, rock_group
  194.    
  195.     # animiate background
  196.     time += 1
  197.     wtime = (time / 4) % WIDTH
  198.     center = debris_info.get_center()
  199.     size = debris_info.get_size()
  200.     canvas.draw_image(nebula_image, nebula_info.get_center(), nebula_info.get_size(), [WIDTH / 2, HEIGHT / 2], [WIDTH, HEIGHT])
  201.     canvas.draw_image(debris_image, center, size, (wtime - WIDTH / 2, HEIGHT / 2), (WIDTH, HEIGHT))
  202.     canvas.draw_image(debris_image, center, size, (wtime + WIDTH / 2, HEIGHT / 2), (WIDTH, HEIGHT))
  203.  
  204.     # draw ship and sprites
  205.     my_ship.draw(canvas)
  206.  
  207.     if started:
  208.         process_sprite_group(rock_group, canvas)
  209.         process_sprite_group(missile_group, canvas)
  210.         process_sprite_group(explosion_group, canvas)
  211.    
  212.     # update ship and sprites
  213.         my_ship.update()
  214.         if group_collide(rock_group, my_ship):
  215.             lives -= 1
  216.             if lives <= 0:
  217.                 started = False
  218.                 rock_group = set([])
  219.                
  220.                 soundtrack.rewind()
  221.         score += group_group_collide(missile_group, rock_group)
  222.  
  223.     # draw game info
  224.     canvas.draw_text("Lives: " + str(lives), (WIDTH / 15.0, HEIGHT / 10), 30, "White")
  225.     canvas.draw_text("Score: " + str(score), (WIDTH - WIDTH / 5.0, HEIGHT / 10), 30, "White")
  226.    
  227.     # draw splash screen if not started
  228.     if not started:
  229.         canvas.draw_image(splash_image, splash_info.get_center(),
  230.                           splash_info.get_size(), [WIDTH / 2, HEIGHT / 2],
  231.                           splash_info.get_size())
  232.  
  233. # key handlers
  234. def key_down(key):
  235.     if key == simplegui.KEY_MAP['right']:
  236.         my_ship.rotate_right()
  237.     elif key == simplegui.KEY_MAP['left']:
  238.         my_ship.rotate_left()
  239.     elif key == simplegui.KEY_MAP['up']:
  240.         my_ship.thrust = True
  241.         ship_thrust_sound.play()
  242.     elif key == simplegui.KEY_MAP['space']:
  243.         my_ship.shoot()
  244.  
  245. def key_up(key):
  246.     if key == simplegui.KEY_MAP['right']:
  247.         my_ship.rotate_stop()
  248.     elif key == simplegui.KEY_MAP['left']:
  249.         my_ship.rotate_stop()
  250.     elif key == simplegui.KEY_MAP['up']:
  251.         my_ship.thrust = False
  252.         ship_thrust_sound.rewind()
  253.  
  254. # mouseclick handlers that reset UI and conditions whether splash image is drawn
  255. def click(pos):
  256.     global started, lives, score, my_ship
  257.     center = [WIDTH / 2, HEIGHT / 2]
  258.     size = splash_info.get_size()
  259.     inwidth = (center[0] - size[0] / 2) < pos[0] < (center[0] + size[0] / 2)
  260.     inheight = (center[1] - size[1] / 2) < pos[1] < (center[1] + size[1] / 2)
  261.     if (not started) and inwidth and inheight:
  262.         started = True
  263.         lives = 3
  264.         score = 0
  265.         my_ship = Ship([WIDTH / 2, HEIGHT / 2], [0, 0], 0, ship_image, ship_info)
  266.        
  267. # timer handler that spawns a rock    
  268. def rock_spawner():
  269.     global rock_group
  270.     pos = [random.randrange(WIDTH), random.randrange(HEIGHT)]
  271.     vel = [random.randrange(1, 3) * 0.01, random.randrange(1, 3) * 0.01]      
  272.     x_dir = random.randrange(2)
  273.     if x_dir:
  274.         vel[0] = - vel[0]
  275.     y_dir = random.randrange(2)
  276.     if y_dir:
  277.         vel[1] = - vel[1]
  278.     if score > 0:
  279.         for i in range(DIMENSIONS):
  280.             vel[i] *= score
  281.     ang_vel = random.randrange(1, 10) / 100.0
  282.     rot_dir = random.randrange(2)
  283.     if rot_dir:
  284.         ang_vel = - ang_vel
  285.     a_rock = Sprite(pos, vel, 0, ang_vel, asteroid_image, asteroid_info)
  286.     if dist(my_ship.get_position(), a_rock.pos) >= my_ship.radius * 3:
  287.         if started:
  288.             if len(rock_group) <= 12:
  289.                 rock_group.add(a_rock)
  290.                 soundtrack.play()
  291.                
  292. # update sprite groups
  293. def process_sprite_group(group, canvas):
  294.     for item in group:
  295.         item.update()
  296.         if item.update():
  297.             group.remove(item)
  298.         item.draw(canvas)
  299.    
  300. def group_collide(group, other_object):
  301.     global explosion_group
  302.     for item in set(group):
  303.         if item.collide(other_object):
  304.             exp_pos = item.pos
  305.             exp_vel = item.vel
  306.             exp_ang_vel = item.angle_vel
  307.             an_explosion = Sprite(exp_pos, exp_vel, 0, exp_ang_vel, explosion_image, explosion_info, explosion_sound)
  308.             explosion_group.add(an_explosion)
  309.             group.remove(item)
  310.             return True
  311.  
  312. def group_group_collide(group1, group2):
  313.     count = 0
  314.     for item in set(group1):
  315.         if group_collide(group2, item):
  316.             group1.discard(item)
  317.             count += 1
  318.     return count    
  319.              
  320. # initialize frame
  321. frame = simplegui.create_frame("Asteroids", WIDTH, HEIGHT)
  322.  
  323. # initialize ship and two sprites
  324. my_ship = Ship([WIDTH / 2, HEIGHT / 2], [0, 0], 0, ship_image, ship_info)
  325. rock_group = set([])
  326. missile_group = set([])
  327. explosion_group = set([])
  328.  
  329. # register handlers
  330. frame.set_draw_handler(draw)
  331. frame.set_keydown_handler(key_down)
  332. frame.set_keyup_handler(key_up)
  333. frame.set_mouseclick_handler(click)
  334.  
  335. timer = simplegui.create_timer(1000.0, rock_spawner)
  336.  
  337. # get things rolling
  338. timer.start()
  339. frame.start()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement