예제 #1
0
class DIRECTION(Enum):
    HAUT = Vector(0, -1)
    BAS = Vector(0, 1)
    DROITE = Vector(1, 0)
    GAUCHE = Vector(-1, 0)
    NONE = Vector(0, 0)

    @classmethod
    def opposite(cls,
                 direction):  #renvoie la direction opposée, ou lève une erreur
        try:
            if direction == cls.HAUT:
                return cls.BAS
            elif direction == cls.BAS:
                return cls.HAUT
            elif direction == cls.GAUCHE:
                return cls.DROITE
            elif direction == cls.DROITE:
                return cls.GAUCHE
            elif direction == cls.NONE:
                return cls.NONE
            else:
                raise ValueError("le vecteur n'est pas une direction")
        except ValueError:
            raise ValueError
예제 #2
0
    def update(self):
        super().update()

        self.update_timers()
        if self.jump_cd > 0:
            self.jump_cd -= 1
        if self.move_cd > 0:
            self.move_cd -= 1

        if self.state == ActorSlime.State.JUMP:
            if self.jump_in:
                can_move = self.move(self.jump_vect_in.x * self.jump_velocity,
                                     self.jump_vect_in.y * self.jump_velocity)

                if not can_move:
                    self.state = ActorSlime.State.IDLE
                    self.jump_cd = self.jump_cd_max

                if self.jump_vect_in.x * (
                        self.jump_target_pos.center_real[0] - self.rect.
                        center_real[0]) < 0 and self.jump_vect_in.y * (
                            self.jump_target_pos.center_real[1] -
                            self.rect.center_real[1]) < 0:
                    self.jump_in = False
                    theta = random.random() * 2 * math.pi
                    self.jump_vect_out = Vector(
                        self.rect.x + 100 * math.cos(theta) -
                        self.rect.center_real[0], self.rect.y +
                        300 * math.sin(theta) - self.rect.center_real[1])
                    self.jump_vect_out.normalize()
                    self.jump_return_pos = Rect(
                        self.rect.x + 100 * math.cos(theta),
                        self.rect.y + 300 * math.sin(theta), 0, 0)
            else:
                self.jump_cd = self.jump_cd_max
                self.state = ActorSlime.State.IDLE
        elif self.state == ActorSlime.State.MOVE:
            can_move = self.move(self.move_vect.x * self.move_velocity,
                                 self.move_vect.y * self.move_velocity)
            self.move_count += 1
            if not can_move or self.move_count >= self.move_count_max:
                self.state = ActorSlime.State.IDLE
                self.move_cd = self.move_cd_max

        target = self.map.get_closest_ennemi(
            self.rect,
            range=self.detection_range,
            ennemi_team=self.team.get_ennemi())

        if self.can_attack() and target is not None and self.allowed_attack:
            if self.can_shoot(target):
                self.shoot(target)
            elif self.can_jump(target):
                self.jump(target)
            elif self.can_move():
                self.move_it()
        elif self.can_move():
            self.move_it()
예제 #3
0
    def jump(self, target):
        self.state = ActorSlime.State.JUMP
        self.jump_initial_pos = copy.deepcopy(self.rect)
        self.jump_return_pos = copy.deepcopy(target.rect)
        self.jump_target_pos = copy.deepcopy(target.rect)
        self.jump_return_pos.x += 300
        self.jump_count = 0
        self.jump_in = True

        self.jump_vect_in = Vector(
            target.rect.center_real[0] - self.rect.center_real[0],
            target.rect.center_real[1] - self.rect.center_real[1])
        self.jump_vect_in.normalize()
예제 #4
0
    def __init__(self):
        super().__init__()

        self.state = ActorSlime.State.IDLE
        self.team = EnumTeam.MONSTER_TEAM

        self.allowed_attack = False
        self.shoot_range = 500
        self.detection_range = 1000  # Distance à laquelle il perçoit un ennemi
        self.jump_range = 700
        self.jump_cd = 0
        self.jump_cd_max = 200
        self.jump_theta = 0
        self.jump_in = True
        self.jump_count = 0
        self.jump_count_max = 30
        self.jump_initial_pos = None
        self.jump_velocity = 12
        self.ammo_max = 3  # Le nombre de balles
        self.ammo = self.ammo_max  # Le nombre de balles max
        self.f = 50  # vie du slime

        self.collidable = True
        self.should_update = True

        self.velocity = Vector(0, 0)
