⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 bullets.cpp

📁 打飞机的过关游戏(linux)
💻 CPP
📖 第 1 页 / 共 2 页
字号:
#include "bullets.h"

void addBullet(object *theWeapon, object *attacker, int y, int dy)
{
	object *bullet;
	signed char imageIndex;
	int tempX, tempY, steps;

	bullet = new object;

	if (attacker == &player)
		currentGame.shots++;

	bullet->next = NULL;
	bullet->active = 1;
	bullet->x = attacker->x - ((attacker->image[0]->w / 2) * attacker->face);
	bullet->y = attacker->y + y;
	bullet->flags = theWeapon->flags;
	bullet->shield = 300; // bullets live for (approximately) 5 seconds

	// Timed explosions live between 1 and 3 seconds
	if (bullet->flags & WF_TIMEDEXPLOSION)
		bullet->shield = 60 + ((rand() % 3) * 60);

	if (attacker->face == 0)
	{
		bullet->dx = theWeapon->speed;
		if ((currentGame.area == 18) || (currentGame.area == 24))
			bullet->dx += fabs(engine.ssx);
	}
	else
	{
		bullet->dx = (0 - theWeapon->speed);
	}

	if (bullet->flags & WF_VARIABLE_SPEED)
	{
		bullet->dx = Math::rrand(100, 200);
		bullet->dx /= 10;
		if (attacker->face == 1)
			bullet->dx = 0 - bullet->dx;
	}

	bullet->dy = dy;

	if (bullet->flags & WF_SCATTER)
	{
		bullet->dy = Math::rrand(-200, 200);
		if (bullet->dy != 0)
			bullet->dy /= 200;
	}

	if (attacker->flags & FL_WEAPCO)
		bullet->flags += WF_WEAPCO;
	else
		bullet->flags += WF_FRIEND;

	bullet->owner = attacker->owner;

	bullet->id = theWeapon->id;

	bullet->damage = theWeapon->damage;

	if (bullet->id == WT_CHARGER)
	{
		bullet->damage = attacker->ammo[1];
		if (bullet->damage < 50)
		{
			bullet->damage = 1;
			bullet->id = WT_PLASMA;
		}
	}

	bullet->target = NULL;

	if (attacker->flags & FL_FRIEND)
		imageIndex = 0;
	else
		imageIndex = 1;

	// Use the enemy's images if applicable
	if (bullet->id != WT_ROCKET)
		bullet->image[0] = theWeapon->image[imageIndex];
	else
		bullet->image[0] = theWeapon->image[attacker->face];

	if (bullet->flags & WF_AIMED)
	{
		tempX = (int)fabs(attacker->target->x - attacker->x);
		tempY = (int)fabs(attacker->target->y - attacker->y);
		steps = max(tempX, tempY);

		if (steps == 0)
			steps = 12;

		if (!(bullet->flags & WF_TIMEDEXPLOSION))
			steps /= 8;
		else
			steps /= 6 + (rand() % 6);

		tempX = (int)(attacker->target->x - attacker->x);
		tempY = (int)(attacker->target->y - attacker->y);

		bullet->dx = tempX / steps;
		bullet->dy = tempY / steps;
	}

	if (attacker->classDef == CD_ASTEROID)
	{
		bullet->dx = Math::rrand(-20, 20);
		bullet->dy = Math::rrand(-20, 20);
		bullet->image[0] = graphics.shape[4];
	}

	engine.bulletTail->next = bullet;
	engine.bulletTail = bullet;
}

