Exemplo n.º 1
0
def main():
    """this function is called when the program starts.
       it initializes everything it needs, then runs in
       a loop until the function returns."""

    # Initialize Everything
    pg.mixer.init()
    pg.init()
    screen = pg.display.set_mode((screen_width, screen_height))
    pg.display.set_caption("Bullet Helln't")
    pg.mouse.set_visible(0)

    # Create The Background
    bg = pg.image.load("art/background/background.png")
    bg_offset = 0

    # Display The Background
    screen.blit(bg, (0, 0))
    # pg.display.flip()

    #
    pg.mixer.music.load('sound/music.wav')
    pg.mixer_music.play(-1)

    # Prepare Game Objects
    clock = pg.time.Clock()
    potion_list = []
    player = Player(screen_width, screen_height, potion_list)
    hud = HUD(player)
    inv = Inventory(player)

    invisible_top_wall = Wall(0, -35, screen_width, 10)
    invisible_bottom_wall = Wall(0, screen_height + 25, screen_width, 10)
    invisible_left_wall = Wall(-35, 0, 10, screen_height)
    invisible_right_wall = Wall(screen_width + 25, 0, 10, screen_height)
    top_wall = Wall(0, 0, screen_width, 10)
    bottom_wall = Wall(0, screen_height - 10, screen_width, 10)
    left_wall = Wall(0, 0, 10, screen_height)
    right_wall = Wall(screen_width - 10, 0, 10, screen_height)
    walls = pg.sprite.RenderPlain(top_wall, bottom_wall, left_wall, right_wall)
    collision_walls = pg.sprite.RenderPlain(invisible_top_wall,
                                            invisible_bottom_wall,
                                            invisible_left_wall,
                                            invisible_right_wall)
    allsprites = pg.sprite.RenderPlain(player, walls, collision_walls, hud,
                                       inv)
    player.walls = collision_walls.sprites()

    bullet_list = []

    enemy_list = []
    for enemy in enemy_list:
        allsprites.add(enemy)

    # Tracker
    item_count = defaultdict(lambda: 0)

    # Tracker specifically for special potion; and whether player holds it
    bomb_inuse = False
    bomb_counter = 0
    bomb_delay = 330

    # Shows the introduction screen
    story = "THE STORY SO FAR:"
    story2 = "In a world filled with swords, you are a superhero with a bow."
    story3 = "Swing your bow, kill enemies and eliminate swords."
    story4 = "Pick up health and a special potion along the way to make swords disappear!"
    story5 = "<TAB> to begin."

    start_game = False
    while not start_game:
        font = pygame.font.SysFont("Arial", 24)
        text = font.render(story, 1, (0, 0, 0))
        text2 = font.render(story2, 1, (0, 0, 0))
        text3 = font.render(story3, 1, (0, 0, 0))
        text4 = font.render(story4, 1, (0, 0, 0))
        text5 = font.render(story5, 1, (0, 0, 0))

        text_pos = text.get_rect(centerx=screen.get_width() / 2, centery=100)
        text_pos2 = text2.get_rect(centerx=screen.get_width() / 2, centery=200)
        text_pos3 = text3.get_rect(centerx=screen.get_width() / 2, centery=300)
        text_pos4 = text4.get_rect(centerx=screen.get_width() / 2, centery=400)
        text_pos5 = text5.get_rect(centerx=screen.get_width() / 2, centery=500)

        screen.blit(text, text_pos)
        screen.blit(text2, text_pos2)
        screen.blit(text3, text_pos3)
        screen.blit(text4, text_pos4)
        screen.blit(text5, text_pos5)

        pg.display.flip()

        for event in pg.event.get():
            if event.type == pg.QUIT:
                quit()
            if event.type == pg.KEYDOWN and event.key == pg.K_TAB:
                start_game = True
            else:
                continue

    # Main Loop
    going = True
    while going:
        # print(item_count[Enemy], item_count[Enemy2], item_count[Potion])

        # draw two backgrounds, slowly moving down
        screen.blit(bg, (0, bg_offset))
        screen.blit(bg, (0, bg_offset - screen_height))
        if bg_offset < screen_height:
            bg_offset += 1
        else:  # once offset goes off the screen, reset it
            bg_offset = 0

        for event in pg.event.get():
            if event.type == pg.QUIT:
                going = False

            # player attack
            if event.type == pg.KEYDOWN and event.key == pg.K_SPACE:
                player.start_attack()

            # player bomb
            if player.bomb_ready and event.type == pg.KEYDOWN and event.key == pg.K_c:
                pg.mixer.Sound('sound/tactical-nuke.wav').play()
                bomb_inuse = True
                player.bomb_ready = False

        if bomb_inuse:
            if bomb_counter < bomb_delay:
                bomb_counter += 1
            else:
                player.bomb_count = 0
                print("BOOM")
                bomb_inuse = False
                bomb_counter = 0

                # remove all bullets
                for bullet in bullet_list:
                    bullet.kill()
                bullet_list.clear()
                allsprites.remove(bullet_list)

                # remove all enemies?
                for enemy in enemy_list:
                    enemy.kill()
                enemy_list.clear()
                allsprites.remove(enemy_list)
                item_count[Enemy] = 0
                item_count[Enemy2] = 0

        if random.random() < chance_spawn(item_count[Potion]):
            potion = Potion(screen_width, screen_height)
            potion_list.append(potion)
            allsprites.add(potion)
            item_count[Potion] = item_count[Potion] + 1

        if random.random() < chance_spawn(item_count[Enemy]):
            enemy = Enemy(screen_width, screen_height)
            enemy_list.append(enemy)
            allsprites.add(enemy)
            item_count[Enemy] = item_count[Enemy] + 1

        if item_count[Enemy2] <= 5 and random.random() < chance_spawn(
                item_count[Enemy2]):
            enemy = Enemy2(screen_width, screen_height)
            enemy_list.append(enemy)
            allsprites.add(enemy)
            item_count[Enemy2] = item_count[Enemy2] + 1

        # a special potion; if you need to collect 4, may as well have them spawn randomly
        if random.random() < 0.003:
            potion = Potion2(screen_width, screen_height)
            potion_list.append(potion)
            allsprites.add(potion)

        # update player (movement, attack frame, health)
        if not player.update():
            end_screen(screen, bg, player)

        if clock.get_time() % 5:
            for enemy in enemy_list:
                if player.attack and player.attack_box.colliderect(
                        enemy.hurtbox):
                    enemy.kill_enemy(player)
                    enemy_list.remove(enemy)

                    if isinstance(enemy, Enemy):
                        item_count[Enemy] = item_count[Enemy] - 1
                    elif isinstance(enemy, Enemy2):
                        item_count[Enemy2] = item_count[Enemy2] - 1
                    allsprites.remove(
                        enemy
                    )  # TODO: Make enemies stay a while before being removed

                if player.hurtbox.colliderect(enemy.hurtbox):
                    if player.damage_cooldown == 0:
                        player.get_hurt()

                # remove if off screen; after calling 'implode' first on Enemy though
                if enemy.rect.y + 50 > screen_height:
                    if isinstance(enemy, Enemy):
                        bullets = enemy.implode(player.rect.x, screen_height)
                        for bullet in bullets:
                            bullet_list.append(bullet)
                            allsprites.add(bullet)

                    if isinstance(enemy, Enemy):
                        item_count[Enemy] = item_count[Enemy] - 1
                    elif isinstance(enemy, Enemy2):
                        item_count[Enemy2] = item_count[Enemy2] - 1

                    allsprites.remove(enemy)
                    enemy_list.remove(enemy)
                    enemy.kill()

                # get each enemy to go through a 'shoot' cycle; returns None if no bullet generated
                # bullet = None
                # if isinstance(enemy, Enemy):
                bullet = enemy.shoot(player.rect.x, player.rect.y)
                # elif isinstance(enemy, Enemy2):
                #     bullet = enemy.shoot(player.h)
                if bullet:
                    bullet_list.append(bullet)
                    allsprites.add(bullet)

            for bullet in bullet_list:
                remove = False
                # bigger hitbox collides with player attack
                if player.attack and player.attack_box.colliderect(
                        bullet.rect):
                    remove = True
                # smaller hitbox collides with player
                elif player.hurtbox.colliderect(bullet.hurtbox):
                    if player.damage_cooldown == 0:
                        player.get_hurt()
                    remove = True
                # off screen; add 20 to coordinates to centre it (knife is 40x40 px)
                elif bullet.rect.x + 20 < 10 or bullet.rect.x + 20 > screen_width - 10 \
                        or bullet.rect.y + 20 < 10 or bullet.rect.y + 20 > screen_height - 10:
                    remove = True

                # cheeky bodge: homing
                if isinstance(bullet, Knife2):
                    xdist = abs(player.rect.x - bullet.rect.x)
                    if bullet.rect.x + 40 < player.rect.x + 50 - 20:
                        bullet.true_x += bullet.xspeed * xdist
                    elif bullet.rect.x + 40 > player.rect.x + 50 + 20:
                        bullet.true_x -= bullet.xspeed * xdist

                if remove:
                    bullet_list.remove(bullet)
                    allsprites.remove(bullet)
                    bullet.kill()

            # remove potions going off screen
            for potion in potion_list:
                if potion.rect.y > screen_height - 30:
                    if isinstance(potion, Potion2):
                        potion2_present = False
                    allsprites.remove(potion)
                    item_count[Potion] = item_count[Potion] - 1
                    potion_list.remove(potion)
                    potion.kill()

        # draw
        allsprites.update()

        # Draw Everything
        allsprites.draw(screen)
        # text_surface = score_text.generate_surface('Health: ')
        # screen.blit(text_surface,
        #             (screen_width - text_surface.get_width() - 100, screen_height - text_surface.get_height() - 45))
        pg.display.flip()

        clock.tick(60)

    pg.quit()
