Author Topic: Intermediate coding guide  (Read 35836 times)

annikk.exe

  • Achiever
  • Ent
  • ****
  • Thank You
  • -Given: 0
  • -Receive: 4
  • Posts: 1,809
Intermediate coding guide
« on: January 21, 2011, 11:10:31 PM »
Hi coders!




Required Knowledge
This guide is intended for people who have covered the beginner's guide, done a little basic map-making of their own to get used to things, and now are ready to move on and learn about the structural commands and techniques needed for more advanced scripting.

Scope
This guide looks almost exclusively at function LevelLogic() - it is assumed that a suitable LevelSetup() already exists with appropriate asteroids added, etc.  It will cover the syntax of various important structural commands, various commands from the maths library, and usage examples.

Could be heavy going..!
Yea, I know you're eying the size of the scrollbar nervously.  This IS a long document.  However, I have split this guide into numbered chunks, each of which should take no longer than 20 minutes to read and thoroughly understand.  Please, give section 1 a read through, and hopefully you will see that it's not all that difficult.  :>  I promise to regale you with my distinctive brand of humour along the way.  Or something.




Contents:

  • 1.  while GameRunning() do
  • 2.  for loops
  • 3.  Arrays
  • 4.  math.random
  • 5.  math.sin, math.cos
  • 6.  Build your own functions!



1.  While GameRunning() do

i)
Code: [Select]
function LevelLogic()

while GameRunning() do

-- later on we'll put some commands here!

coroutine.yield()
end
end


The commands above create a loop that is run continuously, at a rate of 60 times per second, until the game ends.

This specific type of While loop is useful for all sorts of scripting, and I recommend using it as a base for any advanced scripting level.  It's the only while loop you will need in your code - in fact I'd suggest you should avoid using other While loops altogether.

Any code you place after this loop's end will never run.
Code: [Select]
function LevelLogic()

while GameRunning() do

-- later on we'll put some commands here!

coroutine.yield()
end

-- CODE PLACED HERE WILL NEVER RUN

end
That is because the condition of the while loop is "while the game is running".  The game is always running!  :>  The game is only considered to have ended when the player quits, or a Quit() command is triggered, causing the player to return to the menu.


In the beginner's guide, we looked at how you can use the OnAsteroidTaken(id,owner) function to trigger a Victory or Loss.
Now we'll look at another method of doing this using a while GameRunning() do loop, which will work much better alongside our other scripts.



ii)

Suppose we want the player to win if they've taken over the whole galaxy, and lose if they've lost all their asteroids.
First lets make a While GameRunning() do loop and populate it with comments to remind ourselves what each bit of code needs to do, and where it needs to be inserted.


Code: [Select]
function LevelLogic()

while GameRunning() do
-- if player 1 has conquered whole galaxy then
-- Quit(true)

-- if player 1 has lost all asteroids then
-- Quit(false)

coroutine.yield()
end
end



iii)
So how to tell if the player has conquered the whole galaxy?


One way would be to check if the number of asteroids the player owns is equal to the number of asteroids in the level.
If it is, that means the player must own every asteroid - fulfilling the victory condition.

Code: [Select]
if GetEmpire(1):GetNumOwnedAsteroids() == 20 then
Pause()
MessageBox("You have won")
WaitDialog()
Unpause()
Quit(true)
end

This would work fine if the number of asteroids in the level is indeed 20.

But what if you decide later on to go back and add more asteroids?  If there are 25 asteroids in the level but the If statement is only looking for 20, then the player will win when there are 5 asteroids still to conquer.
So although this would work, it's not ideal because it means every time we add or remove asteroids from the level we also have to change the number of asteroids the victory condition is checking for.

So what other method could we use that avoids this problem?



iv)
Well, maybe we could check how many asteroids are owned by the other empires.
If this map only has empire 2 in it, then maybe we could check it like this:

Code: [Select]
if GetEmpire(2):GetNumOwnedAsteroids() == 0 then
Pause()
MessageBox("You have won")
WaitDialog()
Unpause()
Quit(true)
end

Then when Empire 2 has no asteroids left, player 1 would win.  Doing it like this would mean subsequent changes to the number of asteroids in the level would not break the win condition.  :>

But there's a potential problem with this too.  Suppose there are 20 asteroids and the player conquers 5 of them, then goes straight on to conquer all 5 of Empire 2's asteroids.  That leaves 10 asteroids uncolonised, ie they belong to the greys (empire 0).

The player would win at this point even though they've only conquered half the galaxy - because Empire 2 has 0 asteroids left.





This behaviour isn't bad, but the behaviour we were actually looking for is "if the player has conquered the whole galaxy"...



v)
If we really want the player to have to take over the whole galaxy to score a win, we would need to make a modification to our If statement to include Empire 0:

Code: [Select]
if GetEmpire(2):GetNumOwnedAsteroids() == 0 and GetEmpire(0):GetNumOwnedAsteroids() == 0 then
Pause()
MessageBox("You have won")
WaitDialog()
Unpause()
Quit(true)
end

That's better.  :>  We're saying If Empire 2 doesn't have any asteroids left, and Empire 0 doesn't have any asteroids left, then the player wins.
Now this will mean the player must conquer every asteroid in the level in order to win.


vi)
Ok but what if you have Empire 3, too?  What then?  The statement in its current form doesn't check for Empire 3 at all, so if there is an Empire 3 in the level then the player might win even when Empire 3 still owns some asteroids!

We could make another modification to our If statement to also take Empire 3 into account:

Code: [Select]
if GetEmpire(2):GetNumOwnedAsteroids() == 0 and GetEmpire(3):GetNumOwnedAsteroids() == 0 and GetEmpire(0):GetNumOwnedAsteroids() == 0 then
Pause()
MessageBox("You have won")
WaitDialog()
Unpause()
Quit(true)
end




So there's our victory condition.



vii)
What about the loss condition?





Well, in our comments we said that the player should lose "if the player has lost all asteroids".

So we can represent that like this:

Code: [Select]
if GetEmpire(1):GetNumOwnedAsteroids() == 0 then
Pause()
MessageBox("You have lost")
WaitDialog()
Unpause()
Quit(false)
end

Looking at this code, it seems it should work no matter how many asteroids or empires we add or remove.  :>
The loss condition is a lot simpler to make than the win condition..





viii)
Lets return to the template that we wrote out at the start:
Code: [Select]
function LevelLogic()

while GameRunning() do
-- if player 1 has conquered whole galaxy then
-- Quit(true)

-- if player 2 has lost all asteroids then
-- Quit(false)

coroutine.yield()
end
end



ix)
...and populate it with the Win Condition we made in step vi)....
Code: [Select]
function LevelLogic()

while GameRunning() do
-- win condition
if GetEmpire(2):GetNumOwnedAsteroids() == 0 and GetEmpire(3):GetNumOwnedAsteroids() == 0 and GetEmpire(0):GetNumOwnedAsteroids() == 0 then
Pause()
MessageBox("You have won")
WaitDialog()
Unpause()
Quit(true)
end

-- if player 2 has lost all asteroids then
-- Quit(false)

coroutine.yield()
end
end



x)
... and the Lose Condition from step vii).  :>
Code: [Select]
function LevelLogic()

while GameRunning() do
-- win condition
if GetEmpire(2):GetNumOwnedAsteroids() == 0 and GetEmpire(3):GetNumOwnedAsteroids() == 0 and GetEmpire(0):GetNumOwnedAsteroids() == 0 then
Pause()
MessageBox("You have won")
WaitDialog()
Unpause()
Quit(true)
end

-- lose condition
if GetEmpire(1):GetNumOwnedAsteroids() == 0 then
Pause()
MessageBox("You have lost")
WaitDialog()
Unpause()
Quit(false)
end

