Skip to content

Commit

Permalink
initial commit pyweek 34
Browse files Browse the repository at this point in the history
mostly working game after 2 days of work
  • Loading branch information
fireclawthefox committed Sep 6, 2022
0 parents commit 18cb3ae
Show file tree
Hide file tree
Showing 119 changed files with 3,373 additions and 0 deletions.
5 changes: 5 additions & 0 deletions .gitignore
@@ -0,0 +1,5 @@
__pycache__/
*.py[cod]

*.blend[1-9]
*.*~
5 changes: 5 additions & 0 deletions FRAME.project
@@ -0,0 +1,5 @@
{
"name": "outward",
"company": "Grimfang Studio",
"type": "Simple"
}
525 changes: 525 additions & 0 deletions LICENSE.txt

Large diffs are not rendered by default.

3 changes: 3 additions & 0 deletions README.md
@@ -0,0 +1,3 @@
# outward

TODO: write me
47 changes: 47 additions & 0 deletions outward/ai/opponent.py
@@ -0,0 +1,47 @@
import random
from economyStats.economyStats import EconomyStats
from buildings.buildingsManager import BuildingsManager

class Opponent(EconomyStats):
def __init__(self):
EconomyStats.__init__(self)
self.build_speed = random.uniform(0.5, 1.1)
self.wait_build_time = 0
# opponents will built every minute multiplied by build_speed
self.will_build_time = (1 * 60) * self.build_speed
self.buildingsManager = BuildingsManager()

self.max_building_numbers = {
"livingQuarters":5,
"foodProduction":3,
"waterProduction":3,
"mining":2,
"genGoodFactory":2,
"defenseTower":2,
"defenseShield":1,
"defenseArmy":1
}

def do_tick(self):
dt = globalClock.get_dt()
self.wait_build_time += dt

building_id = random.choice(list(self.buildingsManager.buildings.keys()))

building_counts = self.get_building_counts()
max_buildings_reached = []
for building_id, count in building_counts.items():
if self.max_building_numbers[building_id] <= count:
max_buildings_reached.append(building_id)

if self.buildingsManager.can_build_building(building_id, self, max_buildings_reached) \
and self.will_build_time <= self.wait_build_time:
self.buildingsManager.build_building_ai(building_id)
self.ores -= self.buildingsManager.get_required_resources(building_id)
self.wait_build_time = 0

buildings = self.buildingsManager.update_building_time_ai()
if buildings and len(buildings) > 0:
for building in buildings:
self.add_building(building)

Binary file added outward/assets/1K-brushed_metal_1-diffuse.jpg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added outward/assets/1K-brushed_metal_1-normal.jpg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added outward/assets/Army.bam
Binary file not shown.
Binary file added outward/assets/Button.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added outward/assets/Factory.bam
Binary file not shown.
Binary file added outward/assets/Farm.bam
Binary file not shown.
Binary file added outward/assets/Ground.bam
Binary file not shown.
Binary file added outward/assets/LivingQuarters.bam
Binary file not shown.
Binary file added outward/assets/Mine.bam
Binary file not shown.
Binary file added outward/assets/Shield.bam
Binary file not shown.
Binary file added outward/assets/TheTravelingFoxText.otf
Binary file not shown.
Binary file added outward/assets/Tower.bam
Binary file not shown.
Binary file added outward/assets/Warszawa.otf
Binary file not shown.
Binary file added outward/assets/WaterRefinery.bam
Binary file not shown.
Binary file added outward/assets/icons/army_c.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added outward/assets/icons/army_d.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added outward/assets/icons/army_h.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added outward/assets/icons/army_n.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added outward/assets/icons/factory_c.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added outward/assets/icons/factory_d.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added outward/assets/icons/factory_h.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added outward/assets/icons/factory_n.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added outward/assets/icons/farm_c.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added outward/assets/icons/farm_d.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added outward/assets/icons/farm_h.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added outward/assets/icons/farm_n.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added outward/assets/icons/living_c.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added outward/assets/icons/living_d.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added outward/assets/icons/living_h.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added outward/assets/icons/living_n.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added outward/assets/icons/mine_c.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added outward/assets/icons/mine_d.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added outward/assets/icons/mine_h.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added outward/assets/icons/mine_n.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added outward/assets/icons/shield_c.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added outward/assets/icons/shield_d.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added outward/assets/icons/shield_h.png
Binary file added outward/assets/icons/shield_n.png
Binary file added outward/assets/icons/tower_c.png
Binary file added outward/assets/icons/tower_d.png
Binary file added outward/assets/icons/tower_h.png
Binary file added outward/assets/icons/tower_n.png
Binary file added outward/assets/icons/water_c.png
Binary file added outward/assets/icons/water_d.png
Binary file added outward/assets/icons/water_h.png
Binary file added outward/assets/icons/water_n.png
Binary file added outward/assets/sky.png
26 changes: 26 additions & 0 deletions outward/buildings/buildingBase.py
@@ -0,0 +1,26 @@

