크래프톤 정글 TIL : 1011

lazyArtisan·2024년 10월 11일
0

정글 TIL

목록 보기
103/147

👾 나만무


애셋 찾아놓기

팀에서 맡은 과제

차원종류이름주소
2UI캐주얼 아이콘 팩링크
2Character후드 쓴 캐릭터링크
2UI고전게임 느낌 체력바링크
2UI픽셀 아트 UI링크
2Effect불타는 이펙트링크
2Tileset따뜻한 느낌 숲 타일셋링크
-Audio양키 목소리 오디오팩링크
2Tileset연구소 타일셋링크
2UI어플 아이콘 팩링크
2Background우주 픽셀 배경화면링크
3Character복셀 로봇 캐릭터링크
3Objects로우 폴리 나무, 바위링크
3Animation캐릭터 애니메이션 모음링크
3Tileset로우폴리 타일셋링크
3Tileset계절별 로우폴리 나무, 풀, 바위링크
2UI깔끔한 캐주얼 UI링크
2Objects포션 모음링크
-AudioRPG BGM링크
3Objects로우폴리 차 모음링크
2Character수인 캐릭터들링크
2Background우주, 지구, 소행성 배경링크
-Audio미니 게임 BGM링크
2Effect픽셀 스킬 이펙트링크
3Background하늘 배경링크
2Effect피 효과링크
3Asset Pack로우폴리 RPG 애셋팩링크
3Objects나무링크
2Asset Pack도시 애셋 팩 (8방향)링크
2Character중세 사람들링크
2Tileset미래풍 타일셋링크
3Asset Pack로우폴리 창고링크
2Effect말풍선 효과링크
3Objects미래 느낌 총링크
3Character복셀 디스토피아 캐릭터링크
3Asset Pack드론 경주 맵링크
3Objects로우폴리 식물, 버섯, 바위링크
3Asset Pack로우폴리 던전 애셋팩링크
2Asset Pack중세 마을 애셋팩링크

러프한 아이디어 제안

공포 게임 : 공포 잘 느끼는 사람들에게 잘 먹힐 것. 감정을 가장 쉽고 강렬하게 이끌어내는 데에는 공포만한게 없다. 근데 단순히 갑툭튀 원툴이 아니라 공포에 또 뭔가를 추가해야 됨. 근데 공포는 뭔가를 추가하면 할 수록 공포에서 멀어짐. 그냥 어두운 곳에서 우- 하고 쫓아오는 괴물이 무서운거. 연출을 얼마나 실감나게 하는지가 무서운거. 총같은거라도 들려줬다간 공포감 다 날아감. 그때부턴 그냥 슈팅게임 되는거. 에일리언:아이솔레이션 느낌을 멀티로? 공포게임 스킨 씌운 술래잡기 아님? 술래가 좀 많이 세고 나머지는 도망만 다녀야 하는 데바데? 기획적으로는 AI가 아니라 진짜 사람이 들어가니까 서로에게 전달하는 정보(발소리) 등을 어떻게 조절할 건지, 그걸 어떻게 공포심을 조장할 건지에 대해 생각해볼만한 여지가 있겠지만, 개발적 난이도는 전혀 올라가지 않음. 서버 추가하고 움직임만 구현하면 끝. 공포를 해치지 않으면서, 게임적으로 재미있으면서, 보여주는게 재미있으면서, 개발적 난이도가 있는 어떤 기믹을 추가해야 함. ㅇㅇ 불가능. 공포를 해치지 않는게 제일 불가능.

쫓는 사람은 점프로, 도망가는 사람은 로프 액션으로 답답한 통로를 지나감.
근데 쫓기는 사람이 빠져서 죽어버리면 팍 식을 것 같긴 한데? <- 어차피 죽는거 안 보여주면 괜찮을수도
아트 느낌 : Lorn's Lure

메이드 인 와리오, 미니게임천국 : 끊임없는 새로움. 폴가이즈처럼 탈락시키는 걸 1분에 1명씩 하면?

시연(시청)의 재미 요소 : 플레이 하는 사람이 잘 해야됨(스피드런 하는 사람들이나 리듬 게임 잘 하는 사람들 느낌. fps로 장우형 내세워서 도파민 주작?), 아트가 예뻐야됨, 로직이 새로워야(참신해야) 됨.

왜 이 게임을 하고 싶냐?가 아닌 왜 이 게임을 보고 싶냐? 가 돼야 하는 어이 없는 개발 목적. (근데 그러면서도 플레이가 재미는 있어야 됨)
조금 더 현실과 비타협 하자면, 왜 이 게임이 재미있어 보이냐? 왜 이 게임이 완성됐을 때가 기대되냐? 가 목적.

