I am creating the "perfect" sprite packer. This is a sprite packer that makes sure the output sprite is compatible with most if not all game engines and animation software. It is a program that merges images into a horizontal sprite sheet.
It converts (if needed) the source frames to BMP in memory
It considers the top-left pixel fully transparent for the entire image (can be configured)
It parses the frames each individually to find the real coordinates rect (where the actual frame starts, ends, its width and height (sometimes images may have a lot of extra transparent pixels).
It determines the frame box, which have the width and height of the frame with the largest width/height so that it is long enough to contain every frame. (For extra compatibility, every frame must have the same dimensions).
Creates output sprite with width of nFrames * wFrameBox
The problem is - anchor alignment. Currently, it tries to align each frame so that its center is on the frame box center.
if((wBox / 2) > (frame->realCoordinates.w / 2))
{
xpos = xBoxOffset + ((wBox / 2) - (frame->realCoordinates.w / 2));
}
else
{
xpos = xBoxOffset + ((frame->realCoordinates.w / 2) - (wBox / 2));
}
When animated, it looks better with it, but there is still this inconsistent horizontal frame position so that a walking animation looks like walking and shaking.
I also tried the following:
store the real x pixel position of the widest frame and use it as a reference point:
xpos = xBoxOffset + (frame->realCoordinates.x - xRef);
It also gives a little better results, showing that this is still not the correct algorithm.
Honestly, I don't know what am I doing.
What will be the correct way to align sprite frames (obtain the appropriate x position for drawing the next frame) given that the output sprite sheet have width of the number of frames multiplied by the width of the widest frame?
Your problem is that you first calculate the center then calculate the size of the required bounding box. That is why your image 'shakes' because in each image that center is different to the original center.
You should use the center of the original bounding box as your origin, then find out the size of each sprite, keeping track of the leftmost, rightmost, topmost and bottommost non transparent pixels. That would give you the bounding box you need to use to avoid the shaking.
The problem is that you will find that most sprites are already done that way, so the original bounding box is actually defined as to the minimum space to paint the whole sprite's sequence covering these non transparent pixels.
The only way to remove unused sprite space is to store the first sprite complete, and then the origin and dimensions of each other sprite, like is done in animated GIF and APNG ( Animated PNG -> https://en.wikipedia.org/wiki/APNG )
Related
Based on this stackoverflow answer:
https://stackoverflow.com/a/55385972
I'm trying to find a way to move the output of fragment shader inside screen coordinates. In that example the output must have the same size of screen resolution, otherwise you'll see only a portion of the result. Furthermore the result is always aligned with lower-left corner.
In which way someone can resize the final frame and draw it centered in viewport? E.g., screen 1920x1080, viewport 1920x1080, final distorted frame 640x480 centered, so frame position x = 640, y = 300. I can't find a way to move the destination result
See, I'm not posting code because I need logic, math, algorithms. Well:
I'm trying to achieve a 3d-looking visual for a top-down tile map using layers and parallax scrolling. The thing is: At the moment I simply set different "speeds" for each layer. But that would only work with some very specific camera positions, also, it makes so that the blocks have virtually an infinite height (as they will "increase in height" until they are out of the camera's FOV).
Is there a better (should be) to achieve the effect? Oh, and I'm using C with Allegro 5.
I thought about limiting each layer's offset, but I have no idea how.
My current method:
That's my current code for the layer "speed" (it repeats for up, down, left and right, changing coordinates):
if (key[ALLEGRO_KEY_UP])
camera_y[0] -= 1;
camera_y[1] -= 2;
camera_y[2] -= 3;
Then I run a loop to draw the map with the tiles relative to the current layer's offset.
By the way, that's the desired effect (example with 3 layers):
For parallax scrolling, layers that scroll faster must be correspondingly larger:
You can use unscaled tiles stacked on top of each other, offset by a fixed fraction of the distance from the center of the tile to the center of the viewport,
but the tops will not be continuous (unless the bottoms overlap). If all layer tiles are hand-drawn or rendered images, this is not an issue.
If the walls are box-shaped, and you have images of the top and each of the four sides, you can draw them in almost 3D,
where at most two sides of each box wall is drawn, skewed.
In all cases:
If the center of the viewport is at world coordinates (xc, yc), point (x, y, z) maps to coordinates (x', y') relative to the center of the viewport:
x' = (x - xc) × (z + z0) / z0
y' = (y - yc) × (z + z0) / z0
where z0 is a constant that determines the "size" of the parallax or depth effect.
I think you're on the right lines, but the "infinite height" issue can be solved by simply giving the camera an "altitude" property, and adjust the "speed" of each layer by calculating ...
layer.speed = (layer.altitude / camera.altitude) * ZOOM_FACTOR; //gives a float value.
Can't really suggest anything more until you show us some of your math code.
I'm trying to use FreeType to create a bitmap font for a microcontroller, but I'm stuck on the fundamental difference in the way coordinates are expressed. My microcontroller expects an X and Y offset for the glyph bitmap relative to an origin point in the upper left corner, whereas FreeType is giving me "bearings" relative to an invisible baseline. I'm pretty sure bearingX is what I want for my X offset, but how do I determine my Y offset? I tried subtracting bearingY from the ascender height, but some of the offsets come out negative. This is unacceptable, because it makes drawing text in the upper left corner of a display impossible.
I solved my problem by pre-rendering all of the glyphs, and keeping track of the maximum ascent and descent in actual rendered pixels. Then I calculated the maximum height of all glyphs from the two values, and used that to calculate the Y-offset for each glyph bitmap from its top bearing. With an extra rendering step, I can also re-scale the face to more closely match my desired pixel height.
Similar to calibrating a single camera 2D image with a chessboard, I wish to determine the width/height of the chessboard (or of a single square) in pixels.
I have a camera aimed vertically at the ground, ensured to be perfectly level with the surface below. I am using the camera to determine the translation between consequtive frames (successfully achieved using fourier phase correlation), at the moment my result returns the translation in pixels, however I would like to use techniques similar to calibration, where I move the camera over the chessboard which is flat on the ground, to automatically determine the size of the chessboard in pixels, relative to my image height and width.
Knowing the size of the chessboard in millimetres, I can then convert a pixel unit to a real-world-unit in millimetres, ie, 1 pixel will represent a distance proportional to the height of the camera above the ground. This will allow me to convert a translation in pixels to a translation in millimetres, recalibrating every time I change the height of the camera.
What would be the recommended way of achieving this? Surely it must be simpler than single camera 2D calibration.
OpenCV can give you the position of the chessboard's corners with cv::findChessboardCorners().
I'm not sure if the perspective distortion will affect your calculations, but if the chessboard is perfectly aligned beneath the camera, it should work.
This is just an idea so don't hit me.. but maybe using the natural contrast of the chessboard?
"At some point it will switch from bright to dark pixels and that should happen (can't remember number of columns on chessboard) times." should be a doable algorithm.
I need to implement a simple plotting component in C#(WPF to be more precise). What i have is a collection of data samples containing time (X axis) and a value (both double types).
I have a drawing canvas of a fixed size (Width x Height) and a DrawLine method/function that can draw on it. The problem I am facing now is how do I draw the plot so that it is autoscaled? In other words how do I map the samples I have to actual pixels on my Width x Height canvas?
One hacky method that may work is to use a Viewbox control. This control will scale the rendering of its content to fit the size available. However, this might lead to your lines and labels looking too thick or thin.
The more sensible method that you're probably after, though, is how to work out at what scale to draw your graph at in the first place. To do that, work out the range of values on a given axis (for example, your Y-axis value might range from 0 to 100). Work out the available drawing space on that axis (for example, your canvas might have 400 pixels of height). Your Y-axis "scale factor" when drawing the graph would be <available space> / <data range> - or, in this case, 4.
Your canvas' coordinates start from zero in the top-left so, to calculate the Y-position for a given data point, you would calculate like this:
double availableSpace = 400.0; // the size of your canvas
double dataRange = 100.0; // the range of your values
double scaleFactor = availableSpace / dataRange;
double currentValue = 42.0; // the value we're trying to plot
double plottableY = availableSpace - (currentValue * scaleFactor); // the position on screen to draw at
The value of plottableY is the y-coordinate that you would use to draw this point on the canvas.
(Obviously this code would need to be spread out across your drawing method so you're not recalculating all of the values for each point, but it demonstrates the math).