Suggest to make a cup of tea before reading this. It will take a while, as I have answered each question In Full :>
while GameRunning() do
rcolour = GetAsteroid(0):GetNumSeedlings(1)
if rcolour > 255 then
rcolour = 255
1- what does the 'r' refer to in 'rcolour'. i see that in some of annikks code there is 'g' colour. what is the difference and why?
is just a variable i created in order to have something by which to refer to the amount of Red
in the background colour.
You can see where I create it initially:rcolour = GetAsteroid(0):GetNumSeedlings(1)
...and then where I use it later - instead of a fixed number - to set the amount of Red
in the background colour:SetBackdropColour(rcolour,0,0)
So you see, you can create a variable with a name of your choosing simply by "declaring" what it's value is.
In this example we created a variable called rcolour
when we wrote that it should be equal to the number of Seedlings belonging to player 1 on Asteroid ID 0.
The reason I chose to call it "rcolour" is because it's a nice shorthand way of writing "the amount of red". I could just as easily have called it "redamount", or simply "red", and it would work fine.
Another important thing to understand is that All Variables Equal Nil Until You Declare Otherwise
is not the same thing as 0.
Nil means "no value".
This can be useful, for example if you want to check if something has happened. If say, the player moves a certain number of seedlings to an asteroid, you can create a trap for this with a "if, then, else" command, and the result will be to declare a variable like this: Fluffy = 0
Then later on you can check If Fluffy == Nil
and if that is true, then you will be able to say that the player hasn't moved that number of seedlings to the asteroid yet. But if the value of Fluffy
was not nil, but 0, then we know that the player HAS moved that number of seedlings to the target asteroid.
For practical purposes it's often useful to invert it, and say if the value of Fluffy
is NOT equal to Nil, then do something... else do nothing. You do that by using ~=
instead of ==
== Is Equal To
~= Is NOT Equal To
Oh and by the way, gcolour
as you may have guessed by now was simply the variable I created in order to control the amount of Green in the background colour. :>
So it would have been like this:SetBackdropColour(rcolour,gcolour,bcolour)
2- exactly why, or how, does the (0,0,x) part make it change between black and blue? i was hoping to have a range of say, 5 colours, that gradually, after every 45 seconds of game time, merge into the next colour, and so on. i would need to use the GameTime function for this.
(0,0,x) is key for the following reason: the 0,0 is fixed, but x
is a variable
. That means its value can change during the course of play. As opposed to the 0,0 which are fixed and will stay the same through the whole game.
To understand the whole, you have to understand each of the parts.
When the game loads, it runs all of the commands in function LevelSetup()
. Then the game begins, the player may start to give orders to their seedlings etc, and the function LevelLogic()
part of the level kicks in.
The While GameRunning() do
command is used right at the start of the function LevelLogic()
The end of the While GameRunning() do
section is signified by:coroutine.yield()
This command basically says "While the game is running, continually run the commands in this section".
So take a moment to imagine this: The game is continously running these commands, and depending on the number of commands it has to run it may do so several hundred or thousand times a second.
Now we start to imagine the commands we are putting into this section in a different way - it is as if they are tiny slices of time.
Each "game cycle", as I like to refer to them as, we declare that the variable time
is equal to the Game Time.
So imagine as the game constantly refreshes the value of the time
, each cycle increasing it by a tiny tiny fraction of a millisecond.
Now we have a variable that we can plug into a function. :>
Immedietely, we could do this:SetBackdropColour(time,time,time)
So that would mean when the game starts, it sets the value of time
and it's basically 0 because the Game Time on the very first game cycle will be pretty much 0. So it would then set the backdrop command to near enough (0,0,0) which is Black. It would set the backdrop to (0,0,0) because the value of time
is 0 and we are setting it as (time,time,time) in the command we used.
But then, as the game goes on, say after one minute (ie 60 seconds), the value of time is constantly refreshed and is now way up at 60. That means we'll be getting a backdrop(60,60,60) which is dark grey! You will actually be able to see the background colour becoming gradually whiter and whiter as the game time goes up, and the value of the time
variable goes up.
After about 4 minutes the background will be completely white... and once the game time is over 255 seconds the behaviour may be unpredictable :P
Now we have a variable called time
that increases as time goes by.
This is useful for lots of things, but there are some circumstances where we want a variable that goes up and down as time goes by... rather than just increasing forever.
To make a variable that does this, we need to use some clever maths. That's where the math.sin
function comes in.
Hmm. I have realised just now that I picked a bit of an unfortunate variable name "x
". Lets pretend it was actually called "bcolour
" - that will be less confusing...
So the complete function LevelLogic()
code would be like this:
while GameRunning() do
-- first we record the time
time = GetGameTime()
-- we can divide the time by a number - or multiply it - to slow down or speed up the pulses.
time = time / 3
-- now to get the pulsing effect:
bcolour = math.sin(time)
-- bcolour is now a value that ranges up and down between -1 and 1 over time.
-- for this example we want a value that ranges between 0 and 1.
-- lets modify bcolour a bit.
bcolour = bcolour + 1
-- now bcolour ranges between 0 and 2
bcolour = bcolour / 2
-- now it ranges between 0 and 1
bcolour = bcolour * 255
-- now it ranges between 0 and 255
-- this will make the background pulse between black and blue. :>
Do you remember in maths class drawing graphs of Y = Sin(X)
? Perhaps not, but if you plot this equation on a graph then this is what it will look like:
It's a wavy line. It pulses as a perfect spectral wave, free from spikes and jitters! Beautiful to crazy mathematician types, and very useful for creating pulsing effects in levels.
So how do we use this crazy beast? Well, like all mathematical formulas, you basically just plug in the numbers you want and away you go.Y = Sin(X)
..becomes..bcolour = Sin(time)
So now we are basically saying that the up and down motion on that graph is equal to bcolour
. The X-Axis on the graph is time, or in our case literally our variable called time
So what you _actually_ get for bcolour from that command, is a value that goes between 1 and -1. The very top of the curve on the graph is 1, and the very bottom is -1, with 0 being the horizontal axis. Try to look at the graph and visualise this - horizontal is time, vertical is resulting value of bcolour
. You need to understand this in order to understand how the pulsing effect works.
Then we just do a bit more arithmetic on the variable to modify the number to be more useful, and we are able to create a variable with a value that ranges between 0 and 255. :>
Then, finally, we simply plug that variable into the command like so:SetBackdropColour(0,0,bcolour)
And voila, at the bottom of the curve (bcolour = 0) we will get (0,0,0) which is black, and at the top of the curve (bcolour = 255) we will get (0,0,255) which is blue. :>
3- to add asteroids ive merely been copying and pasting the previous code, so im ending up with lots of repititious code. i see that there is another way of doing this to avoid the ugliness and lengthiness of my approach. how do you add many asteroids, while still placing them where you want, without all the repetitive copy and pasting of the same code?
You can add asteroids in lots of different ways.
You can place them one by one by writing out their positions and attributes individually.
Or you can use the inbuilt AddAsteroidRing(number of Asteroids, X-coordinate of the center, Y-coordinate of the centre, overall radius of the ring, width of the ring)
The way I did it in Day & Night, and also for Infected Empire, is to use a for
That basically says, "for this
number of times, run these
commands" - similar to the "While" loop we talked about earlier, but it also lets you use "this
" as a variable. So you can count which pass you are on.
So in Day & Night the For
loop looked like this:for i=1,21 do
So I'm saying, "run all of the below commands, and each time you run them, increment "i" by one, until you reach 21, then stop".
The "1" refers to the number to start counting FROM. Sometimes its more useful to start counting 0,1,2,3,4,5,6... instead of 1,2,3,4,5,6...
This leads perfectly onto the next question....
4- What is the t = 1600 doing? is that just setting a particular letter and number value for later use? or is it specific to something?
...then, for the commands nestled inside my For
loop, I plugged in the mathematical formula for a spiral, and used the "t" value as the "period", or the amount to go further round the spiral before plopping the next asteroid down.
So I made my asteroids coordinates with this spiral command:x = math.cos(t) * t
y = math.sin(t) * t
and then each time it runs through the For
loop, it also does this:t = t + 275t
is the amount further round the spiral we shall travel, before we lay another an asteroid thusly:a = AddAsteroidWithAttribs(x,y,s,e,sp)x
for each asteroid are thus calculated based on the period t
which is incremented on every pass of the For
To be honest this was quite advanced - maybe it would be better to make some basic maps first before you start worrying about procedural generation :P
Will start a new post to answer the rest.