시연할 때 재미있는 것과 직접할 때 재미있는 게임의 차이점 : 일단 직접 플레이를 못하므로 몰입도가 떨어짐. 직접할 때 무엇을 느끼는지에 대한 정보의 쾌감을 느낄 수 없음. (그 순간에 무슨 판단을 했는지 말해주는 걸로는 도파민이 생기지 않음. 태어나서 그 게임을 처음 본 거니까. 와! 방금 거기서 리 신이 상대가 아래쪽이라는 걸 인지하고 3캠 카정을 친 후에 cs 빅 웨이브가 생성되는 적절한 타이밍에 시간 맞춰 다이브를 하는 판단을! 라고 해봤자 롤 모르는 사람은 그게 뭔데 씹덕아) 게임 시청을 하는 사람들은 대부분 자신이 로직을 아는 게임들을 봄. 그래야 더 몰입이 되니까. 그런데 단순히 '보여주는 것'만으로 게임의 재미를 전달한다? 이는 사실상 영화를 보여주는 것과 다름이 없다. 게임 행사 같은 건 직접 플레이하게 되는 기회를 제공하는데 이건 그런 것도 아니라 그냥 보여주고 끝. 심지어 게임 엔진도 막아놔서 게임의 완성도가 필연적으로 떨어짐. 가뜩이나 프로그래머 5명임. 즉, 시연을 할 때 재미있는 게임이라는 건 그 게임이 얼마나 재미있느냐에 달린게 아님. 막말로 프로토타입 대충 만들어놓고 1달 동안 알바한 다음에 알바비로 아트 외주 5명 고용해서 아트 채워넣는게 훨씬 시연에 좋음. 그럼에도 불구하고 재미있는 시연을 만들 한 가지 방안은 게임 로직이 여러개여야 함. 게임 로직이라는 요소 자체가 갖는 힘은 신선함(무언가를 알게되었다는 즐거움) 하나 뿐임. 각각에 직관적이고 시각적으로 재미있는 로직과 함께, 탈락한다는 요소를 넣으면 없는 살림에 최대한 도파민을 쥐어짜낼 수 있을 것. 개발도 각 사람이 맡아서 하면 공평하게 게임 로직 코드를 건드려보니 좋을듯? 브라우저의 한계를 이용하는 온갖 기믹을 떡칠? (https://zeehatcher.itch.io/windowframe 이런거?)

방향성 : 인상 깊어서 후속작을 기대하게 되는 데모? 시연 순간에 가장 빛나는 게임?

웹 서버 멀티의 문제 : 일반적인 기술력으로는 핑이 튈 것으로 예상됨. 그러면 실시간 멀티 게임에서 할 수 있는 것들이 엄청나게 제한됨. 일단 공정성이나 플레이의 일관성이 심각하게 망쳐질 것. 뚝 뚝 끊기면 일단 그냥 하기가 싫다.

좀 예술충 느낌으로 가면 동물원 수족관에 갇혀있던 물고기 두 마리가 펄떡거리며 탈출해서 온갖 인간 세상 일들 하는 미니게임(추격전 or 타이쿤 or FPS 등. 아니면 그냥 단순히 각 상황에 대한 묘사를 게임으로 옮겨도 좋다.) 하면서 바다로 가는 이야기. Journey + It takes two?
검은색 사람들이 아래에 지나가고 물고기들 있는데 그 중 두 개가 딱 멈추고 조작 가능해짐)
서사 부여를 탈출이라는 직선적 스토리로 해결 + 게임 로직 신선함을 잦게 공급
레퍼런스 게임이 있냐요? 라고 하면 It takes two(기본적으로는 플랫포머+퍼즐이지만 여러 게임 장르들을 섞어서 플레이하게 됨)라고 하면 됨. EA겜에다 GOTY였어서 당연히 아실듯?
근데 이건 아트가 좀 받춰줘야 게임의 힘이 올라올듯. 스타일을 판판야 느낌으로 하면 배경은 대충 AI로 떼우고 캐릭터만 어떻게든 하면 적은 아트 인원으로도 되지 않을까? <- 이를 근거로 어떻게든 엔진 쓰게 해달라 징징?
이상적으론 외부 선 굵어서 귀여운 캐주얼 느낌이 좋긴 함. (생각한 느낌에 딱 맞는 레퍼런스를 못 찾겠음. 약간 다르긴 하지만 https://rhosgfx.itch.io/vector-icon-pack 이런 느낌?)



⚔️ 백준


📌 2168 경찰차

import sys
input = sys.stdin.readline
sys.setrecursionlimit(10**6)
N = int(input()) # 도로의 개수
W = int(input()) # 사건의 개수
cases = [(1,1),(N,N)]
for _ in range(W):
    ew, ns = map(int,input().split())
    cases.append((ew,ns))
dp = [[-1]*(W+2) for _ in range(W+2)]
course = [[-1]*(W+2) for _ in range(W+2)]
# 규칙이 없는 경로들의 비용 최솟값이므로 모든 경로의 비용 중 최소를 구해야 함
# 모든 경로를 계산하려면 2의 n승. 불가능하므로 dp 사용.
# 필요한 정보 : (왼쪽 혹은 오른쪽에서) 경로가 정해진다면, 나머지 경로에서의 최소 경로 비용
# dp로 경로 계산을 생략하려면 공통되는 부분이 필요한데,
# 경찰차당 마지막으로 출동했던 사건의 번호를 인덱스로 설정하면 됨
# 자연스럽게 왼쪽에서 경로를 정한 다음 오른쪽의 정보를 요구하는 재귀가 됨.
def distance(a,b):
    return abs(cases[a][0]-cases[b][0])+abs(cases[a][1]-cases[b][1])

def min_d(a,b):
    next = max(a,b)+1
    if next == W+2:
        return 0
    if dp[a][b] != -1:
        return dp[a][b]    
    a_cost = min_d(next,b)+distance(a,next)
    b_cost = min_d(a,next)+distance(b,next)
    if a_cost < b_cost: 
        course[a][b] = 1
        dp[a][b] = a_cost
    else: 
        course[a][b] = 2
        dp[a][b] = b_cost
    return dp[a][b]

min_d(0,1) # 첫번째 경찰차는 1,1, 두번째 경찰차는 N,N에서 시작
print(dp[0][1])

a,b,cnt=0,1,2
while cnt < W+2:
    car = course[a][b]
    print(car)
    if car == 1: a=cnt
    else: b=cnt
    cnt+=1

그리디로는 안된다. 반례 무수히 존재.

최소값을 구하려면 모든 경로에 대한 값을 비교해야 함.
그냥 풀면 2의 n승이므로 dp를 사용해야 함.

내가 갔던 경로를 저장하면서 쌓아나가기 : 상향식, for문
내가 앞으로 갈 경로의 값(미지의 값)을 요구하는거 : 하향식, 재귀

둘 중 하나 고르는 근거 : 각 경찰차가 마지막으로 출동했던 사건이 같으면 앞으로의 최소 경로도 같다.
필요한 정보는 이제까지의 경로가 아닌, 앞으로의 최소 경로이므로 하향식이어야 한다.

답을 뜯어보며 계속 보다가 거의 외우다시피 해서 풀긴 했는데
나름 많이 배우긴 함. 문제는 시간이 좀 느리다.

import sys
from collections import defaultdict

# 두 사건간의 거리를 저장
def get_diff(arr, i):
    i -= 1
    a = sum(arr[i]) - 2
    return [[a, MAX_INDEX-a-2]] + [abs(arr[i][0] - arr[j][0]) + abs(arr[i][1] - arr[j][1]) for j in range(i)]


# 최단경로 역 추적
def backtrack(arr, i, j):
    shor_path = []

    for k in range(L-1, 0, -1):
        if i == k:
            shor_path.append(2)
            i = arr[i][j]
        else:
            shor_path.append(1)
            j = arr[i][j]

    return shor_path[::-1]


def sol(incidents):
    dp = {(0, 0): 0}
    hist = [[0] * L for _ in range(L)]
    maxi = float('inf')

    for i in range(1, L):
        dp2 = defaultdict(lambda: float('inf'))
        diff = get_diff(incidents, i)
        maxi2 = maxi + MAX_INDEX
        maxi = float('inf')

        for k, v in dp.items():
            car2, car1 = k
            d1 = (diff[0][0] if car1 == 0 else diff[car1]) + v
            d2 = (diff[0][1] if car2 == 0 else diff[car2]) + v

            if d1 < maxi2 and d1 < dp2[(car2, i)]:
                dp2[(car2, i)] = d1
                hist[car2][i] = car1

            if d2 < maxi2 and d2 < dp2[(i, car1)]:
                dp2[(i, car1)] = d2
                hist[i][car1] = car2
            
            maxi = min(maxi, d1, d2)

        dp = dp2
    
    k, v = sorted(dp.items(), key=lambda x: x[1])[0]
    y, x = k
    
    return [v] + backtrack(hist, y, x)
    
    

readline = sys.stdin.readline
N = int(readline())
W = int(readline())
incidents = [tuple(map(int, readline().split())) for _ in range(W)]

L = W + 1
MAX_INDEX = 2 * N

print(*sol(incidents), sep='\n')

제일 빠른 건 속도가 나보다 20배 가까이 차이 남.

내일 무슨 얘기인지 마저 봐야할듯.

0개의 댓글