/*
Fill in later...
*/
void fireBullet(object *attacker, int weaponType)
{
	if (attacker->reload[weaponType] > 0)
		return;

	int y = (attacker->image[0]->h) / 5;

	// Remove some ammo from the player
	if ((attacker == &player) && (weaponType == 1) && (!engine.cheatAmmo))
		player.ammo[1]--;

	object *theWeapon = &weapon[attacker->weaponType[weaponType]];

	switch(theWeapon->id)
	{
		case WT_PLASMA:
		case WT_SPREAD:
		case WT_DIRECTIONAL:
			playSound(SFX_PLASMA);
			break;
		case WT_ROCKET:
			playSound(SFX_MISSILE);
			break;
		case WT_LASER:
			playSound(SFX_LASER);
			break;
		case WT_CHARGER:
			playSound(SFX_PLASMA3);
			break;
	}

	if (theWeapon->flags & WF_STRAIGHT)
	{
		switch (theWeapon->ammo[0])
		{
			case 1:
				addBullet(theWeapon, attacker, y * 3, 0);
				break;
			case 2:
				addBullet(theWeapon, attacker, y * 2, 0);
				addBullet(theWeapon, attacker, y * 4, 0);
				break;
			case 3:
				addBullet(theWeapon, attacker, y * 2, 0);
				addBullet(theWeapon, attacker, y * 3, 0);
				addBullet(theWeapon, attacker, y * 4, 0);
				break;
			case 4:
				addBullet(theWeapon, attacker, y, 0);
				addBullet(theWeapon, attacker, y * 2, 0);
				addBullet(theWeapon, attacker, y * 4, 0);
				addBullet(theWeapon, attacker, y * 5, 0);
				break;
			case 5:
				for (int i = 1 ; i < 6; i++)
					addBullet(theWeapon, attacker, y * i, 0);
				break;
		}
	}
	else if (theWeapon->flags & WF_THIN_SPREAD)
	{
		addBullet(theWeapon, attacker, y * 2, -1);
		if (theWeapon->ammo[0] == 3)
		{
			addBullet(theWeapon, attacker, y * 3, 0);
		}
		else
		{
			addBullet(theWeapon, attacker, y * 2, 0);
			addBullet(theWeapon, attacker, y * 4, 0);
		}
		addBullet(theWeapon, attacker, y * 4, 1);
	}
	else if (theWeapon->flags & WF_WIDE_SPREAD)
	{
		addBullet(theWeapon, attacker, y * 1, -2);
		addBullet(theWeapon, attacker, y * 2, -1);
		addBullet(theWeapon, attacker, y * 3, 0);
		addBullet(theWeapon, attacker, y * 4, 1);
		addBullet(theWeapon, attacker, y * 5, 2);
	}

	// Reset the weapon reload time. Double it if it is not friendly or a boss or Kline
	attacker->reload[weaponType] = theWeapon->reload[0];
	if ((attacker->flags & FL_WEAPCO) && (attacker != &enemy[WC_BOSS]) && (attacker != &enemy[WC_KLINE]) && (theWeapon->id != W_LASER))
		attacker->reload[weaponType] *= 2;

	if ((engine.cheatAmmo) || (theWeapon->id == WT_LASER))
		return;

	if ((attacker == &player) && (weaponType == 0))
	{
		if (player.ammo[0] > 0)
		{
			player.ammo[0]--;
			if (player.ammo[0] == 0)
			{
				player.weaponType[0] = W_PLAYER_WEAPON;
				weapon[W_PLAYER_WEAPON2] = weapon[W_PLAYER_WEAPON]; // reset to weapon 1 defaults
			}
		}
	}
}

/*
Used for homing missiles. When a missile is active and it is told to home in
on an enemy, it will attempt to randomly grab one every frame if it does not
already have a target. If the target it is currently chasing is killed, it will
begin to look for a new one (done in doBullets()). The homing missile will make
one attempt per call (one call per frame) to find a suitable target. If the target
it picks is dead or outside the screen range, then it returns NULL. A suitable
target will be returned as the object address.
*/
object *getRandomEnemy(object *bullet)
{
	int i;

	if (bullet->owner->flags & FL_WEAPCO)
	{
		i = (rand() % 10);

		if (i < 1)
			return &player;
	}

	i = rand() % MAX_ALIENS;

	if ((enemy[i].shield < 1) || (!enemy[i].active))
		return NULL;

	if ((bullet->owner->flags & FL_WEAPCO) && (enemy[i].flags & FL_WEAPCO))
		return NULL;

	if ((bullet->owner->flags & FL_FRIEND) && (enemy[i].flags & FL_FRIEND))
		return NULL;

	if (abs((int)bullet->x - (int)enemy[i].target->x) > 800)
		return NULL;

	if (abs((int)bullet->y - (int)enemy[i].target->y) > 200)
		return NULL;

	return &enemy[i];
}

