青瓷引擎 - 游戏主循环

来源:互联网 发布:matlab神经网络编程 编辑:程序博客网 时间:2024/04/28 19:46

游戏主循环

参考:游戏主循环,讲得非常清楚。

青瓷引擎调度器

青瓷引擎启动了个循环定时器来跑游戏主循环:

window.requestAnimationFrame(mainLoop);

游戏主循环的逻辑如下图所示:

Main Loop

这里我们需要先解释下两个概念:

场景(Scene)

1个场景就是一个游戏世界,或者说1个场景=1个关卡。一个场景包含了所有的游戏对象,例如角色、武器、例子系统、声音、敌人等等。在引擎编辑器中,所有的实体对象(或者说node节点)都完整的呈现在Hierarchy面板中:

Scene

更新场景

主循环会递归访问场景所有节点,伪代码如下:

foreach (nodes) {    node.update();    foreach (node’s components) {        component.update();    }}

preUpdatepostUpdate的调度,与update类似。下面举个实际例子来加深下理解。

调度例子

  • 创建一个空的工程,名称为:MainLoop;
  • 创建一个JavaScript脚本文件:Test.js,代码如下:
var Test = qc.defineBehaviour('qc.demo.Test', qc.Behaviour, function() {    console.log('Init');}, {});Test.prototype.preUpdate = function() {    console.log(this.gameObject.name, 'call preUpdate');};Test.prototype.update = function() {    console.log(this.gameObject.name, 'call update');};Test.prototype.postUpdate = function() {    console.log(this.gameObject.name, 'call postUpdate');};
  • 创建两个空的node节点,重命名为:node1和node2;
  • 将脚本Test.js挂载到node1和node2节点;
  • 运行工程,在浏览器的开发控制台查看输出:
    Call

在场景中有2个节点:node1和node2。游戏主循环将调度这两个节点及其挂载的所有组件:

Call

首先,游戏主循环调度所有nodes的preUpdate函数,然后是update,最后是postUpdate。大部分情况下,我们将游戏逻辑代码置于update中。当用户输入时,onDownonClickonUp等函数将会被主循环调用(后续再详细解释)。

附:Game Main Loop

Video games are simply ordinary software - there’s nothing intrinsically special about them. However, they SEEM to behave in a very different way from your ordinary everyday applications - so much that many experienced programmers are at a complete loss when faced with the task of developing a game from scratch. This difference is mostly caused by game’s close ties to their main loop. In this chapter, we’ll examine what is the main loop, and how it works in QICI.

A simple model

How simply could we model a computer game? Let’s start by separating the game in two parts: the data inside the computer, and everything outside the computer. This might seem like a strange thing to say, but remember that games are, first and foremost, interactive software. So, outside the computer, we have (at the very least) the player. Inside the computer we have all sorts of data, but the most important is what we call the game state: it contains all the dynamic information of the game: the position of the player, monsters; the current time; the score - in essence, everything that changes with time.

A computer game can then be understood as a system in which those two entities - player and game state - interact with each other according to a specific pattern of rules. The player inputs data into the system, and the system users the game state to generate output to display to the player. This is not very different from ordinary applications, in which e.g. a click (input) might cause a dialog to show up (output). The difference is how that behaves in respect with time.

The Game Loop

Most applications are developed in a reactive way - your program just sits around waiting for the user to click something, and then it does something in response. There is a main loop behind your application as well, but it’s not important - it’s abstracted away. With games, your code is constantly being invoked, even in the absence of user input.

The pseudo-code for a video game will often look like this:

function main() {    init();    runMainLoop();    deInit();}

The main loop looks something like this:

while (running) {    processInput();    updateGameState();    drawScreen();    waitUntilItsTime();}

First, it reads input from the user and stores it somewhere. Here, it will check the keyboard, gamepad, plastic guitar - basically, it will collect all information from the outside world.

After that, it will use that information to update the game state - depending on what conditions we have, they will have different results. For example, on the menu screen, detecting that the “down” arrow got pressed might increment the “currently selected menu item” variable, but the same input while on the game might instead trigger the “set player as moving down” flag. Note that the world update is invoked even if the user didn’t perform any input. This is a very important property of most video games.

Lastly, it will collect the current game state data to generate the output - it will figure out where the player and everything else are, and generate an image to display on the screen. A more complicated game will also have to deal with other forms of output - audio and network, for example.

QICI Game Loop

QICI start a loop timer to run game loop:

window.requestAnimationFrame(mainLoop);

The main loop is shown as the following diagram:

Main Loop

There are two concepts must be explained in detail first.

What is a Scene?

A scene is a game world, or 1 scene=1 level. The scene contains all gameObjects, for example, characters, weapons, particle systems, sounds, enemies. In QICI Editor, all entities (or gameObjects, or nodes) in the scene are listed in the Hierarchy views:

Scene

How to Update a Scene?

QICI calls scene’s nodes recursively. The pseudo-code looks like this:

foreach (nodes) {    node.update();    foreach (node’s components) {        component.update();    }}

Preupdate and Postupdate is the same to Update a scene. Let’s get to an example to understand it.

Example

  • Create a empty project ‘MainLoop’ first.
  • New a javascript file ‘Test.js’ and type codes:
var Test = qc.defineBehaviour('qc.demo.Test', qc.Behaviour, function() {    console.log('Init');}, {});Test.prototype.preUpdate = function() {    console.log(this.gameObject.name, 'call preUpdate');};Test.prototype.update = function() {    console.log(this.gameObject.name, 'call update');};Test.prototype.postUpdate = function() {    console.log(this.gameObject.name, 'call postUpdate');};
  • Create two empty nodes in the scene, and rename them to ‘node1’ and ‘node2’.
  • Link ‘Test.js’ to node1 and node2.
  • Run the project, and see output in the console view:
    Call

What happened inside the engine?

There are 2 nodes in the scenes: node1 and node2. The main loop visits them and calls their components’ function.

Call

The main loop calls all nodes’ preUpdate function first, then update function, and postUpdate function last. Most of the time, we will put our codes in the update function. When the mouse is clicked (or touch), these function will be called by main loop just like update function: onDown, onClick and onUp (Explain later chapter).

0 0
原创粉丝点击