加载屏幕只能使用一个线程来实现吗? 如果是这样,怎么样?

我已经看到如何使用多个线程实现加载屏幕的指南。 但是确定一个线程就可以这样做,因为在单线程机器上运行的较旧的(甚至2D)游戏也具有加载屏幕。

你是怎么做到的?

你基本上必须把加载的数据分解成更小的块,并且在这些处理之间散布UI更新。 您同步加载/处理的数据块的粒度越精细,UI越可以更新。 本质上,穷人的multithreading。 (这是在多核机器出现之前完成的。)

除非你做了以下一项或多项工作,否则分解成更小的块可能是不可能的:

  • 给任何系统库加载并replace你自己的逻辑
  • 重组你的数据(可能是一个重大的改变)。

所以你会这样做:

while (chunksRemaining > 0) { LoadNextChunk(); UpdateUI(); } 

请注意, LoadNextChunk()调用可能需要几十秒或整秒,但是阻止我们继续执行UpdateUI()直到完成Chunk的处理。 所以确保LoadNextChunk()运行速度快!

用非常非常通用的术语来写这样的东西(伪代码):

 while (!isNewLevelLoaded) { UpdateAndRenderLoadingScreen(percentageOfNewLevelLoaded); LoadNewLevelBytes(numberOfBytesTOLoad); } LoadNewLevelBytes (int bytes) { for (int i = 0; i < bytes; i++) { LoadByte(); } if (endOfFileReached) isNewLevelLoaded = true; } 

我不确定你想要什么样的“单线程机器”,但是你也可以在一个支持asynchronousI / O的系统上运行一个单线程程序。 在这种情况下,正在执行的代码并行发生,但是由操作系统来处理。

所以在伪代码中,你的程序可能是这样的:

 for (fileToLoad) { asyncRead(fileToLoad); } while(numberOfFilesLoaded != numberOfFilesToLoad) { updateLoadingScreen(); } // all files loaded here 

有些语言提供的coroutines类似于线程,它们允许一定程度的多任务,但实际上可以存在于一个线程中。

一个couroutine本质上是一个代码块,在某个时候决定退回给它的调用者,所以你得到这样的代码:

(假设的Lua代码)

 function loadFile(path) --code end function loadFiles(paths) for i, file in ipairs(fileList) do local result = loadFile(file) coroutine.yield(result) end end function updateLoadingScreen() --code end function drawLoadingScreen() --code end function loadingScreen(files) updateLoadingScreen() drawLoadingScreen() local loadFilesCo = coroutine.create(loadFiles) local results = {} while coroutine.status(loadFileCo) ~= "dead" do local success, result = coroutine.resume(loadFilesCo, files) if ~success then error(result) end table.insert(results, result) updateLoadingScreen() drawLoadingScreen() end return results end