How can I draw and collide with a random 2D sine wave landscape?
by John Klimek · in Torque Game Builder · 02/07/2006 (6:29 am) · 26 replies
I'm planning to make a Tanks / Scorched Earth game and I'm not sure how to draw the landscape in Torque 2D.
At first I started making this game in Macromedia Flash and was drawing the landscape like this:
for (var x:Number = 0; x < Stage.width; x++) {
_clip.lineTo(x, (Math.sin(x/34) * 36) + (Math.sin(x/23) * 29) + (Math.sin(x/27) * 37));
}
As you can see, I'm going through X value and adding together three sine waves to get a nice landscape. Eventually I'll be using random numbers inside the sine functions to generate random landscapes... (but for now I'm using static numbers)
How would I draw this in Torque 2D? Can I create/modify a bitmap image and use that?
On top of drawing the landscape/curve, I need to keep track of it for collisions (eg. when a bullet shot from a tank hits the ground it should blow up itself **AND** remove a part of the ground).
Any help at all would be GREATLY appriciated... (even if anybody can point me in the right direction of which functions to use that would be a huge help)
Thanks!
At first I started making this game in Macromedia Flash and was drawing the landscape like this:
for (var x:Number = 0; x < Stage.width; x++) {
_clip.lineTo(x, (Math.sin(x/34) * 36) + (Math.sin(x/23) * 29) + (Math.sin(x/27) * 37));
}
As you can see, I'm going through X value and adding together three sine waves to get a nice landscape. Eventually I'll be using random numbers inside the sine functions to generate random landscapes... (but for now I'm using static numbers)
How would I draw this in Torque 2D? Can I create/modify a bitmap image and use that?
On top of drawing the landscape/curve, I need to keep track of it for collisions (eg. when a bullet shot from a tank hits the ground it should blow up itself **AND** remove a part of the ground).
Any help at all would be GREATLY appriciated... (even if anybody can point me in the right direction of which functions to use that would be a huge help)
Thanks!
About the author
Recent Threads
#2
I'm OK with my method of creating the landscape (using three sine waves) but I'm not sure how to implement it using Torque (sorry if my question was vague/misleading).
Can I create my landscape (eg. sine wave) as a sprite and then use it for collision detection? Can I add/subtract areas from the sprite?
That's the kind of thing I'm wondering...
02/07/2006 (8:51 am)
Thanks for the reply!I'm OK with my method of creating the landscape (using three sine waves) but I'm not sure how to implement it using Torque (sorry if my question was vague/misleading).
Can I create my landscape (eg. sine wave) as a sprite and then use it for collision detection? Can I add/subtract areas from the sprite?
That's the kind of thing I'm wondering...
#3
As for colliding with this beast. you can only collide with convex polygons. So if you seperate all your deviations you could have numDeviations + 1 collision objects with 3 sides and use the built in collision code.
mSine is a function in the source, if it's not accessable by script you could make it so using a ConsoleMethod.
02/07/2006 (9:25 am)
John - You could create it using the new manual poly drawing techniques. Create your sine, and seperate it into X deviations. For every deviation, specify that as a new point in your poly. Then you'll have 1 large polygon made of numDeviations + 3 (for the sides and bottom).As for colliding with this beast. you can only collide with convex polygons. So if you seperate all your deviations you could have numDeviations + 1 collision objects with 3 sides and use the built in collision code.
mSine is a function in the source, if it's not accessable by script you could make it so using a ConsoleMethod.
#4
I'm suprised there isn't an easier way of doing this.... (for example, creating a bitmap/sprite from script and then modifying it, etc)
02/07/2006 (10:22 am)
Would that method work if I wanted to transform the terrain? (eg. after a bomb hits the ground I'd want a circle of the ground to be removed)I'm suprised there isn't an easier way of doing this.... (for example, creating a bitmap/sprite from script and then modifying it, etc)
#5
You want a random terrain you have to create it procedurally. If you want collision you need convex collision polys. You wont get a convex coll poly without splitting up your wave.
Trust me, this method is actually quite simple to do.
02/07/2006 (10:23 am)
Yes, you could still do that. It just takes some coding. You want a random terrain you have to create it procedurally. If you want collision you need convex collision polys. You wont get a convex coll poly without splitting up your wave.
Trust me, this method is actually quite simple to do.
#6
The photo:
02/07/2006 (11:30 am)
By the sounds of it you're trying to do something Justin did and having similar problems. Here's his original thread www.garagegames.com/mg/forums/result.thread.php?qt=29367 and his plan with a nice photo is at www.garagegames.com/index.php?sec=mg&mod=resource&page=view&qid=7689The photo:
#7
Can I ask one more thing? :)
Can you give me the names of the T2D scripting functions I should be looking at or any example code to help me out? (sorry, I'm brand new to Torque/T2D and am very clueless... plus the documentation doesn't seem all that great)
Thanks!
02/08/2006 (6:36 am)
Thanks for all of the help!Can I ask one more thing? :)
Can you give me the names of the T2D scripting functions I should be looking at or any example code to help me out? (sorry, I'm brand new to Torque/T2D and am very clueless... plus the documentation doesn't seem all that great)
Thanks!
#8
%liquid = new t2dShapeVector() { scenegraph = t2dScene; };
%liquid.setPolyCustom(4, "1 0.3 -1 0.3 -1 -0.3 1 -0.3");
%liquid.setFillMode(true);
%liquid.setFillColor("0.5 0.5 0.5 1");
%liquid.setLineColor("0.5 0.5 0.5 1");
%liquid.setSize("10 10");
%liquid.setPosition( "0 0" );
that will draw you a nice rectangle... there is also one for drawing tris, just search the forums.
I just checked and mSin(angle) is already accessible from TorqueScript.
02/08/2006 (6:40 am)
I don't know if youre talking to me or not... but here are a few to look at:%liquid = new t2dShapeVector() { scenegraph = t2dScene; };
%liquid.setPolyCustom(4, "1 0.3 -1 0.3 -1 -0.3 1 -0.3");
%liquid.setFillMode(true);
%liquid.setFillColor("0.5 0.5 0.5 1");
%liquid.setLineColor("0.5 0.5 0.5 1");
%liquid.setSize("10 10");
%liquid.setPosition( "0 0" );
that will draw you a nice rectangle... there is also one for drawing tris, just search the forums.
I just checked and mSin(angle) is already accessible from TorqueScript.
#9
So if I wanted a big landscape I would simple modify the setPolyCustom line?
Normally I'd have a new deviation for every x coordinate, but it seems like that wouldn't be possible using this method. How many deviations would be the max before things would start slowing now? (I'll also be heavily using particle effects, etc)
Also, would it possible to deform the polyform if a projectile hit it? (eg. deform a circle into the landscape/polygon)
02/08/2006 (11:49 am)
Ahhh, ok. Now I'm beginning to understand it a bit more I think.So if I wanted a big landscape I would simple modify the setPolyCustom line?
Normally I'd have a new deviation for every x coordinate, but it seems like that wouldn't be possible using this method. How many deviations would be the max before things would start slowing now? (I'll also be heavily using particle effects, etc)
Also, would it possible to deform the polyform if a projectile hit it? (eg. deform a circle into the landscape/polygon)
#10
It doesn't really matter how many X deviations you use. Set it up with a $numXDeviations variable that will allow you to alter it whenever you want. Then just experiment to find out what the best value is.
02/08/2006 (11:51 am)
John, you can make the poly do whatever you want. You could make it have a circle blast out of it. You just have to code it to work.It doesn't really matter how many X deviations you use. Set it up with a $numXDeviations variable that will allow you to alter it whenever you want. Then just experiment to find out what the best value is.
#11
Are you saying that should create an array of t2dShapeVectors? (eg. an array with around 50 or so t2dShapeVectors?) ...or are you saying I only need *one* t2dShapeVector that will draw my entire terrain?
I understand the code above that draws a box, but I don't understand for the life of me how it could draw a random terrain (and then deform it to remove circles, etc).
I hate to ask this but can you give me another example or further explain how I can do this? (again I'm so sorry for not understaind this...)
On a side note, I sent an e-mail to Justin a day or two ago but haven't heard from him. Hopefully he will be able to help me out a bit as well.
Thanks again for your help.
02/09/2006 (6:20 pm)
Again, thanks for all of the replies and for being so patient while I try to understand all of this stuff.Are you saying that should create an array of t2dShapeVectors? (eg. an array with around 50 or so t2dShapeVectors?) ...or are you saying I only need *one* t2dShapeVector that will draw my entire terrain?
I understand the code above that draws a box, but I don't understand for the life of me how it could draw a random terrain (and then deform it to remove circles, etc).
I hate to ask this but can you give me another example or further explain how I can do this? (again I'm so sorry for not understaind this...)
On a side note, I sent an e-mail to Justin a day or two ago but haven't heard from him. Hopefully he will be able to help me out a bit as well.
Thanks again for your help.
#12
$numWidthSegments = 100;
$left = // whatever hte left coordinate of the screen is
$ bottom is the bottom coordinate of the screen etc.
$terrain = new t2dShapeVector() { scenegraph = t2dScene; };
%poly = -$left SPC $bottom SPC $left SPC $bottom;
// That just sets you up with you bottom points.
for (%c = 0; %c < $numWidthSegments + 1; %c++)
{
%newHeight = ($normalheight + (mSin(getRandom(1000) / 1000))// I dont know how to get a random float
$heights[%c] = %newHeight; // This stores your heights so you can alter them alter.
%poly = %poly @ ((%c / $numWidthSegments) * ($left*2));
}
$terrain.setPolyCustom($numWidthSegments + 3, %poly); // If you alter your heights recall this.
$terrain.setFillMode(true);
$terrain.setFillColor("0.5 0.5 0.5 1");
$terrain.setLineColor("0.5 0.5 0.5 1");
$terrain.setSize($left SPC $bottom);
$terrain.setPosition( "0 0" );
The size, position, and other variables need to be set up, and this code isn't tested... But that is how I'd go about the process.
To add a cricle taken out, just find where the circle intersects your poly, and add new vertices to it to create the circle removal.
You need 1 vector... You need $numWidthSegments collision boxes.
02/10/2006 (4:00 am)
Drawing random terrain... Note, this is pseudoish code.$numWidthSegments = 100;
$left = // whatever hte left coordinate of the screen is
$ bottom is the bottom coordinate of the screen etc.
$terrain = new t2dShapeVector() { scenegraph = t2dScene; };
%poly = -$left SPC $bottom SPC $left SPC $bottom;
// That just sets you up with you bottom points.
for (%c = 0; %c < $numWidthSegments + 1; %c++)
{
%newHeight = ($normalheight + (mSin(getRandom(1000) / 1000))// I dont know how to get a random float
$heights[%c] = %newHeight; // This stores your heights so you can alter them alter.
%poly = %poly @ ((%c / $numWidthSegments) * ($left*2));
}
$terrain.setPolyCustom($numWidthSegments + 3, %poly); // If you alter your heights recall this.
$terrain.setFillMode(true);
$terrain.setFillColor("0.5 0.5 0.5 1");
$terrain.setLineColor("0.5 0.5 0.5 1");
$terrain.setSize($left SPC $bottom);
$terrain.setPosition( "0 0" );
The size, position, and other variables need to be set up, and this code isn't tested... But that is how I'd go about the process.
To add a cricle taken out, just find where the circle intersects your poly, and add new vertices to it to create the circle removal.
You need 1 vector... You need $numWidthSegments collision boxes.
#13
Something I discovered was that ALL polygon line points must be between -1 and 1. I really dislike that system but I think I understand how to use it at least.
Here is my code:
Now... I seem to be having two more problems...
1) When I enable fillmode (see picture below), it doesn't seem to be filling in the correct area. Notice the two arrows (that I drew in photoshop). That area shouldn't be filled in...
2) The polygon (eg. my landscape/terrain) looks VERY jagged. Can this line be somehow smoothed out? It looks terrible in it's current state (imho)...

Thanks again a TON for helping me with this!
02/10/2006 (8:29 pm)
Ok, that code didn't seem to work but I understood the idea enough to write my own code...Something I discovered was that ALL polygon line points must be between -1 and 1. I really dislike that system but I think I understand how to use it at least.
Here is my code:
function drawLand()
{
echo("Drawing!");
// Globals
$terrainWidth = 100;
$terrain = new t2dShapeVector() { scenegraph = t2dScene; };
$terrain.setLineColor("1.0 0.2 0.2 1");
$terrain.setFillMode(true);
$terrain.setSize("100 75");
$terrain.setPosition("0 0");
$terrain.setFillColor("0.2 0.2 1.0 1");
// Start in bottom left
$poly = "-1 1";
$polyCount = 1;
// Loop through entire width of terrain (in this case terrainwidth is the entire width of our camera viewing area)
for (%c = 0; %c < $terrainWidth; %c++)
{
// Get X values between -1 and 1 and spread them out to $terrainWidth number of points
%xVal = -mCos(mDegToRad(180 / $terrainWidth * %c));
// Draw a sine wave
%yVal = -mSin(mDegToRad(360 / $terrainWidth * %c));
// For debugging... I didn't want any points touching the bottom of the screen in case that was causing fillmode problems
if (%yVal > 0.9)
%yVal = 0.9;
$poly = $poly SPC %xVal SPC %yVal;
$polyCount++;
echo(%c SPC "(" @ %xVal @ ", " @ %yVal @ ")" );
}
// Add bottom right corner point
$poly = $poly SPC "1 1";
$polyCount++;
$terrain.setPolyCustom($polyCount, $poly);
}Now... I seem to be having two more problems...
1) When I enable fillmode (see picture below), it doesn't seem to be filling in the correct area. Notice the two arrows (that I drew in photoshop). That area shouldn't be filled in...
2) The polygon (eg. my landscape/terrain) looks VERY jagged. Can this line be somehow smoothed out? It looks terrible in it's current state (imho)...

Thanks again a TON for helping me with this!
#14
Looks to me like that is a line from your last point to the corner... make sure you're creating your bottom right, then bottom left corners before you start creating the rest of the land
How jagged are we talking here? You either need to add more deviations into your poly, or you need anti-aliasing...
$terrain.dump(); and see if there is a way to alias it, but I dont think there is.
02/11/2006 (4:49 am)
I don't know about it filling the wrong area. Looks to me like that is a line from your last point to the corner... make sure you're creating your bottom right, then bottom left corners before you start creating the rest of the land
How jagged are we talking here? You either need to add more deviations into your poly, or you need anti-aliasing...
$terrain.dump(); and see if there is a way to alias it, but I dont think there is.
#15
I also looked at $terrain.dump() but didn't see any anti-aliasing functions. Also, I'm creating a new point for every X value on the screen. For example, in my case the camera is showing 100 units on the X axis and so I am creating 100 (+2) polygon points. I don't think it's really possible to create any more than that so I don't understand why it's so jagged...
T2D seems really amazing but generating a simple 2D landscape/terrain is a key feature for my game... If I'm not able to do this I don't see I can use T2D =(
02/11/2006 (8:03 pm)
I've editted the code so I get the bottom-right and then bottom-left points before the others but I get a similar problem (it is filling area outside of the line).I also looked at $terrain.dump() but didn't see any anti-aliasing functions. Also, I'm creating a new point for every X value on the screen. For example, in my case the camera is showing 100 units on the X axis and so I am creating 100 (+2) polygon points. I don't think it's really possible to create any more than that so I don't understand why it's so jagged...
T2D seems really amazing but generating a simple 2D landscape/terrain is a key feature for my game... If I'm not able to do this I don't see I can use T2D =(
#16
Chris [at} spunkygames [dot] com
02/12/2006 (5:44 am)
John - If you want to sedn me over your games foler (ie, the T2D folder) I'll take a look at it and see if I can't sort out your issue. Chris [at} spunkygames [dot] com
#17
Once again I cannot stress how thankful I am for your help =)
Thanks!
02/12/2006 (7:58 am)
E-mail sent.Once again I cannot stress how thankful I am for your help =)
Thanks!
#18
You want something more like this:
function GenerateTerrain()
{
// starting height from 20 to 60
%h = (getrandom() * 20) + 40; // random start point
for (%i = 0; %i < 99; %i++)
{
%nh = %h + ((getrandom() * 8) - 4); // insert your sine function here instead of my random
// min max check
if (%nh > 80)
%nh = 80;
if (%nh < 20)
%nh = 20;
%x = (%i * 0.02) - 1;
%x2 = %x + 0.02;
%y = (%h * 0.01);
%y2 = (%nh * 0.01);
%poly = new t2dShapeVector()
{
scenegraph = t2dScene;
CollisionCallback = false;
CollisionMaxIterations = 2;
CollisionPolyList = (%x SPC %y SPC %x2 SPC %y2 SPC %x2 SPC "1" SPC %x SPC "1");
CollisionMaterial = terrainMaterial;
collisionDetectionMode = "POLYGON";
collisionResponseMode = "CLAMP";
collisionActiveSend = "1";
collisionActiveReceive = "1";
collisionPhysicsSend = "1";
collisionPhysicsReceive = "1";
collisionLayerMask = "1";
collisionGroupMask = "1";
collisionCallback = "0";
};
%poly.setImmovable(true);
%poly.setPolyCustom(4, %x SPC %y SPC %x2 SPC %y2 SPC %x2 SPC "1" SPC %x SPC "1");
%poly.setFillMode(true);
%poly.setFillColor("0.5 0.5 0.5 1");
%poly.setLineColor("0.5 1 0.5 0.2");
%poly.setPosition("0 5");
%poly.setSize("300 70");
%h = %nh;
}
}
Now; I'm doing a very similiar thing in my game; but I'll be damned if I can get objects to ride along it correctly. The physics always seems to freak out and send my object flying across the screen.
02/12/2006 (8:51 am)
The fill issue is due to mesh teselation. Basically, every polygon is extending from that bottom left corner as a triangle, so you have an edge going from that bottom left corner to the top right corner. The easiest way to fix this is to make your terain out of a bunch of quads instead of one big polygon. 3d hardware doesn't draw nGons, it draws triangles, so it has to tesellate your geometry into triangles, and in doing so it's overlapping itself.You want something more like this:
function GenerateTerrain()
{
// starting height from 20 to 60
%h = (getrandom() * 20) + 40; // random start point
for (%i = 0; %i < 99; %i++)
{
%nh = %h + ((getrandom() * 8) - 4); // insert your sine function here instead of my random
// min max check
if (%nh > 80)
%nh = 80;
if (%nh < 20)
%nh = 20;
%x = (%i * 0.02) - 1;
%x2 = %x + 0.02;
%y = (%h * 0.01);
%y2 = (%nh * 0.01);
%poly = new t2dShapeVector()
{
scenegraph = t2dScene;
CollisionCallback = false;
CollisionMaxIterations = 2;
CollisionPolyList = (%x SPC %y SPC %x2 SPC %y2 SPC %x2 SPC "1" SPC %x SPC "1");
CollisionMaterial = terrainMaterial;
collisionDetectionMode = "POLYGON";
collisionResponseMode = "CLAMP";
collisionActiveSend = "1";
collisionActiveReceive = "1";
collisionPhysicsSend = "1";
collisionPhysicsReceive = "1";
collisionLayerMask = "1";
collisionGroupMask = "1";
collisionCallback = "0";
};
%poly.setImmovable(true);
%poly.setPolyCustom(4, %x SPC %y SPC %x2 SPC %y2 SPC %x2 SPC "1" SPC %x SPC "1");
%poly.setFillMode(true);
%poly.setFillColor("0.5 0.5 0.5 1");
%poly.setLineColor("0.5 1 0.5 0.2");
%poly.setPosition("0 5");
%poly.setSize("300 70");
%h = %nh;
}
}
Now; I'm doing a very similiar thing in my game; but I'll be damned if I can get objects to ride along it correctly. The physics always seems to freak out and send my object flying across the screen.
#19
How would you deform the terrain if you do this? (lets say a missile hits the ground and you want it to deform the land)
Also, your example still looks a bit jaggy :( (maybe thats just the price of using t2dShapeVectors...)
02/12/2006 (9:08 am)
So what you're saying is to draw 100 (or whatever) individual t2dShapeVectors?How would you deform the terrain if you do this? (lets say a missile hits the ground and you want it to deform the land)
Also, your example still looks a bit jaggy :( (maybe thats just the price of using t2dShapeVectors...)
#20
02/12/2006 (9:18 am)
Well, you can up the subdivision all you want to remove the jaggies. Just make 800 segments instead of 100. But yes, you'll need to draw each one as an individual quad since you cannot tesselate the segment from the bottom corner without having two peaks which create an overlap. As for collisions, just store the polygons in a SimSet and update each one individually on a collision callback.
Torque Owner Chris Labombard
Premium Preferred
Create a random number from 1 - maxHeight for each of 800 different terrain width segments.
Then average those a few times to get a nice, smooth, random terrain
When something explodes you can use a mathematical formula to reduce the height at each segment based on what the difference in height is, based on the distance to the center of the balst and the radius.
You wont have a sinucoidal wave, but you will have a random terrain with varying heights. You may be able to encorporate a sine wave if you use a random number when computing the sine. sin(X + getrandom(maxHeight) / maxHeight); or something