|
Ashkin
|
 |
« Reply #2160 on: October 23, 2011, 03:08:29 AM » |
|
Just compressed way too many lines of code into a couple of for loops! It makes CIRCLES. var widthtracker:int = 3;//This is always 3- produces diamonds at larger sizes but whatever. for (var Y:int = Math.round(y/8)-_radius; Y < Math.round(y/8)+_radius+1; Y++) { for (var X:int = Math.round(x/8)-((widthtracker-1)/2)-1; X < Math.round(x/8)+((widthtracker-1)/2); X++) { registry.scenerymap.setTile(X, Y, 0); registry.collisionmap.setTile(X, Y, 0); registry.tilemap.setTile(X, Y, 0); } if (Y > Math.round(y/8)) { widthtracker -= 2; } else if (Y < Math.round(y/8)-1) { widthtracker += 2; } } Yeah, I probably could've found some circle-making code online. But it was fun to do it myself, and the feeling it gave me was awesome.
|
|
|
|
|
Logged
|
|
|
|
|
Nix
|
 |
« Reply #2161 on: October 23, 2011, 05:41:19 AM » |
|
Dude. Just use sin and cos
|
|
|
|
|
Logged
|
|
|
|
|
rivon
|
 |
« Reply #2162 on: October 23, 2011, 07:47:41 AM » |
|
Dude. Just use sin and cos
Exactly my thoughts... It would be much shorter and simpler...
|
|
|
|
|
Logged
|
|
|
|
|
Ashkin
|
 |
« Reply #2163 on: October 23, 2011, 01:50:30 PM » |
|
Dude. Just use sin and cos
Exactly my thoughts... It would be much shorter and simpler... Yeah but you see the problem here is that I'm awful at math. Guess I'd better go look up how to use sin and cos to make circles... Man I suck.
|
|
|
|
|
Logged
|
|
|
|
|
mcc
|
 |
« Reply #2164 on: October 23, 2011, 02:05:32 PM » |
|
Parameters: Radius, Points, Centerx, Centery
For t=0 to Points theta = t/Points * 2 * pi x = Centerx + Radius*sin(theta) y = Centery + Radius*cos(theta) Plot(x,y)
|
|
|
|
|
Logged
|
|
|
|
|
Ashkin
|
 |
« Reply #2165 on: October 23, 2011, 02:12:46 PM » |
|
Parameters: Radius, Points, Centerx, Centery
For t=0 to Points theta = t/Points * 2 * pi x = Centerx + Radius*sin(theta) y = Centery + Radius*cos(theta) Plot(x,y)
I think I understand that... Radius is (obviously) how far the circle extends from the center, while centerx/y is the middle of the circle. But what is the Points variable? 
|
|
|
|
|
Logged
|
|
|
|
|
mcc
|
 |
« Reply #2166 on: October 23, 2011, 02:16:34 PM » |
|
Parameters: Radius, Points, Centerx, Centery
For t=0 to Points theta = t/Points * 2 * pi x = Centerx + Radius*sin(theta) y = Centery + Radius*cos(theta) Plot(x,y)
I think I understand that... Radius is (obviously) how far the circle extends from the center, while centerx/y is the middle of the circle. But what is the Points variable?  "How many points of the circle do I draw?" If you set Points to 4, you will draw a square/diamond If you set Points to something large like 50 or 100 (preferably not larger than you need) it will look like a circle
|
|
|
|
|
Logged
|
|
|
|
|
Ashkin
|
 |
« Reply #2167 on: October 23, 2011, 02:18:47 PM » |
|
Parameters: Radius, Points, Centerx, Centery
For t=0 to Points theta = t/Points * 2 * pi x = Centerx + Radius*sin(theta) y = Centery + Radius*cos(theta) Plot(x,y)
I think I understand that... Radius is (obviously) how far the circle extends from the center, while centerx/y is the middle of the circle. But what is the Points variable?  "How many points of the circle do I draw?" If you set Points to 4, you will draw a square/diamond If you set Points to something large like 50 or 100 (preferably not larger than you need) it will look like a circle Oh, haha, I get it. So you'd need an infinite loop for a proper circle, but the higher the number, the smoother it is. Thanks mcc <3
|
|
|
|
|
Logged
|
|
|
|
|
Glaiel-Gamer
|
 |
« Reply #2168 on: October 23, 2011, 02:37:40 PM » |
|
Dude. Just use sin and cos
or this http://en.wikipedia.org/wiki/Midpoint_circle_algorithmwhich looks closer to what he already has than sin/cos (sin/cos are also expensive if performance matters) especially if you're calculating sin/cos for EVERY POINT, you can/should do it once (with delta_theta which is 2*pi / points) and then do [copypasta from my own circle iteration] gla::sincos((PI/2.0)/seg, sind, cosd); //sincos sets sind to sin(theta) and cosd to cos(thets), slight optimization in my implimentation to do both at the same time rather than one at a time Vec2D edge = Vec2D::UP; //vector is (0, -1), scale it by radius if needed for(int i = 0; i<=seg; i++){ edge.rotate(sind, cosd); //circle point is edge.x, edge.y }
... ... ...
void Vec2D::rotate(float sina, float cosa){ float tx = x*cosa-y*sina; float ty = x*sina+y*cosa; x = tx; y = ty; }
|
|
|
|
|
Logged
|
|
|
|
|
Nix
|
 |
« Reply #2169 on: October 23, 2011, 02:42:01 PM » |
|
You're basically doing a matrix transform and calculating the transformation matrix once. I had a lot of fun playing with matrix transformations while making the lighting for Solar Reboot.
|
|
|
|
|
Logged
|
|
|
|
|
Ashkin
|
 |
« Reply #2170 on: October 23, 2011, 02:48:08 PM » |
|
Oh dear, sin and cos do appear to be quite performance-heavy, especially if you're trying to make a full circle like my algorithm does, rather than just an outline. Honestly I don't see why I should change my algorithm when the other alternatives are more performance-heavy, but I'll try experimenting with the Midpoint circle algorithm that Glaiel posted. Although, honestly, I doubt I can understand it.
... I'm bad at programming. I don't even know what a floating point number is for, though I aim to remedy that right now.
|
|
|
|
|
Logged
|
|
|
|
|
mcc
|
 |
« Reply #2171 on: October 23, 2011, 03:00:22 PM » |
|
What I usually do on the performance issue is something like declare a global
cpVect onehundredpointsofacircle[100];
(where cpVect is a 2-vector) and then prepopulate it with circle values at startup. That means I call the trig functions 200 times at startup, then after that all circle point calculations are a single lookup. Nix/Glaiel's approach sounds good too though and under many situations would be more performant.
|
|
|
|
|
Logged
|
|
|
|
|
Ashkin
|
 |
« Reply #2172 on: October 23, 2011, 03:16:01 PM » |
|
What I usually do on the performance issue is something like declare a global
cpVect onehundredpointsofacircle[100];
(where cpVect is a 2-vector) and then prepopulate it with circle values at startup. That means I call the trig functions 200 times at startup, then after that all circle point calculations are a single lookup. Nix/Glaiel's approach sounds good too though and under many situations would be more performant.
So you're basically 'baking' in preset values so you have a lookup table rather than doing all of the calculations as they happen? That seems like it could be good for performance. But even with the calculations, as long as they take, my circle look... weird. It may be because I'm only doing them in a 7*7 or so space. That's why I feel my algorithm works better- I'll always be working in small sizes.
|
|
|
|
|
Logged
|
|
|
|
|
|
|
st33d
Guest
|
 |
