void GegnerSecret::DoKI(void)
{
	// Secret nicht im Bild ?
	//
	if (xPos + 10 < pTileEngine->XOffset		||
		xPos	  > pTileEngine->XOffset + 640	||
		yPos + 10 < pTileEngine->YOffset		||
		yPos	  > pTileEngine->YOffset + 480)
	{
		return;
	}

	switch (Handlung)
	{
		case GEGNER_STEHEN:
		{
			// Spieler berührt das Secret? Dann Counter erhöhen und deaktivieren
			//
			GegnerRect[GegnerArt].left   = -Value1 / 2 + 20;
			GegnerRect[GegnerArt].right  =  Value1 / 2 + 20;
			GegnerRect[GegnerArt].top    = -Value2 / 2 + 20;
			GegnerRect[GegnerArt].bottom =  Value2 / 2 + 20;

			for (int p = 0; p < NUMPLAYERS; p++)
			if (SpriteCollision(xPos, yPos, GegnerRect[GegnerArt],
								pPlayer[p]->xpos, 
								pPlayer[p]->ypos, 
								pPlayer[p]->CollideRect) == true)
			{
				pPlayer[0]->SecretThisLevel++;
				pPlayer[0]->SecretFullGame++;
				Handlung = GEGNER_FALLEN;

				pSoundManager->PlayWave(100, 128, 11025, SOUND_SECRET);

				for (int i = 0; i < 200; i++)
					pPartikelSystem->PushPartikel(xPos + 20, yPos + 20, KRINGELSECRET);

				WinkelUebergabe = -1.0f;
				pPartikelSystem->PushPartikel(xPos + 20, yPos + 12, TEXTSECRET);
				pPartikelSystem->PushPartikel(xPos - 100, yPos - 100, GRENADEFLARE);
				pPartikelSystem->PushPartikel (xPos + 5, yPos + 5, EXPLOSION_KRINGEL);

			}
		} break;
	}
}
//=============================================================
//Game Engine Helper Methods
//=============================================================
BOOL GameEngine::CheckSpriteCollision(Sprite* pTestSprite)
{
	//See if the sprite has collided with any other sprites
	vector<Sprite*>::iterator siSprite;
	for (siSprite = m_vSprites.begin(); siSprite != m_vSprites.end(); siSprite++)
	{
		//Make sure not to check for the collision of itself
		if (pTestSprite == (*siSprite))
			continue;

		//Test the collision
		if (pTestSprite->TestCollision(*siSprite))
			//Collision detected
			return SpriteCollision((*siSprite), pTestSprite);
	}

	//No collision
	return FALSE;
}
Beispiel #3
0
static void draw_sprites(running_machine *machine, bitmap_t *bitmap)
{
    int offs;
    const rectangle *visarea = video_screen_get_visible_area(machine->primary_screen);

    /* -------------------------------------------------------------- */
    /* There seems to be a strange setup with this board, in that it  */
    /* appears that the S2636 runs from a different clock than the    */
    /* background generator, When the program maps sprite position to */
    /* character position it only has 6 pixels of sprite for 8 pixels */
    /* of character.                                                  */
    /* -------------------------------------------------------------- */
    /* n.b. The original has several graphic glitches as well, so it  */
    /* does not seem to be a fault of the emulation!                  */
    /* -------------------------------------------------------------- */

    CollisionBackground = 0;	/* Read from 0x1e80 bit 7 */

    // for collision detection checking
    copybitmap(tmpbitmap,bitmap,0,0,0,0,visarea);

    for(offs=0; offs<0x50; offs+=0x10)
    {
        if((zac2650_s2636_0_ram[offs+10]<0xF0) && (offs!=0x30))
        {
            int spriteno = (offs / 8);
            int expand   = ((zac2650_s2636_0_ram[0xc0] & (spriteno*2))!=0) ? 2 : 1;
            int bx       = (zac2650_s2636_0_ram[offs+10] * 4) - 22;
            int by       = (zac2650_s2636_0_ram[offs+12] * 3) + 3;
            int x,y;

            /* Sprite->Background collision detection */
            drawgfx_transpen(bitmap,0, machine->gfx[expand],
                             spriteno,
                             1,
                             0,0,
                             bx,by, 0);

            for (x = bx; x < bx + machine->gfx[expand]->width; x++)
            {
                for (y = by; y < by + machine->gfx[expand]->height; y++)
                {
                    if ((x < visarea->min_x) ||
                            (x > visarea->max_x) ||
                            (y < visarea->min_y) ||
                            (y > visarea->max_y))
                    {
                        continue;
                    }

                    if (*BITMAP_ADDR16(bitmap, y, x) != *BITMAP_ADDR16(tmpbitmap, y, x))
                    {
                        CollisionBackground = 0x80;
                        break;
                    }
                }
            }

            drawgfx_transpen(bitmap,0, machine->gfx[expand],
                             spriteno,
                             0,
                             0,0,
                             bx,by, 0);
        }
    }

    /* Sprite->Sprite collision detection */
    CollisionSprite = 0;
//  if(SpriteCollision(machine, 0,1)) CollisionSprite |= 0x20;   /* Not Used */
    if(SpriteCollision(machine, 0,2)) CollisionSprite |= 0x10;
    if(SpriteCollision(machine, 0,4)) CollisionSprite |= 0x08;
    if(SpriteCollision(machine, 1,2)) CollisionSprite |= 0x04;
    if(SpriteCollision(machine, 1,4)) CollisionSprite |= 0x02;
//  if(SpriteCollision(machine, 2,4)) CollisionSprite |= 0x01;   /* Not Used */
}
Beispiel #4
0
void zac2650_state::draw_sprites(bitmap_ind16 &bitmap, const rectangle &cliprect)
{
	int offs;
	const rectangle &visarea = m_screen->visible_area();

	/* -------------------------------------------------------------- */
	/* There seems to be a strange setup with this board, in that it  */
	/* appears that the S2636 runs from a different clock than the    */
	/* background generator, When the program maps sprite position to */
	/* character position it only has 6 pixels of sprite for 8 pixels */
	/* of character.                                                  */
	/* -------------------------------------------------------------- */
	/* n.b. The original has several graphic glitches as well, so it  */
	/* does not seem to be a fault of the emulation!                  */
	/* -------------------------------------------------------------- */

	m_CollisionBackground = 0;   /* Read from 0x1e80 bit 7 */

	// for collision detection checking
	copybitmap(m_bitmap,bitmap,0,0,0,0,visarea);

	for(offs=0;offs<0x50;offs+=0x10)
	{
		if((m_s2636_0_ram[offs+10]<0xF0) && (offs!=0x30))
		{
			int spriteno = (offs / 8);
			int expand   = ((m_s2636_0_ram[0xc0] & (spriteno*2))!=0) ? 2 : 1;
			int bx       = (m_s2636_0_ram[offs+10] * 4) - 22;
			int by       = (m_s2636_0_ram[offs+12] * 3) + 3;
			int x,y;

			/* Sprite->Background collision detection */
			m_gfxdecode->gfx(expand)->transpen(bitmap,cliprect,
					spriteno,
					1,
					0,0,
					bx,by, 0);

			for (x = bx; x < bx + m_gfxdecode->gfx(expand)->width(); x++)
			{
				for (y = by; y < by +m_gfxdecode->gfx(expand)->height(); y++)
				{
					if (visarea.contains(x, y))
						if (bitmap.pix16(y, x) != m_bitmap.pix16(y, x))
						{
							m_CollisionBackground = 0x80;
							break;
						}
				}
			}

			m_gfxdecode->gfx(expand)->transpen(bitmap,cliprect,
					spriteno,
					0,
					0,0,
					bx,by, 0);
		}
	}

	/* Sprite->Sprite collision detection */
	m_CollisionSprite = 0;
//  if(SpriteCollision(0,1)) m_CollisionSprite |= 0x20;   /* Not Used */
	if(SpriteCollision(0,2)) m_CollisionSprite |= 0x10;
	if(SpriteCollision(0,4)) m_CollisionSprite |= 0x08;
	if(SpriteCollision(1,2)) m_CollisionSprite |= 0x04;
	if(SpriteCollision(1,4)) m_CollisionSprite |= 0x02;
//  if(SpriteCollision(2,4)) m_CollisionSprite |= 0x01;   /* Not Used */
}
void GegnerDiamant::DoKI(void)
{
	BlickRichtung = LINKS;

	// Bei Animationsphase 1 kurze Pause damit er nich blinkt wie ein Feuerwehrauto =)
	if (AnimPhase == 0)
		AnimSpeed = 4.0f;
	else
		AnimSpeed = 1.0f;

	// Animieren
	AnimCount += 1.0f SYNC;				// Animationscounter weiterzählen
	if (AnimCount > AnimSpeed)			// Grenze überschritten ?
	{
		AnimCount = 0;					// Dann wieder auf Null setzen
		AnimPhase++;					// Und nächste Animationsphase
		if (AnimPhase >= AnimEnde)		// Animation von zu Ende	?
			AnimPhase = 0;				// Dann wieder von vorne beginnen
	}

	switch(Handlung)
	{
		case GEGNER_FALLEN :			// Diamant fällt runter
		{
			if (ySpeed > 35.0f)			// Fall-Limit nicht überschreiten
				ySpeed = 35.0f;

			// Am Boden abhopfen ?
			if (blocku & BLOCKWERT_WAND ||
				blocku & BLOCKWERT_PLATTFORM)
			{
				//blocku = pTileEngine->BlockUnten (xPos, yPos, xPosOld, yPosOld, GegnerRect[GegnerArt]);

				if (ySpeed > 0.0f)
				{
					ySpeed = -ySpeed / 2.0f;

					if (ySpeed > -0.5f)				// Wieder abspringen oder liegenbleiben ?
					{
						ySpeed   = 0.0f;
						yAcc     = 0.0f;
						Handlung = GEGNER_STEHEN;
						yPos    += 1.0f;
					}
				}
			}
		} break;

		case GEGNER_STEHEN :
		{
			// Value1 == 0? Dann runterfallen lassen
			//
			if (Value1 == 0)
			if (!(pTileEngine->BlockUnten (xPos, yPos, xPosOld, yPosOld, GegnerRect[GegnerArt]) & BLOCKWERT_WAND) &&
				!(pTileEngine->BlockUnten (xPos, yPos, xPosOld, yPosOld, GegnerRect[GegnerArt]) & BLOCKWERT_PLATTFORM))
			{
				yAcc	 = 2.0f;
				Handlung = GEGNER_FALLEN;
			}

		} break;

	} // switch

	// Testen, ob der Spieler den Diamant eingesammelt hat
	for (int i = 0; i < NUMPLAYERS; i++)
	if (SpriteCollision(xPos, yPos, GegnerRect[GegnerArt],
						pPlayer[i]->xpos, pPlayer[i]->ypos, pPlayer[i]->CollideRect) == true)
	{
		// Partikel erzeugen
		if (pPlayer[0]->PunisherActive == false)
			pPartikelSystem->PushPartikel(xPos, yPos, DIAMANTCOLLECTED);

		// Punisher anschiessen
		else
		{
			pProjectiles->PushProjectile(xPos, yPos, DIAMONDSHOT);
		}

		pPlayer[0]->Score += 100;					// Punkte erhöhen
		pPlayer[0]->CollectedDiamonds++;			// Zahl gesammelter Diamanten erhöhen
		pPlayer[0]->DiamondsThisLevel++;
		pPlayer[0]->DiamondsFullGame++;
		if (pPlayer[0]->CollectedDiamonds			// Limit überchritten ?
			>= DIAMONDS_FOR_EXTRALIFE)	
		{	
			pPlayer[0]->CollectedDiamonds = 0;		// Dann auf 0 setzen
			pTileEngine->Timelimit += 100.0f;

			if (pTileEngine->Timelimit > 999.0f)
				pTileEngine->Timelimit = 999.0f;

			// Punisher ggf verschwinden lassen
			pPlayer[0]->PunisherActive = false;
			pPlayer[1]->PunisherActive = false;

			GegnerClass *pTemp;
			GegnerPunisher *pPunisher;

			pTemp = pGegner->pStart;

			while (pTemp != NULL)
			{
				if (pTemp->GegnerArt == PUNISHER)
				{
					pPunisher = (GegnerPunisher*)pTemp;
					pPunisher->Vanish();
				}

				pTemp = pTemp->pNext;
			}
		}
		Energy = 0.0f;
	}
}
Beispiel #6
0
void GegnerExtras::DoKI(void)
{	
	BlickRichtung = LINKS;

	switch(Handlung)
	{
		case GEGNER_SPRINGEN :			// Extra fällt noch im Bogen raus
		{
			// an der Decke abprallen
			/*if (blocko & BLOCKWERT_WAND &&
				ySpeed < 0.0f)
				ySpeed = -ySpeed;*/

			// an der Wand abprallen
			if (blockl & BLOCKWERT_WAND ||
				blockr & BLOCKWERT_WAND)
				xSpeed = -xSpeed;

			// Fall beendet oder auf den Boden gekommen
			if (ySpeed >= 25.0f)
			{
				ySpeed   = -1.0f;
				xSpeed   = 0;
				yAcc     = 0;
				Handlung = GEGNER_STEHEN;

				// Im Tutorial fliegen die Granaten schneller nach oben =)
				if (RunningTutorial == true &&
					Value1 == 8)
					ySpeed = -3.0f;
			}

		} break;

		case GEGNER_STEHEN :			// Extra schwebt langsam nach oben
		{
			// An der Decke anhalten
			if (blocko & BLOCKWERT_WAND)
				ySpeed = 0;

			// Speed verlangsamen
			if (xSpeed > 0.0f)
			{
				xSpeed -= 0.5f SYNC;

				if (xSpeed < 0.0f)
					xSpeed = 0.0f;
			}

			if (xSpeed < 0.0f)
			{
				xSpeed += 0.5f SYNC;

				if (xSpeed > 0.0f)
					xSpeed = 0.0f;
			}
		} break;

	} // switch

	// Testen, ob der Spieler das Extra eingesammelt hat
	PlayerClass *pCollector = NULL;

	for (int i = 0; i < NUMPLAYERS; i++)
	if (SpriteCollision(xPos, yPos, GegnerRect[GegnerArt],
						pPlayer[i]->xpos, pPlayer[i]->ypos, pPlayer[i]->CollideRect) == true)
						pCollector = pPlayer[i];

	if (pCollector != NULL)// &&
		//Handlung != GEGNER_SPRINGEN)
	{
		// Punkte fürs Extras sammeln gebe
		pCollector->Score += 10;

		// "Einsammel" Effekt anzeigen
		pPartikelSystem->PushPartikel (xPos - 4, yPos - 4, EXTRACOLLECTED);

		// Waffen-Upgrade eingesammelt ?
		if (Value1 < 3)
		{
			// Upgraden überhaupt noch notwendig ?
			if (pCollector->CurrentWeaponLevel[Value1] < 8)
			{
				// Anzahl eingesammelter Powerups erhöhen
				//pCollector->CollectedPowerUps[Value1]++;

				// Maximum erreicht ? dann neuen Waffenlevel setzen
				//if (pCollector->CollectedPowerUps[Value1] >= pCollector->NextWeaponLevel[Value1])
				{					
					//pCollector->CollectedPowerUps [Value1] = 0;
					pCollector->CurrentWeaponLevel[Value1]++;
					//pCollector->CalcWeaponLevels();

					// PowerUp Effekt erzeugen
					//
					pPartikelSystem->ClearPowerUpEffects();

					for (int i = 0; i < 300; i++)
					{		
						int p = rand ()%360;
						int r = rand ()%30+100;

						pPartikelSystem->PushPartikel (float (pCollector->xpos + 40 - 6 + sin ((float)p)*r), 
													   float (pCollector->ypos + 40 - 6 + cos ((float)p)*r), KRINGELR + Value1, pCollector);
					}

					pSoundManager->PlayWave (100, 128, 11025, SOUND_UPGRADE);
					pCollector->BlinkCounter = 9.5f;
					pCollector->BlinkColor = Value1+1;
				}
			}
			
			// Aktuelle Waffe auf zuletzt gesammeltes Extra setzen,
			// wenn die Waffe dadurch stärker wird
			//
			if (pCollector->CurrentWeaponLevel[Value1] > 
				pCollector->CurrentWeaponLevel[pCollector->SelectedWeapon] ||
				RunningTutorial == true)
				pCollector->SelectedWeapon = Value1;
		}

		// Blitz-Upgrade eingesammelt ?
		if (Value1 == 3)
		{
			// Upgraden überhaupt noch notwendig ?
			if (pCollector->CurrentWeaponLevel[Value1] < 16)
			{
				// Anzahl eingesammelter Powerups erhöhen
				//pCollector->CollectedPowerUps[Value1]++;

				// Maximum erreicht ? dann neuen Waffenlevel setzen
				//if (pCollector->CollectedPowerUps[Value1] >= pCollector->NextWeaponLevel[Value1])
				{
					//pCollector->CollectedPowerUps [Value1] = 0;
					pCollector->CurrentWeaponLevel[Value1]++;
					//pCollector->NextWeaponLevel   [Value1] = 3;

					// PowerUp Effekt erzeugen
					//
					pPartikelSystem->ClearPowerUpEffects();

					for (int i = 0; i < 300; i++)
					{		
						int p = rand ()%360;
						int r = rand ()%30+100;

						pPartikelSystem->PushPartikel (float (pCollector->xpos + 40 - 6 + sin ((float)p)*r), 
													   float (pCollector->ypos + 40 - 6 + cos ((float)p)*r), KRINGELHB, pCollector);
					}

					pSoundManager->PlayWave (100, 128, 11025, SOUND_UPGRADE);
					pCollector->BlinkCounter = 9.5f;
					pCollector->BlinkColor = 4;
				}
			}
		}

		// Schutzschild
		if (Value1 == 4)
		{
			// Schutzuschild Spawner erzeugen
			if (pCollector->Shield <= 0.0f)
			{
				pProjectiles->PushProjectile (pCollector->xpos, pCollector->ypos, SHIELDSPAWNER, pCollector);
				pProjectiles->PushProjectile (pCollector->xpos, pCollector->ypos, SHIELDSPAWNER2, pCollector);
			}

			// Schild setzen
			pCollector->Shield = 100.0f;
		}

		// Energie auffrischen
		if (Value1 == 5)
			pCollector->Energy = MAX_ENERGY;

		// Rad-Energie auffrischen
		if (Value1 == 6)
			pCollector->Armour = MAX_ARMOUR;

		// Powerline
		if (Value1 == 7 && pCollector->PowerLines < PLAYER_MAXEXTRAS)
			pCollector->PowerLines++;

		// Granate
		if (Value1 == 8 && pCollector->Grenades < PLAYER_MAXEXTRAS)
			pCollector->Grenades++;

		// SmartBomb
		if (Value1 == 9 && pCollector->SmartBombs < 1)
			pCollector->SmartBombs++;

		// Autofire
		if (Value1 == 10)
			pCollector->AutoFireExtra += 120;

		// Supershot
		if (Value1 == 11)
			pCollector->RiesenShotExtra += 120;

		// Score
		if (Value1 == 12)
			pPlayer[0]->Score += 100;

		Energy = 0.0f;

		pSoundManager->PlayWave(100, 128, 11025, SOUND_VOICE_SPREAD + Value1);	// Sound ausgeben

		switch (Value1)
		{
			case 0 :
			case 1 :
			case 2 :
			case 4 :
				pSoundManager->PlayWave(100, 128, 11025, SOUND_COLLECT);	// Sound ausgeben
			break;

			case 8  :
			case 9  :
			case 10 :
				pSoundManager->PlayWave(100, 128, 11000 + rand ()%1000, SOUND_AMMO);	// Sound ausgeben
			break;

			default :
				pSoundManager->PlayWave(100, 128, 11025, SOUND_COLLECT);	// Sound ausgeben
			break;
		}

		pSoundManager->PlayWave(100, 128, 11025, SOUND_COLLECT);	// Sound ausgeben
	}
}
Beispiel #7
0
void GegnerOneUp::DoKI(void)
{
	SimpleAnimation();

	// auf dem Fliessband bewegen
	if (blocku & BLOCKWERT_FLIESSBANDL)
		xSpeed = -11.0f;

	if (blocku & BLOCKWERT_FLIESSBANDR)
		xSpeed = 11.0f;

	BlickRichtung = LINKS;

	switch(Handlung)
	{
		case GEGNER_FALLEN :			// Leben fällt runter
		{
			if (ySpeed > 50.0f)			// Fall-Limit nicht überschreiten
				ySpeed = 50.0f;
			// Am Boden abhopfen ?
			if (pTileEngine->BlockUntenNormal(xPos, yPos, xPosOld, yPosOld, GegnerRect[GegnerArt]) & BLOCKWERT_WAND ||
				pTileEngine->BlockUntenNormal(xPos, yPos, xPosOld, yPosOld, GegnerRect[GegnerArt]) & BLOCKWERT_PLATTFORM)
			{
				yPos  -= 1.0f;
				ySpeed = -ySpeed * 0.2f;
				if (ySpeed > -0.5f)				// Wieder abspringen oder liegenbleiben ?
				{
					xSpeed	 = 0.0f;
					ySpeed   = 0.0f;
					yAcc     = 0.0f;
					Handlung = GEGNER_SPECIAL;
				}
			}
		} break;

		case GEGNER_STEHEN :
		{		
			// Wieder runterfallen
			//
			if (!(pTileEngine->BlockUntenNormal(xPos, yPos, xPosOld, yPosOld, GegnerRect[GegnerArt]) & BLOCKWERT_WAND) &&
				!(pTileEngine->BlockUntenNormal(xPos, yPos, xPosOld, yPosOld, GegnerRect[GegnerArt]) & BLOCKWERT_PLATTFORM))
			{
				Handlung = GEGNER_FALLEN;
				yAcc	 = 2.0f;
			}
		} break;

	} // switch

	// Testen, ob der Spieler das Extraleben eingesammelt hat
	for (int i = 0; i < NUMPLAYERS; i++)
	if (SpriteCollision(xPos, yPos, GegnerRect[GegnerArt],
						pPlayer[i]->xpos, pPlayer[i]->ypos, pPlayer[i]->CollideRect) == true)
	{
		pPlayer[0]->Score += 1000;					// Punkte vergeben
		pPlayer[i]->Lives++;						// Anzahl der Leben erhöhen
		pPlayer[0]->LivesFullGame++;
		pPlayer[0]->LivesThisLevel++;
		Energy = 0.0f;							// Und Leben verschwinden lassen

	pPartikelSystem->PushPartikel(xPos - 40, yPos - 40, EXPLOSIONFLARE);
		pPartikelSystem->PushPartikel(xPos - 40, yPos - 40, EXPLOSIONFLARE);

		for (int i = 0; i < 200; i++)
			pPartikelSystem->PushPartikel(xPos + 20, yPos + 20, KRINGELSECRET);
	}
}
void GegnerBratklops::DoDraw()
{
	// Gegner rendern
	// Animation existiert nur von 1-5, danach läuft sie rückwärts
	//

	int a;

	a = AnimPhase;
	if (a > 5)
		a = 10 - a;

	pGfx[a]->RenderSprite  (float (xPos - pTileEngine->XOffset), float (yPos - pTileEngine->YOffset), 0xFFFFFFFF);

	// Laser rendern ?
	//
	if (FlareDelay > 0.0f)
	{
		int c = int (FlareDelay);

		if (c > 128.0f)
			c = 128;

		if (FlareDelay > 544)
			c = int (128 - (FlareDelay - 544) / 2.0f);

		DirectGraphics.SetAdditiveMode();
		D3DCOLOR Color = D3DCOLOR_RGBA (255, 255, 255, c);
		pFlare->RenderSpriteRotated  (float (xPos - pTileEngine->XOffset) + 64.0f, float (yPos - pTileEngine->YOffset) + 122.0f, FlareDelay*2, Color);
		pFlare->RenderSpriteRotated  (float (xPos - pTileEngine->XOffset) + 64.0f, float (yPos - pTileEngine->YOffset) + 122.0f, FlareDelay*2, Color);

		// Laser rendern
		//
		if (FlareDelay > 150.0f		&&
			((Handlung == GEGNER_SPECIAL &&
			 int (FlareDelay) % 90 < 60) ||
			 Handlung == GEGNER_SPECIAL3))
		{
			if (pSoundManager->its_Sounds[SOUND_BRATLASER]->isPlaying == false)
				pSoundManager->PlayWave (100, 128, 11025, SOUND_BRATLASER);

			VERTEX2D				TriangleStrip[4];					// Strip für ein Sprite
			int Winkel;
			Winkel = int ((FlareDelay - 128.0f) / 4.5f) - 20;

			while (Winkel < 0)
				   Winkel += 360;

			float l,  r,  o,  u;					// Vertice Koordinaten
			float tl, tr, to, tu;					// Textur Koordinaten

			l = float (xPos - pTileEngine->XOffset + 140.0f-0.5f);			// Links
			o = float (yPos - pTileEngine->YOffset + 215.0f-0.5f);			// Oben
			r = float (xPos - pTileEngine->XOffset + 170.0f+0.5f);			// Rechts
			u = float (yPos - pTileEngine->YOffset + 800.0f+0.5f);			// Unten

			tl = 0.0f;
			tr = 1.0f;
			to = 0.0f;
			tu = 1.0f;

			TriangleStrip[0].z	= TriangleStrip[1].z	= TriangleStrip[2].z	 = TriangleStrip[3].z	   = 0.0f;
			TriangleStrip[0].color = TriangleStrip[1].color = TriangleStrip[2].color = TriangleStrip[3].color = 0xFFFFFFFF;
			TriangleStrip[0].x	= l; TriangleStrip[0].y = o; TriangleStrip[0].tu = tl; TriangleStrip[0].tv = to;
			TriangleStrip[1].x  = r; TriangleStrip[1].y	= o; TriangleStrip[1].tu = tr; TriangleStrip[1].tv = to;
			TriangleStrip[2].x  = l; TriangleStrip[2].y	= u; TriangleStrip[2].tu = tl; TriangleStrip[2].tv = tu;
			TriangleStrip[3].x	= r; TriangleStrip[3].y	= u; TriangleStrip[3].tu = tr; TriangleStrip[3].tv = tu;

			// Textur setzen
			//
#if defined(PLATFORM_DIRECTX)
			lpD3DDevice->SetTexture (0, pLaser->itsTexture);
#elif defined(PLATFORM_SDL)
            DirectGraphics.SetTexture(  pLaser->itsTexture );
#endif

			// Blitz rotieren lassen
			//
			D3DXMATRIX	matRot, matTrans, matTrans2;

			D3DXMatrixRotationZ  (&matRot, DegreetoRad[360 - Winkel]);	// Rotationsmatrix
			D3DXMatrixTranslation(&matTrans, -l-15, -o, 0.0f);			// Transformation zum Ursprung
			D3DXMatrixTranslation(&matTrans2, l+15,  o, 0.0f);			// Transformation wieder zurück
			D3DXMatrixMultiply	 (&matWorld, &matTrans, &matRot);		// Verschieben und rotieren
			D3DXMatrixMultiply	 (&matWorld, &matWorld, &matTrans2);	// und wieder zurück
#if defined(PLATFORM_DIRECTX)
			lpD3DDevice->SetTransform(D3DTS_WORLD, &matWorld);
#elif defined(PLATFORM_SDL)
            g_matModelView = matWorld * g_matView;
#if defined(USE_GL1)
            load_matrix( GL_MODELVIEW, g_matModelView.data() );
#endif
#endif

			DirectGraphics.SetFilterMode (true);

			// Blitzstrahl zeichnen
			//
			DirectGraphics.RendertoBuffer (D3DPT_TRIANGLESTRIP, 2, &TriangleStrip[0]);

			DirectGraphics.SetFilterMode (false);

			// Normale Projektions-Matrix wieder herstellen
			//
			D3DXMatrixRotationZ (&matWorld, 0.0f);
#if defined(PLATFORM_DIRECTX)
			lpD3DDevice->SetTransform(D3DTS_WORLD, &matWorld);
#elif defined(PLATFORM_SDL)
            g_matModelView = matWorld * g_matView;
#if defined(GL1)
            load_matrix( GL_MODELVIEW, g_matModelView.data() );
#endif
#endif

			DirectGraphics.SetColorKeyMode();

			// Kollisionsabfrage mit Spieler durch rotierte Rechtecke (wie beim Spielerblitz)
			//
			RECT	Rect;					// Rechteck für die Kollisionserkennung
											// ein Laser-Stück wird grob durch
			Rect.left   = 0;				// ein 24x24 Rechteck abgeschätzt
			Rect.top    = 0;
			Rect.right  = 24;
			Rect.bottom = 24;

			float xs, ys;
			float xstart = float (xPos + 145.0f);
			float ystart = float (yPos + 203.0f);

			// Rechtecke für die Kollisionsabfrage rotieren lassen
			for (int i=0; i<25; i++)
			{
				// Zum anzeigen der Rects, die geprüft werden
				if (DebugMode == true)
					RenderRect(float(xstart-pTileEngine->XOffset),
							   float(ystart-pTileEngine->YOffset),
							   24, 24, 0x80FFFFFF);

				// Laser auf Kollision mit dem Spieler prüfen
				//

				xs = float (xstart);
				ys = float (ystart);

				for (int i = 0; i < NUMPLAYERS; i++)
				if (SpriteCollision (pPlayer[i]->xpos, pPlayer[i]->ypos, pPlayer[i]->CollideRect,
									 xs, ys, Rect) == true)
				{
					pPlayer[i]->DamagePlayer (10.0f SYNC);
				}

				// Und nächstes Rechteck
				//
				xstart += float(24*cos(PI * (360 - Winkel + 90) / 180));
				ystart += float(24*sin(PI * (360 - Winkel + 90) / 180));

				if (pTileEngine->BlockUnten (xs, ys, xs, ys, Rect) & BLOCKWERT_WAND)
				{
					// Funken und Rauch am Boden
					//
					if (rand()%2 == 0) pPartikelSystem->PushPartikel (xs + rand()%24, ys + rand()%24, FUNKE2);
					if (rand()%2 == 0) pPartikelSystem->PushPartikel (xs + rand()%24 - 15, ys + rand()%8 - 40, SMOKE2);
				}
			}
		}
		else
			pSoundManager->StopWave (SOUND_BRATLASER);

		if (FlareDelay > 800.0f)
		{
			FlareDelay = 0.0f;
			Handlung = GEGNER_STEHEN;
		}
	}
}
void GegnerPresswurst::DoKI(void)
{
	// Spieler kann von unten nicht durchspringen
	//
	for (int p = 0; p < NUMPLAYERS; p++)
	if (SpriteCollision(pPlayer[p]->xpos, 
						pPlayer[p]->ypos, 
						pPlayer[p]->CollideRect,
						xPos, yPos, GegnerRect[GegnerArt]) == true &&
						yPos < pPlayer[p]->ypos					   && 
						pPlayer[p]->yspeed < 0.0f)
						pPlayer[p]->yspeed *= -0.25f;

	// Kollisionsrechteck fürs Wegschieben
	GegnerRect[GegnerArt].top = 0;	
	Wegschieben(GegnerRect[GegnerArt], 0.0f);	

	// Kollisionsrechteck für das Unterteil	
	GegnerRect[GegnerArt].top = 251;	

	blocko = pTileEngine->BlockOben		  (xPos, yPos, yPosOld, yPosOld, GegnerRect[GegnerArt]);
	blocku = pTileEngine->BlockUntenNormal(xPos, yPos, yPosOld, yPosOld, GegnerRect[GegnerArt]);	

	// Ja nach Handlung richtig verhalten
	switch (Handlung)
	{
		// Am Anfang einmal initialisieren
		case GEGNER_INIT:
		{			
			yPos -= GegnerRect[GegnerArt].top;
			oldy = yPos;
			Handlung = GEGNER_INIT2;

		} break;

		// Auf Spieler warten
		case GEGNER_INIT2:
		{
			for (int p = 0; p < NUMPLAYERS; p++)
			if (pPlayer[p]->ypos > yPos		&&
				PlayerAbstandHoriz(pPlayer[p]) < 200  &&
				PlayerAbstandVert(pPlayer[p])  < 500)
			{
				Handlung = GEGNER_LAUFEN;
				ySpeed = 10.0f;
				yAcc = 2.5f;

				if (PlayerAbstand(true) < 600)
					pSoundManager->PlayWave3D((int)(xPos + 90), (int)(yPos + 330), 11025, SOUND_PRESSE);
			}
		} break;

		// Pressen
		case GEGNER_LAUFEN :
		{
			// Spieler beim Runterfallen berührt? Dann stirbt er leider ;)
			//
			for (int p = 0; p < NUMPLAYERS; p++)
			if (SpriteCollision(pPlayer[p]->xpos, 
								pPlayer[p]->ypos, 
								pPlayer[p]->CollideRect,
								xPos, yPos, GegnerRect[GegnerArt]) == true &&
								pPlayer[p]->ypos > yPos)
			{
				// wenn er steht, dann gleich zerquetschen
				if (pPlayer[p]->Handlung != SPRINGEN)
					pPlayer[p]->DamagePlayer(500.0f);

				// wenn er springt, dann runterdrücken
				else
				{
					//pPlayer->yspeed = 0.0f;
					//pPlayer->yadd = 0.0f;
					pPlayer[p]->ypos = yPos + GegnerRect[PRESSWURST].bottom;
				}
			}
			

			// Am Boden ? Dann Partikel erzeugen und zum "Produzieren" wechseln
			if (ySpeed > 0.0f &&
			   (blocku & BLOCKWERT_WAND		  ||
				blocku & BLOCKWERT_GEGNERWAND))
			{		
				// Spieler beim Runterfallen berührt? Dann stirbt er leider ;)
				//
				for (int p = 0; p < NUMPLAYERS; p++)
				if (SpriteCollision(pPlayer[p]->xpos, 
									pPlayer[p]->ypos, 
									pPlayer[p]->CollideRect,
									xPos, yPos, GegnerRect[GegnerArt]) == true &&
									pPlayer[p]->ypos > yPos)
									pPlayer[p]->DamagePlayer(500.0f);

				pTileEngine->BlockUnten(xPos, yPos, yPosOld, yPosOld, GegnerRect[GegnerArt]);	

				ySpeed = 0.0f;
				yAcc   = 0.0f;
				SmokeCount = 5.0f;
				
				if (PlayerAbstand() < 600)
					pSoundManager->PlayWave3D((int)(xPos + 90), (int)(yPos + 330), 11025, SOUND_DOORSTOP);

				ShakeScreen(2.0f);

				Handlung = GEGNER_SPECIAL;
			}

			// An der Decke ? Dann wieder in den Wartezustand setzen
			if (ySpeed < 0.0f &&
			   (blocko & BLOCKWERT_WAND		  ||
				blocko & BLOCKWERT_GEGNERWAND))
			{				
				ySpeed = 0.0f;
				yAcc   = 0.0f;				
							
				Handlung = GEGNER_INIT2;
			}

		} break;

		// Presse wartet unten und spuckt dann Dampf
		case GEGNER_SPECIAL:
		{
			SmokeCount -= 1.0f SYNC;

			if (SmokeCount <= 0.0f)
			{
				Handlung  = GEGNER_SPECIAL2;
				AnimCount = 28.0f;
				if (PlayerAbstand() < 600)
					pSoundManager->PlayWave3D((int)(xPos + 90), (int)(yPos + 330), 13000, SOUND_STEAM2);
			}
		} break;

		// Presse dampft
		case GEGNER_SPECIAL2:
		{
			// rauchen lassen
			SmokeCount -= 1.0f SYNC;
			if (SmokeCount <= 0.0f)
			{
				SmokeCount = 0.2f;

				pPartikelSystem->PushPartikel(xPos + 30.0f, yPos + 300.0f, SMOKE3_LU);
				pPartikelSystem->PushPartikel(xPos + 135.0f, yPos + 300.0f, SMOKE3_RU);
			}

			// Spinne spawnen
			AnimCount -= 1.0f SYNC;
			if (AnimCount < 0.0f)
			{
				// Spinne spawnen
				pGegner->PushGegner(xPos + 60.0f, yPos + 357 - GegnerRect[SPIDERBOMB].bottom, SPIDERBOMB, 0, 0, false, true);

				// wieder hochfahren
				Handlung = GEGNER_LAUFEN;
				ySpeed   = -15.0f;
				yAcc     = 0.2f;

				if (PlayerAbstand() < 600)
					pSoundManager->PlayWave3D((int)(xPos + 90), (int)(yPos + 330), 11025, SOUND_PRESSE);
			}
		} break;

	} // switch	
}