Exemple #1
0
    def __init__(self, battle_mech):
        super(MechSprite, self).__init__()

        self.battle_mech = battle_mech

        mech_img = pyglet.resource.image(self.battle_mech.getImagePath())
        mech_img_grid = pyglet.image.ImageGrid(mech_img, 1, 6)

        self.static = True

        img_static = Sprite(mech_img_grid[0])

        self.width = img_static.width
        self.height = img_static.height

        # TODO: setup the non square friendly/enemy indicators based on team of current player's turn
        if battle_mech.player.is_bot:
            indicator = Sprite(Resources.enemy_indicator_img)
        else:
            indicator = Sprite(Resources.friendly_indicator_img)

        indicator.visible = False
        indicator.position = 0, -img_static.height // 2 + indicator.height // 2 + 1
        self.indicator = indicator
        self.add(indicator, z=0)

        shadow = Sprite(MechSprite.shadow_img_grid[battle_mech.getSize() - 1])
        shadow_rect = shadow.get_rect()
        shadow_rect.bottomleft = (self.battle_mech.col * Board.TILE_SIZE), \
                                 (self.battle_mech.row * Board.TILE_SIZE)
        shadow.position = shadow_rect.center
        self.shadow = shadow

        rect = img_static.get_rect()
        rect.bottomleft = (self.battle_mech.col * Board.TILE_SIZE) - (img_static.width//2 - shadow.width//2), \
                          (self.battle_mech.row * Board.TILE_SIZE)
        self.position = rect.center

        self.node = BatchNode()
        self.add(self.node, z=2)

        img_static.y = Board.TILE_SIZE//4
        self.node.add(img_static)
        self.img_static = img_static

        img_ct = Sprite(mech_img_grid[1])
        img_ct.y = Board.TILE_SIZE//4
        self.img_ct = img_ct

        img_ll = Sprite(mech_img_grid[4])
        img_ll.y = Board.TILE_SIZE//4
        self.img_ll = img_ll

        img_rl = Sprite(mech_img_grid[5])
        img_rl.y = Board.TILE_SIZE//4
        self.img_rl = img_rl

        img_la = Sprite(mech_img_grid[2])
        img_la.y = Board.TILE_SIZE//4
        self.img_la = img_la

        img_ra = Sprite(mech_img_grid[3])
        img_ra.y = Board.TILE_SIZE//4
        self.img_ra = img_ra

        # testing the stats stuff
        self.stats = BatchNode()
        self.updateStatsIndicators()
Exemple #2
0
def performAttackOnUnit(board, target_unit, overheat=0):
    # perform an attack on the given target BattleUnit
    battle = board.battle

    turn_unit = battle.getTurnUnit()
    if turn_unit is None or target_unit is None\
            or turn_unit.isDestroyed() or target_unit.isDestroyed():
        # TODO: make sure it is a player unit's turn
        return 0

    src_cell = turn_unit.col, turn_unit.row
    dest_cell = target_unit.col, target_unit.row

    # minimum travel time to target used to determine when to show the damage floater
    min_travel_time = 0
    # maximum travel time to target used to determine when all animations are finished
    max_travel_time = 0

    # cell distance used to determine which range of weapons will fire
    cell_distance = Battle.getCellDistance(src_cell, dest_cell)
    target_range = Battle.getDistanceRange(cell_distance)
    print(target_range + ": " + str(src_cell) + " -> " + str(dest_cell) + " = " + str(cell_distance))

    # perform the attack and show the results
    attack_results = battle.performAttack(turn_unit, target_unit, overheat=overheat)
    attack_damage = attack_results.attack_damage
    critical_type = attack_results.critical_type

    # determine actual target point based on the target unit sprite size
    target_sprite = target_unit.getSprite()
    real_x = (dest_cell[0] * Board.TILE_SIZE) + Board.TILE_SIZE // 2
    real_y = (dest_cell[1] * Board.TILE_SIZE) + (2 * target_sprite.get_height() // 3)

    # if missed, show a visible weapon miss
    if attack_damage == 0:
        real_x += random.choice([-1, 1]) * Board.TILE_SIZE
        real_y += random.choice([-1, 0, 1]) * Board.TILE_SIZE

    for weaponMap in turn_unit.mech.weapons:
        for weapon in weaponMap.iterkeys():

            if not weapon.inRange(cell_distance):
                continue

            weapon_data = weaponMap[weapon]

            # get sound channel to use just for this weapon
            weapon_channel = pygame.mixer.find_channel()
            if weapon_channel is None:
                weapon_channel = pygame.mixer.Channel(0)
            weapon_channel.set_volume(Settings.get_volume_fx())

            weapon_offset = weapon_data.get('offset', [0, 0])
            weapon_x = turn_unit.sprite.x + weapon_offset[0]
            weapon_y = turn_unit.sprite.y - (Board.TILE_SIZE // 2) + weapon_offset[1]

            weapon_color = weapon.get_color()

            if weapon.isPPC():
                # fire test ppcs
                ppc = Meteor()
                ppc.size = 10
                ppc.speed = 20
                ppc.gravity = Point2(0, 0)
                # TODO: offer decreased particle emission rate to improve performance
                ppc.emission_rate = 100
                ppc.life = 0.5
                ppc.life_var = 0.1

                ppc.position = weapon_x, weapon_y
                board.add(ppc, z=1000)

                target_x = real_x + random_offset()
                target_y = real_y + random_offset()
                target_pos = target_x, target_y

                # figure out the duration based on speed and distance
                ppc_speed = weapon.get_speed()  # pixels per second
                distance = Point2(ppc.x, ppc.y).distance(Point2(target_x, target_y))
                ppc_t = distance / ppc_speed

                ppc_sound = Resources.ppc_sound
                weapon_channel.play(ppc_sound)

                action = Delay(0.5) + MoveTo((target_x, target_y), duration=ppc_t) \
                         + CallFunc(impact_ppc, ppc) \
                         + Delay(0.5) + CallFunc(ppc.kill) \
                         + Delay(ppc_sound.get_length()) \
                         + CallFunc(weapon_channel.stop)

                ppc.do(action)

                travel_time = 0.5 + ppc_t
                if min_travel_time == 0 or min_travel_time > travel_time:
                    min_travel_time = travel_time

                if travel_time > max_travel_time:
                    max_travel_time = travel_time

            elif weapon.isFlamer():
                # fire test flamer
                flamer = Fire()

                flamer.size = 25
                flamer.speed = 300
                flamer.gravity = Point2(0, 0)
                # TODO: offer decreased particle emission rate to improve performance
                flamer.emission_rate = 100

                dx = real_x - weapon_x
                dy = real_y - weapon_y
                rads = atan2(-dy, dx)
                rads %= 2 * pi
                angle = degrees(rads) + 90

                flamer.rotation = angle
                flamer.angle_var = 5
                flamer.pos_var = Point2(5, 5)

                flamer.position = weapon_x, weapon_y
                board.add(flamer, z=1000)

                target_x = real_x + random_offset()
                target_y = real_y + random_offset()
                target_pos = target_x, target_y

                # figure out the duration based on speed and distance
                flamer_speed = weapon.get_speed()  # pixels per second
                distance = Point2(flamer.x, flamer.y).distance(Point2(target_x, target_y))
                flamer_t = 1

                flamer.life = distance / flamer_speed
                flamer.life_var = 0

                flamer_sound = Resources.flamer_sound
                weapon_channel.play(flamer_sound)

                action = Delay(flamer_t) \
                         + CallFunc(impact_flamer, flamer) \
                         + CallFunc(weapon_channel.fadeout, 750) \
                         + Delay(flamer_t) + CallFunc(flamer.kill) \
                         + CallFunc(weapon_channel.stop)

                flamer.do(action)

                travel_time = flamer_t
                if min_travel_time == 0 or min_travel_time > travel_time:
                    min_travel_time = travel_time

                if travel_time > max_travel_time:
                    max_travel_time = travel_time

            elif weapon.isLaser():
                # fire test laser
                las_life = 1.0
                las_size = (1, 1, 1)
                if weapon.isShort():
                    las_size = (2, 1, 0.5)
                    las_life = 0.5
                elif weapon.isMedium():
                    las_size = (3, 2, 1)
                    las_life = 0.75
                elif weapon.isLong():
                    las_size = (6, 4, 2)
                    las_life = 1.0

                target_x = real_x + random_offset()
                target_y = real_y + random_offset()
                target_pos = target_x, target_y

                las_outer = gl.SingleLine((weapon_x, weapon_y), (target_x, target_y),
                                          width=las_size[0],
                                          color=(weapon_color[0], weapon_color[1], weapon_color[2], 50))
                las_middle = gl.SingleLine((weapon_x, weapon_y), (target_x, target_y),
                                           width=las_size[1],
                                           color=(weapon_color[0], weapon_color[1], weapon_color[2], 125))
                las_inner = gl.SingleLine((weapon_x, weapon_y), (target_x, target_y),
                                          width=las_size[2],
                                          color=(weapon_color[0], weapon_color[1], weapon_color[2], 200))

                las_outer.visible = False
                las_middle.visible = False
                las_inner.visible = False

                node = cocos.layer.Layer()
                node.add(las_outer, z=1)
                node.add(las_middle, z=2)
                node.add(las_inner, z=3)
                board.add(node, z=1000)

                # give lasers a small particle pre-fire effect
                laser_charge = Galaxy()
                laser_charge.angle = 270
                laser_charge.angle_var = 180
                laser_charge.position = weapon_x, weapon_y
                laser_charge.size = 10
                laser_charge.size_var = 5
                laser_charge.emission_rate = 15
                laser_charge.life = 0.5
                laser_charge.speed = 0
                laser_charge.speed_var = 0
                laser_charge.start_color = Color(weapon_color[0] / 255, weapon_color[1] / 255, weapon_color[2] / 255,
                                                 1.0)
                laser_charge.end_color = Color(weapon_color[0] / 255, weapon_color[1] / 255, weapon_color[2] / 255, 1.0)
                node.add(laser_charge, z=0)

                laser_drift = random.uniform(-15.0, 15.0), random.uniform(-15.0, 15.0)

                las_action = Delay(0.5) + ToggleVisibility() \
                             + CallFunc(create_laser_impact, board, target_pos, laser_drift, las_life) \
                             + gl.LineDriftBy(laser_drift, las_life) \
                             + CallFunc(laser_charge.stop_system) + CallFunc(node.kill)
                las_outer.do(las_action)
                las_middle.do(las_action)
                las_inner.do(las_action)

                las_sound = Resources.las_sound
                weapon_channel.play(las_sound)
                las_duration_ms = int(las_action.duration * 1000)
                weapon_channel.fadeout(las_duration_ms)

                travel_time = 0.5
                if min_travel_time == 0 or min_travel_time > travel_time:
                    min_travel_time = travel_time

                if travel_time > max_travel_time:
                    max_travel_time = travel_time

            elif weapon.isBallistic():
                # fire test ballistic projectile
                num_ballistic = weapon.get_projectiles()

                if weapon.isGauss():
                    ballistic_img = Resources.gauss_img
                elif weapon.isLBX():
                    # LBX fires only one projectile, but will appear to have multiple random impacts
                    num_ballistic = 1
                    ballistic_img = Resources.buckshot_img
                else:
                    ballistic_img = Resources.ballistic_img

                # machine gun sound only plays once instead of per projectile
                cannon_sound = None
                if weapon.isMG():
                    cannon_sound = Resources.machinegun_sound
                elif weapon.isGauss():
                    cannon_sound = Resources.gauss_sound

                for i in range(num_ballistic):
                    ballistic = Sprite(ballistic_img)
                    ballistic.visible = False
                    ballistic.position = weapon_x, weapon_y
                    ballistic.scale = weapon.get_scale()
                    ballistic.anchor = 0, 0

                    dx = real_x - weapon_x
                    dy = real_y - weapon_y
                    rads = atan2(-dy, dx)
                    rads %= 2 * pi
                    angle = degrees(rads)

                    ballistic.rotation = angle

                    target_x = real_x + random_offset()
                    target_y = real_y + random_offset()
                    target_pos = target_x, target_y

                    # figure out the duration based on speed and distance
                    ballistic_speed = weapon.get_speed()  # pixels per second
                    distance = Point2(weapon_x, weapon_y).distance(Point2(target_x, target_y))
                    ballistic_t = distance / ballistic_speed

                    # setup the firing sound
                    if cannon_sound is None:
                        cannon_sound = Resources.cannon_sound

                    impact_func = create_ballistic_impact
                    if weapon.isLBX():
                        impact_func = create_lbx_impact

                    action = Delay(i * 0.1) + ToggleVisibility() \
                             + CallFunc(weapon_channel.play, cannon_sound) \
                             + MoveTo((target_x, target_y), ballistic_t) \
                             + CallFunc(impact_func, weapon, board, target_pos) \
                             + CallFunc(ballistic.kill)

                    if weapon.isGauss():
                        # give gauss sound a bit more time to stop
                        action += Delay(cannon_sound.get_length())

                    if i == num_ballistic - 1:
                        # stop the sound channel after the last projectile only
                        action += CallFunc(weapon_channel.stop)

                    ballistic.do(action)

                    board.add(ballistic, z=1000 + i)

                    travel_time = (i * 0.1) + ballistic_t
                    if min_travel_time == 0 or min_travel_time > travel_time:
                        min_travel_time = travel_time

                    if travel_time > max_travel_time:
                        max_travel_time = travel_time

            elif weapon.isMissile():
                # get another sound channel to use just for the explosions
                explosion_channel = pygame.mixer.find_channel()
                if explosion_channel is None:
                    explosion_channel = pygame.mixer.Channel(1)
                explosion_channel.set_volume(Settings.get_volume_fx())

                # fire test missile projectile
                missile_img = Resources.missile_img

                num_missile = weapon_data.get('count', 1)

                num_per_row = 1
                if weapon.isLRM():
                    num_per_row = 5
                elif weapon.isSRM():
                    num_per_row = 2

                for i in range(num_missile):

                    tube_x = i % num_per_row
                    tube_y = i // num_per_row

                    missile = Sprite(missile_img)
                    missile.visible = False
                    missile.position = weapon_x + tube_x, weapon_y + tube_y
                    missile.scale = weapon.get_scale()
                    missile.anchor = 0, 0

                    dx = real_x - weapon_x
                    dy = real_y - weapon_y
                    rads = atan2(-dy, dx)
                    rads %= 2 * pi
                    angle = degrees(rads)

                    missile.rotation = angle

                    target_x = real_x + random_offset()
                    target_y = real_y + random_offset()
                    target_pos = target_x, target_y

                    # figure out the duration based on speed and distance
                    missile_speed = weapon.get_speed()  # pixels per second
                    distance = Point2(weapon_x, weapon_y).distance(Point2(target_x, target_y))
                    missile_t = distance / missile_speed

                    rand_missile_sound = random.randint(0, 7)
                    missile_sound = Resources.missile_sounds[rand_missile_sound]

                    explosion_sound = Resources.impact_sound

                    action = Delay(i * 0.05) + ToggleVisibility() \
                             + CallFunc(weapon_channel.play, missile_sound) \
                             + MoveTo((target_x, target_y), missile_t) \
                             + CallFunc(create_missile_impact, board, target_pos) \
                             + CallFunc(missile.kill) \
                             + CallFunc(explosion_channel.play, explosion_sound) \
                             + Delay(0.5)

                    if i == num_missile - 1:
                        # stop the sound channels after the last missile only
                        action += CallFunc(weapon_channel.stop) + CallFunc(explosion_channel.stop)

                    missile.do(action)

                    board.add(missile, z=1000 + i)

                    travel_time = (i * 0.05) + missile_t
                    if min_travel_time == 0 or min_travel_time > travel_time:
                        min_travel_time = travel_time

                    if travel_time > max_travel_time:
                        max_travel_time = travel_time

    # scroll focus over to the target area halfway through the travel time
    target_area = Board.board_to_layer(target_unit.col, target_unit.row)

    # show damage floater after the travel time of the first projectile to hit
    floater_text = "%i" % attack_damage
    if attack_damage == 0:
        floater_text = "MISS"

    floater = floaters.TextFloater(floater_text)
    floater.visible = False
    floater.position = real_x, real_y + target_sprite.get_height() // 3
    board.add(floater, z=2000)

    action = Delay(min_travel_time / 2) + CallFunc(board.scroller.set_focus, *target_area) \
        + Delay(min_travel_time / 2) + ToggleVisibility() \
        + Delay(0.25) + MoveBy((0, Board.TILE_SIZE), 1.0) \
        + FadeOut(1.0) + CallFunc(floater.kill)
    floater.do(action)

    if critical_type is not None:
        crit_floater = floaters.TextFloater(critical_type)
        crit_floater.visible = False

        crit_floater.position = real_x, real_y + target_sprite.get_height() // 3
        board.add(crit_floater, z=2000)

        action = Delay(min_travel_time) + Delay(1.0) + ToggleVisibility() \
                 + Delay(0.25) + MoveBy((0, Board.TILE_SIZE), 1.5) \
                 + FadeOut(1.5) + CallFunc(crit_floater.kill)
        crit_floater.do(action)

    if action.duration > max_travel_time:
        max_travel_time = action.duration

    stats_action = Delay(min_travel_time) + CallFunc(target_sprite.updateStatsIndicators) \
                   + CallFunc(Interface.UI.updateTargetUnitStats, target_unit)
    target_sprite.do(stats_action)

    if target_unit.structure > 0:
        print("Remaining %i/%i" % (target_unit.armor, target_unit.structure))

    else:
        print("Target destroyed!")
        # show destroyed floater after the travel time of the first projectile to hit
        destroyed = floaters.TextFloater("DESTROYED")
        destroyed.visible = False
        destroyed.position = real_x, real_y + target_sprite.get_height() // 3
        board.add(destroyed, z=5000)

        action = Delay(max_travel_time) + ToggleVisibility() \
            + (MoveBy((0, Board.TILE_SIZE), 1.0) | CallFunc(create_destruction_explosions, board, target_unit)) \
            + Delay(0.5) + CallFunc(target_sprite.destroy) + FadeOut(2.0) + CallFunc(destroyed.kill)
        destroyed.do(action)

        # give a bit of extra time to explode
        max_travel_time = action.duration

    return max_travel_time
Exemple #3
0
def performAttackOnUnit(battle, target_unit):
    # perform an attack on the given target BattleUnit
    turn_unit = battle.getTurnUnit()
    if turn_unit is None or target_unit is None\
            or turn_unit.isDestroyed() or target_unit.isDestroyed():
        # TODO: make sure it is a player unit's turn
        return 0

    src_cell = turn_unit.col, turn_unit.row
    dest_cell = target_unit.col, target_unit.row

    # minimum travel time to target used to determine when to show the damage floater
    min_travel_time = 0
    # maximum travel time to target used to determine when all animations are finished
    max_travel_time = 0

    # cell distance used to determine which range of weapons will fire
    cell_distance = Battle.getCellDistance(src_cell, dest_cell)
    target_range = Battle.getDistanceRange(cell_distance)
    print(target_range + ": " + str(src_cell) + " -> " + str(dest_cell) +
          " = " + str(cell_distance))

    # TODO: introduce dynamic damage (optional?)
    attack_damage = int(getattr(turn_unit, target_range))

    # apply damage to model before animating
    attack_remainder = target_unit.applyDamage(attack_damage)

    # determine actual target point based on the target unit sprite size
    target_sprite = target_unit.getSprite()
    real_x = (dest_cell[0] * Board.TILE_SIZE) + Board.TILE_SIZE // 2
    real_y = (dest_cell[1] *
              Board.TILE_SIZE) + (2 * target_sprite.get_height() // 3)

    for weaponMap in turn_unit.mech.weapons:
        for weapon in weaponMap.iterkeys():

            if not weapon.inRange(cell_distance):
                continue

            weapon_data = weaponMap[weapon]

            # get sound channel to use just for this weapon
            weapon_channel = pygame.mixer.find_channel()
            if weapon_channel is None:
                weapon_channel = pygame.mixer.Channel(0)

            weapon_offset = weapon_data.get('offset', [0, 0])
            weapon_x = turn_unit.sprite.position[0] + weapon_offset[0]
            weapon_y = turn_unit.sprite.position[1] + weapon_offset[1]

            weapon_color = weapon.get_color()

            if weapon.isPPC():
                # fire test ppcs
                ppc = Meteor()
                ppc.size = 10
                ppc.speed = 20
                ppc.gravity = Point2(0, 0)
                # TODO: offer decreased particle emission rate to improve performance
                ppc.emission_rate = 100
                ppc.life = 0.5
                ppc.life_var = 0.1

                ppc.position = weapon_x, weapon_y
                battle.board.add(ppc, z=1000)

                target_x = real_x + random_offset()
                target_y = real_y + random_offset()
                target_pos = target_x, target_y

                # figure out the duration based on speed and distance
                ppc_speed = weapon.get_speed()  # pixels per second
                distance = Point2(ppc.x,
                                  ppc.y).distance(Point2(target_x, target_y))
                ppc_t = distance / ppc_speed

                ppc_sound = Resources.ppc_sound
                weapon_channel.play(ppc_sound)

                action = Delay(0.5) + MoveTo((target_x, target_y), duration=ppc_t) \
                         + CallFunc(impact_ppc, ppc) \
                         + Delay(0.5) + CallFunc(ppc.kill) \
                         + Delay(ppc_sound.get_length()) \
                         + CallFunc(weapon_channel.stop)

                ppc.do(action)

                travel_time = 0.5 + ppc_t
                if min_travel_time == 0 or min_travel_time > travel_time:
                    min_travel_time = travel_time

                if travel_time > max_travel_time:
                    max_travel_time = travel_time

            elif weapon.isFlamer():
                # fire test flamer
                flamer = Fire()

                flamer.size = 25
                flamer.speed = 300
                flamer.gravity = Point2(0, 0)
                # TODO: offer decreased particle emission rate to improve performance
                flamer.emission_rate = 100

                dx = real_x - weapon_x
                dy = real_y - weapon_y
                rads = atan2(-dy, dx)
                rads %= 2 * pi
                angle = degrees(rads) + 90

                flamer.rotation = angle
                flamer.angle_var = 5
                flamer.pos_var = Point2(5, 5)

                flamer.position = weapon_x, weapon_y
                battle.board.add(flamer, z=1000)

                target_x = real_x + random_offset()
                target_y = real_y + random_offset()
                target_pos = target_x, target_y

                # figure out the duration based on speed and distance
                flamer_speed = weapon.get_speed()  # pixels per second
                distance = Point2(flamer.x, flamer.y).distance(
                    Point2(target_x, target_y))
                flamer_t = 1

                flamer.life = distance / flamer_speed
                flamer.life_var = 0

                flamer_sound = Resources.flamer_sound
                weapon_channel.play(flamer_sound)

                action = Delay(flamer_t) \
                         + CallFunc(impact_flamer, flamer) \
                         + CallFunc(weapon_channel.fadeout, 750) \
                         + Delay(flamer_t) + CallFunc(flamer.kill) \
                         + CallFunc(weapon_channel.stop)

                flamer.do(action)

                travel_time = flamer_t
                if min_travel_time == 0 or min_travel_time > travel_time:
                    min_travel_time = travel_time

                if travel_time > max_travel_time:
                    max_travel_time = travel_time

            elif weapon.isLaser():
                # fire test laser
                las_life = 1.0
                las_size = (1, 1, 1)
                if weapon.isShort():
                    las_size = (2, 1, 0.5)
                    las_life = 0.5
                elif weapon.isMedium():
                    las_size = (3, 2, 1)
                    las_life = 0.75
                elif weapon.isLong():
                    las_size = (6, 4, 2)
                    las_life = 1.0

                target_x = real_x + random_offset()
                target_y = real_y + random_offset()
                target_pos = target_x, target_y

                las_outer = gl.SingleLine(
                    (weapon_x, weapon_y), (target_x, target_y),
                    width=las_size[0],
                    color=(weapon_color[0], weapon_color[1], weapon_color[2],
                           50))
                las_middle = gl.SingleLine(
                    (weapon_x, weapon_y), (target_x, target_y),
                    width=las_size[1],
                    color=(weapon_color[0], weapon_color[1], weapon_color[2],
                           125))
                las_inner = gl.SingleLine(
                    (weapon_x, weapon_y), (target_x, target_y),
                    width=las_size[2],
                    color=(weapon_color[0], weapon_color[1], weapon_color[2],
                           200))

                las_outer.visible = False
                las_middle.visible = False
                las_inner.visible = False

                node = cocos.layer.Layer()
                node.add(las_outer, z=1)
                node.add(las_middle, z=2)
                node.add(las_inner, z=3)
                battle.board.add(node, z=1000)

                # give lasers a small particle pre-fire effect
                laser_charge = Galaxy()
                laser_charge.angle = 270
                laser_charge.angle_var = 180
                laser_charge.position = weapon_x, weapon_y
                laser_charge.size = 10
                laser_charge.size_var = 5
                laser_charge.emission_rate = 15
                laser_charge.life = 0.5
                laser_charge.speed = 0
                laser_charge.speed_var = 0
                laser_charge.start_color = Color(weapon_color[0] / 255,
                                                 weapon_color[1] / 255,
                                                 weapon_color[2] / 255, 1.0)
                laser_charge.end_color = Color(weapon_color[0] / 255,
                                               weapon_color[1] / 255,
                                               weapon_color[2] / 255, 1.0)
                node.add(laser_charge, z=0)

                laser_drift = random.uniform(-15.0, 15.0), random.uniform(
                    -15.0, 15.0)

                las_action = Delay(0.5) + ToggleVisibility() \
                             + CallFunc(create_laser_impact, battle.board, target_pos, laser_drift, las_life) \
                             + gl.LineDriftBy(laser_drift, las_life) \
                             + CallFunc(laser_charge.stop_system) + CallFunc(node.kill)
                las_outer.do(las_action)
                las_middle.do(las_action)
                las_inner.do(las_action)

                las_sound = Resources.las_sound
                weapon_channel.play(las_sound)
                las_duration_ms = int(las_action.duration * 1000)
                weapon_channel.fadeout(las_duration_ms)

                travel_time = 0.5
                if min_travel_time == 0 or min_travel_time > travel_time:
                    min_travel_time = travel_time

                if travel_time > max_travel_time:
                    max_travel_time = travel_time

            elif weapon.isBallistic():
                # fire test ballistic projectile
                num_ballistic = weapon.get_projectiles()

                if weapon.isGauss():
                    ballistic_img = Resources.gauss_img
                elif weapon.isLBX():
                    # LBX fires only one projectile, but will appear to have multiple random impacts
                    num_ballistic = 1
                    ballistic_img = Resources.buckshot_img
                else:
                    ballistic_img = Resources.ballistic_img

                # machine gun sound only plays once instead of per projectile
                cannon_sound = None
                if weapon.isMG():
                    cannon_sound = Resources.machinegun_sound
                elif weapon.isGauss():
                    cannon_sound = Resources.gauss_sound

                for i in range(num_ballistic):
                    ballistic = Sprite(ballistic_img)
                    ballistic.visible = False
                    ballistic.position = weapon_x, weapon_y
                    ballistic.scale = weapon.get_scale()
                    ballistic.anchor = 0, 0

                    dx = real_x - weapon_x
                    dy = real_y - weapon_y
                    rads = atan2(-dy, dx)
                    rads %= 2 * pi
                    angle = degrees(rads)

                    ballistic.rotation = angle

                    target_x = real_x + random_offset()
                    target_y = real_y + random_offset()
                    target_pos = target_x, target_y

                    # figure out the duration based on speed and distance
                    ballistic_speed = weapon.get_speed()  # pixels per second
                    distance = Point2(weapon_x, weapon_y).distance(
                        Point2(target_x, target_y))
                    ballistic_t = distance / ballistic_speed

                    # setup the firing sound
                    if cannon_sound is None:
                        cannon_sound = Resources.cannon_sound

                    impact_func = create_ballistic_impact
                    if weapon.isLBX():
                        impact_func = create_lbx_impact

                    action = Delay(i * 0.1) + ToggleVisibility() \
                             + CallFunc(weapon_channel.play, cannon_sound) \
                             + MoveTo((target_x, target_y), ballistic_t) \
                             + CallFunc(impact_func, weapon, battle.board, target_pos) \
                             + CallFunc(ballistic.kill)

                    if weapon.isGauss():
                        # give gauss sound a bit more time to stop
                        action += Delay(cannon_sound.get_length())

                    if i == num_ballistic - 1:
                        # stop the sound channel after the last projectile only
                        action += CallFunc(weapon_channel.stop)

                    ballistic.do(action)

                    battle.board.add(ballistic, z=1000 + i)

                    travel_time = (i * 0.1) + ballistic_t
                    if min_travel_time == 0 or min_travel_time > travel_time:
                        min_travel_time = travel_time

                    if travel_time > max_travel_time:
                        max_travel_time = travel_time

            elif weapon.isMissile():
                # get another sound channel to use just for the explosions
                explosion_channel = pygame.mixer.find_channel()
                if explosion_channel is None:
                    explosion_channel = pygame.mixer.Channel(1)

                # fire test missile projectile
                missile_img = Resources.missile_img

                num_missile = weapon_data.get('count', 1)

                num_per_row = 1
                if weapon.isLRM():
                    num_per_row = 5
                elif weapon.isSRM():
                    num_per_row = 2

                for i in range(num_missile):

                    tube_x = i % num_per_row
                    tube_y = i // num_per_row

                    missile = Sprite(missile_img)
                    missile.visible = False
                    missile.position = weapon_x + tube_x, weapon_y + tube_y
                    missile.scale = weapon.get_scale()
                    missile.anchor = 0, 0

                    dx = real_x - weapon_x
                    dy = real_y - weapon_y
                    rads = atan2(-dy, dx)
                    rads %= 2 * pi
                    angle = degrees(rads)

                    missile.rotation = angle

                    target_x = real_x + random_offset()
                    target_y = real_y + random_offset()
                    target_pos = target_x, target_y

                    # figure out the duration based on speed and distance
                    missile_speed = weapon.get_speed()  # pixels per second
                    distance = Point2(weapon_x, weapon_y).distance(
                        Point2(target_x, target_y))
                    missile_t = distance / missile_speed

                    rand_missile_sound = random.randint(0, 7)
                    missile_sound = Resources.missile_sounds[
                        rand_missile_sound]

                    explosion_sound = Resources.explosion_sound

                    action = Delay(i * 0.05) + ToggleVisibility() \
                             + CallFunc(weapon_channel.play, missile_sound) \
                             + MoveTo((target_x, target_y), missile_t) \
                             + CallFunc(create_missile_impact, battle.board, target_pos) \
                             + CallFunc(missile.kill) \
                             + CallFunc(explosion_channel.play, explosion_sound) \
                             + Delay(0.5)

                    if i == num_missile - 1:
                        # stop the sound channels after the last missile only
                        action += CallFunc(weapon_channel.stop) + CallFunc(
                            explosion_channel.stop)

                    missile.do(action)

                    battle.board.add(missile, z=1000 + i)

                    travel_time = (i * 0.05) + missile_t
                    if min_travel_time == 0 or min_travel_time > travel_time:
                        min_travel_time = travel_time

                    if travel_time > max_travel_time:
                        max_travel_time = travel_time

    # scroll focus over to the target area halfway through the travel time
    target_area = Board.board_to_layer(target_unit.col, target_unit.row)

    # show damage floater after the travel time of the first projectile to hit
    floater = floaters.TextFloater("%i" % attack_damage)
    floater.visible = False
    floater.position = real_x, real_y + target_sprite.get_height() // 3
    battle.board.add(floater, z=2000)

    action = Delay(min_travel_time / 2) + CallFunc(battle.scroller.set_focus, *target_area) \
        + Delay(min_travel_time / 2) + ToggleVisibility() \
        + Delay(0.25) + MoveBy((0, Board.TILE_SIZE), 1.0) \
        + FadeOut(1.0) + CallFunc(floater.kill)
    floater.do(action)

    if action.duration > max_travel_time:
        max_travel_time = action.duration

    stats_action = Delay(min_travel_time) + CallFunc(target_sprite.updateStatsIndicators) \
                   + CallFunc(Interface.UI.updateTargetUnitStats, target_unit)
    target_sprite.do(stats_action)

    if attack_remainder > 0:
        print("Overkill by %i!" % attack_remainder)

    if target_unit.structure > 0:
        print("Remaining %i/%i" % (target_unit.armor, target_unit.structure))

    else:
        print("Target destroyed!")
        # show destroyed floater after the travel time of the first projectile to hit
        destroyed = floaters.TextFloater("DESTROYED")
        destroyed.visible = False
        destroyed.position = real_x, real_y + target_sprite.get_height() // 3
        battle.board.add(destroyed, z=5000)

        # get another sound channel to use just for the explosions
        explosion_channel = pygame.mixer.find_channel()
        if explosion_channel is None:
            explosion_channel = pygame.mixer.Channel(1)

        explosion_sound = Resources.explosion_multiple_sound

        action = Delay(max_travel_time) + ToggleVisibility() \
            + CallFunc(explosion_channel.play, explosion_sound) \
            + (MoveBy((0, Board.TILE_SIZE), 1.0) | CallFunc(create_destruction_explosions, battle.board, target_unit)) \
            + Delay(0.5) + CallFunc(target_sprite.destroy) + FadeOut(2.0) + CallFunc(destroyed.kill)
        destroyed.do(action)

        # give a bit of extra time to explode
        max_travel_time = action.duration

    return max_travel_time
 def __init__(self):
     super(RulersLayer, self).__init__()
     
     self._kCCBRulerWidth = 15
     
     self._stageOrigin = [0,0]
     self._winSize = [0,0]
     self._zoom = 1.0
     
     # TODO:@twenty0ne
     # CCScale9Sprite
     bgVertical = Sprite('images/ruler-bg-vertical.png')
     # TODO:@twenty0ne
     # notice image_anchor, anchor, transform_anchor difference
     bgVertical.image_anchor = 0,0
     self.add(bgVertical)
     self._bgVertical = bgVertical
     
     bgHorizontal = Sprite('images/ruler-bg-horizontal.png')
     bgHorizontal.image_anchor = 0,0
     self.add(bgHorizontal, z=2)
     self._bgHorizontal = bgHorizontal
     
     marksVertical = CocosNode()
     self.add(marksVertical, z=1)
     self._marksVertical = marksVertical
     
     marksHorizontal = CocosNode()
     self.add(marksHorizontal, z=3)
     self._marksHorizontal = marksHorizontal
     
     mouseMarkVertical = Sprite('images/ruler-guide.png')
     mouseMarkVertical.image_anchor = 0,0.5
     mouseMarkVertical.visible = False
     self.add(mouseMarkVertical, z=4)
     self._mouseMarkVertical = mouseMarkVertical
     
     mouseMarkHorizontal = Sprite('images/ruler-guide.png')
     mouseMarkHorizontal.rotation = -90
     mouseMarkHorizontal.image_anchor = 0,0.5
     mouseMarkHorizontal.visible = False
     self.add(mouseMarkHorizontal, z=4)
     self._mouseMarkHorizontal = mouseMarkHorizontal
     
     xyBg = Sprite('images/ruler-xy.png')
     xyBg.image_anchor = 0,0
     xyBg.position = 0,0
     self.add(xyBg, z=5)
     
     lblX = Label("0", position=(40,3), color=(0,0,0,255), font_size=8, anchor_x="right")
     #lblX.anchor = 1,0
     #lblX.position = 47,3
     lblX.visible = False
     self.add(lblX, z=6)
     self._lblX = lblX
     
     lblY = Label("0", position=(90,3), color=(0,0,0,255), font_size=8, anchor_x="right")
     #lblY.anchor = 1,0
     #lblY.position = 97,3
     lblY.visible = False
     self.add(lblY, z=6)
     self._lblY = lblY
Exemple #5
0
    def __init__(self, battle_mech):
        super(MechSprite, self).__init__()

        self.battle_mech = battle_mech

        mech_img = pyglet.resource.image(self.battle_mech.getImagePath())
        mech_img_grid = pyglet.image.ImageGrid(mech_img, 1, 6)

        self.static = True

        img_static = Sprite(mech_img_grid[0])

        self.width = img_static.width
        self.height = img_static.height

        # TODO: setup the non square friendly/enemy indicators based on team of current player's turn
        if battle_mech.player.is_bot:
            indicator = Sprite(Resources.enemy_indicator_img)
        else:
            indicator = Sprite(Resources.friendly_indicator_img)

        indicator.visible = False
        indicator.position = 0, -img_static.height // 2 + indicator.height // 2 + 1
        self.indicator = indicator
        self.add(indicator, z=0)

        shadow = Sprite(MechSprite.shadow_img_grid[battle_mech.getSize() - 1])
        shadow_rect = shadow.get_rect()
        shadow_rect.bottomleft = (self.battle_mech.col * Board.TILE_SIZE), \
                                 (self.battle_mech.row * Board.TILE_SIZE)
        shadow.position = shadow_rect.center
        self.shadow = shadow

        rect = img_static.get_rect()
        rect.bottomleft = (self.battle_mech.col * Board.TILE_SIZE) - (img_static.width//2 - shadow.width//2), \
                          (self.battle_mech.row * Board.TILE_SIZE)
        self.position = rect.center

        self.node = BatchNode()
        self.add(self.node, z=2)

        img_static.y = Board.TILE_SIZE//4
        self.node.add(img_static)
        self.img_static = img_static

        img_ct = Sprite(mech_img_grid[1])
        img_ct.y = Board.TILE_SIZE//4
        self.img_ct = img_ct

        img_ll = Sprite(mech_img_grid[4])
        img_ll.y = Board.TILE_SIZE//4
        self.img_ll = img_ll

        img_rl = Sprite(mech_img_grid[5])
        img_rl.y = Board.TILE_SIZE//4
        self.img_rl = img_rl

        img_la = Sprite(mech_img_grid[2])
        img_la.y = Board.TILE_SIZE//4
        self.img_la = img_la

        img_ra = Sprite(mech_img_grid[3])
        img_ra.y = Board.TILE_SIZE//4
        self.img_ra = img_ra

        # testing the stats stuff
        self.stats = BatchNode()
        self.updateStatsIndicators()