7
\$\begingroup\$

I was poking around on my Raspberry Pi that I hadn't turned on or used in a while, and I stumbled upon this Python script that I wrote ~1.5 years ago, and I was intrigued.

Essentially, it's a 2D Minecraft clone with no concept of survival. It does have a slightly, complex control scheme, so here's a list of buttons that can be used, and what they do:

  • a, d - Move left/right through the world.
  • LMB - Place a tile at the desired position.
  • RMB - Destroy a tile at the desired position.
  • SHIFT/SPACE - Change the currently selected tile.
  • q - Switch to the underground "realm".
  • e - Switch to the above ground "realm".

Even though I wrote this quite a while ago, and if I had written it now, it would have looked better, I'm still curious as to what all can be improved.

#!usr/bin/env python
# Basic 2d building game, Builder
import pygame
import random
import shutil
import time
import math
import sys
import os


debug_game_data = int(sys.argv[1])
current_version = "0.5.0"

WIDTH = 700
HEIGHT = 700

pygame.init()
pygame.display.set_caption("Builder {}".format(current_version))
screen = pygame.display.set_mode((WIDTH, HEIGHT))
FONT = pygame.font.SysFont("monospace.ttf", 13)
clock = pygame.time.Clock()

mouse_pos = pygame.mouse.get_pos
key_pressed = pygame.key.get_pressed

mouse_x = 0
mouse_y = 1

TILE_SIZE = 25
round_tile_size = lambda x: (
    1+(x-1)/TILE_SIZE)*TILE_SIZE if x%TILE_SIZE>=10 else (
        x/TILE_SIZE)*TILE_SIZE


# Dictionary of game textures
TEXTURES = {
    "dirt": pygame.transform.scale(pygame.image.load("./images/gameDirtBlock.png"), (TILE_SIZE, TILE_SIZE)),
    "grass": pygame.transform.scale(pygame.image.load("./images/gameGrassBlock.png"), (TILE_SIZE, TILE_SIZE)),
    "stone": pygame.transform.scale(pygame.image.load("./images/gameStoneBlock.png"), (TILE_SIZE, TILE_SIZE)),
    "sand": pygame.transform.scale(pygame.image.load("./images/gameSandBlock.png"), (TILE_SIZE, TILE_SIZE)),
    "water": pygame.transform.scale(pygame.image.load("./images/gameWaterBlock.png"), (TILE_SIZE, TILE_SIZE)),
    "wood": pygame.transform.scale(pygame.image.load("./images/gameWoodBlock.png"), (TILE_SIZE, TILE_SIZE)),
    "leaf": pygame.transform.scale(pygame.image.load("./images/gameLeafBlock.png"), (TILE_SIZE, TILE_SIZE)),
}


# Lists containing tile data for overworld and underground
overworld_data = []
underground_data = []


# Variables concerning whether the player is underground, or aboveground
player_underground = False
player_aboveground = True


# Dictionary containing tile types
TILE_TYPES = {
    "dirt": 0,
    "grass": 1,
    "stone": 2,
    "sand": 3,
    "water": 4,
    "wood": 5,
    "leaf": 6
}


# Colors for the game
BLUE_LIGHT = (0, 0, 220)
GRAY_DARK = (100, 100, 100)
BLUE_DARK = (0, 0, 175)
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)


# Background class, for rendering the day/night cycle
class Background(object):
    def __init__(self):
        self.SKY_COLOR = BLUE_LIGHT
        self.UNDERGROUND_SKY_COLOR = GRAY_DARK

    # Render the background
    def render_background(self):
        if player_aboveground:
            screen.fill(self.SKY_COLOR)
        if player_underground:
            screen.fill(self.UNDERGROUND_SKY_COLOR)


# Tile class, to be used to create a chunk with the Chunk class
class Tile(object):
    def __init__(self, x, y, tile_type, tile_image):
        self.x = x
        self.y = y
        self.tile_type = tile_type
        self.tile_image = tile_image

    # Update the position of a tile
    def update_tile_position(self, x_change, y_change):
        self.x += x_change
        self.y += y_change

    # Render the tile on the screen
    def render_tile(self):
        screen.blit(self.tile_image, (self.x, self.y))