class BuildingBase:
def __init__(self, csv_data_dict):
self.csv_data_dict = csv_data_dict

# building general details
self.building_id = self.csv_data_dict["id"]
self.name = self.csv_data_dict["name"].replace("\\n", "\n")
self.tooltip = self.csv_data_dict["tooltip"].replace("\\n", "\n")
self.required_ore = self.get_csv_value_int("required_ore")
self.image = self.csv_data_dict["image"]
self.build_time_m = self.get_csv_value_float("build_time_m")

# affected economy stats
self.food_production = self.get_csv_value_int("food_production")
self.water_production = self.get_csv_value_int("water_production")
self.general_goods_production = self.get_csv_value_int("general_goods_production")
self.ore_production = self.get_csv_value_int("ore_production")
self.population = self.get_csv_value_int("population")
self.defense_strength = self.get_csv_value_int("defense_strength")

def get_csv_value_float(self, value):
return float(self.csv_data_dict[value])

def get_csv_value_int(self, value):
return int(self.csv_data_dict[value])
9 changes: 9 additions & 0 deletions outward/buildings/buildings.csv
@@ -0,0 +1,9 @@
id,name,required_ore,image,tooltip,build_time_m,food_production,water_production,general_goods_production,ore_production,population,defense_strength
livingQuarters,Living\nQuarters,15,living,"Adds population, building time {} Minutes",5,0,0,0,0,10,0
foodProduction,Farm,10,farm,"Produces food, building time {} Minutes",2,75,0,0,0,0,0
waterProduction,Water\nRefinery,10,water,"Produces Water, building time {} Minutes",2,0,75,0,0,0,0
mining,Mine,0,mine,"Produces ores, building time {} Minutes",1,0,0,0,40,0,0
genGoodFactory,Factory,10,factory,"Produces general goods, building time {} Minutes",4,0,0,100,0,0,0
defenseTower,Tower,20,tower,"Enhance defense, building time {} Minutes",8,0,0,0,0,0,5
defenseShield,Shield,25,shield,"Enhance defense, building time {} Minutes",10,0,0,0,0,0,10
defenseArmy,Army,30,army,"Enhance defense, building time {} Minutes",12,0,0,0,0,0,15
143 changes: 143 additions & 0 deletions outward/buildings/buildingsManager.py
@@ -0,0 +1,143 @@
import csv
import os
from buildings.buildingBase import BuildingBase
from gui.btnBuilding import GUI as BtnBuilding
from direct.gui import DirectGuiGlobals as DGG
from DirectGuiExtension.DirectTooltip import DirectTooltip

class BuildingsManager:
def __init__(self):
self.buildings = {}
self.building_buttons = {}
self.currently_built_buildings_elapsed_time_s = 0
self.currently_built_buildings = {}

