Um objeto em um jogo 2D deve renderizar-se?


16

Estou fazendo um jogo 2D de street fighter que não é baseado em blocos. Geralmente, as pessoas recomendam que as entidades sejam dadas a um renderizador que as renderize, e não elas mesmas, mas parece que o inverso é melhor,

Por que um é melhor que o outro?

obrigado


Por que você acha que o inverso é melhor?

1
@ Martin, porque o objeto indicará qual bitmap usar de qualquer maneira, então por que não fazer object-> render ();
jmasterx

Respostas:


11

Algumas considerações:

  • como você mencionou, cada sprite teria que "sugerir" sobre qual bitmap usar, mas se a entidade tiver que se renderizar. O que seria essa 'dica'? Se for uma referência a um bitmap diferente, folha de sprite, etc ... para cada sprite, você poderá acabar usando mais memória do que o necessário ou tendo problemas para gerenciar essa memória. Uma vantagem de um renderizador separado é que você tem apenas uma classe responsável por qualquer gerenciamento de ativos. Dito isto, em um jogo de luta do tipo SF2, você pode ter apenas dois sprites;)

  • como mencionado em outro lugar, sempre que você quiser alterar sua API gráfica, é necessário alterar o código de todos os seus sprites.

  • a renderização raramente é feita sem uma referência a algum contexto gráfico. Portanto, existe uma variável global que representa esse conceito ou cada sprite tem uma interface com render (GraphicalContext ctx). Isso combina a API gráfica e a lógica do seu jogo (que algumas pessoas consideram deselegante) e pode causar problemas de compilação.

  • Pessoalmente, acho que separar a renderização das entidades individuais é um primeiro passo interessante na direção de ver seu jogo como um sistema que não precisa necessariamente de gráficos. O que quero dizer é que, quando você coloca a renderização fora do caminho, percebe que muita jogabilidade acontece em um "mundo não gráfico", onde as coordenadas das entidades, seus estados internos, etc ... é o que importa. Isso abre a porta para testes automatizados, sistema mais dissociado, etc ...

Em suma, tendem a preferir sistemas onde a renderização é feita por uma classe separada. Isso não significa que seus sprites não possam ter alguns atributos "relacionados graficamente" (nome da animação, quadro de animação, altura x largura, ID do sprite, etc ...), se isso facilitar a gravação ou a eficiência do renderizador.

E não sei se isso se aplicaria ao 3D (onde a noção de malhas e a variável de coordenadas que você usaria talvez estivessem ligadas à sua API 3D; enquanto x, y, h, w é praticamente independente de qualquer 2D API).

Esperando que isso ajude.


11

Você deseja que o sistema de renderização esteja no controle do que é desenhado quando. Se os sprites estiverem no controle da renderização, você perderá muitos ganhos de eficiência e flexibilidade. Sou da opinião de que ter o sistema de renderização no controle resulta em um código mais limpo.

Algumas vantagens da renderização centralizada:

  • z-ordering:
    se os próprios objetos do jogo forem responsáveis ​​pela renderização, você precisará chamá-los na ordem correta. Caso contrário, os objetos de segundo plano podem ser desenhados sobre objetos de primeiro plano.
    Com o sistema de renderização sob controle, ele pode escolher classificar todos os objetos de renderização, detectar sobreposições no momento da renderização e apenas renderizá-las, ou simplesmente deixar de ordenar todas juntas. O ponto é que a decisão pode ser tomada facilmente agora.
  • lote:
    A outra vantagem óbvia de permitir que o sistema de renderização esteja sob controle é o lote. Aqui, novamente, o sistema de renderização tem a opção de agrupar sprites para renderizar o compartilhamento de uma textura. Ele pode usar o corte em triângulo para renderizar tudo com uma chamada. Pode ser capaz de armazenar em cache alguns cálculos de renderização. Ou poderia apenas renderizar cada sprite com nenhuma dessas coisas sofisticadas. (Nota: é possível lote quando cada objeto é renderizado, mas o problema é menos eficiente e mais complexo).

