Beispiel #1
0
class Sun(ParticleSystem):

    # total particles
    total_particles = 350

    # duration
    duration = -1

    # gravity
    gravity = Point2(0, 0)

    # angle
    angle = 90.0
    angle_var = 360.0

    # speed of particles
    speed = 20.0
    speed_var = 5.0

    # radial
    radial_accel = 0
    radial_accel_var = 0

    # tangential
    tangential_accel = 0.0
    tangential_accel_var = 0.0

    # emitter variable position
    pos_var = Point2(0, 0)

    # life of particles
    life = 1.0
    life_var = 0.5

    # emits per frame
    emission_rate = total_particles / life

    # color of particles
    start_color = Color(0.75, 0.25, 0.12, 1.0)
    start_color_var = Color(0.0, 0.0, 0.0, 0.0)
    end_color = Color(0.0, 0.0, 0.0, 0.0)
    end_color_var = Color(0.0, 0.0, 0.0, 0.0)

    # size, in pixels
    size = 40.0
    size_var = 00.0

    # blend additive
    blend_additive = True

    # color modulate
    color_modulate = True
Beispiel #2
0
class Death(ParticleSystem):

    pic = resources.particleTexture
    texture = pic.get_texture()

    # total particles
    total_particles = 1000

    # duration
    duration = 0.12

    # gravity
    gravity = Point2(0, 0)

    # angle
    angle = 90
    angle_var = 360

    # radial
    radial_accel = -1000
    radial_accel_var = 100

    # speed of particles
    speed = 400
    speed_var = 50

    # emitter variable position
    pos_var = Point2(5, 5)

    # life of particles
    life = 0.3
    life_var = 0.1

    # emits per frame
    # emission_rate = total_particles / life
    emission_rate = 1000

    start_color = Color(1, 0.53, 0, 1.0)
    start_color_var = Color(0.0, 0.0, 0.0, 0.0)
    end_color = Color(1, 1, 1, 0)
    end_color_var = Color(0.0, 0.0, 0.0, 0.0)

    # size, in pixels
    size = 15
    size_var = 3

    # blend additive
    blend_additive = True

    # color modulate
    color_modulate = True
Beispiel #3
0
class Smoke(ParticleSystem):

    # total particles
    total_particles = 80

    # duration
    duration = -1

    # gravity
    gravity = Point2(0, 0)

    # angle
    angle = 90.0
    angle_var = 10.0

    # speed of particles
    speed = 25.0
    speed_var = 10.0

    # radial
    radial_accel = 5
    radial_accel_var = 0

    # tangential
    tangential_accel = 0.0
    tangential_accel_var = 0.0

    # emitter variable position
    pos_var = Point2(0.1, 0)

    # life of particles
    life = 4.0
    life_var = 1.0

    # size, in pixels
    size = 40.0
    size_var = 10.0

    # emits per frame
    emission_rate = total_particles / life

    start_color = Color(0.5, 0.5, 0.5, 0.1)
    start_color_var = Color(0, 0, 0, 0.1)
    end_color = Color(0.5, 0.5, 0.5, 0.1)
    end_color_var = Color(0, 0, 0, 0.1)

    # blend additive
    blend_additive = True

    # color modulate
    color_modulate = False
Beispiel #4
0
    def _calculate_vertex_points(self):
        w = float(self.texture.width)
        h = float(self.texture.height)

        index_points = []
        vertex_points_idx = []
        texture_points_idx = []

        for x in range(0, self.grid.x + 1):
            for y in range(0, self.grid.y + 1):
                vertex_points_idx += [-1, -1, -1]
                texture_points_idx += [-1, -1]

        for x in range(0, self.grid.x):
            for y in range(0, self.grid.y):
                x1 = x * self.x_step
                x2 = x1 + self.x_step
                y1 = y * self.y_step
                y2 = y1 + self.y_step

                #  d <-- c
                #        ^
                #        |
                #  a --> b
                a = x * (self.grid.y + 1) + y
                b = (x + 1) * (self.grid.y + 1) + y
                c = (x + 1) * (self.grid.y + 1) + (y + 1)
                d = x * (self.grid.y + 1) + (y + 1)

                # 2 triangles: a-b-d, b-c-d
                index_points += [a, b, d, b, c, d]    # triangles

                l1 = (a * 3, b * 3, c * 3, d * 3)
                l2 = (Point3(x1, y1, 0), Point3(x2, y1, 0), Point3(x2, y2, 0), Point3(x1, y2, 0))

                #  building the vertex
                for i in range(len(l1)):
                    vertex_points_idx[l1[i]] = l2[i].x
                    vertex_points_idx[l1[i] + 1] = l2[i].y
                    vertex_points_idx[l1[i] + 2] = l2[i].z

                # building the texels
                tex1 = (a * 2, b * 2, c * 2, d * 2)
                tex2 = (Point2(x1, y1), Point2(x2, y1), Point2(x2, y2), Point2(x1, y2))

                for i in range(len(tex1)):
                    texture_points_idx[tex1[i]] = tex2[i].x / w
                    texture_points_idx[tex1[i] + 1] = tex2[i].y / h

        return index_points, vertex_points_idx, texture_points_idx
Beispiel #5
0
class Explosion(ParticleSystem):

    # total particle
    total_particles = 700

    # duration
    duration = 0.1

    # gravity
    gravity = Point2(0, -90)

    # angle
    angle = 90.0
    angle_var = 360.0

    # radial
    radial_accel = 0
    radial_accel_var = 0

    # speed of particles
    speed = 70.0
    speed_var = 40.0

    # emitter variable position
    pos_var = Point2(0, 0)

    # life of particles
    life = 5.0
    life_var = 2.0

    # emits per frame
    emission_rate = total_particles / duration

    # color of particles
    start_color = Color(0.7, 0.2, 0.1, 1.0)
    start_color_var = Color(0.5, 0.5, 0.5, 0.0)
    end_color = Color(0.5, 0.5, 0.5, 0.0)
    end_color_var = Color(0.5, 0.5, 0.5, 0.0)

    # size, in pixels
    size = 15.0
    size_var = 10.0

    # blend additive
    blend_additive = False

    # color modulate
    color_modulate = True
