Outputting to Editor's console with AngelScript 2.28.1

Started by
7 comments, last by Paul C Skertich 9 years, 8 months ago

I began testing scripting functions inside my game engine. I would like to be able to detect if the player enter a key say mouse left click or space bar - then output to the Level Editor's console. I have to currently outputting in a message box.

So during rendering time - i have the angelscript rebuild modules and executing the functions needed. What I've noticed is the output text is constantly being written multiple times over and over again not only when I hit a space bar or whatever. If I press the space bar I want the output to write to a rich text box only once when the a key is pressed - not multiple times.

Would I have to set up a delegate and a event handler to handle new incoming messages behind handled by the script?

In pseudo-code

-If KeyPressed Is True

-Output To Editor's Console

-If KeyPressed is False

- Do Nothing.

Game Engine's WIP Videos - http://www.youtube.com/sicgames88
SIC Games @ GitHub - https://github.com/SICGames?tab=repositories
Simple D2D1 Font Wrapper for D3D11 - https://github.com/SICGames/D2DFontX
Advertisement

Pretty vague question, it could be because it's in a loop so when you press it, the output will be printed multiple times e.g fffffffffff, or it could be because you aren't acting upon the key being released so it's constantly being written to the file?

Pretty vague question, it could be because it's in a loop so when you press it, the output will be printed multiple times e.g fffffffffff, or it could be because you aren't acting upon the key being released so it's constantly being written to the file?

That's interesting but I think it's because it's inside the rendering loop. How are things made like in Unity when the user debugs his script and it outputs in the console?

There has to be some type of listener that reads a file perhaps then deletes the file upon application closes.I'm thinking that's the only logical way to actually go. I think I know what to do - it may not be perfect but it's something. I think it's more likely either a temporary file or a string collection that gets updated.


void onInput() {
          DebugPrint("You hit me congraduations!");
}

that would be a example of the script code. The DebugPrint function in C++ would have to write to a collection of string either vector or file. Instead of wasting hard drive write and read time - I can just put them in a string collection and have them interpoled in C# using foreach loop.

It'll hit me in a couple hours what I must do.

Game Engine's WIP Videos - http://www.youtube.com/sicgames88
SIC Games @ GitHub - https://github.com/SICGames?tab=repositories
Simple D2D1 Font Wrapper for D3D11 - https://github.com/SICGames/D2DFontX

I think a beter question is not how but whether or not am I suppose to constantly rebuild and execute the angel script files inside the rendering loop? I looked at the sample of Game that's comes with the ANgel Script library. I see they store the method onThink() inside a user cache for later referencing. I was wondering if there was anyone that used AngelScript would know how this typical use would be done.

Game Engine's WIP Videos - http://www.youtube.com/sicgames88
SIC Games @ GitHub - https://github.com/SICGames?tab=repositories
Simple D2D1 Font Wrapper for D3D11 - https://github.com/SICGames/D2DFontX

AngelScript (or any embedded scripting solution) is often used as event handlers.

You would compile the scripts once, e.g. when loading the level data, and then the compiled script functions are called as the game engine detects that a specific event occurred (e.g. the user pressed a button). This way you allow script writer to decide what should happen when the button is pressed, for example, write a message to the console, or fire the player's gun, etc.

You do not want to recompile the script every time you need to call a script. If you're planning on allowing the user to change the script dynamically during the game's execution, then recompile only when the script has actually changed.

AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - Tower - free puzzle game

I'm starting to understand a lot more now! Following steps should be:

- Prepare script functions and compile when level is loading (initializing).

-Execute functions whenever a key is pressed or etc...

here's my test script:


void main()
{
bool result = KeyPressed("FireButton");

if(result == true) {
  DebugPrint("You hit me!!");
 } 

}

in C++ upon initialization I have the script engine initialized. I have the function declarations initialized and compiled or built. For executing the script commands I have it ExecuteCall() function.

I'm just working on one function declaration for now until I fully understand how this beautiful scripting works. I did noticed when I recompile the script and execute calls it would hurt performance and cause fps drop from 60 - 31.


bool ScriptManager::compileScript(const char* file, asIScriptEngine *eng, asIScriptContext *context) {

	CScriptBuilder builder;
	int r = builder.StartNewModule(eng, file);
	if (r < 0) {
		MessageBoxA(0, "Unable to recover from error. Memory is possible full!", "Script Builder Failed.", 0);
		return false;
	}
	r = builder.AddSectionFromFile(file);

	if (r < 0) {
		MessageBoxA(0, "Unable to load script file. Be sure the script file is in the proper location.", "Script Builder Failed!", 0);
		return false;
	}

	r = builder.BuildModule();
	if (r < 0) {
		MessageBoxA(0, "Unable to build script module.", "Script Builder Failed.", 0);
		return false;
	}

	scriptModule = file;
	module = eng->GetModule(scriptModule);
	function = module->GetFunctionByDecl("void main()");

	if (function == 0) {
		return false;
	}

	context = eng->CreateContext();
	context->Prepare(function);

	return true;
}


