FANDOM

1.062 Páginas

Histeresis de la Cara

El error demostrado en MAP30: Icon of Sin

Cuando la salud del jugador cambia entre los rangos correspondientes a las seis diferentes animaciones de la Cara de la barra de estado, los cambios porcentuales de salud en la barra aparecen de inmediato, pero el propio rostro no se actualiza hasta alcanzar el final de la secuencia de animación que esté realizando en ese momento.

Por ejemplo, si un jugador que está gravemente herido con su nivel de salud por debajo del 20%, obtiene una nueva arma, seguido inmediatamente por una recolección grande de salud tal como sucede al obtener una megaesfera, la barra de estado muestra durante un lapso muy breve un porcentaje muy elevado de la salud junto con una cara muy ensangrentada, tal como como se muestra en la captura de pantalla.

Aspectos técnicos

El fenómeno se debe a que el motor elige la siguiente gráfica para la Cara de acuerdo con una jerarquía estricta, y luego trata de evitar la actualización de la cara de nuevo hasta haber pasado un cierto número de tics.

De st_stuff.c:

   #define ST_EVILGRINCOUNT                (2*TICRATE)
   #define ST_STRAIGHTFACECOUNT            (TICRATE/2)
   #define ST_TURNCOUNT                    (1*TICRATE)
   #define ST_OUCHCOUNT                    (1*TICRATE)
   #define ST_RAMPAGEDELAY                 (2*TICRATE)
   void ST_updateFaceWidget(void)        
   {        
       int                i;        
       angle_t            badguyangle;        
       angle_t            diffang;        
       static int         lastattackdown = -1;        
       static int         priority = 0;        
       boolean            doevilgrin;        
           
       if (priority < 10)        
       {        
           // dead        
           if (!plyr->health)        
           {        
               priority = 9;        
               st_faceindex = ST_DEADFACE;        
               st_facecount = 1;        
           }        
       }        
           
       if (priority < 9)        
       {        
           if (plyr->bonuscount)        
           {        
               // picking up bonus        
               doevilgrin = false;        
           
               for (i=0;i<NUMWEAPONS;i++)        
               {        
                   if (oldweaponsowned[i] != plyr->weaponowned[i])        
                   {        
                       doevilgrin = true;        
                       oldweaponsowned[i] = plyr->weaponowned[i];        
                   }        
               }        
               if (doevilgrin)         
               {        
                   // evil grin if just picked up weapon        
                   priority = 8;        
                   st_facecount = ST_EVILGRINCOUNT;        
                   st_faceindex = ST_calcPainOffset() + ST_EVILGRINOFFSET;        
               }        
           }        
       }        
             
       if (priority < 8)        
       {        
           if (plyr->damagecount        
               && plyr->attacker        
               && plyr->attacker != plyr->mo)        
           {        
               // being attacked        
               priority = 7;        
                       
               if (plyr->health - st_oldhealth > ST_MUCHPAIN)        
               {        
                   st_facecount = ST_TURNCOUNT;        
                   st_faceindex = ST_calcPainOffset() + ST_OUCHOFFSET;        
               }        
               else        
               {        
                   badguyangle = R_PointToAngle2(plyr->mo->x,        
                                                 plyr->mo->y,        
                                                 plyr->attacker->x,        
                                                 plyr->attacker->y);        
                           
                   if (badguyangle > plyr->mo->angle)        
                   {        
                       // whether right or left        
                       diffang = badguyangle - plyr->mo->angle;        
                       i = diffang > ANG180;         
                   }        
                   else        
                   {        
                       // whether left or right        
                       diffang = plyr->mo->angle - badguyangle;        
                       i = diffang <= ANG180;         
                   } // confusing, aint it?        
           
                           
                   st_facecount = ST_TURNCOUNT;        
                   st_faceindex = ST_calcPainOffset();        
                           
                   if (diffang < ANG45)        
                   {        
                       // head-on            
                       st_faceindex += ST_RAMPAGEOFFSET;        
                   }        
                   else if (i)        
                   {        
                       // turn face right        
                       st_faceindex += ST_TURNOFFSET;        
                   }        
                   else        
                   {        
                       // turn face left        
                       st_faceindex += ST_TURNOFFSET+1;        
                   }        
               }        
           }        
       }        
             
       if (priority < 7)        
       {        
           // getting hurt because of your own damn stupidity        
           if (plyr->damagecount)        
           {        
               if (plyr->health - st_oldhealth > ST_MUCHPAIN)        
               {        
                   priority = 7;        
                   st_facecount = ST_TURNCOUNT;        
                   st_faceindex = ST_calcPainOffset() + ST_OUCHOFFSET;        
               }        
               else        
               {        
                   priority = 6;        
                   st_facecount = ST_TURNCOUNT;        
                   st_faceindex = ST_calcPainOffset() + ST_RAMPAGEOFFSET;        
               }        
           }        
       }        
             
       if (priority < 6)        
       {        
           // rapid firing        
           if (plyr->attackdown)        
           {        
               if (lastattackdown==-1)        
                   lastattackdown = ST_RAMPAGEDELAY;        
               else if (!--lastattackdown)        
               {        
                   priority = 5;        
                   st_faceindex = ST_calcPainOffset() + ST_RAMPAGEOFFSET;        
                   st_facecount = 1;        
                   lastattackdown = 1;        
               }        
           }        
           else        
               lastattackdown = -1;        
       }        
             
       if (priority < 5)        
       {        
           // invulnerability        
           if ((plyr->cheats & CF_GODMODE)        
               || plyr->powers[pw_invulnerability])        
           {        
               priority = 4;        
           
               st_faceindex = ST_GODFACE;        
               st_facecount = 1;        
           }        
       }        
           
       // look left or look right if the facecount has timed out        
       if (!st_facecount)        
       {        
           st_faceindex = ST_calcPainOffset() + (st_randomnumber % 3);        
           st_facecount = ST_STRAIGHTFACECOUNT;        
           priority = 0;        
       }        
           
       st_facecount--;        
           
   }

Cada cambio en el gráfico de la cara aumenta la variable contador st_facecount (en negrita para enfatizar), que luego disminuye en 1 a cada tic. A fin de que la cara pueda ser renovada, st_facecount debe llegar a cero o bien ocurrir un evento en el juego con mayor precedencia; por ejemplo, la muerte del jugador reemplaza una cara sonriente con la cara "muerte" de inmediato.

Algunos tipos de cara, como el valor por defecto "cara adelante" o la cara de invulnerabilidad, se pueden sustituir por un daño o una recolección de armas en la siguiente convocatoria (st_facecount = 1), pero otros permanecen durante medio segundo o así (TICRATE es 35); las recolecciones de salud posteriores, por lo tanto no pueden ser representadas en la cara durante todo ese intervalo.

¡Interferencia de bloqueo de anuncios detectada!


Wikia es un sitio libre de uso que hace dinero de la publicidad. Contamos con una experiencia modificada para los visitantes que utilizan el bloqueo de anuncios

Wikia no es accesible si se han hecho aún más modificaciones. Si se quita el bloqueador de anuncios personalizado, la página cargará como se esperaba.

También en FANDOM

Wiki al azar