예제 #5
0
    def execute(self, command):
        """ Gère les entrées dans l'invite de commande"""

        commands = command.split(
            sep=" "
        )  # sépare l'entrée en une liste ( escpaces supprimés, remplacés par les ',' de la liste)

        if commands[0] == "debug":
            pass
        elif commands[0] == "hitbox":
            self.draw_hit_box = not self.draw_hit_box
        elif commands[0] == "print":
            print(self.__getattribute__(commands[1]))
            print(
                self.__getattribute__(commands[1]).__getattribute__(
                    commands[2]))
        elif commands[0] == "menu" or commands[
                0] == "quit":  #permet de revenir au menu via l'invite de commande
            if pygame.mixer.music.get_busy():
                pygame.mixer.music.stop(
                )  # On éteint la music pour permettre à celle du menu de se lancer (car vérifie si une musique est
            self.state = StageState.QUIT  # en trainde jouer ou non)
            StageManager().push(game.stages.StageMainMenu.StageMainMenu())
        elif commands[0] == "tp":
            event = pygame.event.Event(pygame.USEREVENT,
                                       name=EVENT_TP,
                                       map_name=commands[1],
                                       spawn_pos=Vector(700, 700),
                                       actor=self.map.get_actor(ActorPlayer))
            pygame.event.post(event)
        elif commands[0] == "invincible":
            self.map.get_actor(ActorPlayer).invicible = not self.map.get_actor(
                ActorPlayer).invicible
예제 #6
0
    def detect_target_position(self, target):
        """Renvoie le vecteur (target.rect.center - self.rect.center) pour donner la direction où aller/tirer"""

        pos = Vector(target.rect.center[0] - self.rect.center[0],
                     target.rect.center[1] - self.rect.center[1])

        return pos
예제 #7
0
    def interact(self, actor):
        if self.state != ActorBomb.State.EXPLODE:
            if isinstance(actor, ActorArrow):
                self.velocity = Vector(actor.speed * math.cos(actor.dir),
                                       actor.speed * math.sin(actor.dir))

                return True

        return False
예제 #8
0
 def handle_mouse_button_down(self, pos, button):
     try:
         self.state = StageState.QUIT
         if self.tile_collidable:
             self.tile_picked = ActorTileCollidable(
                 self.tileset_files[self.tileset_no],
                 Vector(self.grid.get_pos_x(pos[0]),
                        self.grid.get_pos_y(pos[1])), self.grid.width,
                 self.grid.height)
         else:
             self.tile_picked = ActorTile(
                 self.tileset_files[self.tileset_no],
                 Vector(self.grid.get_pos_x(pos[0]),
                        self.grid.get_pos_y(pos[1])), self.grid.width,
                 self.grid.height)
         return True
     except ValueError:
         self.info("Tu n'as pas cliqué sur une image!")
예제 #9
0
    def __init__(self):
        super().__init__()

        self.mouse_pos = Vector(0, 0)
        self.object_pick = None

        self.is_paused = True
        self.mode = EDIT_MODE.PICK
        self.grid = Grid2()  #grille pour mieux positionner acteurs

        self.draw_hit_box = False
예제 #10
0
 def destroy(self):
     self.speed = 0
     self.state = ActorArrowChargedPlayer.State.EXPLODE
     event = pygame.event.Event(pygame.USEREVENT,
                                name=EVENT_EXPLOSION,
                                pos=Vector(self.rect.centerx,
                                           self.rect.centery),
                                radius=self.radius,
                                team=self.team,
                                damage=self.damage)
     pygame.event.post(event)
     self.team = EnumTeam.NEUTRAL_TEAM
예제 #11
0
    def explode(self):
        rect_tmp = self.rect
        self.state = ActorBomb.State.EXPLODE
        self.rect.center = rect_tmp.center

        event = pygame.event.Event(pygame.USEREVENT,
                                   name=EVENT_EXPLOSION,
                                   pos=Vector(self.rect.centerx,
                                              self.rect.centery),
                                   radius=self.radius,
                                   team=self.team,
                                   damage=50)
        pygame.event.post(event)
