Jogo do Mago

Starter pack

Nesta lição, combinaremos nosso motor VFX com muitas das coisas que aprendemos durante este curso para criar um jogo 3D simples: Um mago enfrentando orcs vis usando feitiços e magia. 🧙‍♂️

Uma base sólida para seus próprios projetos de desenvolvimento de jogos na web!

Projeto Inicial

O projeto inicial contém:

Projeto Inicial do Jogo do Mago

Aqui está como o projeto inicial se parece.

Pronto para começar? 🪄

Bem-vindo a Hogwarts 🏰

Antes de implementar qualquer tipo de lógica de jogo, vamos praticar nossas habilidades mágicas em Hogwarts criando feitiços usando o motor de VFX que construímos na lição dedicada.

Como fizemos na lição de fogos de artifício, podemos usar a versão publicada do motor de VFX. Vamos adicioná-lo ao nosso projeto:

yarn add wawa-vfx@^1.0.0

Ao usar @^1.0.0, garantimos que sempre vamos usar a versão principal 1 do pacote, mas incluindo as versões mais recentes de correção e minor. Dessa forma, podemos nos beneficiar das últimas funcionalidades e correções de bugs sem mudanças que quebram.

Agora, no arquivo Magic.jsx, vamos criar um componente <VFXS /> que conterá todos os nossos componentes <VFXParticles /> para o nosso projeto.

import { VFXParticles } from "wawa-vfx";

export const Magic = ({ ...props }) => {
  // ...

  return (
    <group {...props}>
      <VFXS />
      {/* ... */}
    </group>
  );
};

const VFXS = () => {
  return (
    <>
      <VFXParticles
        name="sparks"
        settings={{
          nbParticles: 100000,
          renderMode: "billboard",
          intensity: 3,
          fadeSize: [0.1, 0.1],
        }}
      />
  );
};

E ao lado, um componente Spells que será responsável pela parte de renderização dos nossos feitiços.

// ...
export const Magic = ({ ...props }) => {
  // ...

  return (
    <group {...props}>
      <VFXS />
      <Spells />
      {/* ... */}
    </group>
  );
};

const Spells = () => {
  return <></>;
};

Eu gosto de misturar vários componentes no mesmo arquivo quando eles estão intimamente relacionados. Isso torna mais fácil entender a lógica do arquivo. Sinta-se à vontade para dividi-los em pastas/arquivos separados se preferir.

Vamos preparar nosso primeiro feitiço, o feitiço Void.

Feitiço de Vazio

Vamos criar um componente chamado Void que será renderizado no componente Spells.

// ...
import { VFXEmitter } from "wawa-vfx";

// ...

const Spells = () => {
  return (
    <>
      <Void />
    </>
  );
};

const Void = ({ ...props }) => {
  return (
    <group {...props}>
      <VFXEmitter debug emitter="sparks" />
    </group>
  );
};

O componente VFXEmitter emitirá partículas do emissor sparks que criamos no componente VFXS.

Com debug definido como true teremos controles visuais para moldar o efeito que queremos alcançar.

Ok, vamos criar um feitiço que fará os orcs tremerem!

Um bom efeito de VFX é uma combinação das configurações certas e do tempo certo.

Vamos decompor o que queremos alcançar com o feitiço Void.

Primeiro, queremos uma fase de preparação. É quando a energia é reunida antes do feitiço ser lançado. Quanto melhor for feito, mais antecipação o jogador sentirá, e mais poderoso o feitiço parecerá.

Nossa preparação será composta por:

  • Partículas emitidas lentamente para cima
  • Uma esfera crescente
  • Runas escritas giratórias no chão como se o feitiço estivesse sendo lançado

Em seguida, queremos a fase de explosão. É quando o feitiço é lançado e a energia é liberada. Quanto melhor for feito, mais satisfação o jogador sentirá.

Nossa explosão será composta por:

  • A esfera explodindo (fazendo-a desaparecer)
  • Partículas indo em todas as direções

E para cada efeito visual, adicionaremos um efeito sonoro para torná-lo mais imersivo.

Vamos brincar com as configurações do componente VFXEmitter para alcançar o efeito desejado para as partículas de preparo.

Aqui está o que eu criei:

<VFXEmitter
  emitter="sparks"
  settings={{
    duration: 0.5,
    delay: 0,
    nbParticles: 20,
    spawnMode: "time",
    loop: false,
    startPositionMin: [-0.5, 0, -0.5],
    startPositionMax: [0.5, 1, 0.5],
    startRotationMin: [0, 0, 0],
    startRotationMax: [0, 0, 0],
    particlesLifetime: [0.5, 1],
    speed: [0, 1],
    directionMin: [0, 0, 0],
    directionMax: [0, 0.1, 0],
    rotationSpeedMin: [0, 0, 0],
    rotationSpeedMax: [0, 0, 0],
    colorStart: ["#4902ff"],
    colorEnd: ["#ffffff"],
    size: [0.1, 0.4],
  }}
/>

Podemos ver as partículas subindo lentamente.

Em vez de partículas quadradas, vamos usar triângulos. Para isso, podemos usar uma cone geometry com as configurações apropriadas.

// ...

const VFXS = () => {
  return (
    <>
      <VFXParticles
        name="sparks"
        geometry={<coneGeometry args={[0.5, 1, 8, 1]} />}
        settings={{
          nbParticles: 100000,
          renderMode: "billboard",
          intensity: 3,
          fadeSize: [0.1, 0.1],
        }}
      />
    </>
  );
};

// ...

As partículas agora parecem triângulos.

Agora vamos adicionar a esfera crescente. Para isso, precisamos adicionar um novo componente VFXParticles ao componente VFXS:

const VFXS = () => {
  return (
    <>
      {/* ... */}
      <VFXParticles
        name="spheres"
        geometry={<sphereGeometry args={[1, 32, 32]} />}
        settings={{
          nbParticles: 1000,
          renderMode: "mesh",
          intensity: 5,
          fadeSize: [0.7, 0.9],
          fadeAlpha: [0, 1],
        }}
      />
    </>
  );
};

Definindo fadeSize como [0.7, 0.9], fazemos a esfera crescer lentamente até 70% de sua vida útil e depois desaparecer rapidamente durante os últimos 10%.

Three.js logoReact logo

React Three Fiber: The Ultimate Guide to 3D Web Development

✨ You have reached the end of the preview ✨

Go to the next level with Three.js and React Three Fiber!

Get full access to this lesson and the complete course when you enroll:

  • 🔓 Full lesson videos with no limits
  • 💻 Access to the final source code
  • 🎓 Course progress tracking & completion
  • 💬 Invite to our private Discord community
Unlock the Full Course – Just $85

One-time payment. Lifetime updates included.