program rotatetank3;
{
version 3
Rotates a 32x32 tile with 0 as the transparent color
Press Q or q or esc to quit.
Keypad controls rotation and movement
+ = clockwise rotation
- = counterclockwise rotation
7 8 9
4 5 6
1 2 3
The tank will rotate to direction prior to movement
if not already in that orientation
There isn't any screen range checking done. PTCgraph clips by default
}
uses
ptccrt,
ptcgraph,
Math;
const
MaxCol = 31;
type
MapIconType = array[0..maxcol, 0..maxcol] of byte;
const
desert01: MapIconType = ((2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2),
(2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2),
(2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2),
(2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 26, 2, 2, 2, 2, 26, 2, 2, 2, 2, 2, 2, 22, 2, 22, 2, 2, 2, 2, 2),
(2, 2, 2, 2, 2, 2, 2, 29, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2),
(2, 2, 2, 2, 2, 26, 29, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 22, 2, 2, 2, 2),
(2, 2, 2, 2, 2, 112, 23, 23, 23, 2, 2, 2, 2, 2, 2, 2, 2, 29, 2, 26, 29, 29, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2),
(2, 2, 2, 2, 26, 29, 26, 2, 2, 2, 2, 2, 2, 2, 2, 29, 29, 29, 24, 2, 2, 29, 29, 112, 29, 2, 2, 2, 2, 2, 2, 2),
(2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 24, 26, 24, 24, 24, 2, 2, 26, 24, 24, 2, 2, 2, 2, 2, 2, 2),
(2, 2, 2, 2, 23, 26, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 24, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2),
(2, 2, 2, 2, 23, 2, 2, 2, 2, 2, 22, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2),
(2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2),
(2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2),
(2, 2, 2, 2, 2, 2, 2, 22, 2, 2, 2, 2, 26, 2, 2, 2, 2, 2, 2, 2, 2, 2, 29, 29, 29, 2, 2, 2, 2, 2, 2, 2),
(2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 26, 111, 2, 2, 112, 29, 2, 2, 2, 2, 2),
(2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 26, 2, 2, 2, 2, 111, 29, 2, 2, 22, 22, 29, 2, 2, 2, 2, 2),
(2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 22, 2, 2, 19, 2, 2, 2, 2, 22, 29, 112, 29, 2, 2, 2),
(2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 26, 22, 22, 22, 2, 2, 2),
(2, 2, 2, 2, 2, 2, 2, 2, 2, 23, 23, 2, 2, 29, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2),
(2, 2, 2, 2, 2, 2, 2, 23, 2, 2, 2, 2, 2, 29, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 26),
(2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 19, 19, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2),
(2, 2, 2, 2, 2, 2, 26, 2, 2, 2, 2, 2, 2, 19, 26, 22, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2),
(2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 22, 2, 2, 2, 2, 2, 2, 2, 2, 2),
(2, 2, 2, 26, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2),
(2, 2, 2, 2, 2, 2, 2, 2, 2, 29, 22, 26, 22, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 22, 2, 2, 26, 2, 2),
(2, 2, 2, 2, 29, 29, 2, 2, 2, 112, 19, 26, 29, 22, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2),
(2, 2, 29, 112, 22, 19, 19, 2, 29, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2),
(2, 2, 19, 2, 2, 2, 2, 2, 2, 2, 2, 111, 2, 2, 2, 2, 2, 2, 2, 2, 2, 22, 2, 112, 29, 112, 29, 2, 2, 2, 2, 2),
(2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 113, 29, 2, 2, 2, 2, 29, 2, 2, 2, 2),
(2, 2, 2, 2, 22, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 22, 22, 2, 29, 2, 2, 2),
(2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 22, 2, 2, 2, 2, 2, 29, 22, 22, 2, 2, 22, 2, 112, 2, 2, 2),
(2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2));
TheTank: MapIconType = ((0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41, 41, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 26, 26, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 26, 26, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 26, 26, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 26, 26, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 20, 20, 20, 26, 26, 20, 20,
20, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 20, 190, 190, 190, 26, 26, 190,
190, 190, 20, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
(0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 190, 190, 190, 190, 190, 26, 26,
190, 190, 190, 190, 190, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0),
(0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 190, 190, 190, 190, 190, 26, 26,
190, 190, 190, 190, 190, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0),
(0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 190, 190, 190, 190, 190, 26, 26,
190, 190, 190, 190, 190, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0),
(0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 190, 190, 190, 190, 21, 26, 26,
21, 190, 190, 190, 190, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0),
(0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 190, 190, 190, 21, 23, 23, 23,
23, 21, 190, 190, 190, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0),
(0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 190, 190, 21, 23, 23, 23, 23, 23,
23, 21, 190, 190, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0),
(0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 190, 190, 21, 23, 1, 1, 1, 1, 23,
21, 190, 190, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0),
(0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 190, 190, 21, 23, 1, 1, 1, 1, 23,
21, 190, 190, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0),
(0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 190, 190, 21, 23, 1, 1, 1, 1, 23,
21, 190, 190, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0),
(0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 190, 190, 21, 23, 1, 1, 1, 1, 23,
21, 190, 190, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0),
(0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 190, 190, 21, 23, 23, 23, 23, 23,
23, 21, 190, 190, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0),
(0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 190, 190, 190, 21, 21, 21, 21,
21, 21, 190, 190, 190, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0),
(0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 190, 190, 190, 190, 190, 190, 190,
190, 190, 190, 190, 190, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0),
(0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 190, 190, 190, 190, 190, 190, 190,
190, 190, 190, 190, 190, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0),
(0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 190, 190, 190, 190, 190, 190, 190,
190, 190, 190, 190, 190, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0),
(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 20, 20, 20, 20, 20, 20, 20,
20, 20, 20, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 20, 20, 20, 20, 20, 20, 20,
20, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 20, 20, 20, 20, 20, 20, 20,
20, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0));
type
TSinglePoint = record
x, y: single;
end;
linedata = record
P: Tsinglepoint;
color: byte;
end;
matrixType = array[0..maxcol, 0..maxcol] of linedata;
var
I: integer;
ch: char;
lastdegree: integer;
cx, cy: integer; // center x and center y
b: MatrixType;
gmode, gdriver: smallint;
procedure SetUpTank(x, y: integer);
var
rr, cc: integer;
begin
// setup initial tank coord matrix
for rr := 0 to maxcol do
begin
for cc := 0 to maxcol do
begin
b[rr, cc].color := TheTank[rr, cc];
b[rr, cc].p.x := x + cc;
b[rr, cc].p.y := y + rr;
end;
end;
cx := X + 16; // x + 1/2 matrix width
cy := y + 16; // y + 1/2 matrix depth
end;
procedure drawcell(xx, yy: integer);
var
startx, rr, cc: integer;
begin
startx := xx;
for rr := 0 to maxcol do
begin
xx := startX;
for cc := 0 to maxcol do
begin
putpixel(xx, yy, desert01[rr, cc]);
Inc(xx);
end;
Inc(yy);
end;
end;
procedure rotatepoint(var P: Tsinglepoint; degrees, centerx, centerY: float);
var
newx, newy, angle: float;
cx, cy, y, x: single;
begin
angle := degTorad(degrees);
cx := centerx;
cy := centery;
x := p.x;
y := p.y;
x := x - cx;
Y := y - cy;
newx := (x * cos(angle)) - (y * sin(angle));
newy := (x * sin(angle)) + (y * cos(angle));
newx := newx + cx;
newy := newy + cy;
p.x := newx;
p.y := newy;
end;
procedure moveobject(var M: MatrixType; Xc, Yc: integer);
var
r, c: integer;
begin
for r := 0 to maxcol do
for c := 0 to maxcol do
begin
M[r, c].p.x := M[r, c].p.x + Xc;
M[r, c].p.Y := M[r, c].p.Y + Yc;
end;
end;
procedure rotateobject(var M: Matrixtype; Degrees, CenterX, CenterY: integer);
var
r, c: integer;
Row, Column: integer;
begin
for r := 0 to maxcol do
for c := 0 to maxcol do
begin
rotatepoint(M[r, c].p, degrees, centerx, centery);
Column := round(M[r, c].p.x) mod (maxcol + 1); // map x,y to background tile pixel
Row := round(m[r, c].p.y) mod (maxcol + 1);
// redraw background
putpixel(round(m[r, c].p.x), round(m[r, c].p.y), desert01[Row, Column]);
//overlay tank on screen
if m[r, c].color <> 0 then
putpixel(round(M[r, c].p.x), round(m[r, c].p.y), m[r, c].color);
end;
end;
procedure showobject(M: MatrixType);
var
r, c: integer;
begin
for r := 0 to maxcol do
for c := 0 to maxcol do
if m[r, c].color <> 0 then
putpixel(round(M[r, c].p.x), round(m[r, c].p.y), m[r, c].color);
end;
procedure DrawBackground;
var
ScreenX, ScreenY: integer;
r, c: integer;
begin
screenY := 0;
for r := 0 to 5 do
begin
screenx := 0;
for c := 0 to 8 do
begin
drawcell(screenx, screeny);
Inc(screenx, maxcol + 1);
end;
Inc(screeny, maxcol + 1);
end;
end;
begin
gdriver := vesa; // this is for my system - check documentation for use of initgraph
Gmode := installusermode(320, 200, 256, 1, 8000, 6000);
WindowTitle := 'Tank Rotation';
initgraph(gdriver, gmode, '');
SetupTank(160, 128);
DrawBackground;
lastdegree := 0;
ShowObject(b);
repeat
i := 0;
ch := readkey;
case ch of
'-': i := -1; // counter clockwise
'+': i := 1; // clockwise
'3': begin
if lastdegree <> 135 then
begin
if lastdegree > 135 then i := -1;
if lastdegree < 135 then i := 1;
if lastdegree > 315 then // 316 to 360
begin
i := 1;
repeat
rotateobject(b, i, cx, cy);
LastDegree := lastDegree + i;
delay(10);
until lastdegree = 360;
lastdegree := 0;
end;
repeat
rotateobject(b, i, cx, cy);
LastDegree := lastDegree + i;
delay(10);
until lastdegree = 135;
end;
Inc(cx);
Inc(cy);
i := 0;
moveobject(b, 1, 1);
end;
'1': begin
if lastdegree <> 225 then
begin
if lastdegree = 0 then lastdegree := 360;
if lastdegree > 225 then i := -1
else
i := 1;
if lastdegree <= 45 then
begin
i := -1;
repeat
rotateobject(b, i, cx, cy);
LastDegree := lastDegree + i;
delay(10);
until lastdegree = 0;
i := -1;
lastdegree := 360;
end;
repeat
rotateobject(b, i, cx, cy);
LastDegree := lastDegree + i;
delay(10);
until lastdegree = 225;
end
else
i := 0;
Dec(cx);
Inc(cy);
moveobject(b, -1, 1);
end;
'9': begin
if lastdegree <> 45 then
begin
if lastdegree < 45 then i := 1;
if (lastdegree > 45) and (lastdegree <= 225) then
i := -1;
if lastdegree > 225 then
begin
i := 1;
repeat
rotateobject(b, i, cx, cy);
LastDegree := lastDegree + i;
delay(10);
until lastdegree = 360;
lastdegree := 0;
// i := 1;
end;
repeat
rotateobject(b, i, cx, cy);
LastDegree := lastDegree + i;
delay(10);
until lastdegree = 45;
;
end;
Inc(cx);
Dec(cy);
I := 0;
moveobject(b, 1, -1);
end;
'7': begin
if lastdegree = 0 then lastdegree := 360;
if lastdegree <= 90 then lastdegree := 360 + lastdegree;
if lastdegree <> 315 then
begin
if (lastdegree > 315) then
i := -1
else
i := 1;
repeat
rotateobject(b, i, cx, cy);
LastDegree := lastDegree + i;
delay(10);
until (lastdegree = 315);
end;
i := 0;
Dec(cx);
Dec(cy);
moveobject(b, -1, -1);
end;
'8': begin
// rotate to face position
if (lastdegree <> 0) and (lastdegree <> 360) then
begin
if lastdegree > 180 then i := 1
else
i := -1;
repeat
rotateobject(b, i, cx, cy);
LastDegree := lastDegree + i;
delay(10);
until (lastdegree = 0) or (lastdegree = 360);
end;
Dec(cy);
moveobject(b, 0, -1);
i := 0;
end;
'2': begin
if (lastdegree <> 180) then
begin
if lastdegree > 180 then i := -1
else
i := 1;
repeat
rotateobject(b, i, cx, cy);
LastDegree := lastDegree + i;
delay(10);
until (lastdegree = 180);
end;
Inc(cy);
moveobject(b, 0, 1);
i := 0;
end;
'4': begin
if lastdegree <> 270 then
begin
if lastdegree < 180 then lastdegree := 360 + lastdegree;
if lastdegree > 270 then i := -1
else
i := 1;
repeat
rotateobject(b, i, cx, cy);
LastDegree := lastDegree + i;
delay(10);
until (lastdegree = 270);
end;
Dec(cx);
moveobject(b, -1, 0);
i := 0;
end;
'6': begin
if lastdegree <> 90 then
begin
if lastdegree > 90 then i := -1
else
i := 1;
repeat
rotateobject(b, i, cx, cy);
LastDegree := lastDegree + i;
delay(10);
until (lastdegree = 90);
end;
i := 0;
Inc(cx);
moveobject(b, 1, 0);
end;
end;
lastdegree := lastdegree + i;
if LastDegree < 1 then lastdegree := 360;
if lastdegree >= 360 then lastdegree := 0;
RotateObject(b, i, cx, cy);
while keypressed do readkey; // eat up extra keypresses
until (ch = 'q') or (ch = 'Q') or (ch = chr(27));
closegraph;
end.