순수한 기능 프로그래밍 및 게임 상태


12

함수형 프로그래밍 언어에서 상태 (일반적으로)를 처리하는 일반적인 기술이 있습니까? 모든 (기능) 프로그래밍 언어에는 전역 상태를 처리하는 솔루션이 있지만 가능한 한 이것을 피하고 싶습니다.

순수한 기능 방식의 모든 상태는 기능 매개 변수입니다. 따라서 전체 게임 상태 (세계, 플레이어, 위치, 점수, 자산, 적 등을 포함한 거대한 해시 맵)를 주어진 입력 또는 트리거에서 세계를 조작하려는 모든 함수의 매개 변수로 설정해야합니다. . 이 함수 자체는 gamestate blob에서 관련 정보를 선택하고 그와 관련된 작업을 수행하고 게임 상태를 조작하고 게임 상태를 반환합니다. 그러나 이것은 문제에 대한 가난한 망 솔루션처럼 보입니다. 전체 게임 상태를 모든 함수에 적용하면 전역 변수 또는 명령 방식과 달리 이점이 없습니다.

관련 정보 만 함수에 넣고 주어진 입력에 대해 취할 조치를 리턴 할 수 있습니다. 그리고 하나의 단일 함수가 모든 동작을 게임 상태에 적용합니다. 그러나 대부분의 기능에는 많은 "관련"정보 가 필요합니다 . move()물체 위치, 속도, 충돌 맵, 모든 적의 위치, 현재 체력 등이 필요합니다. 따라서이 방법도 효과가없는 것 같습니다.

그래서 제 질문은 함수형 프로그래밍 언어, 특히 게임 개발에서 방대한 양의 상태를 어떻게 처리합니까?

편집 : Clojure에서 게임을 구축하기위한 게임 프레임 워크가 있습니다. 이 문제를 부분적으로 해결하는 방법 은 게임의 모든 개체를 "엔티티"로 스레드 하여 큰 가방에 넣는 것입니다. GIGANT 주요 기능은 화면을 잡고 그리고 엔티티와 핸들 이벤트 ( :on-key-down, :on-init이 엔티티, ...)와 메인 디스플레이 루프를 실행합니다. 그러나 이것은 내가 찾고있는 깨끗한 솔루션이 아닙니다.


나는 이런 종류의 것에 대해 한동안 생각하고 있었다; 비 기능적 프로그래밍의 함수에 동일한 요소를 여전히 공급해야하기 때문에 고유 한 문제 인 입력 은 아닙니다 . 아니요, 문제가되는 것은 출력 (및 후속 관련 업데이트)입니다. 입력 매개 변수 중 일부를 결합해야합니다. 를 위해 move()아마도 '현재'객체 (또는 식별자)와 이동하는 세계를 전달하고 현재 위치와 속도를 도출해야합니다 . 출력은 전체 물리 세계 또는 적어도 변경된 객체의리스트
Clockwork-Muse

순수한 기능의 장점은 함수 프로토 타입에 프로그램의 모든 종속성이 표시된다는 것입니다.
tp1

3
기능적 언어 인 IMO는 게임 작성에 적합하지 않습니다. 이것은 해결해야 할 많은 문제 중 하나입니다. 게임은 매우 정밀한 성능 제어가 필요하며 예측할 수없는 이벤트가 자연스럽게 발생하기 때문에 동시성이 거의 없습니다. (순수한) 기능적 언어는 사소한 병렬화가 가능하고 최적화하기 어려운 것으로 유명합니다. 게임은 쓰기가 어렵고, 복잡한 기능을 수행하기 전에 전형적인 언어로하는 것이 좋습니다.
Casey Kuball

답변:


7

기능적 프로그래밍 언어의 부작용과 상태는 컴퓨터 과학에서 더 큰 문제입니다. 이전에 본 적이없는 경우 monads를 살펴보십시오 . 그러나 경고 : 그들은 상당히 진보 된 개념이며 내가 아는 대부분의 사람들은 그것들을 이해하려고 애 쓰고 있습니다. 접근 방식과 지식 요구 사항이 다른 많은 온라인 자습서 가 많이 있습니다 . 개인적으로 나는 Eric Lippert의 최고를 좋아했습니다.

저는 "기능적 프로그래밍"배경이없는 C # 프로그래머입니다. 내가 계속 듣고있는이 "모나드"는 무엇이며 어떤 용도로 사용됩니까?

Monads의 Eric Lippert

그러나 고려해야 할 사항 :

  • 순전히 기능적인 언어를 사용해야합니까? 함수형 프로그래밍과 게임 개발에 모두 능숙하다면 아마도 그것을 풀 수있을 것입니다. (하지만 혜택이 노력할만한 가치가 있는지 알고 싶습니다.)
  • 필요한 경우에만 기능적 접근 방식을 사용하는 것이 낫지 않습니까? 객체 지향 (또는 다중 패러다임) 언어를 사용하는 경우 기능적 스타일을 사용하여 이익을 얻는 섹션을 구현하는 데 방해가되지 않습니다. (MapReduce를 좋아 하는가?)

마지막 생각 :

  • 병렬 : 게임을하는 동안 않습니다 많이 사용, 그것의 가장 AFAIK 이미 어쨌든 GPU에서 발생합니다.
  • Statelessness : 상태의 변이는 게임에서 없어서는 안될 부분입니다. 그것들을 제거하려고하면 문제가 불필요하게 복잡해질 수 있습니다.
  • 기능 언어 F #이 .NET의 객체 지향 에코 시스템에서 어떻게 작동하는지 살펴보십시오.