self.tooltip = DirectTooltip(
scale=0.2,
text_scale=0.2,
frameColor=(0.7, 0.9, 1, 0.8),
pad=(.1,.1))

csv_file = os.path.join(base.main_dir, "buildings", "buildings.csv")
with open(csv_file, newline='') as csvfile:
reader = csv.DictReader(csvfile)
z_pos = -0.15
for row in reader:
building = BuildingBase(row)
self.buildings[building.building_id] = building

def destroy(self):
for building_id, button in self.building_buttons.items():
button.destroy()

def create_building_buttons(self, button_holder_frame):
self.button_holder_frame = button_holder_frame
z_pos = -0.15
for building_id, building in self.buildings.items():
self.building_buttons[building_id] = self.create_building_button(
building_id,
building.name,
building.image,
building.tooltip.format(building.build_time_m),
z_pos)
z_pos -= 0.25
z_pos += 0.1
cs = self.button_holder_frame["canvasSize"]
self.button_holder_frame["canvasSize"] = [
cs[0], cs[1],
z_pos, cs[3]]

def can_build_building(self, building_id, economy_stats, max_buildings_reached):
return self.buildings[building_id].required_ore < economy_stats.ores \
and building_id not in max_buildings_reached \
and building_id not in self.currently_built_buildings.keys()

def get_required_resources(self, building_id):
return self.buildings[building_id].required_ore

def build_building(self, building_id):
btn = self.building_buttons[building_id]
btn.wbBuildingTime.show()
btn.btnBuilding["state"] = DGG.DISABLED
btn.wbBuildingTime["value"] = 0
btn.wbBuildingTime["text"] = ""
self.currently_built_buildings[building_id] = 0

def build_building_ai(self, building_id):
self.currently_built_buildings[building_id] = 0

def update_building_time(self):
finished_buildings = []
for building_id, elapsed_time in self.currently_built_buildings.items():
self.currently_built_buildings[building_id] += globalClock.get_dt()

et = self.currently_built_buildings[building_id]

btn = self.building_buttons[building_id]
building = self.buildings[building_id]
value = (et / (building.build_time_m * 60)) * 100
btn.wbBuildingTime["value"] = value

if et >= building.build_time_m * 60:
# this building is done:
btn.wbBuildingTime["value"] = 100
btn.wbBuildingTime.hide()
finished_buildings.append(self.buildings[building_id])
for building in finished_buildings:
del self.currently_built_buildings[building.building_id]
return finished_buildings

def update_building_time_ai(self):
finished_buildings = []
for building_id, elapsed_time in self.currently_built_buildings.items():
self.currently_built_buildings[building_id] += globalClock.get_dt()
building = self.buildings[building_id]
if elapsed_time >= building.build_time_m * 60:
# this building is done:
finished_buildings.append(self.buildings[building_id])
for building in finished_buildings:
del self.currently_built_buildings[building.building_id]
return finished_buildings

def update_building_buttons(self, economy_stats, max_buildings_reached):
for building_id, button in self.building_buttons.items():
if self.can_build_building(building_id, economy_stats, max_buildings_reached):
button.btnBuilding["state"] = DGG.NORMAL
else:
button.btnBuilding["state"] = DGG.DISABLED

def get_building_info(self, building_id):
return self.buildings[building_id]

def create_building_button(
self,
building_id,
building_name,
building_image,
tooltip_text,
z_pos):
btn = BtnBuilding(self.button_holder_frame.canvas)
btn.btnBuilding.setPos(0, 0, z_pos)
btn.btnBuilding["frameColor"] = [
(.8,.8,.8,0),
(.8,.8,.9,0),
(.9,.9,.9,0),
(.2,.2,.2,0)]
btn.btnBuilding["text"] = building_name
btn.btnBuilding["text_scale"] = 0.35
btn.btnBuilding["text_pos"] = (0,-0.8,0)
btn.btnBuilding["text_fg"] = (1,1,1,1)
btn.btnBuilding["text_shadow"] = (0, 0, 0, 1)
btn.btnBuilding["image"] = (
f"assets/icons/{building_image}_n.png",
f"assets/icons/{building_image}_c.png",
f"assets/icons/{building_image}_h.png",
f"assets/icons/{building_image}_d.png")
btn.btnBuilding["extraArgs"] = ["build_building", [building_id]]
btn.btnBuilding.setTransparency(1)
btn.wbBuildingTime.hide()

