Temple of The Roguelike Forums
Development => Programming => Topic started by: TSMI on January 08, 2013, 12:16:18 AM
-
I'm in the early stages of a roguelike on the jvm, and progress has stalled a bit. At first I was writing a little "engine" in java, then calling it from jruby, but a number of issues cropped up (weirdly bad performance that I couldn't really profile from jruby).
so am now doing a re-write of the jruby stuff in java - I just added a "gamespecific" package to my engine and off I went. Stuff like colors, tile definitions, hardcoded overworld, items etc are already in data files. I feel like I might embed a scripting language at some stage - it's trivial to do in java - but I don't know what stage.
Anyway, people love bullet points, and I'd really appreciate if you could tell me, for each item, what should be scripted, what should be in java, and what should be in data files?
- menus (start, inventory, etc)?
- procedural level generators?
- quests?
- npc dialogue?
- AI?
-
The usual answer is "it depends", more elaborated one is "it depends on what you want to do" :)
I would (more or less arbitrarly) use scripting for level generators, quests and AI. Menus would go into java side and npc dialogue into data files. But it really depends on how much of things you want to be able to change without compiling the java side and how flexible you want those things to be.
-
Use scripts for:
- GUI
- quests
- NPC dialogs
As of GUI, it's pretty obvious I guess. There's nothing more annoying than having to recompile the project every time you want to move a button 1 pixel to the right.
It's good to use scripts for quests as it's always easier to write in a scripting language than in the language you use for the rest of the stuff. Making it easier to write quests, you end up having more quests in the game. However, you can also end up having too many simple and schematic quests, as this is what scripting languages typically encourage. Perhaps the optimal solution is to hardcode a few very sophisticated quests and put the rest in the scripts. It's up to you to decide.
If you use scripts for quests, you probably want to have NPC dialogs in the scripts as well. They are very closely related to quests, so why to store them separately? This is how it's done in my game and so far it's been fine.
The thing I'd strongly discourage is using scripts for AI. It would be too slow, too hard to debug and I don't see the need for tuning AI algorithms so frequently. Scripts won't do any good here.
Scripts for procedural generation? Might be a good idea, but you can live without it. If you feel the need to throw in some more decorations or treasures to your dungeon, you can as well do it in your "hard" code. It's not as painful as GUI at least.
-
It makes me giddy that people use outdated languages that are slow to compile :P
If development speed is important, make everything a script except core elements that are unlikely to change and also areas where you feel compiled efficiency is needed. Of course, you can always translate a script into the compiled language if need be, so probably the best bet is to script everything you can until it is in a ready state.
-
It makes me giddy that people use outdated languages that are slow to compile :P
It's better to have a language that's slow to compile than one that's slow to execute :P.
If development speed is important, make everything a script except core elements that are unlikely to change and also areas where you feel compiled efficiency is needed.
"Making everything a script" you end up writing your script interface instead writing your game. Twice as much work and the effect is not guaranteed. Rather poor advice for development speed.
-
Of course, you can always translate a script into the compiled language if need be
You can, but it's sometimes very painful.
Consider the following task "Load a csv file as a matrix and for every value, print it and its position"
in ruby
mat = Matrix[*File.open(filename).map do |l| CSV.parse_line(l) end]
mat.each_with_index{|element, y, x| puts "#{element} at #{x}, #{y}"}
in java (with a third party lib)
InputStream input = LevelReader.class.getResourceAsStream(fileName);
CSVReader reader = new CSVReader(new InputStreamReader(input));
List<String[]> mat = reader.readAll();
for (int x = 0; x < mat.get(0).length; x++) {
for (int y = 0; y < mat.size(); y++) {
String s = mat.get(y)[x];
System.out.println(s + " at " + x + ", " + y);
}
}
-
jRuby and Ruby in general don't have a great reputation for speed. Clojure is pretty fast but a very different language to Ruby.
If the JVM is your primary concern it might be worth looking at Groovy or any of the other JVM languages (http://"http://en.wikipedia.org/wiki/List_of_JVM_languages").
If speed is your primary concern a C/C++ core with LuaJIT as the scripting language would be your best bet. There's a few 2D engines already that do this like Love, MOAI and so on. LuaJIT can be faster than Java so you can safely write more of your game in script without worrying about performance too much.
As for when and how to use scripting there's one primary model that seems to work the best. You have a small, fast engine written in your 'fast' language (JVM, C/C++ and so on) and then write most of the game logic in the scripting language. Anything that's too slow in script (e.g. A*, flood-filling) you move into the fast language. The key point is that you want the interface between the engine and the game to be as small and simple as possible or it becomes a nightmare to maintain.
-
Since your game is being done in Java or Ruby, both are interpreted languages. So I understand them as a bunch of script files. So your game is already a scripted engine without you to have to implement it and without the game player have to recompile everything.
And thus, why mess creating a custom scripting engine if your game is already implemented as an easy-to-modify game?
Why create a custom scripting engine if I can go to source code and modify whatever I need without having to recompile?
-
Since your game is being done in Java or Ruby, both are interpreted languages. So I understand them as a bunch of script files. So your game is already a scripted engine without you to have to implement it and without the game player have to recompile everything.
And thus, why mess creating a custom scripting engine if your game is already implemented as an easy-to-modify game?
Why create a custom scripting engine if I can go to source code and modify whatever I need without having to recompile?
Because you can't with java. java is compiled to byte code which is run on the jvm.
-
Java, just like any language worth something, is not interpreted at all.
They all compile to bytecode and run on a VM.
Which may (or may not) be veyr very well made and very very fast.
HotSpot (the JVM) and luajit are examples of extremely fast VMs, in some cases beating pure C
-
I once thought there is nothing useful in scripting and it's an old school idea from time when compiling really was slow.
I still don't get scripting as a language, but I've thought it could be useful in static data for game objects and stuff. The problem in C++ is the way you need to fill struct style data. It's static and sometimes annoying if you have a lot of data (not to mention if the structure changes). With scripting you could enter only the data you need for that object and not only that, you could use abstract data and basic types with possible special data for each object to reduce the amount of data you need to enter.
-
I am in the process of migrating more logic in Lanarts from C++ to Lua. It's a real-time game so speed is much more of a concern, so I have to take care. I find though that even with major blocks written in C++, having a scripting language call into it is immensely useful for experimentation. With good scripting language bindings, you don't necessarily end up with less complex quests/etc.
The moment you hit a block that requires some behaviour you haven't exposed, write it in your compiled language and expose it. You should make an attempt to expose as generic as possible behaviour, but IMO there is nothing wrong with having hybrid scripted & compiled code. You can leverage the ability to reload scripts in real-time to tune your quest (or whatever you're scripting), and write parts unlikely to change in the compiled language.
-
"Making everything a script" you end up writing your script interface instead writing your game. Twice as much work and the effect is not guaranteed. Rather poor advice for development speed.
You only need to write the interface to use a script once while you may need to rewrite the script's code any number of times. Writing an interface is obviously not twice the work, and if you're getting a lot of practice it becomes easier and easier to the point where it's just completely natural to tack on the interface at the end.
-
Anyway, people love bullet points, and I'd really appreciate if you could tell me, for each item, what should be scripted, what should be in java, and what should be in data files?
- menus (start, inventory, etc)?
- procedural level generators?
- quests?
- npc dialogue?
- AI?
Do you have a specific motivation for having scripted content or are you just trying it out for sake of trying it out (which is as good reason as anything else really)? Because you could just take the easiest one from the list, or the item that you need first and try with that. Instant gratification and learning experience. After the first try, think again to which direction to continue. (yes, I don't like to make big and detailed plans up front).
-
Anyway, people love bullet points, and I'd really appreciate if you could tell me, for each item, what should be scripted, what should be in java, and what should be in data files?
- menus (start, inventory, etc)?
- procedural level generators?
- quests?
- npc dialogue?
- AI?
Do you have a specific motivation for having scripted content or are you just trying it out for sake of trying it out (which is as good reason as anything else really)? Because you could just take the easiest one from the list, or the item that you need first and try with that. Instant gratification and learning experience. After the first try, think again to which direction to continue. (yes, I don't like to make big and detailed plans up front).
My main motivation is I find programming java tedious. Not as tedious as most other C-likes but still painful a lot of the time. However, it's fast, portable, has excellent tooling, and great profilers.
I guess tbh compilation speed is not a huge issue with java, it's pretty good at compiling only part of a project.
Anyway, I tore my hair out trying to embed jruby. The documentation is really shoddy. I'll leave it for now until it comes time for quests and complex AI. Just java and yaml.
-
You only need to write the interface to use a script once while you may need to rewrite the script's code any number of times. Writing an interface is obviously not twice the work, and if you're getting a lot of practice it becomes easier and easier to the point where it's just completely natural to tack on the interface at the end.
Okay, but doing so with 100% of your game logic completely distorts the main idea of scripting, which is getting rid of mundane, repetitive tasks (eliminating the need for recompilation is another thing, not so important actually, at least not if you write in Java or C#). Now if 100% of your logic is in the scripts, you suddenly have twice as much code. You will have to maintain that code. You will have to debug, profile, refactor and so on. And guess what? You will have to use a different set of tools for your "low-level" language and for the scripting language. Different debugger, different profiler, different syntax parser, etc. Does that make life any easier for you? Just imagine that you need to fix a bug and you don't know whether it is in the script or in the "low-level" code. What would you do? Run the debugger for the scripting language (assuming that it exists, which is not so obvious) and the "low-level" debugger at the same time? That must be fun.
-
My main motivation is I find programming java tedious. Not as tedious as most other C-likes but still painful a lot of the time. However, it's fast, portable, has excellent tooling, and great profilers.
I guess tbh compilation speed is not a huge issue with java, it's pretty good at compiling only part of a project.
Anyway, I tore my hair out trying to embed jruby. The documentation is really shoddy. I'll leave it for now until it comes time for quests and complex AI. Just java and yaml.
You may be interested in Lua Programming Language (http://www.lua.org) with LÖVE engine (https://love2d.org), allowing you to create any kind of 2D or 2.5D game and freely redistribute it, with great API documentation and very active and helpful community.
-
You only need to write the interface to use a script once while you may need to rewrite the script's code any number of times. Writing an interface is obviously not twice the work, and if you're getting a lot of practice it becomes easier and easier to the point where it's just completely natural to tack on the interface at the end.
Okay, but doing so with 100% of your game logic completely distorts the main idea of scripting, which is getting rid of mundane, repetitive tasks (eliminating the need for recompilation is another thing, not so important actually, at least not if you write in Java or C#). Now if 100% of your logic is in the scripts, you suddenly have twice as much code. You will have to maintain that code. You will have to debug, profile, refactor and so on. And guess what? You will have to use a different set of tools for your "low-level" language and for the scripting language. Different debugger, different profiler, different syntax parser, etc. Does that make life any easier for you? Just imagine that you need to fix a bug and you don't know whether it is in the script or in the "low-level" code. What would you do? Run the debugger for the scripting language (assuming that it exists, which is not so obvious) and the "low-level" debugger at the same time? That must be fun.
Sounds like you didn't read my original post completely. Anyway, there are no mundane/repetitive tasks in coding, only bad programmers :P You may write a single 'interface' that works with any number of scripts, so you really need to get away from this 'double code' idea.
-
Sounds like you didn't read my original post completely. Anyway, there are no mundane/repetitive tasks in coding, only bad programmers :P You may write a single 'interface' that works with any number of scripts, so you really need to get away from this 'double code' idea.
Let's make it clear: I'm not speaking about code duplication here. Duplication is an issue in itself, but only a minor one. All I wanted to say is that by moving all your logic into scripts you make the maintenance process a lot more complicated, and that's everything but speeding up the development.
-
My main motivation is I find programming java tedious. Not as tedious as most other C-likes but still painful a lot of the time. However, it's fast, portable, has excellent tooling, and great profilers.
I guess tbh compilation speed is not a huge issue with java, it's pretty good at compiling only part of a project.
Anyway, I tore my hair out trying to embed jruby. The documentation is really shoddy. I'll leave it for now until it comes time for quests and complex AI. Just java and yaml.
You may be interested in Lua Programming Language (http://www.lua.org) with LÖVE engine (https://love2d.org), allowing you to create any kind of 2D or 2.5D game and freely redistribute it, with great API documentation and very active and helpful community.
While I do like the lua language, I don't want to abandon the jvm, or the great IDE support for java. Netbeans is a boon for someone like me who constantly changes variable names lol
-
Well an important question in coding, one of if not the most important, is 'where does this functionality belong?'. When a piece of code (be it function or class or even application) starts developing an awareness of the world beyond it's very discrete purpose, that is a flashing neon sign that it is time to refactor.
So similar to how you refactor to introduce a configuration when it becomes clear a piece of information doesn't belong in the code, you will introduce scripting when it becomes clear that behaviour has no place in the code.
Where that line lies will depend on a lot of factors so is mostly a judgement call. Experience or requirements for a project can allow or force you to make that call early on. But in the absence of those, it simply becomes a matter of 'when it becomes appropriate'.