def backup_attack_loop(self): g = self.g self.image = self.orginalImage.subsurface((160, 0, 32, 32)) speed = self.walktimer self.walktimer += 1 if self.walktimer > 6: self.walktimer = 6 self.timer += 1 timergate = self.timer % 100 if timergate >= 80: if timergate == 80: self.face_the_player() if timergate == 85: Shot(g, self.direction, (self.rect.x + 16, self.rect.y + 8), 'shot8', 'enemy') self.walking = 0 else: self.walking = 1 if timergate % 100 == 0: self.face_the_player() dx = self.rect.x - g.player.rect.x if dx <40 and dx > -40: if self.dy == 10.0: self.dy = -10.0 if self.walking: self.rect.x += (1 - (self.direction * 2)) * speed framen = self.timer / 2 % 3 self.image = self.orginalImage.subsurface((32 + framen * 32, 0, 32, 32)) else: self.walktimer = 0 self.dy += .5 if self.dy > 10.0: self.dy = 10.0 self.rect.y += self.dy if self.rect.x < 416: self.direction = 0 self.image = pygame.transform.flip(self.image, self.direction, 0) # hitting the bullets and player s = Rect(self.rect) if s.colliderect (g.player.rect): g.player.touch(self) for b in g.bullets: if b.owner == 'player': drect = (b.rect.x + 30, b.rect.y ) if s.collidepoint(drect): b.destroy() self.health -= b.get_damage() e = Effect(self.g, 'health', (self.rect.x, self.rect.y)) e.healthchange = -b.get_damage() self.image = g.make_image_white(self.image)
def Boom(self, bulletList): tempList = bulletList PlaneBodyRect = Rect(self.x + 36, self.y, 100 - 36, 40) PlaneHeadRect = Rect(self.x, self.y, 100, 124 - 40) for bullet in tempList: bulletRect = Rect(bullet.x, bullet.y, 9, 21) print("子弹坐标" + str(bulletRect), "机头坐标" + str(PlaneHeadRect), "机身坐标" + str(PlaneBodyRect)) if bulletRect.colliderect(PlaneBodyRect) or bulletRect.colliderect( PlaneHeadRect): self.isBomb = True bulletList.remove(bullet)
def isCollided(self, rect): buffer = 7 # check if collided with bars for bar in self.barsCoordinates: barUpRect = Rect(bar[0], bar[1] - self.barVerticalGap - buffer, self.barWidth, self.barHeight) barDownRect = Rect(bar[0], bar[1] + buffer, self.barWidth, self.barHeight) if barDownRect.colliderect(rect) or barUpRect.colliderect(rect): return True # check if collided with ground if rect.bottom >= self.size[1] - self.groundHeight: return True return False
def handle_object_ball_collision(self, rect: Rect, ball: Ball, x_bound, y_bound): if not rect.colliderect(ball.rect): return top_collision = abs(rect.top - ball.rect.bottom) bottom_collision = abs(rect.bottom - ball.rect.top) right_collision = abs(rect.right - ball.rect.left) left_collision = abs(rect.left - ball.rect.right) actual_side_collision = min( [top_collision, bottom_collision, right_collision, left_collision]) if actual_side_collision == right_collision: if ball.direction.x < 0: ball.direction.x = -ball.direction.x ball.move(rect.right + x_bound - ball.rect.x, 0) elif actual_side_collision == bottom_collision: if ball.direction.y < 0: ball.direction.y = -ball.direction.y ball.move(0, rect.bottom + y_bound - ball.rect.y) elif actual_side_collision == left_collision: if ball.direction.x > 0: ball.direction.x = -ball.direction.x ball.move(rect.left - ball.rect.width - ball.rect.x, 0) elif actual_side_collision == top_collision: if ball.direction.y > 0: ball.direction.y = -ball.direction.y ball.move(0, rect.top + y_bound - ball.rect.y) print("i am colliding: {} with {}, direction: {}".format( rect, self.ball.rect, self.ball.direction))
def Boom(self, bulletList): tempList = bulletList PlaneBodyRect = Rect(self.x, self.y, 69, 89) for bullet in tempList: bulletRect = Rect(bullet.x, bullet.y, 22, 22) if bulletRect.colliderect(PlaneBodyRect): self.isBomb = True bulletList.remove(bullet)
class SimpleSprite(pygame.sprite.Sprite): _posx: Decimal = None _posy: Decimal = None width: int = None height: int = None image: pygame.Surface = None rect: Rect = None def __init__(self, posx: Union[Decimal, float, int], posy: Union[Decimal, float, int], path: str, *groups) -> None: super().__init__(*groups) self.image = pygame.image.load( os.path.join(os.getcwd(), 'example/assets', path)) self._posx = Decimal(posx) self._posy = Decimal(posy) self.image = pygame.transform.scale(self.image, (32, 32)) self.width = self.image.get_width() self.height = self.image.get_height() self.update() def get_position( self, as_int=False) -> Union[Tuple[Decimal, Decimal], Tuple[int, int]]: return ((int(self._posx), int(self._posy)) if as_int else (self._posx, self._posy)) def move_position(self, posx: Decimal, posy: Decimal) -> None: self._posx += posx self._posy += posy self.update() def set_position(self, posx: Decimal, posy: Decimal) -> None: self._posx = posx self._posy = posy self.update() def update(self) -> None: self.rect = Rect( int(self._posx) * self.width, int(self._posy) * self.height, self.width, self.height) def is_collided_with(self, sprite: 'SimpleSprite') -> bool: return self.rect.colliderect(sprite.rect)
class Tile(GameSprite): def __init__(self, x, y, sheet, kind, mgr): super(Tile, self).__init__(x, y, kind) self.mgr = mgr self.resourcemgr = mgr.resourcemgr self.sheet = sheet set_tile_stats(self) self.rect = Rect(x, y, self.tile_width, self.tile_height) self.area = self.mgr.areas[self.kind] self.flags = FLAGS.TILE def set_tile(self, kind): self.kind = kind self.area = self.mgr.areas[kind] def render(self, camera=None): if not camera: self.resourcemgr.screen.blit(self.mgr.image, self.rect, self.area) elif self.rect.colliderect(camera): pos = Rect(self.rect.x - camera.rect.x, self.rect.y - camera.rect.y, self.rect.w, self.rect.h) self.resourcemgr.screen.blit(self.mgr.image, pos, self.area)
def loop_hit_death(self, g, r, canbehit, canhitplayer): self.timer += 1 self.image = pygame.transform.flip(self.image, self.direction, 0) s = Rect(self.rect) if self.mode != 'death': if s.colliderect (g.player.rect): if canhitplayer: g.player.touch(self) if canbehit: for b in g.bullets: if b.owner == 'player': drect = (b.rect.x, b.rect.y) if s.collidepoint(drect): b.destroy() self.health -= b.get_damage() e = Effect(self.g, 'health', (self.rect.x, self.rect.y)) e.healthchange = -b.get_damage() if self.mode != 'ouch': self.birdhit.play() self.mode = 'ouch' self.btimer = 0 #k = Rect(b.rect) #k.x -= g.view.x #k.y -= g.view.y #pygame.draw.rect(g.screen, (0,255,255), k) #s.x -= g.view.x #s.y -= g.view.y #pygame.draw.rect(g.screen, (255,0,255), s) # dead if self.health <= 0: if self.mode != 'death': self.mode = 'death' self.btimer = 0
class CollisionObject(object): def __init__(self, label="Default", pos: Vector2D = Vector2D(0, 0), scale: Vector2D = Vector2D(0, 0), center: Vector2D = Vector2D(0, 0), colour: Colour = (0, 0, 0)): self.label = label self.pos: Vector2D = pos self.scale: Vector2D = scale self.center: Vector2D = center self.colour: Colour = colour self.visible = False global_pos: Vector2D = self.pos + self.center self.rect = Rect(global_pos.x, global_pos.y, self.scale.x, self.scale.y) def update(self): global_pos: Vector2D = self.pos + self.center self.rect = Rect(global_pos.x, global_pos.y, self.scale.x, self.scale.y) def draw(self, screen): if self.visible: pygame.draw.rect(screen, self.colour, self.rect, 5) def is_colliding(self, other): return self.rect.colliderect(other.rect) def is_colliding_any(self, others: list): others = [o.rect for o in others] return self.rect.collidelist(others) def is_colliding_all(self, others: list): others = [o.rect for o in others] return self.rect.collidelistall(others)
class AreaCamera(object): """ Base class for displaying maps. Not really featured, here, you should subclass it. """ def __init__(self, area, extent=None, tmxdata=None): self.area = area self.set_extent(extent) self.zoom = 1.0 self.avatars = [] # create a renderer for the map self.maprender = BufferedTilemapRenderer(tmxdata, self.extent.size) self.map_width = tmxdata.tilewidth * tmxdata.width self.map_height = tmxdata.tileheight*tmxdata.height self.center(self.extent.center) self.blank = True # load the children for child in self.area.getChildren(): child.load() # add the avatars for child in self.area.getChildren(): if isinstance(child, AvatarObject): child.avatar.update(0) # hack to re-init avatar self.avatars.append(child.avatar) def set_extent(self, extent): """ the camera caches some values related to the extent, so it becomes nessessary to call this instead of setting the extent directly. """ self.extent = Rect(extent) self.half_width = self.extent.width / 2 self.half_height = self.extent.height / 2 self.width = self.extent.width self.height = self.extent.height def update(self, time): self.maprender.update(None) [ a.update(time) for a in self.avatars ] def center(self, pos): """ center the camera on a pixel location. """ x, y = self.toSurface(pos) if self.map_width > self.width: if x < self.half_width: x = self.half_width elif x > self.map_width - self.half_width - 1: x = self.map_width - self.half_width - 1 else: x = self.map_width / 2 if self.map_height > self.height: if y < self.half_height: y = self.half_height elif y > self.map_height - self.half_height: y = self.map_height - self.half_height else: y = self.map_height / 2 self.extent.center = (x, y) self.maprender.center((x, y)) def clear(self, surface): raise NotImplementedError def draw(self, surface, origin=(0,0)): avatars = [] for a in self.avatars: aWidth, aHeight = a.get_size() d, w, h = a.getSize() x, y = self.toSurface(a.getPosition()) rect = Rect((x-(aWidth-w)/2, y-aHeight+d, aWidth, aHeight)) if self.extent.colliderect(rect): x, y = self.toScreen(a.getPosition()) x += origin[0] y += origin[1] rect = Rect((x-(aWidth-w)/2, y-aHeight+d, aWidth, aHeight)) avatars.append((a, rect)) onScreen = [ (a.image, r, 2) for a, r in avatars ] onScreen.sort(key=screenSorter) self.maprender.draw(surface, onScreen, origin) def toScreen(self, pos): """ Transform the world to coordinates on the screen """ x = pos[1] * self.zoom - self.extent.left y = pos[0] * self.zoom - self.extent.top # if there is a z value, just subtract it from y try: y -= pos[2] except: pass return x, y def toSurface(self, pos): """ Translate world coordinates to coordinates on the surface """ return pos[1], pos[0]
class Unit(GameSprite): def __init__(self, x, y, kind, resourcemgr, team, mgr): super(Unit, self).__init__(x, y, kind, resourcemgr) self.team = team self.mgr = mgr set_unit_stats(self) self.rect = Rect(int(x), int(y), self.w, self.h) self.set_areas() self.area = self.areas[SELECT.NORM] self.health = self.max_health self.attack_time = 0 self.shoot_time = 0 self.x_speed = 0.0 self.y_speed = 0.0 self.x_target = None self.y_target = None self.target = None self.selected = False self.moving = False self.lazy_attacking = False self.mouse_over = False self.active_sounds = [] self.camera_sounds = [] def set_areas(self): self.areas = {} self.areas[SELECT.NORM] = Rect(0, 0, self.w, self.h) self.areas[SELECT.MOVING] = Rect(self.w, 0, self.w, self.h) self.areas[SELECT.FIRING] = Rect(0, self.h, self.w, self.h) self.areas[SELECT.DUNNO] = Rect(self.w, self.h, self.w, self.h) def set_speed(self, x, y): self.x_target = x - (self.w / 2.0) self.y_target = y - (self.h / 2.0) self.moving = True if self.x_target > self.x: self.x_speed = self.speed if self.x_target < self.x: self.x_speed = -self.speed if self.y_target > self.y: self.y_speed = self.speed if self.y_target < self.y: self.y_speed = -self.speed def reset_speed(self): self.moving = False self.x_target = None self.y_target = None self.x_speed = 0.0 self.y_speed = 0.0 def hurt(self, atk): self.health -= atk def is_dead(self): return self.health <= 0 def play_sounds(self, camera): if self is self.mgr.active: for s in self.active_sounds: s.play() v = calculate_volume(self.rect, camera) if v > 0: for s in self.camera_sounds: s.set_volume(v) s.play() self.active_sounds = [] self.camera_sounds = [] def find_area(self): if self.moving: self.area = self.areas[SELECT.MOVING] elif self.shoot_time: if time.get_ticks() - self.shoot_time >= self.shoot_delay: self.shoot_time = 0 else: self.area = self.areas[SELECT.FIRING] else: self.area = self.areas[SELECT.NORM] def draw_select_box(self, camera): if self.selected: self.resourcemgr.screen.lock() dx = self.w / 10 dy = self.h / 10 draw.lines(self.resourcemgr.screen, BLUE, False, ( (self.rect.x - camera.rect.x + 3, self.rect.y - camera.rect.y + 3 + dy), (self.rect.x - camera.rect.x + 3, self.rect.y - camera.rect.y + 3), (self.rect.x - camera.rect.x + 3 + dx, self.rect.y - camera.rect.y + 3), ), 2) draw.lines(self.resourcemgr.screen, BLUE, False, ( (self.rect.x - camera.rect.x - 3 + self.w - dx, self.rect.y - camera.rect.y + 3), (self.rect.x - camera.rect.x - 3 + self.w, self.rect.y - camera.rect.y + 3), (self.rect.x - camera.rect.x - 3 + self.w, self.rect.y - camera.rect.y + 3 + dy), ), 2) draw.lines(self.resourcemgr.screen, BLUE, False, ( (self.rect.x - camera.rect.x - 3 + self.w, self.rect.y - camera.rect.y - 3 + self.h - dy), (self.rect.x - camera.rect.x - 3 + self.w, self.rect.y - camera.rect.y - 3 + self.h), (self.rect.x - camera.rect.x - 3 + self.w - dx, self.rect.y - camera.rect.y - 3 + self.h), ), 2) draw.lines(self.resourcemgr.screen, BLUE, False, ( (self.rect.x - camera.rect.x + 3 + dx, self.rect.y - camera.rect.y - 3 + self.h), (self.rect.x - camera.rect.x + 3, self.rect.y - camera.rect.y - 3 + self.h), (self.rect.x - camera.rect.x + 3, self.rect.y - camera.rect.y - 3 + self.h - dy), ), 2) self.resourcemgr.screen.unlock() def draw_health_bar(self, camera): if self.selected or self.mouse_over: black_rect = Rect(self.rect.x - camera.rect.x, self.rect.y - camera.rect.y, self.w, 6) red_rect = Rect(self.rect.x - camera.rect.x + 1, self.rect.y - camera.rect.y + 1, self.w - 2, 4) green_rect = Rect(self.rect.x - camera.rect.x + 1, self.rect.y - camera.rect.y + 1, (self.w - 2) * (self.health / float(self.max_health)), 4) self.resourcemgr.screen.lock() draw.rect(self.resourcemgr.screen, BLACK, black_rect, 0) draw.rect(self.resourcemgr.screen, RED, red_rect, 0) draw.rect(self.resourcemgr.screen, GREEN, green_rect, 0) self.resourcemgr.screen.unlock() def die(self, camera): if self.is_dead(): self.kill() v = calculate_volume(self.rect, camera) if v > 0: self.die_fx.set_volume(v) self.die_fx.play() def input(self, event, camera, mouse_rect, tilemgr): x, y = mouse.get_pos() x += camera.rect.x y += camera.rect.y self.mouse_over = self.rect.collidepoint(x, y) if event.type == MOUSEBUTTONUP: if event.button == MOUSE.LEFT: include = True if self.rect.colliderect(mouse_rect): if self.team != self.mgr.team and \ len(self.mgr.selected) > 0: include = False elif self.team == self.mgr.team: rem = [] for u in self.mgr.selected: if u.team != self.mgr.team: u.selected = False rem.append(u) self.mgr.selected.remove(*rem) if self.has_flag(FLAGS.STRUCT): for u in self.mgr.selected: if u.has_flag(FLAGS.DUDE): include = False break elif self.has_flag(FLAGS.DUDE): rem = [] for u in self.mgr.selected: if u.has_flag(FLAGS.STRUCT): u.selected = False rem.append(u) self.mgr.selected.remove(*rem) else: include = False if include: self.selected = True self.mgr.selected.add(self) else: self.selected = False self.mgr.selected.remove(self) elif self.team == self.mgr.team and event.button == MOUSE.RIGHT \ and self.selected: self.lazy_attacking = False found = False if self.has_flag(FLAGS.CAN_FIRE): for t in self.mgr.teams: if t == self.team: continue for u in self.mgr.units[t]: if u.rect.collidepoint(x, y): self.target = u found = True break if found: self.active_sounds.append(self.target_fx) break if self.has_flag(FLAGS.CAN_MOVE) and not found: self.set_speed(x, y) self.target = None self.active_sounds.append(self.move_fx) if self.has_flag(FLAGS.CAN_BUILD) and not found: unit = Unit(x - 25, y - 25, self.buildables[0], self.resourcemgr, self.team, self.mgr) if not unit.get_collisions(tilemgr.walls, *self.mgr.units.values()): self.mgr.add(unit) def logic(self, ticks, tilemgr): if self.has_flag(FLAGS.CAN_FIRE): if self.target is not None: if self.target.is_dead() or (self.lazy_attacking and distance( self.x, self.y, self.target.x, self.target.y) > self.range * 2.5): self.lazy_attacking = False self.target = None self.reset_speed() elif distance(self.x, self.y, self.target.x, self.target.y) <= self.range: if self.moving: self.reset_speed() if time.get_ticks() - self.attack_time >= \ self.attack_delay: self.shoot_time = time.get_ticks() self.attack_time = time.get_ticks() self.camera_sounds.append(self.fire_fx) self.target.hurt(self.atk) else: self.set_speed(self.target.x, self.target.y) elif not self.moving: found = False for t in self.mgr.teams: if t == self.team: continue for u in self.mgr.units[t]: if distance(self.x, self.y, u.x, u.y) <= \ self.range * 2: self.target = u self.lazy_attacking = True found = True break if found: break if self.has_flag(FLAGS.CAN_MOVE) and self.moving: x_part = self.x_speed * (ticks / 1000.0) y_part = self.y_speed * (ticks / 1000.0) x_old = self.x y_old = self.y rx_old = self.rect.x ry_old = self.rect.y x_delta = 0.0 y_delta = 0.0 if self.x_target: if abs(self.x_target - self.x) <= abs(x_part): x_delta = self.x_target - self.x elif abs(self.y_target - self.y) > abs(y_part): x_delta = x_part / sqrt(2.0) else: x_delta = x_part self.x += x_delta self.rect.x = int(self.x) if self.get_collisions(tilemgr.walls, *self.mgr.units.values()): self.x = x_old self.rect.x = rx_old if self.y_target: if abs(self.y_target - self.y) <= abs(y_part): y_delta = self.y_target - self.y elif abs(self.x_target - self.x) > abs(x_part): y_delta = y_part / sqrt(2.0) else: y_delta = y_part self.y += y_delta self.rect.y = int(self.y) if self.get_collisions(tilemgr.walls, *self.mgr.units.values()): self.y = y_old self.rect.y = ry_old if self.x_target == self.x and self.y_target == self.y: self.reset_speed() def render(self, camera=None): self.find_area() if not camera: self.resourcemgr.screen.blit(self.image, self.rect, self.area) self.draw_select_box(camera) self.draw_health_bar(camera) elif self.rect.colliderect(camera): pos = Rect(self.rect.x - camera.rect.x, self.rect.y - camera.rect.y, self.rect.w, self.rect.h) self.resourcemgr.screen.blit(self.image, pos, self.area) self.draw_select_box(camera) self.draw_health_bar(camera)
def Notify(self, event): if isinstance(event, TickEvent): ### GAME IS PREPARING if self.state == Game.STATE_PREPARING: self.Start() ### GAME IS RUNNING elif self.state == Game.STATE_RUNNING: # handle existing charactors for c in self.charactors: if c.radius == 0: self.evManager.Post(CharactorImplodeEvent(c)) if ((event.tick % c.speed) == 0): c.radius -= 1 c.sprite.Shrink(c.radius) # check if is time to add new charactor to game board if (event.tick % self.interval == 0) and self.bubbles > 0: self.AddCharactor() self.bubbles -= 1 elif (self.bubbles == 0): self.evManager.Post(NextLevelRequest()) elif (self.player.score > self.highscore): self.highscore = self.player.score if (self.gotHighscore == False): self.gotHighscore = True self.evManager.Post(HighscoreEvent()) elif isinstance(event, NextLevelRequest): self.level += 1 self.bubbles = self.initialbubbles + (3 * self.level) if (self.interval >= 200): self.interval -= 20 elif (self.interval < 200 and self.interval >= 100): self.interval -= 10 elif (self.interval < 100 and self.interval >= 10): self.interval -= 5 if (self.level % 3 == 0): self.lives += 1 elif isinstance(event, CharactorImplodeEvent): # here we count the amount of implodes (this is a BAD thing. we # want the bubbles to be blasted!) self.lives -= 1 self.RemoveCharactor(event.charactor) self.evManager.Post(CharactorSpriteRemoveRequest(event.charactor)) if self.lives == 0: self.Stop() elif isinstance(event, PauseEvent): if self.state == Game.STATE_RUNNING: self.state = Game.STATE_PAUSED else: self.state = Game.STATE_RUNNING elif isinstance(event, MouseClickRequest): if self.state == Game.STATE_RUNNING: pos = event.event.pos ptrRect = Rect(pos, (5,5)) for c in self.charactors: if ptrRect.colliderect(c.sprite.rect): # bubble burst self.player.score += (10+(self.level-1)*5) self.RemoveCharactor(c) self.evManager.Post(CharactorSpriteRemoveRequest(c)) break elif isinstance(event, GameResetEvent): self.Reset()
def advance_frame(input_get=pygame.event.get): global PLATFORMS, HATS, SPIKES, SPRINGS, ENEMIES, _ENEMIES, FLAGS, CHEESE, BACK, SPAWN global X, Y, x_vel, y_vel, DOOR, HAT, STATE, CROUCH, mov, hub, DIR global counter, dframe, IGT, endcard plats = [] allplats = [] for pos, dim, idx in PLATFORMS: allplats.append(Rect(pos, (dim[0]*32, dim[1]*32))) if isnear(pos, dim): plats.append(Rect(pos, (dim[0]*32, dim[1]*32))) # update counters/clock counter += 1 dframe = (dframe + 1) % 12 IGT += CLOCK.tick(30) # draw update screen adjust_scroller() SCREEN.blit(get_screen(), (0, 0)) SCREEN.blit(get_HUD(), (0, 0)) pygame.display.update() # evaluate input jmp = 0 door = 0 for e in input_get(): if e.type == QUIT or e.type == KEYDOWN and e.key == K_ESCAPE: quit() if e.type == KEYDOWN: if e.key == K_LEFT: mov = max(mov - 1, -1) if e.key == K_RIGHT: mov = min(mov + 1, 1) if e.key == K_DOWN: CROUCH = min(CROUCH+1, 1) if e.key == K_SPACE: jmp += 1 if e.key == K_UP: door = True if e.type == KEYUP: if e.key == K_LEFT: mov = min(mov+1, 1) if e.key == K_RIGHT: mov = max(mov-1, -1) if e.key == K_DOWN: CROUCH = max(CROUCH-1, 0) # change state, update movement JUMP = _JUMP * 2 if HAT == "baseball" else _JUMP if STATE == "dmg": if counter == 1: sounds["death"].stop() sounds["death"].play() if counter < 10: return STATE = "stand" X, Y = SPAWN x_vel, y_vel = 0, 0 HAT = None ENEMIES = deepcopy(_ENEMIES) elif jmp and (STATE in ["stand", "run0", "run1", "slide", "wall"] or HAT == "propeller"): sounds["jump"].stop() sounds["jump"].play() if HAT == "propeller": y_vel = JUMP if STATE == "wall": y_vel = JUMP DIR *= -1 x_vel = max(SPEED * DIR, x_vel) if DIR > 0 else min(SPEED * DIR, x_vel) else: STATE = "squat" counter = 0 elif STATE == "squat": if counter >= 3: y_vel = JUMP elif CROUCH: STATE = "crouch" elif mov and STATE not in ['crouch']: if DIR == mov: x_vel = max(SPEED * DIR, x_vel) if DIR > 0 else min(SPEED * DIR, x_vel) elif not x_vel or abs(x_vel) <= 3: DIR = mov if (x_vel > 0 and mov < 0) or (x_vel < 0 and mov > 0): STATE == "slide" elif x_vel == 0: STATE = "stand" else: STATE = "slide" if mov and not STATE in ["run0", "run1", "crouch", "squat"]: if ((x_vel > 0 and mov < 0) or (x_vel < 0 and mov > 0)): STATE = "slide" else: STATE = "run0" counter = 0 if STATE.startswith("run") and counter >= 5: STATE = "run" + str((int(STATE[-1]) + 1) % 2) counter = 0 if y_vel < 0: STATE = "jump0" if y_vel > 0: STATE = "jump1" # friction and gravity if x_vel and not STATE.startswith("jump"): x_vel += friction if x_vel < 0 else -1 y_vel += grav if STATE in ["jump1", "run0", "run1", "stand", "slide"] and HAT == "sombraro" and not CROUCH: y_vel = 0 # animate relevent actors for spring in SPRINGS: if spring[3]: spring[3] -= 1 # enemy logic remove = [] for i in range(len(ENEMIES)): pos, name, d, f , c = ENEMIES[i] if not isnear(pos): continue c += 1 if name == "bone": if c % 2: f = (f + 1) % 2 pos = (pos[0] + BONESPEED, pos[1]) if d == 0 else (pos[0] - BONESPEED, pos[1]) if c > 50: remove.append(i) if name == "skeleton": if abs(pos[0] - X) < 410: if f == 0: d = 0 if X > pos[0] else 1 if c >= 8 and f == 0: f = 1 elif c >= 30 and f == 1: sounds["throw"].stop() sounds["throw"].play() f = 2 ENEMIES.append( [pos, 'bone', d, 0, 0] ) elif c > 40: f, c = 0, 0 else: f, c = 0, 0 if name == "zombie": if c % 4 == 0 and abs(pos[0] - X) < 512: hitbox = Rect((pos[0]+8, pos[1]), (32, 64)) if d == 0: footbox = Rect((pos[0] + 32 + ZOMBIESPEED, pos[1] + 64), (10, 10)) else: footbox = Rect((pos[0] - ZOMBIESPEED, pos[1]+64), (10, 10)) if hitbox.collidelist(allplats) == -1: d = 0 if X > pos[0] else 1 f = (f + 1) % 2 pos = (pos[0] + ZOMBIESPEED, pos[1]) if d == 0 else (pos[0] - ZOMBIESPEED, pos[1]) if hitbox.collidelist(allplats) != -1 or footbox.collidelist(allplats) == -1: pos = (pos[0] - ZOMBIESPEED*2, pos[1]) if d == 0 else (pos[0] + ZOMBIESPEED*2, pos[1]) if name == "snake": hitbox = Rect(pos, (64, 16)) if c % 4 == 0: f = (f + 1) % 2 pos = (pos[0] + SNAKESPEED, pos[1]) if d == 0 else (pos[0] - SNAKESPEED, pos[1]) if hitbox.collidelist(allplats) != -1: d = (d + 1) % 2 pos = (pos[0] + SNAKESPEED*2, pos[1]) if d == 0 else (pos[0] - SNAKESPEED*2, pos[1]) if name == "ghost": d = 0 if X > pos[0] else 1 if (d == 1 and DIR == 1) or (d == 0 and DIR == -1): f = 1 else: f = 0 if abs(pos[0] - X) + abs(pos[1] - Y) < 800 and f == 0: if abs(pos[0] - X) > 30: x = -1 if X < pos[0] else 1 else: x = 0 if abs(pos[1] - Y) > 30: y = -1 if Y < pos[1] else 1 else: y = 0 pos = (pos[0]+x, pos[1]+y) ENEMIES[i] = [pos, name, d, f, c] for i in remove[::-1]: ENEMIES.pop(i) # hit detection - platforms hitbox = Rect((X, Y), (32, 64)) if STATE != "crouch" else Rect((X, Y+32), (32, 32)) checklist = plats if hitbox.collidelist(checklist) != -1: STATE = "dmg" return if x_vel: while hitbox.move(x_vel, 0).collidelist(checklist) != -1: if STATE.startswith("jump"): STATE = "wall" x_vel += 1 if x_vel < 0 else -1 if y_vel: while hitbox.move(0, y_vel).collidelist(checklist) != -1: y_vel += 1 if y_vel < 0 else -1 if x_vel and y_vel: while hitbox.move(x_vel, y_vel).collidelist(checklist) != -1: y_vel += 1 if y_vel < 0 else -1 x_vel += 1 if x_vel < 0 else -1 # hats checklist = [Rect(pos, (46, 46)) for pos, hat in HATS] i = hitbox.collidelist(checklist) if i != -1: HAT = HATS[i][1] # flags checklist = [Rect(pos, (46, 64)) for pos in FLAGS] i = hitbox.collidelist(checklist) if i != -1: SPAWN = FLAGS[i] # spikes and enemies checklist = [] for pos, d in SPIKES: if not isnear(pos): continue if d == 0: checklist += [Rect((pos[0]+8, pos[1]), (16, 16)), Rect((pos[0], pos[1]+16), (32, 16))] elif d == 1: checklist += [Rect((pos[0], pos[1]+8), (16, 16)), Rect((pos[0]+16, pos[1]), (16, 32))] elif d == 2: checklist += [Rect((pos[0], pos[1]), (32, 16)), Rect((pos[0]+8, pos[1]+16), (16, 16))] elif d == 3: checklist += [Rect((pos[0], pos[1]), (16, 32)), Rect((pos[0]+16, pos[1]+8), (32, 16))] for pos, name, d, f, c in ENEMIES: if not isnear(pos): continue if name in ["bone", "ghost"]: checklist.append(Rect(pos, (32, 32))) elif name == "snake": checklist.append(Rect(pos, (64, 16))) else: checklist.append(Rect(pos, (32, 64))) i = hitbox.collidelist(checklist) if i != -1: STATE = "dmg" counter = 0 # springs checklist = [Rect(pos, (48, 48)) for pos, d, s, f in SPRINGS] i = hitbox.collidelist(checklist) if i != -1: if SPRINGS[i][3] != 10: sounds["spring"].stop() sounds["spring"].play() SPRINGS[i][3] = 10 if SPRINGS[i][1] == 0: y_vel = 0 - SPRINGS[i][2] elif SPRINGS[i][1] == 2: y_vel = SPRINGS[i][2] elif SPRINGS[i][1] == 3: DIR = 1 x_vel = SPRINGS[i][2] elif SPRINGS[i][1] == 1: DIR = -1 x_vel = -1 * SPRINGS[i][2] # cheese checklist = [] for pos, idx in CHEESE: if idx == 3: checklist.append(Rect(pos, (64, 64))) else: checklist.append(Rect(pos, (32, 32))) i = hitbox.collidelist(checklist) if i != -1: sounds["get"].stop() sounds["get"].play() if not CHEESE[i][1] == 3: INV.append(CHEESE.pop(i)) else: n = H end = True while end: CLOCK.tick(30) if n >= 0: n -= 10 SCREEN.blit(get_screen(), (0, 0)) SCREEN.blit(endcard, (0, n)) pygame.draw.rect(SCREEN, (200, 200, 200), Rect((380, n + 530), (256, 104))) SCREEN.blit(HEL64.render(str(IGT // 60000) +":"+ ("0" + str(IGT // 1000 % 60))[-2:], 0, (0, 0, 0)), (400, n + 550)) pygame.display.update() for e in pygame.event.get(): if e.type == QUIT or e.type == KEYDOWN and e.key == K_ESCAPE: quit() if e.type == KEYDOWN: if e.key == K_LEFT: mov += -1 if e.key == K_RIGHT: mov += 1 if e.key == K_DOWN: CROUCH += 1 if e.key == K_SPACE and n <= 0: end = False load_level(hublvl) hub=True if e.type == KEYUP: if e.key == K_LEFT: mov -= -1 if e.key == K_RIGHT: mov -= 1 if e.key == K_DOWN: CROUCH -= 1 # door if hub: doorlist = [Rect((256+(i*256), 64), (64, 64)) for i in range(len(LEVELS))] di = hitbox.collidelist(doorlist) # enter door if door and (hitbox.colliderect(Rect(DOOR, (64, 64))) or (hub and di != -1 and len(INV)>=needs[di] )): sounds["door"].stop() sounds["door"].play() n = 2 if not hub: X, Y = DOOR[0] + 16, DOOR[1] adjust_scroller() STATE = "jump1" while n < 980: surf = rotate(get_screen(), n) SCREEN.blit(surf, ((W-surf.get_width())//2, (H - surf.get_height())//2)) n += n // 2 CLOCK.tick(30) pygame.display.update() for e in pygame.event.get(): if e.type == QUIT or e.type == KEYDOWN and e.key == K_ESCAPE: quit() if e.type == KEYDOWN: if e.key == K_LEFT: mov += -1 if e.key == K_RIGHT: mov += 1 if e.key == K_DOWN: CROUCH += 1 if e.type == KEYUP: if e.key == K_LEFT: mov -= -1 if e.key == K_RIGHT: mov -= 1 if e.key == K_DOWN: CROUCH -= 1 if hub and di != -1: load_level(LEVELS[di]) hub = False else: load_level(hublvl) hub = True # apply final calculated movement X += x_vel Y += y_vel
class AreaCamera(object): """ Base class for displaying maps. Not really featured, here, you should subclass it. """ def __init__(self, area, rect, tmxdata=None): rect = Rect(rect) self.rect = rect self.area = area self.set_extent(rect) self.avatars = [] # create a renderer for the map self.maprender = BufferedTilemapRenderer(tmxdata, rect) self.map_width = tmxdata.tilewidth * tmxdata.width self.map_height = tmxdata.tileheight * tmxdata.height self.center(self.extent.center) self.blank = True # load the children for child in self.area.getChildren(): child.load() # add the avatars for child in self.area.getChildren(): if isinstance(child, AvatarObject): child.avatar.update(0) # hack to re-init avatar self.avatars.append(child.avatar) def set_extent(self, extent): """ the camera caches some values related to the extent, so it becomes nessessary to call this instead of setting the extent directly. """ self.extent = Rect(extent) self.half_width = self.extent.width / 2 self.half_height = self.extent.height / 2 self.width = self.extent.width self.height = self.extent.height self.zoom = 1.0 def update(self, time): self.maprender.update(None) [a.update(time) for a in self.avatars] def center(self, pos): """ center the camera on a pixel location. """ x, y = self.toSurface(pos) if self.map_width > self.width: if x < self.half_width: x = self.half_width elif x > self.map_width - self.half_width - 1: x = self.map_width - self.half_width - 1 else: x = self.map_width / 2 if self.map_height > self.height: if y < self.half_height: y = self.half_height elif y > self.map_height - self.half_height: y = self.map_height - self.half_height else: y = self.map_height / 2 self.extent.center = (x, y) self.maprender.center((x, y)) def clear(self, surface): raise NotImplementedError def draw(self, surface): avatars = [] for a in self.avatars: aWidth, aHeight = a.get_size() d, w, h = a.getSize() x, y = self.toSurface(a.getPosition()) rect = Rect( (x - (aWidth - w) / 2, y - aHeight + d, aWidth, aHeight)) if self.extent.colliderect(rect): x, y = self.toScreen(a.getPosition()) x += self.rect.left y += self.rect.top rect = Rect((x - (aWidth - w) / 2, y - aHeight + d * 2, aWidth, aHeight)) avatars.append((a, rect)) onScreen = [(a.image, r, 2) for a, r in avatars] onScreen.sort(key=screenSorter) return self.maprender.draw(surface, onScreen) def toScreen(self, pos): """ Transform the world to coordinates on the screen """ x = pos[1] * self.zoom - self.extent.left y = pos[0] * self.zoom - self.extent.top # if there is a z value, just subtract it from y try: y -= pos[2] except: pass return x, y def toSurface(self, pos): """ Translate world coordinates to coordinates on the surface """ return pos[1], pos[0]
def rects_intersect(r1: Rect, r2: Rect): return r1.colliderect(r2)
class RectPlatform: # If tag is a powerup, this indicates which one it should drop, # Also indicates whether a ball should bounce of the surface or not tag = "" droppedAlready = False # if the platform has pwoerup this indicates if its already dropped # The original image before scaling to fit originalImage = None # The color to display if an image is not provided color = None # Image to blit on the gamesurface img = None # position of the platform xPos = 0 yPos = 0 # size dimensions of the platform width = 1 height = 1 # surface that the plaform should be displayed on mainSurface = None # colliders used for objects to detect collisions with the platform collideTopRect = None collideBottomRect = None collideLeftRect = None collideRightRect = None fullRect = None # used main more bullets to check if they should be destroy debug = False # Game displays the colliders above if this is true # initialize the platform def __init__(self, surface: pygame.Surface, x, y, width, height, tag: str = "platform", image: pygame.image = None, color: tuple = (255, 0, 0)): # set some variables that were inputted self.tag = tag self.xPos = x self.yPos = y self.width = width self.height = height self.mainSurface = surface self.color = color self.originalImage = image self.changeImageSize( ) # change the image size to match the size of the platform self.setRects( ) # set the colliders of the platforms based on the fed positional/dimensional arguments # Used to set the colliders of the platform def setRects(self): # for top and bottom collisions self.collideTopRect = Rect(self.xPos + 5, self.yPos, self.width - 10, 30) self.collideBottomRect = Rect(self.xPos + 5, self.yPos + self.height - 20, self.width - 10, 20) # for side collisions self.collideLeftRect = Rect(self.xPos, self.yPos + 10, 30, self.height - 10) self.collideRightRect = Rect(self.xPos + self.width - 30, self.yPos + 10, 30, self.height - 10) # used mainly for bullet collisions self.fullRect = Rect(self.xPos, self.yPos, self.width, self.height) # display the platform on the surface it was initialized with or a second provided surface def display( self, surface=None ): # if you don't want to display on the gameSurface, use the surface arguement if surface == None: blitSurface = self.mainSurface # set gameSurface as the blitsurface if not new surface provided else: blitSurface = surface # If new surface is provided change the blitSurface to the new surface if self.img != None: blitSurface.blit( self.img, (self.xPos, self.yPos)) # if an image was provided, display it if self.debug: # display the colliders if the debug variable is set true pygame.draw.rect(blitSurface, (0, 255, 0), self.collideTopRect, 1) pygame.draw.rect(blitSurface, (0, 255, 0), self.collideBottomRect, 1) pygame.draw.rect(blitSurface, (0, 255, 0), self.collideLeftRect, 1) pygame.draw.rect(blitSurface, (0, 255, 0), self.collideRightRect, 1) # used to change position of the surface def setPos(self, x, y): # set position self.xPos = x self.yPos = y # reset colliders self.setRects() # used to change the size of the surface def setSize(self, width, height): # change the dimensions self.width = width self.height = height # rescale the image to fit the new dimensions self.changeImageSize() # reset the colliders self.setRects() # used to scale the image to fit the platform def changeImageSize(self): # if an orignal image exists, scale the image to display using it if self.originalImage is not None: self.img = pygame.transform.smoothscale(self.originalImage, (self.width, self.height)) # Used to check top collision def checkTopCollide(self, rect: Rect): if self.collideTopRect.colliderect( rect): # check collision with inputted rect using top collider return True return False # Used to check left collision def checkLeftCollide(self, rect: Rect): if self.collideLeftRect.colliderect( rect ): # check collision with inputted rect using left collider return True return False # Used to check right collision def checkRightCollide(self, rect: Rect): if self.collideRightRect.colliderect( rect ): # check collision with inputted rect using right collider return True return False # Used to check bottom collision def checkBottomCollide(self, rect: Rect): if self.collideBottomRect.colliderect( rect ): # check collision with inputted rect using bottom collider return True return False
class Cell(): def __init__(self, parent): self.parent = parent self.rect = pygame.Rect(0, 0, 0, 0) self.rect_rel = pygame.Rect(0, 0, 0, 0) self.move_offset_x = 0 self.move_offset_y = 0 self.input_xy = OrderedDict() self.output_xy = OrderedDict() self.inputs = OrderedDict() self.outputs = [] self.output_cache = {} self.input_cache = {} self.res = {} self.name = "cell" self.fcs = "cell" self.drawable = False self.border = Rect(0,0,0,0) self.need_redraw = False self.need_body_update = False self.zoom = False def click(self): pass def add_input(self, name): self.inputs[name] = False def add_output(self, name): self.outputs.append(name) self.res[name] = 0 def update_rect(self): self.rect.w = self.parent.canvas.style["d_width"] h = max((len(self.inputs), len(self.outputs))) self.rect.h = self.parent.canvas.style["d_line"] * h if len(self.inputs) > 1: self.rect.w += self.parent.canvas.style["d_input"] if len(self.outputs) > 1: self.rect.w += self.parent.canvas.style["d_output"] self.rect_rel = Rect(self.rect) self.rect_rel.x = 0 self.rect_rel.y = 0 self.update_io_xy() def update_io_xy(self): for pin in self.inputs: i = self.inputs.keys().index(pin) x = self.rect.x y = int(self.rect.y + self.parent.canvas.style["d_line"] * (i + 0.5)) self.input_xy[pin] = [x, y] for pin in self.outputs: i = self.outputs.index(pin) x = self.rect.x + self.rect.w y = int(self.rect.y + self.parent.canvas.style["d_line"] * (i + 0.5)) self.output_xy[pin] = [x, y] self.parent.canvas.request_io_redraw() def get_input_rect(self, pin): i = self.inputs.keys().index(pin) x = 0 y = self.parent.canvas.style["d_line"] * i w = self.parent.canvas.style["d_input"] h = self.parent.canvas.style["d_line"] return pygame.Rect((x, y, w, h)) def get_output_rect(self, pin): i = self.outputs.index(pin) x = self.rect.w - self.parent.canvas.style["d_output"] y = self.parent.canvas.style["d_line"] * i w = self.parent.canvas.style["d_output"] h = self.parent.canvas.style["d_line"] return pygame.Rect((x, y, w, h)) def middle_offset(self): self.move_offset_x = self.rect.w / 2 self.move_offset_y = self.rect.h / 2 def set_offset(self, x, y): self.move_offset_x = x self.move_offset_y = y def clear_offset(self): self.move_offset_x = 0 self.move_offset_y = 0 def set_pos(self, x, y): self.rect.x = x - self.move_offset_x self.rect.y = y - self.move_offset_y self.update_io_xy() self.request_redraw() def clear_input(self, name): self.inputs[name] = False def assign_input(self, name, in_cell, in_pin): if name in self.inputs: self.inputs[name] = [in_cell, in_pin] def assign_free_input(self, in_cell, in_pin): for pin in self.inputs: if self.inputs[pin] == False: self.assign_input(pin, in_cell, in_pin) return def parse_cfg(self, arr): for i in range(len(arr) - 3): name = arr[3 + i] conn = self.parent.find_cell_pin(name) self.assign_free_input(*conn) def get_params(self): p = [] p.append("%dx%d" % (self.rect.x, self.rect.y)) for k in self.inputs: if self.inputs[k] is not False: o, o_pin = self.inputs[k] p.append("%s.%s" % (o.name, o_pin)) else: p.append("LOW.Y") return p def parse(self, arr): self.name = arr[0] self.fcs = arr[1] self.parse_cfg(arr) self.update_rect() self.request_update_body() try: x,y = map(int, arr[2].split("x")) self.set_pos(x, y) except: self.set_pos(0, 0) def reset(self): self.res = {} for pin in self.outputs: self.res[pin] = 0 def clear_io_cache(self): self.input_cache = {} self.output_cache = {} def calc(self, pin): return 0 def tick(self): for i in self.outputs: self.res[i] = self.calc(i) def output(self, pin): return self.res[pin] def input(self, pin): if self.inputs[pin] is False: return 0 in_obj, in_pin = self.inputs[pin] return in_obj.output(in_pin) def update(self): self.update_rect() self.request_update_body() def request_update_body(self): self.need_body_update = True self.parent.request_update() self.request_redraw() def update_body(self, state = None): rect = Rect(0, 0, self.rect.w, self.rect.h) self.surface = self.parent.mk_surface(self.rect) if state is None: color = "c_fill" else: if state: color = "c_high" else: color = "c_low" self.parent.draw_rect(self.surface, self.parent.canvas.style[color], rect) self.parent.draw_rect(self.surface, self.parent.canvas.style["c_border"], rect, 2) if len(self.inputs) > 1: in_rect = Rect(0, 0, self.parent.canvas.style["d_input"], self.rect.h) self.parent.draw_rect(self.surface, self.parent.canvas.style["c_border"], in_rect, 1) if len(self.outputs) > 1: a = self.parent.canvas.style["d_output"] out_rect = Rect(self.rect.w - a, 0, a, self.rect.h) self.parent.draw_rect(self.surface, self.parent.canvas.style["c_border"], out_rect, 1) if len(self.inputs) > 1: for c in self.inputs: rect = self.get_input_rect(c) self.parent.draw_text(self.surface, c, rect) if len(self.outputs) > 1: for c in self.outputs: rect = self.get_output_rect(c) self.parent.draw_text(self.surface, c, rect) self.request_redraw() def request_redraw(self): self.need_redraw = True def draw(self): if self.need_redraw: if self.need_body_update: self.update_body() self.need_body_update = False self.parent.blit(self.surface, self.rect) self.need_redraw = False def draw_io(self): for c in self.inputs: state = self.input(c) if c in self.input_cache: if self.input_cache[c] == state: continue self.input_cache[c] = state pos_xy = self.input_xy[c] self.parent.draw_circle(pos_xy, state) if self.inputs[c] is not False: in_obj, in_pin = self.inputs[c] if not isinstance(in_obj, Invisible): start = pos_xy end = in_obj.output_xy[in_pin] self.parent.draw_line(start, end, state) for c in self.outputs: state = self.output(c) if c in self.output_cache: if self.output_cache[c] == state: continue self.output_cache[c] = state pos_xy = self.output_xy[c] self.parent.draw_circle(pos_xy, state) def check_output_collision(self, pos): for pin in self.outputs: if pin in self.output_xy: out_pos = self.output_xy[pin] p = self.parent.canvas.style["d_point"] rect = pygame.Rect(out_pos[0] - p, out_pos[1] - p, p * 2, p * 2) if (rect.collidepoint(pos)): return pin return False def check_input_collision(self, pos): for pin in self.inputs: if pin in self.input_xy: out_pos = self.input_xy[pin] p = self.parent.canvas.style["d_point"] rect = pygame.Rect(out_pos[0] - p, out_pos[1] - p, p * 2, p * 2) if (rect.collidepoint(pos)): return pin return False def check_input_line_collision(self, pos): for p in self.inputs: if self.inputs[p]: obj, pin = self.inputs[p] if isinstance(obj, Invisible): continue start = self.input_xy[p] end = obj.output_xy[pin] #basic rect TODO offset = self.parent.canvas.style["d_line_col"] x = min((start[0], end[0])) - offset y = min((start[1], end[1])) - offset w = abs(start[0] - end[0]) + offset * 2 h = abs(start[1] - end[1]) + offset * 2 basic = Rect(x, y, w, h) if basic.collidepoint(pos): dx = end[0] - start[0] dy = end[1] - start[1] if dx == 0 and dy == 0: return False if abs(dx) < abs(dy): k = float(dx) / float(dy) x = start[0] + k * (pos[1] - start[1]) if abs(x - pos[0]) < offset: return self, p, obj, pin else: k = float(dy) / float(dx) y = start[1] + k * (pos[0] - start[0]) if abs(y - pos[1]) < offset: return self, p, obj, pin return False def disconnect(self): for wire_output in self.outputs: while True: target = self.parent.find_output(self, wire_output) if target: obj, pin = target obj.clear_input(pin) else: break def calc_border(self): self.border = Rect(self.rect) for c in self.inputs: if self.inputs[c] is not False: in_obj, in_pin = self.inputs[c] if not isinstance(in_obj, Invisible): x, y = in_obj.output_xy[in_pin] self.border = self.border.union(Rect(x, y, 0, 0)) def solve_drawable(self, window, drawable_list): self.calc_border() self.drawable = self.border.colliderect(window) if self.drawable: drawable_list.append(self)
class Collectable(object): """ The collectable class. An instance of this class represents a collectable, like a coin. Attributes: _pos: The position of the collectable. _value: The value of this collectable. _pic: The picture to display this collectable. _collision_rect: The rectangle used for checking for collision. """ def __init__(self, pos=None, size=None, value=5, pic=None): """ Generates a new instance of this class. Generates a new instance of this class and sets the fields. If no picture is given a the rectangle determined by position and size will be filled. Args: pos: The position of the collectable. size: The size of the collectable. value: The value of the collectable. pic: The picture to display the collectable. """ if pos is None: pos = [0, 0] if size is None: size = [0, 0] self._pos = pos self._value = value if pic is None: self._pic = Surface(size) pygame.draw.rect(self._pic, (0, 255, 0), Rect((0, 0), size)) self._collision_rect = Rect(pos, size()) else: self._pic = pic self._collision_rect = Rect(pos, pic.get_size()) def draw(self, surface, tick, camera, size): """ Draws the collectable. Draws this collectable on the given surface if it is in the horizontal range to be visible. Args: surface: The surface to draw on. tick: The current tick of the game. This argument is not used at the moment. camera: The position of the camera. size: The size of the window. """ if self._collision_rect.midright > camera[0] or self._pos[0] < camera[0] + size[0]: surface.blit(self._pic, (self._pos[0] - camera[0], self._pos[1] - camera[1])) def collides(self, rect): """ Checks if the collectable collides. This method checks if the collectable collides with the given rectangle. Args: rect: The rectangle to check with. Returns: True if the collectable collides with the given rectangle. False otherwise. """ return self._collision_rect.colliderect(rect) def get_value(self): """ Returns the value. This method returns the value of this collectable. Returns: The value of this collectable. """ return self._value
class Enemy(Sprite): image = image.load('resources/enemy.png') def __init__(self, location, *groups): super().__init__(*groups) self.rect = Rect(location, self.image.get_size()) self.vertical_velocity = self.default_vertical_velocity = 200 self.rightward_velocity = 100 self.vertical_velocity_decay = 40 self.jump_velocity = -300 def update(self, dt, tilemap, keys_pressed, player): new_rect = self._get_new_position_without_boundaries(dt, self.rect, self.vertical_velocity, self.rightward_velocity) in_boundaries = [InBoundary(boundary_object) for boundary_object in tilemap.layers['triggers'].collide(new_rect, 'blockers') if boundary_object['blockers'] == 'in'] out_boundaries = [OutBoundary(boundary_object) for boundary_object in tilemap.layers['triggers'].collide(new_rect, 'blockers') if boundary_object['blockers'] == 'out'] on_top = False on_boundary = False for boundary in in_boundaries: new_rect, on_boundary = boundary.stick_and_get_new_position(self.rect, new_rect, on_boundary) for boundary in out_boundaries: new_rect, on_boundary, on_top = boundary.stick_and_get_new_position(self.rect, new_rect, on_boundary, on_top) if on_boundary: self.vertical_velocity_decay = randint(5, 30) self.jump_velocity = randint(-500, -300) if new_rect.right <= self.rect.right and self.rightward_velocity > 0: # bounce off right bounding wall and go left self.rightward_velocity = randint(-200, -30) elif new_rect.right >= self.rect.right and self.rightward_velocity < 0: # bounce off left bounding wall and go right self.rightward_velocity = randint(30, 200) self.vertical_velocity = self._maintain_jump( on_boundary, self.vertical_velocity, self.default_vertical_velocity, self.vertical_velocity_decay, self.jump_velocity, can_go_higher=self.rect.top - new_rect.top > 0, can_go_lower=self.rect.top - new_rect.top < 0) self.rect = new_rect if self.rect.colliderect(player.rect): player.is_dead = True @staticmethod def _get_new_position_without_boundaries(dt, new_rect, vertical_velocity, rightward_velocity): new_rect = new_rect.copy() new_rect.y += vertical_velocity * dt new_rect.x += rightward_velocity * dt return new_rect @staticmethod def _maintain_jump(on_boundary, vertical_velocity, default_vertical_velocity, vertical_velocity_decay, jump_velocity, can_go_higher, can_go_lower): if on_boundary and not can_go_lower and vertical_velocity == default_vertical_velocity: # don't jump from mid-air, you must be standing on top of something return jump_velocity # stop velocity degrading short when you bump your head if on_boundary and vertical_velocity != default_vertical_velocity and not can_go_higher: return default_vertical_velocity # turn jump into gravity over time by degrading the vertical velocity return min(vertical_velocity + vertical_velocity_decay, default_vertical_velocity)
class Player(Sprite): def __init__(self, x, y): Sprite.__init__(self) self.xvel = 0 self.yvel = 0 self.on_ground = False self.start_pos = x, y self.image = Surface((40, 40)) self.image.fill(COLOR) self.rect = Rect(x, y, 40, 40) self.image.set_colorkey(COLOR) self.jump_sound = Sound('sounds/jump.ogg') self.punch_sound = Sound('sounds/punch.ogg') self.anim_stay = PygAnimation(ANIM_STAY) self.anim_right = PygAnimation(ANIM_RIGHT) self.anim_left = PygAnimation(ANIM_LEFT) self.anim_jump = PygAnimation(ANIM_JUMP) self.anim_stay.play() self.anim_left.play() self.anim_right.play() self.anim_jump.play() self.anim_stay.blit(self.image, (0, 0)) self.win = False self.lose_reload = 0 def update(self, left, right, up, platforms): self.image.fill(COLOR) if right: self.xvel = MOVE_SPEED self.anim_right.blit(self.image, (0, 0)) elif left: self.xvel = -MOVE_SPEED self.anim_left.blit(self.image, (0, 0)) else: self.xvel = 0 if not up: self.anim_stay.blit(self.image, (0, 0)) if up: self.image.fill(COLOR) self.anim_jump.blit(self.image, (0, 0)) else: self.anim_jump.rewind() if up and self.on_ground: self.yvel = -JUMP_POWER self.jump_sound.play() if not self.on_ground: self.yvel += GRAVITY if self.yvel + GRAVITY < MAX_GRAVITY else 0 self.on_ground = False self.rect.y += self.yvel self.collide(0, self.yvel, platforms) self.rect.x += self.xvel # переносим свои положение на xvel self.collide(self.xvel, 0, platforms) def draw(self, surface): surface.blit(self.image, self.rect.topleft) def collide(self, xvel, yvel, platforms): for platform in platforms: if self.rect.colliderect(platform.rect): if platform.state == 'upper': self.yvel = -JUMP_POWER * 5 continue if xvel > 0: self.rect.right = platform.rect.left if xvel < 0: self.rect.left = platform.rect.right if yvel > 0: self.rect.bottom = platform.rect.top self.on_ground = True self.yvel = 0 if yvel < 0: self.rect.top = platform.rect.bottom self.yvel = 0 if platform.state == 'trap': platforms.remove(platform) self.punch_sound.play() if platform.state == 'enemy': self.rect.x, self.rect.y = self.start_pos self.lose_reload = 60 if platform.state == 'target': self.win = True
def rectangle_rectangle(x1, y1, w1, h1, x2, y2, w2, h2): "Test for intersection of rectangles 1 and 2, centres x,y, dimensions w,h" a = Rect((x1-w1/2, y1-h1/2, w1, h1)) b = Rect((x2-w2/2, y2-h2/2, w2, h2)) return bool(a.colliderect(b))
class Player: def __init__(self): self.x = 50 self.y = 200 self.width = 60 self.height = 100 self.speedX = 0 self.speedY = 0 self.jumping = True self.jump_effect = pygame.mixer.Sound('assets\\sound\\jump.wav') self.rect = Rect(self.x, self.y, self.width, self.height) self.clock = pygame.time.Clock() self.run_images = [] self.jump_images = [] self.dead_images = [] for i in range(9): picture = load_image('assets\\player\\_Jump (' + str(i + 1) + ').png') # picture = pygame.transform.scale(load_image('assets\\player\\_Jump (' + str(i + 1) + ').png'), (80, 105)) # pygame.image.save(picture, 'assets\\player\\_Dead (' + str(i + 1) + ').png') self.jump_images.append(picture) picture = load_image('assets\\player\\_Walk (' + str(i + 1) + ').png') self.run_images.append(picture) picture = load_image('assets\\player\\_Dead (' + str(i + 1) + ').png') self.dead_images.append(picture) self.index = 0 self.time_for_animation_frame = 60 self.tps_delta = 0 def draw(self, surface): self.rect.x = self.x self.rect.y = self.y if self.jumping is True: surface.blit(self.jump_images[self.index], self.rect) else: surface.blit(self.run_images[self.index], self.rect) pygame.draw.rect(surface, Colors.GREEN.value, self.rect, 2) def move_actions(self): self.tps_delta += self.clock.tick() # zwraca czas miedzy klatkami if self.tps_delta > self.time_for_animation_frame: self.tps_delta = 0 self.index += 1 if self.index >= len(self.run_images): self.index = 0 pressed = pygame.key.get_pressed() if pressed[pygame.K_SPACE] and self.jumping is False: self.jump_effect.play() self.speedY = -8 self.jumping = True if self.y > Dimensions.GROUND_LVL: self.jumping = False self.speedY = 0 self.y = Dimensions.GROUND_LVL - 2 if self.jumping is True: self.speedY = self.speedY + 0.2 if pressed[pygame.K_LEFT]: self.speedX = -5 elif pressed[pygame.K_RIGHT]: self.speedX = 5 self.move() self.speedX = self.speedX * 0.8 def move(self): if self.x + self.speedX >= 0 and self.x + self.speedX + self.width <= Sizes.MAP_WIDTH_PIXELS.value: self.x += self.speedX self.y += self.speedY def check_collisions_with_obstacles(self, board): for o in board.obstacles: if self.rect.colliderect(o.rect): return True return False def reset(self): self.x = 50 self.y = 200 self.speedX = 0 self.speedY = 0 self.jumping = True
if e.key == K_RIGHT: mov += 1 if e.key == K_DOWN: CROUCH += 1 if e.key == K_SPACE and n <= 0: end = False load_level(hublvl) hub=True if e.type == KEYUP: if e.key == K_LEFT: mov -= -1 if e.key == K_RIGHT: mov -= 1 if e.key == K_DOWN: CROUCH -= 1 # door if hub: doorlist = [Rect((256+(i*256), 64), (64, 64)) for i in range(len(LEVELS))] di = hitbox.collidelist(doorlist) # enter door if door and (hitbox.colliderect(Rect(DOOR, (64, 64))) or (hub and di != -1 and len(INV)>=needs[di] )): n = 2 if not hub: X, Y = DOOR[0] + 16, DOOR[1] adjust_scroller() STATE = "jump1" while n < 980: surf = rotate(get_screen(), n) SCREEN.blit(surf, ((W-surf.get_width())//2, (H - surf.get_height())//2)) n += n // 2 CLOCK.tick(30) pygame.display.update() for e in pygame.event.get(): if e.type == QUIT or e.type == KEYDOWN and e.key == K_ESCAPE: quit() if e.type == KEYDOWN: if e.key == K_LEFT: mov += -1 if e.key == K_RIGHT: mov += 1