Beispiel #1
0
 def f(x):
     lx = CellularAutomata.laplacian(x)
     lt = CellularAutomata.laplacian(target)
     return tf.reduce_mean(tf.square(lx[..., :3] - lt[..., :3]))
Beispiel #2
0
 def f(ca: CellularAutomata):
     return ca.imagestackfilled(["images/" + fn for fn in filenames])
Beispiel #3
0
def sconf_center_black_dot(ca: CellularAutomata):
    return ca.pointfilled(ca.constfilled(1.0), point_value=0.0)
Beispiel #4
0
 def f(ca: CellularAutomata):
     return ca.imagefilled("images/" + filename)
Beispiel #5
0
def sconf_one_everywhere(ca: CellularAutomata):
    return ca.constfilled(1.0)
Beispiel #6
0
def sconf_zero_everywhere(ca: CellularAutomata):
    return ca.constfilled(0.0)
Beispiel #7
0
    def reset_generation(self):
        # Map Terrain
        tile_indexes = len(self.data.keys()) - 1
        self.map = [[randint(0, tile_indexes) for i in range(self.map_width)]
                    for j in range(self.map_height)]
        self.map_clock = [[0 for i in range(self.map_width)]
                          for j in range(self.map_height)]

        # Create Border Around Map
        for x in range(self.map_width):
            self.map[0][x] = 0

        for y in range(self.map_height):
            self.map[y][0] = 0

        for x in range(self.map_width):
            self.map[self.map_height - 1][x] = 0

        for y in range(self.map_height):
            self.map[y][self.map_width - 1] = 0

        # Terrain 2nd Layer
        self.cellular_automata = CellularAutomata()
        self.cellular_automata.width = self.map_width
        self.cellular_automata.height = self.map_height
        self.cellular_automata.chance = 40
        self.cellular_automata.min_count = 5
        self.cellular_automata.iterations = 0
        self.cellular_automata.pillar_iterations = 1
        self.cellular_automata.flood_tries = 5
        self.cellular_automata.goal_percentage = 30  # above 30% seems to be a good target
        self.cellular_automata.generate()

        tree_indexes = len(self.tree_data.keys()) - 1
        self.tree_map = [[
            randint(1, tree_indexes)
            if self.cellular_automata.grid[j][i] == 1 else ''
            for i in range(self.map_width)
        ] for j in range(self.map_height)]

        for row in reversed(self.tree_map):
            print(row)

        # Viewpane Center
        self.viewpane_center_x = randint(1, self.map_width - 2)
        self.viewpane_center_y = randint(1, self.map_height - 2)

        # Player Input Variables
        self.player = Entity(name=choice(list(self.char_data.keys())))
        self.player.x = self.viewpane_center_x * self.tile_size
        self.player.y = self.viewpane_center_y * self.tile_size
        print(
            self.player.x // self.tile_size, self.player.y // self.tile_size,
            self.tree_map[self.player.x // self.tile_size][self.player.y //
                                                           self.tile_size])
        # Particles
        avg = (self.map_width + self.map_height) // 2

        # self.particles = [Particle(name='muzzle_01',
        #                            x=randint(0, self.map_width-1) * self.tile_size,
        #                            y=randint(0, self.map_height-1) * self.tile_size,
        #                            scale=1,
        #                            texture=self.particle_tex) for i in range(avg)]
        self.particles = [
            Particle(name='twirl_01',
                     x=randint(0, self.map_width - 1) * self.tile_size,
                     y=randint(0, self.map_height - 1) * self.tile_size,
                     scale=1,
                     texture=self.particle_tex) for i in range(avg)
        ]

        print('{} Particles generated'.format(len(self.particles)))

        # Char Entities
        char_names = list(self.char_data.keys())
        self.entities = [
            Entity(name=choice(char_names),
                   x=area[1] * self.tile_size,
                   y=area[0] * self.tile_size)
            for area in self.cellular_automata.areas_of_interest
        ]
        self.entities.append(self.player)
        # avg = (self.map_width + self.map_height) // 2
        # self.entities = [Entity(name=choice(char_names),
        #                         x=randint(0, self.map_width-1) * self.tile_size,
        #                         y=randint(0, self.map_height-1) * self.tile_size) for i in range(avg)]

        print('{} NPCs generated'.format(len(self.entities)))
