로컬 PC 이관 — git 제외 로컬 파일 보관 (manifest·.live 백업·tmp·이 PC 감사 로그) (PD 지시)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
깃 관리자 2026-10-12 11:56:06 +09:00
parent 7a7eb3accc
commit 1f810e4f84
23 changed files with 1993 additions and 0 deletions

View File

@ -0,0 +1,45 @@
# `.live/` 실시간 공유 체계 — 실무 사용 안내
> **역할 분담**: 본 README는 **실무 사용 쿡북**이며, 규칙·헌법급 정의는 [`.claude/skills/너드나비스-코어룰/SKILL.md`](../../.claude/skills/너드나비스-코어룰/SKILL.md) **C34** 단일 SOT. 본 파일은 레포 `.live/` 경로에서 junction 경유로 접근하며, 중앙 저장소는 `$HOME/.claude/nerdnavis-live/`.
## 1. `.live/` 용도
세션 중 변경된 설정·규칙·에이전트 정의·조직 기억을 **세션 갱신 없이 즉시 반영**하기 위한 PC 로컬 실시간 공유 채널. 같은 PC 내 모든 세션(worktree 경계 무관)이 자동 주입받는다.
## 2. 더미 파일 패턴
- 파일명: `{변경 대상 파일명 또는 주제}.md`
- 예: `CLAUDE.md.live`·`C34_memory_확장.md`·`pd_지시_50.md`
- 본문: 변경 요지 append-only. 최대 8,000자
## 3. 생명주기
| 시점 | 상태 | 처리 |
|------|------|------|
| 변경 발생 | PM이 `.live/{파일명}` append | 원본 수정과 동시 수행 |
| 같은 PC 다른 세션 | UserPromptSubmit hook 자동 주입 | 증분만 읽기 (토큰 비용 최소) |
| "세션 공유"·push 시점 | P21-2 트리거 | 원본 반영 확인 후 `.live/` 비움(README.md·.junction-marker 제외) + commit + push |
## 4. 세션 간 공유 시나리오
### 같은 PC 내
1. 세션 A에서 원본 수정 + `.live/` append
2. 세션 B 다음 프롬프트 → UserPromptSubmit hook `live_inject.sh` 증분 주입
3. 즉시 인지 (git 개입 없음)
### 다른 PC 간
1. 세션 A "세션 공유" (P21-2) → `.live/` 비움 + commit + push
2. 세션 B (다른 PC) "세션 갱신" (P21) → git pull → SessionStart hook 자동 복원
## 5. 참조
- **SKILL.md C34** — PC 로컬 실시간 공유 중앙화 체계 (단일 SOT, 헌법급)
- **SKILL.md C21** — 작업 완료 즉시 공유·PM 능동 확인 (내부 공유/공유 완료 2단계)
- **scripts/live_junction_ensure.sh** — junction 자동 보장 (SessionStart + UserPromptSubmit hook)
- **scripts/live_inject.sh** — UserPromptSubmit hook 증분 주입
- **scripts/live_session_load.sh** — SessionStart 전량 1회 로드
## 변경 이력
- 2026-04-19: 전 세션 초기 sentinel 손실 시 원본 소실
- 2026-04-20: #48 D 집행으로 복구. 중앙 저장소에 신규 작성 (모든 PC 자동 동기화)

View File

@ -0,0 +1,26 @@
---
plan_id: 2026-05-28_기획팀장_남은업무보고
created_at: 2026-05-28T11:40:37+09:00
hostname: DESKTOP-RD7PUKN
goal: "PD 호칭 '기획팀장' 직접 지시 — 남은 기획 업무 현황 보고 (C43 정합)"
target_files:
- 공유/PD_지시_트래킹/기획팀_PD_지시_로그.md
- 공유/대화로그/EerieVillage/2026-05-28.md
- 공유/대화로그/조직운영/2026-05-28.md
completion_criteria: "commit + push 완료 후 post-commit hook archived 이동"
---
# 매니페스트 — 2026-05-28_기획팀장_남은업무보고
- **등록 시각**: 2026-05-28T11:40:38+09:00
- **호스트**: DESKTOP-RD7PUKN
- **집행 목표**: PD 호칭 '기획팀장' 직접 지시 — 남은 기획 업무 현황 보고 (C43 정합)
## 대상 파일
- `공유/PD_지시_트래킹/기획팀_PD_지시_로그.md`
- `공유/대화로그/EerieVillage/2026-05-28.md`
- `공유/대화로그/조직운영/2026-05-28.md`
## 완료 기준
commit + push 완료. post-commit hook이 `archived/2026-05-28_기획팀장_남은업무보고.md`로 자동 이동 + target_files cross-check.

View File

@ -0,0 +1,9 @@
2026-04-24_12:54:21 pm-auditor called
2026-04-24_14:42:16 pm-auditor called
2026-04-24_14:53:53 pm-auditor called
2026-04-24_14:59:36 pm-auditor called
2026-04-24_15:11:51 pm-auditor called
2026-04-24_15:20:06 pm-auditor called
2026-04-24_15:24:52 pm-auditor called
2026-04-24_16:12:14 pm-auditor called
2026-04-24_21:19:23 pm-auditor called

View File

@ -0,0 +1,29 @@
import os, sys
sys.stdout.reconfigure(encoding='utf-8')
from pptx import Presentation
from pptx.util import Emu
src = r'C:\Users\PC\Documents\카카오톡 받은 파일\[포트폴리오] 이승우_2019_2.12.22_(구버전).pptx'
prs = Presentation(src)
print(f'슬라이드 수: {len(prs.slides)}')
print(f'크기: {Emu(prs.slide_width).inches:.2f} x {Emu(prs.slide_height).inches:.2f} inches')
print(f'aspect: {prs.slide_width / prs.slide_height:.4f}')
print()
for i, slide in enumerate(prs.slides, 1):
print(f'=== Slide {i} (Layout: {slide.slide_layout.name}) ===')
img = 0
txt_lines = []
for shape in slide.shapes:
if shape.shape_type == 13:
img += 1
if shape.has_text_frame:
for para in shape.text_frame.paragraphs:
t = para.text.strip()
if t:
txt_lines.append(t)
print(f' images={img}, text_runs={len(txt_lines)}')
for j, line in enumerate(txt_lines[:30]):
print(f' T{j+1}: {line[:200]}')
print()

