Exemplo n.º 1
0
def get_pos_delta_on_input(inp, map_, x, y, jump, flight):
    player_slice = map_[x]

    feet_y = y
    head_y = y - 1
    below_y = y + 1
    above_y = y - 2

    dx = -1 * ('a' in inp) + 1 * ('d' in inp)

    dx, dy = get_pos_delta(dx, x, y, map_)

    # Jumps if up pressed, block below, no block above
    if ( 'w' in inp and y > 1
         and (not is_solid( player_slice[above_y] )
              and ( is_solid( player_slice[below_y] )
                    or player_slice[feet_y] == '=' )
              or flight)):

        dy = -1
        jump = 6

    if (flight and 's' in inp and head_y < world_gen['height']
         and (not is_solid(player_slice[below_y]))):
        dy = 1

    return dx, dy, jump
Exemplo n.º 2
0
def spawn(mobs, players, map_, x_start_range, y_start_range, x_end_range,
          y_end_range):
    log("spawning", x_start_range, x_end_range, m='mobs')

    n_mobs_to_spawn = random.randint(0, 5) if random.random() < mob_rate else 0
    new_mobs = {}

    max_attempts = 100 * n_mobs_to_spawn
    attempts = 0

    while (len(mobs) + len(new_mobs) < mob_limit
           and len(new_mobs) < n_mobs_to_spawn and attempts < max_attempts):

        attempts += 1

        mx = random.randint(x_start_range, x_end_range - 1)
        my = random.randint(y_start_range, y_end_range - 1)

        if mx not in map_ or my < 1 or my > len(map_[mx]) - 2: continue

        feet = map_[mx][my]
        head = map_[mx][my - 1]
        floor = map_[mx][my + 1]

        closest_player_dist = min(
            map(lambda p: abs(p['x'] - mx), players.values()))

        spot_found = (not terrain.is_solid(feet) and not terrain.is_solid(head)
                      and terrain.is_solid(floor)
                      and render_interface.get_light_level(
                          mx, my) < max_spawn_light_level
                      and render_interface.get_light_level(
                          mx, my - 1) < max_spawn_light_level
                      and not closest_player_dist < spawn_player_range_min)

        if spot_found:
            new_mobs[str(uuid4())] = {
                'x': mx,
                'y': my,
                'x_vel': 0,
                'health': max_mob_health,
                'type': 'mob',
                'last_attack': 0
            }

    mobs.update(new_mobs)

    return new_mobs
Exemplo n.º 3
0
def get_char(x, y, map_, pixel):
    left = get_block(x-1, y, map_)
    right = get_block(x+1, y, map_)
    below = get_block(x, y+1, map_)

    char = blocks[pixel]['char']

    if below is None or not is_solid(below):

        if left is not None and is_solid(left) and 'char_left' in blocks[pixel]:
            char = blocks[pixel]['char_left']

        elif right is not None and is_solid(right) and 'char_right' in blocks[pixel]:
            char = blocks[pixel]['char_right']

    return char
Exemplo n.º 4
0
def pathfind_towards_delta(entity, delta, map_):
  updated = False
  kill_entity = False

  ex = entity['x']
  ey = entity['y']
  x_vel = entity['x_vel']

  x_vel += delta / 100
  if abs(x_vel) > 1:
      x_vel = x_vel / abs(x_vel)

  dx = round(x_vel)

  if (ex + dx - 1 not in map_.keys() or
          ex + dx not in map_.keys() or
          ex + dx + 1 not in map_.keys()):
      kill_entity = True

  else:
      dx, dy = player.get_pos_delta(dx, ex, ey, map_)
      ex, ey = ex + dx, ey + dy

      if not terrain.is_solid(map_[ex][ey + 1]):
          ey += 1

      entity['x'] = ex
      entity['y'] = ey
      entity['x_vel'] = x_vel

      updated = True

  return updated, kill_entity
Exemplo n.º 5
0
def pathfind_towards_delta(entity, delta, map_):
    updated = False
    kill_entity = False

    ex = entity['x']
    ey = entity['y']
    x_vel = entity['x_vel']

    x_vel += delta / 100
    if abs(x_vel) > 1:
        x_vel = x_vel / abs(x_vel)

    dx = round(x_vel)

    if (ex + dx - 1 not in map_.keys() or ex + dx not in map_.keys()
            or ex + dx + 1 not in map_.keys()):
        kill_entity = True

    else:
        dx, dy = player.get_pos_delta(dx, ex, ey, map_)
        ex, ey = ex + dx, ey + dy

        if not terrain.is_solid(map_[ex][ey + 1]):
            ey += 1

        entity['x'] = ex
        entity['y'] = ey
        entity['x_vel'] = x_vel

        updated = True

    return updated, kill_entity
Exemplo n.º 6
0
def spawn(mobs, players, map_, x_start_range, y_start_range, x_end_range, y_end_range):
    log("spawning", x_start_range, x_end_range, m='mobs');

    n_mobs_to_spawn = random.randint(0, 5) if random.random() < mob_rate else 0
    new_mobs = {}

    max_attempts = 100 * n_mobs_to_spawn
    attempts = 0

    while (len(mobs) + len(new_mobs) < mob_limit and
           len(new_mobs) < n_mobs_to_spawn and
           attempts < max_attempts):

        attempts += 1

        mx = random.randint(x_start_range, x_end_range-1)
        my = random.randint(y_start_range, y_end_range-1)

        if mx not in map_ or my < 1 or my > len(map_[mx]) - 2: continue

        feet = map_[mx][my]
        head = map_[mx][my - 1]
        floor = map_[mx][my + 1]

        closest_player_dist = min(map(lambda p: abs(p['x'] - mx), players.values()))

        spot_found = (not terrain.is_solid(feet) and
                      not terrain.is_solid(head) and
                      terrain.is_solid(floor) and
                      render_interface.get_light_level(mx, my) < max_spawn_light_level and
                      render_interface.get_light_level(mx, my - 1) < max_spawn_light_level and
                      not closest_player_dist < spawn_player_range_min)

        if spot_found:
            new_mobs[str(uuid4())] = {
                'x': mx,
                'y': my,
                'x_vel': 0,
                'health': max_mob_health,
                'type': 'mob',
                'last_attack': 0
            }

    mobs.update(new_mobs)

    return new_mobs
Exemplo n.º 7
0
def get_char(x, y, map_, pixel):
    left = get_block(x - 1, y, map_)
    right = get_block(x + 1, y, map_)
    below = get_block(x, y + 1, map_)

    char = blocks[pixel]['char']

    if below is None or not is_solid(below):

        if left is not None and is_solid(
                left) and 'char_left' in blocks[pixel]:
            char = blocks[pixel]['char_left']

        elif right is not None and is_solid(
                right) and 'char_right' in blocks[pixel]:
            char = blocks[pixel]['char_right']

    return char
Exemplo n.º 8
0
def get_pos_delta(dx, x, y, map_):

    player_slice = map_[x]

    feet_y = y
    head_y = y - 1
    below_y = y + 1
    above_y = y - 2

    dy = 0

    next_slice = map_[x + dx]
    checked_dx = 0
    if not is_solid(next_slice[head_y]):
        if is_solid( next_slice[feet_y] ):
            if ( not is_solid( next_slice[above_y] )
                 and not is_solid( player_slice[above_y] )):

                dy = -1
                checked_dx = dx
        else:
            checked_dx = dx

    return checked_dx, dy
Exemplo n.º 9
0
def get_pos_delta(char, map_, x, y, jump, flight):

    left_slice = map_[x - 1]
    player_slice = map_[x]
    right_slice = map_[x + 1]

    feet_y = y
    head_y = y - 1
    below_y = y + 1
    above_y = y - 2

    dy = 0
    dx = 0

    # Calculate change in x pos for left and right movement
    for test_char, dir_, next_slice in (('a', -1, left_slice), ('d', 1, right_slice)):
        if ( char in test_char
             and not is_solid( next_slice[head_y] )):

            if is_solid( next_slice[feet_y] ):
                if ( not is_solid( next_slice[above_y] )
                     and not is_solid( player_slice[above_y] )):

                    dy = -1
                    dx = dir_
            else:
                dx = dir_

    # Jumps if up pressed, block below, no block above
    if ( char in 'w' and y > 1
         and (not is_solid( player_slice[above_y] )
              and ( is_solid( player_slice[below_y] )
                    or player_slice[feet_y] == '=' )
              or flight)):

        dy = -1
        jump = 5

    if (flight and char in 's' and head_y < world_gen['height']
         and (not is_solid(player_slice[below_y]))):
        dy = 1

    return dx, dy, jump
Exemplo n.º 10
0
def get_pos_delta(char, map_, x, y, blocks, jump):

    left_slice = map_[x - 1]
    player_slice = map_[x]
    right_slice = map_[x + 1]

    feet_y = y
    head_y = y - 1
    below_y = y + 1
    above_y = y - 2

    dy = 0
    dx = 0

    is_solid = lambda block: terrain.is_solid(blocks, block)

    # Calculate change in x pos for left and right movement
    for test_char, dir_, func in (("a", -1, left_slice), ("d", 1, right_slice)):
        if char in test_char and not is_solid(func[head_y]):

            if is_solid(func[feet_y]):
                if not is_solid(func[above_y]) and not is_solid(player_slice[above_y]):

                    dy = -1
                    dx = dir_
            else:
                dx = dir_

    # Jumps if up pressed, block below, no block above
    if (
        char in "w"
        and y > 1
        and not is_solid(player_slice[above_y])
        and (is_solid(player_slice[below_y]) or player_slice[feet_y] == "=")
    ):

        dy = -1
        jump = 5

    return dx, dy, jump
Exemplo n.º 11
0
def light_mask(x, y, map_, slice_heights):
    if is_solid(map_[x][y]) or (world_gen['height'] - y) < slice_heights[x]:
        z = 0
    else:
        z = -1
    return z
Exemplo n.º 12
0
def game(server, settings, benchmarks):
    dt = 0  # Tick
    df = 0  # Frame
    dc = 0  # Cursor
    ds = 0  # Selector
    dpos = False
    dinv = False  # Inventory
    dcraft = False  # Crafting
    FPS = 15  # Max
    MPS = 15  # Movement
    SPS = 5  # Mob spawns

    old_bk_objects = None
    old_edges = None
    redraw_all = True
    last_move = time()
    last_mob_spawn = time()
    inp = None
    jump = 0
    cursor = 0
    crafting = False
    crafting_sel = 0
    crafting_list = []
    inv_sel = 0
    cursor_hidden = True
    new_blocks = {}
    alive = True
    events = []

    crafting_list, crafting_sel = player.get_crafting(
        server.inv,
        crafting_list,
        crafting_sel
    )

    # Game loop
    with NonBlockingInput() as nbi:
        while server.game:
            x, y = server.pos
            dt = server.dt()
            frame_start = time()

            ## Input

            char = True
            inp = []
            while char:
                # Receive input if a key is pressed
                char = nbi.char()
                if char:
                    char = str(char).lower()

                    if char in 'wasdhkjliuoc-=\n ':
                        inp.append(char)

            # Hard pause
            if DEBUG and '\n' in inp:
                input()
                inp.remove('\n')

            # Pause game
            if ' ' in inp or '\n' in inp:
                server.redraw = True
                redraw_all = True
                if ui.pause(server, settings) == 'exit':
                    server.logout()
                    continue

            width = settings.get('width')
            height = settings.get('height')

            # Update player and mobs position / damage
            move_period = 1 / MPS
            while frame_start >= move_period + last_move and x in server.map_:

                dx, dy, jump = player.get_pos_delta_on_input(
                    inp, server.map_, x, y, jump, settings.get('flight'))
                if dx or dy:
                    dpos = True
                    x += dx
                    y += dy

                if x in server.map_ and not settings.get('flight'):
                    # Player falls when no solid block below it and not jumping
                    jump -= dt
                    if jump <= 0:
                        jump = 0
                        if not terrain.is_solid(server.map_[x][y + 1]):
                            # Fall
                            y += 1
                            dpos = True

                if 'h' in inp:
                    item = render.blocks[server.inv[inv_sel]['block']] if len(server.inv) else {}
                    server.player_attack(item.get('attack_radius', 5), item.get('attack_damage', 10))

                server.update_items()
                server.update_mobs()

                if server.health <= 0:
                    alive = False

                last_move += move_period

            ## Update Map

            # Finds display boundaries
            edges = (x - int(width / 2), x + int(width / 2))
            edges_y = (y - int(height / 2), y + int(height / 2))

            if edges_y[1] > data.world_gen['height']:
                edges_y = (data.world_gen['height'] - height, data.world_gen['height'])
            elif edges_y[0] < 0:
                edges_y = (0, height)

            extended_edges = (edges[0]-render.max_light, edges[1]+render.max_light)

            slice_list = terrain.detect_edges(server.map_, extended_edges)
            if slice_list:
                log('slices to load', slice_list)
                chunk_list = terrain.get_chunk_list(slice_list)
                server.get_chunks(chunk_list)
                server.unload_slices(extended_edges)

            # Moving view
            if not edges == old_edges or server.view_change:
                extended_view = terrain.move_map(server.map_, extended_edges)
                old_edges = edges
                server.redraw = True
                server.view_change = False

            # Sun has moved
            bk_objects, sky_colour, day = render.bk_objects(server.time, width, edges[0], settings.get('fancy_lights'))
            if not bk_objects == old_bk_objects:
                old_bk_objects = bk_objects
                server.redraw = True

            if settings.get('gravity'):
                blocks = terrain.apply_gravity(server.map_, extended_edges)
                if blocks: server.set_blocks(blocks)

            ## Crafting

            if 'c' in inp:
                server.redraw = True
                crafting = not crafting and len(crafting_list)

            dcraft, dcraftC, dcraftN = False, False, False
            if dinv: crafting = False
            if crafting:
                # Craft if player pressed craft
                server.inv, inv_sel, crafting_list, dcraftC = \
                    player.crafting(inp, server.inv, inv_sel,
                        crafting_list, crafting_sel)

                # Increment/decrement craft no.
                crafting_list, dcraftN = \
                    player.craft_num(inp, server.inv, crafting_list,
                        crafting_sel)

                dcraft = dcraftC or dcraftN

            # Update crafting list
            crafting_list, crafting_sel = \
                player.get_crafting(server.inv, crafting_list,
                                    crafting_sel, dcraftC)
            if not len(crafting_list): crafting = False

            dc = player.move_cursor(inp)
            cursor = (cursor + dc) % 6

            ds = player.move_sel(inp)
            if crafting:
                crafting_sel = ((crafting_sel + ds) % len(crafting_list)
                                   if len(crafting_list) else 0)
            else:
                inv_sel = ((inv_sel + ds) % len(server.inv)
                              if len(server.inv) else 0)


            if any((dpos, dc, ds, dinv, dcraft)):
                server.redraw = True
            if dpos:
                dpos = False
                server.pos = x, y
                cursor_hidden = True
            if dc:
                cursor_hidden = False

            ## Eating or placing blocks

            p_hungry = server.health < player.MAX_PLAYER_HEALTH

            new_blocks, server.inv, inv_sel, new_events, dhealth, dinv = \
                player.cursor_func(
                    inp, server.map_, x, y, cursor, inv_sel, server.inv, p_hungry
                )

            server.add_health(dhealth)

            if new_blocks:
                server.set_blocks(new_blocks)

            ## Process events

            events += new_events

            new_blocks = {}
            for i in range(int(dt)):
                new_blocks.update(process_events(events, server))
            if new_blocks:
                server.set_blocks(new_blocks)

            # If no block below, kill player
            try:
                block = server.map_[x][y+1]
            except IndexError:
                alive = False

            # Respawn player if dead
            if not alive:
                if ui.respawn() == 'exit':
                    server.logout()
                    continue
                server.redraw = True
                redraw_all = True
                alive = True
                server.respawn()

            ## Spawning mobs / Generating lighting buffer

            lights = render.get_lights(extended_view, bk_objects, x)

            spawn_period = 1 / SPS
            n_mob_spawn_cycles = int((frame_start - last_mob_spawn) // spawn_period)
            last_mob_spawn += spawn_period * n_mob_spawn_cycles
            server.spawn_mobs(n_mob_spawn_cycles, bk_objects, sky_colour, day, lights)

            ## Render

            if server.redraw:
                server.redraw = False

                # TODO: It would be nice to reuse any of the lighting_buffer generated for the mobs which overlaps with the screen
                render_interface.create_lighting_buffer(width, height, edges[0], edges_y[0], server.map_, server.slice_heights, bk_objects, sky_colour, day, lights)

                entities = {
                    'player': list(server.current_players.values()),
                    'zombie': list(server.mobs.values())
                }

                objects = player.entities_to_render_objects(
                    entities, x, int(width / 2), edges
                )

                objects += items_to_render_objects(server.items, x, int(width / 2))

                if not cursor_hidden:
                    cursor_colour = player.cursor_colour(
                        x, y, cursor, server.map_, server.inv, inv_sel
                    )

                    objects.append(player.assemble_cursor(
                        int(width / 2), y, cursor, cursor_colour
                    ))

                render_args = [
                    server.map_,
                    server.slice_heights,
                    edges,
                    edges_y,
                    objects,
                    bk_objects,
                    sky_colour,
                    day,
                    lights,
                    settings,
                    redraw_all
                ]
                render_map = lambda: render_interface.render_map(*render_args)

                if benchmarks:
                    timer = timeit.Timer(render_map)
                    t = timer.timeit(1)
                    log('Render call time = {}'.format(t), m="benchmarks")
                else:
                    render_map()

                redraw_all = False

                crafting_grid = render.render_grid(
                    player.CRAFT_TITLE, crafting, crafting_list,
                    height, crafting_sel
                )

                inv_grid = render.render_grid(
                    player.INV_TITLE, not crafting, server.inv,
                    height, inv_sel
                )

                label = (player.label(crafting_list, crafting_sel)
                        if crafting else
                        player.label(server.inv, inv_sel))

                health = 'Health: {}/{}'.format(round(server.health), player.MAX_PLAYER_HEALTH)

                render.render_grids(
                    [
                        [inv_grid, crafting_grid],
                        [[label]],
                        [[health]]
                    ],
                    width, height
                )

                in_game_log('({}, {})'.format(x, y), 0, 0)

            d_frame = time() - frame_start
            if d_frame < (1/FPS):
                sleep((1/FPS) - d_frame)
Exemplo n.º 13
0
def light_mask(x, y, map_, slice_heights):
    if is_solid(map_[x][y]) or (world_gen['height'] - y) < slice_heights[x]:
        z = 0
    else:
        z = -1
    return z
Exemplo n.º 14
0
def game(blocks, meta, map_, save):
    x = meta['player_x']
    y = meta['player_y']
    dx = 0
    dy = 0
    dt = 0 # Tick
    df = 0 # Frame
    dc = 0 # Cursor
    ds = 0 # Selector
    dinv = False # Inventory
    dcraft = False # Crafting
    width = 40
    height = terrain.world_gen['height'] - 1
    FPS = 15 # Max
    TPS = 10 # Ticks
    IPS = 20 # Input
    MPS = 15 # Movement
    SUN_TICK = radians(1/32)

    old_bk_objects = None
    old_edges = None
    redraw = False
    last_frame = []
    last_out = time()
    last_tick = time()
    last_inp = time()
    last_move = time()
    inp = None
    jump = 0
    cursor = 0
    crafting = False
    crafting_sel = 0
    crafting_list = []
    inv_sel = 0
    c_hidden = True
    new_slices = {}
    alive = True
    events = []

    crafting_list, crafting_sel = player.get_crafting(
        meta['inv'],
        crafting_list,
        crafting_sel,
        blocks
    )

    # Game loop
    game = True
    with NonBlockingInput() as nbi:
        while game:
            # Finds display boundaries
            edges = (x - int(width / 2), x + int(width / 2))
            extended_edges = (edges[0]-render.max_light, edges[1]+render.max_light)

            # Generates new terrain
            slice_list = terrain.detect_edges(map_, extended_edges)
            for pos in slice_list:
                new_slices[pos] = terrain.gen_slice(pos, meta, blocks)
                map_[pos] = new_slices[pos]

            # Save new terrain to file
            if new_slices:
                saves.save_map(save, new_slices)
                new_slices = {}
                redraw = True

            # Moving view
            if not edges == old_edges:
                view = terrain.move_map(map_, edges)
                extended_view = terrain.move_map(map_, extended_edges)
                old_edges = edges
                redraw = True

            # Sun has moved
            bk_objects, sky_colour = render.bk_objects(meta['tick'], width)
            if not bk_objects == old_bk_objects:
                old_bk_objects = bk_objects
                redraw = True

            # Draw view
            if redraw and time() >= 1/FPS + last_out:
                df = 1
                redraw = False
                last_out = time()

                cursor_colour = player.cursor_colour(
                    x, y, cursor, map_, blocks, meta['inv'], inv_sel
                )

                objects = player.assemble_player(
                    int(width / 2), y, cursor, cursor_colour, c_hidden
                )

                lights = render.get_lights(extended_view, edges[0], blocks, bk_objects)

                out, last_frame = render.render_map(
                    view,
                    objects,
                    blocks,
                    bk_objects,
                    sky_colour,
                    lights,
                    meta['tick'],
                    last_frame
                )

                crafting_grid = render.render_grid(
                    player.CRAFT_TITLE, crafting, crafting_list, blocks,
                    height, crafting_sel
                )

                inv_grid = render.render_grid(
                    player.INV_TITLE, not crafting, meta['inv'], blocks,
                    height, inv_sel
                )

                label = (player.label(crafting_list, crafting_sel, blocks)
                        if crafting else
                        player.label(meta['inv'], inv_sel, blocks))

                out += render.render_grids(
                    [
                        [inv_grid, crafting_grid],
                        [[label]]
                    ],
                    width, height
                )

                print(out)
                in_game_debug('({}, {})'.format(x, y), 0, 0)
            else:
                df = 0

            # Respawn player if dead
            if not alive and df:
                alive = True
                x, y = player.respawn(meta)

            if dt:
                # Player falls when no solid block below it
                if jump > 0:
                    # Countdown till fall
                    jump -= 1
                elif not terrain.is_solid(blocks, map_[x][y+1]):
                    # Fall
                    y += 1
                    redraw = True

                new_new_slices = process_events(events, map_, blocks)
                new_slices.update(new_new_slices)
                map_.update(new_new_slices)

            # If no block below, kill player
            try:
                block = map_[x][y+1]
            except IndexError:
                alive = False

            # Receive input if a key is pressed
            char = str(nbi.char()).lower()
            inp = char if char in 'wadkjliuo-=' else None

            # Input Frame
            if time() >= (1/IPS) + last_inp and alive and inp:

                if time() >= (1/MPS) + last_move:
                    # Update player position
                    dx, dy, jump = player.get_pos_delta(
                        str(inp), map_, x, y, blocks, jump)
                    y += dy
                    x += dx

                    last_move = time()

                new_new_slices, meta['inv'], inv_sel, new_events, dinv = \
                    player.cursor_func(str(inp), map_, x, y, cursor, inv_sel, meta, blocks)

                map_.update(new_new_slices)
                new_slices.update(new_new_slices)

                events += new_events

                dcraft, dcraftC, dcraftN = False, False, False
                if dinv: crafting = False
                if crafting:
                    # Craft if player pressed craft
                    meta['inv'], inv_sel, crafting_list, dcraftC = \
                        player.crafting(str(inp), meta['inv'], inv_sel,
                            crafting_list, crafting_sel, blocks)

                    # Increment/decrement craft no.
                    crafting_list, dcraftN = \
                        player.craft_num(str(inp), meta['inv'], crafting_list,
                            crafting_sel, blocks)

                    dcraft = dcraftC or dcraftN

                # Update crafting list
                if dinv or dcraft:
                    crafting_list, crafting_sel = \
                        player.get_crafting(meta['inv'], crafting_list,
                                            crafting_sel, blocks, dcraftC)
                    if not len(crafting_list): crafting = False

                dc = player.move_cursor(inp)
                cursor = (cursor + dc) % 6

                ds = player.move_sel(inp)
                if crafting:
                    crafting_sel = ((crafting_sel + ds) % len(crafting_list)
                                       if len(crafting_list) else 0)
                else:
                    inv_sel = ((inv_sel + ds) % len(meta['inv'])
                                  if len(meta['inv']) else 0)

                if any((dx, dy, dc, ds, dinv, dcraft)):
                    meta['player_x'], meta['player_y'] = x, y
                    saves.save_meta(save, meta)
                    redraw = True
                if dx or dy:
                    c_hidden = True
                if dc:
                    c_hidden = False

                last_inp = time()
                inp = None

            if char in 'c':
                redraw = True
                crafting = not crafting and len(crafting_list)

            # Hard pause
            if DEBUG and char in '\n':
                input()
                char = '0'

            # Pause game
            if char in ' \n':
                meta['player_x'], meta['player_y'] = x, y
                saves.save_meta(save, meta)
                redraw = True
                last_frame = []
                if ui.pause() == 'exit':
                    game = False

            # Increase tick
            if time() >= (1/TPS) + last_tick:
                dt = 1
                meta['tick'] += SUN_TICK
                last_tick = time()
            else:
                dt = 0
Exemplo n.º 15
0
def game(server, settings, benchmarks):
    dt = 0  # Tick
    df = 0  # Frame
    dc = 0  # Cursor
    ds = 0  # Selector
    dpos = False
    dinv = False  # Inventory
    dcraft = False  # Crafting
    FPS = 15  # Max
    MPS = 15  # Movement
    SPS = 5  # Mob spawns

    old_bk_objects = None
    old_edges = None
    redraw_all = True
    last_move = time()
    last_mob_spawn = time()
    inp = None
    jump = 0
    cursor = 0
    crafting = False
    crafting_sel = 0
    crafting_list = []
    inv_sel = 0
    cursor_hidden = True
    new_blocks = {}
    alive = True
    events = []

    crafting_list, crafting_sel = player.get_crafting(server.inv,
                                                      crafting_list,
                                                      crafting_sel)

    # Game loop
    with NonBlockingInput() as nbi:
        while server.game:
            x, y = server.pos
            dt = server.dt()
            frame_start = time()

            ## Input

            char = True
            inp = []
            while char:
                # Receive input if a key is pressed
                char = nbi.char()
                if char:
                    char = str(char).lower()

                    if char in 'wasdhkjliuoc-=\n ':
                        inp.append(char)

            # Hard pause
            if DEBUG and '\n' in inp:
                input()
                inp.remove('\n')

            # Pause game
            if ' ' in inp or '\n' in inp:
                server.redraw = True
                redraw_all = True
                if ui.pause(server, settings) == 'exit':
                    server.logout()
                    continue

            width = settings.get('width')
            height = settings.get('height')

            # Update player and mobs position / damage
            move_period = 1 / MPS
            while frame_start >= move_period + last_move and x in server.map_:

                dx, dy, jump = player.get_pos_delta_on_input(
                    inp, server.map_, x, y, jump, settings.get('flight'))
                if dx or dy:
                    dpos = True
                    x += dx
                    y += dy

                if x in server.map_ and not settings.get('flight'):
                    # Player falls when no solid block below it and not jumping
                    jump -= dt
                    if jump <= 0:
                        jump = 0
                        if not terrain.is_solid(server.map_[x][y + 1]):
                            # Fall
                            y += 1
                            dpos = True

                if 'h' in inp:
                    item = render.blocks[server.inv[inv_sel]['block']] if len(
                        server.inv) else {}
                    server.player_attack(item.get('attack_radius', 5),
                                         item.get('attack_damage', 10))

                server.update_items()
                server.update_mobs()

                if server.health <= 0:
                    alive = False

                last_move += move_period

            ## Update Map

            # Finds display boundaries
            edges = (x - int(width / 2), x + int(width / 2))
            edges_y = (y - int(height / 2), y + int(height / 2))

            if edges_y[1] > data.world_gen['height']:
                edges_y = (data.world_gen['height'] - height,
                           data.world_gen['height'])
            elif edges_y[0] < 0:
                edges_y = (0, height)

            extended_edges = (edges[0] - render.max_light,
                              edges[1] + render.max_light)

            slice_list = terrain.detect_edges(server.map_, extended_edges)
            if slice_list:
                log('slices to load', slice_list)
                chunk_list = terrain.get_chunk_list(slice_list)
                server.get_chunks(chunk_list)
                server.unload_slices(extended_edges)

            # Moving view
            if not edges == old_edges or server.view_change:
                extended_view = terrain.move_map(server.map_, extended_edges)
                old_edges = edges
                server.redraw = True
                server.view_change = False

            # Sun has moved
            bk_objects, sky_colour, day = render.bk_objects(
                server.time, width, edges[0], settings.get('fancy_lights'))
            if not bk_objects == old_bk_objects:
                old_bk_objects = bk_objects
                server.redraw = True

            if settings.get('gravity'):
                blocks = terrain.apply_gravity(server.map_, extended_edges)
                if blocks: server.set_blocks(blocks)

            ## Crafting

            if 'c' in inp:
                server.redraw = True
                crafting = not crafting and len(crafting_list)

            dcraft, dcraftC, dcraftN = False, False, False
            if dinv: crafting = False
            if crafting:
                # Craft if player pressed craft
                server.inv, inv_sel, crafting_list, dcraftC = \
                    player.crafting(inp, server.inv, inv_sel,
                        crafting_list, crafting_sel)

                # Increment/decrement craft no.
                crafting_list, dcraftN = \
                    player.craft_num(inp, server.inv, crafting_list,
                        crafting_sel)

                dcraft = dcraftC or dcraftN

            # Update crafting list
            crafting_list, crafting_sel = \
                player.get_crafting(server.inv, crafting_list,
                                    crafting_sel, dcraftC)
            if not len(crafting_list): crafting = False

            dc = player.move_cursor(inp)
            cursor = (cursor + dc) % 6

            ds = player.move_sel(inp)
            if crafting:
                crafting_sel = ((crafting_sel + ds) % len(crafting_list)
                                if len(crafting_list) else 0)
            else:
                inv_sel = ((inv_sel + ds) %
                           len(server.inv) if len(server.inv) else 0)

            if any((dpos, dc, ds, dinv, dcraft)):
                server.redraw = True
            if dpos:
                dpos = False
                server.pos = x, y
                cursor_hidden = True
            if dc:
                cursor_hidden = False

            ## Eating or placing blocks

            p_hungry = server.health < player.MAX_PLAYER_HEALTH

            new_blocks, server.inv, inv_sel, new_events, dhealth, dinv = \
                player.cursor_func(
                    inp, server.map_, x, y, cursor, inv_sel, server.inv, p_hungry
                )

            server.add_health(dhealth)

            if new_blocks:
                server.set_blocks(new_blocks)

            ## Process events

            events += new_events

            new_blocks = {}
            for i in range(int(dt)):
                new_blocks.update(process_events(events, server))
            if new_blocks:
                server.set_blocks(new_blocks)

            # If no block below, kill player
            try:
                block = server.map_[x][y + 1]
            except IndexError:
                alive = False

            # Respawn player if dead
            if not alive:
                if ui.respawn() == 'exit':
                    server.logout()
                    continue
                server.redraw = True
                redraw_all = True
                alive = True
                server.respawn()

            ## Spawning mobs / Generating lighting buffer

            lights = render.get_lights(extended_view, bk_objects, x)

            spawn_period = 1 / SPS
            n_mob_spawn_cycles = int(
                (frame_start - last_mob_spawn) // spawn_period)
            last_mob_spawn += spawn_period * n_mob_spawn_cycles
            server.spawn_mobs(n_mob_spawn_cycles, bk_objects, sky_colour, day,
                              lights)

            ## Render

            if server.redraw:
                server.redraw = False

                # TODO: It would be nice to reuse any of the lighting_buffer generated for the mobs which overlaps with the screen
                render_interface.create_lighting_buffer(
                    width, height, edges[0], edges_y[0], server.map_,
                    server.slice_heights, bk_objects, sky_colour, day, lights)

                entities = {
                    'player': list(server.current_players.values()),
                    'zombie': list(server.mobs.values())
                }

                objects = player.entities_to_render_objects(
                    entities, x, int(width / 2), edges)

                objects += items_to_render_objects(server.items, x,
                                                   int(width / 2))

                if not cursor_hidden:
                    cursor_colour = player.cursor_colour(
                        x, y, cursor, server.map_, server.inv, inv_sel)

                    objects.append(
                        player.assemble_cursor(int(width / 2), y, cursor,
                                               cursor_colour))

                render_args = [
                    server.map_, server.slice_heights, edges, edges_y, objects,
                    bk_objects, sky_colour, day, lights, settings, redraw_all
                ]
                render_map = lambda: render_interface.render_map(*render_args)

                if benchmarks:
                    timer = timeit.Timer(render_map)
                    t = timer.timeit(1)
                    log('Render call time = {}'.format(t), m="benchmarks")
                else:
                    render_map()

                redraw_all = False

                crafting_grid = render.render_grid(player.CRAFT_TITLE,
                                                   crafting, crafting_list,
                                                   height, crafting_sel)

                inv_grid = render.render_grid(player.INV_TITLE, not crafting,
                                              server.inv, height, inv_sel)

                label = (player.label(crafting_list, crafting_sel)
                         if crafting else player.label(server.inv, inv_sel))

                health = 'Health: {}/{}'.format(round(server.health),
                                                player.MAX_PLAYER_HEALTH)

                render.render_grids(
                    [[inv_grid, crafting_grid], [[label]], [[health]]], width,
                    height)

                in_game_log('({}, {})'.format(x, y), 0, 0)

            d_frame = time() - frame_start
            if d_frame < (1 / FPS):
                sleep((1 / FPS) - d_frame)
Exemplo n.º 16
0
def game(server, settings):
    x, y = server.pos
    dx = 0
    dy = 0
    dt = 0  # Tick
    df = 0  # Frame
    dc = 0  # Cursor
    ds = 0  # Selector
    dinv = False  # Inventory
    dcraft = False  # Crafting
    FPS = 15  # Max
    IPS = 20  # Input
    MPS = 15  # Movement

    old_bk_objects = None
    old_edges = None
    last_frame = {}
    last_out = time()
    last_inp = time()
    last_move = time()
    inp = None
    jump = 0
    cursor = 0
    crafting = False
    crafting_sel = 0
    crafting_list = []
    inv_sel = 0
    c_hidden = True
    new_blocks = {}
    alive = True
    events = []

    crafting_list, crafting_sel = player.get_crafting(
        server.inv,
        crafting_list,
        crafting_sel
    )

    # Game loop
    with NonBlockingInput() as nbi:
        while server.game:
            x, y = server.pos

            width = settings.get('width')
            height = settings.get('height')

            sleep(1/1000)
            # Finds display boundaries
            edges = (x - int(width / 2), x + int(width / 2))
            edges_y = (y - int(height / 2), y + int(height / 2))

            if edges_y[1] > data.world_gen['height']:
                edges_y = (data.world_gen['height'] - height, data.world_gen['height'])
            elif edges_y[0] < 0:
                edges_y = (0, height)

            extended_edges = (edges[0]-render.max_light, edges[1]+render.max_light)

            slice_list = terrain.detect_edges(server.map_, extended_edges)
            if slice_list:
                log('slices to load', slice_list)
                chunk_list = terrain.get_chunk_list(slice_list)
                server.get_chunks(chunk_list)
                server.unload_slices(extended_edges)

            # Moving view
            if not edges == old_edges or server.view_change:
                extended_view = terrain.move_map(server.map_, extended_edges)
                old_edges = edges
                server.redraw = True
                server.view_change = False

            # Sun has moved
            bk_objects, sky_colour, day = render.bk_objects(server.time, width, settings.get('fancy_lights'))
            if not bk_objects == old_bk_objects:
                old_bk_objects = bk_objects
                server.redraw = True

            # Draw view
            if server.redraw and time() >= 1/FPS + last_out:
                df = 1
                server.redraw = False
                last_out = time()

                if settings.get('gravity'):
                    blocks = terrain.apply_gravity(server.map_, edges)
                    if blocks: server.set_blocks(blocks)

                cursor_colour = player.cursor_colour(
                    x, y, cursor, server.map_, server.inv, inv_sel
                )

                objects = player.assemble_players(
                    server.current_players, x, y, int(width / 2), edges
                )

                if not c_hidden:
                    objects.append(player.assemble_cursor(
                        int(width / 2), y, cursor, cursor_colour
                    ))

                lights = render.get_lights(extended_view, edges[0], bk_objects)

                out, last_frame = render.render_map(
                    server.map_,
                    server.slice_heights,
                    edges,
                    edges_y,
                    objects,
                    bk_objects,
                    sky_colour,
                    day,
                    lights,
                    last_frame,
                    settings.get('fancy_lights')
                )

                crafting_grid = render.render_grid(
                    player.CRAFT_TITLE, crafting, crafting_list,
                    height, crafting_sel
                )

                inv_grid = render.render_grid(
                    player.INV_TITLE, not crafting, server.inv,
                    height, inv_sel
                )

                label = (player.label(crafting_list, crafting_sel)
                        if crafting else
                        player.label(server.inv, inv_sel))

                out += render.render_grids(
                    [
                        [inv_grid, crafting_grid],
                        [[label]]
                    ],
                    width, height
                )

                print(out)
                in_game_log('({}, {})'.format(x, y), 0, 0)
            else:
                df = 0

            # Respawn player if dead
            if not alive and df:
                alive = True
                server.respawn()

            if dt and server.chunk_loaded(x):

                if not settings.get('flight'):
                    # Player falls when no solid block below it
                    if jump > 0:
                        # Countdown till fall
                        jump -= 1
                    elif not terrain.is_solid(server.map_[x][y+1]):
                        # Fall
                        y += 1
                        server.pos = x, y
                        server.redraw = True

                new_blocks = process_events(events, server.map_)

                if new_blocks:
                    server.set_blocks(new_blocks)

            # If no block below, kill player
            try:
                block = server.map_[x][y+1]
            except IndexError:
                alive = False

            # Receive input if a key is pressed
            char = str(nbi.char()).lower()
            inp = char if char in 'wasdkjliuo-=' else None

            # Input Frame
            if time() >= (1/IPS) + last_inp and alive and inp:

                if time() >= (1/MPS) + last_move:
                    # Update player position
                    dx, dy, jump = player.get_pos_delta(
                        str(inp), server.map_, x, y, jump, settings.get('flight'))
                    y += dy
                    x += dx

                    last_move = time()

                new_blocks, inv, inv_sel, new_events, dinv = \
                    player.cursor_func(
                        str(inp), server.map_, x, y, cursor, inv_sel, server.inv
                    )

                if dinv:
                    server.inv = inv

                if new_blocks:
                    server.set_blocks(new_blocks)

                events += new_events

                dcraft, dcraftC, dcraftN = False, False, False
                if dinv: crafting = False
                if crafting:
                    # Craft if player pressed craft
                    inv, inv_sel, crafting_list, dcraftC = \
                        player.crafting(str(inp), server.inv, inv_sel,
                            crafting_list, crafting_sel)
                    if dcraftC:
                        server.inv = inv

                    # Increment/decrement craft no.
                    crafting_list, dcraftN = \
                        player.craft_num(str(inp), server.inv, crafting_list,
                            crafting_sel)

                    dcraft = dcraftC or dcraftN

                # Update crafting list
                if dinv or dcraft:
                    crafting_list, crafting_sel = \
                        player.get_crafting(server.inv, crafting_list,
                                            crafting_sel, dcraftC)
                    if not len(crafting_list): crafting = False

                dc = player.move_cursor(inp)
                cursor = (cursor + dc) % 6

                ds = player.move_sel(inp)
                if crafting:
                    crafting_sel = ((crafting_sel + ds) % len(crafting_list)
                                       if len(crafting_list) else 0)
                else:
                    inv_sel = ((inv_sel + ds) % len(server.inv)
                                  if len(server.inv) else 0)

                if any((dx, dy, dc, ds, dinv, dcraft)):
                    server.pos = x, y
                    server.redraw = True
                if dx or dy:
                    c_hidden = True
                if dc:
                    c_hidden = False

                last_inp = time()
                inp = None

            if char in 'c':
                server.redraw = True
                crafting = not crafting and len(crafting_list)

            # Hard pause
            if DEBUG and char in '\n':
                input()
                char = '0'

            # Pause game
            if char in ' \n':
                server.pos = x, y
                server.redraw = True
                last_frame = {}
                if ui.pause(server, settings) == 'exit':
                    server.logout()

            dt = server.dt()