Join devRant
Do all the things like
++ or -- rants, post your own rants, comment on others' rants and build your customized dev avatar
Sign Up
Pipeless API

From the creators of devRant, Pipeless lets you power real-time personalized recommendations and activity feeds using a simple API
Learn More
Search - "eye _am_ the vectors skyler!"
-
Okay, summary of previous episodes:
1. Worked out a simple syntax to convert markdown into hashes/dictionaries, which is useful for say writing the data in a readable format and then generating a structured representation from it, like say JSON.
2. Added a preprocessor so I could declare and insert variables in the text, and soon enough realized that this was kinda useful for writing code, not just data. I went a little crazy on it and wound up assembling a simple app from this, just a bunch of stuff I wanted to share with friends, all packed into a single output html file so they could just run it from the browser with no setup.
3. I figured I might as well go all the way and turn this into a full-blown RPG for shits and giggles. First step was testing if I could do some simple sprites with SVG to see how far I could realistically get in the graphics department.
Now, the big problem with the last point is that using Inkscape to convert spritesheets into SVG was bit of a trouble, mostly because I am not very good at Inkscape. But I'm just doing very basic pixel art, so my thought process was maybe I can do this myself -- have a small tool handle the spritesheet to SVG conversion. And well... I did just that ;>
# pixel-to-svg:
- Input path-to-image, size.
- grep non-transparent pixels.
- Group pixels into 'islands' when they are horizontally or vertically adjacent.
- For each island, convert each pixel into *four* points because blocks:
· * (px*2+0, py*2+0), (px*2+1, py*2+0), (px*2+1, py*2+1), (px*2+0, py*2+1).
· * Each of the four generated coordinates gets saved to a hash unique to that island, where {coord: index}.
- Now walk that quad-ified output, and for each point, determine whether they are a corner. This is very wordy, but actually quite simple:
· * If a point immediately above (px, py-1) or below (px, py+1) this point doesn't exist in the coord hash, then you know it's either top or bottom side. You can determine whether they are right (px+1, py) or left (px-1, py) the same way.
· * A point is an outer corner if (top || bottom) && (left || right).
· * A point is an inner corner if ! ((top || bottom) && (left || right)) AND there is at least _one_ empty diagonal (TR, TL, BR, BL) adjacent to it, eg: (px+1, py+1) is not in the coord hash.
· * We take note of which direction (top, left, bottom, right) every outer or inner corner has, and every other point is discarded. Yes.
Finally, we connect the corners of each island to make a series of SVG paths:
- Get starting point, remember starting position. Keep the point in the coord hash, we want to check against it.
- Convert (px, py) back to non-quadriplied coords. Remember how I made four points from each pixel?
. * {px = px*0.5 + (px & 1)*0.5} will transform the coords from quadriple back to actual pixel space.
· * We do this for all coordinates we emit to the SVG path.
- We're on the first point of a shape, so emit "M${px} ${py}" or "m${dx} ${dy}", depending on whether absolute or relative positioning would take up less characters.
· * Delta (dx, dy) is just (last_position - point).
- We walk from the starting point towards the next:
· * Each corner has only two possible directions because corners.
· * We always begin with clockwise direction, and invert it if it would make us go backwards.
· * Iter in given direction until you find next corner.
· * Get new point, delete it from the coord hash, then get delta (last_position - new_point).
· * Emit "v${dy}" OR "h${dx}", depending on which direction we moved in.
· * Repeat until we arrive back at the start, at which point you just emit 'Z' to close the shape.
· * If there are still points in the coord hash, then just get the first one and keep going in the __inverse__ direction, else stop.
I'm simplifying here and there for the sake of """brevity""", but hopefully you get the picture: this fills out the `d` (for 'definition') of a <path/>. Been testing this a bit, likely I've missed certain edge cases but it seems to be working alright for the spritesheets I had, so me is happiee.
Elephant: this only works with bitmaps -- my entire idea was just adding cute little icons and calling it a day, but now... well, now I'm actually invested. I can _probably_ support full color, I'm just not sure what would be a somewhat efficient way to go about it... but it *is* possible.
Anyway, here's first output for retoori maybe uuuh mystery svg tag what could it be?? <svg viewBox="0 0 8 8" height="16" width="16"><path d="M0 2h1v-1h2v1h2v-1h2v1h1v3h-1v1h-1v1h-1v1h-2v-1h-1v-1h-1v-1h-1Z" fill="#B01030" stroke="#101010" stroke-width="0.2" paint-order="stroke"/></svg>4