void PSBTM(Object* self)
{
	switch(self->routine)
	{
		case Routine_Init:
			self->routine = Routine_PrsStart;
			self->x = PSB_ScreenX;
			self->screenY = PSB_ScreenY;
			self->map = Map_PSB;
			self->gfx = GFX_PSB;

			if(self->frame >= Frame_SpriteLineLimiter)
			{
				self->routine = Routine_Exit;

				if(self->frame == Frame_TM)
				{
					self->gfx = GFX_TM;
					self->x = TM_ScreenX;
					self->screenY = TM_ScreenY;
				}
				break;
			}
			// fall through
		case Routine_PrsStart:
			AnimateSprite(self, Ani_PSBTM);
			break;

		case Routine_Exit:
			break;
	}

	DisplaySprite(self);
}
void TitleSonic(Object* self)
{
	switch(self->routine)
	{
		case Routine_Init:
			self->routine = Routine_Delay;
			self->x = TitleSonic_ScreenX;
			self->screenY = TitleSonic_ScreenY;
			self->map = Map_TitleSonic;
			self->gfx = GFX_TitleSonic;
			self->priority = 1;
			self->delayAni = 29;
			AnimateSprite(self, Ani_TitleSonic);
			// fall through
		case Routine_Delay:
			if(TimerNeg(self->delayAni))
			{
				self->routine = Routine_Move;
				DisplaySprite(self);
			}
			break;

		case Routine_Move:
			self->obScreenY -= 8;

			if(self->screenY == (128 + 22))
				self->routine = Routine_Animate;

			DisplaySprite(self);
			break;

		case Routine_Animate:
			AnimateSprite(self, Ani_TitleSonic);
			DisplaySprite(self);
			break;
	}
}
Esempio n. 3
0
/*
 * DrawAllUnits
 *
 * Draw all the units
 */
void DrawAllUnits (GdkPixmap *pixmap, 
               GtkWidget *drawing_area)
{
    /*
     * Move and display the hero
     */
    ApplyFriction ();
    Move (hero);

    /* --- Keep him in-bounds. --- */
    AdjustSpriteHeight (hero);

    DisplaySprite (drawing_area, sprite_ship, 
                   nShipAdjustment - (sprite_ship->width / 2), 
                   (int) hero->y - (sprite_ship->height / 2));
    /*
     * Move and display everyone else
     */
    DisplayOtherUnits (pixmap, drawing_area);
}
void Splash(Object* self)
{
	switch(self->routine)
	{
		case Routine_Init:
			self->routine = Routine_Main;
			self->map = Map_Splash;
			Obj_SetSomething(self);
			self->priority = 1;
			self->obActWid = 16;
			self->gfx = GFX_Splash;
			self->x = v_player->x;
			// fall through
		case Routine_Main:
			self->y = v_waterpos1;
			AnimateSprite(self, Ani_Splash)
			DisplaySprite(self);
			break;

		case Routine_Delete:
			DeleteObject(self);
			break;
	}
}
Esempio n. 5
0
/*
 * DisplayOtherUnits
 *
 * Display all the units on the screen. First, we need 
 * to move each of the units to their new positions. 
 * Some of this is done in the AI module. 
 * 
 */