예제 #12
0
    def __init__(self,
                 map_name="level_0",
                 spawn_pos_x=700,
                 spawn_pos_y=650,
                 direction=DIRECTION.BAS):
        super().__init__(False)

        self.is_open = False
        self.map_name = map_name
        self.spawn_pos = Vector(spawn_pos_x, spawn_pos_y)

        self.sprites = {}
        self.animation = None
        self.direction = direction
        self.reload()
예제 #13
0
    def __init__(self, dir=DIRECTION.NONE, velocity=VECTOR_NULL):
        super().__init__()
        self.damage = 20
        try:
            self.dir = dir.get_theta()
        except:
            self.dir = dir.value.get_theta()
        self.speed = 8
        self.velocity = Vector(0, 0)
        if math.cos(self.dir) * velocity.x >= 0:
            self.velocity.x = velocity.x / 2   # Hé oui, les vitesses ne sont pas relativistes à cet ordre de grandeur, 2 + x2 = 4
        if math.sin(self.dir) * velocity.y >= 0:
            self.velocity.y = velocity.y / 2
        self.should_update = True

        self.draw_shadow = True
        self.collidable = True
        self.h = 20
예제 #14
0
    def reload(self):
        super().reload()

        self.handle_event = True
        self.should_update = True
        self.etre_vivant = True

        self.allowed_attack = False  # Permet de ne pas tirer dès le début
        self.shoot_range = 500
        self.shoot_rate = 1000  # Période des tirs : en ms
        self.detection_range = 1000  # Distance à laquelle il perçoit un ennemi
        self.jump_range = 700
        self.jump_cd = 0
        self.jump_cd_max = 400
        self.jump_theta = 0  #angle définissant le jump
        self.jump_in = True
        self.jump_count = 0
        self.jump_count_max = 30
        self.jump_initial_pos = None
        self.jump_velocity = 12  #vitesse du saut
        self.theta = 0
        self.ammo_max = 3  # Le nombre de balles
        self.ammo = self.ammo_max  # Le nombre de balles max
        self.hp = 50  # vie su slime

        self.move_cd = 0
        self.move_cd_max = 125
        self.move_vect = None
        self.move_count = 0
        self.move_count_max = 75
        self.move_velocity = 2

        self.collidable = True
        self.should_update = True

        self.velocity = Vector(0, 0)

        self.add_timer(Timer(2000, self.allow_attack))
예제 #15
0
 def move_it(self):
     theta = random.random() * 2 * math.pi
     self.move_vect = Vector(150 * math.cos(theta), 150 * math.sin(theta))
     self.move_vect.normalize()
     self.state = ActorSlime.State.MOVE
     self.move_count = 0
예제 #16
0
from game.utils.Vector import Vector

PLAYER_SPRITE_WIDTH = 64
PLAYER_SPRITE_HEIGHT = 64
PLAYER_MOVE_TOP = Vector(1, 8)
PLAYER_MOVE_LEFT = Vector(1, 9)
PLAYER_MOVE_BOTTOM = Vector(1, 10)
PLAYER_MOVE_RIGHT = Vector(1, 11)
PLAYER_DYING = Vector(1, 20)
PLAYER_MOVE_TILES_NUMBER = 8
PLAYER_DIE_TILES_NUMBER = 6
PLAYER_MOVE_TIME = 70
PLAYER_DYING_TIME = 300
PLAYER_STANDBY = Vector(1, 10)
PLAYER_WIDTH = 48
PLAYER_HEIGHT = 50
PLAYER_DEPTH = 20

WINDOW_WIDTH = 1408
WINDOW_HEIGHT = 832

EVENT_TP = "EVENT_TELEPORT"
# Evenement défini par :
# map_name: le nom de la Map à charger
# actor: l'Actor à téléporter
# spawn_pos: Un Vector représentant la position de l'Actor à téléporter.