# Chunk class, for generating a chunk and rendering it
class Chunk(object):
    def __init__(self, chunk_x):
        self.chunk_x = chunk_x
        self.chunk_data_overworld = []
        self.chunk_data_underground = []

    # Generate an overworld chunk for the center
    def generate_overworld_chunk_center(self):

        # Generate the stone section
        stone_end = HEIGHT-round_tile_size(random.randint(3, 4)*TILE_SIZE)
        for y in range(HEIGHT, stone_end, -TILE_SIZE):
            self.chunk_data_overworld.append(Tile(self.chunk_x, y,
                TILE_TYPES["stone"], TEXTURES["stone"]))

        # Generate the dirt section
        dirt_end = stone_end-round_tile_size(random.randint(1, 2)*TILE_SIZE)
        for y in range(stone_end, dirt_end, -TILE_SIZE):
            self.chunk_data_overworld.append(Tile(self.chunk_x, y,
                TILE_TYPES["dirt"], TEXTURES["dirt"]))

        # Generate the grass section
        grass_end = dirt_end-round_tile_size(TILE_SIZE)
        for y in range(dirt_end, grass_end, -TILE_SIZE):
            self.chunk_data_overworld.append(Tile(self.chunk_x, y,
                TILE_TYPES["grass"], TEXTURES["grass"]))

        # Generate a tree based on a probability
        value1 = random.random()*random.randint(1, 10)
        value2 = random.random()*random.randint(1, 10)
        value3 = random.random()*random.randint(1, 10)
        if value1 < value2 < value3:

            # Generate the wood section
            tree_end = grass_end-round_tile_size(random.randint(4, 5)*TILE_SIZE)
            for y in range(grass_end, tree_end, -TILE_SIZE):
                self.chunk_data_overworld.append(Tile(self.chunk_x, y,
                    TILE_TYPES["wood"], TEXTURES["wood"]))

            # Generate the leaf section
            leaf_end = tree_end-round_tile_size(random.randint(1, 2)*TILE_SIZE)
            for y in range(tree_end, leaf_end, -TILE_SIZE):
                self.chunk_data_overworld.append(Tile(self.chunk_x, y,
                    TILE_TYPES["leaf"], TEXTURES["leaf"]))

    # Generate an overworld chunk for the sides
    def generate_overworld_chunk_side(self):
        beach_end = HEIGHT-round_tile_size(random.randint(4, 6)*TILE_SIZE)
        for y in range(HEIGHT, beach_end, -TILE_SIZE):
            self.chunk_data_overworld.append(Tile(self.chunk_x, y,
                TILE_TYPES["sand"], TEXTURES["sand"]))

    # Generate an overworld chunk for the far sides
    def generate_overworld_chunk_far_side(self):
        water_end = HEIGHT-(TILE_SIZE*3)
        for y in range(HEIGHT, water_end, -TILE_SIZE):
            self.chunk_data_overworld.append(Tile(self.chunk_x, y,
                TILE_TYPES["water"], TEXTURES["water"]))

    # Generate an underground chunk
    def generate_underground_chunk(self):

        # Generate the top section
        stone_end1 = 0+round_tile_size(random.randint(3, 5)*TILE_SIZE)
        for y in range(0, stone_end1, TILE_SIZE):
            self.chunk_data_underground.append(Tile(self.chunk_x, y,
                TILE_TYPES["stone"], TEXTURES["stone"]))

        # Generate the bottom section
        stone_end2 = HEIGHT-round_tile_size(random.randint(3, 5)*TILE_SIZE)
        for y in range(HEIGHT, stone_end2, -TILE_SIZE):
            self.chunk_data_underground.append(Tile(self.chunk_x, y,
                TILE_TYPES["stone"], TEXTURES["stone"]))


    # Add new underground chunk data
    def add_new_chunk_data_underground(self):
        self.chunk_data_underground.append(self.chunk_x)
        self.generate_underground_chunk()
        underground_data.append(self.chunk_data_underground)

    # Add a new chunk for the far sides
    def add_new_chunk_data_far_side(self):
        self.chunk_data_overworld.append(self.chunk_x)
        self.generate_overworld_chunk_far_side()
        overworld_data.append(self.chunk_data_overworld)

    # Add new chunk data for the sides
    def add_new_chunk_data_side(self):
        self.chunk_data_overworld.append(self.chunk_x)
        self.generate_overworld_chunk_side()
        overworld_data.append(self.chunk_data_overworld)

    # Add chunk data to the world for the center
    def add_new_chunk_data_center(self):
        self.chunk_data_overworld.append(self.chunk_x)
        self.generate_overworld_chunk_center()
        overworld_data.append(self.chunk_data_overworld)