void DisplayOtherUnits (GdkPixmap *pixmap, GtkWidget *drawing_area)
{
    typUnit *unit;
    typUnit *unitHit;
    GList *node;
    int xPos;
    int xPosEnd;
    typSprite *sprite;

    /* --- Each unit in the list --- */
    for (node = unitList; node; node = node->next) {
 
        /* --- Get the unit --- */
        unit = (typUnit *) node->data;

        /*  
         * --- Run the AI module on it to move it --- 
         */
        AIModule (unit);

        /* 
         * If the unit was destroyed by the AI, 
         * don't draw the unit.
         */
        if (unit->bDestroy) {
            continue;
        }

        /* 
         * If there's no sprite for the unit, 
         * we can't draw it now, can we?
         */
        sprite = GetSprite (unit);
        if (sprite == NULL) continue;
 
        /* --- Where on the screen is it going? --- */
        xPos = UnitScreenX (unit);

        /* --- Make sure unit doesn't go out of bounds --- */
        AdjustSpriteHeight (unit);

        /* --- Finally draw unit --- */
        DisplaySprite (drawing_area, sprite, 
                   (int) (xPos - sprite[0].width / 2), 
                   (int) (unit->y - sprite[0].height / 2));
    }

    /* 
     * --- once everyone is painted, fire the lasers.
     */

    for (node = unitList; node; node = node->next) {

        unit = (typUnit *) node->data;

        /* --- If this is a laser --- */
        if (unit->type == LASER) {
 
            /* --- Get starting and ending positions --- */
            xPos = ScreenX ((int) unit->x);
            xPosEnd = xPos + LASER_LENGTH * unit->direction;

            /* --- See if anything was hit --- */
            unitHit = AnyoneBetween ((int) xPos, (int) unit->y, 
                                     (int) xPosEnd, (int) unit->y);
            if (unitHit) {

                /* --- Something was hit --- */

                /* --- Laser shot only goes this far --- */
                xPosEnd = UnitScreenX (unitHit);

                /* --- Destroy the unit --- */
                unitHit->bDestroy = TRUE;
                unit->bDestroy = TRUE;

                /* --- Special effects of destruction --- */
                AddExplosion (unitHit);
            }

            /* --- Draw the laser --- */
            gdk_draw_line (pixmap, penWhite,
                           xPos, unit->y, 
                           xPosEnd,
                           unit->y);
            
            /* --- Get real coordinates of laser --- */
            unit->x = GameX (xPosEnd);

            /* --- If laser has gone too far... --- */
            if (DistanceBetween (unit, hero) > nScreenWidth / 2) {

                /* --- destroy it --- */
                unit->bDestroy = TRUE;
            }
        }
    }
}
void DrownCount(Object* self)
{
	switch(self->routine)
	{
		case Routine_Init:
			self->routine = Routine_BubbleExpanding;
			self->map = Map_Bub;
			self->gfx = GFX_Bubble;
			Obj_SetVisible(self);
			Obj_SetBehind(self);
			self->actWid = 16;
			self->priority = 1;

			if(BTST(self->subtype, Subtype_Master))
			{
				self->routine = Routine_Master;
				self->map = Map_Drown;
				self->gfx = GFX_Master;
				VAR_B(self, alwaysOneB) = self->subtype & ~Subtype_Master;
				goto _masterRoutine;
			}

			// Bubble
			self->anim = self->subtype;
			VAR_W(self, origXW) = self->x;
			self->velY = -Bubble_Velocity;
			// fall through
		case Routine_BubbleExpanding:
			AnimateSprite(self, Ani_Drown);
			// fall through
		case Routine_BubbleRising:
			// Still underwater?
			if(self->y >= vWaterpos1)
			{
				// Move bubbles with tunnel current
				if(fWtunnelmode)
					VAR_W(self, origXW) += 4;

				// Wobble
				self->x = VAR_W(self, origXW) + Bubble_Wobble[self->angle & 0x7F];
				self->angle++;

				// Update appearance
				CheckNumberBubbleConversion(self);
				SpeedToPos(self);

				if(Object_IsVisible(self))
					DisplaySprite(self);
				else
					DeleteObject(self);
				break;
			}
			else
			{
				// Reached surface? For small bubbles, this sets their anim to blank and will go routine 6 > 8 and die
				// Big bubbles actually glitch out when they reach the surface cause there aren't enough enim mappings!
				self->routine = Routine_BubbleDying;
				self->anim += 7;
			}
			// fall through
		case Routine_BubbleDying:
		case Routine_NumberUpdate:
		_display:
			// Update appearance
			CheckNumberBubbleConversion(self);
			AnimateSprite(self, Ani_Drown);
			DisplaySprite(self);
			break;

		case Routine_BubbleDead:
		case Routine_NumberDead:
			DeleteObject(self);
			break;

		// Once a number-bubble gets plastered to the screen, it enters this state which handles switching to the
		// "flashing number" animation.
		case Routine_NumberTransition:
			if(v_air > Drown_Air)
			{
				DeleteObject(self);
				break;
			}

			if(TimerZero(VAR_W(self, frameTimerW)))
			{
				self->routine = Routine_NumberUpdate;
				self->anim += 7;
				goto _display;
			}

			AnimateSprite(self, Ani_Drown);

			if(Object_IsVisible(self))
				DisplaySprite(self);
			else
				DeleteObject(self);
			break;

		// The "master" object, spawned when Sonic goes underwater for the first time, goes into this routine forever.
		// It manages counting down the air meter, spawning bubbles/numbers, and drowning/killing Sonic.
		case Routine_Master:
		_masterRoutine:
			// If we're not currently drowning...
			if(VAR_W(self, drowningTimeW) == 0)
			{
				// Manage counting down the timer and stuff
				if(Player_IsDead() || !Player_IsUnderwater())
					return;

				// Count down frames until the next second
				if(TimerNeg(VAR_W(self, frameTimerW), 59))
				{
					VAR_W(self, bubbleFlagsW) = BubbleFlags_Enable;
					VAR_B(self, spawnTimerB) = RandomNumber(2);

					if(ShouldDing())
						PlaySound_Special(SFX_Warning); // ding-ding
					else if(v_air <= Drown_Air)
					{
						if(v_air == Drown_Air)
							PlaySound(BGM_Drowning); // uh oh

						if(TimerNeg(VAR_B(self, sillyTimerB), VAR_B(self, alwaysOneB)))
							BSET(VAR_W(self, bubbleFlagsW), BubbleFlags_SpawnNumber);
					}

					if(TimerNeg(v_air))
					{
						// Drowning time.
						ResumeMusic();
						f_lockmulti = 0x81;
						PlaySound_Special(SFX_Drown);
						VAR_B(self, spawnTimerB) = 10;
						VAR_W(self, bubbleFlagsW) = BubbleFlags_Enable;
						VAR_W(self, drowningTimeW) = Drown_Length;
						Player_ResetOnFloor(v_player);
						Player_SetAnimDrowning();
						Player_SetInAir();
						v_player->gfx |= 0x80;
						v_player->velY = 0;
						v_player->velX = 0;
						v_player->inertia = 0;
						f_nobgscroll = true;
						return;
					}

					goto _makeBubble;
				}
			}
			else
			{
				// Manage the drowning animation (Sonic falling offscreen)
				if(TimerZero(VAR_W(self, drowningTimeW)))
				{
					Player_SetDead();
					return;
				}

				SpeedToPos(v_player);
				v_player->velY += Drown_Velocity;
			}

			// Bubble spawning enabled?
			if(VAR_W(self, bubbleFlagsW))
			{
				if(TimerNeg(VAR_W(self, bubbleTimerW)))
				{
				_makeBubble:
					VAR_W(self, bubbleTimerW) = RandomNumber(16);

					if(auto bubble = FindFreeObj())
					{
						auto bubble = &v_objspace[slot];
						bubble->id = ID_DrownCount;
						bubble->x v_player->x + (Player_IsFlipped() ? -Bubble_OffsX : Bubble_OffsX);
						bubble->y = v_player->y;
						bubble->angle = Player_IsFlipped() ? Bubble_AngleFlipped : 0;
						bubble->subtype = Subtype_SmallBubble;

						// If we're doing drowning-bubbles..
						if(VAR_W(self, drowningTimeW) != 0)
						{
							VAR_W(self, bubbleTimerW) &= 7;
							bubble->y = v_player->y - Bubble_DrownOffsY;
							bubble->angle = RandomNumber(256);

							// 1/4 bubbles are made bigger
							if((v_framecount & 3) == 0)
								bubble->subtype = Subtype_MediumBubble;
						}
						else if(ShouldSpawnNumberBubble(self))
						{
							BSET(VAR_W(self, bubbleFlagsW), BubbleFlags_NumberSpawned);
							bubble->subtype = GetCountdownDigit();
							VAR_W(bubble, frameTimerW) = NumberBubble_Timer1;
						}

						if(TimerNeg(VAR_B(self, spawnTimerB)))
							VAR_W(self, bubbleFlagsW) = 0;
					}
				}
			}

			break;
	}
}