def generate_corner_coordinates(self): interval = 120 # The angles between each corner # Calculating the angles (since polar coordinates are used), for each corner: a = self.angle aa = self.angle - interval aaa = self.angle - 2 * interval # converting 3 polar coordinates to cartesian: c=mt.cartesian(r=self.width/2,theta=a,tuple_new_origin=(self.x,self.y)) cc=mt.cartesian(r=self.height/2,theta=aa,tuple_new_origin=(self.x,self.y)) ccc=mt.cartesian(r=self.height/2,theta=aaa,tuple_new_origin=(self.x,self.y)) return c,cc,ccc
def generate_coordinates(self, given_radius, side_number): coordinates = [] internal_angles = 360 / side_number for i in range( side_number): #Generating a corner for each internal angle coordinates.append( mt.cartesian(given_radius, internal_angles * i + self.inner_angle, (self.x, self.y))) return coordinates
def update_position(self, delta_time): """Updating the poisition of the asteroid""" vel, angle_change = self.get_relative_change(delta_time) self.inner_angle += angle_change self.inner_angle = self.inner_angle % 360 self.x, self.y = mt.cartesian(vel, self.drift_angle, (self.x, self.y)) self.coordinates = self.generate_coordinates(self.radius, self.side_num) self.inner_coordinates = self.generate_coordinates( self.radius * (1 - self.border), self.side_num)
def update_position(self,controls_array,pressed_keys,delta_time,screen_width,screen_height): """Updates the position of the plane. The controls array is an array specifying the controls""" velocity=self.get_velocity(delta_time=delta_time)#get the velocity in this frame angle_dif=self.get_angle_change(delta_time) #Making sure the momentum of the ship cannot get infinitely big: if self.momentum>velocity*1.2: self.momentum=velocity*1.2 elif self.momentum>0.45: #we make sure that the momentum cannot go under 0.45 . If momentum falls under 0, # then the ship will start going backwards self.momentum-=0.001 self.x, self.y = mt.cartesian(self.momentum*1.2, self.momentum_angle, (self.x, self.y)) if pressed_keys[controls_array[0]]: self.angle-= angle_dif self.angle=self.angle%360 #we conver it to mod 360 so that the self.angle variable doesn't become # insanely big if pressed_keys[controls_array[1]]: self.angle += angle_dif self.angle=self.angle%360 #we conver it to mod 360 so that the self.angle variable doesn't become # insanely big if pressed_keys[controls_array[2]]and perf_counter()-self.last_hyper_space>=self.hyper_space_cooldown: #we go to hyperspace self.hyper_space(width=screen_width,height=screen_height) self.last_hyper_space=perf_counter() #reseting the hyperspace cooldown if pressed_keys[controls_array[3]] : self.x,self.y=mt.cartesian(velocity,self.angle,(self.x,self.y)) self.momentum+=0.004 self.momentum_angle=self.angle
def __init__(self, radius, x=None, y=None, color=(255, 255, 255), background_color=(0, 0, 0), velocity_interval=(30, 40), angle_change_per_second_interval=(20, 50), border=0.1, player_coordinate_tuple=(), side_num=8): self.radius = radius #Generating random points if no specific location is given:0 if x == None and y == None: #if not specified, then randomly generate: self.x, self.y = mt.cartesian( randint(self.radius * 6, self.radius * 20), uniform(0, 360)) else: #if specified, then generate at the specified coordinate self.x = x self.y = y self.color = color self.background_color = background_color self.drift_angle = uniform( 0, 360 ) #the angle must be a decimal. When we generate mass amounts of # asteroids with integer angles, then it gives an articifial impression self.velocity = uniform(velocity_interval[0], velocity_interval[1]) self.angle_change_per_second = uniform( angle_change_per_second_interval[0], angle_change_per_second_interval[1]) self.side_num = side_num self.border = border #Initializing side_num amount of corners: self.inner_angle = 0 self.coordinates = self.generate_coordinates(self.radius, self.side_num)
def draw(self, pygame, window, delta_time): pygame.draw.circle(window, self.color, (self.x, self.y), self.r) #this is the main bullet. #DRAWING THE BULLET TRAIL: trail_bullet_num = 4 velocity = self.get_velocity(delta_time) new_color = self.color newx, newy = self.x, self.y for i in range(trail_bullet_num): new_color = ( new_color[0] * 0.6, new_color[1] * 0.6, new_color[2] * 0.6, ) #creating a dimmer rgb color newx, newy = mt.cartesian(r=1.2 * velocity, theta=self.angle - 180, tuple_new_origin=(newx, newy)) pygame.draw.circle(window, new_color, (newx, newy), self.r) # this is the main bullet.
def update_position(self, delta_time): #convert everything to polar coordinates, with the bullet taken as the new origin. This way we can increase # the 'r' value without needing to do any calculations on what x and y will be. self.x, self.y = mt.cartesian( self.direction * self.get_velocity(delta_time), self.angle, (self.x, self.y))
def start_level(saucer_frequency, asteroid_num, alien_bullet_cooldown, big_side): global window, screen_size, width, height, score, player, bullet_color, bullet_cooldown bullets = [] # array of bullets to be stored asteroids = [] # array of asteroid objects in the game saucers = [] # array of ufo objects last_bullet_shot = perf_counter() # when the last bullet was shot run = True death_animation_asteroids = [ ] # asteroids who have died, but still need to play their animation border_dic = { 3: 0.19, 4: 0.17, 5: 0.14, 6: 0.12, 7: 0.1 } # dictionary of which side number gets how much border alien_bullets = [] # array of bullets shot by ufos # generating the initial round of asteroids: for i in range(asteroid_num): asteroids.append( asteroid(radius=30, player_coordinate_tuple=(player.x, player.y), side_num=big_side, velocity_interval=(50, 100), border=border_dic[5])) point_values = {big_side: 20, big_side - 1: 50, big_side - 2: 100} last_saucer = perf_counter() # when the last saucer was generated while run and player.lives > 0 and len(asteroids) > 0: start = perf_counter() pygame.time.wait(10) update_text("Score: " + str(score) + " Lives: " + str(player.lives), where=(140 + len(str(score)) * 10, 30)) for event in pygame.event.get(): if event.type == pygame.QUIT: pygame.quit() quit() break if event.type == pygame.VIDEORESIZE: height = pygame.display.get_window_size() width, height = height screen_size = (width, height) keys = pygame.key.get_pressed() #checking to see if spacebar is pressed, and the cooldown has passed if keys[pygame. K_x] and perf_counter() - last_bullet_shot >= bullet_cooldown: #initializing a bullet: #new coordinates generated so that the bullet matches the tip of the ship initx, inity = mt.cartesian(player.height, player.angle, (player.x, player.y)) bullets.append( bullet(initx, inity, player.angle, 1, color=bullet_color)) last_bullet_shot = perf_counter() #UPDATING AND DRAWING PLAYER: player.update_position( CONTROLS, #specifying controls pygame.key.get_pressed(), #which keys are pressed delta_time=perf_counter() - start, # timing how much time has passed screen_width=width, screen_height=height) player.fix_out_of_screen(screen_width=width, screen_height=height) player.draw(pygame, window) pygame.display.update() window.fill(background_color) #UPDATING AND DRAWING ALIEN BULLETS: for bul in alien_bullets: #The problem with the player's coordinates, is that the bullet is initialized at the back of the # ship. To fix this, we convert everything to polar coordinates, and increase the radius to match the tip of the ship. if ct.separating_axis_theorem(player.generate_corner_coordinates(), [(bul.x - bul.r, bul.y - bul.r), (bul.x + bul.r, bul.y + bul.r), (bul.x - bul.r, bul.y + bul.r), (bul.x + bul.r, bul.y - bul.r)]): #they have collided player.lives -= 1 player.x, player.y = width / 2, height / 2 alien_bullets.pop(alien_bullets.index(bul)) else: #they have not collided, keep going bul.update_position(delta_time=perf_counter() - start) bul.draw(pygame, window, perf_counter() - start) #Checking to see if the bullet is out of the frame: if bul.x + bul.r >= width or bul.x + bul.r <= 0: alien_bullets.pop(alien_bullets.index(bul)) elif bul.y + bul.r > height or bul.y + bul.r < 0: alien_bullets.pop(alien_bullets.index(bul)) #UPDATING AND DRAWING BULLETS: for b in bullets: #The problem with the player's coordinates, is that the bullet is initialized at the back of the # ship. To fix this, we convert everything to polar coordinates, and increase the radius to match the tip of the ship. b.update_position(delta_time=perf_counter() - start) b.draw(pygame, window, perf_counter() - start) #Checking to see if the bullet is out of the frame: if b.x + b.r >= width or b.x + b.r <= 0: bullets.pop(bullets.index(b)) elif b.y + b.r > height or b.y + b.r < 0: bullets.pop(bullets.index(b)) #UPDATING THE SAUCERS: if perf_counter( ) - last_saucer >= saucer_frequency: #checking the ufo cooldown last_saucer = perf_counter() saucers.append( ufo(pygame, (player.x + (width / 3)) % width, (player.y + (height / 3)) % height)) for u in saucers: #checking to see if the ufo's bullet cooldown is down: if perf_counter() - u.last_bullet_shot >= alien_bullet_cooldown: u.last_bullet_shot = perf_counter() #reset cooldown alien_bullets.append( u.generate_alien_bullet((player.x, player.y))) hit = False for b in bullets: if ct.separating_axis_theorem(u.coordinates(), [(b.x - b.r, b.y - b.r), (b.x + b.r, b.y + b.r), (b.x - b.r, b.y + b.r), (b.x + b.r, b.y - b.r)]): hit = True hit_bul = b break if hit: score += 200 if score % player.given_extra * 10000 == 0: #player.lives+=1 player.given_extra += 1 saucers.pop(saucers.index(u)) bullets.pop(bullets.index(hit_bul)) else: if ct.separating_axis_theorem( player.generate_corner_coordinates(), u.coordinates()): player.lives -= 1 player.x, player.y = width / 2, height / 2 u.update_position(perf_counter() - start) u.draw(pygame, window) if u.out_of_screen(screen_width=width, screen_height=height): saucers.pop(saucers.index(u)) # UPDATING AND DRAWING ASTEROIDS: for a in asteroids: # updated information: a.update_position(perf_counter() - start) a.draw(pygame, window) a.fix_out_of_screen(width, height) # checking to see if asteroid is hitting player: if ct.separating_axis_theorem( a.coordinates, player.generate_corner_coordinates()): player.lives -= 1 player.x, player.y = width / 2, height / 2 for b in bullets: # Checking to see if any bullet has hit any asteroid: if ct.radius_collision(a.x, a.y, a.radius, b.x, b.y, b.r): # BEFORE ANYTHING, WE GET RID OF THE BULLET. EACH BULLET CAN ONLY POP 1 ASTEROID bullets.pop(bullets.index(b)) if a.side_num > big_side - 2: # the asteroid splits into 2 child asteroids with 1 less side number, and slightly smaller radius child_1 = asteroid(radius=a.radius * 0.9, x=a.x, y=a.y, side_num=a.side_num - 1) child_2 = asteroid(radius=a.radius * 0.9, x=a.x, y=a.y, side_num=a.side_num - 1) child_2.drift_angle = 180 + child_1.drift_angle # They need to explode in different directions child_1.velocity = a.velocity + 20 # Children explode faster then their parent child_2.velocity = a.velocity + 20 child_1.border = border_dic[ child_1. side_num] # modifying their border according to their side number child_2.border = border_dic[child_2.side_num] asteroids.append(child_1) asteroids.append(child_2) else: # this is the last piece, we have killed the entire asteroid: pass # death_animation_asteroids.append(a) #the asteroid will play it's death animation (which is a bunch of # particles) score += point_values[a.side_num] asteroids.pop(asteroids.index( a)) # if they are colliding, we destroy the asteroid window.fill(background_color)