Spaces:
Sleeping
Sleeping
humanda5
commited on
Commit
·
93a860a
1
Parent(s):
d63937b
테스트
Browse files- npc_social_network/maps/engine/game_engine.py +36 -0
- npc_social_network/maps/manager/building.py +11 -0
- npc_social_network/maps/manager/image_loader.py +22 -0
- npc_social_network/maps/manager/image_registry.py +25 -0
- npc_social_network/maps/manager/tile.py +11 -0
- npc_social_network/maps/manager/village_map.py +64 -0
- npc_social_network/maps/town_hall.py +0 -166
- npc_social_network/maps/villages/town_hall.py +79 -0
- npc_social_network/npc/npc_base.py +32 -0
- npc_social_network/npc/npc_manager.py +27 -0
- npc_social_network/static/images/tiles/{topography → terrain}/tile_dirt.png +0 -0
- npc_social_network/static/images/tiles/{topography → terrain}/tile_grass.png +0 -0
- npc_social_network/static/images/tiles/{topography → terrain}/tile_pool.png +0 -0
- npc_social_network/static/images/tiles/{topography → terrain}/tile_stone.png +0 -0
- npc_social_network/static/images/tiles/{topography → terrain}/tile_water.png +0 -0
npc_social_network/maps/engine/game_engine.py
ADDED
@@ -0,0 +1,36 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# portfolio/npc_social_network/maps/manager/game_engine.py
|
2 |
+
# 게임 루프 및 이벤트 처리
|
3 |
+
import pygame
|
4 |
+
|
5 |
+
class GameEngine:
|
6 |
+
def __init__(self, screen, font, village, time_states):
|
7 |
+
self.screen = screen
|
8 |
+
self.font = font
|
9 |
+
self.village = village
|
10 |
+
self.time_states = time_states
|
11 |
+
self.current_time_index = 0
|
12 |
+
self.frame_count = 0
|
13 |
+
self.frame_per_time_state = 200
|
14 |
+
|
15 |
+
def draw_time(self):
|
16 |
+
time_text = self.font.render(f"현재 시간: {self.time_states[self.current_time_index]}", True, (0, 0, 0))
|
17 |
+
self.screen.blit(time_text, (10, 10))
|
18 |
+
|
19 |
+
def update(self):
|
20 |
+
self.frame_count += 1
|
21 |
+
if self.frame_count % self.frame_per_time_state == 0:
|
22 |
+
self.current_time_index = (self.current_time_index + 1) % len(self.time_states)
|
23 |
+
print(f"\n🕒시간 변경: {self.time_states[self.current_time_index]}")
|
24 |
+
|
25 |
+
if self.frame_count % 20 == 0:
|
26 |
+
self.village.update_npcs(self.time_states[self.current_time_index])
|
27 |
+
|
28 |
+
def handle_click(self, pos):
|
29 |
+
mx, my = pos
|
30 |
+
tile_x = mx // self.village.tile_size
|
31 |
+
tile_y = my // self.village.tile_size
|
32 |
+
npc = self.village.npc_manager.get_npc_at(tile_x, tile_y)
|
33 |
+
if npc:
|
34 |
+
print(f"\n👤 {npc.name} ({npc.job})")
|
35 |
+
print(f" - 위치: ({tile_x}, {tile_y})")
|
36 |
+
print(f" - 대화: {npc.generate_dialogue()}")
|
npc_social_network/maps/manager/building.py
ADDED
@@ -0,0 +1,11 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# portfolio/npc_social_network/maps/manager/building.py
|
2 |
+
# 건물 클래스 정의
|
3 |
+
class Building:
|
4 |
+
def __init__(self, x, y, b_type, image):
|
5 |
+
self.x = x
|
6 |
+
self.y = y
|
7 |
+
self.type = b_type
|
8 |
+
self.image = image
|
9 |
+
|
10 |
+
def draw(self, screen, tile_size):
|
11 |
+
screen.blit(self.image, (self.x * tile_size, self.y * tile_size))
|
npc_social_network/maps/manager/image_loader.py
ADDED
@@ -0,0 +1,22 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# portfolio/npc_social_network/maps/manager/image_loader.py
|
2 |
+
# 이미지 로더 클래스
|
3 |
+
import os
|
4 |
+
import pygame
|
5 |
+
from npc_social_network.maps.manager.image_registry import IMAGE_PATHS
|
6 |
+
|
7 |
+
class ImageLoader:
|
8 |
+
def __init__(self, tile_size):
|
9 |
+
self.tile_size = tile_size
|
10 |
+
self.base_path = "../static/images/tiles"
|
11 |
+
self.cache = {}
|
12 |
+
|
13 |
+
def load(self, category, key):
|
14 |
+
path = IMAGE_PATHS[category][key]
|
15 |
+
if path in self.cache:
|
16 |
+
return self.cache[path]
|
17 |
+
|
18 |
+
full_path = os.path.join(self.base_path, path)
|
19 |
+
image = pygame.image.load(full_path)
|
20 |
+
image = pygame.transform.scale(image, (self.tile_size, self.tile_size))
|
21 |
+
self.cache[path] = image
|
22 |
+
return image
|
npc_social_network/maps/manager/image_registry.py
ADDED
@@ -0,0 +1,25 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# portfolio/npc_social_network/maps/manager/image_registry.py
|
2 |
+
# 모든 이미지 경로 중앙관리
|
3 |
+
|
4 |
+
IMAGE_PATHS = {
|
5 |
+
"terrain": {
|
6 |
+
"grass": "terrain/tile_grass.png",
|
7 |
+
"dirt": "terrain/tile_dirt.png",
|
8 |
+
"stone": "terrain/tile_stone.png",
|
9 |
+
"water": "terrain/tile_water.png",
|
10 |
+
"pool" : "terrain/tile_pool.png",
|
11 |
+
},
|
12 |
+
"building": {
|
13 |
+
"house": "building/build_house.png",
|
14 |
+
"temple": "building/build_temple.png",
|
15 |
+
"market": "building/build_market.png",
|
16 |
+
},
|
17 |
+
"plant": {
|
18 |
+
"tree": "plant/plant_tree.png",
|
19 |
+
"wheat": "plant/plant_wheat.png",
|
20 |
+
"raspberry": "plant/plant_raspberry.png",
|
21 |
+
},
|
22 |
+
"npc": {
|
23 |
+
"default": "npc/npc.png",
|
24 |
+
}
|
25 |
+
}
|
npc_social_network/maps/manager/tile.py
ADDED
@@ -0,0 +1,11 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# portfolio/npc_social_network/maps/manager/tile.py
|
2 |
+
# 타일 클래스 정의
|
3 |
+
class Tile:
|
4 |
+
def __init__(self, x, y, tile_type, image):
|
5 |
+
self.x = x
|
6 |
+
self.y = y
|
7 |
+
self.type = tile_type
|
8 |
+
self.image = image
|
9 |
+
|
10 |
+
def draw(self, screen, tile_size):
|
11 |
+
screen.blit(self.image, (self.x * tile_size, self.y * tile_size))
|
npc_social_network/maps/manager/village_map.py
ADDED
@@ -0,0 +1,64 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# portfolio/npc_social_network/maps/manager/village_map.py
|
2 |
+
# 마을 전체 관리 클래스
|
3 |
+
|
4 |
+
from npc_social_network.npc.npc_base import NPC
|
5 |
+
from npc_social_network.npc.npc_manager import NPCManager
|
6 |
+
|
7 |
+
class Building:
|
8 |
+
def __init__(self, x, y, b_type, image):
|
9 |
+
self.x = x
|
10 |
+
self.y = y
|
11 |
+
self.type = b_type
|
12 |
+
self.image = image
|
13 |
+
|
14 |
+
def draw(self, screen, tile_size):
|
15 |
+
screen.blit(self.image, (self.x * tile_size, self.y * tile_size))
|
16 |
+
|
17 |
+
class VillageMap:
|
18 |
+
def __init__(self, image_loader, tile_size, grid_width, grid_height):
|
19 |
+
self.image_loader = image_loader
|
20 |
+
self.tile_size = tile_size
|
21 |
+
self.grid_width = grid_width
|
22 |
+
self.grid_height = grid_height
|
23 |
+
self.tiles = []
|
24 |
+
self.buildings = []
|
25 |
+
self.npc_manager = NPCManager()
|
26 |
+
|
27 |
+
def generate(self):
|
28 |
+
import random
|
29 |
+
|
30 |
+
terrain_keys = list(self.image_loader.cache.keys()) or ["grass", "dirt", "stone"]
|
31 |
+
|
32 |
+
for y in range(self.grid_height):
|
33 |
+
for x in range(self.grid_width):
|
34 |
+
terrain = random.choice(["grass", "dirt", "stone"])
|
35 |
+
image = self.image_loader.load("terrain", terrain)
|
36 |
+
self.tiles.append((x, y, image))
|
37 |
+
|
38 |
+
# 건물 초기 세팅값
|
39 |
+
self.buildings = [
|
40 |
+
Building(2, 3, "house", self.image_loader.load("building/build_house.png")),
|
41 |
+
Building(5, 5, "market", self.image_loader.load("building/build_market.png")),
|
42 |
+
Building(10, 3, "wheat", self.image_loader.load("plant/plant_wheat.png")),
|
43 |
+
Building(8, 8, "temple", self.image_loader.load("building/build_temple.png")),
|
44 |
+
]
|
45 |
+
|
46 |
+
# NPC 초기 세팅값
|
47 |
+
elin_path = [[2,3], [3,3], [4,3], [5,3], [5,4], [5,5], [4,5], [3, 5], [2,5], [2,4]]
|
48 |
+
elin = NPC("Elin", "farmer", elin_path, self.image_loader.load("npc", "default"))
|
49 |
+
self.npc_manager.add_npc(elin)
|
50 |
+
|
51 |
+
def draw(self, screen):
|
52 |
+
for x, y, image in self.tiles:
|
53 |
+
screen.blit(image, (x * self.tile_size, y * self.tile_size))
|
54 |
+
for b in self.buildings:
|
55 |
+
b.draw(screen, self.tile_size)
|
56 |
+
self.npc_manager.draw_all(screen, self.tile_size)
|
57 |
+
|
58 |
+
def update_npcs(self, time_state):
|
59 |
+
self.npc_manager.move_all()
|
60 |
+
for npc in self.npc_manager.all():
|
61 |
+
x, y = npc.get_position()
|
62 |
+
for b in self. buildings:
|
63 |
+
if (b.x, b.y) == (x, y):
|
64 |
+
print(f"{time_state} - {npc.name}이(가) {b.type}에 도착했습니다.")
|
npc_social_network/maps/town_hall.py
DELETED
@@ -1,166 +0,0 @@
|
|
1 |
-
# portfolio/npc_social_network/maps/town_hall.py
|
2 |
-
import pygame
|
3 |
-
import sys
|
4 |
-
import random
|
5 |
-
import os
|
6 |
-
|
7 |
-
# 초기 설정
|
8 |
-
pygame.init()
|
9 |
-
tile_size = 32
|
10 |
-
grid_width, grid_height = 20, 20
|
11 |
-
screen = pygame.display.set_mode((grid_width * tile_size, grid_height * tile_size))
|
12 |
-
pygame.display.set_caption("town_hall")
|
13 |
-
|
14 |
-
# 캐릭터가 움직이는 일정 시간
|
15 |
-
clock = pygame.time.Clock()
|
16 |
-
font = pygame.font.SysFont("malgungothic", 20) # 한글 출력용
|
17 |
-
|
18 |
-
# 이미지 로드 함수
|
19 |
-
def load_image(name):
|
20 |
-
path = os.path.join("../static/images/tiles", name) # 이미지들은 images/tiles 폴더에 저장한다고 가정
|
21 |
-
return pygame.transform.scale(pygame.image.load(path), (tile_size, tile_size))
|
22 |
-
|
23 |
-
# 타일 이미지 사전
|
24 |
-
TILE_IMAGES = {
|
25 |
-
# 지형
|
26 |
-
"grass": load_image("topography/tile_grass.png"),
|
27 |
-
"dirt": load_image("topography/tile_dirt.png"),
|
28 |
-
"stone": load_image("topography/tile_stone.png"),
|
29 |
-
"water": load_image("topography/tile_water.png"),
|
30 |
-
|
31 |
-
# 건물
|
32 |
-
"house": load_image("building/build_house.png"),
|
33 |
-
"temple": load_image("building/build_temple.png"),
|
34 |
-
"market": load_image("building/build_market.png"),
|
35 |
-
|
36 |
-
# 동물
|
37 |
-
|
38 |
-
# 식물
|
39 |
-
"tree":load_image("plant/plant_tree.png"),
|
40 |
-
"wheat":load_image("plant/plant_wheat.png"),
|
41 |
-
|
42 |
-
# 사람
|
43 |
-
"npc":load_image("npc/npc.png"),
|
44 |
-
}
|
45 |
-
|
46 |
-
# 색상 정의
|
47 |
-
COLORS = {
|
48 |
-
"empty": (230, 230, 230),
|
49 |
-
}
|
50 |
-
|
51 |
-
# 랜덤 배경 타일 생성
|
52 |
-
terrain_types = ["grass", "dirt", "stone", "water"]
|
53 |
-
terrain_map = [[random.choice(terrain_types) for _ in range(grid_width)] for _ in range(grid_height)]
|
54 |
-
|
55 |
-
# 시간 흐름 정의
|
56 |
-
time_states = ["아침", "점심", "저녁", "밤"]
|
57 |
-
current_time_index = 0
|
58 |
-
frame_per_time_state = 200 # 약 20초마다 시간 변경
|
59 |
-
|
60 |
-
# 마을 구조 정의
|
61 |
-
village_map = {
|
62 |
-
"buildings": [
|
63 |
-
{"type": "house", "location": [2,3]},
|
64 |
-
{"type": "house", "location": [3,3]},
|
65 |
-
{"type": "market", "location": [5,5]},
|
66 |
-
{"type": "wheat", "location": [10,3]},
|
67 |
-
{"type": "temple", "location": [8,8]},
|
68 |
-
],
|
69 |
-
"npcs":[
|
70 |
-
{"type": "npc", "name": "Elin", "job": "farmer", "location": [2,3], "path": [[2, 3], [3, 3], [4, 3], [5, 3], [5, 4], [5, 5], [4, 5], [3, 5], [2, 5], [2, 4]]},
|
71 |
-
]
|
72 |
-
}
|
73 |
-
|
74 |
-
# 이벤트 발생 함수
|
75 |
-
def check_event(npc, time_state):
|
76 |
-
for building in village_map["buildings"]:
|
77 |
-
if npc["location"] == building["location"]:
|
78 |
-
if building["type"] == "market":
|
79 |
-
print(f"{time_state} - {npc['name']}이(가) 시장에 도착하여 물건을 샀습니다.")
|
80 |
-
elif building["type"] == "temple":
|
81 |
-
print(f"{time_state} - {npc['name']}이(가) 사원에서 기도를 드립니다.")
|
82 |
-
elif building["type"] == "wheat":
|
83 |
-
print(f"{time_state} - {npc['name']}이(가) 농장에서 일을 시작합니다.")
|
84 |
-
elif building["type"] == "house":
|
85 |
-
print(f"{time_state} - {npc['name']}이(가) 집에 돌아왔습니다.")
|
86 |
-
|
87 |
-
|
88 |
-
# NPC 이동 함수
|
89 |
-
def move_npcs():
|
90 |
-
for npc in village_map["npcs"]:
|
91 |
-
path = npc.get("path", [])
|
92 |
-
if not path:
|
93 |
-
continue
|
94 |
-
|
95 |
-
current_idx = path.index(npc["location"]) if npc["location"] in path else 0
|
96 |
-
next_idx = (current_idx + 1) % len(path)
|
97 |
-
npc["location"] = path[next_idx]
|
98 |
-
check_event(npc, time_states[current_time_index])
|
99 |
-
|
100 |
-
# NPC 클릭 처리
|
101 |
-
def handle_npc_click(pos):
|
102 |
-
mx, my = pos
|
103 |
-
tile_x = mx // tile_size
|
104 |
-
tile_y = my // tile_size
|
105 |
-
|
106 |
-
for npc in village_map["npcs"]:
|
107 |
-
x, y = npc["location"]
|
108 |
-
if x == tile_x and y == tile_y:
|
109 |
-
print(f"\n👤 {npc['name']} ({npc['job']})")
|
110 |
-
print(f" - 위치: ({x}, {y})")
|
111 |
-
print(f" - 대화: {generate_dialogue(npc)}")
|
112 |
-
|
113 |
-
# 간단한 대화 생성
|
114 |
-
def generate_dialogue(npc):
|
115 |
-
if npc["job"] == "farmer":
|
116 |
-
return "오늘은 밭에 나갈 날이군요!"
|
117 |
-
elif npc["job"] == "blacksmith":
|
118 |
-
return "망치를 들고 일할 준비가 되었어요!"
|
119 |
-
return "좋은 하루입니다."
|
120 |
-
|
121 |
-
# 화면 렌더링 함수
|
122 |
-
def draw_map():
|
123 |
-
for y in range(grid_height):
|
124 |
-
for x in range(grid_width):
|
125 |
-
terrain = terrain_map[y][x]
|
126 |
-
screen.blit(TILE_IMAGES[terrain], (x * tile_size, y * tile_size))
|
127 |
-
|
128 |
-
for building in village_map["buildings"]:
|
129 |
-
x, y = building["location"]
|
130 |
-
screen.blit(TILE_IMAGES[building["type"]], (x * tile_size, y * tile_size))
|
131 |
-
|
132 |
-
for npc in village_map["npcs"]:
|
133 |
-
x, y = npc["location"]
|
134 |
-
screen.blit(TILE_IMAGES[npc["type"]], (x * tile_size, y * tile_size))
|
135 |
-
|
136 |
-
# 현재 시간 표시
|
137 |
-
current_time_text = font.render(f"현재 시간: {time_states[current_time_index]}", True, (0, 0, 0))
|
138 |
-
screen.blit(current_time_text, (10, 10))
|
139 |
-
|
140 |
-
# pygame 루프
|
141 |
-
frame_count = 0
|
142 |
-
runnig = True
|
143 |
-
while runnig:
|
144 |
-
draw_map()
|
145 |
-
pygame.display.update()
|
146 |
-
clock.tick(10) # 초당 10프레임
|
147 |
-
|
148 |
-
frame_count += 1
|
149 |
-
|
150 |
-
# 시간 전환
|
151 |
-
if frame_count % frame_per_time_state == 0:
|
152 |
-
current_time_index = (current_time_index + 1) % len(time_states)
|
153 |
-
print(f"\n 시간 변경: {time_states[current_time_index]}")
|
154 |
-
|
155 |
-
# NPC 이동 주기
|
156 |
-
if frame_count % 20 == 0: # 약 2초에 한 번 이동
|
157 |
-
move_npcs()
|
158 |
-
|
159 |
-
for event in pygame.event.get():
|
160 |
-
if event.type == pygame.QUIT:
|
161 |
-
runnig = False
|
162 |
-
elif event.type == pygame.MOUSEBUTTONDOWN:
|
163 |
-
handle_npc_click(pygame.mouse.get_pos())
|
164 |
-
|
165 |
-
pygame.quit()
|
166 |
-
sys.exit()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
npc_social_network/maps/villages/town_hall.py
ADDED
@@ -0,0 +1,79 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# portfolio/npc_social_network/maps/villages/town_hall.py
|
2 |
+
# 메인 실행 파일
|
3 |
+
|
4 |
+
# 이미지 파일 경로는 한 곳에서 딕셔너리로 관리하기
|
5 |
+
# 게임 엔진 파일에서 게임 루프 및 이벤트 관리한다고 했는데 안되어 있음
|
6 |
+
import pygame
|
7 |
+
import sys
|
8 |
+
from npc_social_network.maps.manager.image_loader import ImageLoader
|
9 |
+
from npc_social_network.maps.manager.village_map import VillageMap
|
10 |
+
|
11 |
+
# 초기 설정
|
12 |
+
pygame.init()
|
13 |
+
|
14 |
+
tile_size = 32
|
15 |
+
grid_width, grid_height = 20, 20
|
16 |
+
screen = pygame.display.set_mode((grid_width * tile_size, grid_height * tile_size))
|
17 |
+
pygame.display.set_caption("town_hall")
|
18 |
+
|
19 |
+
# 캐릭터가 움직이는 일정 시간
|
20 |
+
clock = pygame.time.Clock()
|
21 |
+
font = pygame.font.SysFont("malgungothic", 20) # 한글 출력용
|
22 |
+
|
23 |
+
# 시간 흐름 정의
|
24 |
+
time_states = ["아침", "점심", "저녁", "밤"]
|
25 |
+
current_time_index = 0
|
26 |
+
frame_per_time_state = 200 # 약 20초마다 시간 변경
|
27 |
+
frame_count = 0
|
28 |
+
|
29 |
+
# 마을 이미지 로드
|
30 |
+
image_loader = ImageLoader(tile_size)
|
31 |
+
village = VillageMap(image_loader, tile_size, grid_width, grid_height)
|
32 |
+
village.generate()
|
33 |
+
|
34 |
+
# 화면에 시간 보여주기
|
35 |
+
def draw_time():
|
36 |
+
time_text = font.render(f"현재 시간: {time_states[current_time_index]}", True, (0, 0, 0))
|
37 |
+
screen.blit(time_text, (10, 10))
|
38 |
+
|
39 |
+
# NPC 클릭 처리
|
40 |
+
def handle_npc_click(pos):
|
41 |
+
mx, my = pos
|
42 |
+
tile_x = mx // tile_size
|
43 |
+
tile_y = my // tile_size
|
44 |
+
|
45 |
+
for npc in village.npcs:
|
46 |
+
x, y = npc.get_position()
|
47 |
+
if x == tile_x and y == tile_y:
|
48 |
+
print(f"\n👤 {npc.name} ({npc.job})")
|
49 |
+
print(f" - 위치: ({x}, {y})")
|
50 |
+
print(f" - 대화: {npc.generate_dialogue()}")
|
51 |
+
|
52 |
+
# pygame 루프
|
53 |
+
runnig = True
|
54 |
+
while runnig:
|
55 |
+
screen.fill((255, 255, 255))
|
56 |
+
village.draw(screen)
|
57 |
+
draw_time()
|
58 |
+
pygame.display.update()
|
59 |
+
clock.tick(10) # 초당 10프레임
|
60 |
+
|
61 |
+
frame_count += 1
|
62 |
+
|
63 |
+
# 시간 전환
|
64 |
+
if frame_count % frame_per_time_state == 0:
|
65 |
+
current_time_index = (current_time_index + 1) % len(time_states)
|
66 |
+
print(f"\n 시간 변경: {time_states[current_time_index]}")
|
67 |
+
|
68 |
+
# NPC 이동 주기
|
69 |
+
if frame_count % 20 == 0: # 약 2초에 한 번 이동
|
70 |
+
village.update_npcs(time_states[current_time_index])
|
71 |
+
|
72 |
+
for event in pygame.event.get():
|
73 |
+
if event.type == pygame.QUIT:
|
74 |
+
runnig = False
|
75 |
+
elif event.type == pygame.MOUSEBUTTONDOWN:
|
76 |
+
handle_npc_click(pygame.mouse.get_pos())
|
77 |
+
|
78 |
+
pygame.quit()
|
79 |
+
sys.exit()
|
npc_social_network/npc/npc_base.py
ADDED
@@ -0,0 +1,32 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# portfolio/npc_social_network/maps/manager/npc/npc_base.py
|
2 |
+
# NPC 클래스 정의
|
3 |
+
class NPC:
|
4 |
+
def __init__(self, name, job, path, image):
|
5 |
+
self.name = name
|
6 |
+
self.job = job
|
7 |
+
self.path = path
|
8 |
+
self.image = image
|
9 |
+
self.current_index = 0
|
10 |
+
|
11 |
+
# 확장 가능 속성
|
12 |
+
# self.memory = [] # ex) ["유저와 대화", "곡식 수확"]
|
13 |
+
# self.emotion = "neutral"
|
14 |
+
# self.personality = {"kind": 0.5, "lazy": 0.2} # 예시
|
15 |
+
|
16 |
+
def move(self):
|
17 |
+
self.current_index = (self.current_index + 1) % len(self.path)
|
18 |
+
|
19 |
+
def get_position(self):
|
20 |
+
return self.path[self.current_index]
|
21 |
+
|
22 |
+
def draw(self, screen, tile_size):
|
23 |
+
x, y = self.get_position()
|
24 |
+
screen.blit(self.image, (x * tile_size, y * tile_size))
|
25 |
+
|
26 |
+
def generate_dialogue(self):
|
27 |
+
if self.job == "farmer":
|
28 |
+
return "오늘은 밭에 나갈 날이군요!"
|
29 |
+
elif self.job == "blacksmith":
|
30 |
+
return "망치를 들고 일할 준비가 되었어요!"
|
31 |
+
return "좋은 하루입니다."
|
32 |
+
|
npc_social_network/npc/npc_manager.py
ADDED
@@ -0,0 +1,27 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# portfolio/npc_social_network/maps/manager/npc/npc_manager.py
|
2 |
+
from .npc_base import NPC
|
3 |
+
|
4 |
+
class NPCManager:
|
5 |
+
def __init__(self):
|
6 |
+
self.npcs = []
|
7 |
+
|
8 |
+
def add(self, npc: NPC):
|
9 |
+
self.npcs.append(npc)
|
10 |
+
|
11 |
+
def move_all(self):
|
12 |
+
for npc in self.npcs:
|
13 |
+
npc.move()
|
14 |
+
|
15 |
+
def draw_all(self, screen, tile_size):
|
16 |
+
for npc in self.npcs:
|
17 |
+
npc.draw(screen, tile_size)
|
18 |
+
|
19 |
+
def get_npc_at(self, x, y):
|
20 |
+
for npc in self.npcs:
|
21 |
+
nx, ny = npc.get_position()
|
22 |
+
if nx == x and ny == y:
|
23 |
+
return npc
|
24 |
+
return None
|
25 |
+
|
26 |
+
def all(self):
|
27 |
+
return self.npcs
|
npc_social_network/static/images/tiles/{topography → terrain}/tile_dirt.png
RENAMED
File without changes
|
npc_social_network/static/images/tiles/{topography → terrain}/tile_grass.png
RENAMED
File without changes
|
npc_social_network/static/images/tiles/{topography → terrain}/tile_pool.png
RENAMED
File without changes
|
npc_social_network/static/images/tiles/{topography → terrain}/tile_stone.png
RENAMED
File without changes
|
npc_social_network/static/images/tiles/{topography → terrain}/tile_water.png
RENAMED
File without changes
|