View File

@ -0,0 +1,748 @@
# -*- coding: utf-8 -*-
"""
[포트폴리오] 이승우 — 16:9 와이드 현대화 PPT 빌드
- 4:3 (10x7.5) → 16:9 (13.33x7.5)
- Charcoal Minimal + Navy Accent 팔레트
- 게임 기획자 포트폴리오 톤 (전문성·정제)
"""
import os, sys
sys.stdout.reconfigure(encoding='utf-8')
from pptx import Presentation
from pptx.util import Inches, Pt, Emu
from pptx.enum.shapes import MSO_SHAPE
from pptx.dml.color import RGBColor
from pptx.enum.text import PP_ALIGN, MSO_ANCHOR
from pptx.oxml.ns import qn
from copy import deepcopy
from lxml import etree
# ─────────────── 디자인 시스템 ───────────────
COLOR_PRIMARY = RGBColor(0x1E, 0x27, 0x61) # navy (Midnight Executive)
COLOR_DARK = RGBColor(0x21, 0x29, 0x5C) # midnight
COLOR_BG_DARK = RGBColor(0x14, 0x1B, 0x42) # darker navy
COLOR_ACCENT = RGBColor(0xCA, 0xDC, 0xFC) # ice blue
COLOR_GOLD = RGBColor(0xC9, 0xA2, 0x4B) # gold accent (prestige)
COLOR_TEXT = RGBColor(0x21, 0x21, 0x21) # near black
COLOR_MUTED = RGBColor(0x6B, 0x72, 0x80) # gray
COLOR_LIGHT = RGBColor(0xF5, 0xF6, 0xFA) # light bg
COLOR_BORDER = RGBColor(0xE2, 0xE5, 0xEC) # border
COLOR_WHITE = RGBColor(0xFF, 0xFF, 0xFF)
FONT_HEADER = 'Malgun Gothic'
FONT_BODY = 'Malgun Gothic'
FONT_MONO = 'Consolas'
# 16:9 와이드 (PowerPoint 2019 표준)
SLIDE_W = Inches(13.333)
SLIDE_H = Inches(7.5)
OUT_PATH = r'C:\Users\PC\Documents\카카오톡 받은 파일\[포트폴리오] 이승우_2019_2.12.22_(현대화).pptx'
IMG_DIR = r'D:\NerdNavis\BurningTimesAi\tmp\portfolio_images'
def add_textbox(slide, left, top, width, height, text, *,
font=FONT_BODY, size=14, bold=False, italic=False,
color=COLOR_TEXT, align=PP_ALIGN.LEFT, anchor=MSO_ANCHOR.TOP,
line_spacing=1.15):
tb = slide.shapes.add_textbox(left, top, width, height)
tf = tb.text_frame
tf.margin_left = Inches(0.05)
tf.margin_right = Inches(0.05)
tf.margin_top = Inches(0.02)
tf.margin_bottom = Inches(0.02)
tf.word_wrap = True
tf.vertical_anchor = anchor
lines = text.split('\n') if isinstance(text, str) else text
for i, line in enumerate(lines):
p = tf.paragraphs[0] if i == 0 else tf.add_paragraph()
p.alignment = align
p.line_spacing = line_spacing
run = p.add_run()
run.text = line
run.font.name = font
run.font.size = Pt(size)
run.font.bold = bold
run.font.italic = italic
run.font.color.rgb = color
return tb
def add_rect(slide, left, top, width, height, fill_color, line_color=None, shadow=False):
shp = slide.shapes.add_shape(MSO_SHAPE.RECTANGLE, left, top, width, height)
shp.fill.solid()
shp.fill.fore_color.rgb = fill_color
if line_color is None:
shp.line.fill.background()
else:
shp.line.color.rgb = line_color
shp.line.width = Pt(0.5)
if not shadow:
# 그림자 제거
sp = shp.shadow
try:
sp.inherit = False
except Exception:
pass
return shp
def add_rounded(slide, left, top, width, height, fill_color, line_color=None):
shp = slide.shapes.add_shape(MSO_SHAPE.ROUNDED_RECTANGLE, left, top, width, height)
shp.adjustments[0] = 0.08
shp.fill.solid()
shp.fill.fore_color.rgb = fill_color
if line_color is None:
shp.line.fill.background()
else:
shp.line.color.rgb = line_color
shp.line.width = Pt(0.75)
return shp
def add_circle(slide, left, top, size, fill_color, line_color=None):
shp = slide.shapes.add_shape(MSO_SHAPE.OVAL, left, top, size, size)
shp.fill.solid()
shp.fill.fore_color.rgb = fill_color
if line_color is None:
shp.line.fill.background()
else:
shp.line.color.rgb = line_color
return shp
def page_header(slide, page_num, total=20, section=''):
"""우상단 페이지·섹션 표기 (간결)"""
add_textbox(slide, Inches(11.5), Inches(0.25), Inches(1.7), Inches(0.3),
f'{section} {page_num:02d} / {total:02d}',
size=9, color=COLOR_MUTED, align=PP_ALIGN.RIGHT)
def page_footer(slide):
"""좌하단 푸터 — 이름·연락"""
add_textbox(slide, Inches(0.5), Inches(7.05), Inches(8), Inches(0.3),
'Portfolio · 이승우 · Game Designer',
size=9, color=COLOR_MUTED, align=PP_ALIGN.LEFT)
# ─────────────── PPT 생성 시작 ───────────────
prs = Presentation()
prs.slide_width = SLIDE_W
prs.slide_height = SLIDE_H
blank_layout = prs.slide_layouts[6]
# ═══════════════ S1. 표지 ═══════════════
def build_slide_01():
s = prs.slides.add_slide(blank_layout)
# 풀블리드 다크 배경
add_rect(s, 0, 0, SLIDE_W, SLIDE_H, COLOR_BG_DARK)
# 좌측 navy 강조 띠 (단일 면 모티프)
add_rect(s, 0, 0, Inches(0.25), SLIDE_H, COLOR_GOLD)
# 제목군 (중앙 좌측 정렬)
add_textbox(s, Inches(1.0), Inches(2.4), Inches(8), Inches(0.5),
'PORTFOLIO',
size=14, bold=True, color=COLOR_GOLD,
font=FONT_HEADER, align=PP_ALIGN.LEFT)
add_textbox(s, Inches(1.0), Inches(2.9), Inches(11), Inches(1.3),
'포트폴리오',
size=72, bold=True, color=COLOR_WHITE,
font=FONT_HEADER, align=PP_ALIGN.LEFT)
add_textbox(s, Inches(1.0), Inches(4.4), Inches(11), Inches(0.6),
'RPG 개발 경험이 풍부한 제너럴리스트 게임 기획자',
size=22, color=COLOR_ACCENT,
font=FONT_HEADER, align=PP_ALIGN.LEFT)
# 구분선
add_rect(s, Inches(1.0), Inches(5.3), Inches(2.5), Inches(0.04), COLOR_GOLD)
# 이름·날짜
add_textbox(s, Inches(1.0), Inches(5.5), Inches(8), Inches(0.4),
'게임 기획자 · 이승우',
size=18, bold=True, color=COLOR_WHITE,
font=FONT_HEADER, align=PP_ALIGN.LEFT)
add_textbox(s, Inches(1.0), Inches(6.0), Inches(8), Inches(0.3),
'2019.12.22',
size=12, color=COLOR_ACCENT,
font=FONT_BODY, align=PP_ALIGN.LEFT)
# ═══════════════ S2. 대표 작품 인덱스 ═══════════════
def build_slide_02():
s = prs.slides.add_slide(blank_layout)
add_rect(s, 0, 0, SLIDE_W, SLIDE_H, COLOR_WHITE)
# 헤더
add_textbox(s, Inches(0.6), Inches(0.5), Inches(10), Inches(0.4),
'01 · Featured Works',
size=12, bold=True, color=COLOR_GOLD,
font=FONT_HEADER, align=PP_ALIGN.LEFT)
add_textbox(s, Inches(0.6), Inches(0.85), Inches(12), Inches(0.7),
'대표 작품 소개',
size=36, bold=True, color=COLOR_PRIMARY,
font=FONT_HEADER, align=PP_ALIGN.LEFT)
add_textbox(s, Inches(0.6), Inches(1.55), Inches(12), Inches(0.4),
'총 13개 작품 · 최근 런칭 시점 기준 정렬',
size=12, color=COLOR_MUTED,
font=FONT_BODY, align=PP_ALIGN.LEFT)
page_header(s, 2, section='WORKS INDEX')
works = [
('01', '매직 AR', '2019 · AR기반 실시간 전략 PvP'),
('02', '쿠로네코 (가제)', '캐릭터 수집 방치형 RPG · 개발 중단'),
('03', '만렙 영웅 키우기 시리즈', '2017 · 방치형 RPG · 매출 168위'),
('04', '프로젝트 BC', '하드코어 액션 MORPG · 80% 진행'),
('05', '데빌즈 아레나', '수집 성장형 MORPG · 개발 중단'),
('06', '드래곤 헌터스', '2015 · 액션 RPG · 인기 인디 선정'),
('07', '데빌즈', '2013 · 액션 RPG · 인기 무료 1위'),
('08', '동물 그림 맞추기', '2012 · 퍼즐 / 교육 어플'),
('09', '마스터 오브 던전', '2012 · 시나리오형 액션 RPG'),
('10', '최종병기 활', '2011 · 로그라이크 · 영화 OSMU'),
('11', '디스트로이어', '2010 · 액션 RPG · 넥슨 퍼블리싱'),
('12', '에프터 스쿨', '2009 · 미니게임 + 타이쿤'),
('13', '학교가는 길', '2007 · 미니게임 · SKT 킬러 콘텐츠'),
]
cols = 3
cell_w = Inches(4.0)
cell_h = Inches(0.85)
start_x = Inches(0.55)
start_y = Inches(2.2)
gap_x = Inches(0.1)
gap_y = Inches(0.12)
for i, (num, title, desc) in enumerate(works):
r, c = i // cols, i % cols
x = start_x + c * (cell_w + gap_x)
y = start_y + r * (cell_h + gap_y)
# 카드
card = add_rounded(s, x, y, cell_w, cell_h, COLOR_LIGHT, COLOR_BORDER)
# 좌측 번호 박스 (navy)
add_rect(s, x + Inches(0.0), y, Inches(0.6), cell_h, COLOR_PRIMARY)
add_textbox(s, x, y, Inches(0.6), cell_h,
num, size=18, bold=True, color=COLOR_WHITE,
font=FONT_HEADER, align=PP_ALIGN.CENTER, anchor=MSO_ANCHOR.MIDDLE)
# 제목
add_textbox(s, x + Inches(0.75), y + Inches(0.1), cell_w - Inches(0.85), Inches(0.35),
title, size=13, bold=True, color=COLOR_TEXT,
font=FONT_HEADER, align=PP_ALIGN.LEFT)
# 부제
add_textbox(s, x + Inches(0.75), y + Inches(0.42), cell_w - Inches(0.85), Inches(0.4),
desc, size=9.5, color=COLOR_MUTED,
font=FONT_BODY, align=PP_ALIGN.LEFT)
page_footer(s)
# ═══════════════ S3~S15. 게임 소개 슬라이드 (공통 레이아웃) ═══════════════
GAMES = [
# (페이지번호 in deck, 작품번호, title, subtitle, info_dict, overview_lines, role_text, kpi_text, image_filename)
(3, '01', '매직 AR', 'AR 기반의 전략 PvP 게임',
{'장르': 'AR기반 실시간 전략 PvP', '플랫폼': 'Android, iOS', '출시일': '2019. 09'},
[
'증강현실(AR)과 딥 러닝 기술을 활용해 음료수 캔 등 사물을 스캔하여 실제 게임에서 활용할 수 있는 새로운 개념의 게임.',
'클래시 로얄과 유사한 실시간 전략 PvP. 어떤 사물을 스캔하는지에 따라 다양한 변수가 발생되는 것이 특징.',
'신 기술 기반 투자 유치 목적의 프로젝트로, 게임성 개선 및 폴리싱 후 소프트 런칭 버전 대응 완료.',
'※ 개발부·사업부 간 게임에 대한 이해도 차이와 경영 사정 악화로 인해 퇴사 결정.',
],
'전투 밸런스 작업 · 게임 폴리싱 · 아이템 보상 시스템(상자·전투 보상) 등',
None,
'slide03_img10.jpg'),
(4, '02', '쿠로네코 (가제)', 'IP 활용 방치형 게임',
{'장르': '캐릭터 수집 방치형 RPG', '플랫폼': 'Android', '출시일': '개발 중단'},
[
'대만에서 흥행한 이노센트 IP를 활용한 캐릭터 수집·성장 방치형 RPG 프로젝트.',
'200여 종의 개성 있는 캐릭터 리소스를 활용해 수집·성장의 재미를 제공.',
'탱커/원딜/근딜러/서포터로 구성, 캐릭터마다 다양한 컨셉의 스킬로 전략적 덱 조합 가능.',
'원작 리소스를 활용해 개발기간을 단축, 캐릭터 가챠 BM으로 매출 극대화 구상.',
'※ 개발 진척 60% 달성 후 핵심 개발자 퇴사 및 내부 사정으로 개발 중단.',
],
'프로젝트 디렉팅(PD) · 핵심 시스템 기획 · UI&UX 컨셉팅 등 기획 실무 일체',
None,
'slide04_img13.png'),
(5, '03', '만렙 영웅 키우기 시리즈', '전사편 · 소환사편 · 마검사편',
{'장르': 'RPG / 방치형', '플랫폼': 'Android, iOS', '출시일': '2017. 04'},
[
'반복적인 자동 전투로 재화를 수집하고, 무한 환생을 통해 끊임없이 성장하는 방치형 RPG.',
'코어 RPG의 감성을 살린 아이템·스킬 시스템으로 기존 방치형 게임과의 차별화 어필.',
'총 개발기간 약 4개월. 전사편 지표 분석을 통해 의미 있는 성과 달성.',
'결투장·쟁탈전·랭킹 시스템 등 다양한 경쟁 컨텐츠로 유저 몰입 유도.',
],
'프로젝트 디렉팅(PD) · 기획 실무 일체',
'KPI: ARPPU ₩45,553 · Retention 36.7% (1Day) · 최고 매출 168위 · Featured 2017/05',
'slide05_img14.png'),
(6, '04', '프로젝트 BC', '푸른 별의 노래 (가제)',
{'장르': '하드코어 액션 MORPG', '플랫폼': 'Android', '출시일': '개발 중단'},
[
'화려한 2D 그래픽과 액션 RPG의 진수를 느낄 수 있는 하드코어 감성의 2D MORPG.',
'전사·마검사·소환사 3명의 캐릭터가 멀티 시나리오로 제공되며 각기 다른 플레이 스타일 보유.',
'유저간 PvP, RvR 형태의 길드 대전 및 약탈 시스템으로 경쟁 유도.',
'코스튬·펫·용병 시스템을 통해 캐릭터 성장 외에도 풍부한 즐길거리 제공.',
'※ 핵심 시스템 및 컨텐츠 80% 완성, 경영 악화로 인해 일시 중단.',
],
'핵심 시스템 및 컨텐츠 기획 · 몬스터 & 캐릭터 전투 시스템 관련 기획',
None,
None),
(7, '05', '데빌즈 아레나', '자사 IP 활용 액션 MORPG',
{'장르': '수집 성장형 MORPG', '플랫폼': 'Android', '출시일': '개발 중단'},
[
'데빌즈·마스터오브 던전 인기 캐릭터 + 오리지널 30여 종을 활용한 캐릭터 수집·성장 MORPG.',
'실시간 PvP를 비롯한 다양한 경쟁형 컨텐츠 제공.',
'캐릭터간 상성과 플레이 스타일이 다양해 수집·조작의 재미를 모두 추구.',
'※ 정부 지원사업과 연계해 70% 개발 진행, 개발기간 대비 수익성 부족으로 잠정 드랍.',
],
'프로젝트 디렉팅(PD) · 기획 실무 일체',
None,
None),
(8, '06', '드래곤 헌터스', '캐주얼 액션 RPG',
{'장르': '액션 RPG', '플랫폼': 'N스토어 / 원스토어 / GP2X', '출시일': '2015. 02'},
[
'피쳐폰 시절 이통 3사 25만 다운로드 이상을 기록하며 재미 검증을 받은 캐주얼 ARPG.',
'다이나믹한 콤보 액션과 필드 기믹으로 조작감에 대한 호평을 받음.',
'아이템 파밍·스킬 트리 구성으로 캐릭터 성장의 묘미 제공.',
'스마트폰 버전 리뉴얼 출시, 무리한 BM 적용으로 성과는 저조.',
],
'프로젝트 디렉팅(PD) · 기획 실무 일체',
'Featured: 인기 인디 게임 선정 (15/03)',
None),
(9, '07', '데빌즈', '몰입형 싱글 액션 RPG',
{'장르': '액션 RPG', '플랫폼': 'Android, iOS · 컴투스 퍼블리싱', '출시일': '2013. 10'},
[
'아이템 옵션 조합 파밍의 재미와 시나리오 기반 싱글 액션 RPG.',
'4명의 캐릭터가 각자 시점으로 진행되는 멀티 시나리오로 정통 RPG의 색다른 경험 제공.',
'다양한 옵션·등급 아이템과 스텟 포인트 투자로 성장 방법 다양화.',
'노말/하드/헬 난이도 + 최대 레벨 999로 장기 콘텐츠 제공, 보스 레이드·무한의 던전 등 다양한 싱글 컨텐츠 운영.',
'아이템 위주 BM을 통해 수년간 안정적 수익 창출.',
],
'핵심 시스템·컨텐츠 기획 · 기획 실무 일체 (맵 & 레벨 디자인 제외)',
'Featured: 인기 무료 게임 1위 (2013/11)',
None),
(10, '08', '동물 그림 맞추기', '유아 교육용 어플리케이션',
{'장르': '퍼즐 / 교육', '플랫폼': 'Android', '출시일': '2012. 09'},
[
'캐시카우 확보 및 기획팀 유니티 엔진 학습을 위한 단기 개발 프로젝트.',
'귀엽고 깔끔한 그래픽과 직관적인 게임 방법, 유아 교육용 어플리케이션으로 출시.',
'자사 게임 라인업 다양화 및 지속적 수익 타이틀 실험의 대표 케이스.',
'※ 총 인원 3명, 개발 기간 약 2.5주의 초단기 프로젝트.',
],
'아트 컨셉 · UI&UX 설계 · UI 프리펩 배치 등 실무',
None,
None),
(11, '09', '마스터 오브 던전', '시나리오형 액션 RPG',
{'장르': '액션 RPG', '플랫폼': 'Android', '출시일': '2012. 07'},
[
'디스트로이어의 개발 노하우와 엔진을 활용해 제작된 싱글 기반 시나리오형 액션 RPG.',
'짜임새 있는 시나리오와 퀘스트 이벤트로 엔딩까지의 과정을 풍성하게 구성.',
'캐릭터 육성 방식에 따라 특성이 부여되는 정통 RPG 표방.',
'몰이사냥과 다양한 옵션 아이템으로 장비 세팅·파밍의 재미 강조.',
'인앱 과금 시장으로의 전환기에서 다양한 BM 실험을 시도한 프로젝트.',
],
'아이템 및 전투 시스템 기획 · 시나리오 스크립트 작업 일체',
None,
'slide11_img11.jpg'),
(12, '10', '최종병기 활', '영화 OSMU 로그라이크',
{'장르': '로그라이크', '플랫폼': 'Android', '출시일': '2011. 09'},
[
'영화 「최종병기 활」 홍보를 위한 원소스 멀티유즈 전략 프로젝트.',
'영화 개봉 시점에 맞춰 출시하기 위해 로그라이크를 변형한 캐주얼 RPG로 기획.',
'영화 시나리오 플롯을 계승하되 게임만의 오리지날 요소를 가미해 색다른 재미 제공.',
'재화 수집 → 무기·방어구 성장 구조, 타이밍 조작감 강조.',
'※ 촉박한 일정과 단말기 커버리지 한계로 흥행에는 실패.',
],
'핵심 시스템 및 컨텐츠 기획 · 시나리오 스크립트 작업 등 기획 실무 일체',
None,
'slide12_img10.png'),
(13, '11', '디스트로이어', '대작 액션 RPG',
{'장르': '액션 RPG', '플랫폼': 'SKT / Android · 넥슨 모바일 퍼블리싱', '출시일': '2010. 09'},
[
'드래곤 헌터의 성공과 개발력을 검증받아 넥슨과 퍼블리싱 계약이 체결된 대작 액션 프로젝트.',
'당시 모바일 최초로 4명의 캐릭터가 각각의 시점으로 진행되는 멀티 시나리오 제공.',
'거대 보스 레이드, 실시간 PvP 등 방대한 컨텐츠와 풍부한 즐길거리로 플레이타임 확보.',
'영웅 서기를 능가하는 대작 RPG를 목표로 했으나, 개발기간 오버 및 피쳐폰→스마트폰 시장 급변기 직격.',
'터치 조작 미지원으로 흥행에는 실패한 비운의 프로젝트.',
],
'핵심 시스템 및 컨텐츠 기획 · 시나리오 스크립트 작업 등 기획 실무 일체',
None,
None),
(14, '12', '에프터 스쿨', '미니게임 + 타이쿤 복합',
{'장르': '미니게임', '플랫폼': 'SKT', '출시일': '2009. 06'},
[
'학교가는길 시리즈의 성공에 힘입어 독특하고 기발한 컨셉으로 제안·개발한 프로젝트.',
'미니게임과 타이쿤 장르를 믹스해 엄마 파트·아들 파트를 나눠 다양한 할 거리 제공.',
'초기 60~70% 개발 단계에서 ARPG(드래곤헌터) 메인 기획 담당을 위해 인수인계.',
'※ 신입 인력 인수 이후 타이쿤 장르 소화 부족으로 미니게임 장르 전환, 게임성 모호로 흥행 실패.',
],
'컨셉 기획 · 타이쿤 & 미니게임 초기 기획 담당',
None,
None),
(15, '13', '학교가는 길', 'SKT 킬러 콘텐츠',
{'장르': '미니게임', '플랫폼': 'Android', '출시일': '2007. 05'},
[
'SKT 킬러 컨텐츠로 선정되며 흥행에 성공한 최초의 프로젝트. 시리즈화에 성공해 3편까지 출시.',
'학교가는 길을 미니게임화한 독특한 컨셉과 개성 있는 디자인 연출로 피쳐폰 시절 높은 다운로드 수익 창출.',
'10여 종의 미니게임으로 구성. 각 미니게임은 외주 개발업체를 통해 진행.',
'초기 개발 단계부터 참여해 미니게임 전체 세부 기획·밸런싱·아트 컨셉 담당.',
'※ 퍼블리셔와의 수익 배분·라이선스 지분 이슈로 후속작은 타 업체 진행.',
],
'컨셉 기획 · 미니게임 8종 시스템 기획 · 외주 개발 업체 관리 등 실무 전반',
None,
None),
]
def build_game_slide(page, num, title, subtitle, info, overviews, role, kpi, img_file):
s = prs.slides.add_slide(blank_layout)
add_rect(s, 0, 0, SLIDE_W, SLIDE_H, COLOR_WHITE)
# 좌측 다크 사이드바 (게임 정보 카드)
SIDEBAR_W = Inches(4.2)
add_rect(s, 0, 0, SIDEBAR_W, SLIDE_H, COLOR_BG_DARK)
# 좌측 navy 강조 띠
add_rect(s, 0, 0, Inches(0.18), SLIDE_H, COLOR_GOLD)
# 사이드바 — 작품 번호
add_textbox(s, Inches(0.5), Inches(0.5), Inches(3.5), Inches(0.4),
f'WORK · {num}',
size=11, bold=True, color=COLOR_GOLD,
font=FONT_HEADER, align=PP_ALIGN.LEFT)
# 사이드바 — 게임명
add_textbox(s, Inches(0.5), Inches(0.95), Inches(3.5), Inches(1.0),
title, size=26, bold=True, color=COLOR_WHITE,
font=FONT_HEADER, align=PP_ALIGN.LEFT, line_spacing=1.1)
add_textbox(s, Inches(0.5), Inches(2.0), Inches(3.5), Inches(0.7),
subtitle, size=12, color=COLOR_ACCENT,
font=FONT_BODY, align=PP_ALIGN.LEFT, italic=True, line_spacing=1.3)
# 구분선
add_rect(s, Inches(0.5), Inches(2.95), Inches(0.6), Inches(0.025), COLOR_GOLD)
# 사이드바 — 게임 정보 표
y = Inches(3.15)
for label, value in info.items():
add_textbox(s, Inches(0.5), y, Inches(3.5), Inches(0.25),
label.upper(),
size=9, bold=True, color=COLOR_GOLD,
font=FONT_HEADER, align=PP_ALIGN.LEFT)
add_textbox(s, Inches(0.5), y + Inches(0.25), Inches(3.5), Inches(0.35),
value,
size=12, color=COLOR_WHITE,
font=FONT_BODY, align=PP_ALIGN.LEFT)
y += Inches(0.72)
# 사이드바 — 이미지 (있다면 하단)
if img_file:
img_path = os.path.join(IMG_DIR, img_file)
if os.path.exists(img_path):
try:
# 이미지 사이즈 측정 후 비율 유지
from PIL import Image
with Image.open(img_path) as pim:
iw, ih = pim.size
# 너비 3.3", 위치 사이드바 하단
max_w_in = 3.3
max_h_in = 1.4
ratio_img = iw / ih
ratio_box = max_w_in / max_h_in
if ratio_img >= ratio_box:
target_w = max_w_in
target_h = max_w_in / ratio_img
else:
target_h = max_h_in
target_w = max_h_in * ratio_img
ix = Inches((4.2 - target_w) / 2)
iy = Inches(5.95 - target_h / 2)
s.shapes.add_picture(img_path, ix, iy, Inches(target_w), Inches(target_h))
except Exception as e:
print(f' image warn: {e}')
# 우측 컨텐츠 영역
CONTENT_X = Inches(4.7)
# 상단 페이지 표기
add_textbox(s, Inches(11.5), Inches(0.5), Inches(1.7), Inches(0.3),
f'WORKS · {page:02d} / 20',
size=9, color=COLOR_MUTED, align=PP_ALIGN.RIGHT,
font=FONT_BODY)
# 우측 — 섹션 라벨
add_textbox(s, CONTENT_X, Inches(0.55), Inches(8), Inches(0.4),
'GAME OVERVIEW',
size=11, bold=True, color=COLOR_PRIMARY,
font=FONT_HEADER, align=PP_ALIGN.LEFT)
add_rect(s, CONTENT_X, Inches(0.95), Inches(0.6), Inches(0.04), COLOR_PRIMARY)
# 우측 — 게임 개요 (불릿형 단락)
y = Inches(1.15)
for line in overviews:
# 불릿 마커
dot = add_circle(s, CONTENT_X, y + Inches(0.12), Inches(0.08), COLOR_GOLD)
add_textbox(s, CONTENT_X + Inches(0.2), y, Inches(8.3), Inches(0.6),
line, size=11.5, color=COLOR_TEXT,
font=FONT_BODY, align=PP_ALIGN.LEFT, line_spacing=1.3)
# 라인 수에 따른 동적 간격
est_lines = max(1, (len(line) // 50) + 1)
y += Inches(0.34 + 0.22 * (est_lines - 1))
if y > Inches(5.3):
break
# 우측 — 담당 업무 박스
role_y = Inches(5.6)
add_rect(s, CONTENT_X, role_y, Inches(8.4), Inches(0.85), COLOR_LIGHT)
add_rect(s, CONTENT_X, role_y, Inches(0.1), Inches(0.85), COLOR_PRIMARY)
add_textbox(s, CONTENT_X + Inches(0.25), role_y + Inches(0.08), Inches(8), Inches(0.3),
'MY ROLE',
size=10, bold=True, color=COLOR_PRIMARY,
font=FONT_HEADER, align=PP_ALIGN.LEFT)
add_textbox(s, CONTENT_X + Inches(0.25), role_y + Inches(0.36), Inches(8), Inches(0.5),
role, size=11, color=COLOR_TEXT,
font=FONT_BODY, align=PP_ALIGN.LEFT)
# KPI / Featured 박스 (있을 경우)
if kpi:
kpi_y = Inches(6.6)
add_rect(s, CONTENT_X, kpi_y, Inches(8.4), Inches(0.6), COLOR_PRIMARY)
add_textbox(s, CONTENT_X + Inches(0.25), kpi_y + Inches(0.1), Inches(8), Inches(0.4),
'KPI / FEATURED',
size=9, bold=True, color=COLOR_GOLD,
font=FONT_HEADER, align=PP_ALIGN.LEFT)
add_textbox(s, CONTENT_X + Inches(0.25), kpi_y + Inches(0.3), Inches(8), Inches(0.4),
kpi, size=10.5, color=COLOR_WHITE,
font=FONT_BODY, align=PP_ALIGN.LEFT)
# 푸터
add_textbox(s, Inches(4.7), Inches(7.15), Inches(8), Inches(0.25),
'이승우 · Game Designer · Portfolio',
size=8, color=COLOR_MUTED, align=PP_ALIGN.LEFT,
font=FONT_BODY)
# ═══════════════ S16. 경력 개요 ═══════════════
def build_slide_16():
s = prs.slides.add_slide(blank_layout)
add_rect(s, 0, 0, SLIDE_W, SLIDE_H, COLOR_WHITE)
add_textbox(s, Inches(0.6), Inches(0.5), Inches(10), Inches(0.4),
'02 · Career Summary',
size=12, bold=True, color=COLOR_GOLD,
font=FONT_HEADER, align=PP_ALIGN.LEFT)
add_textbox(s, Inches(0.6), Inches(0.85), Inches(12), Inches(0.7),
'경력 개요',
size=36, bold=True, color=COLOR_PRIMARY,
font=FONT_HEADER, align=PP_ALIGN.LEFT)
add_textbox(s, Inches(0.6), Inches(1.55), Inches(12), Inches(0.4),
'총 경력 13년 2개월 · 다수의 메인 기획 및 디렉터 경험',
size=12, color=COLOR_MUTED,
font=FONT_BODY, align=PP_ALIGN.LEFT)
page_header(s, 16, section='CAREER')
# 큰 KPI 박스
add_rect(s, Inches(0.6), Inches(2.25), Inches(3.9), Inches(1.4), COLOR_BG_DARK)
add_rect(s, Inches(0.6), Inches(2.25), Inches(0.15), Inches(1.4), COLOR_GOLD)
add_textbox(s, Inches(0.85), Inches(2.4), Inches(3.5), Inches(0.4),
'TOTAL EXPERIENCE',
size=11, bold=True, color=COLOR_GOLD,
font=FONT_HEADER, align=PP_ALIGN.LEFT)
add_textbox(s, Inches(0.85), Inches(2.75), Inches(3.5), Inches(0.9),
'13년 2개월',
size=42, bold=True, color=COLOR_WHITE,
font=FONT_HEADER, align=PP_ALIGN.LEFT)
add_textbox(s, Inches(0.85), Inches(3.32), Inches(3.5), Inches(0.3),
'Game Designer · PD · PM',
size=11, color=COLOR_ACCENT,
font=FONT_BODY, italic=True, align=PP_ALIGN.LEFT)
# 우측 — 핵심 강점 그리드 (2 columns × 5 rows)
strengths = [
('PROJECT LEADING', '다수의 프로젝트에서 메인 기획 및 디렉터로 리딩 경험'),
('PROVEN HITS', '만렙 영웅 키우기, 데빌즈, 마스터 오브 던전, 드래곤 헌터, 학교가는 길'),
('GLOBAL SERVICE', '미국·중국·일본 등 글로벌 서비스 대응 경험 (데빌즈 외)'),
('MULTI-PLATFORM', 'NDS · GP2X · AR · 콘솔 / 모바일 등 다양한 플랫폼 실무'),
('LIVE OPERATIONS', '라이브 게임 운영 및 서비스 다수 보유'),
('PROACTIVE', '주도적인 프로젝트 제안·추진 (방치형·IP 활용 등)'),
('MULTI-ROLE', 'PD · PM · QA · 외주 개발 관리 등 다양한 포지션 이해'),
('NARRATIVE', '게임 시나리오 작성 및 스크립트 작업 (멀티 시나리오 포함)'),
('TOOLS', '스파인 · 협업 툴 · 발사믹 목업 · 마인드맵 등 효율적 활용'),
('BM DESIGN', '게임 통찰력·서비스 경험 기반 핵심 BM 설계 및 리뉴얼 주도'),
]
col_x = [Inches(4.85), Inches(9.05)]
cell_w = Inches(4.05)
cell_h = Inches(0.85)
start_y = Inches(2.25)
for i, (label, desc) in enumerate(strengths):
col = i % 2
row = i // 2
x = col_x[col]
y = start_y + row * (cell_h + Inches(0.1))
# 카드
card = add_rounded(s, x, y, cell_w, cell_h, COLOR_LIGHT, COLOR_BORDER)
# 좌측 아이콘 원 (gold) + 번호
add_circle(s, x + Inches(0.15), y + Inches(0.2), Inches(0.45), COLOR_PRIMARY)
add_textbox(s, x + Inches(0.15), y + Inches(0.2), Inches(0.45), Inches(0.45),
f'{i+1:02d}', size=10, bold=True, color=COLOR_GOLD,
font=FONT_HEADER, align=PP_ALIGN.CENTER, anchor=MSO_ANCHOR.MIDDLE)
# 라벨
add_textbox(s, x + Inches(0.7), y + Inches(0.12), cell_w - Inches(0.8), Inches(0.3),
label, size=10, bold=True, color=COLOR_PRIMARY,
font=FONT_HEADER, align=PP_ALIGN.LEFT)
# 본문
add_textbox(s, x + Inches(0.7), y + Inches(0.4), cell_w - Inches(0.8), Inches(0.45),
desc, size=10, color=COLOR_TEXT,
font=FONT_BODY, align=PP_ALIGN.LEFT, line_spacing=1.2)
# 하단 — 마지막 1 항목 (소규모 ~ 중형 조직 경험)
bottom_y = Inches(7.0)
add_textbox(s, Inches(0.6), bottom_y, Inches(12.2), Inches(0.3),
'★ 소규모 스타트업부터 중형급 이상의 개발 조직까지 다양한 실무 경험 보유',
size=11, bold=True, color=COLOR_PRIMARY,
font=FONT_HEADER, align=PP_ALIGN.LEFT)
page_footer(s)
# ═══════════════ S17·18·19. 영상 URL ═══════════════
def build_video_links_slide(page_num, section_title, items):
"""items: [(title, url, desc), ...]"""
s = prs.slides.add_slide(blank_layout)
add_rect(s, 0, 0, SLIDE_W, SLIDE_H, COLOR_WHITE)
add_textbox(s, Inches(0.6), Inches(0.5), Inches(10), Inches(0.4),
'03 · Reference Videos',
size=12, bold=True, color=COLOR_GOLD,
font=FONT_HEADER, align=PP_ALIGN.LEFT)
add_textbox(s, Inches(0.6), Inches(0.85), Inches(12), Inches(0.7),
section_title,
size=36, bold=True, color=COLOR_PRIMARY,
font=FONT_HEADER, align=PP_ALIGN.LEFT)
add_textbox(s, Inches(0.6), Inches(1.55), Inches(12), Inches(0.4),
'포트폴리오 참고 영상 / 다운로드 URL',
size=12, color=COLOR_MUTED,
font=FONT_BODY, align=PP_ALIGN.LEFT)
page_header(s, page_num, section='VIDEOS')
y = Inches(2.3)
for title, url, desc in items:
# 카드
add_rounded(s, Inches(0.6), y, Inches(12.15), Inches(1.3), COLOR_LIGHT, COLOR_BORDER)
# 좌측 navy 띠
add_rect(s, Inches(0.6), y, Inches(0.15), Inches(1.3), COLOR_PRIMARY)
# 제목
add_textbox(s, Inches(0.9), y + Inches(0.15), Inches(11.5), Inches(0.4),
title, size=15, bold=True, color=COLOR_PRIMARY,
font=FONT_HEADER, align=PP_ALIGN.LEFT)
# URL
add_textbox(s, Inches(0.9), y + Inches(0.55), Inches(11.5), Inches(0.35),
url, size=10.5, color=COLOR_GOLD,
font=FONT_MONO, align=PP_ALIGN.LEFT)
# 설명
if desc:
add_textbox(s, Inches(0.9), y + Inches(0.92), Inches(11.5), Inches(0.35),
desc, size=10, color=COLOR_MUTED,
font=FONT_BODY, italic=True, align=PP_ALIGN.LEFT)
y += Inches(1.5)
if y > Inches(6.5):
break
page_footer(s)
# ═══════════════ S20. 마무리·다운로드 ═══════════════
def build_slide_20():
s = prs.slides.add_slide(blank_layout)
add_rect(s, 0, 0, SLIDE_W, SLIDE_H, COLOR_BG_DARK)
# 좌측 띠
add_rect(s, 0, 0, Inches(0.25), SLIDE_H, COLOR_GOLD)
add_textbox(s, Inches(1.0), Inches(1.2), Inches(10), Inches(0.5),
'04 · Work Outputs',
size=14, bold=True, color=COLOR_GOLD,
font=FONT_HEADER, align=PP_ALIGN.LEFT)
add_textbox(s, Inches(1.0), Inches(1.7), Inches(11), Inches(1.0),
'실무 작업 결과물',
size=48, bold=True, color=COLOR_WHITE,
font=FONT_HEADER, align=PP_ALIGN.LEFT)
add_textbox(s, Inches(1.0), Inches(2.85), Inches(11), Inches(0.5),
'포트폴리오 다운로드 URL',
size=18, color=COLOR_ACCENT,
font=FONT_BODY, align=PP_ALIGN.LEFT, italic=True)
# 다운로드 카드 (예시 — 원본에 URL 텍스트 단편만 존재)
add_rect(s, Inches(1.0), Inches(3.8), Inches(11.3), Inches(0.04), COLOR_GOLD)
download_items = [
('GAME DESIGN DOCUMENTS',
'기획서 · 시스템 설계 · 밸런스 표 등 실무 작업 결과물 모음'),
('UI / UX MOCKUPS',
'발사믹·스파인·기타 목업 툴을 활용한 화면 설계'),
('SCRIPTS & SCENARIOS',
'게임 시나리오 · 멀티 시나리오 스크립트'),
]
y = Inches(4.2)
for label, desc in download_items:
add_rect(s, Inches(1.0), y, Inches(0.05), Inches(0.7), COLOR_GOLD)
add_textbox(s, Inches(1.2), y + Inches(0.05), Inches(11), Inches(0.35),
label, size=13, bold=True, color=COLOR_WHITE,
font=FONT_HEADER, align=PP_ALIGN.LEFT)
add_textbox(s, Inches(1.2), y + Inches(0.35), Inches(11), Inches(0.3),
desc, size=11, color=COLOR_ACCENT,
font=FONT_BODY, align=PP_ALIGN.LEFT, italic=True)
y += Inches(0.85)
# 푸터
add_textbox(s, Inches(1.0), Inches(6.7), Inches(11), Inches(0.4),
'THANK YOU',
size=22, bold=True, color=COLOR_GOLD,
font=FONT_HEADER, align=PP_ALIGN.LEFT)
add_textbox(s, Inches(1.0), Inches(7.1), Inches(11), Inches(0.3),
'Lee Seung-Woo · Game Designer · 2019.12.22',
size=11, color=COLOR_ACCENT,
font=FONT_BODY, align=PP_ALIGN.LEFT)
# ─────────────── 빌드 실행 ───────────────
print('Building slides...')
build_slide_01(); print(' S1 표지')
build_slide_02(); print(' S2 인덱스')
for game in GAMES:
page, num, title, subtitle, info, overviews, role, kpi, img_file = game
build_game_slide(page, num, title, subtitle, info, overviews, role, kpi, img_file)
print(f' S{page} {title}')
build_slide_16(); print(' S16 경력')
videos_p17 = [
('데빌즈',
'https://youtu.be/GZNZvpsk5WE',
'컴투스 퍼블리싱 · 인기 무료 게임 1위 (2013/11) · 액션 RPG 플레이 영상'),
('프로젝트 BC (2014)',
'https://youtu.be/maMV-lcPB3I',
'하드코어 액션 MORPG · 2D 그래픽과 멀티 시나리오 시연'),
('Spine 2D 작업 시연',
'—',
'캐릭터 애니메이션 작업 영상 (Spine 활용)'),
]
build_video_links_slide(17, 'Reference Videos · 1', videos_p17); print(' S17 영상1')
videos_p18 = [
('드래곤 헌터스',
'https://drive.google.com/open?id=1tUkQ_bOwRrx3Y4LARqRX4KFGi5vXUocv',
'GP2X · HD 버전 플레이 영상'),
('마스터 오브 던전',
'https://youtu.be/9ipP9KkBZxI',
'시나리오형 액션 RPG 플레이 영상'),
]
build_video_links_slide(18, 'Reference Videos · 2', videos_p18); print(' S18 영상2')
videos_p19 = [
('쿠로네코 프로젝트',
'https://drive.google.com/open?id=1poqqti2raZw_rosy3RJlVQNctPmEeE2P',
'개발이 상당부분 완료된 상태에서 중도 드랍된 쿠로네코 프로젝트 시연 영상'),
('학교가는 길 1',
'https://youtu.be/XMWlcZyJYSg',
'조이모아 퍼블리싱 · 학교가는 길 플레이 영상'),
]
build_video_links_slide(19, 'Reference Videos · 3', videos_p19); print(' S19 영상3')
build_slide_20(); print(' S20 마무리')
prs.save(OUT_PATH)
print(f'\n✅ Saved: {OUT_PATH}')
print(f' Size: {os.path.getsize(OUT_PATH):,} bytes')
print(f' Slides: {len(prs.slides)}')

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 150 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 477 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 848 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 862 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 848 B