245 lines
6.9 KiB
Python
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()
|