coroutine.yield()
end
end


Now we've made a working Win/Lose condition using a while GameRunning() do loop.  :>  This will set us up for scripting some advanced behaviours.






This data tunnel is what advanced coding actually looks like...






2.  For loops



i)
The for loop is an essential tool when it comes to coding.
A typical for loop might look like this:

Code: [Select]
for i = 0,9 do

-- some code goes here

end

As you can see, it too needs an "end" to close it off.
What are the numbers about though?  And what's that "i =" doing there?


ii)
This type of loop counts from the first number (0) to the second number (9), and runs the code within the loop for each number counted.

The example above would start with the counter called "i" on "0", and then run all the code inside the loop.  Then, it would increment the counter by one, and run through all the code again.  Then it increments "i" again, runs the code again, and so on.
After the code has been run for the 10th time (ie "i" = 9) then the loop will stop and exit at the end



iii)
The first and most obvious use of a for loop is to run a piece of code multiple times.  For example, the code below would produce 3 message boxes:
Code: [Select]
for i = 0,2 do
MessageBox("Hallo Fluffy")
end




iv)
The second thing that for loops are useful for, is to change values for lots of different entities that are numbered.  For example, asteroids.  :>
Asteroids are numbered according to their ID.  Suppose we had 100 asteroids and wanted to change the Send Distance of all of them at once.  Here is how we could do it:

Code: [Select]
for i = 0,99 do
GetAsteroid(i).SendDistance = 5000
end

What will happen is that each time the loop runs through, "i" is increased by 1, and then when we refer to "GetAsteroid(i)" it's simply getting whichever asteroid ID currently corresponds to the value of "i".

So on the first run through of the loop, the command effectively reduces to this:
Code: [Select]
GetAsteroid(0).SendDistance = 5000
On the second pass of the loop, it would resolve to this:
Code: [Select]
GetAsteroid(1).SendDistance = 5000
...and so on.



v)
Thus, this:
Code: [Select]
for i = 0,99 do
GetAsteroid(i).SendDistance = 5000
end

...is just a (much) shorter way of writing this:
Code: [Select]
GetAsteroid(0).SendDistance = 5000
GetAsteroid(1).SendDistance = 5000
GetAsteroid(2).SendDistance = 5000
GetAsteroid(3).SendDistance = 5000
GetAsteroid(4).SendDistance = 5000
GetAsteroid(5).SendDistance = 5000
GetAsteroid(6).SendDistance = 5000
GetAsteroid(7).SendDistance = 5000
GetAsteroid(8).SendDistance = 5000
GetAsteroid(9).SendDistance = 5000
GetAsteroid(10).SendDistance = 5000
GetAsteroid(11).SendDistance = 5000
GetAsteroid(12).SendDistance = 5000
GetAsteroid(13).SendDistance = 5000
GetAsteroid(14).SendDistance = 5000
GetAsteroid(15).SendDistance = 5000
GetAsteroid(16).SendDistance = 5000
GetAsteroid(17).SendDistance = 5000
GetAsteroid(18).SendDistance = 5000
GetAsteroid(19).SendDistance = 5000
GetAsteroid(20).SendDistance = 5000
GetAsteroid(21).SendDistance = 5000
GetAsteroid(22).SendDistance = 5000
GetAsteroid(23).SendDistance = 5000
GetAsteroid(24).SendDistance = 5000
GetAsteroid(25).SendDistance = 5000
GetAsteroid(26).SendDistance = 5000
GetAsteroid(27).SendDistance = 5000
GetAsteroid(28).SendDistance = 5000
GetAsteroid(29).SendDistance = 5000
GetAsteroid(30).SendDistance = 5000
GetAsteroid(31).SendDistance = 5000
GetAsteroid(32).SendDistance = 5000
GetAsteroid(33).SendDistance = 5000
GetAsteroid(34).SendDistance = 5000
GetAsteroid(35).SendDistance = 5000
GetAsteroid(36).SendDistance = 5000
GetAsteroid(37).SendDistance = 5000
GetAsteroid(38).SendDistance = 5000
GetAsteroid(39).SendDistance = 5000
GetAsteroid(40).SendDistance = 5000
GetAsteroid(41).SendDistance = 5000
GetAsteroid(42).SendDistance = 5000
GetAsteroid(43).SendDistance = 5000
GetAsteroid(44).SendDistance = 5000
-- ok i can't be bothered writing them all out.
-- hopefully you get the idea...
-- ...
GetAsteroid(97).SendDistance = 5000
GetAsteroid(98).SendDistance = 5000
GetAsteroid(99).SendDistance = 5000



vi)
Finally, just so you're aware, you don't have to use "i" for the counter.  You can use whatever name you want.  For example:

Code: [Select]
for fluffy = 0,99 do
GetAsteroid(fluffy):AddSeedlings(fluffy)
end

That would put 0 seedlings on asteroid 0, 1 seedling on asteroid 1, 2 seedlings on asteroid 2, etc.
It doesn't matter that we called the counter "fluffy" instead of "i".  It will still work just fine.  :>




This explosion is HUGE....




3.  Arrays



i)
Arrays are special variables that have lots of different "slots" for storing values, rather than just being one big slot like the variables we've seen so far.
Another way to think about arrays is to imagine them as numbered lists.




ii)
Lets look at some array syntax.


Before you can use an array, you must first declare it like this:
Code: [Select]
fluffy = {}Note the unusual shaped brackets.  This creates an empty array called fluffy.

The usual place to put this command is anywhere in function LevelSetup(), but for now, to keep everything together, I'll put mine at the very top of function LevelLogic().


Code: [Select]
function LevelLogic()

-- declare the array
fluffy = {}


while GameRunning() do
-- some commands go here later
coroutine.yield()
end
end




iii)
Now that we've initialised the fluffy array, we can start assigning values to the slots in it.  But how to refer to the different slots in fluffy?

The answer is with some square brackets tagged on the end like this: fluffy[0]
That would refer to slot 0 of fluffy.

From now on when we refer to the array, we always refer to the slot number that we are interested in as well.
By convention, we usually start with slot 0.




So we can use commands like these:

Code: [Select]
fluffy[0] = 2
fluffy[1] = 4
fluffy[2] = 7
fluffy[3] = 9
fluffy[4] = 5





iv)
Then, when we want to know about the value in a slot, we can test it using the same square brackets as above.  For example:

Code: [Select]
if fluffy[0] == 2 then
MessageBox("w00t!")
end


So what practical use is this?
Well, as I discovered, it turns out there are all sorts of reasons why you might want to store things in an array like this.
To illustrate why, and also to show you a good example of using an array to do useful work, lets implement an example advanced behaviour using some arrays.

What we will do is create a mechanic whereby the player's lasermine can fly from one asteroid to another, and each asteroid they fly to changes the background to a different colour.

So when the game starts, the player's lasermine is orbiting the first asteroid, and the background is black.  When it flies to a nearby second asteroid, the background turns red.  When it flies to the next asteroid, the background turns blue, and so on.

We will store the colours in three arrays named red, green and blue because those are nice logical names that we can plug into our SetBackDropColour command later on.


v)
In this example lets assume there are 5 asteroids in the level, numbered 0, 1, 2, 3 and 4.
At the top of our function LevelLogic(), before the start of the while loop, I'll initialise the arrays and assign some values to them.

Code: [Select]
function LevelLogic()

-- initialise arrays
red = {}
green = {}
blue = {}

-- assign values for the different slots in the arrays
red[0] = 0
green[0] = 0
blue[0] = 0

red[1] = 255
green[1] = 0
blue[1] = 0

red[2] = 0
green[2] = 255
blue[2] = 0

