Home » Community » Forums » » Creating a Scripting System in C++ Part I: An Introduction
  Intel sponsors gamedev.net search:   
[Control Panel] [Register] [Bookmarks] [Who's Online] [Active Topics] [Stats] [FAQ] [Search]

Add Forum to Favorites |  Send Topic To a Friend | View Forum FAQ | Track this topic

Page:   1 2 3 »»

 Last Thread Next Thread 
 Creating a Scripting System in C++ Part I: An Introduction
Post Reply 
Well written. I'm looking forward to see the next part.

 User Rating: 1015   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

Hey, nice article.

But im just wondering (im opening this for discussion) what is the use of scripting.
I want to include it in my 3d engine, but isnt it more efficient to just use the engine as a library and and control it with your gaming code?



 User Rating: 1015   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

Very nice article. I am looking forward to see more.
As far as why you want scripting I can see many merits. Some points are already discussed in the article but just for argument sakes.

You don't need to change our program, this helps against introducing bugs. You can use it to create map data. You can save map data outside your code. This way your game is easily extendible. You can add AI or you can add triggers or whatever else you want. Depending on the complexity of your script. You can add triggers for text, context of objects, music etc
It allows people other than the programmer to extend his program, artists, level creators etc. Depending on your target user it can be simple allowing non-programmers a chance to develop...

am I babbling???


 User Rating: 1015   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

Allright, good


I hate mornings

Anyways, im working on a open source 3d engine and the script should provide for actions and AI.
I think im just going to support both (it shouldnt be too difficult)
Thanks for the idea anyways

 User Rating: 1015   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

Good article so far.

But I would like to see how a scripting engine is integrated into the game engine.

e.g.

How the VM sends "Messages" or commands to the Engine:
1. Something similar to PostMessage - The Advantage here is that then the VM would be a very thin layer - and the Networking Code or "Other" modules could use the same messages/opcodes.

2. Calling functions directly to the engine. - Perhaps slightly easier.

Should the VM be in it's own thread?
How do events in the game call scripted actions?

etc.

Finnally what is the point of using languages like Java or Perl etc as your scripting language. Surely using something which is "Specific" to your engine is better.


 User Rating: 1015   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

The point of using java-script for example (not Java!), is that there are already good open source implementations...

 User Rating: 1015   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

That would make sense as a guide however the VM is going to be specific to your engine so ALOT of work would be needed, but your point is valid.

However, I've heard of Java being used - Maybe not all The libraries etc. But the actual language.

 User Rating: 1015   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

Im thinking of creating a simple C like scripting language, but with OO ofcourse
Though not as bulky as C++
It can include internal functions (actualy most of the functions you can call are direct calls to engine functions)
And it can include other scripts

Any nice ideas to add?

 User Rating: 1015   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

I'm writing realtime renderer as my graduate project an i have another aproach to scripting.
I include no scripting at all, but each object could register its thread, that will do its code, response messages and more. Because objects are DLL's they are not hardcoded into engine and easily replacable (via version depended loading of DLL's). This aproach has two big pluses - native code means bigger speed and
if somebody want's to add some scripting, he can create a DLL for that object (or a group of objects) that will parse and execute that scripts.
What do you mean?

emulating emulated emulates emulation...

 User Rating: 1015   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

Well done on your article, it's good to see somebody doing proper C++ for once (e.g. const correctness, STL).

I don't mean to nit-pick but there's one issue with your code I think you should change. You shouldn't start variable names with an underscore character because these names are reserved by the compiler. It may not seem like a big deal but it makes your code more compliant and you won't get a nose turned up when a C++ veteren reads it. Actually, I think the exact rule is don't start variables with an underscore followed by a capital letter but it is considered bad practice anyway.

Good article all the same though.

 User Rating: 1015    Report this Post to a Moderator | Link

d9930380: Integrating the scripting system into a game engine is what I was referring to when I mentioned "embedding" in the series outline. So yes, I will get to all of these points.

As for using a language like Java or Perl, it would most likely be the same point as using any other reputable 3rd party scripting. It's already developed, saving you time, and it is a tested system. There is less, "oh crap, this isn't going to work, is it" risk involved.

IIRC, you can embed Java in your application using JNI. I have not personally done this, so this is really all I can say about it.

Golthar: Sounds like a pretty good place to start.