Exemplo n.º 2
0
bg = Background()
enemy_spawn_ctrl = enemy.Controller()


fps_target = 30
last = 0
running = True
while running:
    deltaT = clk.tick(60) / 1000
    events.process_events()

    if events.QUIT:
        running = False

    # PHYSICS AND CONTROLLER UPDATES
    player.update(deltaT)
    bullets.update_all_bullets(deltaT)
    enemy_spawn_ctrl.update(deltaT)
    bg.update(deltaT)

    # RENDERING
    srf = pygame.display.get_surface()
    srf.fill((0, 0, 0))

    bg.draw()
    player.draw()
    bullets.draw_all_bullets()
    enemy_spawn_ctrl.draw_all_enemies()

    pygame.display.update()
Exemplo n.º 3
0
        if event.type == hit_cooldown:
            player.iframe = False
            pygame.time.set_timer(hit_cooldown, 0)

        if event.type == enemy_stun_cooldown:
            slime.stunned = False
            pygame.time.set_timer(enemy_stun_cooldown, 0)

    ground.render()

    background.render()

    if player.hp != 0:
        displaysurface.blit(player.image, player.rect)
        player.move()
        player.update()
        if hits:
            # slime_atk.render(player)
            player.hit(slime, hit_cooldown)
    else:
        player.kill()

    if slime.hp != 0:
        slime.render()
        slime.hit(player_group, player, enemy_stun_cooldown)
    else:
        slime.kill()

    if player.attacking == True:
        player.attack()