red[3] = 0
green[3] = 0
blue[3] = 255

red[4] = 127
green[4] = 0
blue[4] = 127




while GameRunning() do

-- later on we'll put some commands here!

coroutine.yield()
end

end




vi)
Now we'll just need to make some code in our while loop to check if the player has a mine at any of the asteroids.
Here we can combine the for loops we learned about earlier with the arrays we've just initialised.

Code: [Select]
function LevelLogic()

-- initialise arrays
red = {}
green = {}
blue = {}

-- assign values for the different slots in the arrays
red[0] = 0
green[0] = 0
blue[0] = 0

red[1] = 255
green[1] = 0
blue[1] = 0

red[2] = 0
green[2] = 255
blue[2] = 0

red[3] = 0
green[3] = 0
blue[3] = 255

red[4] = 127
green[4] = 0
blue[4] = 127


while GameRunning() do

-- Check all the asteroids in turn
for i = 0,4 do
-- if an asteroid has a player mine on it...
if GetAsteroid(i):GetNumMines(1) > 0 then
-- set the backdrop colour to the values for slot i in the red, green and blue arrays
SetBackdropColour(red[i], green[i], blue[i])
end
end

coroutine.yield()
end

end


And that is how we can use arrays to do useful things for us.
You can download a playable level file containing this example script and check out the functionality for yourself.  It's attached to the bottom of this post, named "array example.lua".






vii)
Before we finish up with arrays, lets look at how you might set the values for hundreds of slots in an array using a formula placed inside a for loop.

Imagine the example above, but instead of 5 colour-changing asteroids, we have 500 colour-changing asteroids!
Clearly setting these manually would take a very long time.

Therefore it becomes necessary to think up some way to set the colours for all 500 at once.

Lets take the red array as our example, and figure out some way to generate different values for all 500 slots.

Code: [Select]
for i = 0,500 do
red[i] = ?
end

Any ideas?  Well, the very most simple thing we could do is to make the slot [i] equal to the value i itself.

Code: [Select]
for i = 0,500 do
red[i] = i
end

Then slot 0 would contain the value 0, slot 230 would contain the value 230, and so on.



viii)
That's a bit boring though - and besides, Asteroid 500 would have the corresponding red value of 500, and that's more than the maximum 255 that SetBackdropColour is expecting.
Maybe we can use some maths to make a more interesting series of values!

Code: [Select]
for i = 0,500 do
red[i] = 1 / i
end

That should be pretty cool.  Imagine what this would work out as, for all the different values of i.
If i = 2, then the calculation would be 1 / 2 = 0.5
If i = 5, then the calculation would be 1 / 5 = 0.2
If i = 10, then the calculation would be 1 / 10 = 0.1
If i = 100, then the calculation would be 1 / 100 = 0.01



ix)
There's a problem with this though.
What do you think happens when i = 0?

If i = 0, then the calculation would be 1 / 0 = ........

Dividing by zero makes Eufloria crash.  It's because if you divide something by zero, the answer is always infinity.




To combat this problem, we can make a change:

Code: [Select]
for i = 0,500 do
red[i] = 1 / (i + 1)
end


Why do you think we need "(i + 1)" and not simply "i" on its own?

We add 1 to i.  That way on the first cycle it works out as 1 / 1, which is just a nice harmless 1 instead of an infinity.  :>
The curly brackets just mean that part of the calculation will be worked out first, as a seperate chunk - before the result is used in the rest of the calculation.



x)
This calculation will then give us an array called red that has all its slots filled with values between 0 and 1.
This is ideal mathematically, because it means we can just multiply in the range that we need.  In this case, SetBackdropColour expects values between 0 and 255.
So we just multiply each value by 255:

Code: [Select]
for i = 0,500 do
red[i] = 1 / (i + 1)
red[i] = red[i] * 255
end


Then, using some similar example calculations as we used above...

If i = 0, then the calculation would be (1 / (0 + 1)) * 255 = 1 * 255 = 255
If i = 1, then the calculation would be (1 / (1 + 1)) * 255 = 0.5 * 255 = 127
If i = 4, then the calculation would be (1 / (4 + 1)) * 255 = 0.2 * 255 = 51
If i = 9, then the calculation would be (1 / (9 + 1)) * 255 = 0.1 * 255 = 26
If i = 99, then the calculation would be (1 / (99 + 1)) * 255 = 0.01 * 255 = 3

Hopefully you should be able to see from this selection of examples that this gives us a nice smooth gradiant of different values.  The asteroids with the lowest ID numbers will be reddest.  :>



Multiple arrays can be combined to represent a matrix.  We'll cover matrix usage in a future Advanced Guide.


It's up to you to find your own formulas to assign values for your arrays.  The maths sections below will help you with this.






4.  math.random
i)
The command math.random(a,b) generates a random number between a and b.






So for example, the following command would mean that the variable "MyRandomNumber" is assigned a value between 1 and 6.

Code: [Select]
MyRandomNumber = math.random(1,6)
This is the equivalent of rolling a six-sided dice.  :>


ii)
So what use is this?
Well, it's useful for all sorts of things.  One good example is randomising the stats of your asteroids.  This can make the level different every time it is played, adding variety.

Suppose we have an asteroid like this one...

Code: [Select]
a = AddAsteroidWithAttribs(1500,1200, 0.5,0.5,0.5)
a.owner = 1
a.TreeCap = 3
a.radius = 200
a.SendDistance = 2000
a.Moveable = false

a:AddSeedlings(20)


We could make some of the stats random, like this:


Code: [Select]
a = AddAsteroidWithAttribs(1500,1200, 0.5,0.5,0.5)
a.owner = 1
a.TreeCap = math.random(2,5)
a.radius = math.random(100,450)
a.SendDistance = 2000
a.Moveable = false

a:AddSeedlings(math.random(10,50))

Now the asteroid will have a different treecap, radius and number of seedlings each time we play.  :>



iii)
How else could we improve this code?

Well, we could randomise the send distance, too.
That would be like this:

Code: [Select]
a.SendDistance = math.random(1500,2500)
But the problem with that approach is that we lose the relationship between an asteroid's radius, and its Send Distance.  It's visually pleasing to have asteroids with send distances proportional to their size.



So maybe we could do something else instead, that preserves the relationship between size and send distance...

Code: [Select]
a.radius = math.random(100,450)
a.SendDistance = a.radius * 10

This means that if the asteroid spawns with a radius of 100, its send distance would be 1000; if it spawns with radius 250, its send distance would be 2500, and so on.
This technique allows us to model the send distance after the asteroid size, even when we don't know in advance exactly what size the asteroid will be.




iv)
What else could we do to make it even more random?

Well, we could try adjusting the X and Y coordinates of the asteroid.
So our a = AddAsteroidWithAttribs(1500,1200, 0.5,0.5,0.5) becomes this:

Code: [Select]
a = AddAsteroidWithAttribs(math.random(-1500,1500),math.random(-1200,1200), 0.5,0.5,0.5)
Negative numbers like those in the line above work fine in math.random.  :>

But, there is a problem with randomising asteroid positions, and that is that there's a chance asteroids may spawn on top of each other!
This clearly will not do, so to fix it we can change the Moveable command from false to true.

Code: [Select]
a.Moveable = true
Then, if asteroids spawn on top of each other, the game will move them apart for us.  :>



v)
Lets take a look at what we've got so far:

Code: [Select]
a = AddAsteroidWithAttribs(math.random(-1500,1500),math.random(-1200,1200), 0.5,0.5,0.5)
a.owner = 1
a.TreeCap = math.random(2,5)
a.radius = math.random(100,450)
a.SendDistance = a.radius * 10
a.Moveable = true