btn.btnBuilding.bind(DGG.ENTER, self.tooltip.show, [tooltip_text])
btn.btnBuilding.bind(DGG.EXIT, self.tooltip.hide)

return btn
116 changes: 116 additions & 0 deletions outward/core/config.py
@@ -0,0 +1,116 @@
# Python imports
import os

# Panda3D imoprts
from panda3d.core import (
ConfigPageManager,
ConfigVariableBool,
OFileStream,
loadPrcFileData,
loadPrcFile,
Filename)

#
# PATHS AND CONFIGS
#
# set company and application details
companyName = "Grimfang Studio"
appName = "outward"
versionstring = "22.09"

# build the path from the details we have
home = os.path.expanduser("~")
basedir = os.path.join(
home,
companyName,
appName)
if not os.path.exists(basedir):
os.makedirs(basedir)

# look for a config file
prcFile = os.path.join(basedir, f"{appName}.prc")
if os.path.exists(prcFile):
mainConfig = loadPrcFile(Filename.fromOsSpecific(prcFile))

# set configurations that should not be changed from a config file
loadPrcFileData("",
f"""
#
# Model loading
#
model-path $MAIN_DIR/{appName}/assets/
#
# Window and graphics
#
window-title {appName}
#show-frame-rate-meter 1
#
# Logging
#
#notify-level info
notify-timestamp 1
#
# Audio
#
# Make sure to use OpenAL
audio-library-name p3openal_audio
""")

config_variables = {}

print("Log files and configurations are stored in:", basedir)

def load_config():
# NOTE: Add any custom changed configuration to this dictionary to make it show
# up in the application specific saved config file.
# Structure:
# Key: configuration name
# Value: The configurations value as represented in the config file (string)
global config_variables
config_variables = {
# particles
"particles-enabled": "#t" if base.particleMgrEnabled else "#f",
# audio
"audio-volume": str(round(base.musicManager.getVolume(), 2)),
"audio-music-active": "#t" if ConfigVariableBool("audio-music-active").getValue() else "#f",
"audio-sfx-active": "#t" if ConfigVariableBool("audio-sfx-active").getValue() else "#f",
# logging
"notify-output": os.path.join(basedir, "application.log"),
}

def write_config():
"""Save current config in the prc file or if no prc file exists
create one. The prc file is set in the prcFile variable"""
page = None

# Check if we have an existing configuration file
if os.path.exists(prcFile):
# open the config file and change values according to current
# application settings
page = loadPrcFile(Filename.fromOsSpecific(prcFile))
removeDecls = []
for dec in range(page.getNumDeclarations()):
# Check if our variables are given.
# NOTE: This check has to be done to not loose our base
# or other manual config changes by the user
if page.getVariableName(dec) in config_variables.keys():
removeDecls.append(page.modifyDeclaration(dec))
for dec in removeDecls:
page.deleteDeclaration(dec)
else:
# Create a config file and set default values
cpMgr = ConfigPageManager.getGlobalPtr()
page = cpMgr.makeExplicitPage("Application Config")

# always write custom configurations
for key, value in config_variables.items():
page.makeDeclaration(key, value)
# create a stream to the specified config file
configfile = OFileStream(prcFile)
# and now write it out
page.write(configfile)
# close the stream
configfile.close()

0 comments on commit 18cb3ae

Please sign in to comment.