root / proj / src / sprite.c @ 210
History | View | Annotate | Download (4.03 KB)
1 | 152 | up20180642 | #include <lcom/lcf.h> |
---|---|---|---|
2 | |||
3 | #include "sprite.h" |
||
4 | |||
5 | 166 | up20180642 | #include "graph.h" |
6 | 163 | up20180642 | #include "utils.h" |
7 | 168 | up20180642 | #include "fast_math.h" |
8 | 160 | up20180642 | #include <math.h> |
9 | 210 | up20180642 | |
10 | struct basic_sprite{
|
||
11 | uint8_t *map; |
||
12 | uint16_t w, h; |
||
13 | int16_t u0, v0; |
||
14 | }; |
||
15 | |||
16 | basic_sprite_t* (basic_sprite_ctor)(const char **xpm, int16_t u0, int16_t v0){ |
||
17 | basic_sprite_t *ret = malloc(sizeof(basic_sprite_t));
|
||
18 | if(ret == NULL) return NULL; |
||
19 | enum xpm_image_type type = XPM_8_8_8_8;
|
||
20 | xpm_image_t img; |
||
21 | ret->map = xpm_load((xpm_map_t)xpm, type, &img); |
||
22 | if(ret->map == NULL){ |
||
23 | free(ret); |
||
24 | return NULL; |
||
25 | } |
||
26 | ret->w = img.width; |
||
27 | ret->h = img.height; |
||
28 | ret->u0 = u0; |
||
29 | ret->v0 = v0; |
||
30 | return ret;
|
||
31 | } |
||
32 | void (basic_sprite_dtor)(basic_sprite_t *p){
|
||
33 | if(p == NULL) return; |
||
34 | free(p->map); |
||
35 | free(p); |
||
36 | } |
||
37 | |||
38 | const uint8_t* (basic_sprite_get_map)(const basic_sprite_t *p){ return p->map; } |
||
39 | uint16_t (basic_sprite_get_w) (const basic_sprite_t *p){ return p->w ; } |
||
40 | uint16_t (basic_sprite_get_h) (const basic_sprite_t *p){ return p->h ; } |
||
41 | int16_t (basic_sprite_get_u0) (const basic_sprite_t *p){ return p->u0 ; } |
||
42 | int16_t (basic_sprite_get_v0) (const basic_sprite_t *p){ return p->v0 ; } |
||
43 | |||
44 | struct sprite{
|
||
45 | const basic_sprite_t *bsp;
|
||
46 | int16_t x, y; //position in screen
|
||
47 | double theta, s, c;
|
||
48 | double scale;
|
||
49 | }; |
||
50 | |||
51 | sprite_t* (sprite_ctor)(const basic_sprite_t *bsp){
|
||
52 | sprite_t *ret = malloc(sizeof(sprite_t));
|
||
53 | if(ret == NULL) return NULL; |
||
54 | ret->bsp = bsp; |
||
55 | ret->x = 0;
|
||
56 | ret->y = 0;
|
||
57 | sprite_set_angle(ret, 0.0); |
||
58 | ret->scale = 1.0; |
||
59 | return ret;
|
||
60 | } |
||
61 | void (sprite_dtor)(sprite_t *p){
|
||
62 | if(p == NULL) return; |
||
63 | free(p); |
||
64 | } |
||
65 | |||
66 | void (sprite_set_pos) (sprite_t *p, int16_t x , int16_t y ){ p->x = x; p->y = y; }
|
||
67 | void (sprite_set_angle) (sprite_t *p, double angle ){ p->theta = angle; p->c = fm_cos(p->theta); p->s = fm_sin(p->theta); } |
||
68 | void (sprite_set_scale) (sprite_t *p, double scale ){ p->scale = scale; } |
||
69 | int16_t (sprite_get_x)(const sprite_t *p){ return p->x; } |
||
70 | int16_t (sprite_get_y)(const sprite_t *p){ return p->y; } |
||
71 | |||
72 | void (sprite_src2pic)(const sprite_t *p, int16_t x, int16_t y, int16_t *u, int16_t *v){ |
||
73 | double dx = (x - p->x)/p->scale;
|
||
74 | double dy = (y - p->y)/p->scale;
|
||
75 | int16_t du = dx*p->c - dy*p->s + 0.5; |
||
76 | int16_t dv = dx*p->s + dy*p->c + 0.5; |
||
77 | *u = du + basic_sprite_get_u0(p->bsp); |
||
78 | *v = dv + basic_sprite_get_v0(p->bsp); |
||
79 | } |
||
80 | |||
81 | void (sprite_pic2src)(const sprite_t *p, int16_t u, int16_t v, int16_t *x, int16_t *y){ |
||
82 | int16_t du = u - basic_sprite_get_u0(p->bsp); |
||
83 | int16_t dv = v - basic_sprite_get_v0(p->bsp); |
||
84 | double dx = du*p->c + dv*p->s;
|
||
85 | double dy = -du*p->s + dv*p->c;
|
||
86 | *x = dx*p->scale + 0.5 + p->x; |
||
87 | *y = dy*p->scale + 0.5 + p->y; |
||
88 | } |
||
89 | |||
90 | void (sprite_draw)(const sprite_t *p){ |
||
91 | const uint16_t w = basic_sprite_get_w(p->bsp);
|
||
92 | const uint16_t h = basic_sprite_get_h(p->bsp);
|
||
93 | int16_t xmin, xmax, ymin, ymax; { |
||
94 | int16_t x, y; |
||
95 | sprite_pic2src(p, 0, 0, &x, &y); |
||
96 | xmin = x; xmax = x; ymin = y; ymax = y; |
||
97 | sprite_pic2src(p, w, 0, &x, &y);
|
||
98 | xmin = min(x, xmin); xmax = max(x, xmax); ymin = min(y, ymin); ymax = max(y, ymax); |
||
99 | sprite_pic2src(p, 0, h, &x, &y);
|
||
100 | xmin = min(x, xmin); xmax = max(x, xmax); ymin = min(y, ymin); ymax = max(y, ymax); |
||
101 | sprite_pic2src(p, w, h, &x, &y); |
||
102 | xmin = min(x, xmin); xmax = max(x, xmax); ymin = min(y, ymin); ymax = max(y, ymax); |
||
103 | xmin = max(xmin-2, 0); xmax = min(xmax+2, graph_get_XRes()); |
||
104 | ymin = max(ymin-2, 0); ymax = min(ymax+2, graph_get_YRes()); |
||
105 | } |
||
106 | const uint8_t *map = basic_sprite_get_map(p->bsp);
|
||
107 | const uint16_t bytes_pixel = graph_get_bytes_pixel();
|
||
108 | for(int16_t u, v, y = ymin; y < ymax; ++y){
|
||
109 | unsigned pos = (xmin + y*graph_get_XRes())*bytes_pixel;
|
||
110 | for(int16_t x = xmin; x < xmax; ++x, pos += bytes_pixel){
|
||
111 | sprite_src2pic(p, x, y, &u, &v); |
||
112 | if(0 <= u && u < w && 0 <= v && v < h){ |
||
113 | uint32_t c = *(uint32_t*)(map + (v*w + u)*4);
|
||
114 | if(GET_ALP(c) < 0x7F) |
||
115 | graph_set_pixel_pos(pos, c); |
||
116 | } |
||
117 | } |
||
118 | } |
||
119 | } |