2010-02-11 6 views
8

나는 안드로이드 휴대폰을위한 Java shoot em up 게임을 만들고 있습니다. 나는 각자 몇 가지 독특한 행동을하지만, 대부분의 행동은 특정 행동을 재사용한다는 이상한 적을 20 명이나 받았습니다. 나는 총알, 폭발, 소행성 등을 모델화 할 필요가있다. 나의 현재 디자인은 상속을 통해 구성을 선호하고 게임이 같은 비트 객체를 나타냅니다 단지 기업 이미지로 저장됩니다 무엇이든 그릴게임 개체 렌더링 및 동작을 모듈 방식으로 모델링하는 방법은 무엇입니까?

// Generic game object 
class Entity 
{ 
    // Current position 
    Vector2d position; 

    // Regular frame updates behaviour 
    Behaviour updateBehaviour; 
    // Collision behaviour 
    Behaviour collideBehaviour; 

    // What the entity looks like 
    Image image; 
    // How to display the entity 
    Renderer renderer; 

    // If the entity is dead and should be deleted 
    int dead; 
} 

abstract class Renderer { abstract void draw(Canvas c); } 

abstract class Behaviour { abstract void update(Entity e); } 

, 당신은 예를 들어, 간단한 렌더러를 첨부 할 수 있습니다

class RandomlyMoveBehaviour extends Behaviour 
{ 
    void update(Entity e) 
    { 
    // Add random direction vector to e.position 
    } 
} 

또는 플레이어가 회귀 전에 가까운 때까지 기다리고처럼 더 복잡한 동작을 추가 :

class SimpleRenderer extends Renderer 
{ 
    void draw(Canvas c) 
    { 
    // just draw the image 
    } 
} 

는이 같은 동작을 첨부, 무작위로 각 프레임에 대한 비행 개체를 만들려면
class SleepAndHomeBehaviour extends Behaviour 
{ 
    Entity target; 
    boolean homing; 

    void init(Entity t) { target = t; } 

    void update(Entity e) 
    { 
    if (/* distance between t and e < 50 pixels */) 
    { 
     homing = true; 
     // move towards t... 
    } 
    else 
    { 
     homing = false; 
    } 
    } 
} 

지금까지이 디자인에 정말 만족합니다. 멋지고 융통성있게 다음과 같이 할 수 있습니다. 당신이 새로운 WaitUntilCloseBehaviour (player, 50/픽셀 /, 새로운 MoveRandomlyBehaviour(), 새로운 HomingBehaviour())와 같은 것을 말할 수 있도록 "sleep"행동과 "awake"행동을 제공 할 수 있도록 후자의 클래스를 모듈화하십시오. 이것은 새로운 원수를 만드는 것이 정말 쉽습니다.

나를 괴롭히는 유일한 부분은 동작과 렌더러가 통신하는 방식입니다. 현재 Entity에는 동작이 수정할 수있는 이미지 객체가 포함되어 있습니다. 예를 들어, 하나의 동작은 수면과 깨어있는 이미지 사이에서 객체를 변경할 수 있으며 렌더러는 이미지를 그릴뿐입니다. 예를 들어이 크기가 어떻게 조정될 지 잘 모르겠습니다. 예 :

  • 특정 방향을 향한 터렛과 같은 적은 어떨까요? Behavior와 Renderer가 모두 수정/읽을 수있는 엔티티에 회전 필드를 추가 할 수 있다고 생각합니다.

    • 탱크의 몸체와 탱크의 총이 서로 다른 방향을 갖는 탱크는 어떻습니까? 이제 렌더러는 어딘가에서 두 번 회전하고 두 이미지를 사용할 필요가 있습니다. 탱크가 하나뿐이라면 Entity 클래스를 크게 늘리고 싶지는 않습니다.

    • 총기 재충전으로 인해 빛나는 적은 어떻습니까? Behavior 객체에 충전 시간을 저장하고 싶지만 Renderer 클래스에서는이를 볼 수 없습니다.

내가 그렇게 렌더러와 행동이 다소 별도의 유지 될 수 위를 모델링하는 방법의 문제를 생각하는 데 문제가

. 내가 생각할 수있는 최선의 접근법은 비헤이비 객체에 추가 상태 인 렌더러 객체를 포함시킨 다음 비헤이비어 객체가 렌더러 그리기 메소드를 호출하고 원할 경우 추가 상태 (예 : 회전)를 전달하는 것입니다.

예를 들어 다음과 같이 할 수 있습니다. 후자가 두 개의 이미지를 요구하고 두 개의 회전이 그려 지도록 탱크와 같은 렌더러를 원하는 탱크와 같은 Behavior 객체를가집니다. 탱크를 단순한 이미지로 만들고 싶다면 회전을 무시한 서브 클래스 렌더러를 작성하면됩니다.