a:AddSeedlings(math.random(10,50))

That's pretty damn random!

We might get a tiny asteorid with treecap 5 and 50 seedlings to the northeast, or we might get a large asteroid with treecap 2 and 10 seedlings to the south...  And so forth.

There's one more thing I want to show you while we're looking at math.random, and that is the question of how to randomise asteroid attributes effectively.




vi)
Consider this command:

Code: [Select]
a = AddAsteroidWithAttribs(math.random(-1500,1500),math.random(-1200,1200), math.random(0,1),math.random(0,1),math.random(0,1))
Ok so it's a long one, but basically if you study that, you should get that the asteroid attributes should be between 0 and 1.
Well, that's correct.  But there's a problem that you would quickly discover if you were to use this type of command on one of your asteroids.  See if you can figure out what it is.  :>  You'll be doing well if you manage, because I haven't explicitly mentioned it yet...

In the mean time, lets reorganise that line so it's much easier to read:


Code: [Select]
-- generate X and Y
x = math.random(-1500,1500)
y = math.random(-1200,1200)

-- generate stats
energy = math.random(0,1)
strength = math.random(0,1)
speed = math.random(0,1)

-- add the asteroid
a = AddAsteroidWithAttribs(x,y, energy,strength,speed)

That's better.  Did you spot what the problem could be?








vii)
The problem we will face is that the asteroid's attributes will be set to either total maximum (1) or nothing whatsoever (0).
There's no in between!

To have nice stats for our asteroids, we actually wanted values between 0 and 1 - not 0 or 1 themselves!
More generally, we can say that the math.random(a,b) command generates an integer (a whole number) between A and B.

So suppose we used math.random(1,5)

Values we might get from that command:

  • 1
  • 2
  • 3
  • 4
  • 5

Values we definitely WOULD NOT get from that command:

  • 0
  • 7
  • 1.5
  • 3.141592653
  • -3


Hopefully this is crystal clear to you now.  Assuming so, lets press on and solve the asteroid attributes problem!



viii)
If we really need random values like 0.3, we are going to have to find a way to make them out of integers.
Here's one way:

Code: [Select]
-- generate stats
energy = math.random(0,10) / 10
strength = math.random(0,10) / 10
speed = math.random(0,10) / 10

So lets follow through what happens here.
Take energy for our example.  First, a random number between 0 and 10 is generated; lets say we generate a 6.
Then, that 6 is divided by 10.  What's 6 divided by 10?  It's 0.6!
So then the asteroid would have 60% energy.




ix)
The problem with that approach, once again, is that simply randomising the asteroid's attributes sometimes results in tiny asteroids with awesome stats, and huge asteroids with rubbish stats.
This breaks the relationship we talked about earlier between the size of an asteroid, and its quality.

What do we really need, then?
Lets think about this.  It's important to put the solution into words (and perhaps diagrams) before we try to code it.

We need asteroids to have their stats correspond with their size.  But we don't simply want flat values for energy, strength and speed - we want the proportions of each stat to be random.
So for example, we want an average sized asteroid to have stats like 0.3,0.7,0.5 - NOT 0.5,0.5,0.5.

I know a good solution to this problem, but instead of me telling you what it is yet again, I'm going to leave this problem open-ended and see if you guys can work it out.  :>  If you've read this far down the guide you already know everything you need to know in terms of commands needed to code it.



5.  math.sin, math.cos
i)
Maybe you remember these dreaded symbols from school.  If you're anything like me, the "sin" and "cos" buttons on my calculator taunted me back in maths class with their mystery.  Nobody ever really bothered to explain to me what they actually are.  I mean, what are they?  Sure, you put numbers into them and a result magically comes out, but how?

Incidentally, I had forgotten just about everything I used to know about their usage when I started teaching myself to code in lua.  I had to figure this out on my own from researching it on the internets.  So even if you've never heard these terms before in your life, don't worry.  I'll help you to understand them.  :>

The first half of this section will focus on helping you to conceptualise what sine and cosine are.
The second half will focus on using the calculations in your scripts to do useful (and often spectacular!) work.



ii)
The commands might be used inside of a while GameRunning() do loop, as follows:

Code: [Select]
x = math.sin(GetGameTime())
y = math.cos(GetGameTime())

...or to make it slightly clearer, lets assign the game time to a variable first:

Code: [Select]
time = GetGameTime()
x = math.sin(time)
y = math.cos(time)

We feed a value into the math.sin or math.cos (in this case, time).
Then we record the result to a variable, in this case x and y respectively.

What sort of values will we get for x and y as the Game Time proceeds?



iii)
It will always be a value between -1 and 1.  So it might be 0.33351, or it might be -0.778391, or it might even be 0.  It all depends on what value is fed into it.
If sin is plotted on a graph, it produces a wavy line:



This wavy line repeats itself for as long as the value fed in (eg GetGameTime()) increases.
The graph for cos is almost exactly the same.  The only difference is that it starts with the line in a different position.  Don't worry about this for now, it will all become clear (hopefully!)



iv)
Lets proceed to conceptualising how this "value between -1 and 1" is calculated.


Imagine you are a bird hovering above a field.

In the field below you is a circular train track.

A train drives in circles round the track.




The distance the train has travelled so far is what we will feed into our sin and cos to produce the values between -1 and 1.

math.sin(DistanceTravelled) is equal to wherever on the vertical axis the train would be after travelling that far.
math.cos(DistanceTravelled) is equal to wherever on the horizontal axis the train would be after travelling that far.


So for example, if math.cos(DistanceTravelled) = -1, the train must be on the west side of the track.


Lets look at another diagram to try to visualise this better:





v)
That's the whole deal.
Sin and cos are simply representations of each axis when imagining travelling round and round in a circle.

So if the train had gone round the circle exactly once, the output would be the same as if it had gone round the circle exactly twice, or exactly 3 times.

Please download and run the level file attached to this post called "sincos example.lua"
Play the level in Eufloria and you can see another example of what sin and cos do.  Check the names of each asteroid to see what they represent.



vi)
The commands math.sin() and math.cos() both expect a number inside their brackets, as we've seen.
This input is technically thought to be radians, rather than train tracks or seconds of game time, but in reality you can use any unit of measurement you want and it will be considered as the radians-equivalent.  Time is a very common thing to use as the input for sin and cos, because it continually counts up at a steady pace, making it ideal for achieving regular pulsing motions.

Now lets look at some useful things we can do with this pulsing effect.




vii)
First of all lets build our usual wrapper for this to go into:

Code: [Select]
function LevelLogic()
while GameRunning() do

-- some code goes here later!


coroutine.yield()
end
end


Now we'll record the game time to a variable called time...

Code: [Select]
function LevelLogic()
while GameRunning() do

-- record the time
time = GetGameTime()


coroutine.yield()
end
end


Now lets create a variable called.... oh... I don't know, I guess we'll go with something generic like input.


Code: [Select]
function LevelLogic()
while GameRunning() do

-- record the time
time = GetGameTime()

-- calculate a value for "input" by taking the math.sin of time
input = math.sin(time)

coroutine.yield()
end
end


A good start.  Now the variable called input will pulse between -1 and 1 as the game progresses.

1

-1

In this graph, the X-axis represents game time.  The Y-axis represents the value we'll get for input.



viii)
Now that we've got our pulsing variable, lets figure out something that it could control.

How about the radius of an asteroid?
We could make an asteroid grow bigger, then smaller... then bigger, then smaller...

For that, values between -1 and 1 are no good.  We need values between, say, 50 and 500!
Time to do some maths to change input to our desired range of values.

Code: [Select]
-- input is a value between -1 and 1

input = input + 1
-- now input is a value between 0 and 2

