[Freeciv-Dev] (PR#12214) generating unit selection animation frames
[Top] [All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
<URL: http://bugs.freeciv.org/Ticket/Display.html?id=12214 >
And this one supports alpha levels through multi-sampling. Change the
alpha_sampling value to something like 16 to get good results.
-jason
/* By Jason Dorje Short. Distributed under the GPL. */
/* Compile as
gcc -Wall -g `pkg-config --cflags --libs gtk+-2.0` select.c -o select
*/
#include <assert.h>
#include <stdlib.h>
#include <math.h>
#include <gtk/gtk.h>
#define FRAMES 4
#define SEGMENTS 6
#define PI 3.14159265359
/* Return the angle, on the scale of 0..1 */
double get_angle(double x, double y)
{
if (x == 0.0) {
if (y >= 0.0) {
return 0.25;
} else {
return 0.75;
}
}
return atan(y / x) / (2 * PI);
}
int main(int argc, char **argv)
{
GdkPixbuf *fog;
int W, H, i;
char *filename;
int iso;
const int alpha_sampling = 1, S = alpha_sampling;
if (argc < 4) {
printf("Usage: %s <width> <height> <output PNG>\n", argv[0]);
printf("\n");
printf("Give this program a tile size and filename and it will create\n");
printf("a set of 4 selected-unit sprites.\n");
exit(1);
}
W = atoi(argv[1]);
H = atoi(argv[2]);
filename = argv[3];
printf("Converting %d x %d sprites in %s.\n", W, H, filename);
if (W != H) {
iso = 1;
assert(W == 2 * H);
} else {
iso = 0;
}
gtk_init(&argc, &argv);
fog = gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, 8, W * FRAMES, H);
for (i = 0; i < FRAMES; i++) {
int x, y, xa, ya;
const int x0 = i * W, y0 = 0;
for (x = 0; x < W; x++) {
for (y = 0; y < H; y++) {
int count = 0;
/* Pixbuf X/Y values. */
const int px = x + x0;
const int py = y + y0;
guchar *pixel = gdk_pixbuf_get_pixels(fog)
+ py * gdk_pixbuf_get_rowstride(fog)
+ px * gdk_pixbuf_get_n_channels(fog);
for (xa = 0; xa < S; xa++) {
for (ya = 0; ya < S; ya++) {
const double WS = W * S;
// const double HS = H * S;
const int xb = x * S + xa;
const int yb = y * S + ya;
const double tx = xb - (iso ? (WS / 2.0) : 0);
const double ty = yb;
/* Transformed X/Y values. */
const double mx = iso ? (tx + ty * 2.0) : tx;
const double my = iso ? (ty * 2.0 - tx) : ty;
const double center = (WS - (double)S) / 2.0;
const double rx = mx - center;
const double ry = my - center;
const double min_r2 = center * center * 0.7;
const double max_r2 = center * center * 1.0;
double r2 = rx * rx + ry * ry;
double angle = get_angle(rx, ry) + 10000.0;
int circle = iso; /* Otherwise square. */
angle += (double) i / (double)(FRAMES * SEGMENTS);
assert(angle >= 0.0); /* otherwise we get rounding errors */
if (((circle && r2 >= min_r2 && r2 < max_r2)
|| (!circle && (ABS(rx) > WS * 0.4 || ABS(ry) > WS * 0.4)))
&& (int)(angle * SEGMENTS * 2) % 2 == 0) {
count++;
}
}
}
pixel[0] = pixel[1] = pixel[2] = 255;
pixel[3] = 255 * count / (S * S);
}
}
}
gdk_pixbuf_save(fog, filename, "png", NULL, NULL);
return 0;
}
|
|