Files
2025-03-12 15:35:25 -04:00

245 lines
6.9 KiB
Python

import pygame
import pygame.freetype
import math
import random
import agent_stat
import ztime
import action
import agent
import decision
from defs import *
# ###############################################################
class Display:
def __init__(self, screen, clock):
self.screen = screen
self.clock = clock
self.run = True
self.delta = 0
self.font = None
def draw_gobj(self, gobj):
pygame.draw.circle(
self.screen,
gobj.color,
gobj.pos(),
gobj.radius)
def draw_text(self, msg, x, y, color):
surface, rect = self.font.render(msg, color)
self.screen.blit(surface, (x, y))
def draw_line(self, p1, p2, color,width=1):
pygame.draw.line(
self.screen,
color,
p1,
p2,
width)
def init_display(sw, sh):
pygame.init()
screen = pygame.display.set_mode((sw,sh))
clock = pygame.time.Clock()
display = Display(screen, clock)
display.font = pygame.freetype.Font('JuliaMono-Bold.ttf', 18)
pygame.key.set_repeat(200,100)
return display
def wrap_text(text, font, width):
splt_text = text.split()
lines = []
cur = 0
line = ""
while cur < len(splt_text):
new_line = ""
if len(line) > 0:
new_line = f"{line} {splt_text[cur]}"
else:
new_line = splt_text[cur]
r = pygame.freetype.Font.get_rect(font, new_line)
if r.width > width:
lines.append(line)
line = ""
else:
line = new_line
cur += 1
if len(line) > 0:
lines.append(line)
return lines
# #################################################################
def MakeStats():
stats = {}
for n,vals in STATS.items():
astat = agent_stat.Stat(n,vals)
stats[n] = astat
return stats
def MakeAgent(agent_name, cur_time):
a = agent.Agent(
agent_name,
MakeStats(),
f"{agent_name} is doin' nuthin'."
)
return a
def UpdateAgent(myagent, curtime):
myagent.update_action(curtime)
def DrawUI(display,
cur_time,
myagent,
winw, winh,
stat_index,
game_speed,
decision_sys_running):
display.draw_text(
f"Day: {cur_time.day_of_week()}",
10,10,FG_COLOR)
display.draw_text(
f"Hour: {cur_time.hour():02}",
180,10,FG_COLOR)
display.draw_text(
f"Min: {cur_time.minit():02}",
300,10,FG_COLOR)
display.draw_text(
f"{myagent.get_name()}'s stats",
10,40,FG_COLOR)
display.draw_text(
f"Game: {game_speed[0]}",
410,10,FG_COLOR)
display.draw_text(
f"Decision Sys: {decision_sys_running}",
580,10,FG_COLOR)
display.draw_line((400,0),(400,winh),"black",2)
display.draw_text(
f"{myagent.get_name()}'s Action",
410,40,FG_COLOR)
wrapped_msg = wrap_text(myagent.get_action_message(),
display.font, 380)
y = 70
for msg in wrapped_msg:
display.draw_text(
msg,
410, y, FG_COLOR)
y += 25
y = 70
x = 10
for i,name in enumerate(STAT_NAMES):
s = myagent.get_stat(name)
c = FG_COLOR
if i == stat_index:
c = 'red'
display.draw_text(
f"{name:<12} {s.get_value()}",
x,y,c)
y += 25
if y+25 > winh:
x += 200
y = 70
def MakeDecisionSys(myagent):
decision.make_decisionsys(myagent)
def CheckDecisionSys(myagent, curtime):
decision.tick_decisionsys(myagent, curtime)
def GameLoop(display, _agent, _time):
winw, winh = pygame.display.get_window_size()
curtime = _time
myagent = _agent
stat_index = 0
old_speed = 0
sim_speed = 0
time_last_tick = 0
next_behavior_update = curtime
decision_sys_running = False
# Here is where the behavior is created before the
# game loop starts.
MakeDecisionSys(myagent)
while display.run:
ticks = display.clock.tick(60)
dt = ticks / 1000
for event in pygame.event.get():
if event.type == pygame.QUIT:
display.run = False
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
myagent.change_stat(STAT_NAMES[stat_index],-1)
elif event.key == pygame.K_RIGHT:
myagent.change_stat(STAT_NAMES[stat_index],1)
elif event.key == pygame.K_UP:
stat_index = ((stat_index-1)+len(STAT_NAMES))%len(STAT_NAMES)
elif event.key == pygame.K_DOWN:
stat_index = (stat_index+1)%len(STAT_NAMES)
elif event.key == pygame.K_LEFTBRACKET:
if sim_speed > 0:
sim_speed -= 1
elif event.key == pygame.K_RIGHTBRACKET:
if sim_speed < len(GAME_SPEEDS)-1:
sim_speed += 1
elif event.key == pygame.K_p:
if sim_speed == 0:
sim_speed = old_speed
else:
old_speed = sim_speed
sim_speed = 0
elif event.key == pygame.K_q:
display.run = False
elif event.key == pygame.K_d:
curtime.tick(60*24)
elif event.key == pygame.K_s:
curtime.tick(-60*24)
elif event.key == pygame.K_h:
curtime.tick(60)
elif event.key == pygame.K_g:
curtime.tick(-60)
elif event.key == pygame.K_m:
curtime.tick(1)
elif event.key == pygame.K_n:
curtime.tick(-1)
elif event.key == pygame.K_SPACE:
decision_sys_running = not decision_sys_running
# This function call checks the agent's action. If the
# action has expired, the agent is set to idle.
UpdateAgent(myagent, curtime)
# Here is where the agent's behavior is checked.
# and if necessary, is switched to another action.
if decision_sys_running:
CheckDecisionSys(myagent, curtime)
display.screen.fill(BG_COLOR)
DrawUI(display, curtime, myagent, winw, winh, stat_index,
GAME_SPEEDS[sim_speed], decision_sys_running)
pygame.display.flip()
if GAME_SPEEDS[sim_speed][1] - time_last_tick <= 0:
curtime.tick(GAME_SPEEDS[sim_speed][2])
time_last_tick = 0
else:
time_last_tick += ticks
def main():
display = init_display(800,600)
myagent = MakeAgent(AGENT_NAME, START_TIME)
cur_time = ztime.Time(START_TIME)
GameLoop(display, myagent, cur_time)
if __name__ == "__main__":
main()