Thinking: Difference between revisions

From Valve Developer Community
Jump to navigation Jump to search
m (→‎top: Unicodifying, replaced: [[Image: → [[File:)
(Eu traduzi tudo, mas pode ter alguns erros... eu nao sou muito bom em ver ce tem)
Line 2: Line 2:
[[File:Entity init.png|right|130px|The Source engine entity initialization process.]]
[[File:Entity init.png|right|130px|The Source engine entity initialization process.]]


'''Think functions''' allow entities to schedule code to be run in the future. By constantly rescheduling thinks, automated loops can be created that make an entity autonomous.
'''Think functions''' permitem entidades preparar código para ser feito no futuro. Quando você reagendar os ''Thinks'', loops automáticos podem ser criados para fazer a entidade fazer as funções automaticamente
{{clr}}
{{clr}}
== Scheduling ==
== Preparando ==
<code>SetNextThink()</code> is used to configure when an entity should next think. It accepts a [[float]] value.
<code>SetNextThink()</code> é usado para poder configurar quando a entidade deve executar a próxima função ''think'' . O código aceita valores com virgula.


<source lang=cpp>
<source lang=cpp>
Line 11: Line 11:
{
{
BaseClass::Spawn();
BaseClass::Spawn();
SetNextThink( gpGlobals->curtime ); // Think now
SetNextThink( gpGlobals->curtime ); // Faça o think agora
}
}


void CMyEntity::Think()
void CMyEntity::Think()
{
{
BaseClass::Think(); // Always do this if you override Think()
BaseClass::Think(); //Sempre faça isso se você substituir Think()!


Msg( "I think, therefore I am.\n" );
Msg( "Penso ,logo existo.\n" );
SetNextThink( gpGlobals->curtime + 1 ); // Think again in 1 second
SetNextThink( gpGlobals->curtime + 1 ); // Execute o '' think'' depois de 1 segundo!
}
}
</source>
</source>


Notice the use of <tt>gpGlobals->curtime</tt> to make the value passed relative to the time of execution.
Olhe o uso de <tt>gpGlobals->curtime</tt> para fazer com que o valor passado seja relativo ao tempo de execução.
{{tip|<code>SetNextThink(-1)</code> will cancel any future thinks. This is better than <tt>SetNextThink(NULL)</tt>, because <tt>TICK_NEVER_THINK</tt> is -1.}}
{{tip|<code>SetNextThink(-1)</code> ira cancelar qualquer '' think ''futuro! . É melhor usar esse comparado ao<tt>SetNextThink(NULL)</tt>, pois o<tt>TICK_NEVER_THINK</tt> é -1.}}


== New Think Functions ==
== Novas Think Functions ==
An entity can have any number of additional think functions. To register a new one:
Uma entidade pode ter inúmeras ''think functions'' adicionas. Para fazer uma nova:
# Ensure the function is <tt>void</tt>.
# Tenha certeza que a função é do tipo<tt>void</tt>.
# Add it to the entity's [[DATADESC]] with <tt>DEFINE_THINKFUNC()</tt>.
# Adicione ela para a [[DATADESC]] da entidade, usando <tt>DEFINE_THINKFUNC()</tt>!.
# Call <code>SetThink()</code> and pass a pointer to the function (see example below).
# Chame <code>SetThink()</code> e passe o pointer para a função! (olhe o exemplo abaixo).
# Ensure <code>DECLARE_DATADESC();</code> is in your class.
# Tenha certeza que <code>DECLARE_DATADESC();</code> esta em sua classe!


<source lang=cpp>
<source lang=cpp>
BEGIN_DATADESC( CMyEntity )
BEGIN_DATADESC( CMyEntity )
DEFINE_THINKFUNC( MyThink ), // Register new think function
DEFINE_THINKFUNC( MyThink ), // Registre uma nova função
END_DATADESC()
END_DATADESC()


Line 41: Line 41:
{
{
BaseClass::Spawn();
BaseClass::Spawn();
SetThink( &CMyEntity::MyThink ); // Pass a function pointer
SetThink( &CMyEntity::MyThink ); // Passe o pointer da função
SetNextThink(gpGlobals->curtime);
SetNextThink(gpGlobals->curtime);
}
}
Line 47: Line 47:
void CMyEntity::MyThink()
void CMyEntity::MyThink()
{
{
Msg( "I think, therefore I am.\n" );
Msg( "Penso,logo existo.\n" );
SetNextThink( gpGlobals->curtime + 1 );
SetNextThink( gpGlobals->curtime + 1 );
}
}
</source>
</source>


Splitting your think code into different functions makes it easy to switch an entity between modes of operation.
Devindo seu codigos entre outras funções que estão sendo usado para o ''think'' deixa mais fácil trocar entre modos de operação!
{{tip|<code>SetThink()</code> can be called from within a think function, too. The next call will be to the new function.}}
{{tip|<code>SetThink()</code> pode ser chamado dentro de uma função ''think'' também. A próxima chamado será na nova função.}}


== Using Contexts ==
== Usando contexto ==
It is possible to schedule any number of think functions side-by-side with "think contexts." To create a new context:
É possível agendar qualquer número de funções de pensamento lado a lado com "contextos de thinks". Para criar um novo contexto:
# Call <code>RegisterThinkContext([[string]] ContextName)</code>
# Chame <code>RegisterThinkContext([[string]] NomeDoContexto)</code>
# Call <code>SetContextThink([[void]]* Function, float NextThinkTime, string ContextName)</code>
# Use< code>SetContextThink([[void]]* Function, float NextThinkTime, string NomeDoContexto)</code>
# For subsequent thinks, call <code>SetNextThink(float NextThinkTime, string ContextName)</code>
# For subsequent thinks, call <code>SetNextThink(float NextThinkTime, string NomeDoContexto)</code>


<source lang=cpp>
<source lang=cpp>
Line 68: Line 68:
void CMyEntity::Spawn()
void CMyEntity::Spawn()
{
{
SetNextThink( gpGlobals->curtime ); // Default think loop - no context
SetNextThink( gpGlobals->curtime ); //Loop de pensamento padrão - sem contexto
RegisterThinkContext( "TestContext" );
RegisterThinkContext( "TestContext" );
SetContextThink( &CMyEntity::ContextThink, gpGlobals->curtime, "TestContext" );
SetContextThink( &CMyEntity::ContextThink, gpGlobals->curtime, "ContextoTest" );
}
}


Line 89: Line 89:
</source>
</source>


This creates two simultaneous think loops, both writing to the console at different rates.
Isso cria dois loops de pensamento simultâneos, ambos gravando no console em taxas diferentes.
{{tip|Creating a new context is a great way to delay function calls to the future without upsetting existing think loops.}}
{{tip|Criar um novo contexto é uma ótima maneira de atrasar chamadas de função para o futuro sem perturbar os ciclos de pensamento existentes.}}
 
== Utilidades ==


== Utilities ==
These should be self-explanatory:


<source lang=cpp>
<source lang=cpp>
float GetLastThink()
float GetLastThink() // Pegamos o ultimo ''think'' que foi executado
float GetNextThink()
float GetNextThink() // Pegamos o proximo ''think''  a ser executado
int GetLastThinkTick()
int GetLastThinkTick() //Pegamos o ultimo ''tick'' do ultimo ''think'' que foi executado
int GetNextThinkTick()
int GetNextThinkTick() // Pegamos o proximo ''tick'' do próximo ''think'' a ser executado
</source>
</source>


[[File:Barnacle.jpg|right|50px|link=npc_barnacle]]
[[File:Barnacle.jpg|right|50px|link=npc_barnacle]]


The <code>GetLast</code> functions are useful for controlling the rate at which something occurs.  
As funções <code>GetLast</code> são úteis para controlar a taxa com que algo ocorre.
This think code from {{ent|npc_barnacle}} modulates the speed of tongue movement, even if the frequency of thinking changes:
Este código de pensamento de {{ent|npc_barnacle}} modula a velocidade do movimento da língua, mesmo que a frequência do pensamento mude:
<source lang=cpp>


<source lang=cpp>
float dt = gpGlobals->curtime - GetLastThink(); // dt é "delta time"
float dt = gpGlobals->curtime - GetLastThink(); // dt is "delta time"
SetAltitude( m_flAltitude + m_flBarnaclePullSpeed * dt ); // Mudamos a altitude de sua língua!
SetAltitude( m_flAltitude + m_flBarnaclePullSpeed * dt ); // Change tongue altitude
</source>
</source>


For its non-[[skeletal]] animation to be smooth, this code would need to be executed every frame. This is exactly what happens, until the barnacle is no longer in the player's [[PVS]] and the rate is slowed down—thus requiring the above code.
Para que sua animação não [[esquelética]] seja suave, esse código precisaria ser executado a cada quadro. Isso é exatamente o que acontece, até que a craca não esteja mais no [[PVS]] do jogador e a taxa diminua - exigindo assim o código acima.


==<tt>ClientThink()</tt>==
==<tt>ClientThink()</tt>==
Thinking can also occur on the client, but its effects are limited. Only one think function is supported for each entity.
''Thinking'' também pode acontecer no cliente, mas os efeitos são limitados!. Apenas podemos usar 1 função para cada entidade.


  <span style="color:blue;">void</span> C_MyEntity::ClientThink()
  <span style="color:blue;">void</span> C_MyEntity::ClientThink()
  {
  {
  Msg( <span style="color:brown;">"Don't put anything [[expensive]] in this function!\n"</span> );
  Msg( <span style="color:brown;">"NÃO COLOQUE NADA [[PESADO]] NESSAFUNÇÃO!\n"</span> );
  SetNextClientThink( CLIENT_THINK_ALWAYS ); <span style="color:green;">// Think every frame</span>
  SetNextClientThink( CLIENT_THINK_ALWAYS ); <span style="color:green;">/ ''Think'' é executado todo frame</span>
  }
  }


Some examples of client-side thinking are:
Alguns exemplos de ''client-side'' thinking são:


* Visual effects / particles
* Efeitos visuais/partículas
* VGUI screen interaction
* Interação com VGUI
* Modifying player speed (done on the client as well as server to avoid [[prediction]] errors)
* Modificação da velocidade do jogador (feita tanto no cliente quanto no servidor para evitar erros de [[predição]])
* Striders’ legs snapping ropes (disabled by default)
* Pernas dos Peregrinos quebrando cordas (desativado por padrão)


<code>SetNextClientThink()</code> is used to schedule <code>ClientThink()</code>. There are two special values it accepts:
<code>SetNextClientThink()</code> é usado para agendar <code>ClientThink()</code>. Existem dois valores especiais que ele aceita:


; <tt>CLIENT_THINK_ALWAYS</tt>: Think on the client once every frame. Use with caution! {{tip|Use <code>gpGlobals->frametime</code> to regulate speed.}}
; <tt>CLIENT_THINK_ALWAYS</tt>: Pense no cliente uma vez a cada frame. Use com cuidado! {{tip|Use <code>gpGlobals->frametime</code> para regular a velocidade.}}
; <tt>CLIENT_THINK_NEVER</tt>: Pause all automated client thinking.
; <tt>CLIENT_THINK_NEVER</tt>: pause todo o pensamento automatizado do cliente.

Revision as of 08:21, 16 January 2024

English (en)Deutsch (de)Español (es)Português do Brasil (pt-br)Русский (ru)Translate (Translate)
The Source engine entity initialization process.

Think functions permitem entidades preparar código para ser feito no futuro. Quando você reagendar os Thinks, loops automáticos podem ser criados para fazer a entidade fazer as funções automaticamente

Preparando

SetNextThink() é usado para poder configurar quando a entidade deve executar a próxima função think . O código aceita valores com virgula.

void CMyEntity::Spawn()
{
	BaseClass::Spawn();
	SetNextThink( gpGlobals->curtime ); // Faça o think agora
}

void CMyEntity::Think()
{
	BaseClass::Think(); //Sempre faça isso se você substituir Think()!

	Msg( "Penso ,logo existo.\n" );
	SetNextThink( gpGlobals->curtime + 1 ); // Execute o '' think'' depois de 1 segundo!
}

Olhe o uso de gpGlobals->curtime para fazer com que o valor passado seja relativo ao tempo de execução.

Tip.pngTip:SetNextThink(-1) ira cancelar qualquer think futuro! . É melhor usar esse comparado aoSetNextThink(NULL), pois oTICK_NEVER_THINK é -1.

Novas Think Functions

Uma entidade pode ter inúmeras think functions adicionas. Para fazer uma nova:

  1. Tenha certeza que a função é do tipovoid.
  2. Adicione ela para a DATADESC da entidade, usando DEFINE_THINKFUNC()!.
  3. Chame SetThink() e passe o pointer para a função! (olhe o exemplo abaixo).
  4. Tenha certeza que DECLARE_DATADESC(); esta em sua classe!
BEGIN_DATADESC( CMyEntity )
	DEFINE_THINKFUNC( MyThink ), // Registre uma nova função 
END_DATADESC()

void CMyEntity::Spawn()
{
	BaseClass::Spawn();
	SetThink( &CMyEntity::MyThink ); // Passe o pointer da função
	SetNextThink(gpGlobals->curtime);
}

void CMyEntity::MyThink()
{
	Msg( "Penso,logo existo.\n" );
	SetNextThink( gpGlobals->curtime + 1 );
}

Devindo seu codigos entre outras funções que estão sendo usado para o think deixa mais fácil trocar entre modos de operação!

Tip.pngTip:SetThink() pode ser chamado dentro de uma função think também. A próxima chamado será na nova função.

Usando contexto

É possível agendar qualquer número de funções de pensamento lado a lado com "contextos de thinks". Para criar um novo contexto:

  1. Chame RegisterThinkContext(string NomeDoContexto)
  2. Use< code>SetContextThink(void* Function, float NextThinkTime, string NomeDoContexto)
  3. For subsequent thinks, call SetNextThink(float NextThinkTime, string NomeDoContexto)
BEGIN_DATADESC( CMyEntity )
	DEFINE_THINKFUNC( ContextThink ),
END_DATADESC()

void CMyEntity::Spawn()
{
	SetNextThink( gpGlobals->curtime ); //Loop de pensamento padrão - sem contexto
	
	RegisterThinkContext( "TestContext" );
	SetContextThink( &CMyEntity::ContextThink, gpGlobals->curtime, "ContextoTest" );
}

void CMyEntity::Think()
{
	BaseClass::Think();

	Msg( "Think\n" );
	SetNextThink( gpGlobals->curtime + .1 );
}

void CMyEntity::ContextThink()
{
	Msg( "Context think\n" );
	SetNextThink(gpGlobals->curtime + .2, "TestContext" );
}

Isso cria dois loops de pensamento simultâneos, ambos gravando no console em taxas diferentes.

Tip.pngTip:Criar um novo contexto é uma ótima maneira de atrasar chamadas de função para o futuro sem perturbar os ciclos de pensamento existentes.

Utilidades

float	GetLastThink() // Pegamos o ultimo ''think'' que foi executado
float	GetNextThink() // Pegamos o proximo ''think''  a ser executado
int	GetLastThinkTick() //Pegamos o ultimo ''tick'' do ultimo ''think'' que foi executado
int	GetNextThinkTick() // Pegamos o proximo ''tick'' do próximo ''think'' a ser executado
Barnacle.jpg

As funções GetLast são úteis para controlar a taxa com que algo ocorre. Este código de pensamento de npc_barnacle modula a velocidade do movimento da língua, mesmo que a frequência do pensamento mude:

float dt = gpGlobals->curtime - GetLastThink(); // dt é "delta time"
SetAltitude( m_flAltitude + m_flBarnaclePullSpeed * dt ); // Mudamos a altitude de sua língua!

Para que sua animação não esquelética seja suave, esse código precisaria ser executado a cada quadro. Isso é exatamente o que acontece, até que a craca não esteja mais no PVS do jogador e a taxa diminua - exigindo assim o código acima.

ClientThink()

Thinking também pode acontecer no cliente, mas os efeitos são limitados!. Apenas podemos usar 1 função para cada entidade.

void C_MyEntity::ClientThink()
{
	Msg( "NÃO COLOQUE NADA PESADO NESSAFUNÇÃO!\n" );
	SetNextClientThink( CLIENT_THINK_ALWAYS ); / Think é executado todo frame
}

Alguns exemplos de client-side thinking são:

  • Efeitos visuais/partículas
  • Interação com VGUI
  • Modificação da velocidade do jogador (feita tanto no cliente quanto no servidor para evitar erros de predição)
  • Pernas dos Peregrinos quebrando cordas (desativado por padrão)

SetNextClientThink() é usado para agendar ClientThink(). Existem dois valores especiais que ele aceita:

CLIENT_THINK_ALWAYS
Pense no cliente uma vez a cada frame. Use com cuidado!
Tip.pngTip:Use gpGlobals->frametime para regular a velocidade.
CLIENT_THINK_NEVER
pause todo o pensamento automatizado do cliente.