input = input / 2
-- now input is a value between 0 and 1

input = input * 450
-- now input is a value between 0 and 450

input = input + 50
-- now input is a value between 50 and 500!

I did it in some slow steps there to make it easy to follow, but to make things a bit neater, I could just bundle all of that into one line like this:

Code: [Select]
input = (((input + 1) / 2) * 450) + 50


iv)
Now lets fire that line into the rest of our code:


Code: [Select]
function LevelLogic()
while GameRunning() do

-- record the time
time = GetGameTime()

-- calculate a value for "input" by taking the math.sin of time
input = math.sin(time)
-- now input is between -1 and 1

input = (((input + 1) / 2) * 450) + 50
-- now input is between 50 and 500


coroutine.yield()
end
end

Finally, lets change the radius of Asteroid 0 using our "input".


Code: [Select]
function LevelLogic()
while GameRunning() do

-- record the time
time = GetGameTime()

-- calculate a value for "input" by taking the math.sin of time
input = math.sin(time)
-- now input is between -1 and 1

input = (((input + 1) / 2) * 450) + 50
-- now input is between 50 and 500

GetAsteroid(0).radius = input


coroutine.yield()
end
end


And there we have it.  Download the level file "pulse example.lua" and play it in Eufloria to see this code in action.




6.  Build your own functions!
i)
This is it.  This is the part where you realise you are actually inside the matrix.



Well, I guess we'll start at the beginning.  What is a function?


A function is a container for code.
You put code inside the container, and then you "call" the function from elsewhere.

This very general description likely makes little sense to you for now.  Don't worry!   Lets look at some examples.



ii)
For our first example, lets imagine it's the start of the game and you want to bring up a MessageBox to greet the player.
Your function LevelLogic() might look like this:


Code: [Select]
function LevelLogic()

Pause()
MessageBox("Welcome to happyfuntimeland.  Is nice here.")
WaitDialog()
Unpause()
end

Four lines of code just to bring up a message on the screen!
It's not a problem for now really, but when you have a LevelLogic() that is several hundred lines long, it can start to become a nightmare to keep track of where everything is.


Lets put those 4 commands into a function.
We place this text below everything else, including the "end" of your LevelLogic().

Code: [Select]
function GreetPlayer()
Pause()
MessageBox("Welcome to happyfuntimeland.  Is nice here.")
WaitDialog()
Unpause()
end




iii)
Now that we've moved that code into its own function, we will need to "call" it.


Code: [Select]
function LevelLogic()

GreetPlayer()

end


function GreetPlayer()
Pause()
MessageBox("Welcome to happyfuntimeland.  Is nice here.")
WaitDialog()
Unpause()
end


Ok so what happens is that when the level loads, LevelLogic() will run the command "GreetPlayer()".  This will then run the commands in the function with the corresponding name.  It's practically as if the compiler copies and pastes the code inside our new function in place of anywhere we put our "GreetPlayer()" command.




iv)
What about other occasions when we need a Message Box?
If we know that we'll always pause the game when these messages appear, then the only thing that changes each time is the content of the message.

We could have lots of different functions, with names like "GreetPlayer()", "PlayerLoseMessage()", "PlayerWinMessage()", and so on.  But that would mean writing out loads of functions and cluttering up our code again, when really we only need one function to do this.

How can we display different messages with just the one function, you ask?
Well, what we do is that we pass a variable into the function.

From now on when we use our "GreetPlayer()" command, the command will expect a variable or value of some kind in the brackets.
Like this:


Code: [Select]
function LevelLogic()

DisplayMessage("Welcome to happyfuntimeland.  Is nice here.")

end


function DisplayMessage(message)
Pause()
MessageBox(message)
WaitDialog()
Unpause()
end



v)
So lets walk through what happens there.

First, the level loads and LevelLogic() starts running.  Straight away, it runs the DisplayMessage command which activates the DisplayMessage function.  It also passes a value into the function, in this case the value is "Welcome to happyfuntimeland.  Is nice here."
The function receives this value, and stores it in a variable called "message".
Then, the game is paused, and a MessageBox is displayed, containing the contents of the variable called "message".
When the MessageBox is clicked, it will Unpause the game.



vi)
If you followed all that, you should be able to figure out what this code would do:


Code: [Select]
function LevelLogic()

DisplayMessage("Welcome to happyfuntimeland.  Is nice here.")
DisplayMessage("Chase rabbits down holes!!")
DisplayMessage("It's fun and the rabbits enjoy it.")

end


function DisplayMessage(message)
Pause()
MessageBox(message)
WaitDialog()
Unpause()
end

It would display 3 message boxes one after the other, all with different messages!

This is already just 9 lines of code.  Doing it the "normal" way would be 12 lines.  Hopefully you can see how, if you have a lot of message boxes, this would save you a lot of space!



viii)
You can also call functions from within functions.

For example, consider this code:

Code: [Select]
function LevelSetup()

energy = {}
strength = {}
speed = {}
radius = {}
senddist = {}
x = {}
y = {}

for i = 0,math.random(5,15) do
energy[i] = math.random(1,10) / 10
strength[i] = math.random(1,10) / 10
speed[i] = math.random(1,10) / 10
radius[i] = math.random (100,500)
senddist[i] = radius[i] * 10

x[i] = math.random(-5000,5000)
y[i] = math.radom(-5000,5000)

a = AddAsteroidWithAttribs(x[i],y[i],energy[i],strength[i],speed[i])
a.radius = radius[i]
a.SendDistance = senddist[i]
a.Moveable = true
end

end


We could split it up like this....

Code: [Select]
function LevelSetup()

InitArrays()

for i = 0,math.random(5,15) do
RandomiseAttributes(i)
PlaceTheRoids(i)
end

end

function InitArrays()
energy = {}
strength = {}
speed = {}
radius = {}
senddist = {}
x = {}
y = {}
end

function RandomiseAttributes(RoidID)

energy[RoidID] = math.random(1,10) / 10
strength[RoidID] = math.random(1,10) / 10
speed[RoidID] = math.random(1,10) / 10
radius[RoidID] = math.random (100,500)
senddist[RoidID] = radius[i] * 10

x[RoidID] = math.random(-5000,5000)
y[RoidID] = math.radom(-5000,5000)


end


function PlaceTheRoids(RoidID)

a = AddAsteroidWithAttribs(x[RoidID],y[RoidID],energy[RoidID],strength[RoidID],speed[RoidID])
a.radius = radius[RoidID]
a.SendDistance = senddist[RoidID]
a.Moveable = true

end


... and then like this.  
Code: [Select]
function LevelSetup()

GenerateLevel()

end





function GenerateLevel()
InitArrays()
for i = 0,math.random(5,15) do
RandomiseAttributes(i)
PlaceTheRoids(i)
end
end

function InitArrays()
energy = {}
strength = {}
speed = {}
radius = {}
senddist = {}
x = {}
y = {}
end

function RandomiseAttributes(RoidID)

energy[RoidID] = math.random(1,10) / 10
strength[RoidID] = math.random(1,10) / 10
speed[RoidID] = math.random(1,10) / 10
radius[RoidID] = math.random (100,500)
senddist[RoidID] = radius[i] * 10

x[RoidID] = math.random(-5000,5000)
y[RoidID] = math.radom(-5000,5000)


end


function PlaceTheRoids(RoidID)

a = AddAsteroidWithAttribs(x[RoidID],y[RoidID],energy[RoidID],strength[RoidID],speed[RoidID])
a.radius = radius[RoidID]
a.SendDistance = senddist[RoidID]
a.Moveable = true

end

Note how some functions are called from within another function.  You can "nest" functions as deep as you like in this way.



viii)
Have you realised what's going on yet?

