Click Here for Original Discussion Thread (http://www.dyson-game.com/smf/index.php?topic=701.0)
Overwhelmed by the thought of trying to code your own levels?
Don't worry, Fluffy is here to halp.
Follow this guide and you'll be making levels in no time!
(If you actually try everything suggested here for yourself, it will take you about 40-60 mins to learn how to make levels.)
To start with we will create a very simple level, and then learn by adjusting values and playing the level each time to see what has changed.
1.
Click Start
(http://img6.imageshack.us/img6/142/36526858.jpg)
2.
Click on "Run".
(http://img710.imageshack.us/img710/8116/36419182.jpg)
3.
Type "notepad.exe" into the box as shown, and click OK.
(http://img204.imageshack.us/img204/922/65731594.jpg)
4.
Notepad opens.
(http://img6.imageshack.us/img6/8894/14841297.jpg)
5.
Enter the text shown below into Notepad.
If you would prefer to copy & paste the text (recommended) instead of typing it out yourself, click the "Spoiler" button below:
function LevelSetup()
-- Set Global Values
Globals.G.Asteroids=(0)
Globals.G.EnemyFactionsMin=(1)
Globals.G.EnemyFactionsMax=(1)
-- Asteroid 0 - starting asteroid
a = AddAsteroidWithAttribs(0,0, 0.7,0.6,0.5)
a.Owner = 1
a.TreeCap = 1
a:SetRadius(250)
a.SendDistance = 2500
a:AddSeedlings(90)
-- Asteroid 1
a = AddAsteroidWithAttribs(2000,0, 0.3,0.3,0.3)
a.Owner = 2
a.TreeCap = 2
a:SetRadius(450)
a.SendDistance = 2500
a:AddSeedlings(100)
end
function LevelLogic()
end
(http://www.hpruk.com/annikk/5.JPG)
6.
Now click "File" in the top left of Notepad, and choose "Save As".
(http://img10.imageshack.us/img10/6420/57757928.jpg)
7.
We need to make sure we save it in the right folder.
The picture below shows the correct location of the "Maps" folder.
Use the drop-down box at the top of the "Save As" window to navigate to the right folder.
(http://img22.imageshack.us/img22/5870/20113803.jpg)
8.
Give your level a name, and make sure that it ends with ".lua"
Set the file type to All Files.
Set Encoding to ANSI.
(http://img685.imageshack.us/img685/4331/65826991.jpg)
Then click the Save button. Now it's time to check out our level.
9.
Load up Eufloria, choose "Custom Levels" from the main menu, and your new level should be waiting there.
Click on it to try playing it!
(http://img205.imageshack.us/img205/849/52530803.jpg)
10.
When it loads up, this is what it should look like.
(http://img24.imageshack.us/img24/8132/84046997.jpg)
11.
If you send a scout to the asteroid next door, you should see that there are enemy seedlings orbiting it.
(http://img37.imageshack.us/img37/5839/93108433.jpg)
If you got this far, congratulations - you are through the biggest barrier, which is getting started. It will be plain sailing from here!
Now that we've made a simple level, lets experiment with it by changing some values.
12.
To start with, lets change the number of seedlings that the Player starts with from 90 up to 500. Make the change indicated below:
(http://img706.imageshack.us/img706/3084/40805528.jpg)
13.
Now that we've made the change, it is important that we remember to save the file. Otherwise our changes won't be apparent when we try to play the level.
(http://img51.imageshack.us/img51/6796/54366703.jpg)
14.
Now go back to Eufloria and try loading up the level like before. You should start with loads of seedlings this time!
(http://img168.imageshack.us/img168/3464/77124470.jpg)
15.
Next lets try to change the size of the Player's asteroid. Make the change indicated below, and don't forget to save the level afterwards by clicking "File" and "Save", like in step 13.
(http://img36.imageshack.us/img36/5592/51821390.jpg)
16.
Now load the game up, and lo and behold your asteroid has swollen to epic proportions!
(http://img46.imageshack.us/img46/3052/92900231.jpg)
17.
Next lets try changing the maximum number of trees allowed on the Player's asteroid. Make the change indicated below - make sure you change the right asteroid! Then save the level again.
(http://img10.imageshack.us/img10/4010/98261872.jpg)
18.
Load it up in Eufloria and now we can plant up to 20 trees :>
(http://img7.imageshack.us/img7/627/54948032.jpg)
Now try changing some of the other values yourself. I would suggest to only change one thing at a time - that way if you accidentally break the level, it's easy to know what to undo to fix the problem.
19.
Hopefully by now you should be getting an idea of how this works.
You can kind of tell what each line means... it doesn't take a genius to work out that "SendDistance" is how far the asteroid can send seedlings.
However, one command is not so obvious, and that is the AddAsteroidWithAttribs command, which as you might guess is used to create asteroids and set their basic attributes. Lets take a moment to look at that line, because it's a good example to teach us about the other commands as well.
(http://img709.imageshack.us/img709/3493/81814545.jpg)
Lets deal with the bits in brackets first.
There are 5 values seperated by commas.
The first two values are the X and Y coordinates of the asteroid - it tells the game where on the map the asteroid is located. These have to be integers (whole numbers).
This map hopefully gives you an idea of what sort of values you can use.
(http://www.hpruk.com/annikk/2.PNG)
20.
The next three values are the Energy, Strength, and Speed of the asteroid.
(http://img294.imageshack.us/img294/7162/52879545.jpg)
You can use any number between 0 and 1. So you could have 0.5, or you could have 0.55555 or whatever you like really.
21.
Now that we've dealt with the brackets, lets look at the bit at the start:
(http://img193.imageshack.us/img193/2910/54927322.jpg)
The command starts with an "a = ". The "a" is sort of like the name of the asteroid that we are creating.
Then we can use the various functions and property commands to tell the game what the asteroid is like.
This is what a.TreeCap is doing - we refer to the asteroid called "a", and then we tell the game that "a" has a Tree Cap of...whatever we set it to.
(http://img35.imageshack.us/img35/5545/85404933.jpg)
22.
You might notice that we use "a" a second time to make the second asteroid:
(http://img20.imageshack.us/img20/5867/25950604.jpg)
It doesn't matter if we use it twice in a row like that. When we use it to make the second asteroid, we are just telling the game to "forget" which asteroid "a" is, because now this asteroid is called "a". We just overwrite the old value by declaring a new one.
Then we can set the properties for the second asteroid using the same commands like before, such as "a.TreeCap" and "a:AddSeedlings()" and so on.
Note: You can give each asteroid a unique name if you wish, rather than just re-using "a" all the time. This can actually be useful if you want to refer to them in your scripts later on.
fluffy = AddAsteroidWithAttribs is perfectly acceptable. :> fluffy.TreeCap and other commands will work without problems.
"a." (with a dot) is used to set properties, and "a:" (with a colon) is used for functions. You must be careful not to mix them up, or the level won't load.
A complete list of the different commands you can use for asteroid properties can be found in the LUA Scripting Reference Sticky (http://www.dyson-game.com/smf/index.php?topic=212.msg1913#msg1913).
23.
Finally, the complete command looks like this:
NAME = AddAsteroidWithAttribs(Horizontal Position,Vertical Position,Energy,Strength,Speed)
24.
Now to try adding a new asteroid to your level.
You need to make sure you put it within the bounds of the function LevelSetup(). That is, it must appear after the LevelSetup() command, and before the end command, as shown.
(http://img694.imageshack.us/img694/4462/86511777.jpg)
Lets make an asteroid by typing in the code for it where the red arrow indicates.
First we should make a comment to remind ourselves later on that this is Asteroid 2 (remember we had asteroid 0, 1, and this will be asteroid 2).
So type in "-- Asteroid 2" like this:
(http://img704.imageshack.us/img704/387/33940935.jpg)
25.
Now lets type the command to add an asteroid, and pick some values for the new asteroid.
I'll use coordinates 2000, -2000 and energy 0.8, strength 0.6, speed 0.9.
(http://img515.imageshack.us/img515/134/91863825.jpg)
26.
To save some time, I'll copy and paste the commands I used on the previous asteroids.
(http://img200.imageshack.us/img200/5684/72141017.jpg)
27.
Now I'll change the values around a bit to make the asteroid the way I want it:
(http://img519.imageshack.us/img519/674/62015524.jpg)
28.
Now lets save the level, load it up, and check out the new roid! :D
(http://img32.imageshack.us/img32/1311/41598610.jpg)
29.
There are some other nifty commands you can use in LevelSetup.
A really handy one is SetBackdropColour() which lets you change the background colour using 3 comma-seperated RGB values between 0 and 255.
Lets make the background red!
(http://img515.imageshack.us/img515/8599/83975020.jpg)
30.
And the fruits of our work so far....
(http://img15.imageshack.us/img15/1207/57175934.jpg)
31.
Maybe you noticed by now that the asteroid positions don't seem to be quite right. Because of their large size the game is squashing them apart.
To prevent this behaviour, add this line to each of your asteroids:
(http://img294.imageshack.us/img294/460/17872634.jpg)
32.
Save the level and try playing it. Now the asteroids are positioned exactly where we specified them in our coordinates. :>
(http://img708.imageshack.us/img708/8726/53889164.jpg)
33.
We have been studying the section called function LevelSetup(), which deals with the creation of the level and all the initial conditions.
Now it's time to have a look at the function LevelLogic() section. This section lets you make things happen during play, such as scripted events.
(http://img710.imageshack.us/img710/284/36266925.jpg)
34.
To begin with, lets make a Message Box appear after 5 seconds of game time has passed.
The messagebox could contain a greeting, and instructions for the player.
Add this code:
-- Greet the player
Timer = GetGameTime() + 5
while GetGameTime() < Timer do
coroutine.yield()
end
Pause()
MessageBox("Take the asteroid to the east to win. Don't lose yours.")
WaitDialog()
Unpause()
(http://www.hpruk.com/annikk/2.JPG)
Load up the level to test it out:
(http://www.hpruk.com/annikk/3.JPG)
35.
So what happened there? Lets think about this for a minute before we move on.
a.
Well, first we created a variable called Timer (case sensitive!).
(http://img168.imageshack.us/img168/7460/88808303.jpg)
We set it to Game Time + 5, and since it is the first thing the game evaluates once it's running, Timer must have a value of 0:05 seconds.
b.
Then we used something called a While loop to create a delay.
(http://img709.imageshack.us/img709/6391/59126537.jpg)
We told the game, while the game time is less than Timer, just keep repeating these commands.
c.
The part which tells it the loop has ended is the coroutine.yield() command.
(http://img3.imageshack.us/img3/1229/34929163.jpg)
This command tells the game the loop has ended and the game should go back up and check if the conditions of the While statement are still being met.
We don't have any commands in between our While statement and our coroutine.yield(). So basically the game just does nothing for 5 seconds. :>
d.
Once the 5 seconds are up, the While loop exits at the end statement.
(http://img4.imageshack.us/img4/9681/59964157.jpg)
e.
Then next thing that happens is that the game pauses, a Message Box appears, and when the player clicks OK, the game unpauses again.
(http://img341.imageshack.us/img341/7088/72836962.jpg)
Look at the commands and read over this part a few times if you need to. It is helpful if you can conceptualise what is going on here.
36.
The level is a bit easy at the moment. Lets add a scripted event where a bunch of enemy seedlings spawn on Asteroid 1.
I'll make mine 20 seconds after the Message Box appears, and I guess I'll add about... 400 seedlings.
You might notice I've started adding comments as well, to remind myself what each part does later on.
(http://img189.imageshack.us/img189/7690/27886850.jpg)
Did you notice we used the :AddSeedlings command in LevelSetup() too? Most of the commands used there are also usable here. In this case, we weren't able to refer to it by a name like "a" because "a" had been replaced with a different asteroid, so instead we just tell the game which asteroid we mean with GetAsteroid(ID). Hence, GetAsteroid(1):AddSeedlings(400) is the command to add 400 seedlings to asteroid 1.
37.
Lets save the level and see if the the enemies spawn correctly. :>
(http://img40.imageshack.us/img40/9678/36076019.png)
38.
If you would like to make it even more interesting, you can add the following line after:
GetAsteroid(1):SendSeedlingsToTarget(2,400,GetAsteroid(0))
This sends seedlings from Asteroid 1, belonging to player 2... it sends 400 of them, to Asteroid 0.
(http://img693.imageshack.us/img693/7725/24226274.jpg)
39.
At the moment, if the player takes over all the asteroids, the game just continues running. There is no way to "win".
We will create a winning condition and a losing condition, so that the game can actually be won or lost by the player.
Add this code:
gamewon = 0
while gamewon == 0 do
coroutine.yield()
end
if gamewon == 1 then
Pause()
MessageBox("You have won.")
WaitDialog()
Unpause()
Quit(true)
end
if gamewon == 2 then
Pause()
MessageBox("You have lost.")
WaitDialog()
Unpause()
Quit(false)
end
(http://www.hpruk.com/annikk/C.JPG)
There are three new things here.
Quit(true) means the game ends and the player won.
Quit(false) means the game ends and the player lost.
If and then statements. These check if something is true, and if so, does something.
So if the variable gamewon is equal to 1, then the player is told they have won and the game ends in victory.
But if the variable gamewon is equal to 2, it skips the first If statement and proceeds to the second If statement... resulting in the player being told they have lost, and the game ending in defeat.
You might also notice that in some places we use a single "=", and in other places we use the double: "==".
A single equals sign "=" is used to set values, whereas the double "==" is used to compare values.
40.
Now that we have created the winning and losing code, we need to have some way to trigger the victory or defeat.
For this example, we will say that if Player 1 gets asteroid 1, the player wins (gamewon = 1). And if Player 2 gets Asteroid 0, the player loses (gamewon = 2).
The easiest way to check this is to use an entirely new function - seperate entirely from function LevelLogic - this new one is called function OnAsteroidTaken, and we place it below everything else.
Add this code:
function OnAsteroidTaken(id, owner)
if id == 1 and owner == 1 then
gamewon = 1
return
end
if id == 0 and owner == 2 then
gamewon = 2
return
end
end
(http://img683.imageshack.us/img683/6806/72432968.jpg)
41.
function OnAsteroidTaken is triggered every time an asteroid changes owner.
We can put If statements in there to check the asteroid and the owner, and if appropriate, change the gamewon variable to either 1 or 2.
Once we change the gamewon variable to something other than 0, the While loop that we made in our function LevelLogic() for the victory/defeat code ends. Straight after that loop ends, the gamewon variable is evaluated to see whether the player lost or won. Go and look again at the code in step 39 and make sure you understand how this works.
Now you should understand the mechanism of our victory/defeat detection system.
Lets give it a try:
(http://img686.imageshack.us/img686/4022/57887165.jpg)
(http://img199.imageshack.us/img199/13/99095502.jpg)
42.
Now you know enough to begin making your own levels.
I hope you will read the LUA Scripting Reference (http://www.dyson-game.com/smf/index.php?topic=212.0) as well and see all the crazy things it's possible to change in this game, and let your imagination run wild :>
Happy coding,
-Fluffy
Click Here for Original Discussion Thread (http://www.dyson-game.com/smf/index.php?topic=701.0)
Click Here for Original Discussion Thread (http://www.dyson-game.com/smf/index.php?topic=1219.0)
(http://img41.imageshack.us/img41/6389/lukebanner.png)
A series of guides intended to help you install all the different engines into your level.
Free to use, copy and modify.
~
Contents
- Read this first (#post_readthisfirst)
- Infected AI (#post_infectedai)
- Gravity/Collisions (#post_gravity)
- Parallax Scrolling (#post_parallax)
- Downloads (#post_downloads)
Thanks to CybeRogue (http://cyberogue.deviantart.com/) for the banner.
~
Read this first.
Hello.
(http://www.playdota.com/img/art/2858/fanart/f1244804694.jpg)
I wrote all of the engines in this thread. This series of guides assumes some very basic knowledge of map-making - I expect for example that you are aware how to make a While GameRunning() do loop, that you are comfortable with creating your own Asteroids in LevelSetup(), etc. If you are a newcomer to level design please read the Beginner's Guide (#post_absolutebeginners) first and try all the examples there. That combined with a couple hours of experimentation will bring you up to speed sufficiently to have a go at using some engines.
Attached to each guide you will find three files:
- The first file is not a level - it's actually just the complete code for the engine, which you just copy and paste to the bottom of your level file, below absolutely everything else.
- The second file is a simple playable map, the way I imagine your maps might look before you have any engines in them. Think of it as a "before"...
- The third file is the "after" version. This is the exact same map but with the engine in question added. This is so that you can compare the two to see the differences.
I have furnished each template with some default values, so installing the engine in your level is little more than a simple copy and paste affair, and the level will then load fine and you'll be able to see it doing something, at least.
However, only the Infected AI is intended to be used "as is". The other engines all have variables that can and should be tweaked in order to get the particular functionality you are looking for.
It would be disappointing and extremely cheesy to see finished maps being released with these default values, especially when I have taken the trouble to explain the comparitively simple ins and outs of modifying them to your own design.
Therefore, if you use any of my engines other than the Infected AI, please ensure you alter the variables in such a way that it looks sufficiently different from the defaults.
I can't force you to do this. The code is up here, freely available for all, and ultimately you can do what you want with it and there's nothing I or anyone can do to stop you. However I wanted to make my personal wishes clear in the hope that they will be respected because - from my own experimentation - I know how much is actually possible with the code contained herein, and it would be a tragic waste if that potential was not exploited by the map-making community.
Furthermore, to my mind, tweaking variables is what is so much fun about these engines. I encourage you to let your imagination go wild, and if you have any questions regarding any aspect of the engines or a query on how to implement a particular behaviour, please ask about it in the original discussion thread (http://www.dyson-game.com/smf/index.php?topic=1219.0) and I will do my best to respond.
Happy coding. :>
-Annikk.
~
(http://img218.imageshack.us/img218/5719/infectedaicover.png)
Difficulty: Easy
CPU Cost: Medium; intermittent bursts.
Downloads: Before (http://www.dyson-game.com/smf/index.php?action=dlattach;topic=1565.0;attach=1007) | After (http://www.dyson-game.com/smf/index.php?action=dlattach;topic=1565.0;attach=1006) | Engine (http://www.dyson-game.com/smf/index.php?action=dlattach;topic=1565.0;attach=1008)
1. Description
- The Infected AI Engine is a scripted alternative to the normal, ingame AI. It is designed as an "aggressive expansionist" and will use its seedlings very efficiently.
It is designed to:
i) target poorly defended asteroids when attacking
ii) use large swarms effectively by splitting its attacks across multiple different points
iii) not become traumatised by extensive damage to its empire
iv) cope with having its empire split up into parts that cannot reach one another.
If the AI's empire is reduced to a single asteroid, it will still (if subsequently left unchecked) come back to ultimately take over the entire galaxy and win.
- The Infected AI engine is the easiest of all the engines to implement, because it doesn't require you to change any variables. It will just automatically learn about your level and take control of the seedlings/trees/etc that you've added for Empires 2 and up.
- The AI is equally at home on a static map as it is on a map with moving asteroids or maps where the numbers of asteroids in play changes over time.
- It will automatically take control of any seedlings or asteroids that you assign to Empires 2 and up, and will cause them to efficiently colonise the galaxy around them, defending themselves if attacked, before ultimately aggressively attacking the player and each other.
- You only need one copy of the engine to run as many different AI empires as you like.
- The AI will not control Greys (Empire 0). So you can still use greys as a passive buffer force to guard valuable asteroids. The AI will generally avoid trying to colonise these asteroids unless it has a sufficient force to kill them all.
- The AI knows how to use flowers to get Super Seedlings, but it doesn't know how to plant them on Defence Trees to make laser mines. Perhaps a future update will introduce this functionality. However, the AI does respond vigourously if the player attacks with a laser mine, so feel free to allow the player to build mines in your level, should you deem it appropriate.
- Finally, for the avoidance of any doubt, commands like "GetAI(2).Cowardice = 0.05" and "GetAI(2).MinExpansionForce = 10" do not affect the Infected AI in any way - so remove them if you don't want the extra clutter. Those commands are for the default in-game AI, which the Infected AI automatically switches off for you when the engine initialises.
2. Implementation
- 1. Download the file attached to this post called "Infected AI Engine.lua".
- 2. Open the file in notepad or whatever text editor you use.
- 3. Select all of the code and copy it to your clipboard.
- 4. Open your own level and scroll down to the very bottom, and paste the code in. It is imperative that it appears below everything else - including the "end" from your function LevelLogic(). The code you are pasting is two entirely seperate functions so if you inadvertantly put it inside function LevelLogic() then the map won't work.
- 5. At the bottom of your function LevelSetup(), insert this command: AIinit()
- 6. In your function LevelLogic(), ensure you have a While GameRunning() do loop (or create one if you don't), then insert the following command anywhere in the loop: InfectedAIEngine()
Now the engine is implemented. Save your level and try to play it.
That's all that is required to implement Infected AI.
The process for the other engines is exactly the same - the only thing that differs is the name of the functions.
3. Variables
There are no variables to change in Infected AI. Once you have completed the above steps, the AI will be in the level. It will take control of any asteroids and seedlings that you create for Empires 2 and up.
~
(http://img3.imageshack.us/img3/15/gravityandcollisionscov.png)
Difficulty: Medium
CPU Cost: Low/medium - dependent on number of asteroids
Downloads: Before (http://www.dyson-game.com/smf/index.php?action=dlattach;topic=1565.0;attach=1004) | After (http://www.dyson-game.com/smf/index.php?action=dlattach;topic=1565.0;attach=1003) | Engine (http://www.dyson-game.com/smf/index.php?action=dlattach;topic=1565.0;attach=1005)
1. Description
- The Gravity/Collision Engine allows you to designate certain asteroids (or all asteroids) as having gravitational properties. It gives asteroids the ability to move around, bump into each other, and orbit each other in a realistic way. The fact that it is based on real life physics (loosely - antigravity doesn't really exist as far as I know) makes it all the more interesting to play around with - and some surprising behaviours fall out of the equations naturally...
- You can use this engine to make asteroids orbit each other in complex patterns. You can make asteroids incredibly bouncy, or so non-bouncy that they stick together the moment they collide. You can make asteroids that behave like balloons. You can create asteroids that have antigravity. There is a LOT you can do with this - it's extremely fun to sit around tweaking the settings to produce unlikely looking trajectories, and experiment with strange anomalies such as black holes.
- The engine is quite forgiving for mistakes. If you forget to specify variables for some of your asteroids, the level will still load - but those asteroids will not move or have any gravity. Other asteroids will still be able to bounce off them, however.
2. Implementation
- 1. Download the file attached to this post called "Gravity Engine.lua".
- 2. Open the file in notepad or whatever text editor you use.
- 3. Select all of the code and copy it to your clipboard.
- 4. Open your own level and scroll down to the very bottom, and paste the code in. It is imperative that it appears below everything else - including the "end" from your function LevelLogic(). The code you are pasting is two entirely seperate functions so if you inadvertantly put it inside function LevelLogic() then the map won't work.
- 5. At the bottom of your function LevelSetup(), insert this command: GravityInit()
- 6. In your function LevelLogic(), ensure you have a While GameRunning() do loop (or create one if you don't), then insert the following command anywhere in the loop: GravityEngine()
Now the engine is implemented, but you will need to set some variables before it will do what you want it to do.
3. Variables
In this engine there are several "global" variables which you only need to set once for the whole engine, and a handful of variables that you need to specify on a per-asteroid basis.
You can find the variables inside the "function GravityInit()" section in the code that you pasted in. The variables are all initialised here, so this is where you change all the settings.
Global Variables
- G - the overall force of gravity. I'd suggest setting this to 1 to begin with.
- bounce - how bouncy are asteroids? A perfectly elastic collision (ie the most bouncy any real life object could possibly be) is 1. I'd suggest trying 1.1 or 1.2 personally. :> It stops asteroids from clumping up together.
- EmergencyBrakeThreshold, MidBrakeThreshold, LowBrakeThreshold - These are for slowing down asteroids that are moving too fast. Set it to the speed an asteroid must be travelling to incur a slowing-down effect.
- EmergencyBrakeFactor, MidBrakeFactor, LowBrakeFactor - When one of the above thresholds is reached, this is the value that the speed is multiplied by. Setting a value of less than about 0.98 causes the asteroid to slow down like a balloon does in air.
The brakes aren't exactly very true to astrophysics, but it lets you simulate (somewhat crudely) things like the response to an atmosphere such as if you try to throw a balloon. The balloon slows down very rapidly and doesn't go very far.
Brakes are necessary if you use a bounce factor greater than 1, because that will mean each collision adds energy to the system. Without brakes, the asteroids will collide and collide, picking up more and more speed, until eventually they fly all over the screen at lightning speed colliding with each other dozens of times a second, and vanish.
This is certainly interesting but hardly makes for a productive level-making environment. Hence, the brakes.
Per-Asteroid Variables
Just copy and paste these ready-made template examples for each asteroid you need to declare for.
-- Asteroid 1
-- This asteroid has gravity and moves around. It is drifting northwest at game start.
roid = 1
hasgravity[roid] = true
canmove[roid] = true
MomentumX[roid] = -13.1
MomentumY[roid] = -9
density[roid] = 0.3
If you forget to set these attributes for one of your asteroids, some default settings will be used for it instead (the asteroid won't move and won't have gravity).
- roid - Enter the ID of the asteroid you are setting properties for.
- hasgravity - True or False. If you set to true, the asteroid will contribute forces to the gravitational field around it. If you set false, it won't produce any gravity or feel any gravity from others.
- canmove - True or False. Can the asteroid be moved (by gravity and from being struck by other asteroids), or is it static and unmoving? Using different combinations of "hasgravity" and "canmove" is the one of the main methods of producing different asteroid behaviours.
- density - how dense is the asteroid? Asteroids with greater density have more gravity. An asteroid made of metal (which has very high density, eg 10) would produce more gravity, and also take more force to get it moving, than an asteroid made of gas (which would have a density of about 0.1).
- MomentumX and MometumY - This is the starting speed/direction for this asteroid. For example, if you set the X to -3 and the Y to 0, the asteroid will start the game drifting gently west.
You can also change the properties of individual asteroids ingame whilst the simulation is in progress. To do this, simply open the console and declare a new value for the variable in question.
For example, if I wanted to set the density of Asteroid 1 to 500 instead of 0.3, this is the command I would type into the console:
density[1] = 500
Asteroid 1 would then instantly have a gravitational field more than 1500 times stronger than before, and the asteroids would all behave differently as a result of the change.
This looks hilarious, by the way. It's like someone just pulled a giant plug in space, and everything starts rushing towards it...
~
(http://img156.imageshack.us/img156/9861/parallaxscrollingcover.png)
Difficulty: Advanced
CPU Cost: High - dependent on number of asteroids and stars
Downloads: Before (http://www.dyson-game.com/smf/index.php?action=dlattach;topic=1565.0;attach=1010) | After (http://www.dyson-game.com/smf/index.php?action=dlattach;topic=1565.0;attach=1009) | Engine (http://www.dyson-game.com/smf/index.php?action=dlattach;topic=1565.0;attach=1011)
1. Description
- The Parallax Scrolling Engine lets you create stars that float behind the asteroids in your level, giving a faux-3D effect.
- This engine is the most difficult to understand and configure. However, in its default form it is cut back a great deal. You should be able to massively increase the number of stars that are displayed with some tweaking, especially if this is the only engine you are using in your level.
- This version is designed to display stars, but you can also use it to display other things. Lots of different visual effects are possible. The engine is set up to use Sprite Index 0 which in my view is the most star-like, however you can also set it to display other sprite indexes. Possibly with some interesting results.
2. Implementation
- 1. Download the file attached to this post called "Parallax Engine.lua".
- 2. Open the file in notepad or whatever text editor you use.
- 3. Select all of the code and copy it to your clipboard.
- 4. Open your own level and scroll down to the very bottom, and paste the code in. It is imperative that it appears below everything else - including the "end" from your function LevelLogic(). The code you are pasting is two entirely seperate functions so if you inadvertantly put it inside function LevelLogic() then the map won't work.
- 5. At the bottom of your function LevelSetup(), insert this command: ParallaxInit()
- 6. Insert a LevelDraw function in between your LevelSetup() and your LevelLogic() using this command: function LevelDraw()
- 7. Ensure that you place an "end" after it, to indicate where the code in that function stops.
- 8. Inside your LevelDraw, insert this command: ParallaxEngine()
Now the engine is implemented, and will work immedietely. However, be sure to change the variables to your own design before releasing it.
3. Variables
The Parallax Engine has a large number of variables. Some of the variables are arrays, so you will need to set values for all of the arrays too. Because some of the arrays can span hundreds of slots, you may wish to combine formulas and For loops in order to set all the values efficiently, without having to manually specify each one.
This engine is not nice and friendly like gravity. If you forget to set one of the values, the level will probably not load.
The settings for the Parallax Engine all appear in the ParallaxInit() function that you pasted in.
The section marked "User-Changeable Variables" roughly marks out the bounds of which variables are designed to be modified easily.
Single Variables
These are just single values that you can specify to govern global properties of the engine.
- numberofstars - The total number of stars in your level. Be careful with setting this too high - stars require a lot of processing power, especially if you have a lot of asteroids in your level.
- numberoflayers - How many Parallax layers are there? The stars will be split equally among the layers, so if you have 50 stars and 10 layers, there will be 5 stars in each layer. You can set some attributes per-star, and other attributes per-layer.
- widthofstarfield, heightofstarfield - How large an area shall the starfield occupy? Change this to be optimum for your size of map. The engine always centres the starfield at coordinates 0,0.
- starsize - How big should each star be? 200 is good for average sized stars. Setting this value very high creates some interesting effects, but the higher the value, the greater the CPU cost.
- stoprenderingbelow - When you zoom out, the engine will start to reduce the alpha of certain layers (exactly which layers is definable in the arrays section below). When the alpha falls below a certain point, the engine will just stop rendering them completely, saving CPU. Set that threshold here. Allowed values 0-1.
Setup Arrays
This is where you specify the attributes for individual stars and layers.
All these arrays are required by the engine and their values must be specified by you.
Red, Green, Blue - How much of each colour in the star? 0,0,0 is black. 1,1,1 is white.
For example, if you have 3 stars:
red[0] = 1
green[0] = 0.2
blue[0] = 0.2
red[1] = 0.2
green[1] = 0.2
blue[1] = 1
red[2] = 1
green[2] = 1
blue[2] = 1
This code would make the first star red, the second star blue, and the third star white.
The number in square brackets refers to the individual star we are colouring.
If you have hundreds or thousands of stars, this method is not a good approach. Instead, set the values with a formula. For example, this formula would colour the stars different shades of grey:
for setcol = 0,numberofstars do
red[setcol] = math.sqrt(1 / numberofstars)
green[setcol] = math.sqrt(1 / numberofstars)
blue[setcol] = math.sqrt(1 / numberofstars)
end
How to make the right formula?
Well, first think of what sort of values you are going to need. I know that for grey stars I need the values for red, green and blue to be the same for each star. So the formula should be the same for each of them (which isn't always the case - it depends entirely on the effect you're trying to achieve).
Next, I know that the values should vary between 0 and 1. I also know that the one thing that I can rely on changing between one star and another, is its ID number. So we can use that as the seed of difference for our formula.
"setcol" is going to vary between 1 and however many stars we have. Say it was 50. What could we do with the number 50 to get a value between 0 and 1?
One answer is to divide 1 by that 50, and use the result. But that's only 0.02 - if we have 100 stars then it means most of them will basically be black.
We need to find a way to increase the result we get, without making it stray above 1.
An ideal way to do this is to take the square root. The square root of 0.02 for the 50th star would be around 0.14, so its r, g and b values would be at 14%. That's a dark grey, but not black. The 10th star would be the square root of 0.1, which is about 32% - a gunmetal grey. So it looks like this formula would work well for creating stars with different shades of grey.
It's up to you to develop your own methods for setting the colours of these arrays. Lets move onto the next array.
threshold - How zoomed out do we have to be before each layer starts to fade out/disappear?
This is useful for keeping lots of detail when zoomed in, but only displaying a certain amount of stars when zoomed out so that the FPS doesn't suffer.
You need to specify a value for each layer. Unlike stars, the numbering of layers always starts on 1, NOT 0.
You can specify values manually:
threshold[1] = 0.3
threshold[2] = 0.2
threshold[3] = 0.1
threshold[4] = 0.07
threshold[5] = 0.04
Or you can do it with some formula that you invent:
for setthresh = 1, numberoflayers do
threshold[setthresh] = 1 / setthresh
end
zdepth - How far away does this layer look?
This should normally be a value greater than 1. The higher the value, the closer the stars look.
If the value is equal to 1, the stars will look like they are so far away that they don't move with the camera at all.
If the value is less than 1, the stars will move backwards!
If the value is 0, the stars will not be rendered.
If the value is less than 0, the stars will seem to be in the foreground - in front of the asteroids (but they will still disappear when they actually move in front of one)
In the template, the line looks like this:
zdepth[numberoflayers - lnumber + 1] = 1 + (5 * (1 / lnumber))
You can replace the bit after the = and write your own formula, or you can replace that line entirely and specify the z-depths for all the layers manually:
zdepth[1] = 1.1
zdepth[2] = 1.4
zdepth[3] = 1.8
zdepth[4] = 2.5
...or with any other method of your choosing.
Additional Arrays
As well as the arrays that are required for startup, there are also two others that you may be interested in using.
They are SetStarX and SetStarY. These are the "given" positions of stars. The engine generates these automatically at the start of the level but there is no reason why you couldn't refer to it and change it during play using some code in your function LevelLogic().
For example, if I want to make a star (lets say star number 50) move from side to side, I can do it with this:
function LevelLogic()
While GameRunning() do
SetStarX[50] = 1000 * math.sin(GetGameTime())
coroutine.yield()
end
end
That would cause star number 50 to drift left and right.
Using this, it's possible to make some - or all - of the stars move. You could move lots of them at once by employing a for loop.
You can do a similar thing with the other variables and arrays. You could have stars that flash/twinkle, or pulsate, or anything you like. You can even have stars that come closer or move further away! (by changing the zdepth of their layer..)
Click Here for Original Discussion Thread (http://www.dyson-game.com/smf/index.php?topic=1219.0)