mirror of
https://github.com/duckduckdoof/miniopolis.git
synced 2025-07-04 22:00:28 -04:00
Separating game/scene logic
This commit is contained in:
parent
ebb1460e25
commit
455f392965
9 changed files with 334 additions and 225 deletions
61
lib/engine/game_board.py
Normal file
61
lib/engine/game_board.py
Normal file
|
@ -0,0 +1,61 @@
|
|||
"""
|
||||
game_board.py
|
||||
|
||||
author: Caleb Scott
|
||||
|
||||
Representation of the game board/space. Ideally, this module can be
|
||||
modified/swapped if the geometry of the game changes (2D-3D, etc.)
|
||||
"""
|
||||
|
||||
# CLASSES -----------------------------------------------------------
|
||||
|
||||
class FlatWorld:
|
||||
|
||||
def __init__(self, init_space: list):
|
||||
|
||||
# We assume that the initial space is a rectangular 2D array
|
||||
# Initialize the world space (2D array)
|
||||
self.space = init_space
|
||||
self.width = len(init_space[0])
|
||||
self.height = len(init_space)
|
||||
|
||||
def get_at(self, x, y):
|
||||
"""
|
||||
Returns object located at (x,y) coordinate of space.
|
||||
"""
|
||||
if (x >= 0 and x < self.width) and (y >= 0 and y < self.height):
|
||||
return self.space[x][y]
|
||||
else:
|
||||
return None
|
||||
|
||||
def set_at(self, x, y, object):
|
||||
"""
|
||||
Sets object located at (x,y) coordinate of space.
|
||||
"""
|
||||
if (x >= 0 and x < self.width) and (y >= 0 and y < self.height):
|
||||
self.space[x][y] = object
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
class LayeredFlatWorld:
|
||||
|
||||
def __init__(self, layers: dict):
|
||||
|
||||
# We assume that layers is a dictionary of 2D arrays.
|
||||
# Initialize the layers of 2D space
|
||||
self.layers = {}
|
||||
for layer in layers.keys():
|
||||
self.layers[layer] = FlatWorld(layers[layer])
|
||||
|
||||
def get_at(self, x, y, layer):
|
||||
"""
|
||||
Gets object at (x,y) coordinate at layer
|
||||
"""
|
||||
return self.layers[layer].get_at(x, y)
|
||||
|
||||
def set_at(self, x, y, layer, object):
|
||||
"""
|
||||
Sets object located at (x,y) coordinate at layer
|
||||
"""
|
||||
self.layers[layer].set_at(x, y, object)
|
|
@ -7,4 +7,21 @@ Configuration file for game objects (like setting default rates, types, etc.).
|
|||
This is not the same as scene_config.py, which configures the scene (visuals, sprites, etc.).
|
||||
"""
|
||||
|
||||
# CONSTANTS ---------------------------------------------------------
|
||||
# CONSTANTS ---------------------------------------------------------
|
||||
|
||||
# Game Starting Resources
|
||||
STARTING_RESOURCES = {
|
||||
"people": 10,
|
||||
"food": 200,
|
||||
"metal": 50,
|
||||
"wood": 100,
|
||||
"rock": 100
|
||||
}
|
||||
|
||||
# Resource types
|
||||
RESOURCE_MANPOWER = "Manpower"
|
||||
RESOURCE_WATER = "Water"
|
||||
RESOURCE_METALS = "Metals"
|
||||
RESOURCE_ROCKS = "Rocks"
|
||||
RESOURCE_WOOD = "Wood"
|
||||
RESOURCE_POWER = "Power"
|
|
@ -9,100 +9,108 @@ visual elements; this is handles in the scene/ python files
|
|||
|
||||
# IMPORTS -----------------------------------------------------------
|
||||
|
||||
import arcade
|
||||
from lib.scene.scene_config import *
|
||||
from lib.scene.scene_tiles import *
|
||||
from lib.engine.game_config import *
|
||||
from lib.engine.game_board import LayeredFlatWorld
|
||||
|
||||
# FUNCTIONS ---------------------------------------------------------
|
||||
|
||||
def init_gb_from_scene_info(scene_info: dict):
|
||||
"""
|
||||
Takes a dictionary of 2D arrays (organized by layer name), and
|
||||
converts them into their proper game board of game objects.
|
||||
"""
|
||||
|
||||
|
||||
# CLASSES -----------------------------------------------------------
|
||||
|
||||
class GameLogic:
|
||||
|
||||
def __init__(self, scene, starting_resources):
|
||||
def __init__(self, layers, starting_resources=STARTING_RESOURCES):
|
||||
|
||||
# Initializes the game board (from arcade Scene)
|
||||
# and starting resources
|
||||
self.scene = scene
|
||||
self.game_board = LayeredFlatWorld(layers)
|
||||
self.resources = starting_resources
|
||||
|
||||
def place_structure(self, struct_type, x, y):
|
||||
"""
|
||||
Game logic for placing a structure, if valid.
|
||||
"""
|
||||
# First check and see if we already have a structure there.
|
||||
s_tiles = arcade.get_sprites_at_point((x,y), self.scene[LAYER_STRUCTURES])
|
||||
if len(s_tiles) == 1:
|
||||
return "Structure already in this space."
|
||||
# def place_structure(self, struct_type, x, y):
|
||||
# """
|
||||
# Game logic for placing a structure, if valid.
|
||||
# """
|
||||
# # First check and see if we already have a structure there.
|
||||
# s_tiles = arcade.get_sprites_at_point((x,y), self.scene[LAYER_STRUCTURES])
|
||||
# if len(s_tiles) == 1:
|
||||
# return "Structure already in this space."
|
||||
|
||||
# Get the centered location of the tile chosen
|
||||
# We use the environment layer instead to determine if placement
|
||||
# is legal.
|
||||
e_tiles = arcade.get_sprites_at_point((x,y), self.scene[LAYER_ENVIRONMENT])
|
||||
if len(e_tiles) == 1:
|
||||
print(e_tiles[0].properties)
|
||||
env_tile_type = e_tiles[0].properties['class']
|
||||
c_x, c_y = e_tiles[0].center_x, e_tiles[0].center_y
|
||||
# # Get the centered location of the tile chosen
|
||||
# # We use the environment layer instead to determine if placement
|
||||
# # is legal.
|
||||
# e_tiles = arcade.get_sprites_at_point((x,y), self.scene[LAYER_ENVIRONMENT])
|
||||
# if len(e_tiles) == 1:
|
||||
# print(e_tiles[0].properties)
|
||||
# env_tile_type = e_tiles[0].properties['class']
|
||||
# c_x, c_y = e_tiles[0].center_x, e_tiles[0].center_y
|
||||
|
||||
# Determine what sprite object to place
|
||||
if struct_type == LOGGER:
|
||||
if env_tile_type == TREES:
|
||||
logger_sprite = LoggerTile(c_x, c_y)
|
||||
self.scene.add_sprite(LAYER_STRUCTURES, logger_sprite)
|
||||
return ""
|
||||
else:
|
||||
return "Logger must be placed on trees tile."
|
||||
elif struct_type == CROPS:
|
||||
if env_tile_type == GROUND:
|
||||
crops_sprite = CropsTile(c_x, c_y)
|
||||
self.scene.add_sprite(LAYER_STRUCTURES, crops_sprite)
|
||||
return ""
|
||||
else:
|
||||
return "Crops must be placed on a ground tile."
|
||||
elif struct_type == HYDROPOWER:
|
||||
if env_tile_type == WATER:
|
||||
hydro_sprite = HyroPowerTile(c_x, c_y)
|
||||
self.scene.add_sprite(LAYER_STRUCTURES, hydro_sprite)
|
||||
return ""
|
||||
else:
|
||||
return "Hydro Power must be placed on a water tile."
|
||||
elif struct_type == HOUSING:
|
||||
if env_tile_type == GROUND:
|
||||
housing_sprite = HousingTile(c_x, c_y)
|
||||
self.scene.add_sprite(LAYER_STRUCTURES, housing_sprite)
|
||||
return ""
|
||||
else:
|
||||
return "Housing must be placed on a ground tile."
|
||||
elif struct_type == MINER:
|
||||
if env_tile_type == IRON:
|
||||
miner_sprite = MinerTile(c_x, c_y)
|
||||
self.scene.add_sprite(LAYER_STRUCTURES, miner_sprite)
|
||||
return ""
|
||||
else:
|
||||
return "Miner must be placed on an iron tile."
|
||||
elif struct_type == FACTORY:
|
||||
if env_tile_type == GROUND:
|
||||
factory_sprite = FactoryTile(c_x, c_y)
|
||||
self.scene.add_sprite(LAYER_STRUCTURES, factory_sprite)
|
||||
return ""
|
||||
else:
|
||||
return "Factory must be placed on a ground tile."
|
||||
elif struct_type == JUNCTION:
|
||||
if env_tile_type == GROUND:
|
||||
junction_sprite = JunctionTile(c_x, c_y)
|
||||
self.scene.add_sprite(LAYER_STRUCTURES, junction_sprite)
|
||||
return ""
|
||||
else:
|
||||
return "Junctions must be placed on a ground tile."
|
||||
else:
|
||||
return ""
|
||||
# # Determine what sprite object to place
|
||||
# if struct_type == LOGGER:
|
||||
# if env_tile_type == TREES:
|
||||
# logger_sprite = LoggerTile(c_x, c_y)
|
||||
# self.scene.add_sprite(LAYER_STRUCTURES, logger_sprite)
|
||||
# return ""
|
||||
# else:
|
||||
# return "Logger must be placed on trees tile."
|
||||
# elif struct_type == CROPS:
|
||||
# if env_tile_type == GROUND:
|
||||
# crops_sprite = CropsTile(c_x, c_y)
|
||||
# self.scene.add_sprite(LAYER_STRUCTURES, crops_sprite)
|
||||
# return ""
|
||||
# else:
|
||||
# return "Crops must be placed on a ground tile."
|
||||
# elif struct_type == HYDROPOWER:
|
||||
# if env_tile_type == WATER:
|
||||
# hydro_sprite = HyroPowerTile(c_x, c_y)
|
||||
# self.scene.add_sprite(LAYER_STRUCTURES, hydro_sprite)
|
||||
# return ""
|
||||
# else:
|
||||
# return "Hydro Power must be placed on a water tile."
|
||||
# elif struct_type == HOUSING:
|
||||
# if env_tile_type == GROUND:
|
||||
# housing_sprite = HousingTile(c_x, c_y)
|
||||
# self.scene.add_sprite(LAYER_STRUCTURES, housing_sprite)
|
||||
# return ""
|
||||
# else:
|
||||
# return "Housing must be placed on a ground tile."
|
||||
# elif struct_type == MINER:
|
||||
# if env_tile_type == IRON:
|
||||
# miner_sprite = MinerTile(c_x, c_y)
|
||||
# self.scene.add_sprite(LAYER_STRUCTURES, miner_sprite)
|
||||
# return ""
|
||||
# else:
|
||||
# return "Miner must be placed on an iron tile."
|
||||
# elif struct_type == FACTORY:
|
||||
# if env_tile_type == GROUND:
|
||||
# factory_sprite = FactoryTile(c_x, c_y)
|
||||
# self.scene.add_sprite(LAYER_STRUCTURES, factory_sprite)
|
||||
# return ""
|
||||
# else:
|
||||
# return "Factory must be placed on a ground tile."
|
||||
# elif struct_type == JUNCTION:
|
||||
# if env_tile_type == GROUND:
|
||||
# junction_sprite = JunctionTile(c_x, c_y)
|
||||
# self.scene.add_sprite(LAYER_STRUCTURES, junction_sprite)
|
||||
# return ""
|
||||
# else:
|
||||
# return "Junctions must be placed on a ground tile."
|
||||
# else:
|
||||
# return ""
|
||||
|
||||
def delete_structure(self, x, y):
|
||||
"""
|
||||
Game logic for deleting a structure, if valid.
|
||||
"""
|
||||
s_tiles = arcade.get_sprites_at_point((x,y), self.scene[LAYER_STRUCTURES])
|
||||
if len(s_tiles) == 1:
|
||||
struct_sprites = self.scene[LAYER_STRUCTURES]
|
||||
struct_sprites.remove(s_tiles[0])
|
||||
return ""
|
||||
else:
|
||||
return "No structure on that space."
|
||||
# def delete_structure(self, x, y):
|
||||
# """
|
||||
# Game logic for deleting a structure, if valid.
|
||||
# """
|
||||
# s_tiles = arcade.get_sprites_at_point((x,y), self.scene[LAYER_STRUCTURES])
|
||||
# if len(s_tiles) == 1:
|
||||
# struct_sprites = self.scene[LAYER_STRUCTURES]
|
||||
# struct_sprites.remove(s_tiles[0])
|
||||
# return ""
|
||||
# else:
|
||||
# return "No structure on that space."
|
|
@ -12,14 +12,50 @@ between the game scene/rendering and game logic/objects.
|
|||
|
||||
import math
|
||||
|
||||
# CONSTANTS ---------------------------------------------------------
|
||||
from lib.engine.game_config import *
|
||||
from global_config import *
|
||||
|
||||
MANPOWER = "Manpower"
|
||||
WATER = "Water"
|
||||
METALS = "Metals"
|
||||
ROCKS = "Rocks"
|
||||
WOOD = "Wood"
|
||||
POWER = "Power"
|
||||
# FUNCTIONS ---------------------------------------------------------
|
||||
|
||||
def str_to_game_object(game_obj_str: str):
|
||||
"""
|
||||
Factory method: given a game object string
|
||||
(usually from tileset arrays), return the corresponding object.
|
||||
"""
|
||||
if game_obj_str == JUNCTION:
|
||||
return Junction()
|
||||
elif game_obj_str == HOUSING:
|
||||
return Housing()
|
||||
elif game_obj_str == ROCKSILO:
|
||||
return Silo(RESOURCE_ROCKS)
|
||||
elif game_obj_str == METALSILO:
|
||||
return Silo(RESOURCE_METALS)
|
||||
elif game_obj_str == WOODSILO:
|
||||
return Silo(RESOURCE_WOOD)
|
||||
elif game_obj_str == WATER_TOWER:
|
||||
return WaterTower()
|
||||
elif game_obj_str == CAPACITOR:
|
||||
return Capacitor()
|
||||
elif game_obj_str == HYDRO_POWER:
|
||||
return HydroPower()
|
||||
elif game_obj_str == CROPS:
|
||||
return Crops()
|
||||
elif game_obj_str == FACTORY:
|
||||
return Factory()
|
||||
elif game_obj_str == FOUNDATION:
|
||||
return Foundation()
|
||||
elif game_obj_str == WATER:
|
||||
return Water()
|
||||
elif game_obj_str == TREES:
|
||||
return Trees()
|
||||
elif game_obj_str == GROUND:
|
||||
return Ground()
|
||||
elif game_obj_str == METAL:
|
||||
return Metals()
|
||||
elif game_obj_str == ROCKS:
|
||||
return Rocks()
|
||||
else:
|
||||
return None
|
||||
|
||||
# CLASSES -----------------------------------------------------------
|
||||
|
||||
|
@ -55,17 +91,17 @@ class Junction(GameObject):
|
|||
class Housing(Storage):
|
||||
|
||||
def __init__(self):
|
||||
super().__init__("Housing", MANPOWER, 20.0)
|
||||
super().__init__("Housing", RESOURCE_MANPOWER, 20.0)
|
||||
|
||||
class WaterTower(Storage):
|
||||
|
||||
def __init__(self):
|
||||
super().__init__("WaterTower", WATER, 600.0)
|
||||
super().__init__("WaterTower", RESOURCE_WATER, 600.0)
|
||||
|
||||
class Capacitor(Storage):
|
||||
|
||||
def __init__(self):
|
||||
super().__init__("Capacitor", POWER, 100.0)
|
||||
super().__init__("Capacitor", RESOURCE_POWER, 100.0)
|
||||
|
||||
class Silo(Storage):
|
||||
|
||||
|
@ -94,6 +130,16 @@ class Quarry(Producer):
|
|||
def __init__(self):
|
||||
super().__init__("Quarry", 0.0)
|
||||
|
||||
class Crops(Producer):
|
||||
|
||||
def __init__(self):
|
||||
super().__init__("Crops", 0.0)
|
||||
|
||||
class Factory(Producer):
|
||||
|
||||
def __init__(self):
|
||||
super().__init__("Factory", 0.0)
|
||||
|
||||
|
||||
## LAYER: Foundations
|
||||
class Foundation(GameObject):
|
||||
|
@ -105,7 +151,7 @@ class Foundation(GameObject):
|
|||
class Water(Storage):
|
||||
|
||||
def __init__(self):
|
||||
super().__init__("Water", WATER, math.inf, math.inf)
|
||||
super().__init__("Water", RESOURCE_WATER, math.inf, math.inf)
|
||||
|
||||
class Ground(GameObject):
|
||||
|
||||
|
@ -115,14 +161,14 @@ class Ground(GameObject):
|
|||
class Trees(Storage):
|
||||
|
||||
def __init__(self):
|
||||
super().__init__("Trees", WOOD, 500.0, 500.0)
|
||||
super().__init__("Trees", RESOURCE_WOOD, 500.0, 500.0)
|
||||
|
||||
class Metals(Storage):
|
||||
|
||||
def __init__(self):
|
||||
super().__init__("Metals", METALS, 500.0, 500.0)
|
||||
super().__init__("Metals", RESOURCE_METALS, 500.0, 500.0)
|
||||
|
||||
class Rocks(Storage):
|
||||
|
||||
def __init__(self):
|
||||
super().__init__("Rocks", ROCKS, 500.0, 500.0)
|
||||
super().__init__("Rocks", RESOURCE_ROCKS, 500.0, 500.0)
|
Loading…
Add table
Add a link
Reference in a new issue