示例#1
0
class Company():
    """large unit of several batallions controlled by Flag

    Attributes
    ----------
    coords : float 1-D numpy.ndarray [2], >=0
        coords of center of Company
    speed : float, >=0
        absolute velocity of Company
    moving : bool
        whether Company is moving, including marching and forming up
    angle : float
        angle in radians of Company to x-axis.
    oldAngle : float
        angle in radians of Company to x-axis saved from last forming up
    troops : list of Infantry
        list of sprites representing troops in Company
    flag : Flag
        sprite that user interacts with to give commands to Company
    target : Company or None
        enemy Company which this Company is aiming at
    maxSize : int, >= 0
        number of Infantry that Company starts with
    sizex : int, >= 0
        number of troops in a row of Infantry
    sizey : int, >= 0
        number of rows of Infantry
    showOrders : int
        stage of selecting orders
    bayonetButton : Button
        button pressed to command Company to charge enemy with bayonets
    carreButton : Button
        button pressed to command Company to form carre
    lineButton : Button
        button pressed to command Company to form line
    play : bool
        whether Company can be given orders by player
    team : str
        team Company is on for friend-foe detection
    formation : String
        formation of Company
    defense : bool
        whether unit will ignore AI move orders
    allies : list of Battery, Company, Squadron
        list of all units with same team value
    enemies : list of Battery, Company, Squadron
        list of all units with different team value

    Properties
    ----------
    size : int, >= 0
        number of Infantry currently contained in Company
    formed : int, >= 0
        count of Infantry in formation
    idle : bool
        whether AI can move this Company
    velocity : float 1-D numpy.ndarray [2]
        velocity of Company in vertical and horizontal axes
    morale : int
        percent chance of Company entering panic on losing next Infantry

    Methods
    -------
    unitInit
        set allies and enemies
    setSpeed
        set speed to min of default, distance to coords
    distanceMany
        measure straight line distance Company to list of coords
    stop
        stop Company, Infantry
    update
        move Company, update Infantry, panic if necessary
    follow
        move Company and Infantry to flag
    lookAt
        set rotation to angle from current center to new point
    findTarget
        select enemy as target
    aim
        turn toward selected target
    getHit
        kill own Infantry when shot
    getShelled
        kill own Infantry hit by cannonball
    orders
        give orders other than move for Company
    formCarre
        Company forms a carre
    formLine
        Company forms a line
    AIcommand
        orders Company to move to coords
    AIsupport
        move to visible allies in combat
    AIcarre
        form carre when idle and charged by cavalry
    blitme
        print elements of Company
    __str__
        return string with name of file for id, used in testing
    """
    def __init__(self,
                 screen,
                 angle,
                 x,
                 y,
                 sizex,
                 sizey,
                 team,
                 flags,
                 strength,
                 play=True,
                 defense=False):
        super().__init__()
        if team == "green":
            fil1, fil2, fil3, fileFlag = greenImages
        elif team == "blue":
            fil1, fil2, fil3, fileFlag = blueImages
        coords = np.array([x, y], dtype=float)
        self.troops = []
        # self.maxSize = sizex * sizey
        # add infantry to company
        for i in range(sizex * sizey):
            """ x, y displacement from center of Company based on count
            shiftx increases with count with a period of sizex, creating
            a row of soldiers with a length of sizex
            shifty increases when count increases by sizex, starting
            a new row of soldiers every sizex soldiers
            """
            shifty = I_GAPY * ((i % sizey) - sizey // 2)
            shiftx = I_GAPX * ((i // sizey) - sizex // 2)
            self.troops.append(
                Infantry(screen, angle, shiftx, shifty, strength, team, fil1,
                         fil2, fil3, coords, play, defense))
        self.flag = Flag(screen, (x, y), angle, fileFlag, play)
        flags.append(self.flag)
        # 0,1=click,release to show buttons, 2,3=click,release to select
        self.showOrders = 0
        self.bayonetButton = Button(screen, "Bayonets")
        self.carreButton = Button(screen, "Carre")
        self.lineButton = Button(screen, "Line")
        self.healthDisp = Button(screen, str(self.health))
        self.play = play
        self.team = team
        self.formation = "Line"
        self.oldUnits = []
        # used to id object for testing, not meant to be seen/used
        self.id = fil1

    def unitInit(self, units):
        # set allies and enemies
        if units != self.oldUnits:
            self.oldUnits = units.copy()
            [unit.unitInit(units) for unit in self.troops]

    @property
    def size(self):
        # number of Infantry currently contained in Company
        return len(self.troops)

    @property
    def flagVars(self):
        return (self.flag.coords, self.flag.select, self.flag.attackMove,
                self.flag.angle, self.flag.change)

    @property
    def health(self):
        return sum(inf.size for inf in self.troops)

    def update(self):
        # move Company, update Infantry, panic if necessary
        [unit.panic() for unit in self.troops if unit.panicTime > 0]
        for unit in self.troops:
            if unit.size <= 0:
                self.troops.remove(unit)
            elif unit.panicTime == -1:
                unit.update()

    def follow(self, flags):
        # move Company and Infantry to flag
        if self.play:
            self.flag.checkDrag(flags)
        [unit.follow(*self.flagVars) for unit in self.troops]
        self.flag.change = False

    def aim(self):
        # turn toward selected target
        [troop.aim() for troop in self.troops]

    def orders(self):
        # give orders other than move for Company
        if not self.play or self.size == 0:
            return
        if self.flag.select != 0 or pygame.mouse.get_pressed()[2]:
            self.showOrders = 0
        mouse = pygame.mouse.get_pos()
        click = pygame.mouse.get_pressed()[0]
        touch = any([inf.rect.collidepoint(mouse) for inf in self.troops])
        coords = self.troops[0].coords
        buttonCoords = (coords[0], coords[1] + FB_SIZE[1])
        if click and self.showOrders == 0 and touch:
            self.showOrders = 1
        if self.showOrders == 1 and not click:
            self.showOrders = 2
            self.bayonetButton.draw(coords)
            if self.formation == "Line":
                self.carreButton.draw(buttonCoords)
                self.lineButton.draw((-100, -100))
            if self.formation == "Carre":
                self.lineButton.draw(buttonCoords)
                self.carreButton.draw((-100, -100))
        if self.showOrders == 2 and click:
            self.showOrders = 3
            if self.bayonetButton.rect.collidepoint(mouse):
                for troop in self.troops:
                    troop.bayonets = not troop.bayonets
            if self.carreButton.rect.collidepoint(mouse):
                self.formCarre()
            if self.lineButton.rect.collidepoint(mouse):
                self.formLine()
        if self.showOrders == 3 and not click:
            self.showOrders = 0

    def formCarre(self):
        # Company forms a carre
        self.formation = "Carre"
        [inf.formCarre() for inf in self.troops]

    def formLine(self):
        # Company forms a line
        self.formation = "Line"
        [inf.formLine() for inf in self.troops]

    def AIcommand(self, coords, attackMove=False):
        # orders company to move to coords
        self.flag.coords = coords
        self.flag.attackMove = attackMove

    def AIsupport(self):
        # move to visible allies in combat
        if self.play or self.size == 0:
            return
        unit = self.troops[0]
        allyDist = unit.distanceMany([grp.coords for grp in unit.allies])
        for ally, d in zip(unit.allies, allyDist):
            cannon = hasattr(ally, 'shot')
            canSee = d < I_SIGHT
            if unit.idle and ally.target is not None and canSee and not cannon:
                self.AIcommand(ally.target.coords, True)
                break

    def AIcarre(self):
        [troop.AIcarre() for troop in self.troops]

    def blitme(self):
        # print elements of Company
        if self.showOrders > 1:
            self.bayonetButton.blitme()
            self.carreButton.blitme()
            self.lineButton.blitme()
            coords = self.troops[0].coords
            healthCoords = (coords[0], coords[1] - FB_SIZE[1])
            self.healthDisp.draw(healthCoords, str(self.health))
            self.healthDisp.blitme()
        [infantry.blitme() for infantry in self.troops]
        self.flag.blitme()

    def __str__(self):
        return self.id
示例#2
0
class Squadron():
    """Small unit of several Cavalry controlled by Flag

    Attributes
    ----------
    coords : float 1-D numpy.ndarray [2], >=0
        coords of center of Squadron
    speed : float, >=0
        absolute velocity of Squadron
    moving : bool
        whether Squadron is moving, including marching and forming up
    angle : float
        angle in radians of Squadron to x-axis.
    oldAngle : float
        angle in radians of Squadron to x-axis saved from last forming up
    troops : list of Cavalry
        list of sprites representing troops in Squadron
    flag : Flag
        sprite that user interacts with to give commands to Squadron
    target : Squadron or None
        enemy Squadron which this Squadron is aiming at
    maxSize : int, >= 0
        number of Cavalry that Squadron starts with
    sizey : int, >= 0
        number of rows of Cavalry
    panicTime : int, >= 0
        time in milliseconds when Squadron started panicking
    showOrders : int
        stage of selecting orders
    chargeStart : int
        when Squadron started charging at target
    play : bool
        whether Squadron can be given orders by player
    team : str
        team Squadron is on for friend-foe detection
    defense : bool
        whether unit will ignore AI move orders
    allies : list of Battery, Squadron, Squadron
        list of all units with same team value
    enemies : list of Battery, Squadron, Squadron
        list of all units with different team value

    Properties
    ----------
    size : int, >= 0
        number of Cavalry currently contained in Squadron
    formed : int, >= 0
        count of Cavalry in formation
    idle : bool
        whether AI can move this Squadron
    velocity : float 1-D numpy.ndarray [2]
        velocity of Squadron in vertical and horizontal axes
    allowShoot : bool
        whether Squadron will currently aim at targets
    range : int, >= 0
        distance in pixels which Squadrons will set enemies as target
    aimVars : list of vars
        variables passed to Cavalry for aim funciton
    formVars :
        variables passed to Cavalry for form function
    morale : int
        percent chance of Squadron entering panic on losing next Cavalry

    Methods
    -------
    unitInit
        set allies and enemies
    setSpeed
        set speed to min of default, distance to coords
    distance
        measure straight line distance Squadron to coords
    distanceMany
        measure straight line distance Squadron to list of coords
    stop
        stop Squadron, Cavalry
    update
        move Squadron, update Cavalry, panic if necessary
    follow
        move Squadron and Cavalry to flag
    lookAt
        set rotation to angle from current center to new point
    findTarget
        select enemy as target
    aim
        turn toward selected target
    hitBayonets
        take losses from defended enemies
    getHit
        kill own Cavalry when shot
    getShelled
        kill own Cavalry hit by cannonball
    orders
        give orders other than move for Squadron
    AIcommand
        orders company to move to coords
    AIsupport
        move to visible allies in combat
    blitme
        print elements of Squadron
    __str__
        return string with name of file for id, used in testing
    """
    def __init__(self,
                 screen,
                 angle,
                 x,
                 y,
                 sizex,
                 sizey,
                 team,
                 flags,
                 strength,
                 play=True,
                 defense=False):
        super().__init__()
        if team == "green":
            file1, fileFlag = greenCav
        elif team == "blue":
            file1, fileFlag = blueCav
        coords = np.array([x, y], dtype=float)
        self.troops = []
        # add infantry to company
        for i in range(sizex * sizey):
            """ x, y displacement from center of Company based on count
            shiftx increases with count with a period of sizex, creating
            a row of soldiers with a length of sizex
            shifty increases when count increases by sizex, starting
            a new row of soldiers every sizex soldiers
            """
            shifty = CV_GAPY * ((i % sizey) - sizey // 2)
            shiftx = CV_GAPX * ((i // sizey) - sizex // 2)
            self.troops.append(
                Cavalry(screen, angle, shiftx, shifty, strength, team, file1,
                        coords, play, defense))
        self.flag = Flag(screen, (x, y), angle, fileFlag, play)
        flags.append(self.flag)
        # 0,1=click,release to show buttons, 2,3=click,release to select
        self.showOrders = 0
        # self.bayonetButton = Button(screen, "Bayonets")
        self.healthDisp = Button(screen, str(self.health))
        # self.bayonets = False
        self.play = play
        self.team = team
        self.oldUnits = []
        # used to id object for testing, not meant to be seen/used
        self.id = file1

    def unitInit(self, units):
        # set allies and enemies
        if units != self.oldUnits:
            self.oldUnits = units
            [unit.unitInit(units) for unit in self.troops]

    @property
    def size(self):
        # number of Cavalry currently contained in Squadron
        return len(self.troops)

    @property
    def flagVars(self):
        return (self.flag.coords, self.flag.select, self.flag.attackMove,
                self.flag.angle, self.flag.change)

    @property
    def health(self):
        return sum(inf.size for inf in self.troops)

    def update(self):
        # move Squadron, update Cavalry, panic if necessary
        [unit.panic() for unit in self.troops if unit.panicTime > 0]
        for unit in self.troops:
            if unit.size <= 0:
                self.troops.remove(unit)
            elif unit.panicTime == -1:
                unit.update()

    def follow(self, flags):
        # move Squadron and Cavalry to flag
        if self.play:
            self.flag.checkDrag(flags)
        [unit.follow(*self.flagVars) for unit in self.troops]
        self.flag.change = False

    def aim(self):
        # turn toward selected target
        [troop.aim() for troop in self.troops]

    def orders(self):
        # give orders other than move for Squadron
        if not self.play or self.size == 0:
            return
        if self.flag.select != 0 or pygame.mouse.get_pressed()[2]:
            self.showOrders = 0
        mouse = pygame.mouse.get_pos()
        click = pygame.mouse.get_pressed()[0]
        touch = any([inf.rect.collidepoint(mouse) for inf in self.troops])
        if click and self.showOrders == 0 and touch:
            self.showOrders = 1
        if self.showOrders == 1 and not click:
            self.showOrders = 2
            # self.bayonetButton.draw(self.coords)
        if self.showOrders == 2 and click:
            self.showOrders = 3
            # if self.bayonetButton.rect.collidepoint(mouse):
            # self.bayonets = not self.bayonets
        if self.showOrders == 3 and not click:
            self.showOrders = 0

    def AIcommand(self, coords, attackMove=False):
        # orders Squadron to move to coords
        self.flag.coords = coords
        self.flag.attackMove = attackMove

    def AIsupport(self):
        # move to visible allies in combat
        if self.play or self.size == 0:
            return
        unit = self.troops[0]
        allyDist = unit.distanceMany([grp.coords for grp in unit.allies])
        for ally, d in zip(unit.allies, allyDist):
            cannon = hasattr(ally, 'shot')
            canSee = d < CV_SIGHT
            if unit.idle and ally.target is not None and canSee and not cannon:
                self.AIcommand(ally.target.coords, True)
                break

    def blitme(self):
        # print elements of Squadron
        [unit.blitme() for unit in self.troops]
        if self.size > 0:
            self.flag.blitme()
        if self.showOrders > 1:
            coords = self.troops[0].coords
            healthCoords = (coords[0], coords[1] - FB_SIZE[1])
            self.healthDisp.draw(healthCoords, str(self.health))
            self.healthDisp.blitme()
            # self.bayonetButton.blitme()

    def __str__(self):
        return self.id