Spaces:
Running
Running
감정 고도화 작업
Browse files
npc_social_network/maps/engine/game_engine.py
CHANGED
@@ -1,4 +1,4 @@
|
|
1 |
-
# portfolio/npc_social_network/maps/
|
2 |
# 게임 루프 및 이벤트 처리
|
3 |
import pygame
|
4 |
from datetime import datetime, timedelta
|
@@ -14,23 +14,44 @@ class GameEngine:
|
|
14 |
self.time_states = time_states
|
15 |
self.current_time_index = 0
|
16 |
self.frame_count = 0
|
17 |
-
self.frame_per_time_state = 200
|
18 |
self.npcs = npcs # 전체 NPC 리스트
|
19 |
|
|
|
|
|
|
|
|
|
20 |
def draw(self):
|
21 |
self.village.draw(self.screen) # 마을 전체를 그림
|
22 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
23 |
self.screen.blit(time_text, (10, 10))
|
24 |
|
25 |
def update(self):
|
26 |
self.frame_count += 1
|
|
|
|
|
27 |
if self.frame_count % self.frame_per_time_state == 0:
|
28 |
self.current_time_index = (self.current_time_index + 1) % len(self.time_states)
|
29 |
print(f"\n🕒시간 변경: {self.time_states[self.current_time_index]}")
|
30 |
|
|
|
|
|
|
|
|
|
31 |
if self.frame_count % 20 == 0:
|
32 |
self.village.update_npcs(self.time_states[self.current_time_index])
|
33 |
|
|
|
|
|
|
|
|
|
|
|
34 |
def handle_click(self, pos):
|
35 |
mx, my = pos
|
36 |
tile_x = mx // self.village.tile_size
|
@@ -39,4 +60,5 @@ class GameEngine:
|
|
39 |
if npc:
|
40 |
print(f"\n👤 {npc.name} ({npc.job})")
|
41 |
print(f" - 위치: ({tile_x}, {tile_y})")
|
42 |
-
print(f" - 대화: {npc.generate_dialogue()}")
|
|
|
|
1 |
+
# portfolio/npc_social_network/maps/engine/game_engine.py
|
2 |
# 게임 루프 및 이벤트 처리
|
3 |
import pygame
|
4 |
from datetime import datetime, timedelta
|
|
|
14 |
self.time_states = time_states
|
15 |
self.current_time_index = 0
|
16 |
self.frame_count = 0
|
17 |
+
self.frame_per_time_state = 200 # 기존: 시간 상태 전환 프레임
|
18 |
self.npcs = npcs # 전체 NPC 리스트
|
19 |
|
20 |
+
# 실제 시간 흐름 시뮬레이션용
|
21 |
+
self.current_time = datetime.now() # 현재 시뮬레이션 시간
|
22 |
+
self.time_step = timedelta(minutes=1) # 1틱 = 1분
|
23 |
+
|
24 |
def draw(self):
|
25 |
self.village.draw(self.screen) # 마을 전체를 그림
|
26 |
+
|
27 |
+
# 상단 시간 텍스트 출력
|
28 |
+
time_state_text = self.time_states[self.current_time_index]
|
29 |
+
time_text = self.font.render(
|
30 |
+
f"현재 시간: {time_state_text} | {self.current_time.strftime('%H:%M')}",
|
31 |
+
True, (0, 0, 0)
|
32 |
+
)
|
33 |
self.screen.blit(time_text, (10, 10))
|
34 |
|
35 |
def update(self):
|
36 |
self.frame_count += 1
|
37 |
+
|
38 |
+
# 1) 시간 상태(아침/점심 등) 순환 유지
|
39 |
if self.frame_count % self.frame_per_time_state == 0:
|
40 |
self.current_time_index = (self.current_time_index + 1) % len(self.time_states)
|
41 |
print(f"\n🕒시간 변경: {self.time_states[self.current_time_index]}")
|
42 |
|
43 |
+
# 2) 실제 시간 경과
|
44 |
+
self.current_time += self.time_step
|
45 |
+
|
46 |
+
# NPC 행동/기억 업데이트
|
47 |
if self.frame_count % 20 == 0:
|
48 |
self.village.update_npcs(self.time_states[self.current_time_index])
|
49 |
|
50 |
+
# NPC 기억 승격 판단
|
51 |
+
if self.frame_count % 60 == 0: # 60 프레임마다 약 3초 기준
|
52 |
+
for npc in self.npcs:
|
53 |
+
npc.memory_store.promote_memories(time_threshold_minutes=60)
|
54 |
+
|
55 |
def handle_click(self, pos):
|
56 |
mx, my = pos
|
57 |
tile_x = mx // self.village.tile_size
|
|
|
60 |
if npc:
|
61 |
print(f"\n👤 {npc.name} ({npc.job})")
|
62 |
print(f" - 위치: ({tile_x}, {tile_y})")
|
63 |
+
print(f" - 대화: {npc.generate_dialogue()}")
|
64 |
+
print(f" - 기억: {npc.recall()}")
|
npc_social_network/maps/villages/town_hall.py
CHANGED
@@ -24,8 +24,13 @@ font = pygame.font.SysFont("malgungothic", 20) # 한글 출력용
|
|
24 |
image_loader = ImageLoader(tile_size)
|
25 |
village = VillageMap(image_loader, tile_size, width, height)
|
26 |
village.generate()
|
27 |
-
|
28 |
-
|
|
|
|
|
|
|
|
|
|
|
29 |
|
30 |
# pygame 루프
|
31 |
runnig = True
|
|
|
24 |
image_loader = ImageLoader(tile_size)
|
25 |
village = VillageMap(image_loader, tile_size, width, height)
|
26 |
village.generate()
|
27 |
+
|
28 |
+
|
29 |
+
# npc 리스트 추출
|
30 |
+
npcs = village.npc_manager.npcs
|
31 |
+
|
32 |
+
# 게임 엔진 초기 세팅
|
33 |
+
engine = GameEngine(screen, font, village, ["아침", "점심", "저녁", "밤"], npcs)
|
34 |
|
35 |
# pygame 루프
|
36 |
runnig = True
|
npc_social_network/npc/npc_base.py
CHANGED
@@ -1,6 +1,5 @@
|
|
1 |
# portfolio/npc_social_network/npc/npc_base.py
|
2 |
-
from .npc_memory import Memory
|
3 |
-
from .npc_memory import MemoryStore
|
4 |
|
5 |
# NPC 클래스 정의
|
6 |
class NPC:
|
@@ -18,6 +17,48 @@ class NPC:
|
|
18 |
# npc 기억
|
19 |
self.memory_store = MemoryStore()
|
20 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
21 |
# 확장 가능 속성
|
22 |
# self.emotion = "neutral"
|
23 |
# self.personality = {"kind": 0.5, "lazy": 0.2} # 예시
|
@@ -35,6 +76,10 @@ class NPC:
|
|
35 |
x, y = self.get_position()
|
36 |
screen.blit(self.image, (x * tile_size, y * tile_size))
|
37 |
|
|
|
|
|
|
|
|
|
38 |
# 직업에 따른 기본 대사 생성
|
39 |
def generate_dialogue(self):
|
40 |
if self.job == "farmer":
|
|
|
1 |
# portfolio/npc_social_network/npc/npc_base.py
|
2 |
+
from .npc_memory import Memory, MemoryStore
|
|
|
3 |
|
4 |
# NPC 클래스 정의
|
5 |
class NPC:
|
|
|
17 |
# npc 기억
|
18 |
self.memory_store = MemoryStore()
|
19 |
|
20 |
+
# 고차원 감정 상태 정의 (GoEmotions 기반)
|
21 |
+
self.emotion_state = {
|
22 |
+
# 기본 정서 (긍정)
|
23 |
+
"core_positive":{
|
24 |
+
"joy": 0, # 기쁨
|
25 |
+
"satisfaction": 0, # 만족
|
26 |
+
"gratitude": 0, # 감사
|
27 |
+
"calm": 0, # 평온
|
28 |
+
"anticipation": 0, # 기대
|
29 |
+
"pride": 0, # 자부심
|
30 |
+
"connectedness": 0 # 유대감
|
31 |
+
},
|
32 |
+
# 기본 정서 (부정)
|
33 |
+
"core_negative": {
|
34 |
+
"sadness": 0, # 슬픔
|
35 |
+
"anger": 0, # 분노
|
36 |
+
"anxiety": 0, # 불안
|
37 |
+
"disgust": 0, # 혐오
|
38 |
+
"fear": 0, # 공포
|
39 |
+
"regret": 0, # 후회
|
40 |
+
"frustration": 0 # 좌절
|
41 |
+
},
|
42 |
+
# 사회적 감정
|
43 |
+
"social_emotion": {
|
44 |
+
"jealousy": 0, # 질투
|
45 |
+
"shame": 0, # 수치심
|
46 |
+
"guilt": 0, # 죄책감
|
47 |
+
"compassion": 0, # 동정심
|
48 |
+
"awe": 0, # 경외심
|
49 |
+
"empathy": 0 # 공감
|
50 |
+
},
|
51 |
+
# 인지적 상태
|
52 |
+
"cognitive_state": {
|
53 |
+
"confusion": 0, # 혼란
|
54 |
+
"nervousness": 0, # 긴장
|
55 |
+
"apathy": 0, # 무관심
|
56 |
+
"excitement": 0, # 흥분
|
57 |
+
"immersion": 0, # 몰입
|
58 |
+
"skepticism": 0 # 회의
|
59 |
+
}
|
60 |
+
}
|
61 |
+
|
62 |
# 확장 가능 속성
|
63 |
# self.emotion = "neutral"
|
64 |
# self.personality = {"kind": 0.5, "lazy": 0.2} # 예시
|
|
|
76 |
x, y = self.get_position()
|
77 |
screen.blit(self.image, (x * tile_size, y * tile_size))
|
78 |
|
79 |
+
# 감정 상태에 따른 대사 생성 (대표 감정 하나 반영)
|
80 |
+
def generate_dialogue(self):
|
81 |
+
pass
|
82 |
+
|
83 |
# 직업에 따른 기본 대사 생성
|
84 |
def generate_dialogue(self):
|
85 |
if self.job == "farmer":
|
test.ipynb
CHANGED
@@ -2699,6 +2699,52 @@
|
|
2699 |
"# GPU 지원 버전으로 다시 설치\n",
|
2700 |
"!pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu118"
|
2701 |
]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2702 |
}
|
2703 |
],
|
2704 |
"metadata": {
|
|
|
2699 |
"# GPU 지원 버전으로 다시 설치\n",
|
2700 |
"!pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu118"
|
2701 |
]
|
2702 |
+
},
|
2703 |
+
{
|
2704 |
+
"cell_type": "code",
|
2705 |
+
"execution_count": 1,
|
2706 |
+
"id": "8140bcea",
|
2707 |
+
"metadata": {},
|
2708 |
+
"outputs": [
|
2709 |
+
{
|
2710 |
+
"name": "stdout",
|
2711 |
+
"output_type": "stream",
|
2712 |
+
"text": [
|
2713 |
+
"pygame 2.6.1 (SDL 2.28.4, Python 3.11.11)\n",
|
2714 |
+
"Hello from the pygame community. https://www.pygame.org/contribute.html\n"
|
2715 |
+
]
|
2716 |
+
},
|
2717 |
+
{
|
2718 |
+
"ename": "SystemExit",
|
2719 |
+
"evalue": "",
|
2720 |
+
"output_type": "error",
|
2721 |
+
"traceback": [
|
2722 |
+
"An exception has occurred, use %tb to see the full traceback.\n",
|
2723 |
+
"\u001b[31mSystemExit\u001b[39m\n"
|
2724 |
+
]
|
2725 |
+
},
|
2726 |
+
{
|
2727 |
+
"name": "stderr",
|
2728 |
+
"output_type": "stream",
|
2729 |
+
"text": [
|
2730 |
+
"c:\\Users\\stina\\.conda\\envs\\portfolio\\Lib\\site-packages\\IPython\\core\\interactiveshell.py:3678: UserWarning: To exit: use 'exit', 'quit', or Ctrl-D.\n",
|
2731 |
+
" warn(\"To exit: use 'exit', 'quit', or Ctrl-D.\", stacklevel=1)\n"
|
2732 |
+
]
|
2733 |
+
}
|
2734 |
+
],
|
2735 |
+
"source": [
|
2736 |
+
"# pygame simulator 실행기 (임시)\n",
|
2737 |
+
"\n",
|
2738 |
+
"# 1. 환경 변수 설정 (모듈 인식 위해)\n",
|
2739 |
+
"import sys\n",
|
2740 |
+
"import os\n",
|
2741 |
+
"sys.path.append(os.path.abspath(\".\")) # 최상위 경로를 sys.path에 추가\n",
|
2742 |
+
"\n",
|
2743 |
+
"# 2. town_hall 직접 import 후 실행\n",
|
2744 |
+
"from npc_social_network.maps.villages import town_hall\n",
|
2745 |
+
"\n",
|
2746 |
+
"# town_hall.py는 __main__이 아니라 직접 실행되므로"
|
2747 |
+
]
|
2748 |
}
|
2749 |
],
|
2750 |
"metadata": {
|