Exemplo n.º 4
0
class Game:
    def __init__(self, display):
        self.display = display
        self.clock = pg.time.Clock()
        pg.display.set_caption(WINDOW_TITLE)

        self.joysticks = [
            pg.joystick.Joystick(x) for x in range(pg.joystick.get_count())
        ]
        self.joystick = None
        if len(self.joysticks) > 0:
            self.joystick = self.joysticks[0]
            self.joystick.init()

        # sprite groups
        self.all_sprites = None
        self.items_on_floor = None
        self.solid = None
        self.doors = None

        self.background_surface = None
        self.triggers = []
        self.collisions = []  # rectangles
        self.spritesheet = None
        self.map = None
        self.player = None
        self.camera = None
        self.playing = False
        self.dt = 0.0
        self.global_time = 0
        self.pressed_keys = {}
        self.keys_just_pressed = {}
        self.joystick_just_pressed = {}

        self.gui = Nanogui(display)
        self.visibility_data = None  # [x][y] -> True, False
        self.fov_data = None  # [x][y] -> True, False
        self.update_fov = True
        self.light_map = []

    def load(self):
        self.all_sprites = pg.sprite.Group()
        self.solid = pg.sprite.Group()
        self.items_on_floor = pg.sprite.Group()
        self.doors = pg.sprite.Group()

        assets_folder = path.join(getcwd(), 'assets')
        self.map = Map(path.join(assets_folder, 'maps/map1.json'))

        self.spritesheet = Spritesheet(
            path.join(assets_folder, 'spritesheet.png'), 32)
        wall_img = self.spritesheet.get_image_at_col_row(0, 0)
        apple_img = self.spritesheet.get_image_alpha_at_col_row(1, 0)
        keycard_img = self.spritesheet.get_image_alpha_at_col_row(0, 3)
        self.background_surface = pg.Surface(
            (self.map.width * TILE_SIZE, self.map.height * TILE_SIZE))

        self.visibility_data = [[True] * self.map.height
                                for i in range(self.map.width)]
        self.fov_data = [[True] * self.map.height
                         for i in range(self.map.width)]

        for node in self.map.objects:
            x, y = node['x'], node['y']
            if node["name"] == 'WALL':
                #self.collisions.append(pg.Rect(x, y, TILE_SIZE, TILE_SIZE))  # TODO big rectangles
                wall = Wall(self, x, y, wall_img)
                if not LIMIT_FOV_FOR_STATIC_SPRITES:
                    wall.remove(self.all_sprites)  # skip drawing
                    self.background_surface.blit(
                        wall_img, (x * TILE_SIZE, y * TILE_SIZE))
                self.visibility_data[x][y] = False
            elif node["name"] == 'PLAYER':
                self.player = Player(self, x, y)
            elif node["name"] == 'APPLE':
                item = Item(self, x, y, apple_img)
                item.pickable = Pickable(item, 'apple', False, 1, False)
            elif node["name"] == 'KEYCARD':  # key card
                item = Item(self, x, y, keycard_img)
                item.pickable = Pickable(item, 'keycard', False, 1, False)
            elif node["name"] == "DOOR":
                Door(self, x, y, node["dir"])
                self.visibility_data[x][
                    y] = False  # TODO opened doors visibility

        for trigger in self.map.triggers:
            TextTrigger(
                self,
                pg.Rect(trigger["x"], trigger["y"], trigger["width"],
                        trigger["height"]), trigger["text"])

        self.camera = Camera(self.map.width_screen, self.map.height_screen)

    def update(self):
        self.gui.pre(self.joystick)

        if not message.Message.messages:
            self.player.update(self.dt)
        message.update(self)

        camera_updated = self.camera.update(self.player)
        if self.update_fov:
            player_hit_rect = self.player.hit_rect
            player_tilex = math.floor(player_hit_rect.x / TILE_SIZE)
            player_tiley = math.floor(player_hit_rect.y / TILE_SIZE)

            self.fov_data = calc_fov(player_tilex, player_tiley, FOV_RADIUS,
                                     self.visibility_data, self.fov_data)
            self.update_light_map(self.player.x, self.player.y)
            self.update_fov = False

        self.gui.after()

    def draw(self):
        self.display.fill(BG_COLOR)

        bg_x, bg_y = self.camera.transform_xy(0, 0)
        self.display.blit(self.background_surface, (bg_x, bg_y))

        # TODO layering
        if not LIMIT_FOV_FOR_STATIC_SPRITES:
            for sprite in self.all_sprites:
                if sprite != self.player and not isinstance(sprite, Item):
                    self.display.blit(sprite.image,
                                      self.camera.transform(sprite))

        if LIMIT_FOV_FOR_STATIC_SPRITES:
            fov_group = self.all_sprites
        else:
            fov_group = self.items_on_floor
        for sprite in fov_group:
            tilex = math.floor(sprite.x)
            tiley = math.floor(sprite.y)
            if sprite != self.player:
                if self.fov_data[tilex][tiley]:
                    self.display.blit(sprite.image,
                                      self.camera.transform(sprite))

        # darken image
        self.display.fill(DARKEN_COLOR, special_flags=pg.BLEND_SUB)
        # draw light
        for light in self.light_map:
            self.display.fill(light[1], light[0], pg.BLEND_ADD)

        if DEBUG_FOV:
            self.draw_fov()

        self.display.blit(self.player.image,
                          self.camera.transform(self.player))
        if message.Message.messages:
            message.Message.messages[0].render(self.display)

            #self.__put_text_on_screen(str(messages))
            #if messages.has_picture():
            #    self.__put_picture_on_screen__(messages.get_picture())

        self.gui.draw()
        pg.display.flip()

    def __put_picture_on_screen(self, image):
        self.display.blit(image, (SCREEN_WIDTH // 2, SCREEN_HEIGHT // 2))

    def run(self):
        self.playing = True
        while self.playing:
            self.dt = self.clock.tick(FPS) / 1000
            self.global_time += self.dt
            self.events()
            self.update()
            self.draw()

    def quit(self):
        pg.quit()
        sys.exit()

    def events(self):
        self.keys_just_pressed.clear()
        self.joystick_just_pressed.clear()

        self.pressed_keys = pg.key.get_pressed()
        for event in pg.event.get():
            if event.type == pg.QUIT:
                self.quit()
            if event.type == pg.KEYDOWN:
                self.keys_just_pressed[event.key] = True
                if event.key == pg.K_ESCAPE:
                    self.quit()
                if event.key == pg.K_F11:
                    self.toggle_fullscreen()
            if event.type == pg.JOYBUTTONDOWN:
                self.joystick_just_pressed[event.button] = True

    def toggle_fullscreen(self):
        """Taken from http://pygame.org/wiki/toggle_fullscreen"""

        screen = pg.display.get_surface()
        tmp = screen.convert()
        caption = pg.display.get_caption()
        cursor = pg.mouse.get_cursor()

        w, h = screen.get_width(), screen.get_height()
        flags = screen.get_flags()
        bits = screen.get_bitsize()

        pg.display.quit()
        pg.display.init()

        self.display = pg.display.set_mode((w, h), flags ^ pg.FULLSCREEN, bits)
        self.display.blit(tmp, (0, 0))
        pg.display.set_caption(*caption)

        pg.key.set_mods(0)

        pg.mouse.set_cursor(*cursor)

        return screen

    def get_vbutton_down(self, name):
        if name in V_BUTTONS:
            for key in V_BUTTONS[name]:
                if self.pressed_keys[key]:
                    return True
        return False

    def get_vbutton_jp(self, name):
        if name in V_BUTTONS:
            for key in V_BUTTONS[name]:
                if key in self.keys_just_pressed:
                    return True
        return False

    def get_key_jp(self, key):
        # get key just pressed (clears on new frame)
        if key in self.keys_just_pressed:
            return True
        return False

    def get_joystick_jp(self, button):
        # get joystick button just pressed (clears on new frame)
        if button in self.joystick_just_pressed:
            return True
        return False

    def get_axis(self, number):
        if self.joystick is not None:
            return self.joystick.get_axis(number)
        return 0.0

    def set_visibility(self, tilex, tiley, value):
        self.visibility_data[tilex][tiley] = value
        self.update_fov = True

    def draw_fov(self):
        for x in range(len(self.fov_data)):
            for y in range(len(self.fov_data[0])):
                if self.fov_data[x][y]:
                    newx, newy = self.camera.transform_xy(
                        x * TILE_SIZE, y * TILE_SIZE)
                    pg.draw.rect(self.display, (200, 200, 200),
                                 pg.Rect(newx, newy, TILE_SIZE, TILE_SIZE), 1)

    def update_light_map(self, source_x, source_y):
        self.light_map.clear()
        radius_sqr = FOV_RADIUS * FOV_RADIUS
        tmp = 1.0 / (1.0 + radius_sqr)

        for x in range(len(self.fov_data)):
            for y in range(len(self.fov_data[0])):
                if self.fov_data[x][y]:
                    newx, newy = self.camera.transform_xy(
                        x * TILE_SIZE, y * TILE_SIZE)

                    dist_sqr = (source_x - x) * (source_x - x) + (
                        source_y - y) * (source_y - y)
                    intensity = 1.0 / (1.0 + dist_sqr / 20)
                    intensity = intensity - tmp
                    intensity = intensity / (1.0 - tmp)
                    color = tuple(intensity * v for v in LIGHT_COLOR)
                    self.light_map.append((pg.Rect(newx, newy, TILE_SIZE,
                                                   TILE_SIZE), color))