Beispiel #8
0
class RenderWidget(Widget):
    data = {
    }  # dict of tile names pointing to a list of bytecode for each tile image
    data_size = {}  # dict of tile names pointing to a tuple of the image size
    blank_tex = None
    particle_tex = None
    player = None

    tree_data = {
    }  # dict of tile names pointing to a list of bytecode for each tree tile image
    tree_enum = {}

    char_data = {
    }  # dict of char names pointing to bytecode for each character image
    particles = []  # list of particles
    tile_enum = {}  # dict of integers pointing to a tile name
    entities = []  # list of NPCs
    foilage = []  # list of foilage
    cellular_automata = None

    tex = None  # texture layer for background tiles
    fov_tex = None  # texture layer containing FOV shadowing/lightning
    entities_tex = None  # texture layer containing entities
    tile_clock = None  # clock for constantly updating texture

    map = None  # map 2d array for tile integers
    map_clock = None  # map 2d array for what cycle image index each tile is on
    tree_map = None
    tree_clock = None

    viewpane_center_x = NumericProperty(0)  # center_x position for viewpane
    viewpane_center_y = NumericProperty(0)  # center_y position for viewpane

    tile_size = 32  # size of each tile, pixels
    player_x = NumericProperty(0)  # x-position of player
    player_y = NumericProperty(0)  # y-position of player
    player_speed = 8  # pixels per tick
    player_turn = True
    player_turn_speed = 0.01

    pressed_keys = {
        97: False,
        100: False,
        115: False,
        119: False,
        113: False,
        101: False
    }

    def __init__(self, **kwargs):
        super(RenderWidget, self).__init__(**kwargs)
        self.size = 608, 608
        self.tile_size = 32
        self.atlas = Atlas(ATLAS_FILE)
        self.atlas_trees = Atlas(ATLAS_TREE_FILE)
        self.char_atlas = Atlas(ATLAS_CHAR_FILE)
        self.map_width = 50
        self.map_height = 50

        # Load Particle Textures
        self.particle_tex = CoreImage('{}/assets/twirl_01.png'.format(
            os.getcwd())).texture
        # self.add_widget(self.kivy_particle)

        ind = -1
        for name, tex in self.atlas.textures.items():

            if '_' in name:
                tile_name, tile_number = name.split('_')
            else:
                tile_name, tile_number = name, '0'

            # tex.flip_vertical()
            if self.data.get(tile_name):
                self.data[tile_name].append(tex)
            else:
                ind += 1
                self.data[tile_name] = [tex]
            self.data_size[tile_name] = tex.size

            if not self.tile_enum.get(ind):
                self.tile_enum[ind] = tile_name

        # Tree Textures
        ind = 1
        for name, tex in self.atlas_trees.textures.items():
            self.tree_data[name] = tex
            self.tree_enum[ind] = name
            ind += 1

        # Entity Textures
        for name, tex in self.char_atlas.textures.items():
            self.char_data[name] = tex

        with self.canvas.before:
            Callback(self._set_blend_func)
        with self.canvas.after:
            Callback(self._reset_blend_func)

        self.initialize_tiles()
        Window.bind(on_key_down=self._keydown)
        Window.bind(on_key_up=self._keyup)
        Clock.schedule_interval(self.check_for_keys, 60**-1)
        self.tile_clock = Clock.schedule_interval(self.update_tiles, 60**-1)

    def _set_blend_func(self, instruction):
        #glBlendFunc(self.blend_factor_source, self.blend_factor_dest)
        #glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
        # glBlendFunc(GL_SRC_ALPHA, GL_ONE)
        pass

    def _reset_blend_func(self, instruction):
        # glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
        pass

    def on_player_x(self, instance, value):
        # Keep player_x between -tile_size and tile_size
        if self.player_x >= self.tile_size:
            self.viewpane_center_x -= 1
            self.player_x -= self.tile_size
        elif self.player_x <= -self.tile_size:
            self.viewpane_center_x += 1
            self.player_x += self.tile_size

        self.player.x = (
            (self.viewpane_center_x + 1) * self.tile_size) - self.player_x
        # self.player.x -= value

    def on_player_y(self, instance, value):
        # Keep player_x between -tile_size and tile_size
        if self.player_y >= self.tile_size:
            self.viewpane_center_y -= 1
            self.player_y -= self.tile_size

        elif self.player_y <= -self.tile_size:
            self.viewpane_center_y += 1
            self.player_y += self.tile_size

        self.player.y = (
            (self.viewpane_center_y + 1) * self.tile_size) - self.player_y
        # self.player.y -= value

    def toggle_player_turn(self, dt):
        self.player_turn = True

    def check_for_keys(self, dt):

        # if not self.player_turn:
        #     return

        x = self.player.x // self.tile_size
        y = self.player.y // self.tile_size

        # if self.pressed_keys[115]:
        if self.pressed_keys[115] and self.viewpane_center_y >= 0:
            # print(self.tree_map[y-1][x], not self.tree_map[y-1][x])
            # if self.pressed_keys[115] and self.viewpane_center_y > 0 + (self.height//2) // self.tile_size - 1:
            if not self.tree_map[y - 1][x]:
                self.player_y += self.player_speed
                # self.player_turn = False
                # Clock.schedule_once(self.toggle_player_turn, self.player_turn_speed)

        # if self.pressed_keys[119]:
        if self.pressed_keys[
                119] and self.viewpane_center_y <= self.map_height - 2:
            # print(self.tree_map[y+1][x], not self.tree_map[y+1][x])
            # if self.pressed_keys[119] and self.viewpane_center_y < self.map_height - (self.height//2) // self.tile_size - 1:
            if not self.tree_map[y + 1][x]:
                self.player_y -= self.player_speed
                # self.player_turn = False
                # Clock.schedule_once(self.toggle_player_turn, self.player_turn_speed)

        # if self.pressed_keys[100]:
        if self.pressed_keys[
                100] and self.viewpane_center_x <= self.map_width - 2:
            if not self.tree_map[y][x + 1]:
                self.player_x -= self.player_speed
                # self.player_turn = False
                # Clock.schedule_once(self.toggle_player_turn, self.player_turn_speed)

        # if self.pressed_keys[97]:
        if self.pressed_keys[97] and self.viewpane_center_x >= 0:
            # if self.pressed_keys[97] and self.viewpane_center_x > 0 + (self.width//2) // self.tile_size - 1:
            #     print(self.tree_map[y][x-1], not self.tree_map[y][x-1])
            if not self.tree_map[y][x - 1]:
                self.player_x += self.player_speed
                # self.player_turn = False
                # Clock.schedule_once(self.toggle_player_turn, self.player_turn_speed)

    def _keyup(self, keyboard, keycode, text, *args, **kwargs):
        pressed_key = keycode
        self.pressed_keys[pressed_key] = False

    def _keydown(self, keyboard, keycode, text, modifiers, *args, **kwargs):
        pressed_key = keycode
        self.pressed_keys[pressed_key] = True

    def reset_generation(self):
        # Map Terrain
        tile_indexes = len(self.data.keys()) - 1
        self.map = [[randint(0, tile_indexes) for i in range(self.map_width)]
                    for j in range(self.map_height)]
        self.map_clock = [[0 for i in range(self.map_width)]
                          for j in range(self.map_height)]

        # Create Border Around Map
        for x in range(self.map_width):
            self.map[0][x] = 0

        for y in range(self.map_height):
            self.map[y][0] = 0

        for x in range(self.map_width):
            self.map[self.map_height - 1][x] = 0

        for y in range(self.map_height):
            self.map[y][self.map_width - 1] = 0

        # Terrain 2nd Layer
        self.cellular_automata = CellularAutomata()
        self.cellular_automata.width = self.map_width
        self.cellular_automata.height = self.map_height
        self.cellular_automata.chance = 40
        self.cellular_automata.min_count = 5
        self.cellular_automata.iterations = 0
        self.cellular_automata.pillar_iterations = 1
        self.cellular_automata.flood_tries = 5
        self.cellular_automata.goal_percentage = 30  # above 30% seems to be a good target
        self.cellular_automata.generate()

        tree_indexes = len(self.tree_data.keys()) - 1
        self.tree_map = [[
            randint(1, tree_indexes)
            if self.cellular_automata.grid[j][i] == 1 else ''
            for i in range(self.map_width)
        ] for j in range(self.map_height)]

        for row in reversed(self.tree_map):
            print(row)

        # Viewpane Center
        self.viewpane_center_x = randint(1, self.map_width - 2)
        self.viewpane_center_y = randint(1, self.map_height - 2)

        # Player Input Variables
        self.player = Entity(name=choice(list(self.char_data.keys())))
        self.player.x = self.viewpane_center_x * self.tile_size
        self.player.y = self.viewpane_center_y * self.tile_size
        print(
            self.player.x // self.tile_size, self.player.y // self.tile_size,
            self.tree_map[self.player.x // self.tile_size][self.player.y //
                                                           self.tile_size])
        # Particles
        avg = (self.map_width + self.map_height) // 2

        # self.particles = [Particle(name='muzzle_01',
        #                            x=randint(0, self.map_width-1) * self.tile_size,
        #                            y=randint(0, self.map_height-1) * self.tile_size,
        #                            scale=1,
        #                            texture=self.particle_tex) for i in range(avg)]
        self.particles = [
            Particle(name='twirl_01',
                     x=randint(0, self.map_width - 1) * self.tile_size,
                     y=randint(0, self.map_height - 1) * self.tile_size,
                     scale=1,
                     texture=self.particle_tex) for i in range(avg)
        ]

        print('{} Particles generated'.format(len(self.particles)))

        # Char Entities
        char_names = list(self.char_data.keys())
        self.entities = [
            Entity(name=choice(char_names),
                   x=area[1] * self.tile_size,
                   y=area[0] * self.tile_size)
            for area in self.cellular_automata.areas_of_interest
        ]
        self.entities.append(self.player)
        # avg = (self.map_width + self.map_height) // 2
        # self.entities = [Entity(name=choice(char_names),
        #                         x=randint(0, self.map_width-1) * self.tile_size,
        #                         y=randint(0, self.map_height-1) * self.tile_size) for i in range(avg)]

        print('{} NPCs generated'.format(len(self.entities)))

    def initialize_tiles(self):
        # Create all Texture Layers
        self.blank_tex = Texture.create(size=self.size, colorfmt='rgba')
        self.blank_tex.blit_buffer(pbuffer=b'\x00\x00\x00\xff' *
                                   self.tile_size * self.tile_size * 4,
                                   size=(self.tile_size, self.tile_size),
                                   colorfmt='rgba',
                                   bufferfmt='ubyte')
        self.fov_tex = Texture.create(size=self.size, colorfmt='rgba')
        self.fov_tex.blit_buffer(pbuffer=b'\x00\x00\x00\xff' * self.tile_size *
                                 self.tile_size * 4,
                                 size=(self.tile_size, self.tile_size),
                                 colorfmt='rgba',
                                 bufferfmt='ubyte')
        self.tex = Texture.create(size=self.size, colorfmt='rgba')
        self.tex.mag_filter = 'nearest'
        self.entities_tex = Texture.create(size=self.size, colorfmt='rgba')
        self.entities_tex.mag_filter = 'nearest'

        # Initialize Texture Data
        size = self.width * self.height * 4
        buf = [255 for _ in range(size)]
        arr = array("B", buf)
        self.tex.blit_buffer(arr, colorfmt='rgba', bufferfmt=BUFFERFMT)
        self.reset_generation()
        # self.render_canvas()

    def resize(self, new_size):
        self.size = self.width + new_size, self.height + new_size
        if self.parent:
            self.parent.size = self.width - self.tile_size, self.height - self.tile_size

        self.initialize_tiles(0)

    def update_tiles(self, dt):
        # print(self.player.x, self.player.y)
        self.canvas.clear()
        viewpane_width = (self.width // self.tile_size) // 2
        viewpane_height = (self.height // self.tile_size) // 2
        fov_dist = 6
        center = (viewpane_width + viewpane_height + 1) // 2

        # Find Entities within View Pane
        entities_to_render = {}
        entities_to_render = self.find_entities_within_fov(
            viewpane_width, viewpane_height, fov_dist, dt)

        # Find Particle Entities within View Pane
        particles_to_render = {}
        particles_to_render = self.find_particles_within_fov(
            viewpane_width, viewpane_height, fov_dist, dt)

        with self.canvas:
            Color(1, 1, 1, 1.0)

            # Render Background Tiles Within
            for y in range(self.viewpane_center_y + viewpane_height + 1,
                           self.viewpane_center_y - viewpane_height - 1, -1):
                for x in range(self.viewpane_center_x + viewpane_width + 1,
                               self.viewpane_center_x - viewpane_width - 1,
                               -1):

                    Color(1, 1, 1, 1.0)
                    correct_x = x - self.viewpane_center_x + viewpane_width  # normalize to l0 thru map width
                    correct_y = y - self.viewpane_center_y + viewpane_height

                    try:
                        1 // (abs(y + 1) + y + 1)  # check for negative numbers
                        1 // (abs(x + 1) + x + 1)
                        tile_integer = self.map[y][x]
                        tile_name = self.tile_enum[(floor(tile_integer))]
                        tile_clock_ind = floor(self.map_clock[y][x])
                        tile_tex = self.data[tile_name][tile_clock_ind]

                    except ZeroDivisionError:
                        tile_tex = self.blank_tex  # default to black
                    except IndexError:
                        try:
                            self.map_clock[y][x] = 0
                            tile_tex = self.data[tile_name][0]
                        except:
                            tile_tex = self.blank_tex  # default to black
                    Color(1, 1, 1, 1.0)
                    Rectangle(
                        texture=tile_tex,
                        size=tile_tex.size,
                        pos=((correct_x * self.tile_size) + self.parent.x +
                             self.player_x - self.tile_size,
                             (correct_y * self.tile_size) + self.parent.y +
                             self.player_y - self.tile_size))

                    # Render Trees
                    try:
                        correct_x = x - self.viewpane_center_x + viewpane_width  # normalize to 0 thru map width
                        correct_y = y - self.viewpane_center_y + viewpane_height
                        1 // (abs(y + 1) + y + 1)
                        1 // (abs(x + 1) + x + 1)
                        tile_integer = self.tree_map[y][x]
                        tile_name = self.tree_enum[(floor(tile_integer))]
                        tile_tex = self.tree_data[tile_name]
                        # Color(1, 1, 1, randint(0, 255) / 255)
                        # Color(1, 1, 1, randint(200, 255) // 255)
                        Rectangle(
                            texture=tile_tex,
                            size=tile_tex.size,
                            pos=((correct_x * self.tile_size) + self.parent.x +
                                 self.player_x - self.tile_size,
                                 (correct_y * self.tile_size) + self.parent.y +
                                 self.player_y - self.tile_size))
                    except TypeError:
                        # If "None" is encountered from tree_map array with no object placed
                        # continue
                        pass
                    except IndexError:
                        # If x/y coordinates exceed tree_map array
                        # continue
                        pass
                    except ZeroDivisionError:
                        # Check for any x/y coordinates dips below 0, otherwise will select from end of array
                        # continue
                        pass

                    # Render Particle
                    p = particles_to_render.get((x, y))
                    if p:
                        p.update(dt)
                        correct_x = (
                            p.x // self.tile_size
                        ) - self.viewpane_center_x + viewpane_width
                        correct_y = (
                            p.y // self.tile_size
                        ) - self.viewpane_center_y + viewpane_height
                        PushMatrix()
                        r = Rotate()
                        r.angle = p.angle
                        r.axis = (0, 0, 1)
                        # r = Scale()
                        # r.x = p.scale
                        # r.y = p.scale
                        r.origin = (correct_x * self.tile_size +
                                    self.parent.x + self.player_x -
                                    (self.tile_size // 2)), (
                                        correct_y * self.tile_size +
                                        self.parent.y + self.player_y -
                                        (self.tile_size // 2))
                        Color(1, 1, 0, 1.0)
                        Rectangle(
                            texture=p.texture,
                            size=p.texture.size,
                            pos=((correct_x * self.tile_size + self.parent.x +
                                  self.player_x - self.tile_size),
                                 (correct_y * self.tile_size + self.parent.y +
                                  self.player_y - self.tile_size)))
                        PopMatrix()

                    # Render Entities
                    e = entities_to_render.get((x, y))
                    if e:
                        entity_tex = self.char_data[e.name]
                        correct_x = (e.x + self.tile_size * viewpane_width) - \
                                    (self.viewpane_center_x * self.tile_size)
                        correct_y = (e.y + self.tile_size * viewpane_height
                                     ) - (self.viewpane_center_y *
                                          self.tile_size)
                        Rectangle(texture=entity_tex,
                                  size=entity_tex.size,
                                  pos=((correct_x + self.parent.x +
                                        self.player_x - self.tile_size),
                                       (correct_y + self.parent.y +
                                        self.player_y - self.tile_size)))
            # FOV Rendering
            for x in range(self.viewpane_center_x + viewpane_width + 1,
                           self.viewpane_center_x - viewpane_width - 1, -1):
                for y in range(self.viewpane_center_y + viewpane_height + 1,
                               self.viewpane_center_y - viewpane_height - 1,
                               -1):
                    # FOV/Shadow Texture
                    correct_x = x - self.viewpane_center_x + viewpane_width  # normalize to 0 thru map width
                    correct_y = y - self.viewpane_center_y + viewpane_height

                    # Outside FOV
                    dist = self.calculate_distance(
                        correct_x - 1, correct_y - 1, center, center) + 0.05
                    if dist > fov_dist:
                        Color(0, 0, 0, 0.5)
                        Rectangle(
                            texture=self.blank_tex,
                            size=self.blank_tex.size,
                            pos=((correct_x * self.tile_size) + self.parent.x +
                                 self.player_x - self.tile_size,
                                 (correct_y * self.tile_size) + self.parent.y +
                                 self.player_y - self.tile_size))
                    # else:  # Within FOV
                    #     Color(1, 1, 1, 1/dist)
                    #     Rectangle(texture=self.blank_tex,
                    #               size=self.blank_tex.size,
                    #               pos=((correct_x * self.tile_size) + self.parent.x + self.player_x - self.tile_size,
                    #                    (correct_y * self.tile_size) + self.parent.y + self.player_y - self.tile_size))

    def find_entities_within_fov(self, viewpane_width, viewpane_height,
                                 fov_dist, dt):
        # Find All Entities Within fov_dist and return in {position:entity_object} form
        # Note: does not account if more than one entity is in the same position
        center = (viewpane_width + viewpane_height + 1) // 2
        render_entities = [e for e in self.entities \
                           if self.calculate_distance(
                (e.x // self.tile_size) - self.viewpane_center_x + viewpane_width - 1,
                (e.y // self.tile_size) - self.viewpane_center_y + viewpane_height - 1, center,
                center) <= fov_dist]

        return {(e.x // self.tile_size, e.y // self.tile_size): e
                for e in render_entities}

    def find_particles_within_fov(self, viewpane_width, viewpane_height,
                                  fov_dist, dt):
        center = (viewpane_width + viewpane_height + 1) // 2
        render_particles = [p for p in self.particles \
                           if self.calculate_distance(
                (p.x // self.tile_size) - self.viewpane_center_x + viewpane_width - 1,
                (p.y // self.tile_size) - self.viewpane_center_y + viewpane_height - 1, center,
                center) <= fov_dist]

        return {(p.x // self.tile_size, p.y // self.tile_size): p
                for p in render_particles}

    @staticmethod
    def calculate_distance(x1, y1, x2, y2):
        return sqrt((x2 - x1)**2 + (y2 - y1)**2)