Beispiel #1
0
/* The main game loop */
GAMECODE gameLoop()
{
	static uint32_t lastFlushTime = 0;

	static int renderBudget = 0;  // Scaled time spent rendering minus scaled time spent updating.
	static bool previousUpdateWasRender = false;
	const Rational renderFraction(2, 5);  // Minimum fraction of time spent rendering.
	const Rational updateFraction = Rational(1) - renderFraction;

	countUpdate(false); // kick off with correct counts

	while (true)
	{
		// Receive NET_BLAH messages.
		// Receive GAME_BLAH messages, and if it's time, process exactly as many GAME_BLAH messages as required to be able to tick the gameTime.
		recvMessage();

		// Update gameTime and graphicsTime, and corresponding deltas. Note that gameTime and graphicsTime pause, if we aren't getting our GAME_GAME_TIME messages.
		gameTimeUpdate(renderBudget > 0 || previousUpdateWasRender);

		if (deltaGameTime == 0)
		{
			break;  // Not doing a game state update.
		}

		ASSERT(!paused && !gameUpdatePaused(), "Nonsensical pause values.");

		unsigned before = wzGetTicks();
		syncDebug("Begin game state update, gameTime = %d", gameTime);
		gameStateUpdate();
		syncDebug("End game state update, gameTime = %d", gameTime);
		unsigned after = wzGetTicks();

		renderBudget -= (after - before) * renderFraction.n;
		renderBudget = std::max(renderBudget, (-updateFraction * 500).floor());
		previousUpdateWasRender = false;

		ASSERT(deltaGraphicsTime == 0, "Shouldn't update graphics and game state at once.");
	}

	if (realTime - lastFlushTime >= 400u)
	{
		lastFlushTime = realTime;
		NETflush();  // Make sure that we aren't waiting too long to send data.
	}

	unsigned before = wzGetTicks();
	GAMECODE renderReturn = renderLoop();
	unsigned after = wzGetTicks();

	renderBudget += (after - before) * updateFraction.n;
	renderBudget = std::min(renderBudget, (renderFraction * 500).floor());
	previousUpdateWasRender = true;

	return renderReturn;
}
Beispiel #2
0
/* The main game loop */
GAMECODE gameLoop(void)
{
	static uint32_t lastFlushTime = 0;

	bool didTick = false;
	while (true)
	{
		// Receive NET_BLAH messages.
		// Receive GAME_BLAH messages, and if it's time, process exactly as many GAME_BLAH messages as required to be able to tick the gameTime.
		recvMessage();

		// Update gameTime and graphicsTime, and corresponding deltas. Note that gameTime and graphicsTime pause, if we aren't getting our GAME_GAME_TIME messages.
		gameTimeUpdate();

		if (deltaGameTime == 0)
		{
			break;  // Not doing a game state update.
		}
		didTick = true;

		ASSERT(!paused && !gameUpdatePaused() && !editPaused(), "Nonsensical pause values.");

		syncDebug("Begin game state update, gameTime = %d", gameTime);
		gameStateUpdate();
		syncDebug("End game state update, gameTime = %d", gameTime);

		ASSERT(deltaGraphicsTime == 0, "Shouldn't update graphics and game state at once.");
	}

	if (didTick || realTime - lastFlushTime < 400u)
	{
		lastFlushTime = realTime;
		NETflush();  // Make sure the game time tick message is really sent over the network, and that we aren't waiting too long to send data.
	}

	return renderLoop();
}
Beispiel #3
0
static void gameStateUpdate()
{
	syncDebug("map = \"%s\", pseudorandom 32-bit integer = 0x%08X, allocated = %d %d %d %d %d %d %d %d %d %d, position = %d %d %d %d %d %d %d %d %d %d", game.map, gameRandU32(),
	          NetPlay.players[0].allocated, NetPlay.players[1].allocated, NetPlay.players[2].allocated, NetPlay.players[3].allocated, NetPlay.players[4].allocated, NetPlay.players[5].allocated, NetPlay.players[6].allocated, NetPlay.players[7].allocated, NetPlay.players[8].allocated, NetPlay.players[9].allocated,
	          NetPlay.players[0].position, NetPlay.players[1].position, NetPlay.players[2].position, NetPlay.players[3].position, NetPlay.players[4].position, NetPlay.players[5].position, NetPlay.players[6].position, NetPlay.players[7].position, NetPlay.players[8].position, NetPlay.players[9].position
	         );
	for (unsigned n = 0; n < MAX_PLAYERS; ++n)
	{
		syncDebug("Player %d = \"%s\"", n, NetPlay.players[n].name);
	}

	// Add version string to desynch logs. Different version strings will not trigger a desynch dump per se, due to the syncDebug{Get, Set}Crc guard.
	auto crc = syncDebugGetCrc();
	syncDebug("My client version = %s", version_getVersionString());
	syncDebugSetCrc(crc);

	// Actually send pending droid orders.
	sendQueuedDroidInfo();

	sendPlayerGameTime();
	NETflush();  // Make sure the game time tick message is really sent over the network.

	if (!paused && !scriptPaused())
	{
		/* Update the event system */
		if (!bInTutorial)
		{
			eventProcessTriggers(gameTime / SCR_TICKRATE);
		}
		else
		{
			eventProcessTriggers(realTime / SCR_TICKRATE);
		}
		updateScripts();
	}

	// Update abandoned structures
	handleAbandonedStructures();

	// Update the visibility change stuff
	visUpdateLevel();

	// Put all droids/structures/features into the grid.
	gridReset();

	// Check which objects are visible.
	processVisibility();

	// Update the map.
	mapUpdate();

	//update the findpath system
	fpathUpdate();

	// update the command droids
	cmdDroidUpdate();

	fireWaitingCallbacks(); //Now is the good time to fire waiting callbacks (since interpreter is off now)

	for (unsigned i = 0; i < MAX_PLAYERS; i++)
	{
		//update the current power available for a player
		updatePlayerPower(i);

		DROID *psNext;
		for (DROID *psCurr = apsDroidLists[i]; psCurr != nullptr; psCurr = psNext)
		{
			// Copy the next pointer - not 100% sure if the droid could get destroyed but this covers us anyway
			psNext = psCurr->psNext;
			droidUpdate(psCurr);
		}

		for (DROID *psCurr = mission.apsDroidLists[i]; psCurr != nullptr; psCurr = psNext)
		{
			/* Copy the next pointer - not 100% sure if the droid could
			get destroyed but this covers us anyway */
			psNext = psCurr->psNext;
			missionDroidUpdate(psCurr);
		}

		// FIXME: These for-loops are code duplicationo
		STRUCTURE *psNBuilding;
		for (STRUCTURE *psCBuilding = apsStructLists[i]; psCBuilding != nullptr; psCBuilding = psNBuilding)
		{
			/* Copy the next pointer - not 100% sure if the structure could get destroyed but this covers us anyway */
			psNBuilding = psCBuilding->psNext;
			structureUpdate(psCBuilding, false);
		}
		for (STRUCTURE *psCBuilding = mission.apsStructLists[i]; psCBuilding != nullptr; psCBuilding = psNBuilding)
		{
			/* Copy the next pointer - not 100% sure if the structure could get destroyed but this covers us anyway. It shouldn't do since its not even on the map!*/
			psNBuilding = psCBuilding->psNext;
			structureUpdate(psCBuilding, true); // update for mission
		}
	}

	missionTimerUpdate();

	proj_UpdateAll();

	FEATURE *psNFeat;
	for (FEATURE *psCFeat = apsFeatureLists[0]; psCFeat; psCFeat = psNFeat)
	{
		psNFeat = psCFeat->psNext;
		featureUpdate(psCFeat);
	}

	// Clean up dead droid pointers in UI.
	hciUpdate();

	// Free dead droid memory.
	objmemUpdate();

	// Must end update, since we may or may not have ticked, and some message queue processing code may vary depending on whether it's in an update.
	gameTimeUpdateEnd();

	// Must be at the beginning or end of each tick, since countUpdate is also called randomly (unsynchronised) between ticks.
	countUpdate(true);

	static int i = 0;
	if (i++ % 10 == 0) // trigger every second
	{
		jsDebugUpdate();
	}
}
Beispiel #4
0
// ///////////////// /////////////////////////////////////////////////
// Main Front end game loop.
TITLECODE titleLoop(void)
{
	TITLECODE RetCode = TITLECODE_CONTINUE;

	pie_SetDepthBufferStatus(DEPTH_CMP_ALWAYS_WRT_ON);
	pie_SetFogStatus(false);
	screen_RestartBackDrop();
	wzShowMouse(true);

	// When we first init the game, firstcall is true.
	if (firstcall)
	{
		firstcall = false;
		// First check to see if --host was given as a command line option, if not,
		// then check --join and if neither, run the normal game menu.
		if( hostlaunch )
		{
			ingame.bHostSetup = true;
			bMultiPlayer = true;
			bMultiMessages = true;
			game.type = SKIRMISH;		// needed?
			changeTitleMode(MULTIOPTION);
			hostlaunch = false;			// reset the bool to default state.
		}
		else if(strlen(iptoconnect) )
		{
			joinGame(iptoconnect, 0);
		}
		else
		{
			changeTitleMode(TITLE);			// normal game, run main title screen.
		}
		// Using software cursors (when on) for these menus due to a bug in SDL's SDL_ShowCursor()
		wzSetCursor(CURSOR_DEFAULT);
	}

	if (titleMode != MULTIOPTION && titleMode != MULTILIMIT && titleMode != STARTGAME)
		screen_disableMapPreview();

	switch(titleMode) // run relevant title screen code.
	{
		// MULTIPLAYER screens
		case PROTOCOL:
			runConnectionScreen(); // multiplayer connection screen.
			break;
		case MULTIOPTION:
			runMultiOptions();
			break;
		case GAMEFIND:
			runGameFind();
			break;
		case MULTI:
			runMultiPlayerMenu();
			break;
		case MULTILIMIT:
			runLimitScreen();
			break;
		case KEYMAP:
			runKeyMapEditor();
			break;

		case TITLE:
			runTitleMenu();
			break;

		case SINGLE:
			runSinglePlayerMenu();
			break;

		case TUTORIAL:
			runTutorialMenu();
			break;

//		case GRAPHICS:
//			runGraphicsOptionsMenu();
//			break;

		case CREDITS:
			runCreditsScreen();
			break;

//		case DEMOMODE:
//			runDemoMenu();
//			break;
//	case VIDEO:
//			runVideoOptionsMenu();
//			break;
		case OPTIONS:
			runOptionsMenu();
			break;

		case GAME:
			runGameOptionsMenu();
			break;


		case GRAPHICS_OPTIONS:
			runGraphicsOptionsMenu();
			break;

		case AUDIO_OPTIONS:
			runAudioOptionsMenu();
			break;

		case VIDEO_OPTIONS:
			runVideoOptionsMenu();
			break;

		case MOUSE_OPTIONS:
			runMouseOptionsMenu();
			break;

		case QUIT:
			RetCode = TITLECODE_QUITGAME;
			break;

		case STARTGAME:
		case LOADSAVEGAME:
  			if (titleMode == LOADSAVEGAME)
			{
				RetCode = TITLECODE_SAVEGAMELOAD;
			}
			else
			{
				RetCode = TITLECODE_STARTGAME;
			}
			return RetCode;			// don't flip!

		case SHOWINTRO:
			pie_SetFogStatus(false);
	  		pie_ScreenFlip(CLEAR_BLACK);
			changeTitleMode(TITLE);
			RetCode = TITLECODE_SHOWINTRO;
			break;

		default:
			debug( LOG_FATAL, "unknown title screen mode" );
			abort();
	}
	NETflush();  // Send any pending network data.

	audio_Update();

	pie_SetFogStatus(false);
	pie_ScreenFlip(CLEAR_BLACK);//title loop

	if ((keyDown(KEY_LALT) || keyDown(KEY_RALT))
	    /* Check for toggling display mode */
	    && keyPressed(KEY_RETURN)) {
		wzToggleFullscreen();
	}
	return RetCode;
}