누구나 다른 대안을 생각해 낼 수 있습니까?나는 단순함을 정말로 원한다. 그것이 게임이기 때문에, 효율성은 예를 들어, 5 개의 5x5 적 이미지를 그리면 50 명의 적을 60fps로 비행 할 때 많은 함수 호출 레이어가 필요합니다.

답변

1

컴포지션 디자인은 동작 및 렌더링을 혼합 및 일치시킬 수 있으므로 유효한 디자인입니다.

게임에서 우리는 기본적인 정보 (귀하의 경우 위치 및 죽은/살아있는 상태)와 동작에 의해 설정/설정 해제되는 변수 데이터를 포함하는 "databag"를 추가했습니다 및 충돌 서브 시스템을 포함한다. 그런 다음 렌더러는 이러한 데이터를 사용할 수 있습니다 (필요하지 않은 경우가 아니라면). 이것은 잘 작동하며 주어진 그래픽 효과에 대해 "대상"을 설정하는 것과 같은 깔끔한 효과를 허용합니다.

몇 가지 문제 :

  • 렌더러가 동작이 설정되지 않았 음을 데이터를 요구하는 경우

    . 이 경우 이벤트가 기록되고 렌더러에 정의 된 기본값이 사용됩니다.
  • 미리 필요한 정보 (예 : 렌더러 A의 데이터 버퍼에 어떤 데이터가 있어야하는지, 동작 B에서 설정 한 데이터는 무엇인지)를 확인하는 것이 조금 어렵습니다. 우리는 문서를 최신 상태로 유지하려고 노력하지만, 우리는 클래스를 통해 set/get을 생각하고 문서 페이지를 생성하려고합니다 ...

현재 우리는 HashMap을 사용하고 있습니다. databag,하지만 이것은 PC에 있지만 아이폰에는 없다. 퍼포먼스가 충분할 지 모르겠다.이 경우 다른 구조체가 더 좋을 수도있다.

우리의 경우에는 특수 렌더러 세트를 결정했습니다. 함께

Renderer renderer1 = new RotatedImage("Tank.png", "TankRotation"); 
Renderer enderer2 = new RotatedImage("Turret.png", "TurretRotation"); 

"엔티티가 아닌 무효 실드 데이터를 가지고 있으면, 예를 들어, ShieldRenderer는 표현을 표시 ... 케이스, 상기 탱크는 두 (초기화 정의) datas 연결된 두 렌더러를 가지고 있었다 TankRotation "및"TurretRotation "을 설정합니다. 렌더러는 이미지를 단순히 위치를 표시하기 전에 회전시킵니다.

image.rotate (entity.databag.getData(variable)); 

희망이 도움

감사
기욤

+0

감사합니다. 필자는 프로파일을 작성하지 않았지만 많은 객체 (예 : 총알)가 필요하다면 안드로이드의 모든 동작을 업데이트하기 위해 해시 맵을 사용하지 않아야합니다. 변수 객체를 동작 객체에 로컬로 유지하는 것에 주목 한 이점 중 하나는 같은 변수를 사용하는 결합 된 동작에 대해 걱정할 필요가 없으므로 시스템을 훨씬 강력하고 쉽게 테스트 할 수 있다는 것입니다. – BobbyJim

+0

가 동의했습니다. 내가 말했듯이, 우리는 PC에 있으며 너무 많은 객체가 없습니다. 또한, 그것은 재미 있습니다 :) –

1

당신이려고하고 디자인은 나에게 좋아 보인다. components에 관한이 장은 도움이 될 것입니다.

+0

감사. 나는 지금 위의 접근 방식을 구현했으며 훌륭합니다! 사람들이 보지 못하는 한 가지 일은 행동 순서 지정 (예 : 두 가지 행동을 순차적으로 호출하는 행동)과 조건부 행동 (예 : 한 행동은 조건부로 다른 행동을 호출 함)입니다. 지금은 스크립팅 언어가 조금 밖에 없어서 매우 가볍습니다. 예를 들어, 객체의 조합을 사용하여 "if (플레이어에서 300 픽셀 떨어진 위치) (플레이어의 집)에서 그렇지 않으면 (플레이어에서 촬영)"과 같은 것을 말할 수 있습니다. 나는 예를 들어 새로운 코드를 작성할 수 있습니다. 몇 분 안에 게임의 적을 – BobbyJim

+0

그건 아주 멋지다. 당신은 기본적으로 스크립팅 언어를 가지고 있습니다. 그것은 교과서 [통역사 패턴]입니다 (http://en.wikipedia.org/wiki/Interpreter_pattern). – munificent

관련 문제