int ScriptManager::ExecuteCall(asIScriptContext *context) {
		int r = context->Execute(); 
		if (r != asEXECUTION_FINISHED)
		{
			if (r == asEXECUTION_EXCEPTION)
			{

				const char * exceptionString = asCtx->GetExceptionString();
				const char * exceptionFunction = asCtx->GetExceptionFunction()->GetDeclaration();
				int  exceptionLineNumber = asCtx->GetExceptionLineNumber();

				wchar_t msg[1024] = {};
				swprintf_s(msg, L"Exception: %s, Function: %s, Line: %d", exceptionString, exceptionFunction, exceptionLineNumber);
				MessageBox(0, msg, L"Script Exception!", 0);
				// It is possible to print more information about the location of the 
				// exception, for example the call stack, values of variables, etc if 
				// that is of interest.
			}
		}
		return r;
}

So, perhaps the execution isn't the best call during the rendering loop because if there's any mistakes inside the script I'll get infinity message box popping up. Event Handlers......, In C++ whenever there's a key pressed would I execute the functionDelcaration("void main()"); ??

Game Engine's WIP Videos - http://www.youtube.com/sicgames88
SIC Games @ GitHub - https://github.com/SICGames?tab=repositories
Simple D2D1 Font Wrapper for D3D11 - https://github.com/SICGames/D2DFontX

wouldn't the prepare(asIScriptFunction); get rid of the context after it's done being executed or would it be the unprepare function? Is that why in the Game sample inside the AngelScript library keep a vector of script context - upon the prepareContextPool it finds to see if there's a module that already exist if not then it creates a new context. It then prepares the function within that context after words.

In the callOnThink() inside the scriptmanager.h what I see - is that it checks to see if there's any modules containing Player or Enemy - prepares the function. Executes that function then unprepares it by popping back from the vector list and unpreparing the function from context. Alternatively switching from player to enemy like a chess game, am I right Andreas?

Game Engine's WIP Videos - http://www.youtube.com/sicgames88
SIC Games @ GitHub - https://github.com/SICGames?tab=repositories
Simple D2D1 Font Wrapper for D3D11 - https://github.com/SICGames/D2DFontX

Now I believe i understand what is going on. Okay, I re-read the XACT3 article with Angelscript by example that douglas wrote. On initial load of the level - compile scripts necessary. In my case it would be main(). Stores the functions neccary like DebugPrint and KeyPressed into array or vector. on updateInput() C++ function for instance: prepare the functions that were gathered and execute them as needed NOT recompile the modules.

If I would to have the following:


void onInputUpdate() {
      DebugPrint("Yes, you hit me again! You're very abusive!");
}

Inside the angelcode for instance - it's already compiled upon initialization. The onInputUpdate() is already stored as a asIScriptFunction. So, in C++ when I'm checking to see if there was any input pressed or what not. I would prepare the DebugPrint function that is stored and execute the function. Just like in the sample inside the AngelScript library called Console.

Game Engine's WIP Videos - http://www.youtube.com/sicgames88
SIC Games @ GitHub - https://github.com/SICGames?tab=repositories
Simple D2D1 Font Wrapper for D3D11 - https://github.com/SICGames/D2DFontX

Well I solved it thanks to the article written by Douglas and for clarification from Andreas. I implemented a ContextData struct that holds the asIScriptContext and asIScriptFunctions[] array inside the script manager. Upon initialization of the script manager - I intiialized the angelscript engine; loaded the global functions I needed such as DebugPrint and KeyPressed. After loading the script - I built it using the asIScriptContext inside the ContextData structure. I also assigned the function declaration of "void main()" to the asIScriptFunction[] array.

When I'm updating I prepare the script context with the function that has "void main()" then I execute the script. Inside the level editor - a timer is checking every 100th millisecond intervals to prepare and execute the "void main()" inside the script. The DebugPrint function in C++ writes the output to text file. C# inside timer - loads the file if it exists and displays the output to a richtextboxcontrol.

Now I can focus on expanding the scripting manager and how everything interacts with the scripting side.

I was really confused on how everything fit in. Now it's time to get creative and have fun!

Game Engine's WIP Videos - http://www.youtube.com/sicgames88
SIC Games @ GitHub - https://github.com/SICGames?tab=repositories
Simple D2D1 Font Wrapper for D3D11 - https://github.com/SICGames/D2DFontX

This topic is closed to new replies.

Advertisement