전체적으로, 그것이 학문적으로 흥미로울 수 있다고해도 나는이 접근법이 실용적이고 노력할 가치가 있다고 생각합니다.


경험이없는 주제에 대한 의견을 게시해야하는 이유는 무엇입니까? 사람들의 의견은 하나의 사고 패러다임에 갇혀 있습니다.
Anthony Raimondo 2016 년

4

나는 FOP (다중 패러다임, 불순하고 기능 우선 언어)를 사용하여 OOP에서 FRP에 이르는 몇 가지 게임을 작성했습니다 . 이것은 광범위한 질문이지만 최선을 다하겠습니다.

함수형 프로그래밍 언어에서 상태 (일반적으로)를 처리하는 일반적인 기술이 있습니까?

내가 선호하는 방법은 전체 게임을 나타내는 불변 유형을 갖는 것입니다 State. 그런 다음 State각 틱마다 업데이트 되는 전류에 대한 변경 가능한 참조가 있습니다. 이것은 순전히 순수하지는 않지만 변경 가능성을 한 곳으로 제한합니다.

전체 게임 상태를 모든 함수에 적용하면 전역 변수 또는 명령 방식과 달리 이점이 없습니다.

사실이 아니다. State타입은 불변 이므로, 구식 컴포넌트를 잘못 정의 된 방식으로 월드를 변형시킬 수 없습니다. 이렇게하면 GameObject접근 방식 의 가장 큰 문제가 해결됩니다 (Unity에서 인기 있음). Update통화 순서를 제어하기가 어렵습니다 .

전역을 사용하는 것과 달리 단위 테스트 및 병렬화가 용이합니다.

또한 문제를 해결하기 위해 상태의 하위 속성을받는 도우미 함수를 작성해야합니다.

예를 들면 다음과 같습니다.

let updateSpaceShip ship = 
  {
    ship with 
      Position = ship.Position + ship.Velocity
  }

let update state = 
  { 
    state with 
      SpaceShips = state.SpaceShips |> map updateSpaceShip 
  }

여기서는 update전체 상태에 영향을 미치지 updateSpaceShip만 개인 SpaceShip에 대해서는 단독으로 만 행동합니다 .

관련 정보 만 함수에 넣고 주어진 입력에 대해 취할 조치를 리턴 할 수 있습니다.

Input키보드, 마우스, 게임 패드 등 상태를 유지 하는 유형 을 만드는 것이 좋습니다. 그런 다음받는 함수 쓸 수 State와는 Input다음을 반환를 State:

let applyInput input state = 
  // Something

이것이 어떻게 맞는지에 대한 아이디어를 제공하기 위해 전체 게임은 다음과 같습니다.

let mutable state = initialState ()

// Game loop
while true do
  // Apply user input to the world
  let input = collectInput ()

  state <- applyInput input state

  // Game logic
  let dt = computeDeltaTime ()

  state <- update dt state

  // Draw
  render state

그래서 제 질문은 함수형 프로그래밍 언어, 특히 게임 개발에서 방대한 양의 상태를 어떻게 처리합니까?

간단한 게임의 경우 위의 접근 방식을 사용할 수 있습니다 (도움말 기능). 더 복잡한 것을 원한다면 " 렌즈 " 를 사용해 볼 수 있습니다 .

여기에 언급 된 의견 들과는 달리, (불완전한) 기능적 프로그래밍 언어로 게임을 작성하거나 적어도 시도해 보라고 강력히 제안합니다! 반복이 빨라지고 코드베이스가 작고 버그가 적다는 것을 알았습니다.

또한 (불완전한) FP 언어로 게임을 작성하기 위해 모나드를 배울 필요 가 없다고 생각합니다. 코드가 대부분 차단되고 단일 스레드이기 때문입니다.

멀티 플레이어 게임을 작성하는 경우 특히 그렇습니다. 그러면이 접근 방식을 사용하면 게임 상태를 간단하게 직렬화하고 네트워크를 통해 전송할 수 있기 때문에 훨씬 쉬워집니다.

더 많은 게임이 이런 식으로 쓰여지지 않은 이유는 말할 수 없습니다. 그러나 이것은 모든 프로그래밍 영역 (금융을 제외하고)에서 사실이므로, 기능 언어가 게임 프로그래밍에 적합하지 않다는 주장으로 이것을 사용하지 않을 것입니다.

또한 읽을만한 가치가있는 것은 순전히 기능적인 Retrogames 입니다.


1

당신이 찾고있는 것은 FRP 게임 개발입니다.

일부 비디오 소개 :

핵심 게임 로직을 순전히 기능적인 방식으로 만드는 것이 100 % 가능하고 바람직합니다. 전체 산업이 단순히 뒤처져 있고 하나의 사고 패러다임에 갇혀 있습니다.

Unity에서도 가능합니다.

질문에 답하기 위해 새로운 게임 상태는 무언가가 움직일 때마다 업데이트 / 만들어 질 것입니다. 카맥은 대화에서 문제가되지 않습니다. 순전히 기능적이고 유지 보수가 용이하며 유연한 아키텍처에서 발생하는인지 오버 헤드의 급격한 감소는 성능에 전혀 영향을 미치지 않습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.