shavlul@ucscb.ucsc.edu (60231000) (12/12/90)
In response to your question about rotating sprites, i decided to try to write something like it. Since I haven't used my commodore 64 in a while I would probably make too many mistakes trying to translate the following to commodore basic without trying it out. The following does work on standard unix C. Since commodore sprites are 24x24, you'd have to adjust the 4.5's to 11.5 (equidistant from 0 and 23), 5.0's to 12.0, and the size of sprite and sprite2. The method used is to write into the new sprite (never overwrite the original sprite data or you'll lose resolution FAST) pixel by pixel, looking at the pixel at same distance and angle (original angle-ph) from the center of the sprite. floor () is equivalent to BASIC's INT. Why was 4.5 used in one place and 5.0 in another? The 5.0 is actually because it is floor(4.5+ ... +0.5), same as INT(X+.5) to round numbers properly. This code acts strange when rounding isn't working in a fair manner. In case you don't know C, the derivation is at the end of this post. (I apologize for not sending mail- this machine is very flaky with bitnet) +/* This is only a test */ +#include <stdio.h> +#include <math.h> +char sprite[11][11] = +{ "....AB....", + "....CD....", + "....EF....", + "....GH....", + "....IJ....", + "....KL....", + "....MN....", + "....OP....", + "....QR....", + "....ST...." +}; +char sprite2[11][11]; +char readspr(); +void writespr(); +main () +{ int i,j,x,y; + double th,ph,cx,cy; + for (i=0; i<10; ++i) + puts(sprite[i]); + + scanf ("%lf",&ph); + printf ("Confirming %lf\n",ph); + ph=ph*(3.1415926535897932384626433832795028843/180.); + for (x=0; x<10; ++x) + { cx=(double)x-4.5; + for (y=0; y<10; ++y) + { + cy=(double)y-4.5; + writespr(x,y, + readspr( (int)floor(5.0+( (cx*cos(ph))+(cy*sin(ph)) )) , + (int)floor(5.0+( (cy*cos(ph))-(cx*sin(ph)) )) )); + } + } + for (i=0; i<10; ++i) + puts(sprite2[i]); +} + +char readspr(x,y) + int x; int y; + +{ printf ("%d %d\n",x,y); + if ((x<10)&&(y<10)&&(x>=0)&&(y>=0)) + return (sprite[x][y]); + return ('.'); +} + +void writespr(x,y,c) + int x; int y; char c; + +{ if ((x<10)&&(y<10)&&(x>=0)&&(y>=0)) + sprite2[x][y]=c; +} + +#ifdef JUNK +th=original angle of (x,y) relative to center of sprite (theta) +ph=angle of rotation (phi) +centerx, centery=coordinates of center of sprite (4.5, 4.5) or (11.5, 11.5) +cx, cy distance from center horizontally, vertically + +distance from center=sqrt((x-centerx)^2 + (y-centery)^2) +th=arccos(cx/distance from center) ..or.. + arcsin(cx/distance from center) (one of these is right, the other may + have to be negated to be corrected) +newx=(centerx)+(distance from center*cos(th-ph) +newy=(centery)+(distance from center*sin(th-ph) + +cos (a-b) = cosacosb+sinasinb +costhcosph+sinthsinph +((cx/d) cos ph) + ((cy/d) sin ph) <- notice how cos(arccos(...))=cx/d, etc. + +sin (a-b) = sina cosb - cosa sinb +((cy/d) cos ph) - ((cx/d) sin ph) + +therefore newx=(centerx)+((cx*(cos ph))+(cy*(sin ph))) + newy=(centery)+((cy*(cos ph))+(cx*(sin ph))) +#endif