/*
Fill in later...
*/
void destroyAlien(object *bullet, object *theEnemy)
{
	playSound(SFX_EXPLOSION);

	// Chain reaction destruction if needed
	if (theEnemy->flags & FL_DAMAGEOWNER)
	{
		theEnemy->owner->shield -= theEnemy->maxShield;
		if (theEnemy->owner->shield < 1)
			destroyAlien(bullet, theEnemy->owner);
	}

	if (theEnemy->flags & FL_FRIEND)
	{
		if (theEnemy->classDef == CD_PHOEBE)
			currentGame.wingMate1Ejects++;
		else if (theEnemy->classDef == CD_URSULA)
			currentGame.wingMate2Ejects++;

		// Phoebe cannot eject on the rescue mission
		if (currentGame.area != 7)
		{
			if ((theEnemy->classDef == CD_PHOEBE) || (theEnemy->classDef == CD_URSULA))
				setInfoLine(">> Ally has ejected! <<\n", FONT_RED);
			else
				setInfoLine(">> Friendly craft has been destroy!! <<\n", FONT_RED);
		}
	}

	if (bullet->owner == &player)
	{
		// Once again, stop point leeching
		if (currentGame.area != MAX_MISSIONS - 1)
			currentGame.cash += theEnemy->score;
		currentGame.cashEarned += theEnemy->score;
		currentGame.totalKills++;
	}
	else if (bullet->owner->classDef == CD_PHOEBE)
	{
		currentGame.wingMate1Kills++;
	}
	else if (bullet->owner->classDef == CD_URSULA)
	{
		currentGame.wingMate2Kills++;
	}
	else
	{
		currentGame.totalOtherKills++;
	}

	if ((bullet->owner->classDef == CD_PHOEBE) || (bullet->owner->classDef == CD_URSULA))
	{
		if ((rand() % 8) == 0)
		{
			getKillMessage(bullet->owner);
		}
	}

	updateMissionRequirements(M_DESTROY_TARGET_TYPE, theEnemy->classDef, 1);
	updateMissionRequirements(M_PROTECT_TARGET, theEnemy->classDef, 1);

	if (rand() % 100 <= theEnemy->collectChance)
	{
		unsigned char value;

		if ((rand() % 10) == 0)
			theEnemy->collectValue *= 2;

		while (theEnemy->collectValue > 0)
		{
			value = (10 + (rand() % theEnemy->collectValue));
			if (value > theEnemy->collectValue)
				value =theEnemy->collectValue;
			addCollectable(theEnemy->x, theEnemy->y, theEnemy->collectType, value, 600);
			theEnemy->collectValue -= value;
		}
	}

	// Make it explode immediately
	if (theEnemy->classDef == CD_ASTEROID)
	{
		theEnemy->shield = -999;
		if ((currentGame.area == 10) && (theEnemy != &enemy[0]) && (currentMission.completed1[0] == 0) && (currentMission.targetValue1[1] == 1))
			engine.targetArrowTimer = 120;
	}

	if ((theEnemy->classDef == CD_KRASS) && (bullet->owner == &player))
		setRadioMessage(FACE_CHRIS, "My NAME is CHRIS!!!!!!!!", 1);

	if (theEnemy->classDef == CD_KLINE)
	{
		setRadioMessage(FACE_KLINE, "It was an honor... to have fought you...", 1);
		theEnemy->dx = theEnemy->dy = 0;
		theEnemy->maxShield = 1500;
		theEnemy->shield = -200;
	}
}

char checkPlayerShockDamage(float x, float y, int radius)
{
	// Don't let the player be hurt by an explosion after they have completed
	// all the mission objectives. That would be *really* annoying!
	if ((engine.cheatShield) || (engine.missionCompleteTimer != 0))
		return 0;

	float distX = fabs(x - player.x);
	float distY = fabs(y - player.y);

	if ((distX <= 50) && (distY <= 50))
	{
		if (distX >= 1)
			distX /= 5;

		if (distY >= 1)
			distY /= 5;

		player.shield -= (int)(10 - distX);
		player.shield -= (int)(10 - distY);
		Math::limitInt(&player.shield, 0, player.maxShield);
		player.hit = 10;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -