Пример #1
0
static void CampaignIntroDraw(void *data)
{
	// This will only draw once
	const CampaignSetting *c = data;

	GraphicsBlitBkg(&gGraphicsDevice);
	const int w = gGraphicsDevice.cachedConfig.Res.x;
	const int h = gGraphicsDevice.cachedConfig.Res.y;
	const int y = h / 4;

	// Display title + author
	char *buf;
	CMALLOC(buf, strlen(c->Title) + strlen(c->Author) + 16);
	sprintf(buf, "%s by %s", c->Title, c->Author);
	FontOpts opts = FontOptsNew();
	opts.HAlign = ALIGN_CENTER;
	opts.Area = gGraphicsDevice.cachedConfig.Res;
	opts.Pad.y = y - 25;
	FontStrOpt(buf, Vec2iZero(), opts);
	CFREE(buf);

	// Display campaign description
	// allow some slack for newlines
	if (strlen(c->Description) > 0)
	{
		CMALLOC(buf, strlen(c->Description) * 2);
		// Pad about 1/6th of the screen width total (1/12th left and right)
		FontSplitLines(c->Description, buf, w * 5 / 6);
		FontStr(buf, Vec2iNew(w / 12, y));
		CFREE(buf);
	}
}
Пример #2
0
static void MissionBriefingDraw(void *data)
{
	const MissionBriefingData *mData = data;

	GraphicsBlitBkg(&gGraphicsDevice);

	// Mission title
	FontStrOpt(mData->Title, Vec2iZero(), mData->TitleOpts);
	// Display password
	FontStrOpt(mData->Password, Vec2iZero(), mData->PasswordOpts);
	// Display description with typewriter effect
	FontStr(mData->TypewriterBuf, mData->DescriptionPos);
	// Display objectives
	for (int i = 0;
		i < (int)mData->MissionOptions->missionData->Objectives.size;
		i++)
	{
		const MissionObjective *o =
			CArrayGet(&mData->MissionOptions->missionData->Objectives, i);
		// Do not brief optional objectives
		if (o->Required == 0)
		{
			continue;
		}
		const Vec2i yInc = Vec2iNew(0, i * mData->ObjectiveHeight);
		FontStr(o->Description, Vec2iAdd(mData->ObjectiveDescPos, yInc));
		DrawObjectiveInfo(
			mData->MissionOptions, i, Vec2iAdd(mData->ObjectiveInfoPos, yInc));
	}
}
Пример #3
0
void MenuLoop(MenuSystem *menu)
{
	assert(menu->numExitTypes > 0);
	for (;; SDL_Delay(10))
	{
		// Input
		InputPoll(menu->joysticks, menu->keyboard);
		// Update
		if (menu->current->type == MENU_TYPE_KEYS &&
			menu->current->u.normal.changeKeyMenu != NULL)
		{
			MenuProcessChangeKey(menu->current);
		}
		else
		{
			int cmd = GetMenuCmd();
			menu->current = MenuProcessCmd(menu->current, cmd);
		}
		if (MenuHasExitType(menu, menu->current->type))
		{
			break;
		}
		// Draw
		if (menu->graphics != NULL)
		{
			GraphicsBlitBkg(menu->graphics);
		}
		ShowControls();
		MenuDisplay(menu);
		CopyToScreen();
	}
}
Пример #4
0
static void MenuDraw(void *data)
{
	const MenuSystem *ms = data;
	GraphicsBlitBkg(ms->graphics);
	ShowControls();
	MenuDisplay(ms);
}
Пример #5
0
void MenuLoop(MenuSystem *menu)
{
	assert(menu->numExitTypes > 0);
	for (;; SDL_Delay(10))
	{
		MusicSetPlaying(&gSoundDevice, SDL_GetAppState() & SDL_APPINPUTFOCUS);
		// Input
		InputPoll(menu->inputDevices, SDL_GetTicks());
		// Update
		if (menu->current->type == MENU_TYPE_KEYS &&
			menu->current->u.normal.changeKeyMenu != NULL)
		{
			MenuProcessChangeKey(menu->current);
		}
		else
		{
			int cmd = GetMenuCmd(gPlayerDatas);
			MenuProcessCmd(menu, cmd);
		}
		if (MenuIsExit(menu))
		{
			break;
		}
		// Draw
		GraphicsBlitBkg(menu->graphics);
		ShowControls();
		MenuDisplay(menu);
		BlitFlip(menu->graphics, &gConfig.Graphics);
	}
}
Пример #6
0
int NumPlayersSelection(
	int *numPlayers, campaign_mode_e mode,
	GraphicsDevice *graphics, InputDevices *input)
{
	MenuSystem ms;
	int i;
	int res = 0;
	MenuSystemInit(
		&ms, input, graphics,
		Vec2iZero(),
		Vec2iNew(
			graphics->cachedConfig.ResolutionWidth,
			graphics->cachedConfig.ResolutionHeight));
	ms.root = ms.current = MenuCreateNormal(
		"",
		"Select number of players",
		MENU_TYPE_NORMAL,
		0);
	for (i = 0; i < MAX_PLAYERS; i++)
	{
		if (mode == CAMPAIGN_MODE_DOGFIGHT && i == 0)
		{
			// At least two players for dogfights
			continue;
		}
		char buf[2];
		sprintf(buf, "%d", i + 1);
		MenuAddSubmenu(ms.current, MenuCreateReturn(buf, i + 1));
	}
	MenuAddExitType(&ms, MENU_TYPE_RETURN);

	for (;;)
	{
		int cmd;
		InputPoll(&gInputDevices, SDL_GetTicks());
		if (KeyIsPressed(&gInputDevices.keyboard, SDLK_ESCAPE))
		{
			res = 0;
			break;	// hack to allow exit
		}
		cmd = GetMenuCmd(gPlayerDatas);
		MenuProcessCmd(&ms, cmd);
		if (MenuIsExit(&ms))
		{
			*numPlayers = ms.current->u.returnCode;
			res = 1;
			break;
		}

		GraphicsBlitBkg(graphics);
		MenuDisplay(&ms);
		BlitFlip(graphics, &gConfig.Graphics);
		SDL_Delay(10);
	}

	MenuSystemTerminate(&ms);
	return res;
}
Пример #7
0
static void DogfightFinalScoresDraw(void *data)
{
	UNUSED(data);

	// This will only draw once
	const int w = gGraphicsDevice.cachedConfig.Res.x;
	const int h = gGraphicsDevice.cachedConfig.Res.y;

	GraphicsBlitBkg(&gGraphicsDevice);

	// Work out who's the winner, or if it's a tie
	int maxScore = 0;
	int playersWithMaxScore = 0;
	for (int i = 0; i < (int)gPlayerDatas.size; i++)
	{
		const PlayerData *p = CArrayGet(&gPlayerDatas, i);
		if (p->RoundsWon > maxScore)
		{
			maxScore = p->RoundsWon;
			playersWithMaxScore = 1;
		}
		else if (p->RoundsWon == maxScore)
		{
			playersWithMaxScore++;
		}
	}
	const bool isTie = playersWithMaxScore == (int)gPlayerDatas.size;

	// Draw players and their names spread evenly around the screen.
	// If it's a tie, display the message in the centre,
	// otherwise display the winner just below the winning player
#define DRAW_TEXT	"It's a draw!"
#define WINNER_TEXT	"Winner!"
	CASSERT(
		gPlayerDatas.size >= 2 && gPlayerDatas.size <= 4,
		"Unimplemented number of players for dogfight");
	for (int i = 0; i < (int)gPlayerDatas.size; i++)
	{
		const Vec2i pos = Vec2iNew(
			w / 4 + (i & 1) * w / 2,
			gPlayerDatas.size == 2 ? h / 2 : h / 4 + (i / 2) * h / 2);
		const PlayerData *p = CArrayGet(&gPlayerDatas, i);
		DisplayCharacterAndName(pos, &p->Char, p->name);
		ShowPlayerScore(pos, p->RoundsWon);
		if (!isTie && maxScore == p->RoundsWon)
		{
			FontStrMask(
				WINNER_TEXT,
				Vec2iNew(pos.x - FontStrW(WINNER_TEXT) / 2, pos.y + 30),
				colorGreen);
		}
	}
	if (isTie)
	{
		FontStrCenter(DRAW_TEXT);
	}
}
Пример #8
0
static void PlayerEquipDraw(void *data)
{
	const PlayerEquipData *pData = data;
	GraphicsBlitBkg(&gGraphicsDevice);
	for (int i = 0; i < GetNumPlayers(false, false, true); i++)
	{
		MenuDisplay(&pData->menus[i].ms);
	}
}
Пример #9
0
static void DeathmatchFinalScoresDraw(void *data)
{
	UNUSED(data);

	// This will only draw once
	const int w = gGraphicsDevice.cachedConfig.Res.x;
	const int h = gGraphicsDevice.cachedConfig.Res.y;

	GraphicsBlitBkg(&gGraphicsDevice);

	// Work out the highest kills
	int maxKills = 0;
	for (int i = 0; i < (int)gPlayerDatas.size; i++)
	{
		const PlayerData *p = CArrayGet(&gPlayerDatas, i);
		if (p->kills > maxKills)
		{
			maxKills = p->kills;
		}
	}

	// Draw players and their names spread evenly around the screen.
	CASSERT(
		gPlayerDatas.size >= 2 && gPlayerDatas.size <= 4,
		"Unimplemented number of players for deathmatch");
#define LAST_MAN_TEXT	"Last man standing!"
	for (int i = 0; i < (int)gPlayerDatas.size; i++)
	{
		const Vec2i pos = Vec2iNew(
			w / 4 + (i & 1) * w / 2,
			gPlayerDatas.size == 2 ? h / 2 : h / 4 + (i / 2) * h / 2);
		const PlayerData *p = CArrayGet(&gPlayerDatas, i);
		DisplayCharacterAndName(pos, &p->Char, p->name);
		
		// Kills
		char s[16];
		sprintf(s, "Kills: %d", p->kills);
		FontStrMask(
			s, Vec2iNew(pos.x - FontStrW(s) / 2, pos.y + 20),
			p->kills == maxKills ? colorGreen : colorWhite);

		// Last man standing?
		if (p->Lives > 0)
		{
			FontStrMask(
				LAST_MAN_TEXT,
				Vec2iNew(pos.x - FontStrW(LAST_MAN_TEXT) / 2, pos.y + 30),
				colorGreen);
		}
	}
}
Пример #10
0
static void PlayerSelectionDraw(void *data)
{
	const PlayerSelectionData *pData = data;

	GraphicsBlitBkg(&gGraphicsDevice);
	const int w = gGraphicsDevice.cachedConfig.Res.x;
	const int h = gGraphicsDevice.cachedConfig.Res.y;
	int idx = 0;
	for (int i = 0; i < (int)gPlayerDatas.size; i++, idx++)
	{
		const PlayerData *p = CArrayGet(&gPlayerDatas, i);
		if (!p->IsLocal)
		{
			idx--;
			continue;
		}
		if (p->inputDevice != INPUT_DEVICE_UNSET)
		{
			MenuDisplay(&pData->menus[idx].ms);
		}
		else
		{
			Vec2i center = Vec2iZero();
			const char *prompt = "Press Fire to join...";
			const Vec2i offset = Vec2iScaleDiv(FontStrSize(prompt), -2);
			switch (GetNumPlayers(false, false, true))
			{
			case 1:
				// Center of screen
				center = Vec2iNew(w / 2, h / 2);
				break;
			case 2:
				// Side by side
				center = Vec2iNew(idx * w / 2 + w / 4, h / 2);
				break;
			case 3:
			case 4:
				// Four corners
				center = Vec2iNew(
					(idx & 1) * w / 2 + w / 4, (idx / 2) * h / 2 + h / 4);
				break;
			default:
				CASSERT(false, "not implemented");
				break;
			}
			FontStr(prompt, Vec2iAdd(center, offset));
		}
	}
}
Пример #11
0
static void DogfightScoresDraw(void *data)
{
	UNUSED(data);

	// This will only draw once
	const int w = gGraphicsDevice.cachedConfig.Res.x;
	const int h = gGraphicsDevice.cachedConfig.Res.y;

	GraphicsBlitBkg(&gGraphicsDevice);

	CASSERT(
		gPlayerDatas.size >= 2 && gPlayerDatas.size <= 4,
		"Unimplemented number of players for dogfight");
	for (int i = 0; i < (int)gPlayerDatas.size; i++)
	{
		const Vec2i pos = Vec2iNew(
			w / 4 + (i & 1) * w / 2,
			gPlayerDatas.size == 2 ? h / 2 : h / 4 + (i / 2) * h / 2);
		const PlayerData *p = CArrayGet(&gPlayerDatas, i);
		DisplayCharacterAndName(pos, &p->Char, p->name);
		ShowPlayerScore(pos, p->RoundsWon);
	}
}
Пример #12
0
static void VictoryDraw(void *data)
{
	// This will only draw once
	const CampaignOptions *c = data;

	GraphicsBlitBkg(&gGraphicsDevice);
	const int w = gGraphicsDevice.cachedConfig.Res.x;
	const int h = gGraphicsDevice.cachedConfig.Res.y;
	FontOpts opts = FontOptsNew();
	opts.HAlign = ALIGN_CENTER;
	opts.Area = gGraphicsDevice.cachedConfig.Res;
	int y = 100;

	// Congratulations text
#define CONGRATULATIONS "Congratulations, you have completed "
	FontStrOpt(CONGRATULATIONS, Vec2iNew(0, y), opts);
	y += 15;
	opts.Mask = colorRed;
	FontStrOpt(c->Setting.Title, Vec2iNew(0, y), opts);

	// Display players
	switch (gPlayerDatas.size)
	{
	case 1:
		{
			const PlayerData *p = CArrayGet(&gPlayerDatas, 0);
			DisplayCharacterAndName(Vec2iNew(w / 4, h / 4), &p->Char, p->name);
		}
		break;
	case 2:
		{
			// side by side
			const PlayerData *p1 = CArrayGet(&gPlayerDatas, 0);
			DisplayCharacterAndName(
				Vec2iNew(w / 8, h / 4), &p1->Char, p1->name);
			const PlayerData *p2 = CArrayGet(&gPlayerDatas, 1);
			DisplayCharacterAndName(
				Vec2iNew(w / 8 + w / 2, h / 4), &p2->Char, p2->name);
		}
		break;
	case 3:	// fallthrough
	case 4:
		{
			// 2x2
			const PlayerData *p1 = CArrayGet(&gPlayerDatas, 0);
			DisplayCharacterAndName(
				Vec2iNew(w / 8, h / 8), &p1->Char, p1->name);
			const PlayerData *p2 = CArrayGet(&gPlayerDatas, 1);
			DisplayCharacterAndName(
				Vec2iNew(w / 8 + w / 2, h / 8), &p2->Char, p2->name);
			const PlayerData *p3 = CArrayGet(&gPlayerDatas, 2);
			DisplayCharacterAndName(
				Vec2iNew(w / 8, h / 8 + h / 4), &p3->Char, p3->name);
			if (gPlayerDatas.size == 4)
			{
				const PlayerData *p4 = CArrayGet(&gPlayerDatas, 3);
				DisplayCharacterAndName(
					Vec2iNew(w / 8 + w / 2, h / 8 + h / 4),
					&p4->Char, p4->name);
			}
		}
		break;
	default:
		CASSERT(false, "not implemented");
		break;
	}

	// Final words
	const char *finalWordsSingle[] = {
		"Ha, next time I'll use my good hand",
		"Over already? I was just warming up...",
		"There's just no good opposition to be found these days!",
		"Well, maybe I'll just do my monthly reload then",
		"Woof woof",
		"I'll just bury the bones in the back yard, he-he",
		"I just wish they'd let me try bare-handed",
		"Rambo? Who's Rambo?",
		"<in Austrian accent:> I'll be back",
		"Gee, my trigger finger is sore",
		"I need more practice. I think I missed a few shots at times"
	};
	const char *finalWordsMulti[] = {
		"United we stand, divided we conquer",
		"Nothing like good teamwork, is there?",
		"Which way is the camera?",
		"We eat bullets for breakfast and have grenades as dessert",
		"We're so cool we have to wear mittens",
	};
	const char *finalWords;
	if (gPlayerDatas.size == 1)
	{
		const int numWords = sizeof finalWordsSingle / sizeof(char *);
		finalWords = finalWordsSingle[rand() % numWords];
	}
	else
	{
		const int numWords = sizeof finalWordsMulti / sizeof(char *);
		finalWords = finalWordsMulti[rand() % numWords];
	}
	Vec2i pos = Vec2iNew((w - FontStrW(finalWords)) / 2, h / 2 + 20);
	pos = FontChMask('"', pos, colorDarker);
	pos = FontStrMask(finalWords, pos, colorPurple);
	FontChMask('"', pos, colorDarker);
}
Пример #13
0
static void MissionSummaryDraw(void *data)
{
	// This will only draw once
	const struct MissionOptions *m = data;

	GraphicsBlitBkg(&gGraphicsDevice);
	const int w = gGraphicsDevice.cachedConfig.Res.x;
	const int h = gGraphicsDevice.cachedConfig.Res.y;

	// Display password
	if (strlen(gAutosave.LastMission.Password) > 0)
	{
		char s[64];
		sprintf(s, "Last password: %s", gAutosave.LastMission.Password);
		FontOpts opts = FontOptsNew();
		opts.HAlign = ALIGN_CENTER;
		opts.VAlign = ALIGN_END;
		opts.Area = gGraphicsDevice.cachedConfig.Res;
		opts.Pad.y = opts.Area.y / 12;
		FontStrOpt(s, Vec2iZero(), opts);
	}

	// Display objectives and bonuses
	Vec2i pos = Vec2iNew(w / 6, h / 2 + h / 10);
	int idx = 1;
	for (int i = 0; i < (int)m->missionData->Objectives.size; i++)
	{
		const struct Objective *o = CArrayGet(&m->Objectives, i);
		const MissionObjective *mo = CArrayGet(&m->missionData->Objectives, i);

		// Do not mention optional objectives with none completed
		if (o->done == 0 && mo->Required == 0)
		{
			continue;
		}

		// Objective icon
		DrawObjectiveInfo(m, i, Vec2iAdd(pos, Vec2iNew(-26, FontH())));

		// Objective completion text
		char s[100];
		sprintf(s, "Objective %d: %d of %d, %d required",
			idx, o->done, mo->Count, mo->Required);
		FontOpts opts = FontOptsNew();
		opts.Area = gGraphicsDevice.cachedConfig.Res;
		opts.Pad = pos;
		if (mo->Required == 0)
		{
			// Show optional objectives in purple
			opts.Mask = colorPurple;
		}
		FontStrOpt(s, Vec2iZero(), opts);

		// Objective status text
		opts = FontOptsNew();
		opts.HAlign = ALIGN_END;
		opts.Area = gGraphicsDevice.cachedConfig.Res;
		opts.Pad = pos;
		if (o->done < mo->Required)
		{
			opts.Mask = colorRed;
			FontStrOpt("Failed", Vec2iZero(), opts);
		}
		else if (
			o->done == mo->Count && o->done > mo->Required && AreAnySurvived())
		{
			opts.Mask = colorGreen;
			char buf[16];
			sprintf(buf, "Perfect: %d", PERFECT_BONUS);
			FontStrOpt(buf, Vec2iZero(), opts);
		}
		else if (mo->Required > 0)
		{
			FontStrOpt("Done", Vec2iZero(), opts);
		}
		else
		{
			FontStrOpt("Bonus!", Vec2iZero(), opts);
		}

		pos.y += 15;
		idx++;
	}

	// Draw other bonuses
	if (AreAnySurvived())
	{
		char s[64];

		sprintf(s, "Access bonus: %d", GetAccessBonus(m));
		FontStr(s, pos);

		pos.y += FontH() + 1;
		int seconds;
		const int timeBonus = GetTimeBonus(m, &seconds);
		sprintf(s, "Time bonus: %d secs x 25 = %d", seconds, timeBonus);
		FontStr(s, pos);
	}

	// Draw per-player summaries
	Vec2i size;
	switch (gPlayerDatas.size)
	{
	case 1:
		size = Vec2iNew(w, h / 2);
		DrawPlayerSummary(Vec2iZero(), size, CArrayGet(&gPlayerDatas, 0));
		break;
	case 2:
		// side by side
		size = Vec2iNew(w / 2, h / 2);
		DrawPlayerSummary(Vec2iZero(), size, CArrayGet(&gPlayerDatas, 0));
		DrawPlayerSummary(
			Vec2iNew(w / 2, 0), size, CArrayGet(&gPlayerDatas, 1));
		break;
	case 3:	// fallthrough
	case 4:
		// 2x2
		size = Vec2iNew(w / 2, h / 4);
		DrawPlayerSummary(Vec2iZero(), size, CArrayGet(&gPlayerDatas, 0));
		DrawPlayerSummary(
			Vec2iNew(w / 2, 0), size, CArrayGet(&gPlayerDatas, 1));
		DrawPlayerSummary(
			Vec2iNew(0, h / 4), size, CArrayGet(&gPlayerDatas, 2));
		if (gPlayerDatas.size == 4)
		{
			DrawPlayerSummary(
				Vec2iNew(w / 2, h / 4), size, CArrayGet(&gPlayerDatas, 3));
		}
		break;
	default:
		CASSERT(false, "not implemented");
		break;
	}
}
Пример #14
0
int PlayerEquip(int numPlayers, GraphicsDevice *graphics)
{
	int i;
	WeaponMenu menus[MAX_PLAYERS];
	for (i = 0; i < numPlayers; i++)
	{
		WeaponMenuCreate(
			&menus[i], numPlayers, i,
			&gCampaign.Setting.characters.players[i], &gPlayerDatas[i],
			&gInputDevices, graphics, &gConfig.Input);
	}

	debug(D_NORMAL, "\n");

	for (;;)
	{
		int cmds[MAX_PLAYERS];
		int isDone = 1;
		InputPoll(&gInputDevices, SDL_GetTicks());
		if (KeyIsPressed(&gInputDevices.keyboard, SDLK_ESCAPE))
		{
			return 0; // hack to exit from menu
		}
		GetPlayerCmds(&cmds, gPlayerDatas);
		for (i = 0; i < numPlayers; i++)
		{
			if (!MenuIsExit(&menus[i].ms))
			{
				MenuProcessCmd(&menus[i].ms, cmds[i]);
			}
			else if (gPlayerDatas[i].weaponCount == 0)
			{
				// Check exit condition; must have selected at least one weapon
				// Otherwise reset the current menu
				menus[i].ms.current = menus[i].ms.root;
			}
		}
		for (i = 0; i < numPlayers; i++)
		{
			if (!MenuIsExit(&menus[i].ms))
			{
				isDone = 0;
			}
		}
		if (isDone)
		{
			break;
		}

		GraphicsBlitBkg(graphics);
		for (i = 0; i < numPlayers; i++)
		{
			MenuDisplay(&menus[i].ms);
		}
		BlitFlip(graphics, &gConfig.Graphics);
		SDL_Delay(10);
	}

	for (i = 0; i < numPlayers; i++)
	{
		MenuSystemTerminate(&menus[i].ms);
	}
	return 1;
}
Пример #15
0
int PlayerSelection(int numPlayers, GraphicsDevice *graphics)
{
	int i;
	int hasInputDevice[MAX_PLAYERS];
	PlayerSelectMenu menus[MAX_PLAYERS];
	for (i = 0; i < numPlayers; i++)
	{
		PlayerSelectMenusCreate(
			&menus[i], numPlayers, i,
			&gCampaign.Setting.characters.players[i], &gPlayerDatas[i],
			&gInputDevices, graphics, &gConfig.Input);
		hasInputDevice[i] = 0;
	}

	KeyInit(&gInputDevices.keyboard);
	for (;;)
	{
		int cmds[MAX_PLAYERS];
		int isDone = 1;
		InputPoll(&gInputDevices, SDL_GetTicks());
		if (KeyIsPressed(&gInputDevices.keyboard, SDLK_ESCAPE))
		{
			// TODO: destroy menus
			return 0; // hack to allow exit
		}
		GetPlayerCmds(&cmds, gPlayerDatas);
		for (i = 0; i < numPlayers; i++)
		{
			if (hasInputDevice[i] && !MenuIsExit(&menus[i].ms))
			{
				MenuProcessCmd(&menus[i].ms, cmds[i]);
			}
		}
		for (i = 0; i < numPlayers; i++)
		{
			if (!MenuIsExit(&menus[i].ms))
			{
				isDone = 0;
			}
		}
		if (isDone)
		{
			break;
		}

		AssignPlayerInputDevices(
			hasInputDevice, numPlayers,
			gPlayerDatas, &gInputDevices, &gConfig.Input);

		GraphicsBlitBkg(graphics);
		for (i = 0; i < numPlayers; i++)
		{
			if (hasInputDevice[i])
			{
				MenuDisplay(&menus[i].ms);
			}
			else
			{
				Vec2i center;
				const char *prompt = "Press Fire to join...";
				Vec2i offset = Vec2iScaleDiv(TextGetSize(prompt), -2);
				int w = graphics->cachedConfig.ResolutionWidth;
				int h = graphics->cachedConfig.ResolutionHeight;
				switch (numPlayers)
				{
				case 1:
					// Center of screen
					center = Vec2iNew(w / 2, h / 2);
					break;
				case 2:
					// Side by side
					center = Vec2iNew(i * w / 2 + w / 4, h / 2);
					break;
				case 3:
				case 4:
					// Four corners
					center = Vec2iNew(
						(i & 1) * w / 2 + w / 4, (i / 2) * h / 2 + h / 4);
					break;
				default:
					assert(0 && "not implemented");
					break;
				}
				DrawTextString(prompt, graphics, Vec2iAdd(center, offset));
			}
		}
		BlitFlip(graphics, &gConfig.Graphics);
		SDL_Delay(10);
	}

	for (i = 0; i < numPlayers; i++)
	{
		MenuSystemTerminate(&menus[i].ms);
	}
	return 1;
}
Пример #16
0
static void Display(GraphicsDevice *g, int yc, HandleInputResult result)
{
	char s[128];
	int y = 5;
	int i;
	int w = g->cachedConfig.Res.x;
	int h = g->cachedConfig.Res.y;
	Mission *mission = CampaignGetCurrentMission(&gCampaign);

	if (mission)
	{
		// Re-make the background if the resolution has changed
		if (gEventHandlers.HasResolutionChanged)
		{
			MakeBackground(g, 0);
		}
		if (result.RemakeBg || brush.IsGuideImageNew)
		{
			// Clear background first
			for (i = 0; i < GraphicsGetScreenSize(&g->cachedConfig); i++)
			{
				g->buf[i] = PixelFromColor(g, colorBlack);
			}
			brush.IsGuideImageNew = false;
			GrafxDrawExtra extra;
			extra.guideImage = brush.GuideImageSurface;
			extra.guideImageAlpha = brush.GuideImageAlpha;
			GrafxDrawBackground(g, &sDrawBuffer, tintNone, camera, &extra);
		}
		GraphicsBlitBkg(g);

		// Draw brush highlight tiles
		if (brush.IsActive && IsBrushPosValid(brush.Pos, mission))
		{
			EditorBrushSetHighlightedTiles(&brush);
		}
		for (i = 0; i < (int)brush.HighlightedTiles.size; i++)
		{
			Vec2i *pos = CArrayGet(&brush.HighlightedTiles, i);
			Vec2i screenPos = GetScreenPos(*pos);
			if (screenPos.x >= 0 && screenPos.x < w &&
				screenPos.y >= 0 && screenPos.y < h)
			{
				DrawRectangle(
					g,
					screenPos, Vec2iNew(TILE_WIDTH, TILE_HEIGHT),
					colorWhite, DRAW_FLAG_LINE);
			}
		}

		sprintf(
			s, "Mission %d/%d",
			gCampaign.MissionIndex + 1, (int)gCampaign.Setting.Missions.size);
		TextStringMasked(&gTextManager, 
			s, g, Vec2iNew(270, y),
			yc == YC_MISSIONINDEX ? colorRed : colorWhite);
		if (brush.LastPos.x)
		{
			sprintf(s, "(%d, %d)", brush.Pos.x, brush.Pos.y);
			TextString(&gTextManager, s, g, Vec2iNew(w - 40, h - 16));
		}
	}
	else
	{
		ClearScreen(g);
		if (gCampaign.Setting.Missions.size)
		{
			sprintf(s, "End/%d", (int)gCampaign.Setting.Missions.size);
			TextStringMasked(&gTextManager, 
				s, g, Vec2iNew(270, y),
				yc == YC_MISSIONINDEX ? colorRed : colorWhite);
		}
	}

	if (fileChanged)
	{
		DrawTPic(10, y, PicManagerGetOldPic(&gPicManager, 221));
	}

	TextString(&gTextManager, 
		"Press F1 for help", g, Vec2iNew(20, h - 20 - CDogsTextHeight()));

	y = 150;

	UIObjectDraw(
		sObjs, g, Vec2iZero(), gEventHandlers.mouse.currentPos, &sDrawObjs);

	if (result.WillDisplayAutomap && mission)
	{
		AutomapDraw(AUTOMAP_FLAGS_SHOWALL, true);
	}
	else
	{
		if (sTooltipObj && sTooltipObj->Tooltip)
		{
			UITooltipDraw(
				g, gEventHandlers.mouse.currentPos, sTooltipObj->Tooltip);
		}
		MouseDraw(&gEventHandlers.mouse);
	}
	BlitFlip(g, &gConfig.Graphics);
}