# WorldGenerator class, responsible for finalizing world data
class WorldGenerator(object):
    def __init__(self):
        self.START_X_CENTER = -2000
        self.END_X_CENTER = 2000

        # Start and end for left side
        self.START_X_LEFT = self.START_X_CENTER-500
        self.END_X_LEFT = self.START_X_CENTER

        # Start and end for right side
        self.START_X_RIGHT = self.END_X_CENTER
        self.END_X_RIGHT = self.END_X_CENTER+500

        # Start and end for far left side
        self.START_X_FAR_LEFT = self.START_X_LEFT-750
        self.END_X_FAR_LEFT = self.START_X_LEFT

        # Start and end for far right side
        self.START_X_FAR_RIGHT = self.END_X_RIGHT
        self.END_X_FAR_RIGHT = self.END_X_RIGHT+750

        # Start and end for underground
        self.UNDER_START_X = -3250
        self.UNDER_END_X = 3250

    # Generate the world
    def generate_world(self):

        # Generate the far left side
        for chunk_x in range(self.START_X_FAR_LEFT, self.END_X_FAR_LEFT, TILE_SIZE):
            chunk = Chunk(chunk_x)
            chunk.add_new_chunk_data_far_side()

        # Generate the left side
        for chunk_x in range(self.START_X_LEFT, self.END_X_LEFT, TILE_SIZE):
            chunk = Chunk(chunk_x)
            chunk.add_new_chunk_data_side()

        # Generate the center
        for chunk_x in range(self.START_X_CENTER, self.END_X_CENTER, TILE_SIZE):
            chunk = Chunk(chunk_x)
            chunk.add_new_chunk_data_center()

        # Generate the right side
        for chunk_x in range(self.START_X_RIGHT, self.END_X_RIGHT, TILE_SIZE):
            chunk = Chunk(chunk_x)
            chunk.add_new_chunk_data_side()

        # Generate the far right side
        for chunk_x in range(self.START_X_FAR_RIGHT, self.END_X_FAR_RIGHT, TILE_SIZE):
            chunk = Chunk(chunk_x)
            chunk.add_new_chunk_data_far_side()

        # Generate the underground portion
        for chunk_x in range(self.UNDER_START_X, self.UNDER_END_X, TILE_SIZE):
            chunk = Chunk(chunk_x)
            chunk.add_new_chunk_data_underground()


# ChunkLoader class, used for rendering chunks
class ChunkLoader(object):
    def __init__(self):
        pass

    # Render the current loaded chunks aboveground
    def render_current_loaded_chunks_aboveground(self):
        for chunk in overworld_data:
            for tile in chunk[1:]:
                if tile.x >= 0 and tile.x <= WIDTH:
                    tile.render_tile()

    # Render the current loaded chunks underground
    def render_current_loaded_chunks_underground(self):
        for chunk in underground_data:
            for tile in chunk[1:]:
                if tile.x >= 0 and tile.x <= WIDTH:
                    tile.render_tile()


# Player class, containing all player data
class Player(object):
    def __init__(self):
        self.chunk_loader = ChunkLoader()
        self.selected_tile = 0
        self.inventory = {
            0: [0, pygame.transform.scale(pygame.image.load("./images/gameDirtBlock.png"), (17, 17))],
            1: [0, pygame.transform.scale(pygame.image.load("./images/gameGrassBlock.png"), (17, 17))],
            2: [0, pygame.transform.scale(pygame.image.load("./images/gameStoneBlock.png"), (17, 17))],
            3: [0, pygame.transform.scale(pygame.image.load("./images/gameSandBlock.png"), (17, 17))],
            4: [0, pygame.transform.scale(pygame.image.load("./images/gameWaterBlock.png"), (17, 17))],
            5: [0, pygame.transform.scale(pygame.image.load("./images/gameWoodBlock.png"), (17, 17))],
            6: [0, pygame.transform.scale(pygame.image.load("./images/gameLeafBlock.png"), (17, 17))],
        }

    # Loop through the world and change tile positions belowground
    def loop_through_world_belowground(self, x_change, y_change):
        for chunk in underground_data:
            for tile in chunk[1:]:
                tile.update_tile_position(x_change, y_change)

    # Move through the world belowground
    def move_player_belowground(self):
        if key_pressed()[pygame.K_a]:
            self.loop_through_world_belowground(TILE_SIZE, 0)
        if key_pressed()[pygame.K_d]:
            self.loop_through_world_belowground(-TILE_SIZE, 0)

    # Loop through the world and change tile positions aboveground
    def loop_through_world_aboveground(self, x_change, y_change):
        for chunk in overworld_data:
            for tile in chunk[1:]:
                tile.update_tile_position(x_change, y_change)

    # Move through the world aboveground
    def move_player_aboveground(self):
        if key_pressed()[pygame.K_a]:
            self.loop_through_world_aboveground(TILE_SIZE, 0)
        if key_pressed()[pygame.K_d]:
            self.loop_through_world_aboveground(-TILE_SIZE, 0)

    # Render the player's hitbox on the screen
    def render_player_hitbox(self):
        pygame.draw.rect(screen, WHITE,
            pygame.Rect(round_tile_size(mouse_pos()[mouse_x]-(TILE_SIZE/2)),
                 round_tile_size(mouse_pos()[mouse_y]-(TILE_SIZE/2)),
                     TILE_SIZE, TILE_SIZE), 1)

    # Render the player's inventory
    def render_player_inventory(self):
        pygame.draw.rect(screen, GRAY_DARK, (3, 218, 22, 142), 0)

        # Positions for inventory items
        item_x = 5
        item_y = 220

        # Render the item "icons"
        for item in self.inventory:
            item_image = self.inventory[item][1]
            screen.blit(item_image, (item_x, item_y))
            item_y += 20

        # Change item_x and item_y
        item_x = 7.5
        item_y = 226.5

        # Render the item counts
        for item in self.inventory:
            item_count = FONT.render(
                "{}".format(self.inventory[item][0]), 1, WHITE)
            screen.blit(item_count, (item_x, item_y))
            item_y += 20

        # Render the selected tile
        pygame.draw.rect(screen, GRAY_DARK, (3, 193, 22, 22), 0)
        screen.blit(self.inventory[self.selected_tile][1], (5, 195))

    # Change the selected tile
    def change_selected_tile(self):
        if pygame.key.get_pressed()[pygame.K_SPACE]:
            if self.selected_tile <= len(self.inventory)-2:
                self.selected_tile += 1
            else:
                self.selected_tile = 0

    # Change between underground and aboveground
    def change_aboveground_underground(self):

        # Make aboveground & belowground variables global
        global player_aboveground
        global player_underground

        # Change to belowground
        if pygame.key.get_pressed()[pygame.K_q]:
            player_aboveground = False
            player_underground = True

        # Change to aboveground
        if pygame.key.get_pressed()[pygame.K_e]:
            player_aboveground = True
            player_underground = False

    # Delete a tile from the world aboveground
    def delete_tile_aboveground(self):
        if pygame.mouse.get_pressed()[0]:
            for chunk in overworld_data:  
                for tile in chunk[1:]:
                    if round_tile_size(mouse_pos()[mouse_x]-(TILE_SIZE/2)) == tile.x and round_tile_size(mouse_pos()[mouse_y]-(TILE_SIZE/2)) == tile.y:
                        if self.inventory[tile.tile_type][0] <= 127:
                            self.inventory[tile.tile_type][0] += 1
                            del overworld_data[overworld_data.index(chunk)][overworld_data[overworld_data.index(chunk)].index(tile)]
                            break

    # Add a tile to the world aboveground
    def add_tile_aboveground(self):
        if pygame.mouse.get_pressed()[2]:
            for chunk in overworld_data:
                if round_tile_size(mouse_pos()[mouse_x]-(TILE_SIZE/2)) == chunk[0]:
                    if self.inventory[self.selected_tile][0] >= 1:
                        self.inventory[self.selected_tile][0] -= 1
                        chunk.append(Tile(
                            round_tile_size(mouse_pos()[mouse_x]-(TILE_SIZE/2)),
                            round_tile_size(mouse_pos()[mouse_y]-(TILE_SIZE/2)),
                            self.selected_tile,
                            pygame.transform.scale(self.inventory[self.selected_tile][1], (TILE_SIZE, TILE_SIZE))
                        ))
                        break

    # Delete a tile from the world belowground
    def delete_tile_belowground(self):
        if pygame.mouse.get_pressed()[0]:
            for chunk in underground_data:  
                for tile in chunk[1:]:
                    if round_tile_size(mouse_pos()[mouse_x]-(TILE_SIZE/2)) == tile.x and round_tile_size(mouse_pos()[mouse_y]-(TILE_SIZE/2)) == tile.y:
                        if self.inventory[tile.tile_type][0] <= 127:
                            self.inventory[tile.tile_type][0] += 1
                            del underground_data[underground_data.index(chunk)][underground_data[underground_data.index(chunk)].index(tile)]
                            break

    # Add a tile to the world belowground
    def add_tile_belowground(self):
        if pygame.mouse.get_pressed()[2]:
            for chunk in underground_data:
                if round_tile_size(mouse_pos()[mouse_x]-(TILE_SIZE/2)) == chunk[0]:
                    if self.inventory[self.selected_tile][0] >= 1:
                        self.inventory[self.selected_tile][0] -= 1
                        chunk.append(Tile(
                            round_tile_size(mouse_pos()[mouse_x]-(TILE_SIZE/2)),
                            round_tile_size(mouse_pos()[mouse_y]-(TILE_SIZE/2)),
                            self.selected_tile,
                            pygame.transform.scale(self.inventory[self.selected_tile][1], (TILE_SIZE, TILE_SIZE))
                        ))
                        break


# Game class, where the events are executed
class Game(object):
    def __init__(self):
        self.player = Player()
        self.chunk_loader = ChunkLoader()
        self.background = Background()

    # Run all game events
    def run_events(self):
        self.background.render_background()

        # Player aboveground?
        if player_aboveground:
            self.chunk_loader.render_current_loaded_chunks_aboveground()

        # Player underground?
        if player_underground:
            self.chunk_loader.render_current_loaded_chunks_underground()

        # Move player aboveground?
        if player_aboveground:
            self.player.move_player_aboveground()

        # Move player underground?
        if player_underground:
            self.player.move_player_belowground()

        # Other player methods
        self.player.change_selected_tile()
        self.player.render_player_hitbox()
        self.player.render_player_inventory()
        self.player.change_aboveground_underground()

        # Add & delete tiles aboveground?
        if player_aboveground:
            self.player.delete_tile_aboveground()
            self.player.add_tile_aboveground()

        # Add and delete tile belowground?
        if player_underground:
            self.player.delete_tile_belowground()
            self.player.add_tile_belowground()


# Initalize the game
def initalize_game():
    clock.tick(75)
    background = Background()
    generator = WorldGenerator()
    generator.generate_world()


# Print game debug data
def print_debug_data():
    if debug_game_data:
        for chunk in overworld_data:
            for tile in chunk[1:]:
                print tile.tile_type, tile.x, tile.y


# Main program loop where all game events are executed
def main_program_loop():
    game = Game()
    while True:
        game.run_events()
        pygame.display.update()

        # Check if the user wants to quit
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                sys.exit(0)


# Start the main program loop
if __name__ == "__main__":
    initalize_game()
    print_debug_data()
    main_program_loop()

For those who are curious, the tile textures can be found here.

\$\endgroup\$
5
\$\begingroup\$

A few things that could be improved upon:


TEXTURES = {
    "dirt": pygame.transform.scale(pygame.image.load("./images/gameDirtBlock.png"), (TILE_SIZE, TILE_SIZE)),
    "grass": pygame.transform.scale(pygame.image.load("./images/gameGrassBlock.png"), (TILE_SIZE, TILE_SIZE)),
    "stone": pygame.transform.scale(pygame.image.load("./images/gameStoneBlock.png"), (TILE_SIZE, TILE_SIZE)),
    "sand": pygame.transform.scale(pygame.image.load("./images/gameSandBlock.png"), (TILE_SIZE, TILE_SIZE)),
    "water": pygame.transform.scale(pygame.image.load("./images/gameWaterBlock.png"), (TILE_SIZE, TILE_SIZE)),
    "wood": pygame.transform.scale(pygame.image.load("./images/gameWoodBlock.png"), (TILE_SIZE, TILE_SIZE)),
    "leaf": pygame.transform.scale(pygame.image.load("./images/gameLeafBlock.png"), (TILE_SIZE, TILE_SIZE)),
}

A few things here:

  • There's no need to wrap the actual texture title with game*Block: ./images/*.png is fine.
  • All the lines are basically the same except for the texture title, you could probably loop over this if you wanted, or move the pygame.transform.scale(pygame.image.load(), (TITLE_SIZE, TILE_SIZE)) into a function.

    def render_background(self):
        if player_aboveground:
            screen.fill(self.SKY_COLOR)
        if player_underground:
            screen.fill(self.UNDERGROUND_SKY_COLOR)

