Jump to content

Where to put game logic?


amorgan
 Share

Recommended Posts

So, where is it intended for the logic to be? I currently put my logic in the renderLoop, but there is also the registerBeforeRender function. As a project gets bigger, it seems like I don't want to be performing all of the logic checks inside the renderLoop. Right now the way I'm getting around it is using the modulus of a loopCounter to acheive a different logic rate, but this also has problems.

 

With that, where would Babylon JS like the logic to be? I kind of asked this before, but felt like it should be a separate question.

 

Thanks

Link to comment
Share on other sites

Good question :)

 

All these functions exist for users that want to perform specific actions at specific moments.

To separate your code into different files and classes, you should create one that will manage collections of specific actions.

 

Like:

function Manager() {    this.beforeRenderFunctions = new Array();}Manager.prototype.runBeforeRenderFunctions = function() {    for (var i=0; i < this.beforeRenderFunctions.length; i++)        this.beforeRenderFunctions[i].execute();    // So, each function in this.beforeRenderFunctions must implement the "execute()" function}// And then somewhere in your codemyScene.registerBeforeRender(myManager.runBeforeRenderFunctions);[...]// You can use the same method for runRenderLoop by adding custom renderLoopFunctions in your// manager and then call myEngine.runRenderLoop(myManager.runRenderLoopFunctions);// Etc.

It is a potential solution, I think we can find better :)

Link to comment
Share on other sites

Yea and that's what I'm trying to understand, is if there was a place in Babylon that was intended for taking care of "game" logic. I understand the Babylone JS framework is really meant to be a 3D framework and not specifically a 3D Game framework, but that is definitely a hot topic of usage. In the end I was debating on whether or not I needed to create my own manager, as you suggested, or if Babylon has provisions for it already, that is scalable.

 

My guess would be that it doesn't and I should create my own.

Link to comment
Share on other sites

So I've been thinking this through. I'm trying to understand where things should exist. I think I need to definitely create my own "game" logic paradigm, which I am going to try to acheive with event driven logic. Therefore, thinking through what actually should go into the renderLoop, besides scene.render(), would be functions like moveWithCollisions. But I don't know if that should live in the renderLoop function or the registerBeforeRender function. Is there a performance difference between the two? This main issue I could see is scalability.

 

For example, if I have 100 "enemies" (meshes) that all need to be moveWithCollisions, how can I loop through all of them withouth hindering the FPS? I have a current solution, though I don't like it. I am creating a loopCounter, that increments by 1 on each pass of the renderLoop function and then I excute things on (loopCounter % x),  x being the interval at which I want the condition to execute. Though, with moveWithCollisions, this has to be processed on each pass through the renderLoop, otherwise it is choppy.

 

Here is a snippet of my code for what I am working, this is inside the renderLoop function:

switch (Game.engine.loopCounter) {   	case 1000:		Game.engine.loopCounter=0;		break;	default:		Game.engine.loopCounter++;		break;}if (Game.engine.loopCounter % 5 == 0) {	$('#fps').text('FPS: ' + Game.engine.getFps().toFixed());	//check what room the player is in	this.checkActiveRoom();}else if (Game.engine.loopCounter % (21 + this.enemyCounter) == 0) {	if (this.enemyCounter >= this.activeRoom.enemy.length) { 		this.enemyCounter = 0;		//open doors if all enemies are dead		if (this.activeRoom.enemiesDead) {			for (var doorLoop=0; doorLoop < this.activeRoom.doors.length; doorLoop++) {				if (this.activeRoom.doors[doorLoop].isOpen == false) {					this.activeRoom.doors[doorLoop].mesh.checkCollisions = false;					this.activeRoom.doors[doorLoop].mesh.isVisible = false;					this.activeRoom.doors[doorLoop].isOpen = true;					//apply to matching door					this.activeRoom.doors[doorLoop].pairedDoor.mesh.checkCollisions = false;					this.activeRoom.doors[doorLoop].pairedDoor.mesh.isVisible = false;					this.activeRoom.doors[doorLoop].pairedDoor.isOpen = true;				}			}		}	}	else {		if (this.enemyCounter == 0 ) {			this.activeRoom.enemiesDead = this.activeRoom.enemy[this.enemyCounter].isDead;		}		else {			this.activeRoom.enemiesDead = (this.activeRoom.enemiesDead && this.activeRoom.enemy[this.enemyCounter].isDead);		}		this.activeRoom.enemy[this.enemyCounter].velocity = GetPathVector(this.activeRoom.enemy[this.enemyCounter].mesh.position,this.player.mesh.position,{speed: this.activeRoom.enemy[this.enemyCounter].speed, tolerance: 12});		this.activeRoom.enemy[this.enemyCounter].mesh.rotation.y = -this.activeRoom.enemy[this.enemyCounter].velocity.angle;		if (this.activeRoom.enemy[this.enemyCounter].velocity.direction.x == 0 && this.activeRoom.enemy[this.enemyCounter].mesh.enemyAnimations.animatable) {			this.activeRoom.enemy[this.enemyCounter].mesh.enemyAnimations.animatable.stop();			this.activeRoom.enemy[this.enemyCounter].mesh.enemyAnimations.animating=0;		}		else {			this.activeRoom.enemy[this.enemyCounter].mesh.enemyAnimations.move(this,this.activeRoom.enemy[this.enemyCounter]);		}		this.enemyCounter++;	}}processInput(this.player.mesh, this.player.speed);//Need to update this every loop, I guessfor (i=0; i < this.activeRoom.enemy.length;i++) {	this.activeRoom.enemy[i].mesh.moveWithCollisions(this.activeRoom.enemy[i].velocity.direction);}//Render scene and any changesthis.render();

I'm sure some things seems messy, but definitely a work in progress.

Link to comment
Share on other sites

 

 

But I don't know if that should live in the renderLoop function or the registerBeforeRender function. Is there a performance difference between the two? This main issue I could see is scalability.

 

It should be in registerBeforeRender. This function is here for that ! The render loop should be here only to render your scene, and that's it. Every other actions that should be executed all frames should be in registerBeforeRender.

 

Actually, there is no difference between those two. registerBeforeRender is called in scene.render().

But you can call registerBeforeRender every time you need it. The function that you gives in parameter is stored : 

registerBeforeRender(func) {   // very simplified   actions.push(func);}

and then, when you render your scene : 

render() {   // very simplified again    actions.forEach(function(f) {     f();   }}
Link to comment
Share on other sites

This is very good to know! Does this method scale well? I don't know enough about how the render() function and registerBeforeRender() function works, I should probably dive into the code to understand it better. But it seems like it will perform all of the actions in registerBeforeRender before actually updating the screen?

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...