« Reply #2174 on: October 24, 2011, 02:52:18 AM » |
|
What I usually do on the performance issue is something like declare a global
cpVect onehundredpointsofacircle[100];
(where cpVect is a 2-vector) and then prepopulate it with circle values at startup. That means I call the trig functions 200 times at startup, then after that all circle point calculations are a single lookup. Nix/Glaiel's approach sounds good too though and under many situations would be more performant.
So you're basically 'baking' in preset values so you have a lookup table rather than doing all of the calculations as they happen? That seems like it could be good for performance. But even with the calculations, as long as they take, my circle look... weird. It may be because I'm only doing them in a 7*7 or so space. That's why I feel my algorithm works better- I'll always be working in small sizes. Um, there's always the Bresenham algorithms for these: package com.nitrome.gfx { /** * Draws a filled pixelated circle to a Vector of pixels * * code is a trimmed version of the code found here: * http://actionsnippet.com/?p=1658 * * @author Aaron Steed, nitrome.com */ public function bresenhamCircle(x:int, y:int, radius:int, pixels:Vector.<uint>, width:int, height:int, col:uint = 0x00000000):void{ var xoff:int =0; var yoff:int = radius; var balance:int = -radius; var i:int, p0:int, p1:int, w0:int, w1:int, index:int; var size:int = width * height; while(xoff <= yoff){ p0 = x - xoff; p1 = x - yoff; w0 = xoff + xoff; w1 = yoff + yoff; index = p0 + (y + yoff) * width; for (i = 0; i < w0; i++){ index++; if(index > -1 && index < size) pixels[index] = col; } index = p0 + (y - yoff) * width; for (i = 0; i < w0; i++){ index++; if(index > -1 && index < size) pixels[index] = col; } index = p1 + (y + xoff) * width; for (i = 0; i < w1; i++){ index++; if(index > -1 && index < size) pixels[index] = col; } index = p1 + (y - xoff) * width; for (i = 0; i < w1; i++){ index++; if(index > -1 && index < size) pixels[index] = col; }
balance += xoff + xoff; xoff++; if (balance >= 0){ yoff--; balance -= yoff + yoff; } } }
}
package com.nitrome.gfx { import flash.display.BitmapData; /** * Draws a Bresenham Ellipse. * * ported from: * http://homepage.smc.edu/kennedy_john/belipse.pdf * * (if he mentioned it was written in Delphi in the paper it would have saved me some time) * * @author Aaron Steed, nitrome.com */ public function bresenhamEllipse(cx:int, cy:int, radiusX:int, radiusY:int, bitmapData:BitmapData, col:uint = 0x00000000):void{ var x:int, y:int; var changeX:int, changeY:int; var error:int; var twoASquare:int, twoBSquare:int; var stoppingX:int, stoppingY:int; twoASquare = 2 * radiusX * radiusX; twoBSquare = 2 * radiusY * radiusY; x = radiusX; y = 0; changeX = radiusY * radiusY * (1 - 2 * radiusX); changeY = radiusX * radiusX; error = 0; stoppingX = twoBSquare * radiusX; stoppingY = 0; while(stoppingX >= stoppingY){ bitmapData.setPixel32(cx + x, cy + y, col); bitmapData.setPixel32(cx - x, cy + y, col); bitmapData.setPixel32(cx - x, cy - y, col); bitmapData.setPixel32(cx + x, cy - y, col); y++; stoppingY += twoASquare; error += changeY; changeY += twoASquare; if(2 * error + changeX > 0){ x--; stoppingX -= twoBSquare; error += changeX; changeX += twoBSquare; } } x = 0; y = radiusY; changeX = radiusY * radiusY; changeY = radiusX * radiusX * (1 - 2 * radiusY); error = 0; stoppingX = 0; stoppingY = twoASquare * radiusY; while(stoppingX <= stoppingY){ bitmapData.setPixel32(cx + x, cy + y, col); bitmapData.setPixel32(cx - x, cy + y, col); bitmapData.setPixel32(cx - x, cy - y, col); bitmapData.setPixel32(cx + x, cy - y, col); x++; stoppingX += twoBSquare; error += changeX; changeX += twoBSquare; if(2 * error + changeY > 0){ y--; stoppingY -= twoASquare; error += changeY; changeY += twoASquare; } } }
}
They're about the fastest method you're going to get. Or you could simply build a table if it's always small circles.
|
|
|
|
|
Logged
|
|
|
|
|