Shouldn't if player_underground be elif? You can't be in both places at once.


    self.START_X_LEFT = self.START_X_CENTER-500
    self.END_X_LEFT = self.START_X_CENTER

    # Start and end for right side
    self.START_X_RIGHT = self.END_X_CENTER
    self.END_X_RIGHT = self.END_X_CENTER+500

    # Start and end for far left side
    self.START_X_FAR_LEFT = self.START_X_LEFT-750
    self.END_X_FAR_LEFT = self.START_X_LEFT

    # Start and end for far right side
    self.START_X_FAR_RIGHT = self.END_X_RIGHT
    self.END_X_FAR_RIGHT = self.END_X_RIGHT+750

Where's the spacing in between self.* + val?


    self.inventory = {
        0: [0, pygame.transform.scale(pygame.image.load("./images/gameDirtBlock.png"), (17, 17))],
        1: [0, pygame.transform.scale(pygame.image.load("./images/gameGrassBlock.png"), (17, 17))],
        2: [0, pygame.transform.scale(pygame.image.load("./images/gameStoneBlock.png"), (17, 17))],
        3: [0, pygame.transform.scale(pygame.image.load("./images/gameSandBlock.png"), (17, 17))],
        4: [0, pygame.transform.scale(pygame.image.load("./images/gameWaterBlock.png"), (17, 17))],
        5: [0, pygame.transform.scale(pygame.image.load("./images/gameWoodBlock.png"), (17, 17))],
        6: [0, pygame.transform.scale(pygame.image.load("./images/gameLeafBlock.png"), (17, 17))],
    }

Really?

  1. You should cast expelliarmus on the magic number 17!
  2. ArrayPositions are bad keys. In fact, useless.
  3. I'm not familiar with pygame, but couldn't you just transform the TEXTURES instead?

    for chunk_x in range(self.START_X_FAR_LEFT, self.END_X_FAR_LEFT, TILE_SIZE):
        chunk = Chunk(chunk_x)
        chunk.add_new_chunk_data_far_side()

    # Generate the left side
    for chunk_x in range(self.START_X_LEFT, self.END_X_LEFT, TILE_SIZE):
        chunk = Chunk(chunk_x)
        chunk.add_new_chunk_data_side()

    # Generate the center
    for chunk_x in range(self.START_X_CENTER, self.END_X_CENTER, TILE_SIZE):
        chunk = Chunk(chunk_x)
        chunk.add_new_chunk_data_center()

    # Generate the right side
    for chunk_x in range(self.START_X_RIGHT, self.END_X_RIGHT, TILE_SIZE):
        chunk = Chunk(chunk_x)
        chunk.add_new_chunk_data_side()

    # Generate the far right side
    for chunk_x in range(self.START_X_FAR_RIGHT, self.END_X_FAR_RIGHT, TILE_SIZE):
        chunk = Chunk(chunk_x)
        chunk.add_new_chunk_data_far_side()

    # Generate the underground portion
    for chunk_x in range(self.UNDER_START_X, self.UNDER_END_X, TILE_SIZE):
        chunk = Chunk(chunk_x)
        chunk.add_new_chunk_data_underground()

DRY this a bit.


def initalize_game():
    clock.tick(75)
    background = Background()
    generator = WorldGenerator()
    generator.generate_world()

Is there any reason to assign background and generator?

    Background()
    WorldGenerator().generate_world()

Why do the comments in run_events have question marks on the end?

# Player aboveground? 

Also in run_events:

    # Player aboveground?
    if player_aboveground:
        self.chunk_loader.render_current_loaded_chunks_aboveground()

    # Player underground?
    if player_underground:
        self.chunk_loader.render_current_loaded_chunks_underground()

    # Move player aboveground?
    if player_aboveground:
        self.player.move_player_aboveground()

    # Move player underground?
    if player_underground:
        self.player.move_player_belowground()

Why are these seperate?

    if player_aboveground:
        self.chunk_loader.render_current_loaded_chunks_aboveground()
        self.player.move_player_aboveground()

    elif player_underground:
        self.chunk_loader.render_current_loaded_chunks_underground()
        self.player.move_player_belowground()

On a related note to above:

    if player_aboveground:
        self.chunk_loader.render_current_loaded_chunks_aboveground()
        self.player.move_player_aboveground()

    elif player_underground:
        self.chunk_loader.render_current_loaded_chunks_underground()
        self.player.move_player_belowground()
  • Above: player_aboveground, *chunks_aboveground(), *move_player_aboveground()
  • Under: player_underground, *loaded_chunks_underground(), move_player_belowground()

All the above ones use above, but all the under ones are not the same, one is below. IMHO, below sounds better (Linguistically) than under, but, the issue is that they should all be consistent.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.