emulator: Yes, using DLL modules is an alternative to a custom scripting language. I believe Quake uses this approach.

AP: Thanks for pointing this out. I'd rather you say something like this than keep it to yourself. I've always been under the impression though, that, like you said in the end, only names of the form _X are reserved, and not _x. If you can point me to information that states _x is a reserved identifier as well, please do so. I have seen other programmers using the same style for naming member variables as I do, so I am not yet convinced that this is really non-compliant.

Thanks for the praise too.

-If I've missed answering anybody so far (don't think I have) please smack me and tell me so. Thanks for the feedback thus far.

"Don't be afraid to dream, for out of such fragile things come miracles."

 User Rating: 1079   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

The underscore _variables is some c++ coding practice to indicate private members. Some other people start names with m.
The fear of name clashes with names somewhere else in the code is c++ less than in c because of the name space.

About the article: I like the article and look forward to the next part, it's an intersting topic. I do have some problems with the code which still smells too much like c. He uses the
containers only as a size independent mallocs and also the classes seem more like structs with function members.

Take for instance the VirtualMachine, there he uses _scriptCount
which is redundant because is already included in the vector and can be obtained by doing _scriptList.size(). This seems more readable to me. Also if he makes _instr a std::vector.iter then he can change the while in Execute to:
for (_scriptList[_scriptId]._instrList.begin();
_scriptList[_scriptId]._instrList.end(); ++_instr)

In this way you don't need the op_end instruction because it will always end at the last instruction of the vector (which i think is more error proof than placing a 0 in the while).


 User Rating: 1015    Report this Post to a Moderator | Link

I can understand why you might think it smells like C. Like I stated, I am not taking an Object Oriented approach in the series, but rather an Object Based one. As far as I know, C++ doesn't demand that you program according to a specific methodology, such as OOP, but rather allows the option to. As an added attraction, the simply Object Based approach makes the example code much more accessible to those who would rather work with straight C, because they really are simply structs with member functions. I'd rather not get into a C vs. C++ debate, however.

---
At the moment, yes, the containers are really only functioning as size independent arrays. Don't you think it's rather convenient? It makes it very easy to provide example code that isn't obfuscated with off-topic details such as creating a more specialized dynamic array for this purpose. I never said my code was intended to be an end-all library to be inserted in other people's work, verbatim. In fact, I stated that people should be using my examples only for the purpose of learning. In the end, a person really should be writing their own.

---
Yes, you certainly can make better use of the vector class as you describe, using the provided iterator class, and using the for-loop method. In fact, this is what my original version used... that is, until I wanted to be able to easily jump from one point to another, via an index.

In an article I read regarding the STL, I believe I heard that one of the improvements to be made with iterators is to allow this kind of jumping without making a hack to do it, but this is currently not available as far as I know. So I use a pointer, which is a legitimate form of iterator. On top of that, it's a pointer that only allows reading of the data it points to.

---
Yes, you can certainly make good use of the vector's end to determine when to stop, but this assumes that the ending point of a script is always at the end of the vector. This does not always have to be the case, as will be shown when I get into flow-control instructions.

---
Finally, the size() of the vector can be used to obtain the correct offset when loading a script. The count doesn't have to be independently tracked.

My original intention was related to the SelectScript() utility. Originally, I intended to perform a run-time evaluation to determine whether a script id was valid, rather than the assert I now have in place.

Storing the actual value of the size would have made this evaluation somewhat faster, as the size() of the vector wouldn't actually have to be computed, which would have made a bit of difference when the selection function was called many times in a short time span. This would be the case with many short scripts being executed within a tight loop.

Since this evaluation now only takes place during debugging, I suppose it is no longer necessary to store the size separately. So thank you for making me re-evaluate the purpose of this. It is always good to reduce the memory footprint of your VM if you can without sacrificing its execution speed.

I think that covers it all so far.

"Don't be afraid to dream, for out of such fragile things come miracles."

 User Rating: 1079   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

I would like to congratulate the author for the choice of topic. As many others, I am looking forward for the continuation. By the way, is there any way I can be notified when it comes out?
Regards,

Ney André de Mello Zunino.

"Take of the fruit,
But guard the seed..."


 User Rating: 1015   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

Great! I was just thinking about implementing a scripting engine when I saw the article. I am also looking forward to see the second part!

 User Rating: 1015   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

