Your browser does not seem to support JavaScript. As a result, your viewing experience will be diminished, and you have been placed in read-only mode.
Please download a browser that supports JavaScript, or enable it if it's disabled (i.e. NoScript).
Math is useful after all!
When ZP posted the beta of SMM with rotation and displacement built in, my first thought was, "I bet I can make shapes with this." Using a shell script and a bit of clever math, you can get the tool to churn out all kinds of shapes automatically. The actual utility of this in mapmaking is debatable, but I thought it was a fun exercise to try.
The circle seemed like a good first candidate to test the waters: simple, elegant, and, above all, easy to implement. So, I made a circle of radius 800px out of short wasteland walls. You will note that there is a gap between each sprite; they actually match up perfectly, but of course, the visible part of the sprite (and, usually, its collision rectangle) is smaller than its clipping rectangle.
More shapes to come, hopefully.
This post has been edited by cheleball : 25 February 2007 - 03:21 PM
Nice, cheleball. I also think math is usefull afterall.
@cheleball, on Feb 25 2007, 08:19 PM, said in SketchMapMerge Shapes:
cute - and a perfect example why when I first posted I said I tended to prefer perl and a text editor than fancy gui programs (especially ones that use 80% of your CPU for no good reason)
Now that's (mis)use of my stuff one that I didn't foresee (but I knew from the moment I made this that it could be used for a number of things)
By the way, math is useful, always, how do you think I programmed rotation? (and no, it isn't as trivial as you may be thinking)
Quote
It seems that someone needs to check the batteries in his joke detector.
I do have some idea. There's a simple formula for rotating a point about the origin. Apply that formula to the geometric center of each sprite; this will yield the x and y offsets produced by the rotation. You must either add or subtract these offsets based on the quadrant the point begins in. You then rotate the sprite by the specified rotation angle and translate it by the aforementioned offsets.
I bet there are some complications with rotating the sprites due to the rotational center not always being the geometric center, and correcting for that.
Close or no cigar?
BTW, scaling would also be a nice feature, if you've time and inclination.
@cheleball, on Feb 26 2007, 03:48 AM, said in SketchMapMerge Shapes:
Translation, scaling and rotation can all be done (in one go, with pencil & paper) using very simple (2x2) matrix multiplication. (EDIT: I lie, translation is (of course) an addition/subtraction) Scaling is particularly easy since it is merely a scalar multiplication. You just need to apply to all four vertices of the sprite (which can be done as one 4x2 matrix (or 5x2 if the centre point is 'off-centre' and needing to be calculated separately). I'm sure google will find you a 'learn-it-yourslef' introduction. Probably as a result of some university's coursework schedule and lecture notes being on the public internet .
The theory was tested at GCSE (yr 15/6) maths here in the UK, with 3D points and shapes in A-level (17/8) (and other fun like judging whether lines intersect planes or not). Happy memories of a maths geek.
It took until university though before we actually programmed up (in plain raw C, none of this fancy Java/C++/Obj-C object nonsense ;)) libraries for rotating shapes etc. First year course-work - which was quite tough for those who hadn't done maths before, but plain sailing for those of us who had. Meant we could spend more time in the pub. Ah... to be a student again.
Ah... but... it also meant having no income... so maybe I prefer the working life
This post has been edited by Crono : 26 February 2007 - 04:16 AM
Don't worry, I suspected it was a joke However, complexities with how the sprites are actually placed mean that rotating them is more complicated than that. Scaling I don't like it at all. It has the potential to render a playable level unplayable, would decrease line width in the whole level which would make it incoherent with any levels merged with it and any other level released to date. In short, I don't do it because the player isn't scaled himself.
Back to the topic: I'm wondering what other shapes you could do say, do me a cycloid!
@zacha-pedro, on Feb 26 2007, 10:13 AM, said in SketchMapMerge Shapes:
Yup, it's a shame that some of the sprites aren't actually vector based - obviously it would be a touch difficult with the pen - but many of the others would scale wonderfully that way. (sniff)
What I'd be quite interested in would be making curvy passage-ways this way - by passing a suitable pseudo-random polynomial function one could make walls that follow the path and hence simply making passage ways.
You are quite right though that the edges of the drawn sprites are almost never in line with the edges of the sprite boxes (another sigh) so it would need a fair amount of manual touch-up work or a DB of the actual vertices of the contacts of the sprites. However, often some overlap I've found from my experience looks quite good rather than pixel-perfect line placement
To get it right, I'd have to measure the length of the line, rather than just getting the length from the editor. I was too lazy for this exercise, but if I actually wanted to use a circle in a map, I'd have to.
As for other shapes: most are considerably trickier than the circle. The circle was easy because the rotation increment is constant, there's a simple correlation between rotation angle and the radius vector (used for the offsets), and the edge matching happens automagically if you set it up as an inscribed polygon (which it is).
I'm thinking that it should be possible to do arbitrary shapes given a function describing the curve and its derivative. The trouble comes when you need to figure out what value of x to pass to the function to get the edges to match up. This is why I said "maybe" to more shapes--I'm going to try, but don't know if I'll succeed!
Or - here's a thought I just had - you could use the inscribed polygon thing again. Solve the distance formula simultaneously with the curve function to find the values of x and y that yield a distance the length of one wall from the previous wall placed, while still falling on the curve. You wouldn't even need a derivative for rotation angle, since you'd have two points.
It might work. Too bad I have midterms all this week. I might still be able to steal a few hours to do this. (Others could make shapes too; Crono, I'm looking at you. :))
One last reason not to have scaling: how to handle tiled flags? With rotation and displacement, The whole things always looks the same, including with these (precisely because the tiling starts from the top left corner of the sprite, and is not independant of the sprite position), but scaling would mess up this, even if it would only be cosmetic. As for vectors, this isn't really the miracle solution to this problem (and the more general problem of resolution independance, as the Iconfactory guys recently explained); you wouldn't like sprites that look like cheleball's sample replacement assets in his Custom Asset Enabler (sorry chele, but they look like they're coming from "a PostScript printer in 1990", I suppose they are quick Illustrator work); the point of this game is hand-drawn sprites and lines.
As for sprite joining, the best an automated tool can do is try to have the contact boxes be in, well, contact. Indeed line joining is best, but short of analysing the texture (yeah, right ) it's the best an automated tool can do.
@zacha-pedro, on Feb 26 2007, 04:07 PM, said in SketchMapMerge Shapes:
I'm not quite sure what you mean by vectors not being resolution independent - they would be far more so than bitmaps which by their very nature are totally resolution dependent. However, resolution independence has very little to do with it anyway, since SFA is itself not in the least bit RI - it always displays at 800x600 and stretches it to fill the screen in full-screen mode...
Given that it doesn't use vector graphics, there's no way that it could be RI though. (okay, not quite try, you could play the finder's icon trick and simply have many bitmaps at various sizes and scale between the two closest to the correct dimension required... but I digress). RI just means that you are working with relative sizes rather than absolute - anyone who has ever put pen to web-paper and has a reasonable knowledge of css will be quite adapet at producing RI pages - at least as far as text and layout is concerned... of course, web-pages contain bitmaps too.. Vector graphics are an answer because they can be scaled to any size, but (as I said above) you couldn't produce the pen sprite at all easily with VG - or indeed anything vaguely photo-realistic. Well... until someone makes a fortune out making the perfect bitmap to vector converter.
But I digress further
To be honest, the points you talk about could mostly be handled with a suitable database of offsets for where the join marks actually are on the sprites (which would have to be hand generated). It works only because SFA isn't resolution independent (though ironically it were, the game engine would probably be of a standard whereby it was much easier to do!). However (as I said) it hardly seems worth going about it noting all the said offsets. An approximation and then manual touch up is better IMHO, otherwise you may well get CG effects
Tiling could also be dealt with (assuming you know the sprite is tiled, and how the engine handles that) by just applying the same offsets as the game would as a result. As I said before, I view it is a bug that tiled sprites use their top-left offset to offset the bitmap they contain, but that's the way it was chosen so fair enough. Maybe one day we'll expand the 32-bit tiled flag to contain land-scaping too <_<
One cycloid, coming right up!
It turns out that there is no algebraic solution to the system of the parametric cycloid equations and the distance formula. Since I was going to need to solve it numerically anyway, I tried the brute force method: Increment the parameter by 0.0001; calculate x, y, and the distance D of that point from the previous; check to see if D=L (the length of the sprite). It works!
The only problem I'm having is that the angle of rotation is off by a bit, and I'm not sure why. I'll post the code I'm using, and maybe another propellerhead can figure it out.
#!/usr/bin/php <?php //Numeric configuration; for now must determine by hand // r and L are in pixels $r = 200; //Radius of the generating circle $L = 72; //Length of the wall $theta = 0; //Angle of rotation $limit = 17; //Max parameter value $inc = 0.0001; //Parameter increment for the "brute force" method. //previous x,y $a = 0; $b = 0; $base1 = escapeshellarg ('/Users/ryos/Documents/Sketchfighter/SMM Shapes/base1.SketchMap'); $base2 = escapeshellarg ('/Users/ryos/Documents/Sketchfighter/SMM Shapes/base2.SketchMap'); $outFile = escapeshellarg ('/Users/ryos/Documents/Sketchfighter/SMM Shapes/Cycloid.SketchMap'); $smmPath = escapeshellarg ('/Applications/Games/SketchFighter 4000 Alpha/SketchMapMerge 1.0.0b1/SketchMapMerge'); $useBase = $base2; for ($t = 0; $t <= $limit; $t += $inc) { //The parametric cycloid equations $x = $r*( $t - sin($t) ); $y = -$r*( 1 - cos($t) ); $D = sqrt( pow(($x-$a),2) + pow(($y-$:P,2) ); //the distance formula //Angle theta found as clockwise rotation starting from the y-axis if (round($D) == $L) { switch (true) { case ($y < $;): $theta = asin( ($x-$a)/$L ); break; case ($y > $B): $theta = pi() - asin( ($x-$a)/$L ); break; case ($y == $;): $theta = pi()/2; break; default: //all hell breaks loose } echo "theta: $theta\n"; echo "x: $x\ny: $y\n"; echo "a: $a\nb: $b\n\n"; shell_exec ("$smmPath -i $useBase -t ". round(rad2deg($theta)) ." -d ". round($x) ." ". round($y) ." -i $outFile -o $outFile"); $a = $x; $b = $y; } } ?>
This post has been edited by cheleball : 26 February 2007 - 06:48 PM
@cheleball, on Feb 26 2007, 11:46 PM, said in SketchMapMerge Shapes:
ick, PHP, no variable scoping or checking.
One solution to the problem is to think of this as draw part circles. Essentially you have two functions, one which does the % of the circle's circumference that you previously wanted, the second which is a step function that kicks in and alters the circle's centre after each circle sector is drawn. Much simpler, and no 'brute force'
Another (more continuous) method is simply to do it by the absolute( sine(x) ), which will do pretty much what you are after
@crono, on Feb 27 2007, 02:53 AM, said in SketchMapMerge Shapes:
I knew someone would say something about that. You just couldn't resist, could you?
Look, we run a MAMP shop where I work, so PHP is what I write web pages with every day. I don't know Python or Ruby or Perl, but I know me some PHP, and by golly, it gets the job done just the same.
Sounds interesting, but I don't understand how it would yield a cycloid. Would you mind being a bit more specific?
Sounds like a great way to get a sinusoid, but again, how would that get me a cycloid? (I know you're being pragmatic, but getting a shape that looks like a cycloid but is not one just doesn't tick that checkbox next to the goal in my brain that says, "make a cycloid." ;))
As for the source of the bad rotation angles, I figure it could be one of three things:
Roundoff errors in the calculation (the angles are a bit too far off for this to be the case IMO, and also, they're off by the same amount in successive cycloids, which would tend to point away from roundoff error).
The angle is calculated for the center of the sprite and not its rightmost edge.
There's something about the way SMM works that I don't understand.
I hope the true cause is really on that list. Now I just need to figure out which it might be...
FYI, the "base" is a map file with just a wasteland wall short, sized 84x46 and positioned with its center at the origin, with the "in" side facing right. I calculate the rotation angle as the angle between the line determined by the two points found in the cycloid calculation and the y-axis. (BTW, I replaced the switch statement with a single line that takes advantage of the fact that a Β b = abcos(theta), but the result is exactly the same. :()
@cheleball, on Feb 27 2007, 05:24 PM, said in SketchMapMerge Shapes:
FYI, the "base" is a map file with just a wasteland wall short, sized 84x46 and positioned with its center at the origin, with the "in" side facing right. I calculate the rotation angle as the angle between the line determined by the two points found in the cycloid calculation and the y-axis. (BTW, I replaced the switch statement with a single line that takes advantage of the fact that a β’ b = abcos(theta), but the result is exactly the same. :()
lol - well, I've done a fairly huge amount of php too, and have developed a loathing for the language. There's just no consistency in the API's (haystack, needle, or vice-versa?) - the way references work is insanely broken, there's no decent type and safety checking - not even any scoping like perl's 'use strict' to catch variable name typos... It's just... ugh... my shining star example of terrible open-source
But... I use it nonetheless because so many people I do websites in my spare time for insist on it. Seems to be a mantra these days... "must... have... php.... ajax... javascript... web2 ... other-marketing-buzzword-which-I-don't-know-what-it-means-but-I-want-it-anyway!"
However (as with most languages - it's whatever works best for you. I've done a limited amount of python, insanely huge (10's of thousands of lines of object-orientated perl - yeah, OO-perl 5 it is possible... sort of... ), but no ruby. I do want to try ruby-on-rails at some point, if I can only be bothered to sit down and learn it.
Then there's the more traditional c (and 'newer' c99),c++, obj-c, haskell, java and such. But... gah, they all seem so low level after using scripting languages.
So I'm somewhat multi-lingual, and therefore feel I have a right to slate php
but moving on...
Well, to me (and apologies if I've got the wrong end of the stick, a 'cycloid' is a something that looks quite like
y = abs( sin(x) )
i.e. (using macos x's wonderful grapher program), assuming no tweaking of he constants that define it.
y_abs_sin_x.png (19.43K) Number of downloads: 7
the difference being on the gradient differential - a cycloid looks like it is about to go asymptotic where it crosses the axis, whilst this does not (the gradient is moving towards 1 as it crosses the axis. Of course, if you take a more general formula:
y=n*abs(sin(m*x))+c
then 'n' gives a height scale factor, 'm' gives a frequency scale factor and 'c' gives an offset (probably not useful here)
The partial circle idea solves this neatly, but still suffers from having discontinuities where the step function kicks in and moves you from right-hand edge of one circle to left-hand edge of the next....
Moving on...
However... if you want to make a 'real' cycloid, you've got to go parametric. I'm assuming you know about radians rather than degrees when doing graphs (it makes things easier) - so you want an equation along the lines of (where 't' is in radians)
x = at - h sin(t), y = a - h cos(t)
Which when plotted will give you a cycloid. e.g. I did in the grapher for this image with t running from 0 to 6*PI: (PI radians = 180 degrees = 1/2 a circle, if you prefer using degrees)
parametric.png (11.2K) Number of downloads: 4
again, you can play with the constants (both taken as '1') to adjust it. If 'h' > 'a' then you will see that you make loops rather than 'points' between the main curves which look quite pretty but aren't in this use case very interesting for this application. Try it in the grapher program and see what takes your fancy. Finally, there's the special case where 'a' = 0, which as you can probably tell, will give you your normal circle, radius, 'h' centred on the origin.
Ah... my A-level maths is all coming back to me
(edited for some typos in my anti-php rant)
This post has been edited by Crono : 27 February 2007 - 06:03 PM
snip anti-PHP rant
I actually agree with most of what you said. The one time I used references I vowed I would never do it again. The inability to know exactly for sure what type a variable is can be annoying, although I find that the empty() function combined with the is_ datatype functions do most of what I need. I always need to consult the manual whenever I use a needle/haystack function, because I can never keep them straight. But my biggest gripe with the language is the weird OO structure that doesn't really fit the rest of the language, and the difficulty of error handling.
But, its associative arrays are awesome, there's a function for just about everything, and it has some nice bits like its handling of sessions and request data. Which make up enough for its deficiencies that I haven't taken time out from my work projects to switch to Ruby or something.
But even the much-vaunted Ruby is untyped - it uses "duck typing" to figure out the types of variables. I'll leave it an exercise to your imagination to decide what that means :).
snip lots of math
Uh...A for effort, man, and I do appreciate the effort, but...well, I can look up the formula for a cycloid just fine. In fact, I used the parametric formula in my code. But I was actually curious about this:
That sounds interesting, like it could solve my angle problem if I understood how it works. For example, a cycloid, as far as I can tell, is not composed of "partial circles" at all. And how do you tell how much to "alter the circle's center after each sector is drawn"?
@cheleball, on Feb 28 2007, 06:00 AM, said in SketchMapMerge Shapes:
Uh...A for effort, man, and I do appreciate the effort, but...well, I can look up the formula for a cycloid just fine. In fact, I used the parametric formula in my code.
Wow, now I do feel like I'm back at school
Yup, I was just trying to illustrate how the two earlier versions I gave are just discontinuous approximations to a 'standard' cycloid - i.e. where h=a by going though some of the maths behind it. But given your next question it looks like I didn't really get that point across anyway
Whether h=a or not, a cycloid is always continuous, and by making h > a so you can see the loops going on, it shows that you have a continuous function. Now, what is important is that the direction that the walls face is governed by the differential - and around the 'points' between curves (t = 0, 2PI, 4PI etc) where h = a you have an issue that the differential is changing extremely rapidly (try plotting the gradients and even the 2nd order gradients to see what I mean - I'll drop the images now! ).
But I was actually curious about this: That sounds interesting, like it could solve my angle problem if I understood how it works. For example, a cycloid, as far as I can tell, is not composed of "partial circles" at all. And how do you tell how much to "alter the circle's center after each sector is drawn"?
Indeed, as outlined above, a cycloid is continuous, and it is this very issue that causes you problems (I suspect) when placing walls based on the values around the interconnects.
That said, you are not going to come up with a single formula which will smoothly do these. Both the ABS(sin(x)) and partial circle formulae will help to a certain extent, but you will need to special,case out the joins yourself (possibly with an inverted and much smaller half circle). I'm at work at the moment, so since you are good with google I'll let you play. I'll go into more details when I get out if you want.
Ahem people Programming language discussions are best suited for Just Tech; let's not scare the average SketchFighter 4000 Alpha player who first comes here more than he is already seeing all these map design topics
Crono, the way you describe to do a cycloid (like it is a light on a rotating bicycle wheel) is really the cycloid equation (abs(sin(x)) isn't, by far). However, simply having (note: this is pseudo-code more or less C-like):
angle = 0; centerX = 0; for index from 0 to 100 SketchMapMerge -i result.SketchMap -i LoneWall.Sketch -t angle -d centerX 0 -o result.SketchMap angle += alpha; centerX += delta; end for (with, of course, (alpha*Ο/180)*distance_of_wall_from_0_0=delta)
won't really work, as the wall wouldn't be in the direction of the tangeant of the cycloid at that point, and there would be many walls at the bottom point and not many at the top since the light goes very slow (it even reaches 0 speed) at the bottom and very fast at the top.
@zacha-pedro, on Feb 28 2007, 02:22 PM, said in SketchMapMerge Shapes:
Ahem peopleβ¦ Programming language discussions are best suited for Just Tech; let's not scare the average SketchFighter 4000 Alpha player who first comes here more than he is already seeing all these map design topicsβ¦
awww...
Crono, the way you describe to do a cycloid (like it is a light on a rotating bicycle wheel) is really the cycloid equation (abs(sin(x)) isn't, by far).
Uh, yes, I thought that was what I had been saying...
However, for the case in point which (to my understanding) was essentially trying to create a set of touching 'U's (upside-down or otherwise) of walls - then something like abs(sin(x)) (simple, but has the wrong derivatives as already noted) or just partial circles (has correct derivative if the end required result is what I mentioned) are much better and don't have the problems of the gradient doing a full 360 at each of the 'joins' in a cycloid with no back-overlap (h=a).
If the point in question is to create a true-cycloid, then the answer is to use the equation that cheleball first used, but he also needs to not iterate linearly over values for 't'. Instead, the equation needs to be remapped in terms of x and y and increment them both by suitable amounts based on the length and width of the rotated shape - essentially you are repeating a shape of known dimensions along a path, not just plotting a point. Alternatively, one can attempt to 'brute force' it by simply incrementing 't' until such time as the new x,y value is outside the pervious shape.
Regardless of how you do it, what you get out at the end though will be pretty useless with regards to a SFA wall though for obvious reasons.
But anyways, I think I've said my fill here - I'll let cheleball clarify what he was actually after.
This post has been edited by Crono : 28 February 2007 - 01:37 PM
Augh! My head! My head!