🤔 Para Refletir :
"Mudar não é fraqueza, pelo contrário, é um sinônimo de superação"
- Ricky O Bardo

RPG Maker MZ Tutorial (RPG MAKER MV/MZ) - Criando uma Janela

GuilhermeSantos001 Masculino

Conde
Membro
Membro
Desenvolvedor FullStack
Juntou-se
29 de Dezembro de 2017
Postagens
337
Bravecoins
69

Introdução

Nesse tutorial iremos criar um plugin para adicionar uma nova janela customizada no RPG MAKER MV/MZ.

Requisitos

  1. RPG MAKER MV/MZ
  2. Visual Studio Code

Conteúdo

Olá a todos vocês, espero que estejam bem!
Resolvi experimentar criar esse tipo de conteúdo para ver se consigo transmitir conhecimento e ensinar algumas coisas legais. Para começar vamos criar uma janela a pedido do @DadoCWB, a criação de janelas é um tema muito recorrente para os iniciantes em programação no RPG MAKER, elas ajudam a exibir informações ao usuário, e muitos plugins utilizam esse recurso, imagine ter uma janela de opções para parametrizar o seu plugin, maneiro né? agora vamos começar a codificação.

DISCLAIMER
Esse tutorial pode ser consumido por qualquer pessoa que tenha interesse na área de programação, ele foi escrito e pensado para pessoas com qualquer nível de experiencia profissional.​

Primeiro acesse o Visual Studio Code e abra a pasta do seu projeto.

gNMsYhU.png

fZv2x6P.png


Crie um novo arquivo chamado "CustomWindow.js", dentro da pasta JS > Plugins.

nc9bRDW.png


Agora que já temos nosso arquivo, vamos adicionar o seguinte trecho de código:

Javascript:
 (function () {
  'use strict';

})();

Criamos uma função que será executada automaticamente e definimos "use strict", o strict mode faz várias mudanças nas semânticas normais do JavaScript. Primeiro, o strict mode elimina alguns erros silenciosos do JavaScript fazendo-os lançar exceções. Segundo, o strict mode evita equívocos que dificultam que motores JavaScript realizem otimizações: código strict mode pode às vezes ser feito para executar mais rápido que código idêntico não-strict mode. Terceiro, strict mode proíbe algumas sintaxes que provavelmente serão definidas em versões futuras do ECMAScript.​

Entendo a Window_Base
A Window_Base é usada como a base de toda janela criada no maker, digamos que ela seja a mãe das janelas, na programação orientada a objetos nos chamamos esse comportamento de Parent and Child, ou seja, existe o vinculo entre as classes e isso se chama Herança, com o javascript podemos passar as heranças usando funções de prototipo, veja esse trecho de código:​

Javascript:
Window_Base.prototype = Object.create(Window.prototype);
Window_Base.prototype.constructor = Window_Base;

Primero é criado a função prototipada a partir do método Object.create() que criará um novo objeto com base no Window.prototype que foi passado como parâmetro, dessa forma a Window_Base.prototype receberá todos os métodos também definidos em Window, criando assim a relação de Parent and Child, e por fim temos a mudança do Constructor que será responsavel por definir a autoria dos métodos criados a partir de Window_Base.prototype, se não mudarmos isso todos os métodos gerados em Window_Base passariam a ser de autoria de Window.

Entenda a seguinte declaração:
Javascript:
function Window_Base() {
    this.initialize(...arguments);
}

Window_Base.prototype.initialize = function(rect) {
    Window.prototype.initialize.call(this);
    this.loadWindowskin();
    this.checkRectObject(rect);
    this.move(rect.x, rect.y, rect.width, rect.height);
    this.updatePadding();
    this.updateBackOpacity();
    this.updateTone();
    this.createContents();
    this._opening = false;
    this._closing = false;
    this._dimmerSprite = null;
};

A função é criada normalmente, porem existe a chamada do método Initialize passando os Arguments da função usando a sintaxe Spread, mas agora você deve se perguntar a onde você defini esses "Arguments", bem veja que existe dentro do método "Window_Base.prototype.initialize" a seguinte declaração "function(rect)", ou seja existe 1 (um) argumento: rect. Existe a seguinte invocação "Window.prototype.initialize.call(this);", existe um motivo de ela está no topo do bloco da função, essa invocação tem como objetivo fazer com que o Parent execute seu método Initialize usando o this, se atente a essa palavra, pois ela é reservada e faz referência clara a função na qual o bloco de código se encontra. Perceba que o método foi chamado usando o .call(this), dessa maneira this (Window) passa a ser this (Window_Base).

Criando nossa Window_Custom
Vamos criar nossa Window a partir da Window_Gold, veja o trecho a seguir:
Javascript:
  //-----------------------------------------------------------------------------
  // Window_Custom
  //
  // The window for displaying the party's gold.

  function Window_Custom() {
    this.initialize(...arguments);
  }

  Window_Custom.prototype = Object.create(Window_Selectable.prototype);
  Window_Custom.prototype.constructor = Window_Custom;

  Window_Custom.prototype.initialize = function (rect) {
    Window_Selectable.prototype.initialize.call(this, rect);
    this.refresh();
  };

  Window_Custom.prototype.colSpacing = function () {
    return 0;
  };

  Window_Custom.prototype.refresh = function () {
    const rect = this.itemLineRect(0);
    const x = rect.x;
    const y = rect.y;
    const width = rect.width;
    this.contents.clear();
    this.drawText(this.value(), x, y, width, "center");
  };

  Window_Custom.prototype.value = function () {
    return "Hello World";
  };

  Window_Custom.prototype.open = function () {
    this.refresh();
    Window_Selectable.prototype.open.call(this);
  };