A maneira como eu implemento isso nos meus jogos é para que os objetos do jogo registrem os sprites que eles desejam desenhar com o sistema de renderização. Quando o objeto não deseja mais que ele seja desenhado, ele cancela o registro do sprite ou o marca como inativo.

Tudo o que disse. Se for mais fácil fazer com que seus objetos de jogo sejam renderizados por todos os meios, faça-o dessa maneira. É muito mais importante progredir e desenhar algo / qualquer coisa do que ter uma arquitetura perfeita.


Sobre a ordem z, se os objetos se desenham, um sistema não pode decidir sobre a ordem de chamar seu método de desenho? Quero dizer centralizado vs não centralizado parecem não fazer diferença sobre a ordem z.
GorillaApe

3

Isenção de responsabilidade: sua pergunta não fornece muitos detalhes, por isso estou respondendo com um princípio geral. Por favor, desculpe-me se eu entendi mal o seu uso ou 'renderize'.

Geralmente, uso um objeto externo para renderizar vários atores em uma cena como uma maneira de encapsular propriedades e métodos no nível da cena fora dos 'objetos de ator' individuais. Objetos na cena devem conter apenas métodos e propriedades internas; eles devem saber apenas sobre o que são e o que fazem. Presumivelmente, eles serão influenciados por outros objetos no jogo, bem como pela entrada do usuário. Isso afetará como / se eles são renderizados na tela. Um 'objeto diretor' pode, por exemplo, traduzir o pressionamento de tecla 'w' para pular e depois informar ao objeto ator .jump (). Essa lógica no nível do diretor também pode dizer aos atores para entrar ou sair completamente da cena.

Cheers, David


Mas, nesse sentido, o diretor não poderia simplesmente dizer acton-> setVisible (false); ?
jmasterx

Mesmo no caso de setVisible (false), é uma entidade externa que faz a renderização verificando a variável visível do ator e processando-a apenas se for verdadeira.
Nav

Apenas tornar um ator invisível não o remove da cena. Também deve parar de participar de colisões, etc.
finnw

3

E se algum dia você quiser portar seu jogo para uma resolução diferente (por exemplo, iPhone e amigos). Portanto, uma propriedade global sobre a renderização de alterações, como você atualiza facilmente seu código?


3

O que eu usei foi um design baseado em observador. Quando criei uma instância de uma classe que queria renderizar, um ponteiro para ela foi armazenado na classe Renderer central. Quando você chama RenderFrame(), o renderizador já possui todos os objetos existentes necessários para renderizar e acessou suas propriedades para fazê-lo. As próprias aulas não tinham ideia de que seriam renderizadas. Esta API foi agradável, limpa e fácil de usar.


1
+1 Interessante. Eu usei essa abordagem para som enquanto utilizava o padrão de visitantes para gráficos. Eu pensei que isso fazia mais sentido para o som, porque enquanto os gráficos e a IA estão sendo executados no mesmo relógio, o mixer de áudio está sendo executado em outro, para que um modelo de evento seja mais fácil. Também não é crítico se um evento de movimento (que faz com que o pan / reverb de um canal de áudio mude) chegue alguns milissegundos atrasado, mas é crítico se um sprite for desenhado no estado errado.
finnw

2

Em geral, é sempre sobre como é fácil manter e expandir seu código. Amanhã você descobrirá que não gosta da API de gráficos que está usando no momento e deseja mudar. Agora você terá que passar por todas as suas classes de objetos e mudar tudo ou ainda precisará alterar seu código em um ponto central do projeto?

Depende do que seus objetos estão realmente fazendo quando você chama render (). Contanto que eles apenas envolvam as chamadas de método em seu mecanismo gráfico, tudo ficará bem, pois a lógica <-> ainda será apresentada.

Por exemplo, se seus métodos render () são basicamente métodos de conveniência e se parecem com isso:

void MyClass::render(const Graphics &g)
{
    g.draw(this);
}

ou

void MyClass::render()
{
   mySprite->render();
}

ou

void MyClass::render()
{
    mySprite->UseShader(thatshader);
    mySprite->render();
}

ou perto disso, não acho que seja um problema.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.