def draw(self, screen, work_rects=None): """Draw the map to the screen""" if work_rects is None: work_rects = [Rect(0,0,screen.get_width(),screen.get_height())] extra_things = collections.defaultdict(list) for (k,v) in self.map_to_draw.objects.items(): extra_things[k].extend(v) extra_things[self.map_coords(pygame.mouse.get_pos(), screen)].append(self.mouse_cursor) for i in range(self.map_to_draw.w): for j in range(self.map_to_draw.h): view_x = 32*i-32*j view_y = 16*i+16*j x, y = view_x - self.view_x + screen.get_width()//2, view_y-self.view_y + screen.get_height()//2 t = self.map_to_draw.terrain((i,j)) s = t.sprite s_pos = Rect(x-32,y+16-s.get_height(),s.get_width(),s.get_height()) if s_pos.collidelist(work_rects)>=0: screen.blit(s, s_pos) if (i,j) in extra_things: for t in extra_things[(i,j)]: if isinstance(t, pygame.Surface): s = t else: s = t.sprite screen.blit(s,(x-32,y+16-s.get_height()))
def test_collidelist(self): # __doc__ (as of 2008-08-02) for pygame.rect.Rect.collidelist: # Rect.collidelist(list): return index # test if one rectangle in a list intersects # # Test whether the rectangle collides with any in a sequence of # rectangles. The index of the first collision found is returned. If # no collisions are found an index of -1 is returned. r = Rect(1, 1, 10, 10) l = [Rect(50, 50, 1, 1), Rect(5, 5, 10, 10), Rect(15, 15, 1, 1)] self.assertEqual(r.collidelist(l), 1) f = [Rect(50, 50, 1, 1), (100, 100, 4, 4)] self.assertEqual(r.collidelist(f), -1)
def Explode(self): global Players # Determine if we have to remove any tile within our range. BRects = [ Rect(self.x + 32, self.y, 32, 32), Rect(self.x - 32, self.y, 32, 32), Rect(self.x, self.y + 32, 32, 32), Rect(self.x, self.y - 32, 32, 32)] for Tile in Map : if Tile.Breakable == False : continue TRect = Rect(Tile.x, Tile.y, 32, 32) if TRect.collidelist(BRects) != -1 : RandomPowerUp = Globals.PowerupType(random.choice(list(Globals.PowerupType))) if( not(RandomPowerUp == Globals.PowerupType.PW_NONE) ) : Map.append(MapObject(Tile.x,Tile.y,RandomPowerUp)) Map.remove(Tile) self.AdjustOwnerBombCount() for player in Players : PRect = Rect(player.x, player.y, 32, 32) if PRect.collidelist(BRects) != -1 or (player.x == self.x and player.y == self.y): # Player died. # Find the owner #if self.OwnerID == player.ID : #print("Player suicided.") #else : #print("Client ID ", self.OwnerID, " killed ", player.ID) #if self.OwnerID == NetInterface.ID : # GetMainPlayer().NumKills += 1 # print("YAY KILLED!") if player.ID == GetMainPlayer().ID : continue if not(player.Used) : continue player.Used = False print("Player died"); GetMainPlayer().NumKills += 1 NetInterface.PackAndWriteOp(Globals.NetworkOP.OP_DIED, player.ID.to_bytes(8,'little'),player.Address)
class Entity(object): ''' Entity base class for all the other entities to build upon. ''' def __init__(self, x, y, image, movement_speed, rotates = True, collides = True, wall_collides = True): ''' "x" and "y" should be ints. "image" should be a string with the IMAGES identifier "width_or_size" should either be an int denoting the width of the entity or a tuple containing both width and height in that order. In the latter case, height should be left empty ''' self.x = x self.y = y # Getting width and height from image file self.width, self.height = g.images[image].get_size() # Variables for checking if the entity should move. self.x_plus = False self.x_minus = False self.y_plus = False self.y_minus = False # Variables for checking if the entity has moved. self.old_x = x self.old_y = y # Set picture string self.image = image # The movement speed of the entity, specified by 1 / movement_speed # seconds for each pixel self.movement_speed = float(movement_speed) # Creates four rectangles for collision checking self.update_collision_rects() # Whether or not the entity collides with terrain self.collides = collides self.wall_collides = wall_collides # Whether or not the entity rotates when it changes direction self.rotates = rotates # The amount of degrees from facing down the unit should rotate and the angle of the last time # paint was called self.angle = 0 self.last_angle = 0 # The name in g.special_entity_list of the FollowingEntity following this entity. self.following_entity = None def update(self, delta_remainder): ''' Updates the entity location if any of the plus and minus variables are set to True "delta_remainder" should be the time since the last update in seconds. moves the enitity one pixel at the time if the delta_remainder is too large (Larger than 1 / movement_speed. if so, it subtracts 1 / movement_speed and uses that as the delta, because the entity shouldn't move more than one pixel per update because of collision detection) ''' # If the delta value (the time passed) is too large, make sure the player doesn't move more than one pixel. if self.movement_speed > 0: delta = 0 while delta_remainder > 0: if delta_remainder > (1 / self.movement_speed): delta = (1 / self.movement_speed) delta_remainder = (delta_remainder - delta) else: delta = delta_remainder delta_remainder = 0 # Variables for checking if the entity changed pixel prev_x = self.x prev_y = self.y # Move the entity in the direction the variables denote it should be. if self.x_plus: self.x += self.movement_speed * delta if self.x_minus: self.x -= self.movement_speed * delta if self.y_plus: self.y += self.movement_speed * delta if self.y_minus: self.y -= self.movement_speed * delta self.collision_check() if self.rotates: # Rotation logic, which direction is the entity facing and how many degrees should it rotate # Uses last angle if the entity is not moving if self.x_plus and not self.x_minus: if self.y_plus and not self.y_minus: self.angle = 45 elif self.y_minus and not self.y_plus: self.angle = 135 else: self.angle = 90 elif self.x_minus and not self.x_plus: if self.y_plus and not self.y_minus: self.angle = -45 elif self.y_minus and not self.y_plus: self.angle = -135 else: self.angle = -90 else: if self.y_plus and not self.y_minus: self.angle = 0 elif self.y_minus and not self.y_plus: self.angle = 180 else: self.angle = self.last_angle # Update the player if he's aiming in a new direction if self.angle != self.last_angle: g.force_update = True # Remember the angle until next time self.last_angle = self.angle def tick(self): ''' Dummy method for what happens every tick ''' pass def paint(self): ''' Paints the player on the screen ''' if self.rotates: # Create a key with the current entity string and the angle key = self.image if self.angle != 0: key = key + str(self.angle) # Check the images dict for a key with the current entity and rotation if g.images.has_key(key): image = g.images[key].get() else: # The images dict doesn't have the current sprite with that rotation, create it g.images[key] = Graphics(pygame.transform.rotate(g.images[self.image].get(), self.angle)) image = g.images[key].get() else: image = g.images[self.image].get() # Actually paint the object if float(int(self.angle / 90.0)) != self.angle / 90.0: # Compensate for rotated entities g.screen.blit(image, (int(self.x) - int(self.width/5.0), int(self.y) - int(self.height/5.0))) else: g.screen.blit(image, (int(self.x), int(self.y))) def has_moved(self, update=True): ''' Compares an old x and y value with the current one. If the value has changed, the unit has moved to another pixel and should be redrawn. update should be 1 if you want to update the checking to a new pixel and 0 if you don't returns True if the player has changed pixel and False if it hasn't ''' if self.old_x != int(self.x) or self.old_y != int(self.y): if update: self.old_x = int(self.x) self.old_y = int(self.y) return True else: return False def get_tile(self): ''' Returns the coordinates of tile the entity is currently on (x and y) ''' return int((self.x + self.width/2) / float(c.TILE_SIZE)), int((self.y + self.height/2) / float(c.TILE_SIZE)) def corner_in_tile(self, tile): ''' Checks if any of the entities corners are inside of the specified tile. "tile" should be a tiles.Tile object ''' # Get the corners of the entity corners = [(self.x, self.y), (self.x+self.width, self.y), (self.x, self.y+self.height), (self.x+self.width, self.y+self.height)] # And get rects for those corners corner_rects = [] for corner in corners: corner_rects.append(Rect(corner, (1, 1))) if tile.rect().collidelist(corner_rects) != -1: return True else: return False def update_collision_rects(self): ''' Method for creating four pygame Rect object along the sides of the entity for use in collision detection ''' self.col_right = Rect(self.x + self.width - 1, self.y + 1, 1, self.height - 2) self.col_left = Rect(self.x, self.y + 1, 1, self.height - 2) self.col_top = Rect(self.x + 1, self.y, self.width - 2, 1) self.col_bottom = Rect(self.x + 1, self.y + self.height - 1, self.width - 2, 1) def collision_check(self): ''' Method for checking if the entity has run into a tree or something and move it back a pixel if it has ''' if self.wall_collides: # Move the entity inside of the window (border collision) entity_rect = Rect(self.x, self.y, self.width,self.height) window_rect = Rect(0, 0, g.width * c.TILE_SIZE, g.height * c.TILE_SIZE) if not window_rect.contains(entity_rect): entity_rect.clamp_ip(window_rect) self.x = entity_rect.left self.y = entity_rect.top if self.collides: # Make sure collision rectangles are up to date self.update_collision_rects() # Get the tile the entity is standing on tile_pos = self.get_tile() checked_tiles = [] # Loop through a 3x3 tile square around the entity, to not check the entire map for i in range(tile_pos[0] - 1, tile_pos[0] + 2): for j in range(tile_pos[1] - 1, tile_pos[1] + 2): try: if c.IMAGES[g.map[i][j].type].collides: checked_tiles.append(g.map[i][j].rect()) except IndexError: # That index was apparently outside of the map pass except: raise # Check if each of the zones collides with any of the tiles if self.col_left.collidelist(checked_tiles) != -1: self.x += 1 if self.col_right.collidelist(checked_tiles) != -1: self.x -= 1 if self.col_bottom.collidelist(checked_tiles) != -1: self.y -= 1 if self.col_top.collidelist(checked_tiles) != -1: self.y += 1
def add_rect(self, new_rect: pygame.Rect): for sheet in Spritesheet.select(): rects = [pygame.Rect(t.x,t.y,t.width,t.height) for t in sheet.thumbnails] sheet_rect = pygame.Rect(0,0,sheet.height, sheet.width) for rect in rects: crects = rects.copy() crects.remove(rect) new_rect.topleft = rect.topright if new_rect.collidelist(crects) == -1: if sheet_rect.contains(new_rect): return sheet, new_rect new_rect.topleft = rect.bottomright if new_rect.collidelist(crects) == -1: if sheet_rect.contains(new_rect): return sheet, new_rect new_rect.topright = rect.topleft if new_rect.collidelist(crects) == -1: if sheet_rect.contains(new_rect): return sheet, new_rect new_rect.topright = rect.bottomleft if new_rect.collidelist(crects) == -1: if sheet_rect.contains(new_rect): return sheet, new_rect sheet = Spritesheet.create(height=DEFAULT_HEIGHT, width=DEFAULT_WIDTH) new_rect.topleft = (0, 0) return sheet, new_rect
def has_obstacle(self, other: GameObject, dx: int, dy: int) -> bool: tmp_tile_rect = Rect( other.tile_rect.left + dx, other.tile_rect.top + dy, other.tile_rect.width, other.tile_rect.height, ) if -1 != tmp_tile_rect.collidelist(self.obstacles): return True obstacle_rects = list( map(lambda sprite: sprite.tile_rect, self.obstacle_sprites)) return -1 != tmp_tile_rect.collidelist(obstacle_rects)
def is_collided(self): # Check if the bird touch ground if self.bird_height + self.bird_y + 1 >= self.base_y: self.distance_reward = 0 return True bird_bbox = Rect(self.bird_x, self.bird_y, self.bird_width, self.bird_height) pipe_boxes = [] for pipe in self.pipes: pipe_boxes.append( Rect(pipe["x_upper"], pipe["y_upper"], self.pipe_width, self.pipe_height)) pipe_boxes.append( Rect(pipe["x_lower"], pipe["y_lower"], self.pipe_width, self.pipe_height)) # Check if the bird's bounding box overlaps to the bounding box of any pipe if bird_bbox.collidelist(pipe_boxes) == -1: return False for i in range(2): cropped_bbox = bird_bbox.clip(pipe_boxes[i]) min_x1 = cropped_bbox.x - bird_bbox.x min_y1 = cropped_bbox.y - bird_bbox.y min_x2 = cropped_bbox.x - pipe_boxes[i].x min_y2 = cropped_bbox.y - pipe_boxes[i].y if np.any(self.bird_hitmask[ self.bird_index][min_x1:min_x1 + cropped_bbox.width, min_y1:min_y1 + cropped_bbox.height] * self.pipe_hitmask[i][min_x2:min_x2 + cropped_bbox.width, min_y2:min_y2 + cropped_bbox.height]): self.distance_reward = 0.9 / (self.diff_distance() + 1) return True return False
def is_wall(self, pos): # TODO only create a Rect if one hasn't been created already pos_rect = Rect(pos[0], pos[1], 1, 1) ret = pos_rect.collidelist(self.walls) if ret == -1: return False return True
def move_invaders(self, key, data): for item in self.text_indicators: item.set_top(item.get_top() - 2) for invader in self.invaders: invader.move(self.MOVE_INTERVAL, self.velocity) if (invader.item.get_top() > SCREEN_HEIGHT): self.remove_invader(invader) else: left = self.character.get_left() + self.data.collision.left top = self.character.get_top() + self.data.collision.top width = self.character.get_width( ) - self.data.collision.left - self.data.collision.right height = self.character.get_height( ) - self.data.collision.top - self.data.collision.bottom character = Rect(left, top, width, height) item = Rect(invader.get_left(), invader.get_top(), invader.get_width(), invader.get_height()) k = character.collidelist([item]) if k != -1: if invader.good: self.character_animation.footsteps_concrete_sound.stop( ) self.item_found_sound.play() self.character_animation.first_walking = True self.score += invader.points self.score_board.value.set_text(str(self.score)) self.top_layer.add(self.good_indicator) item = ItemText(invader.get_left(), invader.get_top(), self.font, 0, "+" + str(invader.points), h_align=2, v_align=2) self.text_indicators.append(item) self.top_layer.add(item) fade_out_item(item, True, self.GOOD_INDICATOR_INTERVAL) self.start_timer(3, self.GOOD_INDICATOR_INTERVAL, self.remove_good_indicator) else: self.stop_timer(1) self.stop_timer(2) self.game_over() return self.remove_invader(invader)
def main(): pygame.init() screen = pygame.display.set_mode((1024, 768)) pygame.display.set_caption("Rect Test") #Create a Rectangle #Obs.: will be mouse-controlled #optional: create a tuple for the rectangle's colour player_rect = Rect(0, 0, 100, 100) player_colour = (0, 255, 0) #Create a list of rectangles rect_list = [Rect(550, 100, 200, 200), Rect(150, 150, 350, 350), Rect(800, 600, 150, 150)] #optional: create a list of colours (should match rect #list length) colours = [(255, 255, 0), (255, 0, 255), ( 0, 255, 255)] #Create an extra rectangle for overlap detection result = Rect(0, 0, 0, 0) is_running = True #Game loop while is_running: for evt in pygame.event.get(): if evt.type == pygame.QUIT: is_running = False #Controlling the player rectangle with the mouse #(uncomment code below) player_rect.center = pygame.mouse.get_pos() #clip result rectangle: #result = player_rect.clip(rect_list[0]) #advanced: clip against a list result = player_rect.clip(rect_list[player_rect.collidelist(rect_list)]) #Render part screen.fill((0, 0, 127)) #Render rectangles: #1: Render player rectangle pygame.draw.rect(screen, player_colour, player_rect) #2: Render list of rectangles #optional: use a for loop to render them with the #same or different colours. If using a for loop, the #example code below should be adjusted accordingly for i in range(len(rect_list)): pygame.draw.rect(screen, colours[i], rect_list[i]) #If there is a collision, render it here #Alternative if statements: #if player_rect.collidelist(rect_list) > -1: #if result.width > 0 and result.height > 0: if result.width > 0 < result.height: pygame.draw.rect(screen, (255, 0, 0), result, 5) #Render loop end pygame.display.flip() #cleanup pygame.quit() sys.exit()
class Chromossome: def __init__(self, position, size, _range, cic=3, angl=[]): self.size = size self.initialp = position self.position = position self.xposition = (self.position[0] + self.size[0] // 2), (self.position[1] + self.size[1] // 2) self.rect = Rect(position, size) self.angles = [angles[randint(0, 7)] for i in range(cic)] if angl == [] else angl self._range = _range self.cic = cic self.cicles = -1 def crossover(self, other): i1 = randint(0, self.cic - 1) newchromo1 = Chromossome(self.initialp, self.size, self._range, self.cic, self.angles[:i1] + other.angles[i1:]) newchromo2 = Chromossome(self.initialp, self.size, self._range, self.cic, other.angles[:i1] + self.angles[i1:]) return newchromo1, newchromo2 def move(self, ang): if ang >= pi: if (type(tan(ang)) == float): self.rect.move_ip(-self._range, round(tan(ang) * (-self._range))) self.position = (self.position[0] - self._range, self.position[1] + round(tan(ang) * (-self._range))) else: self.rect.move_ip(0, -self._range) self.position = (self.position[0], self.position[1] - self._range) else: if type(tan(ang)) == float: self.rect.move_ip(self._range, round(tan(ang) * (self._range))) self.position = (self.position[0] + self._range, self.position[1] + round(tan(ang) * (self._range))) else: self.rect.move_ip(0, self._range) self.position = (self.position[0], self.position[1] + self._range) self.xposition = (self.position[0] + self.size[0] // 2), (self.position[1] + self.size[1] // 2) def mutate(self, p=0.03): if random() <= p: self.angles[randint(0, self.cic - 1)] = angles[randint(0, 7)] def getCicl(self, nzombies, zombieargs, dist): if self.cicles > -1: return initialp = self.position, self.xposition zs = [ Zombie(zombieargs[0], [zombieargs[1][0] + i, zombieargs[1][1] + dist * i], zombieargs[2]) for i in range(nzombies) ] k = 0 while True: for z in zs: z.move(self.xposition) self.move(self.angles[k]) k += 1 if ((self.rect.collidelist([z.rect for z in zs])) > -1) or ( self.xposition[0] >= 100 or self.xposition[1] >= 100) or ( self.xposition[0] <= 0 or self.xposition[1] <= 0): ##print(k) self.cicles = k break self.position, self.xposition = initialp
def obsToState3(obs): # possible values for f# # -1 = beyond edge # 0 = road # 1 = car # 2 = turtle/log # 3 = water # 4 = home frog_x = obs['frog_x'] frog_y = obs['frog_y'] # init all values to 0 f = np.zeros(25) # Check every rectangle within 5x5 of frog # Start with f0 (top left) left = frog_x - 64 top = frog_y - 64 w = h = 32 temp = Rect(left, top, w, h) # Check if frog is near water set in front to water if (frog_y <= 293): # initialize f0-f4 to waters f[0] = f[1] = f[2] = f[3] = f[4] = 3 if (frog_y <= 261): # initialize f5-f9 to waters f[5] = f[6] = f[7] = f[8] = f[9] = 3 # If frog in river, set behind to water if (frog_y <= 197): # set f15-19 to waters f[15] = f[16] = f[17] = f[18] = f[19] = 3 if (frog_y <= 165): # set f20-24 to waters f[20] = f[21] = f[22] = f[23] = f[24] = 3 for i in range(25): # Frog pos --> Skip this position if (i == 12): # update left accordingly left = left + 32 temp = Rect(left, top, w, h) continue # All other squares # Check edges if (top < 0 or top > 517 or left < 0 or left > 448): f[i] = -1 # Check if state reaches homes if (frog_y < kPlayYHomeLimit + 64): collideInd = temp.collidelist(obs['homeR']) if (collideInd != -1): # Theres a home in sight of frog # If home is not occupied, set square to home, else, set to water if (obs['homes'][collideInd] == 0): f[i] = 4 else: f[i] = 3 # Check if state reaches river if (frog_y < kPlayYRiverLimit + 64): collideInd = temp.collidelist(obs['rivers']) if (collideInd != -1): # Theres a log/turtle in sight of frog f[i] = 2 # Check cars collideInd = temp.collidelist(obs['cars']) if (collideInd != -1): # Theres a car in sight of frog f[i] = 1 # Update X/Y # Reset X and Y if gone too far if (i == 4 or i == 9 or i == 14 or i == 19): left = frog_x - 64 # Increment y top = top + 32 else: left = left + 32 # recalculate temp temp = Rect(left, top, w, h) return State3(f[0],f[1],f[2],f[3],f[4],f[5],f[6],f[7],f[8],f[9],f[10],f[11], \ f[13],f[14],f[15],f[16],f[17],f[18],f[19],f[20],f[21],f[22],f[23],f[24])
class Bullet(Sprite): All = {} def __init__(self, x, y, dx, dy): SOUND_SHOT.play() self.vx, self.vy = vx, vy = XY(dx, dy)*(10/math.hypot(dx, dy)) Sprite.__init__(self, y + 4*vy) self.x = x + 4*vx self.rect = Rect(0,0,5,5) self.bounces = 2 Bullet.All[self] = self def update(self): self.x += self.vx self.y += self.vy self.rect.center = self.x, self.y tankhit = self.rect.collidelist(Tank.All) if tankhit >= 0: Tank.All[tankhit].hit() self.explode() return if self.rect.collidelist(Wall.All) >= 0: if self.bounces: self.bounces -= 1 r = self.rect.copy() # Try horizontal bounce... bounce_x = self.x-self.vx r.centerx = bounce_x if r.collidelist(Wall.All) < 0: SOUND_BOUNCE.play() self.vx = -self.vx self.x = bounce_x self.rect = r return # Try vertical: bounce_y = self.y-self.vy r.center = self.x, bounce_y if r.collidelist(Wall.All) < 0: self.vy = -self.vy self.y = bounce_y self.rect = r SOUND_BOUNCE.play() return # Try both: if self.bounces: r.centerx = bounce_x if self.rect.collidelist(Wall.All) < 0: SOUND_BOUNCE.play() self.bounces -= 1 self.vx, self.vy = -self.vx, -self.vy self.x, self.y = bounce_x, bounce_y self.rect = r return self.explode() return r = self.rect.copy() self.rect.y = -999 # avoid self collision by going OOS nearby = r.inflate(10,10).collidedictall(Bullet.All) if nearby: for aoi in (r, r.move(-self.vx,-self.vy)): colliding = aoi.collidedict(dict(nearby)) if colliding: colliding[0].explode() self.explode() return self.rect = r # restore def explode(self): Explosion(10, (self.x, self.y)) del Bullet.All[self] self.dissapear() def draw(self): draw.circle(SCREEN, WHITE , ints(self.x-self.vx/3, (self.y-self.vy/3)/2-BULLET_HEIGHT), 3) draw.circle(SCREEN, WHITE, ints(self.x, self.y/2-BULLET_HEIGHT), 3) draw.line(SCREEN, BLACK, (self.x-1, self.y/2), (self.x+1, self.y/2))
class Tank(Sprite): All = [] def __init__(self, color, x, y): self.color = color self.x, self.y = x, y Sprite.__init__(self, y) Tank.All.append(self) self.bodies = load_multiimage('tank_body.png', 8, color) self.turrets = load_multiimage('tank_turret.png', 8, color) self.sx, self.sy = self.bodies[0].get_size() # size self.putface('happy') width = self.sx self.rect = Rect(x-width/2, y-width/2, width, width).inflate(-8,-8) self.heading = self.facing = 3 # SE self.sound = None self.mire = Mire(self.color, x, y) self.readyamo = 3 self.reloading = 0 # Controls: self.headto, self.fire, self.targetx, self.targety = None, 0, x, y def putface(self, face): self.faces = load_multiimage('memes/'+face+'8.png', 8, self.color) fw,fh = self.faces[0].get_size() self.faceoffset = XY((self.sx-fw)/2,16-fh) def dissapear(self): if self.sound: self.sound.stop() Sprite.dissapear(self) Tank.All.remove(self) #for t in self.trail: t.dissapear() def noise(self, sound): if self.sound != sound: if self.sound: self.sound.stop() self.sound = sound if sound: sound.play(-1) def update(self): if self.headto == self.heading: self.noise(SOUND_WALK) newxy = ( self.x + DIRECTIONS[self.heading][0] , self.y + DIRECTIONS[self.heading][1] ) self.rect.center = newxy # Check for obstacles: if self.rect.collidelist(Wall.All) != -1 or 1<len(self.rect.collidelistall(Tank.All)): self.rect.center = self.x, self.y else: self.x, self.y = newxy elif self.headto != None: self.noise(SOUND_TURN) if (self.headto+8-self.heading)&7 <= 4: self.heading += 1 else: self.heading -= 1 self.heading &= 7 else: self.noise(None) self.mire.aim(self.targetx, self.targety) dx,dy = self.targetx - self.x, self.targety - self.y self.facing = direction(dx, dy) if self.fire and self.readyamo: self.fire -= 1 self.readyamo -= 1 self.reloading = RELOAD_TIME # STRATEGY: Firing restarts reload Bullet(self.x, self.y, dx, dy) elif self.reloading: self.reloading -= 1 if not self.reloading: SOUND_RELOAD.play() self.readyamo += 1 if self.readyamo < MAX_BULLETS: self.reloading = RELOAD_TIME def render(self, xy): #draw.line(SCREEN, BLACK, (self.x-30, self.y/2), (self.x+30, self.y/2)) #draw.line(SCREEN, BLACK, (self.x, self.y/2-20), (self.x, self.y/2+20)) BLIT(self.bodies[self.heading], xy) BLIT(self.turrets[self.facing], xy) BLIT(self.faces[self.facing], self.faceoffset + xy) def draw(self): self.render(ints(self.x-self.sx/2,(self.y-self.sy-TANK_HEIGHT)/2)) def hit(self): Explosion(self.sx, self.rect.center) self.dissapear()
class Bullet: effects = None camera = None screen = None enemy = None objects = None explode = None hero = None houses = None bullet = None def __init__(self, x, y, weapon, fire_bullet, angle): self.damage = weapons[weapon]['damage'] self.radius = weapons[weapon]['radius'] self.bullet_speed = weapons[weapon]['speed'] self.color = (196, 196, 196) self.angle = angle if weapon == 'flamethrower': self.color = [196, 73, 16] self.flame_bull_time = 25 if fire_bullet: self.damage = 3 self.color = (255, 255, 0) self.weapon = weapon self.x, self.y = x, y self.rect = Rect(self.x - self.radius, self.y - self.radius, self.radius * 2, self.radius * 2) # Направление пули self.dx = self.dy = 0 if 90 < self.angle < 270: self.dx = -abs(cos(radians(self.angle)) * self.bullet_speed) elif (self.angle != 90) and (self.angle != 270): self.dx = abs(cos(radians(self.angle)) * self.bullet_speed) if 0 < self.angle < 180: self.dy = -abs(sin(radians(self.angle)) * self.bullet_speed) elif (self.angle != 0) and (self.angle != 180): self.dy = abs(sin(radians(self.angle)) * self.bullet_speed) # Эффекты if self.weapon == 'flamethrower': # Шлейф от огня Bullet.effects.append( Effect(self.x, self.y, self.angle, 100, 'fire_bullet_train', self)) elif self.weapon == 'launcher': # Эффект от рокеты Bullet.effects.append( Effect(self.x, self.y, self.angle, 500, 'rocket', self)) else: if fire_bullet: # Шлейф от огненной пули Bullet.effects.append( Effect(self.x, self.y, self.angle, 100, 'fire_bullet_train', self)) else: # Шлейф от обычной пули Bullet.effects.append( Effect(self.x, self.y, self.angle, 100, 'bullet_train', self)) def render(self): # Выход за пределы игры xx, yy = Bullet.camera.get_pos(self.x, self.y, True) if not (-self.radius < xx < SIZE[0] + self.radius) or not ( -self.radius < yy < SIZE[1] + self.radius): Bullet.bullet.remove(self) # Коллизия self.collision() # Перемещение self.x += self.dx self.y += self.dy self.rect.center = self.x, self.y # Огонь от огнемёта if self.weapon == 'flamethrower': self.flame_bull_time -= 1 if self.color[0] + 5 < 256: self.color[0] += 5 if self.color[1] + 5 < 256: self.color[1] += 5 if self.radius - 0.05 > 0: self.radius -= 0.05 if self.flame_bull_time <= 0: self.x = -200 self.dx = self.dy = 0 # Отображение if self.weapon != 'launcher': draw.circle(Bullet.screen, self.color, (xx, yy), round(self.radius)) def collision(self): collide_objects = Bullet.enemy + [ ob for ob in Bullet.objects if ob.Collide ] for n in Rect.collidelistall(self.rect, collide_objects): if collide_objects[n] in Bullet.enemy: if self.weapon == 'launcher': Bullet.explode.append(Explode(self.x, self.y)) weapons[Bullet.hero.weapon]['sound'].stop() if self.weapon != 'rifle': self.x = -200 self.dx = self.dy = 0 collide_objects[n].hp -= self.damage elif collide_objects[n] in Bullet.objects: if self.weapon == 'launcher': Bullet.explode.append(Explode(self.x, self.y)) weapons[Bullet.hero.weapon]['sound'].stop() self.x = -200 self.dx = self.dy = 0 for n in Bullet.houses: num = self.rect.collidelist(n.rect) if num != -1: if self.weapon == 'launcher': Bullet.explode.append(Explode(self.x, self.y)) weapons[Bullet.hero.weapon]['sound'].stop() self.x = -200 self.dx = self.dy = 0