Within these articles, you might want to add a little whitespace to your code, as well as a some syntax highlighting. I'm just imagining someone completely unfamiliar with scripting trying to pull all the information out of your class design. You've got all the room you need, no need to cram functions onto as few lines as possible.

 User Rating: 1015   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

I don't have control of highlighting, but I'll keep the spacing in mind for the next article.

"Don't be afraid to dream, for out of such fragile things come miracles."

 User Rating: 1079   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

hi redleaf,
Thanks for the lenghty reply. I hope i didn't offend anyone with the smell of c, but when i see "in c++" in the title i expect it to be somehow written with oo concepts in mind. I was expecting something allong the line of building some kind of stack, like using the pushback and popback of a vector to store operations and variables (don't know if this is the smart way of doing it, but that was the mental picture that popped in my mind after reading the title.).
Anyway, after reading your article i had the impressing that i fully understood it, but when i looked at your code i didn't see why you would make certain things more complicated then they should (like using pointer to read from container). Most of your above mentioned design choices are clear now, they are partly optimization and partly functionality the vm will get. Right?


 User Rating: 1015    Report this Post to a Moderator | Link

That's exactly right.

As to further use of the vector as a virtual stack, I actually intend to do just that in a future article. Most likely, #3. Stay tuned.


 User Rating: 1079   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

From Stroustrup's "The C++ Programming Language" Section 4.9.3:

"Names starting with an underscore are reserved for special facilites in the implementation and the run-time enviroment, so such names should not be used in application programs."

If you bring this topic up in a C++ newsgroup you will basically start a flamewar over wether you should start variables with an underscore. It's non-complient to use the underscore in this way and experienced C++ users will frown at you. I'd recommend the "m_" prefix if you need to use one and just avoid these issues all together.

There really is no real advantage over using the "_" prefix over "m_". Ok, it's shorter but the risk of being considered a bad coder is the deciding factor why you shouldn't use it in my opion.

Good coding on the whole though.

 User Rating: 1015    Report this Post to a Moderator | Link

Alright, thanks for the heads up. Although I'd have to disagree a bit about this indicating that one may be a bad coder. There is quite a bit more to coding, and to be labelled in such a way simply because of this is a bit shallow in my opinion.

"Don't be afraid to dream, for out of such fragile things come miracles."

 User Rating: 1079   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

Out of curiosity, why not just append the underscore to the private variable name:

So, instead of _myvariable, just change it to myvariable_. This is used quite a bit throughout discussions of design patterns. Personally I like it and use it in my own code.

The m_ prefix is also another good choice but it is more a matter of style.



Dire Wolf
www.digitalfiends.com

 User Rating: 1015   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

Well, I'll explain what I found attractive about the "leading underscore on data member" style.

-First, with tab, all the underscores would line up, and make the data section very distinguishable, and much easier to read... at least to me.
-Second, it was simply an additional character added onto the variable name, and so wasn't too awkward to type.

Certainly the trailing underscore satisfies the second benefit, but doesn't easily fit the first, while the "m_" leading style satisfies the first, but not the second.

Now of course, if the leading underscore style really is a no-no, as I'm being told, then it really shouldn't be used. But it seems to be a shame.

"Don't be afraid to dream, for out of such fragile things come miracles."

Edited by - Redleaf on January 17, 2002 6:26:44 PM

 User Rating: 1079   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

I didn't mean to imply Redleaf was a bad coder (I already said his C++ code was refreshingly good), I just meant that you run the risk of being labelled as that when some people skim your code.

For example, I wouldn't recommend presenting code like this in a job interview because it shows you aren't familiar with C++ compliant code and hints there may be other flaws in your coding.

You should try to making your coding style as readable and consistant as possible, but most of all it should be compliant. The leading underscore is not and you just shouldn't use it.

It's vaguely similar to the using "goto" statements debate in that it is disapproved of. The only difference is you *really* aren't meant to use leading underscores. Doing so just shows you are not respecting standards.

 User Rating: 1015    Report this Post to a Moderator | Link
Page:   1 2 3 »»
All times are ET (US)

Post Reply
 Last Thread Next Thread 
Forum Rules:
You may not post new threads
You may post replies
You may not edit your posts
You may not use HTML in your posts
Jump To:
Administrative Options: