home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / C / Games / Arashi 1.1.1 / source code / Game Source / jam src / STPulsar.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-01-13  |  11.7 KB  |  485 lines  |  [TEXT/KAHL]

  1. /*/
  2.      Project Arashi: STPulsar.c
  3.      Major release: Version 1.1d2, 9/5/95
  4.  
  5.      Last modification: Thursday, January 13, 1994, 7:32
  6.      Created: Sunday, February 12, 1989, 22:58
  7.  
  8.      Copyright © 1989-1994, Juri Munkki
  9. /*/
  10.  
  11. #include "VA.h"
  12. #include "STORM.h"
  13. #include "STCrack.h"
  14.  
  15. #define    MAXPULSARS        20
  16. #define    PULSARCOLOR        (ThisLevel.puColor)
  17. #define    PULSARROTSPEED    (ThisLevel.puRot)
  18. #define    PULSARUPSPEED    (ThisLevel.puSpeed)
  19. #define    PULSINGTIME        (ThisLevel.puTime)
  20. #define    NERVOUSNESS        (PULSINGTIME>>2)
  21.  
  22. typedef    struct
  23. {
  24.     int        state;        /*    star=0, inactive=1, active=2        */
  25.     int        pulscounter;/*    While this is >0, pulsar is pulsing.*/
  26.     int        lane;        /*    Actual lane number                    */
  27.     IFixed    level;        /*    Depth level of pulsar                */
  28.     int        vertex;        /*    vertex currently connected to        */
  29.     int        mirror;        /*    Draw mirror image?                    */
  30.     int        rotation;    /*    Current rotation of pulsar            */
  31.     int        direction;    /*    Rotation direction                    */
  32. }    Pulsar,*PulsarPtr;
  33.  
  34. enum    {    star, inactive, active    };    /*    Pulsar states        */
  35.  
  36. Pulsar    *Pulsars;        /*    Pointer to an array of pulsars.        */
  37. int        ActivePulsars;    /*    The number of active pulsars.        */
  38. int        PulsarPower;
  39.  
  40. extern    Player    Hero;    /*    Player status record.                */
  41. extern
  42. EventRecord        Event;    /*    Event record. DEBUG USE ONLY!        */
  43.  
  44. /*
  45. >>    Given a connecting point (cx,cy) and a vector (dx,dy)
  46. >>    a pulsar shape is drawn as quickly as possible.
  47. */
  48. void    DrawPulsar(cx,cy,dx,dy,power)
  49. int        cx,cy,dx,dy,power;
  50. {
  51.     register    int        normx,normy;
  52.     register    int        ex,ey;
  53.     register    int        bx,by;
  54.     
  55.     dx>>=1;
  56.     dy>>=1;
  57.     ex=cx+dx;
  58.     ey=cy+dy;
  59.  
  60.  
  61.     dx -= (power * dx)>>5;
  62.     dy -= (power * dy)>>5;
  63.  
  64.     bx = dx/3;
  65.     by = dy/3;
  66.  
  67.     normx=(-dy*power)>>4;
  68.     normy=( dx*power)>>4;
  69.     
  70.     /* if(normy==0 && normx==0) */ /* Tests for when pulsar is most flat */
  71.         
  72.  
  73.     VA.color=PULSARCOLOR;
  74.     VAMoveTo    (ex+dx,            ey+dy);
  75.     VASafeLineTo(ex+dx-bx+normx,ey+dy-by+normy);
  76.     VASafeLineTo(ex+bx-normx,    ey+by-normy);
  77.     VASafeLineTo(ex+normx,        ey+normy);
  78.     VASafeLineTo(ex-bx-normx,    ey-by-normy);
  79.     VASafeLineTo(ex-dx+bx+normx,ey-dy+by+normy);
  80.     VASafeLineTo(ex-dx,            ey-dy);
  81. }
  82. /*
  83. >>    Create a newborn pulsar. A pulsar appears
  84. >>    as one of the center stars, so the lane or
  85. >>    vertex is decided when the star touches the
  86. >>    playfield. Some of this stuff could just as 
  87. >>    well be done at that time.
  88. */
  89. void    CreateNewPulsar()
  90. {
  91.     register    Pulsar        *thepulsar;
  92.  
  93.     if(ActivePulsars<MAXPULSARS)
  94.     {    thepulsar=Pulsars;
  95.         while(thepulsar->state!=inactive)
  96.         {    thepulsar++;
  97.         }
  98.         thepulsar->state=star;
  99.         thepulsar->lane=0;
  100.         thepulsar->level.f=0;
  101.         thepulsar->level.i=DEPTH;
  102.         thepulsar->mirror=0;
  103.         thepulsar->pulscounter=0;
  104.     
  105.         thepulsar->direction= (VARandom()<0)?PULSARROTSPEED:
  106.                                         -PULSARROTSPEED;
  107.         StarApproach(&(thepulsar->state),PULSARCOLOR);
  108.         ActivePulsars++;
  109.     }
  110. }
  111. /*
  112. >>    This routine creates two pulsars from a destroyed
  113. >>    tanker.
  114. */
  115. void    CreateSplitPulsars(lane,level)
  116. int        lane,level;
  117. {
  118.     register    int            i,delta,nextseg,prevseg;
  119.     register    Pulsar        *thepulsar;
  120.     
  121.     for(i=0;i<2;i++)
  122.     {    if(ActivePulsars<MAXPULSARS)
  123.         {    thepulsar=Pulsars;
  124.             while(thepulsar->state!=inactive)
  125.             {    thepulsar++;
  126.             }
  127.             thepulsar->vertex= lane+i;
  128.             if(thepulsar->vertex>=ww.numsegs)
  129.                 thepulsar->vertex -= ww.numsegs;
  130.  
  131.             thepulsar->state= active;
  132.             thepulsar->level.f=0;
  133.             thepulsar->level.i=level;
  134.             thepulsar->mirror=0;
  135.             thepulsar->pulscounter=0;
  136.                     
  137.             thepulsar->direction= i ? PULSARROTSPEED : -PULSARROTSPEED;
  138.  
  139.             nextseg=NextSeg[thepulsar->vertex];
  140.             prevseg=PrevSeg[thepulsar->vertex];
  141.  
  142.             delta=nextseg-prevseg;
  143.             if(delta<0) delta+=ANGLES;
  144.             
  145.             if(thepulsar->direction < 0)
  146.             {    thepulsar->rotation=NextSeg[thepulsar->vertex]-delta/2;
  147.             }
  148.             else
  149.             {    thepulsar->rotation=PrevSeg[thepulsar->vertex]+delta/2;
  150.             }
  151.  
  152.             thepulsar->lane=LaneSel[thepulsar->vertex][thepulsar->rotation];
  153.  
  154.             ActivePulsars++;
  155.         }
  156.     }
  157. }
  158.  
  159. /*
  160. >>    A pulsar moves by rotating from one vertex
  161. >>    to another. It "grabs" onto the vertex while
  162. >>    rotating, so at times it needs to change
  163. >>    the way it touches. The mirror value is
  164. >>    used for properly drawing the pulsar when
  165. >>    this change happens.
  166. */
  167. void    PulsarSegSkip(thepulsar)
  168. register
  169. PulsarPtr    thepulsar;
  170. {
  171.     thepulsar->rotation+=ANGLES/2;
  172.     if(thepulsar->rotation>=ANGLES)    thepulsar->rotation-=ANGLES;
  173.     thepulsar->mirror= !thepulsar->mirror;
  174.  
  175.     if(thepulsar->level.i==0)
  176.         Hero.lanestat[LaneSel[thepulsar->vertex][thepulsar->rotation]] |= PulsMask;
  177. }
  178.  
  179. /*
  180. >>
  181. */
  182.  
  183. void    DoPulsing(pulsarp)
  184. PulsarPtr    pulsarp;
  185. {
  186.     pulsarp->pulscounter=PULSINGTIME;
  187. }
  188. /*
  189. >>    This routine is called for each active pulsar.
  190. >>    An active pulsar has gone through the star
  191. >>    phase and now rotates and climbs up.
  192. */
  193. void        UpdateActivePulsar(pulsarp)
  194. register
  195. PulsarPtr    pulsarp;
  196. {
  197.     register    int        dx,dy,x,y;
  198.                 int        sc;
  199.                 int        doskip;
  200.  
  201.     pulsarp->level.f-=PULSARUPSPEED;/*    Move up a bit.                            */
  202.     if(pulsarp->level.i<=0)            /*    Don't move past the top.                */
  203.     {    pulsarp->level.i=0;
  204.         ThisLevel.edgeCount++;        /*    Pulsar is on the edge.                    */
  205.     }
  206.  
  207.     y=pulsarp->direction;    /*    I find this ugly, but it needs to be fast.        */
  208.  
  209.     if(pulsarp->pulscounter==0)
  210.     {    x=pulsarp->rotation;/*    x is now the current rotation value.            */
  211.         dx=NextSeg[pulsarp->vertex]-x;    /*    Find next clockwise vertex angle.    */
  212.         dy=PrevSeg[pulsarp->vertex]-x;    /*    Find next counter-cw vertex angle.    */
  213.                                 /*    Note that the above angles are relative!    */
  214.  
  215.         if(dx<-ANGLES)    dx=y+y;    /*    A negative angle is used as a flag value    */
  216.         if(dy<-ANGLES)    dy=y+y;    /*    to indicate that there is no "next vertex".    */
  217.  
  218.         if(y>0)                        /*    Clockwise rotation?                        */
  219.         {    if(dx<=0)    dx+=ANGLES;    /*    Force angle between 1 and ANGLES        */
  220.             if(dy<=0)    dy+=ANGLES;    /*    Same thing here.                        */
  221.             if(dx<dy)                /*    Which vertex is next?                    */
  222.             {    if(y>=dx)            /*    Can we reach the next clockwise vertex?    */
  223.                 {    
  224.                     y=0;
  225.                     DoPulsing(pulsarp);
  226.                     pulsarp->rotation+=dx;    /*    Rotate to this vertex.            */
  227.                     pulsarp->vertex++;        /*    Increment vertex value.            */
  228.  
  229.                     doskip= 1;        /*    We skipped from a vertex to another.    */
  230.                     if(ww.wraps)    /*    Following code depends on field type.    */
  231.                     {    if(pulsarp->vertex>=ww.numsegs)
  232.                         {    pulsarp->vertex=0;    /*    Wrap around to other side.    */
  233.                         }
  234.                     }
  235.                     else    /*    Bounce back, if hit the edge of the playfield.    */
  236.                     {    if(pulsarp->vertex>=ww.numsegs)
  237.                         {    pulsarp->vertex=ww.numsegs-1;
  238.                             pulsarp->direction= -pulsarp->direction;
  239.                             y= -y;
  240.                             doskip= 0;
  241.                             if(pulsarp->level.i==0)
  242.                                 Hero.lanestat[pulsarp->vertex] |= PulsMask;
  243.                         }
  244.                     }
  245.                     if(doskip)        /*    Did we grab a new vertex?                */
  246.                         PulsarSegSkip(pulsarp);
  247.                 }
  248.                 else    /*    Didn't reach a new vertex. No more rotating to do.    */
  249.                 {    pulsarp->rotation+=y;
  250.                     y=0;
  251.                 }
  252.             }
  253.             else            /*    Basically the same code as above follows,        */
  254.             {    if(y>=dy)    /*     but in the other direction.                    */
  255.                 {    y=0;
  256.                     DoPulsing(pulsarp);
  257.                     pulsarp->rotation+=dy;
  258.                     pulsarp->vertex--;
  259.                     doskip= 1;
  260.                     
  261.                     if(ww.wraps)
  262.                     {    if(pulsarp->vertex<0)
  263.                         {    pulsarp->vertex=ww.numsegs-1;
  264.                         }
  265.                     }
  266.                     else
  267.                     {    if(pulsarp->vertex==0)
  268.                         {    pulsarp->vertex=1;
  269.                             pulsarp->direction= -pulsarp->direction;
  270.                             y= -y;
  271.                             doskip= 0;
  272.                             if(pulsarp->level.i==0)
  273.                                 Hero.lanestat[0] |= PulsMask;
  274.                         }
  275.                     }
  276.                     if(doskip)
  277.                         PulsarSegSkip(pulsarp);
  278.                 }
  279.                 else
  280.                 {    pulsarp->rotation+=y;
  281.                     y=0;
  282.                 }
  283.             }
  284.             /*    Adjust rotation angle to be between 0 and ANGLES-1.                */
  285.             if(pulsarp->rotation>=ANGLES) pulsarp->rotation-=ANGLES;
  286.         }
  287.         else    /*    Counterclockwise rotation. Otherwise similar to above code.    */
  288.         {    if(dx>=0)    dx-=ANGLES;
  289.             if(dy>=0)    dy-=ANGLES;
  290.             if(dx>dy)
  291.             {    if(y<=dx)
  292.                 {    
  293.                     y=0;
  294.                     DoPulsing(pulsarp);
  295.                     pulsarp->rotation+=dx;
  296.                     pulsarp->vertex++;
  297.                     
  298.                     doskip= 1;
  299.                     if(ww.wraps)
  300.                     {    if(pulsarp->vertex>=ww.numsegs)
  301.                         {    pulsarp->vertex=0;
  302.                         }
  303.                     }
  304.                     else
  305.                     {    if(pulsarp->vertex>=ww.numsegs)
  306.                         {    pulsarp->vertex=ww.numsegs-1;
  307.                             pulsarp->direction= -pulsarp->direction;
  308.                             y= -y;
  309.                             doskip= 0;
  310.                             if(pulsarp->level.i==0)
  311.                                 Hero.lanestat[pulsarp->vertex] |= PulsMask;
  312.                         }
  313.                     }
  314.                     if(doskip)
  315.                         PulsarSegSkip(pulsarp);
  316.                 }
  317.                 else    
  318.                 {    pulsarp->rotation+=y;
  319.                     y=0;
  320.                 }
  321.             }
  322.             else
  323.             {    if(y<=dy)
  324.                 {    
  325.                     y=0;
  326.                     DoPulsing(pulsarp);
  327.                     pulsarp->rotation+=dy;
  328.                     pulsarp->vertex--;
  329.                     doskip= 1;
  330.                     
  331.                     if(ww.wraps)
  332.                     {    if(pulsarp->vertex<0)
  333.                         {    pulsarp->vertex=ww.numsegs-1;
  334.                         }
  335.                     }
  336.                     else
  337.                     {    if(pulsarp->vertex==0)
  338.                         {    pulsarp->vertex=1;
  339.                             pulsarp->direction= -pulsarp->direction;
  340.                             y= -y;
  341.                             doskip= 0;
  342.                             if(pulsarp->level.i==0)
  343.                                 Hero.lanestat[0] |= PulsMask;
  344.                         }
  345.                     }
  346.                     if(doskip)
  347.                         PulsarSegSkip(pulsarp);
  348.                 }
  349.                 else
  350.                 {    pulsarp->rotation+=y;
  351.                     y=0;
  352.                 }
  353.             }
  354.             if(pulsarp->rotation<0)    pulsarp->rotation+=ANGLES;
  355.         }
  356.     }
  357.     
  358.     /*    Find out the lane that we belong to currently.    This depends
  359.     **    on the vertex we are connected to and the angle at which we
  360.     **    are hanging.
  361.     */
  362.     pulsarp->lane=LaneSel[pulsarp->vertex][pulsarp->rotation];
  363.     
  364.     if(pulsarp->pulscounter)
  365.     {    if(ThisLevel.puPulsDepth > pulsarp->level.i)
  366.         {    pulsarp->pulscounter--;
  367.             /* change in pulsar behavior so it waits then pulses, then waits */
  368.             /* in each lane. (mz) */
  369.             if( (pulsarp->pulscounter < (int)(PULSINGTIME*.75)) &&
  370.                     (pulsarp->pulscounter > (int)(PULSINGTIME*.30)))
  371.                 Hero.lanestat[pulsarp->lane] |= PulsMask;
  372.             if(PulsarPower>=13 && pulsarp->pulscounter<NERVOUSNESS)
  373.             {    pulsarp->pulscounter=0;
  374.             }
  375.         }
  376.         else
  377.         {    pulsarp->pulscounter=0;
  378.         }
  379.     }
  380.  
  381.  
  382.     /*    Calculate the position and width of the pulsar.                */
  383.     dx= ww.unitlen[pulsarp->level.i];    /*    Look up length at this level.    */
  384.     
  385.     dy= (dx*(long) -Sins[pulsarp->rotation])>>8;    /*    Fixed point rotation.    */
  386.     dx= (dx*(long)Cosins[pulsarp->rotation])>>8;
  387.  
  388.     x=ww.x[pulsarp->vertex][pulsarp->level.i];/*    Find position on screen.*/
  389.     y=ww.y[pulsarp->vertex][pulsarp->level.i];
  390.     
  391.     if(!VA.Late)                /*    Is there time to draw something?    */
  392.     {    if(pulsarp->mirror)        /*    Is the pulsar mirrored?            */
  393.             DrawPulsar(x+dx,y+dy,-dx,-dy,PulsarPower);
  394.         else
  395.             DrawPulsar(x,y,dx,dy,PulsarPower);
  396.     }
  397.  
  398.     /*    Notify the player record if a pulsar is on the edge.            */
  399.     if(pulsarp->level.i==0)
  400.     {    Hero.segmstat[pulsarp->vertex] |= PulsMask;
  401.     }
  402.     
  403.     /*    Test to see if the player has hit us.                            */
  404.     if(ShotHitTest(pulsarp->lane,pulsarp->level.i))
  405.     {    sc=ww.unitlen[pulsarp->level.i];        /*    Explode into two parts.    */
  406.         AddCrack(    x,y,
  407.                     -dx >> 2,-dy >> 2,
  408.                     PULSARCOLOR,sc,PulsarCrack,
  409.                     pulsarp->rotation,-2*pulsarp->direction,10);
  410.  
  411.         ThisLevel.puCount--;
  412.         ThisLevel.totalCount--;
  413.  
  414.         PlayB(Splitter,13);
  415.         IncreaseScore(ThisLevel.puPoints);
  416.         pulsarp->state=inactive;
  417.         ActivePulsars--;
  418.     }
  419. }
  420.  
  421. /*
  422. >>    Go through the pulsars checking their state and
  423. >>    promoting them from stars to fully grown pulsar,
  424. >>    when they reach the playfield.
  425. */
  426. void    UpdatePulsars()
  427. {
  428.     register    Pulsar        *psp;
  429.     register    int            i;
  430.  
  431.     PulsarPower=(VA.FrameCounter) & 31;
  432.     if(ActivePulsars && PulsarPower==30)
  433.     {    PlayB(Phazer2,9);
  434.     }
  435.  
  436.     if(PulsarPower>15)
  437.         PulsarPower=31-PulsarPower;
  438.     
  439.     psp=Pulsars;
  440.     for(i=0;i<MAXPULSARS;i++)
  441.     {    if(psp->state<0)
  442.         {    psp->vertex= -(psp->state + 1)/STARDIVISION;
  443.             psp->state= active;
  444.             if(!ww.wraps && psp->vertex==0)    psp->vertex=1;
  445.             if(psp->vertex>ww.numsegs)        psp->vertex=ww.numsegs;
  446.  
  447.             if(psp->direction < 0)
  448.             {    psp->rotation=NextSeg[psp->vertex];
  449.             }
  450.             else
  451.             {    psp->rotation=PrevSeg[psp->vertex];
  452.             }
  453.         }
  454.         else
  455.         {    if(psp->state==active)
  456.                 UpdateActivePulsar(psp);
  457.         }
  458.         psp++;
  459.     }
  460.  
  461.     if(ActivePulsars<MAXPULSARS && ThisLevel.puCount>ActivePulsars)
  462.     {    if(VAPosRandom() < ThisLevel.puProb+ThisLevel.probIncrease)
  463.         {    CreateNewPulsar();
  464.         }
  465.     }
  466.     ThisLevel.starCount += ThisLevel.puCount-ActivePulsars;
  467.     ThisLevel.activeCount += ActivePulsars;
  468. }
  469.  
  470. void    InitPulsars()
  471. {
  472.     register    int        i;
  473.     
  474.     for(i=0;i<MAXPULSARS;i++)
  475.     {    Pulsars[i].state=inactive;
  476.     }
  477.     
  478.     ActivePulsars=0;
  479. }
  480.  
  481. void    AllocPulsars()
  482. {
  483.     Pulsars=(Pulsar *)NewPtr(sizeof(Pulsar)*MAXPULSARS);
  484. }
  485.