You really are somewhere down the rabbit hole, Alice...  because function LevelSetup() and function LevelLogic() are themselves just functions which are being called by the Eufloria engine.



You've been inside The Matrix all along!
« Last Edit: May 28, 2012, 09:06:41 PM by Eufloria Admin »

Bonobo

  • Achiever
  • Old Oak
  • ****
  • Thank You
  • -Given: 139
  • -Receive: 12
  • Posts: 670
  • Eufloria: Yes
Re: Intermediate coding examples
« Reply #1 on: January 22, 2011, 04:00:11 AM »
Annikk-Sensei, forgive my interfering, but …

… do you think a dedicated board, e.g., “Turorials—Learning And Teaching Level Coding” could be appropriate and doable for this kind of threads, so that they won’t be overlooked among all those custom levels submission threads etc.? Or perhaps make ALL such (tutorial) threads sticky? But then this board might soon have too many sticky threads, I think.

A good way to do this could be, IMHO, to change this board to contain two sub-boards:
  • Board: User levels and modifications
    • Sub-Board 1: Submit your user levels and mods here
    • Sub-Board 2: How to do it (or the above example name)
… and then to move all threads to the appropriate sub-boards. Quite some work for the admin <cough> I can imagine. And then, I think, it would still be good to make this and the other real tutorial threads sticky, so as to make them prominent (like “read this before you ask” or so) before the other Q&A threads.

BTW I don’t really care about the ordering of the two sub-boards, I mean: I don’t think one order would be preferrable over the other.

Just an idea that I watched flying from one asteroid to another …

Pilchard123

  • Tester
  • Old Oak
  • ****
  • Thank You
  • -Given: 4
  • -Receive: 24
  • Posts: 932
  • Eufloria: Yes
Re: Intermediate coding examples
« Reply #2 on: January 22, 2011, 04:40:37 AM »
If I might suggest that you add this? It's an adaptation of one of your codes. I believe it should be faster (without checks for roid sizes, etc.) because it stops the instant it finds an imaginary roid and only saves a variable once, rather than every time a roid is found. I haven't done any speed checks, though.

Ignore me if you don't want it, of course.

Code: [Select]
function LevelSetup()
  -- roids and stuff created here

  for i = 0, math.huge do
    if GetAsteroid(i) == nil then
      highroidID = i - 1
      break
    end
  end

  for i = 0, highroidID do
    if GetAsteroid(i).radius > 10 then
      playableroidnum = playableroidnum + 1
  end
end

function LevelLogic()
  --loremipsumdolorsitametfgjdflhldfgnkljndfgdg
end

You'll probably be able to tell, but this check a potentially infinite amount of asteroid IDs and when it finds that an asteroid does not exist, saves the highest roid ID to be one less than the first non-existent one and breaks out of the for loop.
It then checks all of the real roids and finds any playable ones, increasing the number by one each time it finds one. This is not using IDs, since if it were to be used in a win/lose condition, having one less than the real amount (because of ID 0) would mess it up.

Btw, math.huge is equal to +infinity. This should work, though there may be problems with the whole "infinite for loop" thing there.
« Last Edit: January 22, 2011, 05:00:03 AM by Pilchard123 »

annikk.exe

  • Achiever
  • Ent
  • ****
  • Thank You
  • -Given: 0
  • -Receive: 4
  • Posts: 1,809
Re: Intermediate coding examples
« Reply #3 on: January 22, 2011, 06:58:56 AM »
heh, that's a nifty way of doing it.  :>  I'll probably just stick to the basic structural commands like if and for for this guide though, and do another thread with useful bits and pieces of code.

annikk.exe

  • Achiever
  • Ent
  • ****
  • Thank You
  • -Given: 0
  • -Receive: 4
  • Posts: 1,809
Re: Intermediate coding examples
« Reply #4 on: January 22, 2011, 07:23:34 AM »
Quote
… do you think a dedicated board, e.g., “Turorials—Learning And Teaching Level Coding” could be appropriate and doable for this kind of threads, so that they won’t be overlooked among all those custom levels submission threads etc.? Or perhaps make ALL such (tutorial) threads sticky? But then this board might soon have too many sticky threads, I think.

Its crossed my mind.  I guess we'll see how many guide threads there ends up being..  I think the status quo is ok for the moment though.  :>

annikk.exe

  • Achiever
  • Ent
  • ****
  • Thank You
  • -Given: 0
  • -Receive: 4
  • Posts: 1,809
Re: Intermediate coding examples
« Reply #5 on: January 22, 2011, 07:29:24 AM »
This guide is boring and needs more pictures or something.

edit - that's a bit better..
« Last Edit: January 22, 2011, 09:27:45 AM by annikk.exe »

Avaguard

  • Seedling
  • **
  • Thank You
  • -Given: 0
  • -Receive: 0
  • Posts: 40
Re: Intermediate coding guide
« Reply #6 on: January 26, 2011, 03:28:47 AM »
ANnik trust ME........... ITS not the PICtures ??? :o ??? :o ??? :o its prety crazy if just scrool down it lol make u feel (!WAIT wh  huh WHAT WTF SO much NUMBERS LOL) hmmm i realy outa read and try some though  ;)

Bonobo

  • Achiever
  • Old Oak
  • ****
  • Thank You
  • -Given: 139
  • -Receive: 12
  • Posts: 670
  • Eufloria: Yes
Re: Intermediate coding guide
« Reply #7 on: January 26, 2011, 06:35:02 AM »
Oh, I for one LOVE the images, especially since they began to turn from “huh” to pictures of what seemed to make some sense in the context … and it made it easier for me—code phobic— to at leadst take a glimpse here and there, and then a larger paragraph, firstleaving out the real code and only reading—and suddenly here and there understanding!—the meta-code which again led to that I began to allow an eye here and the other eye there to peak, shyly … and I can imagine that I could get myself to read it in order and then some later to understand everything …which I usually waved off, thinking that’s waaay over my head.

If the other, beginner’s guide is written in a manner like this one I might dare to dive into it sometime when I find some more time. Currently staying alive spiritually takes a lot of my time.

But what I wanted to say, was, all in all, I was right with attributing you, Annikk, with Sensei. You are a good teacher. I can hardly imagine how much better you might be before an IRL auditorium of people who want to learn from you. You are a wonderful teacher. You inspire life into these dead things (as they seem to a codning n00b like me). Thank you. I might even create a map, someday, in three or four years :D at that pace I'm moving in currently.

annikk.exe

  • Achiever
  • Ent
  • ****
  • Thank You
  • -Given: 0
  • -Receive: 4
  • Posts: 1,809
Re: Intermediate coding guide
« Reply #8 on: January 26, 2011, 10:48:07 AM »
Thanks guys.  :>

I would be rubbish in a real-life situation though.  My strength in explaining things is basically in forum BB-code :P

My favourite section so far is sin/cos.  Still need to write up math.random, that should be a fairly short section though..



By the way, here's some subjects I was thinking of putting into an Advanced Guide, which I will eventually write...


  • LevelDraw, ScreenDraw, OnMouseLeftDown, OnMouseRightDown
  • Comprehensive guide for how to build your own formulas to create variables with the desired ranges/properties.
  • Matrices / multidimensional data structures
  • Square and non-square nested for loops
  • math.tan and math.atan2
  • Optimizing code for performance
  • Walkthroughs of various pieces of code to perform certain common tasks, EG checking the number of playable, non-spacer asteroids in the level


Some of the stuff that I want to put in there I will need to research to make sure I get all the details right, so it will take a lot longer to write that one.  Let me know what you guys think, does it sound cool and is there anything else you would like to see in it?

