Como criar um velocímetro
Este tutorial é uma resposta a este tópico em que me ofereci para criar um tutorial. A maioria dos tutoriais sobre velocímetros são bem antigos (alguns de 2010), não usam textdraws por jogador e estão seriamente desatualizados. O tutorial a seguir é baseado no SpeedoMeter do Fallout que encontrei há muito tempo. Este tutorial assume que você conhece o peão básico. Isso é declaração de variável, inicialização de variável, arrays, loops, tags, callbacks e funções. Se você não sabe o que alguns deles significam, talvez conheça os conceitos, mas simplesmente não sabia seus nomes. Portanto, apenas continue a ler.Isso é o que iremos criar (mais ou menos):
1. Introdução:
(Nota: parece que esta introdução tem informações suficientes, que se tornou seu próprio tutorial.)
Este tutorial envolve desenhos de texto, então precisamos saber quais são primeiro. Mesmo que essas informações possam ser encontradas no wiki, o que se segue são algumas coisas que considero importantes o suficiente para incluir neste tutorial. Se você já sabe qual é a diferença entre um textdraw global e um textdraw por jogador, pule para 2. Mas eu recomendo apenas lê-lo rapidamente, talvez você descubra algo que não sabia.
1.1 O que é um desenho de texto:
Um textdraw é um texto que pode ser desenhado em qualquer lugar na tela do jogador por um período indefinido de tempo. Pode ser um texto simples, como um relógio, um endereço de site, uma pontuação e assim por diante. Também pode ser algo complexo como uma barra de saúde, mostrar modelos de visualização, mostrar sprites e assim por diante. O texto pode ser desenhado em uma caixa. Também só podemos usar a caixa, fornecendo um texto vazio. Quando você pesquisa em ****** , você pode encontrar alguns bons exemplos do que é possível com textdraws.
1.2 Tipos de desenho de texto:
Existem dois tipos de desenho de texto: global e por jogador, que exploraremos nas seções a seguir.
1.2.1 Textdraw global:
Um textdraw global é o mesmo para todos os jogadores, por exemplo, um relógio. Ou é mostrado a um jogador ou não. Você só pode criar 2048 textdraws globais! Uma solução para esse problema é explorada na seção a seguir sobre desenhos de texto por jogador. Continue primeiro com esta seção, para que a próxima seja mais fácil de entender.
Exemplo:
- Temos um desenho de texto do relógio que mostra 10:50.
- O jogador0 vê o desenho do texto.
- Jogador1 vê o desenho do texto.
- Player2 não vê o textdraw.
- Quando a hora mudar, queremos que este desenho mostre a nova hora, e todos os jogadores que estão vendo o desenho verão a hora atualizada.
1.2.1.1 Declaração:
Código:
novo texto: myFancyTD;
Código:
novo Float: myFancyFloat;1.2.1.2 Inicialização:
Também precisamos inicializar a variável com algo, caso contrário, este texto pode entrar em conflito com outros conforme você adiciona mais. Na verdade, é muito importante que você faça isso, caso contrário, o primeiro desenho de texto que você criar funcionará bem, mas quando você adiciona mais e mais, alguns podem começar a mostrar informações de outros e ter algum outro comportamento estranho. É realmente difícil depurar e descobrir onde está o problema, porque o compilador não fornecerá nenhum erro ou aviso. Portanto, não se esqueça de fazer isso.
Código:
novo Texto: myFancyTD = Texto: INVALID_TEXT_DRAW ;
1.2.1.3 Funções:
uma lista das funções pode ser encontrada aqui . Observe que todos eles têm 'TextDraw' em seus nomes. Você não pode usar uma função de desenho de texto global em um desenho de texto por jogador, ou vice-versa. Caso contrário, o compilador lhe dará um aviso de incompatibilidade de tag.
1.2.2 Textdraw por jogador:
Um textdraw por jogador é único para cada jogador, por exemplo, a velocidade de seu veículo. Isso significa que cada jogador pode ver o textdraw com informações pessoais ou não pode ver o textdraw. Você pode criar 256 desenhos de texto por jogador para cada jogador! Isso é muito mais do que apenas 2.048 globais.
Exemplo:
- Temos um desenho de texto de pontuação que mostra a pontuação do jogador.
- O jogador0 tem pontuação 50, então seu desenho de texto precisa mostrar 50.
- O jogador1 tem pontuação 100, então seu desenho de texto precisa mostrar 100.
- Jogador2 não vê seu desenho de texto.
- Quando a pontuação de player0 muda, queremos apenas que seu textdraw mude, não os textdraws de outros jogadores.
1.2.2.1 Declaração:
Código:
novo PlayerText: myFancyTD [MAX_PLAYERS] ;
1.2.2.2 Inicialização:
Novamente, precisamos inicializar a variável com algo para evitar conflitos. Desta vez, precisamos inicializar todos os elementos do array. Isso pode ser feito com a sintaxe {, ...}.
Código:
novo PlayerText: myFancyTD [MAX_PLAYERS] = {PlayerText: INVALID_TEXT_DRAW, ...} ;
1.2.2.3 Funções:
uma lista das funções pode ser encontrada aqui . Observe que todos eles têm 'PlayerTextDraw' em seus nomes, não apenas 'TextDraw'! Novamente, você não pode usar uma função de desenho de texto global em um desenho de texto por jogador, ou vice-versa. Caso contrário, o compilador lhe dará um aviso de incompatibilidade de tag.
1.3 Ferramenta para simplificar a criação de textdraws:
Uma vez que textdraws só podem ser criados com código, pode ser muito difícil fazer algumas coisas certas. Então, para desenvolver seus textdraws visualmente, existe uma ferramenta útil por adri1. Continue lendo por enquanto, você pode brincar com essa ferramenta mais tarde, quando entender como tudo funciona.
2. Declarando e inicializando as variáveis necessárias:
Estaremos usando os dois tipos de textdraws neste tutorial. Textdraws globais serão usados para criar uma interface de usuário de boa aparência. Eles definitivamente não são necessários para fazer o velocímetro funcionar, mas eu queria mostrar os dois tipos de desenho de texto. Os textdraws por jogador serão usados para mostrar as informações pessoais. Se você não entender o que alguns dos códigos a seguir fazem, volte para 1.
O código a seguir deve ser colocado no topo do seu script, em includes e define.
2.1 Variáveis globais de textdraw:
Precisamos de 5 textdraws globais: 4 linhas pretas e 1 fundo transparente (veja a imagem). As linhas pretas e o fundo são iguais para todos os jogadores, então é por isso que podemos usar textdraws globais aqui.
Código:
novo Texto: SpeedoBackground = Texto: INVALID_TEXT_DRAW; novo Texto: SpeedoLineAbove = Texto: INVALID_TEXT_DRAW; novo Texto: SpeedoLineLeft = Texto: INVALID_TEXT_DRAW; novo Texto: SpeedoLineRight = Texto: INVALID_TEXT_DRAW; novo Texto: SpeedoLineUnder = Texto: INVALID_TEXT_DRAW;
Precisamos de um desenho de texto por jogador, que contém as informações sobre o veículo em que o jogador está (veja a imagem).
Código:
novo PlayerText: SpeedoCarInfo [MAX_PLAYERS] = { PlayerText: INVALID_TEXT_DRAW, ...};
Também precisamos controlar se o velocímetro é mostrado a um jogador. Por exemplo, não precisamos ocultá-lo quando já estiver oculto. Portanto, precisamos de um array de bools e, portanto, da tag 'bool'. Também usamos a inicialização de array para inicializar cada elemento do array.
Código:
novo bool: SpeedoShown [MAX_PLAYERS] = {false, ...};
Por fim, precisamos de um cronômetro que funcione para todos os jogadores. Não há necessidade de usar um cronômetro para cada jogador.
Código:
novo SpeedoStatusTimer = -1;Não vou explicar as funções e parâmetros, pois este tutorial já é mais longo do que eu queria e não é um tutorial sobre textdraws ou timers. Consulte o wiki para saber o que cada função faz.
3.1 Textdraws globais:
Como os textdraws globais são iguais para todos os jogadores, só precisamos criá-los uma vez. Faremos isso quando o servidor iniciar, mais especificamente, em OnGameModeInit. Todas as funções têm 'TextDraw' em seus nomes, não 'PlayerTextDraw'!
3.1.1 OnGameModeInit:
Nenhum dos textdraws globais tem texto. Podemos criar um desenho de texto sem texto usando um sublinhado como texto. Podemos tornar uma caixa de desenho de texto transparente usando os valores alfa da cor.
Código:
SpeedoBackground = TextDrawCreate (481.0,353.0, "_" ); //Nenhum texto TextDrawUseBox (SpeedoBackground, 1); TextDrawBoxColor (SpeedoBackground, 0x000000 33 ); // 20% visível, muito transparente TextDrawTextSize (SpeedoBackground, 596.0,0.0); TextDrawAlignment (SpeedoBackground, 0); TextDrawBackgroundColor (SpeedoBackground, 0x000000ff); TextDrawFont (SpeedoBackground, 3); TextDrawLetterSize (SpeedoBackground, 1.0,9.5); TextDrawColor (SpeedoBackground, 0xffffffff); TextDrawSetOutline (SpeedoBackground, 1); TextDrawSetProportional (SpeedoBackground, 1); TextDrawSetShadow (SpeedoBackground, 1); SpeedoLineAbove = TextDrawCreate (481.0,353.0, "_" ); //Nenhum texto TextDrawUseBox (SpeedoLineAbove, 1); TextDrawBoxColor (SpeedoLineAbove, 0x000000 ff ); // 100% visível, tão sólido TextDrawTextSize (SpeedoLineAbove, 596.0,0.0); TextDrawAlignment (SpeedoLineAbove, 0); TextDrawBackgroundColor (SpeedoLineAbove, 0x000000ff); TextDrawFont (SpeedoLineAbove, 3); TextDrawLetterSize (SpeedoLineAbove, 1.0, -0,10); TextDrawColor (SpeedoLineAbove, 0xffffffff); TextDrawSetOutline (SpeedoLineAbove, 1); TextDrawSetProportional (SpeedoLineAbove, 1); TextDrawSetShadow (SpeedoLineAbove, 1); SpeedoLineLeft = TextDrawCreate (481.0,353.0, "_" ); //Nenhum texto TextDrawUseBox (SpeedoLineLeft, 1); TextDrawBoxColor (SpeedoLineLeft, 0x000000 ff ); // 100% visível, tão sólido TextDrawTextSize (SpeedoLineLeft, 480.0,0.0); TextDrawAlignment (SpeedoLineLeft, 0); TextDrawBackgroundColor (SpeedoLineLeft, 0x000000ff); TextDrawFont (SpeedoLineLeft, 3); TextDrawLetterSize (SpeedoLineLeft, 1.0,9.50); TextDrawColor (SpeedoLineLeft, 0xffffffff); TextDrawSetOutline (SpeedoLineLeft, 1); TextDrawSetProportional (SpeedoLineLeft, 1); TextDrawSetShadow (SpeedoLineLeft, 1); SpeedoLineRight = TextDrawCreate (597.0,353.0, "_" ); //Nenhum texto TextDrawUseBox (SpeedoLineRight, 1); TextDrawBoxColor (SpeedoLineRight, 0x000000 ff ); // 100% visível, tão sólido TextDrawTextSize (SpeedoLineRight, 596.0,0.0); TextDrawAlignment (SpeedoLineRight, 0); TextDrawBackgroundColor (SpeedoLineRight, 0x000000ff); TextDrawFont (SpeedoLineRight, 3); TextDrawLetterSize (SpeedoLineRight, 1.0,9.50); TextDrawColor (SpeedoLineRight, 0xffffffff); TextDrawSetOutline (SpeedoLineRight, 1); TextDrawSetProportional (SpeedoLineRight, 1); TextDrawSetShadow (SpeedoLineRight, 1); SpeedoLineUnder = TextDrawCreate (481.0,440.0, "_" ); //Nenhum texto TextDrawUseBox (SpeedoLineUnder, 1); TextDrawBoxColor (SpeedoLineUnder, 0x000000 ff ); // 100% visível, tão sólido TextDrawTextSize (SpeedoLineUnder, 596.0,0.0); TextDrawAlignment (SpeedoLineUnder, 0); TextDrawBackgroundColor (SpeedoLineUnder, 0x000000ff); TextDrawFont (SpeedoLineUnder, 3); TextDrawLetterSize (SpeedoLineUnder, 1.0, -0,10); TextDrawColor (SpeedoLineUnder, 0xffffffff); TextDrawSetOutline (SpeedoLineUnder, 1); TextDrawSetProportional (SpeedoLineUnder, 1); TextDrawSetShadow (SpeedoLineUnder, 1);
É sempre bom limpar tudo, especialmente quando você usa o comando '/ rcon gmx'. Destrua os textdraws globais e redefina as variáveis.
Código:
TextDrawDestroy (SpeedoBackground); TextDrawDestroy (SpeedoLineAbove); TextDrawDestroy (SpeedoLineLeft); TextDrawDestroy (SpeedoLineRight); TextDrawDestroy (SpeedoLineUnder); SpeedoBackground = Texto: INVALID_TEXT_DRAW; SpeedoLineAbove = Texto: INVALID_TEXT_DRAW; SpeedoLineLeft = Texto: INVALID_TEXT_DRAW; SpeedoLineRight = Texto: INVALID_TEXT_DRAW; SpeedoLineUnder = Texto: INVALID_TEXT_DRAW;
Como os textdraws por jogador são únicos para cada jogador e são automaticamente destruídos em OnPlayerDisconnect (veja wiki), precisamos criá-los toda vez que um jogador entrar. Então, isso está em OnPlayerConnect. Todas as funções têm 'PlayerTextDraw' em seus nomes, não apenas 'TextDraw'!
3.2.1 OnPlayerConnect:
Este desenho de texto conterá texto, mas não no início, então apenas fornecemos uma string vazia com o sublinhado enquanto isso. Observe que, por algum motivo, precisamos criar um textdraw por jogador com CreatePlayerTextDraw em vez de PlayerTextDrawCreate. Todas as outras funções têm 'PlayerTextDraw' na frente. Visto que 'SpeedoCarInfo' é um array de textdraws por jogador, precisamos fornecer qual elemento do array estamos usando em cada função. Por fim, há também um parâmetro adicional de que precisamos em cada função, para saber de qual player estamos falando. Se você não entende isso, continue lendo.
Código:
SpeedoCarInfo [playerid] = CreatePlayerTextDraw (playerid, 485.0, 355.0, "_" ); // Sem texto PlayerTextDrawBackgroundColor (playerid, SpeedoCarInfo [playerid] , 0x000000ff); PlayerTextDrawAlignment (playerid, SpeedoCarInfo [playerid] , 0); PlayerTextDrawFont (playerid, SpeedoCarInfo [playerid] , 1); PlayerTextDrawLetterSize (playerid, SpeedoCarInfo [playerid] , 0,30, 1,0); PlayerTextDrawColor (playerid, SpeedoCarInfo [playerid] , 0xffffffff); PlayerTextDrawSetOutline (playerid, SpeedoCarInfo [playerid] , 1); PlayerTextDrawSetProportional (playerid, SpeedoCarInfo [playerid] , 1); PlayerTextDrawSetShadow (playerid, SpeedoCarInfo [playerid] , 1);
Código:
TextDrawFont (SpeedoBackground, 3); // Textdraw global PlayerTextDrawFont ( playerid , SpeedoCarInfo [playerid] , 1); // Textdraw por jogador
Quando você usa 'SpeedoCarInfo [playerid]', está usando uma variável do tipo PlayerText. Quando você usa 'playerid', você está usando uma variável do tipo Integer. Lembra que um textdraw por jogador é único para cada jogador? Em outras palavras, ele está vinculado a esse jogador. Portanto, o parâmetro 'playerid' é necessário para saber a qual jogador o textdraw pertence e o 'SpeedoCarInfo [playerid]' é necessário para saber a qual textdraw desse jogador nos referimos. Aqui está outra explicação:
- SpeedoCarInfo é um array.
- Cada elemento da matriz contém um desenho de texto PlayerText.
- Portanto, a matriz é do tipo PlayerText.
- Para acessar um elemento da matriz, usamos um índice.
- Um índice é um número inteiro.
- Escolhemos um sistema lógico no qual o textdraw do jogador com ID 0 está localizado na matriz no elemento com índice 0.
3.2.2 OnPlayerDisconnect:
Destrua o textdraw por jogador e redefina a variável.
Código:
PlayerTextDrawDestroy (playerid, SpeedoCarInfo [playerid] ); SpeedoCarInfo [playerid] = PlayerText: INVALID_TEXT_DRAW;
3.3 Variável Bool:
Precisamos zerar a variável quando um jogador entra, pois o velocímetro não é mostrado naquele momento.
3.3.1 OnPlayerConnect:
Inicialize a variável quando o jogador se conectar.
Código:
SpeedoShown [playerid] = false;Redefina a variável quando o player se desconecta.
Código:
SpeedoShown [playerid] = false;3.4 Variável do temporizador:
Temos um temporizador global que deve ser executado sempre.
3.4.1 OnGameModeInit:
Inicia um cronômetro que deve marcar uma vez a cada décimo de segundo (que é definitivamente rápido o suficiente) e que deve se repetir para sempre. Não precisamos de parâmetros de temporizador, pois faremos um loop por todos os jogadores.
Código:
SpeedoStatusTimer = SetTimer ( "SpeedoStatus" , 100, 1); // O nome da função que usaremos mais tarde
Mate o cronômetro e redefina a variável.
Código:
KillTimer (SpeedoStatusTimer); SpeedoStatusTimer = -1;
Agora, finalmente, no que estamos trabalhando. O cronômetro que controlará tudo.
O código a seguir deve ser colocado em algum lugar do seu script. Eu sempre coloco no fundo. Mas isso realmente não importa.
4.1 Encaminhamento e implementação:
Temos um temporizador que chama uma função sem parâmetros. Portanto, precisamos usar parênteses vazios. Como sempre acontece com funções públicas, você também precisa encaminhar.
Código:
SpeedoStatus para a frente () ; // Lembra-se deste nome e nenhum parâmetro de 3.4.1? public SpeedoStatus () { // Mesmo nome e parâmetros como forward // Loop (consulte a próxima parte) }
Uma vez que este temporizador irá controlar todos os jogadores, precisamos usar um loop. Não precisamos fazer nada se o player não estiver online, então não se esqueça de incluir a marca 'IsPlayerConnected'.
Código:
for (new playerid = 0, higherPlayerid = GetPlayerPoolSize (); playerid <= higherPlayerid; playerid ++) { if (IsPlayerConnected (playerid)) { // Na verificação do veículo (veja a próxima parte) } }
Não use o seguinte.
Código:
para (novo playerid = 0; playerid <MAX_PLAYERS; playerid ++) { if (IsPlayerConnected (playerid)) { } }
Também não use o seguinte.
Código:
for (new playerid = 0; playerid <= GetPlayerPoolSize (); playerid ++) { if (IsPlayerConnected (playerid)) { } }
4.3 Verificar se o jogador está em um veículo:
Se o jogador não estiver em um veículo, precisamos ocultar o velocímetro, caso contrário, precisamos mostrá-lo.
Código:
if (IsPlayerInAnyVehicle (playerid)) { // Verificação não mostrada (consulte a próxima parte) } senão { // Verificação exibida (veja a próxima parte) }
Só precisamos mostrar o velocímetro quando ele ainda não for mostrado. Mas precisamos atualizar o conteúdo sempre, então isso deve estar fora da verificação. Não se esqueça de colocar o booleano em true, o que nos permite saber que o velocímetro agora é mostrado.
Código:
if (! SpeedoShown [playerid]) { // Mostrar (veja a próxima parte) SpeedoShown [playerid] = verdadeiro; } // Atualize o conteúdo (explicado no final)
Só precisamos ocultar o velocímetro quando ainda não estiver oculto. Não se esqueça de colocar o booleano em falso, o que nos permite saber que o velocímetro agora está oculto.
Código:
if (SpeedoShown [playerid]) { // Ocultar (veja a próxima parte) SpeedoShown [playerid] = false; }
Mostrar os desenhos de texto globais e por jogador.
Código:
TextDrawShowForPlayer (playerid, SpeedoLineAbove); TextDrawShowForPlayer (playerid, SpeedoLineLeft); TextDrawShowForPlayer (playerid, SpeedoLineRight); TextDrawShowForPlayer (playerid, SpeedoLineUnder); TextDrawShowForPlayer (playerid, SpeedoBackground); PlayerTextDrawShow (playerid, SpeedoCarInfo [playerid]);
Oculte os desenhos de texto globais e por jogador.
Código:
TextDrawHideForPlayer (playerid, SpeedoLineAbove); TextDrawHideForPlayer (playerid, SpeedoLineLeft); TextDrawHideForPlayer (playerid, SpeedoLineRight); TextDrawHideForPlayer (playerid, SpeedoLineUnder); TextDrawHideForPlayer (playerid, SpeedoBackground); PlayerTextDrawHide (playerid, SpeedoCarInfo [playerid]);
Finalmente o próprio conteúdo.
Código:
// Precisamos saber em qual veículo o jogador está novo Vehicleid = GetPlayerVehicleID (playerid); // Precisamos saber qual é a velocidade desse veículo novo Float: VelX, Float: VelY, Float: VelZ; GetVehicleVelocity (Vehicleid, VelX, VelY, VelZ); // Fazemos alguns cálculos com esses valores, vamos a este tópico para obter mais informações novo flutuador: velocidade; Velocidade = (floatsqroot (((VelX * VelX) + (VelY * VelY)) + (VelZ * VelZ)) * 181,5); // Coloque as informações em uma string nova String [8+ 1]; format (String, sizeof (String), "% ikm / h", floatround (Speed, floatround_floor)); // floatround arredonda o float para um inteiro // Coloque a string no textdraw PlayerTextDrawSetString (playerid, SpeedoCarInfo [playerid], String);

0 Comentários