humanda5 commited on
Commit
93a860a
·
1 Parent(s): d63937b
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