EVENT_PLAYER_INTERACT = "EVENT_PLAYER_INTERACT"
# Evenement défini par :
# actor: L'Actor qui demande l'intéraction
예제 #17
0
class ActorSlime(ActorAlive, ActorAnimation):
    """ Un ennemi (slime en l'occurence) qui a plusieurs animations selon qu'il soit imobile, attaquant , mourant ou en déplacement"""

    ID = 32
    NAME = "SLIME"

    class State(EnumAuto):
        IDLE = ()
        ATTACK = ()
        JUMP = ()
        MOVE = ()
        DIE = ()

    WIDTH = 128
    HEIGHT = 128
    FILE = "assets/slime_blue_128.png"

    def __init__(self):
        super().__init__()

        self.state = ActorSlime.State.IDLE
        self.team = EnumTeam.MONSTER_TEAM

        self.allowed_attack = False
        self.shoot_range = 500
        self.detection_range = 1000  # Distance à laquelle il perçoit un ennemi
        self.jump_range = 700
        self.jump_cd = 0
        self.jump_cd_max = 200
        self.jump_theta = 0
        self.jump_in = True
        self.jump_count = 0
        self.jump_count_max = 30
        self.jump_initial_pos = None
        self.jump_velocity = 12
        self.ammo_max = 3  # Le nombre de balles
        self.ammo = self.ammo_max  # Le nombre de balles max
        self.f = 50  # vie du slime

        self.collidable = True
        self.should_update = True

        self.velocity = Vector(0, 0)

    def reload(self):
        super().reload()

        self.handle_event = True
        self.should_update = True
        self.etre_vivant = True

        self.allowed_attack = False  # Permet de ne pas tirer dès le début
        self.shoot_range = 500
        self.shoot_rate = 1000  # Période des tirs : en ms
        self.detection_range = 1000  # Distance à laquelle il perçoit un ennemi
        self.jump_range = 700
        self.jump_cd = 0
        self.jump_cd_max = 400
        self.jump_theta = 0  #angle définissant le jump
        self.jump_in = True
        self.jump_count = 0
        self.jump_count_max = 30
        self.jump_initial_pos = None
        self.jump_velocity = 12  #vitesse du saut
        self.theta = 0
        self.ammo_max = 3  # Le nombre de balles
        self.ammo = self.ammo_max  # Le nombre de balles max
        self.hp = 50  # vie su slime

        self.move_cd = 0
        self.move_cd_max = 125
        self.move_vect = None
        self.move_count = 0
        self.move_count_max = 75
        self.move_velocity = 2

        self.collidable = True
        self.should_update = True

        self.velocity = Vector(0, 0)

        self.add_timer(Timer(2000, self.allow_attack))

    def allow_attack(self, *arks, **kwargs):
        self.allowed_attack = True

    def update(self):
        super().update()

        self.update_timers()
        if self.jump_cd > 0:
            self.jump_cd -= 1
        if self.move_cd > 0:
            self.move_cd -= 1

        if self.state == ActorSlime.State.JUMP:
            if self.jump_in:
                can_move = self.move(self.jump_vect_in.x * self.jump_velocity,
                                     self.jump_vect_in.y * self.jump_velocity)

                if not can_move:
                    self.state = ActorSlime.State.IDLE
                    self.jump_cd = self.jump_cd_max

                if self.jump_vect_in.x * (
                        self.jump_target_pos.center_real[0] - self.rect.
                        center_real[0]) < 0 and self.jump_vect_in.y * (
                            self.jump_target_pos.center_real[1] -
                            self.rect.center_real[1]) < 0:
                    self.jump_in = False
                    theta = random.random() * 2 * math.pi
                    self.jump_vect_out = Vector(
                        self.rect.x + 100 * math.cos(theta) -
                        self.rect.center_real[0], self.rect.y +
                        300 * math.sin(theta) - self.rect.center_real[1])
                    self.jump_vect_out.normalize()
                    self.jump_return_pos = Rect(
                        self.rect.x + 100 * math.cos(theta),
                        self.rect.y + 300 * math.sin(theta), 0, 0)
            else:
                self.jump_cd = self.jump_cd_max
                self.state = ActorSlime.State.IDLE
        elif self.state == ActorSlime.State.MOVE:
            can_move = self.move(self.move_vect.x * self.move_velocity,
                                 self.move_vect.y * self.move_velocity)
            self.move_count += 1
            if not can_move or self.move_count >= self.move_count_max:
                self.state = ActorSlime.State.IDLE
                self.move_cd = self.move_cd_max

        target = self.map.get_closest_ennemi(
            self.rect,
            range=self.detection_range,
            ennemi_team=self.team.get_ennemi())

        if self.can_attack() and target is not None and self.allowed_attack:
            if self.can_shoot(target):
                self.shoot(target)
            elif self.can_jump(target):
                self.jump(target)
            elif self.can_move():
                self.move_it()
        elif self.can_move():
            self.move_it()

    def can_move(self):
        return self.state == ActorSlime.State.IDLE and self.move_cd == 0

    def move_it(self):
        theta = random.random() * 2 * math.pi
        self.move_vect = Vector(150 * math.cos(theta), 150 * math.sin(theta))
        self.move_vect.normalize()
        self.state = ActorSlime.State.MOVE
        self.move_count = 0

    def can_attack(self):
        return self.state == ActorSlime.State.IDLE

    def get_distance(self, target):
        return (self.rect.x - target.rect.x)**2 + (self.rect.y -
                                                   target.rect.y)**2

    def can_shoot(self, target):
        return self.get_distance(
            target) <= self.shoot_range**2 and self.ammo > 0

    def can_jump(self, target):
        return self.get_distance(
            target) <= self.jump_range**2 and self.jump_cd == 0

    def jump(self, target):
        self.state = ActorSlime.State.JUMP
        self.jump_initial_pos = copy.deepcopy(self.rect)
        self.jump_return_pos = copy.deepcopy(target.rect)
        self.jump_target_pos = copy.deepcopy(target.rect)
        self.jump_return_pos.x += 300
        self.jump_count = 0
        self.jump_in = True

        self.jump_vect_in = Vector(
            target.rect.center_real[0] - self.rect.center_real[0],
            target.rect.center_real[1] - self.rect.center_real[1])
        self.jump_vect_in.normalize()

    def shoot(self, target):
        self.state = ActorSlime.State.ATTACK

        arrow = ActorArrowSlime(self.detect_target_position(target))
        arrow.team = self.team
        arrow.rect.x = self.rect.x + (self.rect.w - arrow.rect.w) / 2
        arrow.rect.y = self.rect.y + (self.rect.h - arrow.rect.w) / 2
        self.map.add_actor(arrow)

        self.ammo -= 1

        if self.ammo == 0:
            self.reload_ammo()

    def reload_ammo(self):
        self.add_timer(Timer(2500, self.reload_ammo_callback))

    def reload_ammo_callback(self):
        self.ammo = self.ammo_max

    def idle(self):
        if not self.is_dead:
            self.state = ActorSlime.State.IDLE

    def die(self):
        self.collidable = False
        self.state = ActorSlime.State.DIE

    def dead(self):
        nb_slime = 0

        for actor in self.map.actors:
            if isinstance(actor, ActorSlime):
                nb_slime += 1

        if nb_slime == 1:
            for actor in self.map.actors:
                if isinstance(actor, ActorDoor) or isinstance(
                        actor, ActorDoorWin):
                    actor.open()

        self.map.remove_actor(self)
        del self

    def turn_on_shoot(self):
        print("turn on shoor appellé")
        self.can_shoot = True

    def detect_target_position(self, target):
        """Renvoie le vecteur (target.rect.center - self.rect.center) pour donner la direction où aller/tirer"""

        pos = Vector(target.rect.center[0] - self.rect.center[0],
                     target.rect.center[1] - self.rect.center[1])

        return pos

    def load_sprite(self):
        super().load_sprite()

        sprite_sheet = load_image(type(self).FILE, False)
        width = type(self).WIDTH
        height = type(self).HEIGHT

        self.animations = {}
        self.animations[ActorSlime.State.IDLE] = Animation(
            sprite_sheet, pygame.Rect(0, 0, width, height), 9, 50, True)
        self.animations[ActorSlime.State.MOVE] = Animation(
            sprite_sheet, pygame.Rect(0, height, width, height), 9, 100, True)
        self.animations[ActorSlime.State.JUMP] = Animation(
            sprite_sheet, pygame.Rect(0, height * 2, width, height), 9, 50,
            True)
        self.animations[ActorSlime.State.ATTACK] = Animation(
            sprite_sheet,
            pygame.Rect(0, height * 3, width, height),
            9,
            50,
            True,
            callback_fun=self.idle)
        self.animations[ActorSlime.State.DIE] = Animation(
            sprite_sheet,
            pygame.Rect(0, height * 4, width, height),
            9,
            50,
            True,
            callback_fun=self.dead)

    @property
    def animation(self):
        return self.animations[self.state]

    @property
    def is_dead(self):
        return self.hp <= 0

    def interact(self, actor):
        return super().interact(actor)