O que fizemos foi pegar todo o código da Window_Gold e modificar algumas partes, nossa janela irá mostrar a mensagem "Hello World". Agora que já temos a janela criada, precisamos adicionar a mesma a camada da Scene que queremos, mas antes iremos entender as Scenes.

O que é uma Scene?
As scenes como o próprio nome já diz são as cenas representadas em tela para o jogador, no RPG MAKER tudo é representado por cenas. Devemos entender a Scene mais importante a "Scene_Base", assim como a "Window_Base" é responsável por cada janela no jogo, a Scene_Base fica responsável por cada cena. Veja o trecho a seguir:
Javascript:
  //-----------------------------------------------------------------------------
  // Scene_Map
  //
  // The scene class of the map screen.

  const _sceneMap_start = Scene_Map.prototype.start;
  Scene_Map.prototype.start = function () {
    _sceneMap_start.call(this);
    this.addWindowCustom(0,0, 200, 100);
  };

  Scene_Map.prototype.addWindowCustom = function (x, y, width, height) {
    this._windowCustom = new Window_Custom(new Rectangle(x, y, width, height));
    this.addWindow(this._windowCustom);
  };

Perceba que invocamos o método start da cena do map, então toda vez que um mapa for iniciado nossa janela será criada também. Veja a seguinte declaração: const _sceneMap_start = Scene_Map.prototype.start;, o motivo para definir uma o constante com o valor da função que invocamos é que se não fizermos isso, logo a nova declaração adicionada ao método start, iria sobrescrever o anterior e quebrar o jogo, veja o exemplo a seguir:​

Javascript:
// Modo errado!

/*
Dessa forma estamos sobrescrevendo o método.
*/

Scene_Map.prototype.start = function() {
    Scene_Message.prototype.start.call(this);
    SceneManager.clearStack();
    this.addWindowCustom(0,0, 200, 100);
};

Scene_Map.prototype.addWindowCustom = function (x, y, width, height) {
    this._windowCustom = new Window_Custom(new Rectangle(x, y, width, height));
    this.addWindow(this._windowCustom);
};

// Modo correto!

/*
Dessa forma estamos criando um alias (_sceneMap_start) para que o método anterior
ainda possa ser preservado e chamado novamente.
*/

const _sceneMap_start = Scene_Map.prototype.start;
Scene_Map.prototype.start = function () {
    _sceneMap_start.call(this);
    this.addWindowCustom(0,0, 200, 100);
};

Scene_Map.prototype.addWindowCustom = function (x, y, width, height) {
    this._windowCustom = new Window_Custom(new Rectangle(x, y, width, height));
    this.addWindow(this._windowCustom);
};

Testando nossa Janela!
Agora que já entendemos o que era essencial, vamos criar nossa janela em tela, veja o trecho a seguir:

Javascript:
(function () {
  'use strict';

  //-----------------------------------------------------------------------------
  // Window_Custom
  //
  // The window for displaying the party's gold.

  function Window_Custom() {
    this.initialize(...arguments);
  }

  Window_Custom.prototype = Object.create(Window_Selectable.prototype);
  Window_Custom.prototype.constructor = Window_Custom;

  Window_Custom.prototype.initialize = function (rect) {
    Window_Selectable.prototype.initialize.call(this, rect);
    this.refresh();
  };

  Window_Custom.prototype.colSpacing = function () {
    return 0;
  };

  Window_Custom.prototype.refresh = function () {
    const rect = this.itemLineRect(0);
    const x = rect.x;
    const y = rect.y;
    const width = rect.width;
    this.contents.clear();
    this.drawText(this.value(), x, y, width, "center");
  };

  Window_Custom.prototype.value = function () {
    return "Hello World";
  };

  Window_Custom.prototype.open = function () {
    this.refresh();
    Window_Selectable.prototype.open.call(this);
  };

  //-----------------------------------------------------------------------------
  // Scene_Map
  //
  // The scene class of the map screen.

  const _sceneMap_start = Scene_Map.prototype.start;
  Scene_Map.prototype.start = function () {
    _sceneMap_start.call(this);
    this.addWindowCustom(0, 0, 200, 100);
  };

  Scene_Map.prototype.addWindowCustom = function (x, y, width, height) {
    this._windowCustom = new Window_Custom(new Rectangle(x, y, width, height));
    this.addWindow(this._windowCustom);
  };
})();

Abra o seu RPG MAKER e adicione nosso plugin e veja seu funcionamento.

fNYcdIP.jpg

Referências

 
Última edição:
Nem é preciso dizer, mas digo mesmo assim: se tem um cara que admiro muito nessa comunidade é o Dr. xamã. Cara, que fantástico essa tua iniciativa de compartilhar teu conhecimento com a gente! A criação de janelas é uma dos grandes mistérios do RPG MAKER.

Nem sem como agradecer. Obrigado mesmo!

Edit: O script está funcionando apenas no MZ. No MV ele da um erro e não executa.
 
Última edição:
Voltar
Topo Inferior