annikk.exe

  • Achiever
  • Ent
  • ****
  • Thank You
  • -Given: 0
  • -Receive: 4
  • Posts: 1,809
Re: Intermediate coding guide
« Reply #9 on: January 31, 2011, 11:57:54 PM »
That's the section on math.random written, finally.
It probably has tons of errors at the moment.  If you spot one, even just a spelling mistake or punctuation problem, let me know!  I want this guide to be as high quality, understandable and friendly as possible.  :>

I also decided I ought to do a section in the intermediate guide on custom functions.  I was going to leave that for the advanced guide but it's really not that difficult to understand custom functions and they are really really handy, especially if you like to keep your code really neat.  :>  (And ESPECIALLY if you use Notepad++ with its collapsible code sections!)



Anyone have an idea for the asteroid attributes problem? :>  I struggled with it for months and when I finally figured out the solution, kicked myself because it was so simple.  :>  (relative to some of the other craziness I tried, hehe)

Pilchard123

  • Tester
  • Old Oak
  • ****
  • Thank You
  • -Given: 4
  • -Receive: 24
  • Posts: 932
  • Eufloria: Yes
Re: Intermediate coding guide
« Reply #10 on: February 01, 2011, 02:58:57 AM »
Ehh...   math.random()   always will return 0<X<1    You don't need all that, I think.

The 'roids that will have different values every time you play. In fact they will always have the same, unless you seed the random number table.  math.randomseed(os.time()) will give you a nice seed for your random numbers. Lua only uses pseudo-random numbers, unless you happen to have G-M tube connected to it and have coded it in.




EDIT: Sine and cosine are in radians here, but this will help flip between them. You might want to say what a radian actually is, too.
Quote from: lua-users wiki

math.cos , math.sin , math.tan

Return the cosine, sine and tangent value for a given value in radians.

    > = math.cos(math.pi / 4)
    0.70710678118655
    > = math.sin(0.123)
    0.12269009002432
    > = math.tan(5/4)
    3.0095696738628
    > = math.tan(.77)
    0.96966832796149



math.deg , math.rad
Convert from radians to degrees and vice versa.

    > = math.deg(math.pi)
    180
    > = math.deg(math.pi / 2)
    90
    > = math.rad(180)
    3.1415926535898
    > = math.rad(1)
    0.017453292519943

« Last Edit: February 01, 2011, 03:18:19 AM by Pilchard123 »

annikk.exe

  • Achiever
  • Ent
  • ****
  • Thank You
  • -Given: 0
  • -Receive: 4
  • Posts: 1,809
Re: Intermediate coding guide
« Reply #11 on: February 01, 2011, 03:25:58 AM »
You're right Pilchard, I didn't realise math.random() could be used standalone like that.  How handy.  :>

Oh well, at least the guide's method gives some practice working with variables..  all the same, I will almost certainly amend it at some point so I will be sure to change that part.


Also this answered another question that's been troubling me for a while, but I have't bothered to go and research.  That is, how many degrees in a radian...  :>  Looks like it's 180.

Sniped50

  • Sapling
  • **
  • Thank You
  • -Given: 0
  • -Receive: 0
  • Posts: 97
Re: Intermediate coding guide
« Reply #12 on: February 02, 2011, 12:46:06 AM »
Actually, annikk, I had a squizz on Wikipedia, and apparently a radian is 180/pi. If you can't be arsed to type the page in yourself, then here's the URL:

http://en.wikipedia.org/wiki/Radian

annikk.exe

  • Achiever
  • Ent
  • ****
  • Thank You
  • -Given: 0
  • -Receive: 4
  • Posts: 1,809
Re: Intermediate coding guide
« Reply #13 on: February 02, 2011, 12:54:46 AM »
Hmm, you're right, there's something funny going on there.
Google says 1 radian = 57.2957795 degrees
I'll research this better at some stage, if I get a reason to know more about radians.  :>

Pilchard123

  • Tester
  • Old Oak
  • ****
  • Thank You
  • -Given: 4
  • -Receive: 24
  • Posts: 932
  • Eufloria: Yes
Re: Intermediate coding guide
« Reply #14 on: February 02, 2011, 02:16:21 AM »
1 radian is the distance aroud the circumference of a circle that is equal to its radius. More accurately, it is the angle that a sector of a circle with an arc of length R has at its origin, where R is the radius length.


There are 2pi radians in 360 degrees, and it simplifies loads of circle formulae.

annikk.exe

  • Achiever
  • Ent
  • ****
  • Thank You
  • -Given: 0
  • -Receive: 4
  • Posts: 1,809
Re: Intermediate coding guide
« Reply #15 on: February 02, 2011, 03:32:00 AM »
Ok, cool, thanks :>

annikk.exe

  • Achiever
  • Ent
  • ****
  • Thank You
  • -Given: 0
  • -Receive: 4
  • Posts: 1,809
Re: Intermediate coding guide
« Reply #16 on: February 03, 2011, 08:33:54 PM »
This is basically finished now, I think.
Possible to get it stickied at some point?  :>

Alex/Rudolf, do you guys think we should move all the guides, the mechanics thread, the reference, etc, into either one big thread, or create a seperate subforum for them, or something?  There are quite a few stickies in this forum now and I'm sure more will accumulate in the coming months.

Bonobo

  • Achiever
  • Old Oak
  • ****
  • Thank You
  • -Given: 139
  • -Receive: 12
  • Posts: 670
  • Eufloria: Yes
Re: Intermediate coding guide
« Reply #17 on: February 03, 2011, 10:38:14 PM »
Good idea, to move all this to a subforum for coding guides :D

BTW then it would IMHO also be fine to number these three: 1. Beginner’s …, 2. Intermediate …, 3. Advanced …, so these would stand at the top of these stickied threads in this order.

But Annik, it prolly could be wise to PM A/R since it seems that b/c of the PSN work they currently don’t have time to look here.

annikk.exe

  • Achiever
  • Ent
  • ****
  • Thank You
  • -Given: 0
  • -Receive: 4
  • Posts: 1,809
Re: Intermediate coding guide
« Reply #18 on: February 03, 2011, 11:02:37 PM »
Well stickies are ordered by whichever was posted in most recently, so in order to do it like that, the Advanced guide would need to be posted (or replied to) first, then the intermediate, then the beginners.

In order to maintain the order, the threads would then need to be locked.

I would be worried that it might stifle discussion really.  Maybe it would be better to have a single thread entitled something like "Eufloria Level Creation Guide".  I could reserve the first 20 or 30 posts, then I would be able to make hyperlinks to each individual section in the first post in the thread.  That would allow a "contents" section to be created.


Also, I don't know if it's really that much of a priority.  It would have to be something pretty serious for me to go bothering A&R right now.  I'm sure it can wait a few weeks.. :>

Eufloria Admin

  • Global Moderator
  • Seedling
  • *****
  • Thank You
  • -Given: 0
  • -Receive: 0
  • Posts: 38
Re: Intermediate coding guide
« Reply #19 on: February 13, 2011, 10:10:29 AM »
Hopefully A&R won't mind if I sticky this...

AWS

  • Achiever
  • Arboreal Being
  • ****
  • Thank You
  • -Given: 0
  • -Receive: 2
  • Posts: 275
Re: Intermediate coding guide
« Reply #20 on: February 13, 2011, 11:22:10 PM »
...I would be worried that it might stifle discussion really.  Maybe it would be better to have a single thread entitled something like "Eufloria Level Creation Guide".  I could reserve the first 20 or 30 posts, then I would be able to make hyperlinks to each individual section in the first post in the thread.  That would allow a "contents" section to be created.
...

an excellently well organised idea...
i liike...


Rudolf

  • Administrator
  • Old Oak
  • *****
  • Thank You
  • -Given: 5
  • -Receive: 13
  • Posts: 669
  • Eufloria: Yes
