class Teammate(pygame.sprite.Sprite): def __init__(self, center, gs=None): pygame.sprite.Sprite.__init__(self) self.gs = gs self.image = pygame.image.load("imgs/tank2.png") self.orig_image = pygame.image.load("imgs/tank2.png") # tank is a tad smaller than gun bc collision detecting self.image = pygame.transform.scale(self.image, (40, 40)) self.orig_image = pygame.transform.scale(self.orig_image, (40, 40)) self.rect = self.image.get_rect() self.rect.center = center self.fire_x = 0 self.fire_y = 0 self.fire_timer = 0 self.tofire = False self.mx=0 self.my=0 self.gun = Gun(self.rect.center, self.gs) self.hold = False self.key = 0 def tick(self): if self.hold and self.key is not 0: self.move(self.key) dx = self.mx - self.rect.centerx dy = self.rect.centery - self.my if self.fire_timer != 0: self.fire_timer -= 1 if self.tofire == True and self.fire_timer == 0: self.fire_timer = 60 # can still come from center of tank since the # gun will be pointing in the same direction # ^^ jk because of collision detection fire_x, fire_y = self.mx, self.my angle = math.atan2(self.rect.centery-fire_y, fire_x-self.rect.centerx) pellet_center = (self.rect.centerx+math.cos(angle)*36,self.rect.centery-math.sin(angle)*36) pellet = Pellet(self, angle, pellet_center, self.gs) self.gs.pellets.append(pellet) ######################################################### # SOUND #if pygame.mixer.music.get_busy() == False: # pygame.mixer.music.load("screammachine.wav") # pygame.mixer.music.set_volume(1) # pygame.mixer.music.play() else: #pygame.mixer.stop() if dx != 0: self.gun.rotate(dx, dy) def move(self, keycode): """ Called when keydown is detected in main """ #self.gun.move(keycode) if keycode == 273 or keycode == 119: # trial if self.checkBlocks((0, -3)) is False: self.rect = self.rect.move(0, -3) self.gun.move((0,-3)) elif keycode == 274 or keycode == 115: if self.checkBlocks((0, 3)) is False: self.rect = self.rect.move(0, 3) self.gun.move((0, 3)) elif keycode == 275 or keycode == 100: if self.checkBlocks((3, 0)) is False: self.rect = self.rect.move(3, 0) self.gun.move((3, 0)) elif keycode == 276 or keycode == 97: if self.checkBlocks((-3, 0)) is False: self.rect = self.rect.move(-3, 0) self.gun.move((-3, 0)) def checkBlocks(self, movement): """ Return True if there is any overlap """ collide = False self.temp_rect = self.rect.move(movement[0], 0) for block in self.gs.blocks: if pygame.Rect.colliderect(self.temp_rect, block.rect): collide = True self.temp_rect = self.rect.move(0, movement[1]) for block in self.gs.blocks: if pygame.Rect.colliderect(self.temp_rect, block.rect): collide = True return collide def explode(self): if self.gs.tank1_life: self.gs.tank1_life = False center = deepcopy(self.rect.center) self.gs.explosions.append(Explosion(center, self.gs))
class Teammate(pygame.sprite.Sprite): def __init__(self, center, gs=None): pygame.sprite.Sprite.__init__(self) self.gs = gs self.image = pygame.image.load("imgs/tank2.png") self.orig_image = pygame.image.load("imgs/tank2.png") # tank is a tad smaller than gun bc collision detecting self.image = pygame.transform.scale(self.image, (40, 40)) self.orig_image = pygame.transform.scale(self.orig_image, (40, 40)) self.rect = self.image.get_rect() self.rect.center = center self.fire_x = 0 self.fire_y = 0 self.fire_timer = 0 self.tofire = False self.mx = 0 self.my = 0 self.gun = Gun(self.rect.center, self.gs) self.hold = False self.key = 0 def tick(self): if self.hold and self.key is not 0: self.move(self.key) dx = self.mx - self.rect.centerx dy = self.rect.centery - self.my if self.fire_timer != 0: self.fire_timer -= 1 if self.tofire == True and self.fire_timer == 0: self.fire_timer = 60 # can still come from center of tank since the # gun will be pointing in the same direction # ^^ jk because of collision detection fire_x, fire_y = self.mx, self.my angle = math.atan2(self.rect.centery - fire_y, fire_x - self.rect.centerx) pellet_center = (self.rect.centerx + math.cos(angle) * 36, self.rect.centery - math.sin(angle) * 36) pellet = Pellet(self, angle, pellet_center, self.gs) self.gs.pellets.append(pellet) ######################################################### # SOUND #if pygame.mixer.music.get_busy() == False: # pygame.mixer.music.load("screammachine.wav") # pygame.mixer.music.set_volume(1) # pygame.mixer.music.play() else: #pygame.mixer.stop() if dx != 0: self.gun.rotate(dx, dy) def move(self, keycode): """ Called when keydown is detected in main """ #self.gun.move(keycode) if keycode == 273 or keycode == 119: # trial if self.checkBlocks((0, -3)) is False: self.rect = self.rect.move(0, -3) self.gun.move((0, -3)) elif keycode == 274 or keycode == 115: if self.checkBlocks((0, 3)) is False: self.rect = self.rect.move(0, 3) self.gun.move((0, 3)) elif keycode == 275 or keycode == 100: if self.checkBlocks((3, 0)) is False: self.rect = self.rect.move(3, 0) self.gun.move((3, 0)) elif keycode == 276 or keycode == 97: if self.checkBlocks((-3, 0)) is False: self.rect = self.rect.move(-3, 0) self.gun.move((-3, 0)) def checkBlocks(self, movement): """ Return True if there is any overlap """ collide = False self.temp_rect = self.rect.move(movement[0], 0) for block in self.gs.blocks: if pygame.Rect.colliderect(self.temp_rect, block.rect): collide = True self.temp_rect = self.rect.move(0, movement[1]) for block in self.gs.blocks: if pygame.Rect.colliderect(self.temp_rect, block.rect): collide = True return collide def explode(self): if self.gs.tank1_life: self.gs.tank1_life = False center = deepcopy(self.rect.center) self.gs.explosions.append(Explosion(center, self.gs))
class tank(pygame.sprite.Sprite): def __init__(self, center, gs=None): pygame.sprite.Sprite.__init__(self) self.gs = gs self.image = pygame.image.load("imgs/tank1.png") self.orig_image = pygame.image.load("imgs/tank1.png") # tank is a tad smaller than gun bc collision detecting self.image = pygame.transform.scale(self.image, (40, 40)) self.orig_image = pygame.transform.scale(self.orig_image, (40, 40)) self.rect = self.image.get_rect() self.rect.center = center self.fire_x = 0 self.fire_y = 0 self.fire_timer = 0 self.tofire = False self.mx = 0 self.my = 0 self.life = True #attach gun, has to be a different part in order # to move around seemlessly (as opposed to a weird # rotating square) self.gun = Gun(self.rect.center, self.gs) self.hold = False self.key = 0 def tick(self): #allow for coasting w a variable set in gamespace if self.hold and self.key is not 0: self.move(self.key) # get movement dx = self.mx - self.rect.centerx dy = self.rect.centery - self.my if self.fire_timer != 0: self.fire_timer -= 1 if self.tofire == True and self.fire_timer == 0: self.fire_timer = 60 # can still come from center of tank since the # gun will be pointing in the same direction # ^^ jk because of collision detection fire_x = self.mx fire_y = self.my # move bullets to start outside of rect, so they # don't get stuck bc of collision detection angle = math.atan2(self.rect.centery-fire_y, fire_x-self.rect.centerx) pellet_center = (self.rect.centerx+math.cos(angle)*36,self.rect.centery-math.sin(angle)*36) pellet = Pellet(self, angle, pellet_center, self.gs) self.gs.pellets.append(pellet) else: # if we are moving, rotate gun # this class is completely referenced through # the tank class since it is not a real sprite, # jsut a sub sprite if dx != 0: self.gun.rotate(dx, dy) def move(self, keycode): """ Called when keydown is detected in main Moves objects according to key """ #self.gun.move(keycode) if keycode == 273 or keycode == 119: # trial if self.checkBlocks((0, -3)) is False: self.rect = self.rect.move(0, -3) self.gun.move((0,-3)) elif keycode == 274 or keycode == 115: if self.checkBlocks((0, 3)) is False: self.rect = self.rect.move(0, 3) self.gun.move((0, 3)) elif keycode == 275 or keycode == 100: if self.checkBlocks((3, 0)) is False: self.rect = self.rect.move(3, 0) self.gun.move((3, 0)) elif keycode == 276 or keycode == 97: if self.checkBlocks((-3, 0)) is False: self.rect = self.rect.move(-3, 0) self.gun.move((-3, 0)) def checkBlocks(self, movement): """ Return True if there is any overlap in tank and blocks, no explosion """ collide = False self.temp_rect = self.rect.move(movement[0], 0) for block in self.gs.blocks: if pygame.Rect.colliderect(self.temp_rect, block.rect): collide = True self.temp_rect = self.rect.move(0, movement[1]) for block in self.gs.blocks: if pygame.Rect.colliderect(self.temp_rect, block.rect): collide = True return collide def explode(self): """ Create a new explosion at the center of the collision Explosion is another sprite, gets sent to gs """ if self.gs.tank1_life: self.life = False center = deepcopy(self.rect.center) self.gs.explosions.append(Explosion(center, self.gs))
class Enemy(pygame.sprite.Sprite): def __init__(self, gs=None, center=None, angle=None, target=None, interval = None): """ Enemy class: sort of a hybrid between the user tank and the pellets. It is a tank, and the gun follows the user at all time. But it changes directions when it hits another enemy or a wall """ pygame.sprite.Sprite.__init__(self) self.gs = gs self.angle = angle self.target = target self.center = center self.image = pygame.image.load("imgs/tank3.png") self.orig_image = pygame.image.load("imgs/tank3.png") self.image = pygame.transform.scale(self.image, (40, 40)) self.orig_image = pygame.transform.scale(self.orig_image, (40, 40)) self.rect = self.image.get_rect() self.rect.center = self.center self.dx = math.cos(self.angle)*2 self.dy = math.sin(self.angle)*-2 self.exploded = False self.tofire = False self.gun = Gun(self.rect.center, self.gs) #random interval at which to fire at user self.fire_interval = interval self.fire_timer = 0 def tick(self): if not self.exploded: if not self.target.life: if self.target == self.gs.tank1: self.target = self.gs.teammate else: self.target = self.gs.tank1 # first check if direction needs to be changed self.checkBounce() # then move. will always move, unlike user self.move(self.target) self.fire_timer += 1 if self.fire_timer == self.fire_interval: #create pellets when the interval reaches # the time specified at creation self.fire_timer = 0 fire_x, fire_y = self.target.rect.center angle = math.atan2(self.rect.centery-fire_y, fire_x-self.rect.centerx) pellet_center = (self.rect.centerx+math.cos(angle)*36, self.rect.centery-math.sin(angle)*36) pellet = Pellet(self, angle, pellet_center, self.gs) self.gs.pellets.append(pellet) def move(self, tank1): """ Move tank at every tick in the same direction, until another object is hit or we die """ mx, my = tank1.rect.center dx = mx - self.rect.centerx dy = self.rect.centery - my self.rect = self.rect.move(self.dx, self.dy) self.gun.move((self.dx, self.dy)) if dx != 0: self.gun.rotate(dx, dy) def checkBounce(self): """ A check for if the motion needs to be changed due to a collision (a bounce) """ orig_center = self.rect.center self.temp_rect = self.rect.copy() horiz_coll = False vert_coll = False # loop through blocks and compare rectangles self.temp_rect = self.temp_rect.move(self.dx, 0) for block in self.gs.blocks: if pygame.Rect.colliderect(self.temp_rect, block.rect): horiz_coll = True # same for other enemies besides self for enemy in self.gs.enemies: if enemy is not self: if pygame.Rect.colliderect(self.temp_rect, enemy.rect): horiz_coll = True # repeat for vertical collisions self.temp_rect = self.rect.copy() self.temp_rect = self.rect.move(0, self.dy) for block in self.gs.blocks: if pygame.Rect.colliderect(self.temp_rect, block.rect): vert_coll = True for enemy in self.gs.enemies: if enemy is not self: if pygame.Rect.colliderect(self.temp_rect, enemy.rect): vert_coll = True # change direction if there is if horiz_coll: self.dx = -1 * self.dx if vert_coll: self.dy = -1 * self.dy if (horiz_coll or vert_coll): self.move(self.gs.tank1) self.move(self.gs.tank1) def explode(self): """ Function to create explosion object when enemy dies """ if not self.exploded: self.gs.enemies.remove(self) self.exploded = True expl_center = deepcopy(self.rect.center) self.gs.explosions.append(Explosion(expl_center, self.gs))