/
sprite.c
101 lines (86 loc) · 3.48 KB
/
sprite.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
#include <SDL_image.h>
#include <SDL_rotozoom.h>
#include "sprite.h"
#define RGBA_FORMAT 32,0x00ff0000,0x0000ff00,0x000000ff,0xff000000
void sprite_origin_rect(Sprite *sprite, Action action, int frame, SDL_Rect *rect)
{
frame = frame % sprite->frame_count;
rect->x = sprite->origin.x + frame *sprite->frame_size.x;
rect->y = sprite->origin.y + action*sprite->frame_size.y;
rect->w = sprite->frame_size.x;
rect->h = sprite->frame_size.y;
}
#define ANGLE_STEP 15
#define ZOOM 1
void sprite_rotated_rect(Sprite *sprite, Action action, int frame, int angle, SDL_Rect *rect)
{
frame = frame % sprite->frame_count;
int angle_index = ((int)(360+angle+ANGLE_STEP/2) % 360) / ANGLE_STEP;
rect->x = frame *sprite->rotated_frame_size.x;
rect->y = action*sprite->rotated_frame_size.y+
+ sprite->rotated_frame_size.y*ACTION_COUNT*angle_index;
rect->w = sprite->rotated_frame_size.x;
rect->h = sprite->rotated_frame_size.y;
}
void sprite_gen_rotation(Sprite *sprite)
{
rotozoomSurfaceSize(
sprite->frame_size.x,
sprite->frame_size.y,
45, // to maximize size
ZOOM, // no zoom
&sprite->rotated_frame_size.x,
&sprite->rotated_frame_size.y
);
if(sprite->rotated)
SDL_FreeSurface(sprite->rotated);
sprite->rotated = SDL_CreateRGBSurface(SDL_HWSURFACE,
sprite->rotated_frame_size.x * sprite->frame_count,
sprite->rotated_frame_size.y * ACTION_COUNT * 360/ANGLE_STEP,
RGBA_FORMAT);
if(sprite->rotated == NULL) {
fprintf(stderr, "CreateRGBSurface failed: %s\n", SDL_GetError());
exit(1);
}
//printf("cache size %dx%d for %d angles\n", sprite->rotated->w, sprite->rotated->h, 360/ANGLE_STEP);
SDL_Surface *element = SDL_CreateRGBSurface(SDL_HWSURFACE,
sprite->frame_size.x,
sprite->frame_size.y,
RGBA_FORMAT);
SDL_SetAlpha(sprite->source,0,0xff);
SDL_SetAlpha(element,0,0xff);
SDL_SetAlpha(sprite->rotated,SDL_SRCALPHA,0xff);
int frame, action, angle;
for(action=0; action<ACTION_COUNT; action++) {
for(frame=0; frame<sprite->frame_count; frame++) {
SDL_Rect src;
sprite_origin_rect(sprite, action, frame, &src);
for(angle=0; angle<360; angle+=ANGLE_STEP) {
SDL_Rect dst;
sprite_rotated_rect(sprite, action, frame, angle, &dst);
SDL_FillRect(element, NULL, 0x00000000);
SDL_BlitSurface( sprite->source, &src, element, NULL );
SDL_Surface *rotozoom = rotozoomSurface(element, angle+90, ZOOM, SMOOTHING_ON); // XXX 90 offset, because the sprite images are looking downwards
SDL_SetAlpha(rotozoom,0,0);
SDL_SetColorKey(rotozoom,0,0);
dst.x += dst.w/2 - rotozoom->w/2;
dst.y += dst.h/2 - rotozoom->h/2; // center
SDL_BlitSurface(rotozoom, NULL, sprite->rotated, &dst );
SDL_FreeSurface(rotozoom);
}
}
}
SDL_FreeSurface(element);
}
void sprite_init(Sprite *sprite, int ox, int oy, int fx, int fy, int c, const void *mem, int len)
{
memset(sprite,0,sizeof(Sprite));
sprite->origin.x = ox;
sprite->origin.y = oy;
sprite->frame_size.x = fx;
sprite->frame_size.y = fy;
sprite->frame_count = c;
sprite->source = IMG_Load_RW(SDL_RWFromConstMem( mem, len), 0);
sprite->rotated = NULL;
sprite_gen_rotation(sprite);
}