Beispiel #6
0
class Fireworks(ParticleSystem):

    # total particles
    total_particles = 3000

    # duration
    duration = -1

    # gravity
    gravity = Point2(0, -90)

    # angle
    angle = 90
    angle_var = 20

    # radial
    radial_accel = 0
    radial_accel_var = 0

    # speed of particles
    speed = 180
    speed_var = 50

    # emitter variable position
    pos_var = Point2(0, 0)

    # life of particles
    life = 3.5
    life_var = 1

    # emits per frame
    emission_rate = total_particles / life

    # color of particles
    start_color = Color(0.5, 0.5, 0.5, 1.0)
    start_color_var = Color(0.5, 0.5, 0.5, 1.0)
    end_color = Color(0.1, 0.1, 0.1, 0.2)
    end_color_var = Color(0.1, 0.1, 0.1, 0.2)

    # size, in pixels
    size = 8.0
    size_var = 2.0

    # blend additive
    blend_additive = False

    # color modulate
    color_modulate = True
Beispiel #7
0
    def spawnStompCloud(self, reverse):
        # show cloud particles from stomps
        stomp_cloud = Meteor()
        stomp_cloud.start_color = cocos.particle.Color(0.3, 0.3, 0.3, 1.0)
        stomp_cloud.end_color = cocos.particle.Color(0.5, 0.5, 0.5, 0.2)
        stomp_cloud.duration = 0.1
        stomp_cloud.blend_additive = False
        stomp_cloud.size = 10 + (10 * self.battle_mech.getSize() / 4)
        stomp_cloud.speed = 20
        stomp_cloud.gravity = Point2(0, 0)
        # TODO: offer decreased particle emission rate to improve performance
        stomp_cloud.emission_rate = 100
        stomp_cloud.life = 0.5
        stomp_cloud.life_var = 0.1

        if not reverse:
            stomp_cloud.position = self.indicator.position[0] + (self.img_static.width // 4), \
                self.indicator.position[1] - self.indicator.height // 5
        else:
            stomp_cloud.position = self.indicator.position[0] - (self.img_static.width // 4), \
                self.indicator.position[1] - self.indicator.height // 5

        self.add(stomp_cloud, z=1)

        stomp_action = Delay(stomp_cloud.duration + stomp_cloud.life + stomp_cloud.life_var) \
            + CallFunc(stomp_cloud.kill)

        self.do(stomp_action)
Beispiel #8
0
    def __init__(self):
        self.rot = 0

        # left-bottom corner position corresponding to board array
        self.pos = Point2((Settings.COLUMN - self.n) // 2, Settings.ROW - 2)

        self.color_shape()
Beispiel #9
0
    def update_grid(self):
        win_size = director.get_window_size()
        grid_size = (win_size[0] / g_grid_size), (win_size[1] / g_grid_size)

        for x in xrange(grid_size[0] + 1):
            for y in xrange(grid_size[1] + 1):
                world_grid_pos = x, y

                world_pos = grid_to_world(world_grid_pos)
                aligned_world_pos = align_pos_to_grid(self.game_world.point_to_local(world_pos))

                # Visible if anything is visible within a radius
                fog_grid_pos = world_to_grid(aligned_world_pos)
                fog_visible = self.grid_pos_is_active(fog_grid_pos)

                if fog_visible:
                    radius = g_fog_neighbour_radius
                    for radius_x in xrange(-radius, radius + 1):
                        if not fog_visible:
                            break
                        for radius_y in xrange(-radius, radius + 1):
                            new_fog_grid_pos = tuple(fog_grid_pos + Point2(radius_x, radius_y))
                            fog_visible = self.grid_pos_is_active(new_fog_grid_pos)
                            if not fog_visible:
                                break

                self.squares_screen_space[world_grid_pos] = fog_visible

        for square in self.grid_canvases:
            if square.needs_update():
                square.free()
Beispiel #10
0
class Rain(ParticleSystem):
    def __init__(self, w, h):
        ParticleSystem.__init__(self, False)
        self.pos_var = Point2(w, 0)
        self.speed = h * 3.5
        self.speed_var = h * 2.5

    texture = pyglet.resource.image('res/particles/rain2.png').texture


    # def load_texture(self):
    #     return pyglet.image.load('res/particles/rain.png').texture

    # total paticles
    total_particles = 2000

    # duration
    duration = -1

    # gravity
    gravity = Point2(0, -100)

    # angle
    angle = -105.0
    angle_var = 0

    # speed of particles
    # speed = 300.0
    # speed_var = 0.0

    # radial
    # radial_accel = -380
    # radial_accel_var = 0

    # tangential
    # tangential_accel = 45.0
    # tangential_accel_var = 0.0

    # emitter variable position
    # pos_var = Point2(100, 0)

    # life of particles
    life = 12.0
    life_var = 0.0

    # emits per frame
    emission_rate = total_particles / life

    # color of particles
    start_color = Color(1, 1, 1, 0.5)
    # start_color_var = Color(0, 0, 0, 0.0)
    end_color = Color(1, 1, 1, 0)
    # end_color_var = Color(0, 0, 0, 0, 0.0)

    # size, in pixels
    size = 20.0
    size_var = 10.0

    # blend additive
    blend_additive = True
Beispiel #11
0
    def __init__(self):
        # load the image
        script_dir = os.path.dirname('.')
        path = os.path.join(script_dir, 'datas/cooling_map.png')
        self.image = pyglet.image.load(path)

        # get the texture
        self.texture = self.image.get_texture()

        # get image size
        x, y = self.image.width, self.image.height

        # size of the grid: 20 x 20
        # The image will be slipted in 20 squares x 20 tiles
        self.grid_size = Point2(10, 12)

        # size of each tile
        self.x_step = x // self.grid_size.x
        self.y_step = y // self.grid_size.y

        # calculate vertex, textures depending on image size
        idx_pts, ver_pts_idx, tex_pts_idx = self._calculate_vertex_points()

        # Generates an indexed vertex array with texture, vertex and color
        # http://www.glprogramming.com/red/chapter02.html#name6
        nb_vertex = (self.grid_size.x + 1) * (self.grid_size.y + 1)
        self.vertex_list = pyglet.graphics.vertex_list_indexed(
            nb_vertex, idx_pts, "t2f", "v3f/stream", "c4B")
        self.vertex_list.vertices = ver_pts_idx  # vertex points
        self.vertex_list.tex_coords = tex_pts_idx  # texels
        self.vertex_list.colors = (255, 255, 255, 255) * self.vertex_list.count

        # call the "step" method every frame when the layer is active
        self.elapsed = 0
Beispiel #12
0
class Explosion0(ParticleSystem):
    # total particles
    total_particles = 500

    # duration
    duration = 0.05

    # gravity
    gravity = Point2(0, 0)

    # angle
    angle = 90.0
    angle_var = 360

    # radial
    radial_accel = -200
    radial_accel_var = 40

    # speed of particles
    speed = 100
    speed_var = 80

    # emitter variable position
    pos_var = Point2(5, 5)

    # life of particles
    life = 0.18
    life_var = 0.1

    # emits per frame
    emission_rate = total_particles / life

    # color of particles
    start_color = Color(0.76, 0.25, 0.12, 1.0)
    start_color_var = Color(0.0, 0.0, 0.0, 0.0)
    end_color = Color(0.0, 0.0, 0.0, 1.0)
    end_color_var = Color(0.0, 0.0, 0.0, 0.0)

    # size, in pixels
    size = 70.0
    size_var = 10.0

    # blend additive
    blend_additive = True

    # color modulate
    color_modulate = True
Beispiel #13
0
    def moveToCell(self, col, row, reverse=False, func=None):
        num_steps = 1 + int(math.ceil(Point2(col, row).distance(Point2(self.battle_mech.col, self.battle_mech.row))))
        time = self.timeBySize() * (num_steps * 2)

        self.battle_mech.col = col
        self.battle_mech.row = row

        shadow_rect = self.shadow.get_rect()
        shadow_rect.bottomleft = (col * 32), (row * 32)

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

        actions = MoveTo(rect.center, duration=time)
        if func is not None:
            actions += CallFunc(func)

        self.do(actions)

        shadow_action = MoveTo(shadow_rect.center, duration=time)
        self.shadow.do(shadow_action)

        # play movement sounds
        sound_index = self.battle_mech.getSize() - 1

        stomp_sound = Resources.stomp_sounds[sound_index]
        stomp_action = Delay(0)
        for i in range(num_steps):
            # use channel 0 and 1 for alternating steps
            stomp_channel = pygame.mixer.Channel(i % 2)

            stomp_reverse = True
            if i % 2 == (1 if reverse else 0):
                stomp_reverse = False

            stomp_action += CallFunc(stomp_channel.play, stomp_sound) + Delay(time / num_steps) \
                + CallFunc(self.spawnStompCloud, stomp_reverse)

        self.do(stomp_action)

        return time
Beispiel #14
0
    def __init__(self):
        super( Character, self ).__init__()

        self.pos = Point2( COLUMNS//2-1, ROWS )
        self.status = 'STAY'

        s0 = pyglet.resource.image('fez.png')
        sprites = [s0]

        anim = pyglet.image.Animation.from_image_sequence(sprites, 0.5, True)
        self.sprite = pyglet.sprite.Sprite(anim)
Beispiel #15
0
class BigExplosion(cocos.particle_systems.Explosion):
    """玩家或敌人爆炸粒子系统"""

    speed = 100.0  # 粒子移动速度
    life = 0.5  # 粒子生命期
    life_var = 0.2
    size = 5.0  # 粒子大小
    size_var = 1.0  # 粒子大小偏差
    gravity = Point2(0, 0)  # 粒子的重力, (0, 0)不受重力影响
    start_color = Color(0.7, 0.2, 0.5, 1.0)  # 粒子的开始颜色
    start_color_var = Color(0.5, 0.5, 0.7, 0.0)  # 粒子开始颜色偏差
    end_color = Color(0.5, 0.5, 0.5, 0.3)  # 粒子的结束颜色
    end_color_var = Color(0.5, 0.5, 0.5, 0.0)  # 粒子的结束颜色偏差
Beispiel #16
0
    def __init__(self):
        super(Block, self).__init__()

        self.pos = Point2(COLUMNS // 2 - 1, ROWS)
        self.rot = 0

        for x in range(len(self._shape)):
            for y in range(len(self._shape[x])):
                if self._shape[x][y]:
                    r = random.random()
                    if r < status.level.prob:
                        color = random.choice(status.level.blocks)
                    else:
                        color = self.color
                    self._shape[x][y] = color
Beispiel #17
0
class BrokenBrick(ParticleSystem):
    total_particles = 4
    duration = 0.1
    gravity = Point2(0, -600)
    angle = 90
    angle_var = 90.0
    speed = 100.0
    life = 3.0
    size = 8.0
    start_color = Color(255, 255, 255, 255)
    end_color = Color(255, 255, 255, 255)
    emission_rate = total_particles / duration

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

        self.position = pos
        self.auto_remove_on_finish = True

    def load_texture(self):
        self.__class__.texture = Image.normal_brick2.get_texture()
Beispiel #18
0
    def __init__(self):

        super(Flag3D, self).__init__()

        # load the image
        self.image = pyglet.resource.image('flag.png')

        # get the texture
        self.texture = self.image.get_texture()

        # get image size
        x, y = self.image.width, self.image.height

        # size of the grid: 20 x 20
        # The image will be slipted in 20 squares x 20 tiles
        self.grid_size = Point2(20, 20)

        # size of each tile
        self.x_step = x // self.grid_size.x
        self.y_step = y // self.grid_size.y

        # calculate vertex, textures depending on image size
        idx_pts, ver_pts_idx, tex_pts_idx = self._calculate_vertex_points()

        # Generates an indexed vertex array with texture, vertex and color
        # http://www.glprogramming.com/red/chapter02.html#name6
        self.vertex_list = pyglet.graphics.vertex_list_indexed(
            (self.grid_size.x + 1) * (self.grid_size.y + 1), idx_pts, "t2f",
            "v3f/stream", "c4B")
        self.vertex_list.vertices = ver_pts_idx  # vertex points
        self.vertex_list.tex_coords = tex_pts_idx  # texels
        self.vertex_list.colors = (255, 255, 255, 255) * (
            self.grid_size.x + 1) * (self.grid_size.y + 1)  # colors

        # call the "step" method every frame when the layer is active
        self.schedule(self.step)
Beispiel #19
0
    def __init__(self):
        super(GameLayer, self).__init__()
        # 获得窗口的宽度和高度
        s_width, s_height = director.get_window_size()

        # 创建背景精灵
        background = Sprite('images/zippo.jpg')
        background.position = s_width // 2, s_height // 2
        # 添加背景精灵
        self.add(background, 0)

        ps = Fire()
        ps.gravity = Point2(45, 600)  # x,y轴重力加速度  x正值为右边  y正值为上
        ps.radial_accel = 60
        ps.size = 220
        ps.size_var = 50
        ps.tangential_accel = 20
        ps.tangential_accel_var = 10
        ps.life = 0.99
        ps.life_var = 0.45
        ps.emission_rate = 200
        ps.position = 270, 580

        self.add(ps)
Beispiel #20
0
    def init_particle(self):
        # position
        # p=self.particles[idx]

        a = self.particle_life < 0
        idxs = a.nonzero()

        idx = -1

        if len(idxs[0]) > 0:
            idx = idxs[0][0]
        else:
            raise ExceptionNoEmptyParticle()

        # position
        self.particle_pos[idx][0] = self.pos_var.x * rand()
        self.particle_pos[idx][1] = self.pos_var.y * rand()

        # start position
        self.start_pos[idx][0] = self.x
        self.start_pos[idx][1] = self.y

        a = math.radians(self.angle + self.angle_var * rand())
        v = Point2(math.cos(a), math.sin(a))
        s = self.speed + self.speed_var * rand()

        dir = v * s

        # direction
        self.particle_dir[idx][0] = dir.x
        self.particle_dir[idx][1] = dir.y

        # radial accel
        self.particle_rad[idx] = self.radial_accel + self.radial_accel_var * rand()

        # tangential accel
        self.particle_tan[idx] = self.tangential_accel + self.tangential_accel_var * rand()

        # life
        life = self.particle_life[idx] = self.life + self.life_var * rand()

        # Color
        # start
        sr = self.start_color.r + self.start_color_var.r * rand()
        sg = self.start_color.g + self.start_color_var.g * rand()
        sb = self.start_color.b + self.start_color_var.b * rand()
        sa = self.start_color.a + self.start_color_var.a * rand()

        self.particle_color[idx][0] = sr
        self.particle_color[idx][1] = sg
        self.particle_color[idx][2] = sb
        self.particle_color[idx][3] = sa

        # end
        er = self.end_color.r + self.end_color_var.r * rand()
        eg = self.end_color.g + self.end_color_var.g * rand()
        eb = self.end_color.b + self.end_color_var.b * rand()
        ea = self.end_color.a + self.end_color_var.a * rand()

        delta_color_r = (er - sr) / life
        delta_color_g = (eg - sg) / life
        delta_color_b = (eb - sb) / life
        delta_color_a = (ea - sa) / life

        self.particle_delta_color[idx][0] = delta_color_r
        self.particle_delta_color[idx][1] = delta_color_g
        self.particle_delta_color[idx][2] = delta_color_b
        self.particle_delta_color[idx][3] = delta_color_a

        # size
        self.particle_size[idx] = self.size + self.size_var * rand()
        self._scale_particle_size()

        # gravity
        self.particle_grav[idx][0] = self.gravity.x
        self.particle_grav[idx][1] = self.gravity.y
Beispiel #21
0
class ParticleSystem(CocosNode):
    """
    Base class for many flawors of cocos particle systems

    The most easy way to customize is subclass and redefine some class members;
    see particle_systems by example.

    If you want to use a custom texture remember it should hold only one image,
    so don't use texture = pyglet.resource.image(...) (it would produce an atlas,
    ie multiple images in a texture); using texture = pyglet.image.load(...) is fine
    """

    # type of particle
    POSITION_FREE, POSITION_GROUPED = range(2)

    #: is the particle system active ?
    active = True

    #: duration in seconds of the system. -1 is infinity
    duration = 0

    #: time elapsed since the start of the system (in seconds)
    elapsed = 0

    #: Gravity of the particles
    gravity = Point2(0.0, 0.0)

    #: position is from "superclass" CocosNode
    #: Position variance
    pos_var = Point2(0.0, 0.0)

    #: The angle (direction) of the particles measured in degrees
    angle = 0.0
    #: Angle variance measured in degrees;
    angle_var = 0.0

    #: The speed the particles will have.
    speed = 0.0
    #: The speed variance
    speed_var = 0.0

    #: Tangential acceleration
    tangential_accel = 0.0
    #: Tangential acceleration variance
    tangential_accel_var = 0.0

    #: Radial acceleration
    radial_accel = 0.0
    #: Radial acceleration variance
    radial_accel_var = 0.0

    #: Size of the particles
    size = 0.0
    #: Size variance
    size_var = 0.0

    #: How many seconds will the particle live
    life = 0
    #: Life variance
    life_var = 0

    #: Start color of the particles
    start_color = Color(0.0, 0.0, 0.0, 0.0)
    #: Start color variance
    start_color_var = Color(0.0, 0.0, 0.0, 0.0)
    #: End color of the particles
    end_color = Color(0.0, 0.0, 0.0, 0.0)
    #: End color variance
    end_color_var = Color(0.0, 0.0, 0.0, 0.0)

    #: Maximum particles
    total_particles = 0

    #: texture for the particles. Lazy loaded because Intel weakness, #235
    texture = None

    #: blend additive
    blend_additive = False

    #: color modulate
    color_modulate = True

    # position type
    position_type = POSITION_GROUPED

    def __init__(self, fallback=None):
        """
        fallback can be None, True, False; default is None
            False: use point sprites, faster, not always availabel
            True: use quads, slower but always available)
            None: autodetect, use the faster available

        """
        super(ParticleSystem, self).__init__()

        # particles
        # position x 2
        self.particle_pos = numpy.zeros((self.total_particles, 2), numpy.float32)
        # direction x 2
        self.particle_dir = numpy.zeros((self.total_particles, 2), numpy.float32)
        # rad accel x 1
        self.particle_rad = numpy.zeros((self.total_particles, 1), numpy.float32)
        # tan accel x 1
        self.particle_tan = numpy.zeros((self.total_particles, 1), numpy.float32)
        # gravity x 2
        self.particle_grav = numpy.zeros((self.total_particles, 2), numpy.float32)
        # colors x 4
        self.particle_color = numpy.zeros((self.total_particles, 4), numpy.float32)
        # delta colors x 4
        self.particle_delta_color = numpy.zeros((self.total_particles, 4), numpy.float32)
        # life x 1
        self.particle_life = numpy.zeros((self.total_particles, 1), numpy.float32)
        self.particle_life.fill(-1.0)
        # size x 1
        self.particle_size = numpy.zeros((self.total_particles, 1), numpy.float32)
        # particle size in respect to node scaling and window resizing
        self.particle_size_scaled = self.particle_size
        # start position
        self.start_pos = numpy.zeros((self.total_particles, 2), numpy.float32)

        #: How many particles can be emitted per second
        self.emit_counter = 0

        #: Count of particles
        self.particle_count = 0

        #: auto remove when particle finishes
        self.auto_remove_on_finish = False

        self.load_texture()

        #: rendering mode; True is quads, False is point_sprites, None is auto fallback
        if fallback is None:
            fallback = not point_sprites_available()
        self.fallback = fallback
        if fallback:
            self._fallback_init()
            self.draw = self.draw_fallback
        else:
            self._init_shader()

        self.schedule(self.step)

    def _init_shader(self):
        vertex_code = """
        #version 120
        attribute float particle_size;

        void main()
        {
            gl_PointSize = particle_size;
            gl_Position = ftransform();
            gl_FrontColor = gl_Color;
        }
        """
        frag_code = """
        #version 120
        uniform sampler2D sprite_texture;

        void main()
        {
            gl_FragColor = gl_Color * texture2D(sprite_texture, gl_PointCoord);
        }
        """
        self.sprite_shader = ShaderProgram.simple_program('sprite', vertex_code, frag_code)
        self.particle_size_idx = gl.glGetAttribLocation(self.sprite_shader.program, b'particle_size')

    def load_texture(self):
        if self.texture is None:
            pic = pyglet.image.load('fire.png', file=pyglet.resource.file('fire.png'))
            self.__class__.texture = pic.get_texture()

    def on_enter(self):
        super(ParticleSystem, self).on_enter()
        director.push_handlers(self)
        # self.add_particle()

    def on_exit(self):
        super(ParticleSystem, self).on_exit()
        director.remove_handlers(self)

    def on_cocos_resize(self, usable_width, usable_height):
        self._scale_particle_size()

    @CocosNode.scale.setter
    def scale(self, s):
        # Extend CocosNode scale setter property
        # The use of super(CocosNode, CocosNode).name.__set__(self, s) in the setter function is no mistake.
        # To delegate to the previous implementation of the setter, control needs to pass
        # through the __set__() method of the previously defined name property. However, the
        # only way to get to this method is to access it as a class variable instead of an instance
        # variable. This is what happens with the super(CocosNode, CocosNode) operation.
        super(ParticleSystem, ParticleSystem).scale.__set__(self, s)
        self._scale_particle_size()

    def _scale_particle_size(self):
        """Resize the particles in respect to node scaling and window resize;
        only used when rendering with shaders.
        """
        node = self
        scale = 1.0
        while node.parent:
            scale *= node.scale
            node = node.parent
        if director.autoscale:
            scale *= 1.0 * director._usable_width / director._window_virtual_width
        self.particle_size_scaled = self.particle_size * scale

    def draw(self):
        gl.glPushMatrix()
        self.transform()

        # color preserve - at least nvidia 6150SE needs that
        gl.glPushAttrib(gl.GL_CURRENT_BIT)
        # glPointSize(self.get_scaled_particle_size())

        gl.glEnable(gl.GL_TEXTURE_2D)
        gl.glEnable(gl.GL_PROGRAM_POINT_SIZE)
        # glBindTexture(GL_TEXTURE_2D, self.texture.id)


        gl.glEnable(gl.GL_POINT_SPRITE)
        gl.glTexEnvi(gl.GL_POINT_SPRITE, gl.GL_COORD_REPLACE, gl.GL_TRUE)

        gl.glEnableClientState(gl.GL_VERTEX_ARRAY)
        vertex_ptr = PointerToNumpy(self.particle_pos)
        gl.glVertexPointer(2, gl.GL_FLOAT, 0, vertex_ptr)

        gl.glEnableClientState(gl.GL_COLOR_ARRAY)
        color_ptr = PointerToNumpy(self.particle_color)
        gl.glColorPointer(4, gl.GL_FLOAT, 0, color_ptr)

        gl.glEnableVertexAttribArray(self.particle_size_idx)

        size_ptr = PointerToNumpy(self.particle_size_scaled)
        gl.glVertexAttribPointer(self.particle_size_idx, 1, gl.GL_FLOAT,
            False, 0, size_ptr)

        gl.glPushAttrib(gl.GL_COLOR_BUFFER_BIT)
        gl.glEnable(gl.GL_BLEND)
        if self.blend_additive:
            gl.glBlendFunc(gl.GL_SRC_ALPHA, gl.GL_ONE)
        else:
            gl.glBlendFunc(gl.GL_SRC_ALPHA, gl.GL_ONE_MINUS_SRC_ALPHA)

        # mode = GLint()
        # glTexEnviv( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, mode )
        #
        # if self.color_modulate:
        #   glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE )
        # else:
        #   glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE )

        self.sprite_shader.install()
        self.sprite_shader.usetTex('sprite_texture', 0, 
            gl.GL_TEXTURE_2D, self.texture.id)

        gl.glDrawArrays(gl.GL_POINTS, 0, self.total_particles)

        self.sprite_shader.uninstall()
        # un -blend
        gl.glPopAttrib()

        # color restore
        gl.glPopAttrib()

        # restore env mode
        # glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, mode)

        # disable states
        gl.glDisableVertexAttribArray(self.particle_size_idx)
        gl.glDisableClientState(gl.GL_COLOR_ARRAY)
        gl.glDisableClientState(gl.GL_VERTEX_ARRAY)

        gl.glDisable(gl.GL_POINT_SPRITE)
        gl.glDisable(gl.GL_PROGRAM_POINT_SIZE)
        gl.glDisable(gl.GL_TEXTURE_2D)

        gl.glPopMatrix()

    def step(self, delta):

        # update particle count
        self.particle_count = numpy.sum(self.particle_life >= 0)

        if self.active:
            rate = 1.0 / self.emission_rate
            self.emit_counter += delta

#            if random.random() < 0.01:
#                delta += 0.5

            while self.particle_count < self.total_particles and self.emit_counter > rate:
                self.add_particle()
                self.emit_counter -= rate

            self.elapsed += delta

            if self.duration != -1 and self.duration < self.elapsed:
                self.stop_system()

        self.update_particles(delta)

        if (not self.active and
                self.particle_count == 0 and self.auto_remove_on_finish is True):
                self.unschedule(self.step)
                self.parent.remove(self)

    def add_particle(self):
        """
        Code calling add_particle must be either:
          be sure there is room for the particle
          or
          be prepared to catch the exception ExceptionNoEmptyParticle
          It is acceptable to try: ... except...: pass
        """
        self.init_particle()
        self.particle_count += 1

    def stop_system(self):
        self.active = False
        self.elapsed = self.duration
        self.emit_counter = 0

    def reset_system(self):
        self.elapsed = self.duration
        self.emit_counter = 0

    def update_particles(self, delta):
        # radial: posx + posy
        norm = numpy.sqrt(self.particle_pos[:, 0] ** 2 + self.particle_pos[:, 1] ** 2)
        # XXX prevent div by 0
        norm = numpy.select([norm == 0], [0.0000001], default=norm)
        posx = self.particle_pos[:, 0] / norm
        posy = self.particle_pos[:, 1] / norm

        radial = numpy.array([posx, posy])
        tangential = numpy.array([-posy, posx])

        # update dir
        radial = numpy.swapaxes(radial, 0, 1)
        radial *= self.particle_rad
        tangential = numpy.swapaxes(tangential, 0, 1)
        tangential *= self.particle_tan

        self.particle_dir += (tangential + radial + self.particle_grav) * delta

        # update pos with updated dir
        self.particle_pos += self.particle_dir * delta

        # life
        self.particle_life -= delta

        # position: free or grouped
        if self.position_type == self.POSITION_FREE:
            tuple = numpy.array([self.x, self.y])
            tmp = tuple - self.start_pos
            self.particle_pos -= tmp

        # color
        self.particle_color += self.particle_delta_color * delta

        # if life < 0, set alpha in 0
        self.particle_color[:, 3] = numpy.select([self.particle_life[:, 0] < 0], [0],
                                                 default=self.particle_color[:, 3])

        # print self.particles[0]
        # print self.pas[0,0:4]

    def init_particle(self):
        # position
        # p=self.particles[idx]

        a = self.particle_life < 0
        idxs = a.nonzero()

        idx = -1

        if len(idxs[0]) > 0:
            idx = idxs[0][0]
        else:
            raise ExceptionNoEmptyParticle()

        # position
        self.particle_pos[idx][0] = self.pos_var.x * rand()
        self.particle_pos[idx][1] = self.pos_var.y * rand()

        # start position
        self.start_pos[idx][0] = self.x
        self.start_pos[idx][1] = self.y

        a = math.radians(self.angle + self.angle_var * rand())
        v = Point2(math.cos(a), math.sin(a))
        s = self.speed + self.speed_var * rand()

        dir = v * s

        # direction
        self.particle_dir[idx][0] = dir.x
        self.particle_dir[idx][1] = dir.y

        # radial accel
        self.particle_rad[idx] = self.radial_accel + self.radial_accel_var * rand()

        # tangential accel
        self.particle_tan[idx] = self.tangential_accel + self.tangential_accel_var * rand()

        # life
        life = self.particle_life[idx] = self.life + self.life_var * rand()

        # Color
        # start
        sr = self.start_color.r + self.start_color_var.r * rand()
        sg = self.start_color.g + self.start_color_var.g * rand()
        sb = self.start_color.b + self.start_color_var.b * rand()
        sa = self.start_color.a + self.start_color_var.a * rand()

        self.particle_color[idx][0] = sr
        self.particle_color[idx][1] = sg
        self.particle_color[idx][2] = sb
        self.particle_color[idx][3] = sa

        # end
        er = self.end_color.r + self.end_color_var.r * rand()
        eg = self.end_color.g + self.end_color_var.g * rand()
        eb = self.end_color.b + self.end_color_var.b * rand()
        ea = self.end_color.a + self.end_color_var.a * rand()

        delta_color_r = (er - sr) / life
        delta_color_g = (eg - sg) / life
        delta_color_b = (eb - sb) / life
        delta_color_a = (ea - sa) / life

        self.particle_delta_color[idx][0] = delta_color_r
        self.particle_delta_color[idx][1] = delta_color_g
        self.particle_delta_color[idx][2] = delta_color_b
        self.particle_delta_color[idx][3] = delta_color_a

        # size
        self.particle_size[idx] = self.size + self.size_var * rand()
        self._scale_particle_size()

        # gravity
        self.particle_grav[idx][0] = self.gravity.x
        self.particle_grav[idx][1] = self.gravity.y

    # Below only fallback functionality.
    # It uses quads instehad of point sprites, doing a transformation
    # point sprites buffers -> quads buffer, so any change in point sprite mode
    # is automatically reflects in the fallback mode (except for changes in the
    # draw method which should be manually adapted

    def _fallback_init(self):
        self.vertexs = numpy.zeros((self.total_particles, 4, 2), numpy.float32)
        tex_coords_for_quad = numpy.array([[0.0, 1.0], [0.0, 0.0], [1.0, 0.0], [1.0, 1.0]], numpy.float32)
        self.tex_coords = numpy.zeros((self.total_particles, 4, 2), numpy.float32)
        self.tex_coords[:] = tex_coords_for_quad[numpy.newaxis, :, :]
        self.per_vertex_colors = numpy.zeros((self.total_particles, 4, 4), numpy.float32)
        self.delta_pos_to_vertex = numpy.zeros((self.total_particles, 4, 2), numpy.float32)

    def draw_fallback(self):
        self.make_delta_pos_to_vertex()
        self.update_vertexs_from_pos()
        self.update_per_vertex_colors()

        gl.glPushMatrix()
        self.transform()

        # color preserve - at least intel 945G needs that
        gl.glPushAttrib(gl.GL_CURRENT_BIT)

        gl.glEnable(gl.GL_TEXTURE_2D)
        gl.glBindTexture(gl.GL_TEXTURE_2D, self.texture.id)

        gl.glEnableClientState(gl.GL_VERTEX_ARRAY)
        vertexs_ptr = PointerToNumpy(self.vertexs)
        gl.glVertexPointer(2, gl.GL_FLOAT, 0, vertexs_ptr)

        gl.glEnableClientState(gl.GL_COLOR_ARRAY)
        color_ptr = PointerToNumpy(self.per_vertex_colors)
        # gl.glColorPointer(4, gl.GL_UNSIGNED_BYTE, 0, color_ptr)
        gl.glColorPointer(4, gl.GL_FLOAT, 0, color_ptr)

        gl.glEnableClientState(gl.GL_TEXTURE_COORD_ARRAY)
        tex_coord_ptr = PointerToNumpy(self.tex_coords)
        gl.glTexCoordPointer(2, gl.GL_FLOAT, 0, tex_coord_ptr)

        gl.glPushAttrib(gl.GL_COLOR_BUFFER_BIT)
        gl.glEnable(gl.GL_BLEND)
        if self.blend_additive:
            gl.glBlendFunc(gl.GL_SRC_ALPHA, gl.GL_ONE)
        else:
            gl.glBlendFunc(gl.GL_SRC_ALPHA, gl.GL_ONE_MINUS_SRC_ALPHA)

        gl.glDrawArrays(gl.GL_QUADS, 0, len(self.vertexs) * 4)

        # un -blend
        gl.glPopAttrib()

        # color restore
        gl.glPopAttrib()

        # disable states
        gl.glDisableClientState(gl.GL_TEXTURE_COORD_ARRAY)
        gl.glDisableClientState(gl.GL_COLOR_ARRAY)
        gl.glDisableClientState(gl.GL_VERTEX_ARRAY)
        gl.glDisable(gl.GL_TEXTURE_2D)

        gl.glPopMatrix()

    def update_vertexs_from_pos(self):
        vertexs = self.vertexs
        delta = self.delta_pos_to_vertex
        pos = self.particle_pos
        vertexs[:] = delta + pos[:, numpy.newaxis, :]

    def update_per_vertex_colors(self):
        colors = self.particle_color
        per_vertex_colors = self.per_vertex_colors
        per_vertex_colors[:] = colors[:, numpy.newaxis, :]

    def make_delta_pos_to_vertex(self):
        size2 = self.particle_size / 2.0

        # counter-clockwise
        self.delta_pos_to_vertex[:,0] = numpy.array([-size2, +size2]).T  # NW
        self.delta_pos_to_vertex[:,1] = numpy.array([-size2, -size2]).T  # SW
        self.delta_pos_to_vertex[:,2] = numpy.array([+size2, -size2]).T  # SE
        self.delta_pos_to_vertex[:,3] = numpy.array([+size2, +size2]).T  # NE
Beispiel #22
0
 def __init__(self, w, h):
     ParticleSystem.__init__(self, False)
     self.pos_var = Point2(w, 0)
     self.speed = h * 3.5
     self.speed_var = h * 2.5
Beispiel #23
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
Beispiel #24
0
    def on_key_release(self, key, modifiers):
        self.keys_pressed.remove(key)

        move_key_map = {
            ord('w'): Point2(0, 1),
            ord('a'): Point2(-1, 0),
            ord('s'): Point2(0, -1),
            ord('d'): Point2(1, 0),
        }
        if key in move_key_map:
            grid_pos = world_to_grid(self.player.position)
            new_pos = Point2(grid_pos[0], grid_pos[1]) + move_key_map[key]
            if self.is_valid_player_grid_pos(new_pos):
                self.game_world.current_turn += 1
                self.player.position = grid_to_world(new_pos)

                # Do circle around player
                radius = g_player_view_radius
                square_radius = radius * radius
                for x in xrange(-radius, radius + 1):
                    for y in xrange(-radius, radius + 1):
                        if (x * x + y * y) <= square_radius:
                            target_pos = new_pos + (x, y)
                            hit, hit_pos = self.raytrace(new_pos, target_pos, ignore_half_cover=True)
                            if hit:
                                self.fow.set_grid_pos_visible(
                                    hit_pos,
                                    True,
                                    self.game_world.current_turn + g_steps_fog_stays_around)
                                self.fow_visited.set_grid_pos_visible(
                                    hit_pos,
                                    True,
                                    self.game_world.current_turn + g_steps_half_fog_stays_around)

                            # Check from around the player if we can't see.
                            if hit and g_check_around_player:
                                moves = [
                                    Point2(1, 0),
                                    Point2(-1, 0),
                                    Point2(0, 1),
                                    Point2(0, -1),
                                    Point2(1, 1),
                                    Point2(1, -1),
                                    Point2(-1, 1),
                                    Point2(-1, -1),
                                ]
                                for move in moves:
                                    if self.is_valid_player_grid_pos(new_pos + move):
                                        hit, hit_pos = self.raytrace(new_pos + move, target_pos, ignore_half_cover=True)
                                        if hit:
                                            self.fow.set_grid_pos_visible(
                                                hit_pos,
                                                True,
                                                self.game_world.current_turn + g_steps_fog_stays_around)
                                            self.fow_visited.set_grid_pos_visible(
                                                hit_pos,
                                                True,
                                                self.game_world.current_turn + g_steps_half_fog_stays_around)
                                        elif not hit:
                                            break

                            if not hit:
                                self.fow.set_grid_pos_visible(
                                    new_pos + (x, y),
                                    True,
                                    self.game_world.current_turn + g_steps_fog_stays_around)
                                self.fow_visited.set_grid_pos_visible(
                                    new_pos + (x, y),
                                    True,
                                    self.game_world.current_turn + g_steps_half_fog_stays_around)

                self.update_camera()
Beispiel #25
0
class PyFenseProjectileSlow(ParticleSystem, pyglet.event.EventDispatcher):
    """
    Projectile in the form of particles for the slow tower.
    Class variables have to be used because of ParticleSystem.
    """

    # total particles
    total_particles = 2000

    # duration
    duration = 0.1
    # gravity
    gravity = Point2(0, 0)

    # angle
    angle = 0
    angle_var = 5

    # radial
    radial_accel = 1000
    radial_accel_var = 0

    # speed of particles, fallback value
    speed = 800
    speed_var = 50

    # emitter variable position
    pos_var = Point2(12, 0)

    # distance that particles fly, fallback value
    distance = 200

    # life of particles, fallback value
    life = 5
    life_var = 0.005

    # emits per frame
    emission_rate = 500

    # color of particles
    start_color = Color(0.58, 0.98, 0.98, 1.0)
    start_color_var = Color(0.0, 0.0, 0.0, 0.6)
    end_color = Color(0.53, 0.96, 0.95, 1.0)
    end_color_var = Color(0.0, 0.0, 0.0, 0.2)

    # size, in pixels
    size = 40
    size_var = 2.0

    # blend additive
    blend_additive = True

    # color modulate
    color_modulate = True

    def __init__(self, towerParent, target, towerNumber, rotation, speed,
                 damage, effect, effectDuration, effectFactor):
        """
        Create a projectile and schedule event.

        :Parameters:
            `towerParent`: tower object
                Tower that launched the projectile.
            `target` : enemy object
                Enemy that is targeted.
            `towerNumber` : int
                Number of the parent tower.
            `rotation` : int
                Rotation of the parent tower.
            `speed` : int
                Speed of the particles.
            `damage` : int
                Damage the projectile causes.
            `effect` : string
                Effect that is caused by projectile (here: slow)
            `effectDuration` : int
                Duration that the effect is active.
            `effectFactor` : int
                How strong the effect is.
        """

        super().__init__()
        self.position = towerParent.position
        self.rotation = rotation - 90
        __class__.speed = speed
        __class__.distance = self._distance(target.position, self.position)
        __class__.life = __class__.distance / __class__.speed
        self.damage = damage

        self.schedule_interval(self._dispatch_hit_event, __class__.life,
                               target, towerNumber, effect, effectDuration,
                               effectFactor)

    def _dispatch_hit_event(self, dt, target, towerNumber, effect,
                            effectDuration, effectFactor):
        """
        Dispatch event when enemy is hit.

        The event is then handled by the enitites class in order to subtract
        health points from the enemy and to handle the different effects.
        """

        self.unschedule(self._dispatch_hit_event)
        self.dispatch_event('on_target_hit', self, target, towerNumber, effect,
                            effectDuration, effectFactor)

    def _distance(self, a, b):
        """
        Compute distance between two tupels (= position).
        """
        dis = math.sqrt((b[0] - a[0])**2 + (b[1] - a[1])**2)
        return dis
Beispiel #26
0
    def _calculate_vertex_points(self):
        # generate the vertex array with the correct values

        # size of the texture (power of 2)
        w = float(self.image.width) // self.texture.tex_coords[3]
        h = float(self.image.height) // self.texture.tex_coords[7]

        index_points = []
        vertex_points_idx = []
        texture_points_idx = []

        # generate 2 empty lists:
        #  vertex_list:
        #  texex_list:
        for x in range(0, self.grid_size.x + 1):
            for y in range(0, self.grid_size.y + 1):
                vertex_points_idx += [-1, -1, -1]
                texture_points_idx += [-1, -1]

        # since we are using vertex_list_indexed we must calculate
        # the index points
        for x in range(0, self.grid_size.x):
            for y in range(0, self.grid_size.y):
                x1 = x * self.x_step
                x2 = x1 + self.x_step
                y1 = y * self.y_step
                y2 = y1 + self.y_step

                #  d <-- c
                #        ^
                #        |
                #  a --> b
                a = x * (self.grid_size.y + 1) + y
                b = (x + 1) * (self.grid_size.y + 1) + y
                c = (x + 1) * (self.grid_size.y + 1) + (y + 1)
                d = x * (self.grid_size.y + 1) + (y + 1)

                # we are generating 2 triangles: a-b-d, b-c-d
                # (and not 1 quad, to prevent concave quads
                # although this example can work OK with quads)
                index_points += [a, b, d, b, c, d]

                l1 = (a * 3, b * 3, c * 3, d * 3)
                l2 = (Point3(x1, y1, 0), Point3(x2, y1, 0), Point3(x2, y2, 0),
                      Point3(x1, y2, 0))

                # populate the vertex list
                for i in range(len(l1)):
                    vertex_points_idx[l1[i]] = l2[i].x
                    vertex_points_idx[l1[i] + 1] = l2[i].y
                    vertex_points_idx[l1[i] + 2] = l2[i].z

                tex1 = (a * 2, b * 2, c * 2, d * 2)
                tex2 = (Point2(x1, y1), Point2(x2,
                                               y1), Point2(x2,
                                                           y2), Point2(x1, y2))
                # populate the texel list
                for i in range(len(l1)):
                    texture_points_idx[tex1[i]] = tex2[i].x / w
                    texture_points_idx[tex1[i] + 1] = tex2[i].y / h

        return (index_points, vertex_points_idx, texture_points_idx)
Beispiel #27
0
    def getCellDistance(cell_1, cell_2):
        point_1 = Point2(cell_1[0], cell_1[1])
        point_2 = Point2(cell_2[0], cell_2[1])

        return point_1.distance(point_2)