Re: Intermediate coding guide
« Reply #21 on: February 15, 2011, 06:21:16 AM »
Hah, this is rather useful for me as well believe it or not. :-D

annikk.exe

  • Achiever
  • Ent
  • ****
  • Thank You
  • -Given: 0
  • -Receive: 4
  • Posts: 1,809
Re: Intermediate coding guide
« Reply #22 on: February 15, 2011, 10:47:11 AM »
Really?  Heh, awesome.  :>  ::shares teh knowledge!::

w4tc

  • Achiever
  • Shrub
  • ****
  • Thank You
  • -Given: 0
  • -Receive: 0
  • Posts: 170
Re: Intermediate coding guide
« Reply #23 on: February 20, 2011, 05:04:10 AM »
OMG YOU DO IT!
about that array.lau for that colour
do you remember it? that I've ever asked about the color change
o dammm al your ohtere lvls omg <3 i love it !

annikk.exe

  • Achiever
  • Ent
  • ****
  • Thank You
  • -Given: 0
  • -Receive: 4
  • Posts: 1,809
Re: Intermediate coding guide
« Reply #24 on: February 20, 2011, 10:19:30 AM »
Hmm? :>  Do you mean Array Example.lua ?
Not quite sure what you're asking... slow down a bit ! =)

w4tc

  • Achiever
  • Shrub
  • ****
  • Thank You
  • -Given: 0
  • -Receive: 0
  • Posts: 170
Re: Intermediate coding guide
« Reply #25 on: February 20, 2011, 08:17:09 PM »

annikk.exe

  • Achiever
  • Ent
  • ****
  • Thank You
  • -Given: 0
  • -Receive: 4
  • Posts: 1,809
Re: Intermediate coding guide
« Reply #26 on: February 20, 2011, 08:24:11 PM »
Ahh yes... I remember looking at that and trying to decypher what you wanted.. :>  Sorry I never got back to you about that!
It's still not hugely clear to me unfortunately...  Is it either of these?

1) The colour used for the background corresponds to whichever asteroid has the most seedlings on it.

2) The colour used for the background corresponds to whichever asteroid received some seedlings most recently.



Once I understand what you want to happen, I can help you make that functionality.  :>

Aino

  • Ent
  • ******
  • Thank You
  • -Given: 4
  • -Receive: 30
  • Posts: 1,527
  • Eufloria: Yes
Re: Intermediate coding guide
« Reply #27 on: February 20, 2011, 08:30:20 PM »
Uhhm, annikk, use math.random() when you are going to set the stats :) Cause math.random() with nothing in the parantheses generates a decimal number between 0 and 1 :)

EDIT: You probbably know this already :)

w4tc

  • Achiever
  • Shrub
  • ****
  • Thank You
  • -Given: 0
  • -Receive: 0
  • Posts: 170
Re: Intermediate coding guide
« Reply #28 on: February 20, 2011, 08:53:10 PM »
right now that I'm thinking
for doing otherwise
the color can only change when you click on an asteroid
...but code-ing is now long time xD for me xD
so can you little help me out
(click to show/hide)

Aino

  • Ent
  • ******
  • Thank You
  • -Given: 4
  • -Receive: 30
  • Posts: 1,527
  • Eufloria: Yes
Re: Intermediate coding guide
« Reply #29 on: February 20, 2011, 09:01:37 PM »
Well, if you want it to be when it is selected do:
Code: [Select]
function OnAsteroidSelected(id)
if id > 7 and id < 15 then
SetBackdropColour(r,g,b)
elseif if > 15 and id < 33 then
SetBackdropColour(r,g,b)
end
end

Where 7 and 15 is just a limit for colours, the r,g,b in the SetBackdropColour is supposed to be the colours you want, jsut change all the values at your desire :) And here's also the code if you want the owner to be the player, dunno if you want it to but whatever :)

Code: [Select]
function OnAsteroidSelected(id)
if GetAsteroid(id).owner == 1 then
if id > 7 and id < 15 then
SetBackdropColour(r,g,b)
elseif if > 15 and id < 33 then
SetBackdropColour(r,g,b)
end
end
end

For all the colours just add new elseifs and change the ID numbers :) Hope I helped you out...

annikk.exe

  • Achiever
  • Ent
  • ****
  • Thank You
  • -Given: 0
  • -Receive: 4
  • Posts: 1,809
Re: Intermediate coding guide
« Reply #30 on: February 20, 2011, 09:24:42 PM »
Heh, beat me to it.  :>  I was busy beta testing! :P

Aino

  • Ent
  • ******
  • Thank You
  • -Given: 4
  • -Receive: 30
  • Posts: 1,527
  • Eufloria: Yes
Re: Intermediate coding guide
« Reply #31 on: February 20, 2011, 09:40:28 PM »
Hah :) But I have a problem, just gotta know if I need to call the ScreenDraw() function or does it run repeatily all the time?

annikk.exe

  • Achiever
  • Ent
  • ****
  • Thank You
  • -Given: 0
  • -Receive: 4
  • Posts: 1,809
Re: Intermediate coding guide
« Reply #32 on: February 20, 2011, 09:44:20 PM »
ScreenDraw automatically repeats itself :>

Aino

  • Ent
  • ******
  • Thank You
  • -Given: 4
  • -Receive: 30
  • Posts: 1,527
  • Eufloria: Yes
Re: Intermediate coding guide
« Reply #33 on: February 20, 2011, 09:44:57 PM »
Strange, cause it won't change the colours, checking my code again :)

Aino

  • Ent
  • ******
  • Thank You
  • -Given: 4
  • -Receive: 30
  • Posts: 1,527
  • Eufloria: Yes
Re: Intermediate coding guide
« Reply #34 on: February 21, 2011, 05:12:31 AM »
Yay fixed it, wonder if I am going to release CC tonight :)

Aino

  • Ent
  • ******
  • Thank You
  • -Given: 4
  • -Receive: 30
  • Posts: 1,527
  • Eufloria: Yes
Re: Intermediate coding guide
« Reply #35 on: July 25, 2011, 04:50:36 PM »
That must be spam! Though, I'm not 100% sure either x.x

Aino

  • Ent
  • ******
  • Thank You
  • -Given: 4
  • -Receive: 30
  • Posts: 1,527
  • Eufloria: Yes
Re: Intermediate coding guide
« Reply #36 on: August 03, 2011, 11:48:41 AM »
What do you mean?

Pilchard123

  • Tester
  • Old Oak
  • ****
  • Thank You
  • -Given: 4
  • -Receive: 24
  • Posts: 932
  • Eufloria: Yes
Re: Intermediate coding guide
« Reply #37 on: August 04, 2011, 02:45:02 AM »
Spam, that's what. Check its email address.

Aino

  • Ent
  • ******
  • Thank You
  • -Given: 4
  • -Receive: 30
  • Posts: 1,527
  • Eufloria: Yes
Re: Intermediate coding guide
« Reply #38 on: August 04, 2011, 03:19:54 AM »
I'm so confused D:

There is no link to advertise for something totally strange o.O

Pilchard123

  • Tester
  • Old Oak
  • ****
  • Thank You
  • -Given: 4
  • -Receive: 24
  • Posts: 932
  • Eufloria: Yes
Re: Intermediate coding guide
« Reply #39 on: August 04, 2011, 03:30:07 AM »
Hm, maybe I was wrong. It does seem a little odd though.

FYI, 'huerta' means 'orchard' in Spanish.

YUI88IUY

  • Guest
Re: Intermediate coding guide
« Reply #40 on: January 28, 2012, 02:07:06 PM »
Ah ~ good hard to understand :o