Malenfant wrote:Thanks! That worked, at least for printing "Hello, Universe!". But what are all the numbers for? They don't show up in the text file.
Assuming that you mean the numbers in commands
Code: Select all
celestia:print ("Opening file...", 1, -1, -1, 1, 4)
Code: Select all
celestia:print ("Outputting data...", 1, -1, -1, 1, 4)
and
Code: Select all
celestia:print ("Done!", 3, -1, -1, 1, 4)
These have nothing to do with the printing to the file. Maxim included these so the script would display what it is doing and as a sort of "in-code" documentation.
Note that all three of these are
celestia:print() commands. These are like the
celestia:flash() commands - they present the text on the screen. The first number is the number of seconds to leave the text on the screen (just like in
flash()). The next two numbers indicate where on the screen the text should be placed: the first -1 indicates to the left of screen, the second indicates at the bottom, hence -1, -1 means at the bottom left of the screen. The next two are "fine-tuning" and indicate how many characters and lines to offset the print position by. Using these four values allows you (with some twiddling and hair-pulling) to place the text anywhere you want on the screen.
And is there any way of controlling where the text file is saved to? It seems to end up in the default Celestia directory.
You would have to include the path in the filename used with
io.open(). e.g.
Code: Select all
io.open("C:/mydirectory/myfile.txt", "w")
And I really don't get why some commands require ':' and others require '.' as separators - it seems very inconsistent.
a) The simple answer:
'Cause that's the way it is!
b) The more detailed answer:
At first, there may seem to be an inconsistency, but it relates to object oriented programming techniques as opposed to traditional methods of accessing "structures" and "libraries". What seems inconsistent at first will become second-nature soon enough, and even make sense at some point.
Let's begin with the ".". You will find this is used mainly in two places: when accessing "libraries" and when extracting information from "tables". The use of a period to do this is a left-over (or "legacy") from the days of C and other similar languages. C has "libraries" and something close to a "table" called a "structure" and both of these used the period to get at stuff "inside" them.
But, what is a "library"? It is a group of related programming routines that have been bundled together and put in a single place where you can get at them. There is an io library that contains routines to open files, write to files, read from files, etc. Likewise, there is a math library that contains routines to do absolute values, sine functions, square roots and other things; and you call them by
a) opening the math library (which you don't have to do in CELX - the math library is already opened for you. But you do have to open the io library yourself by calling
celestia:requestsystemaccess())
b) calling the function you want such as math.abs(), math.sin() or math.sqrt().
But why always put the "math" in front? Simple - to distinguish it from any other routines that may be in other libraries. There is no abs() in the io library, but if there were then calling abs() would be confusing - which to you want? So you would call io.abs() as opposed to math.abs().
Okay, so what is a table? I don't know if you are familiar with arrays or not.
If you are, a table is a single-dimension array where each element of the array can contain any variable type.
If you don't know what an array is, think of it tables this way: you know that a variable can hold value. Well a table can hold several variables. Each variable has it's own name in the table. So instead of
Code: Select all
me_x = 1
me_y = 7
me_z = -2
him_x = 18
him_y = 2
him_z = 1
we could group the data into two tables:
Code: Select all
me = { x = 1, y = 7, z = -2 }
him = { x = 18, y = 2, z = 1 }
now to get at the
y value of
him we would use
him.yIf does not seem to make much sense right now, don't worry. As you continue to create more scripts you will find situations where it will make a lot of sense to group the variables together in tables.
At any rate, the important thing is that "." is used to specify the routine in a library (library.routine) or the element in a table (table.element).
Now, on to the ":". This is a little trickier unless you are familiar with OOP (Object Oriented Programming). Without delving too deep into this dark and mysterious world, in OOP an object is a representation of a "thing" - a "noun". The Celestia code is made up almost entirely of objects that call each other and pass information back and forth in order to make all those lovely little lights and coloured balls appear on the screen
. CELX has the ability to get at a few of different types of objects in Celestia. In particular CELX can see
celestia - an object that represents the entire simulation being run.
observer - an object that represents a single "view" within the simulation
object - an object that represents a celestial body (e.g. Jupiter or Earth)
position - an object that represents the position of something
... and few others that we don't need to get into here.
Now, as you can imagine, an object has a lot of information within it that we might like to get at. For instance, an observer object knows where in space that view is looking from, what direction it is facing, what it's current field of view is. An object can also do things. An observer object can go to a new position in space, it can change its field of view, it can look in a new direction. But how do we get at that information? How do we get an object to do something?
Well, you get at the information by calling a routine associated with the object, and likewise, you get the object to do things by calling a routine associated with the object. The format for doing this is object:routine(). So to get the position of the active observer
Code: Select all
-- call the celestia object's getobserver() routine
active_observer = celestia:getobserver()
-- returns an observer object which we will store in active_observer
-- call the observer object's getposition routine
observer_position = active_observer:getposition()
-- returns a position object which we will store in observer_position
Okay, so why ":" and not ".". Well, because that is the convention for calling routines associated with objects. If you ever plunge deeper into to world of OOP then you will see that there are practical reasons for this difference, but it would be nearly impossible to itemize them without this becoming a 2Mb post.
I hope that wasn't too overblown an answer. I thought you might like a little background and understanding. Afterall, the more you understand about how Lua and Celx do what they do, the better you can make them do what you want.