## rotatable isometric image

Game development specific discussions.
BasicCoder2
Posts: 3536
Joined: Jan 01, 2009 7:03

### rotatable isometric image

The program creates a list of 3d points abs3D()
The program requires these two images to be downloaded and resaved as bitmaps ambulance4.bmp and top2.bmp respectively.  The list of 3d points abs3D() are rotated by some angle into the rot3D() array and then projected onto a 2d bitmap image.
This bitmap image is then PUT onto the display at the isometric position of the ambulance's 2D position.
The two ambulances use the same set of absolute points to create an image but are rotated by their own angles and have their own 2d positions.
One ambulance is controlled by the arrow keys and the other is controlled by the ASDW keys.
The reason for the TANK label is because it was going to be a tank vehicle but I haven't got around to writing the code to draw a tank.
So it is meant to be a tank image which I will hopefully remedy later.

EDIT: Code modified with suggestions made in next two posts.

Code: Select all

`const ScrW = 1280const ScrH = 480const imgW = 100const imgH = 100'some useful definesConst Pi = 4 * Atn(1)Dim Shared As single TwoPi = 8 * Atn(1)Dim Shared As single RtoD = 180 / Pi   ' radians * RtoD = degreesDim Shared As single DtoR = Pi / 180   ' degrees * DtoR = radiansscreenres ScrW,ScrH,32color rgb(0,0,0),rgb(155,155,255):cls'===========    make cube   ========================dim shared as any ptr cube1cube1 = imagecreate(32,33,rgb(255,0,255))dim as integer x1,y1,x2,y2for i as integer = 1 to 9    read x1,y1,x2,y2    line cube1,(x1,y1)-(x2,y2),rgb(0,0,0)next ipaint cube1,(10,7),rgb(204,167,98),rgb(0,0,0)paint cube1,(23,20),rgb(98,49,49),rgb(0,0,0)paint cube1,(8,19),rgb(158,98,68),rgb(0,0,0)data 16,0,31,8,  31,8,16,15,  15,16, 0,8,  0,8,15,0data 31,24,16,32,  15,32,0,24,  31,8, 31,24,  15,16,15,32,  0,8,0,24'======================================================dim shared as any ptr ambulanceambulance = imagecreate(61,47)bload "ambulance4.bmp",ambulancedim shared as any ptr toptop = imagecreate(110,31)bload "top2.bmp",topdim shared as any ptr image        'hold a image of rotated pointsimage = imagecreate(imgW,imgH)type Point3D    x as single    y as single    z as single    c as ulongend typesub plot3D(x as single,y as single,z as single, c as ulong)    'circle ( (x-y) + imgW/2, (x+y)/2 + z + imgH/2 ),1,c,,,,f    pset image,( (x-y) + imgW/2, (x+y)/2 + z + imgH/2 ),cend sub'dodicat's fast qsort of points according to distanceSub QsortZ(array() As Point3D,begin As Long,Finish As Ulong)    Dim As Long i=begin,j=finish    Dim As Point3D x =array(((I+J)\2))    While I <= J        While array(I).z > X .z:I+=1:Wend        While array(J).z < X .z:J-=1:Wend        If I<=J Then Swap array(I),array(J): I+=1:J-=1    Wend    If J >begin Then QsortZ(array(),begin,J)    If I <Finish Then QsortZ(array(),I,Finish)End Subtype TANK    as single  x          'x position of center of disc    as single  y          'y position of center of disc    as single  dx         'change in x position per cycle    as single  dy         'change in y position per cycle    as single  v          'speed restricted to -1.0 to +1.0    as single  angle     'direction in degreesend typedim shared as integer MAX_DOTSdim shared as integer TOT_DOTSMAX_DOTS = 50000dim shared as TANK t1,t2t1.x = 0t1.y = 0t1.angle = 0t2.x = 100t2.y = 200t2.angle = 0'now dimension array of absolute position of points and array of rotated pointsdim shared as Point3D abs3D(MAX_DOTS)  'absolute positionsdim shared as Point3D rot3D(MAX_DOTS)  'relative positions after any rotationdim as ulong v,v2dim as integer flag,x,y,z' ============   create absolute point positions for ambulance  =========='edge data to draw back,top and bottom pixels of objectdim as integer edgeX(0 to 110),edgeY(0 to 110)for i as integer = 0 to 110    read edgeX(i),edgeY(i)next ifor j as integer = 1 to 46    flag = 0    for i as integer = 0 to 60        v = point(i,j,ambulance)        if v <> rgb(255,0,255)  then            abs3D(TOT_DOTS).x = i  - imgW/4            abs3D(TOT_DOTS).y = 15            abs3D(TOT_DOTS).z = j            abs3D(TOT_DOTS).c = v            if TOT_DOTS < MAX_DOTS then TOT_DOTS = TOT_DOTS + 1                    end if    next inext jfor j as integer = 0 to 46    for i as integer = 0 to 60        v = point(i,j,ambulance)        if v <> rgb(255,0,255) then            abs3D(TOT_DOTS).x = i   - imgW/4            abs3D(TOT_DOTS).y = -15            abs3D(TOT_DOTS).z = j            abs3D(TOT_DOTS).c = v            if TOT_DOTS < MAX_DOTS then TOT_DOTS = TOT_DOTS + 1        end if    next inext jfor i as integer = 0 to 109    for y as integer = -15 to 15        abs3D(TOT_DOTS).x = edgeX(i) -imgW/4        abs3D(TOT_DOTS).y = y        abs3D(TOT_DOTS).z = edgeY(i)        abs3D(TOT_DOTS).c = point(i,y+15,top)        if TOT_DOTS < MAX_DOTS then TOT_DOTS = TOT_DOTS + 1     next ynext i'=====================================================================sub moveTank(t as TANK)    t.dx = cos(t.angle*DtoR) * t.v    t.dy = sin(t.angle*DtoR) * t.v    t.x = t.x + t.dx    t.y = t.y + t.dyend subsub rotatePoints(tt as TANK)  'rotates points by tt.angle        dim as single x,y,z,scale    'rotate    dim as single cosAngleX,sinAngleX,angleX    dim as single cosAngleY,sinAngleY,angleY    dim as single cosAngleZ,sinAngleZ,angleZ        angleZ = tt.angle*DtoR    'angle to rotate points    cosAngleZ = cos(angleZ)    sinAngleZ = sin(angleZ)    scale = 1/sqr(2)        for i as integer = 0 to TOT_DOTS - 1  'rotate each point        'rotate z axis        x = abs3D(i).x        y = abs3D(i).y        z = abs3D(i).z        rot3D(i).x = ((cosAngleZ * x) - (sinAngleZ * y))*scale        rot3D(i).y = ((sinAngleZ * x) + (cosAngleZ * y))*scale        rot3D(i).z = z*0.5        rot3D(i).c = abs3D(i).c    next i        'sort by distance along z axis    '***dodisort***    Qsortz(rot3D(),Lbound(rot3D),TOT_DOTS - 1)    'Qsortz(rot3D(),Lbound(rot3D),Ubound(rot3D))    end subsub drawSprite(t as TANK)        'clear image    line image,(0,0)-(imgW-1,imgH-1),rgb(255,0,255),bf    line image,(0,0)-(imgW-1,imgH-1),rgb(0,0,0),b  'show edge of image        rotatePoints(t)  'rotate abs3D() points by t.angle to produce rot3D() points        'draw rotated points onto image bitmap    for i as integer = 0 to TOT_DOTS - 1         plot3D(rot3D(i).x, rot3D(i).y, rot3D(i).z, rot3D(i).c)    next i        'cartesian to isometric coordinates of image    dim as single tempX = (t.x - t.y) + 640 - imgW/2    dim as single tempY = (t.x + t.y) / 2 + 30 - imgH/2        'put rotated image on display    put (tempX,tempY),image,trans    end subsub drawPoints()    screenlock    cls    'draw isometric cubes    for y as integer = 0 to 24        for x as integer = 0 to 24            put ( (x*16-y*16) + SCRW/2 - 16, (x*16+y*16)/2 + 0 + 30 ),cube1,trans        next x    next y        moveTank(t1)    drawSprite(t1)  'draw rotated pixels onto image and place on screen        moveTank(t2)    drawSprite(t2)  'draw rotate pixels onto image and place on screen        locate 2,2    print t1.angle,t2.angle,TOT_DOTS        screenunlock()end subdim as double now1now1 = timerdo        if timer - now1 > 0.01 then        now1 = timer                drawPoints()                '==================================================        'cursor keys to control tank1        t1.v = 0            if multikey(&H50) then t1.v = -2 'REVERSE        if multikey(&H48) then t1.v =  2 'FORWARD                'rotate around z axis        if multikey(&H4D) then            t1.angle = t1.angle + 1            if t1.angle > 360 then t1.angle = t1.angle - 360        end if        if multikey(&H4B) then            t1.angle = t1.angle - 1            if t1.angle < 0 then t1.angle = t1.angle + 360        end if                '==================================================        'ASDW keys to control tank2        t2.v = 0                if multikey(&H1F) then t2.v = -2 'REVERSE        if multikey(&H11) then t2.v =  2 'FORWARD                'rotate around z axis        if multikey(&H20) then            t2.angle = t2.angle + 1            if t2.angle > 360 then t2.angle = t2.angle - 360        end if        if multikey(&H1E) then            t2.angle = t2.angle - 1            if t2.angle < 0 then t2.angle = t2.angle + 360        end if            end if        sleep 2     loop until multikey(&H01)sleep'coordinates of back, top and front of side edge of ambulance image to join using colors in top2 bitmapdata 0,30, 0,29, 0,28, 0,27, 1,27, 1,26, 1,25, 1,24, 1,23, 1,22, 1,21, 1,20, 1,19, 1,18, 1,19, 1,18, 1,17, 1,16data 1,15, 1,14, 1,13, 1,12, 1,11, 1,10, 1,9, 1,8, 1,7, 1,6, 1,5, 1,4, 1,3, 1,2, 2,1, 3,0data 4,0, 5,0, 6,0, 7,0, 8,0, 9,0, 10,0, 11,0, 12,0, 13,0, 14,0, 15,0, 16,0, 17,0, 18,0, 19,0, 20,0, 21,0data 22,0, 23,0, 24,0, 25,0, 26,0, 27,0, 28,0, 29,0, 30,0, 31,0, 32,0, 33,0, 34,0, 35,0, 36,0, 37,0, 38,0, 39,0data 40,0, 41,0, 42,0, 43,0, 44,0data 44,1, 45,2, 45,3, 46,4, 46,5, 47,6, 47,7, 48,8, 48,9, 49,10, 49,11, 50,12, 51,13, 52,14, 53,14, 54,15, 55,15data 56,16, 57,16, 58,17, 58,18, 58,19, 58,20, 58,21, 58,22, 58,23, 58,24, 58,25, 58,26, 58,27, 59,27, 60,27, 60,28, 60,29, 60,30`
Last edited by BasicCoder2 on Sep 30, 2018 6:54, edited 3 times in total.
Posts: 2047
Joined: May 24, 2007 22:10
Location: The Netherlands

### Re: rotatable isometric image - still has a bug

Looking into it...

Three other things I noticed:
* Change dim as single now1 to dim as double now1 (weird problems on linux otherwise)
* Rotation speed and velocity depend on computer speed and/or compiler options
* 2nd 'tank' moves backwards when I expect forward [W]

I'm not sure yet, but it seems like you have one set of rot3D(...) which are used for both 'tanks'.
The rotation is a relative rotation? E.g. angle change compared to previous rotation.
Sorry, that can be it. abs3D --> rotation --> rot3D

If I disable ***dodisort*** the problem disappears
dodicat
Posts: 6487
Joined: Jan 10, 2006 20:30
Location: Scotland

### Re: rotatable isometric image - still has a bug

If you sort within the array range of i it seems OK

Qsortz(rot3D(),Lbound(rot3D),TOT_DOTS - 1)
BasicCoder2
Posts: 3536
Joined: Jan 01, 2009 7:03

### Re: rotatable isometric image

I will have to find a simple way to solve the frames per second issue for different compiles or computers.
It seems simpler with Javascript which I have been trying to learn where you simply set the milliseconds with

Code: Select all

`setInterval(draw, 10);  // for 10 milliseconds`
Last edited by BasicCoder2 on Sep 30, 2018 6:54, edited 1 time in total.
Posts: 2047
Joined: May 24, 2007 22:10
Location: The Netherlands

### Re: rotatable isometric image - still has a bug

BasicCoder2 wrote:I will have to find a simple way to solve the frames per second issue for different compiles or computers.
It seems simpler with Javascript which I have been trying to learn where you simply set the milliseconds with

Code: Select all

`setInterval(draw, 10);  // for 10 milliseconds`

Do a search for dodicat's fps regulator. He makes useful stuff sometimes :-)

Some other thing. I would separate the the heavy calculations and sorting form the drawing itself. Now everything happens between screenlock/unlock. Although, currently a bit difficult because of 1 rot3D set.

Code: Select all

`   screenlock   calculate & sort   draw tank 1   calculate & sort   draw tank 2   screenunlock()`

To (but not possible now):

Code: Select all

`   calculate & sort   calculate & sort   screenlock   draw tank 1   draw tank 2   screenunlock()`
Last edited by badidea on Sep 29, 2018 22:19, edited 2 times in total.
dodicat
Posts: 6487
Joined: Jan 10, 2006 20:30
Location: Scotland

### Re: rotatable isometric image - still has a bug

My little regulator takes care of the framerate.

Code: Select all

`   const ScrW = 1280const ScrH = 480const imgW = 100const imgH = 100'some useful definesConst Pi = 4 * Atn(1)Dim Shared As single TwoPi = 8 * Atn(1)Dim Shared As single RtoD = 180 / Pi   ' radians * RtoD = degreesDim Shared As single DtoR = Pi / 180   ' degrees * DtoR = radiansdim shared as long fpsscreenres ScrW,ScrH,32color rgb(0,0,0),rgb(155,155,255):cls'===========    make cube   ========================dim shared as any ptr cube1cube1 = imagecreate(32,33,rgb(255,0,255))dim as integer x1,y1,x2,y2for i as integer = 1 to 9    read x1,y1,x2,y2    line cube1,(x1,y1)-(x2,y2),rgb(0,0,0)next ipaint cube1,(10,7),rgb(204,167,98),rgb(0,0,0)paint cube1,(23,20),rgb(98,49,49),rgb(0,0,0)paint cube1,(8,19),rgb(158,98,68),rgb(0,0,0)data 16,0,31,8,  31,8,16,15,  15,16, 0,8,  0,8,15,0data 31,24,16,32,  15,32,0,24,  31,8, 31,24,  15,16,15,32,  0,8,0,24'======================================================dim shared as any ptr ambulanceambulance = imagecreate(61,47)bload "ambulance4.bmp",ambulancedim shared as any ptr toptop = imagecreate(110,31)bload "top2.bmp",topdim shared as any ptr image        'hold a image of rotated pointsimage = imagecreate(imgW,imgH)type Point3D    x as single    y as single    z as single    c as ulongend typesub plot3D(x as single,y as single,z as single, c as ulong)    'circle ( (x-y) + imgW/2, (x+y)/2 + z + imgH/2 ),1,c,,,,f    pset image,( (x-y) + imgW/2, (x+y)/2 + z + imgH/2 ),cend sub'dodicat's fast qsort of points according to distanceSub QsortZ(array() As Point3D,begin As Long,Finish As Ulong)    Dim As Long i=begin,j=finish    Dim As Point3D x =array(((I+J)\2))    While I <= J        While array(I).z > X .z:I+=1:Wend        While array(J).z < X .z:J-=1:Wend        If I<=J Then Swap array(I),array(J): I+=1:J-=1    Wend    If J >begin Then QsortZ(array(),begin,J)    If I <Finish Then QsortZ(array(),I,Finish)End SubFunction Regulate(Byval MyFps As Long,Byref fps As Long) As Long    Static As Double timervalue,lastsleeptime,t3,frames    Var t=Timer    frames+=1    If (t-t3)>=1 Then t3=t:fps=frames:frames=0    Var sleeptime=lastsleeptime+((1/myfps)-T+timervalue)*1000    If sleeptime<1 Then sleeptime=1    lastsleeptime=sleeptime    timervalue=T    Return sleeptimeEnd Functiontype TANK    as single  x          'x position of center of disc    as single  y          'y position of center of disc    as single  dx         'change in x position per cycle    as single  dy         'change in y position per cycle    as single  v          'speed restricted to -1.0 to +1.0    as single  angle     'direction in degreesend typedim shared as integer MAX_DOTSdim shared as integer TOT_DOTSMAX_DOTS = 50000dim shared as TANK t1,t2t1.x = 0t1.y = 0t1.angle = 0t2.x = 100t2.y = 200t2.angle = 0'now dimension array of absolute position of points and array of rotated pointsdim shared as Point3D abs3D(MAX_DOTS)  'absolute positionsdim shared as Point3D rot3D(MAX_DOTS)  'relative positions after any rotationdim as ulong v,v2dim as integer flag,x,y,z' ============   create absolute point positions for ambulance  =========='edge data to draw back,top and bottom pixels of objectdim as integer edgeX(0 to 110),edgeY(0 to 110)for i as integer = 0 to 110    read edgeX(i),edgeY(i)next ifor j as integer = 1 to 46    flag = 0    for i as integer = 0 to 60        v = point(i,j,ambulance)        if v <> rgb(255,0,255)  then            abs3D(TOT_DOTS).x = i  - imgW/4            abs3D(TOT_DOTS).y = 15            abs3D(TOT_DOTS).z = j            abs3D(TOT_DOTS).c = v            if TOT_DOTS < MAX_DOTS then TOT_DOTS = TOT_DOTS + 1                    end if    next inext jfor j as integer = 0 to 46    for i as integer = 0 to 60        v = point(i,j,ambulance)        if v <> rgb(255,0,255) then            abs3D(TOT_DOTS).x = i   - imgW/4            abs3D(TOT_DOTS).y = -15            abs3D(TOT_DOTS).z = j            abs3D(TOT_DOTS).c = v            if TOT_DOTS < MAX_DOTS then TOT_DOTS = TOT_DOTS + 1        end if    next inext jfor i as integer = 0 to 109    for y as integer = -15 to 15        abs3D(TOT_DOTS).x = edgeX(i) -imgW/4        abs3D(TOT_DOTS).y = y        abs3D(TOT_DOTS).z = edgeY(i)        abs3D(TOT_DOTS).c = point(i,y+15,top)        if TOT_DOTS < MAX_DOTS then TOT_DOTS = TOT_DOTS + 1     next ynext i'=====================================================================sub moveTank(t as TANK)    t.dx = cos(t.angle*DtoR) * t.v    t.dy = sin(t.angle*DtoR) * t.v    t.x = t.x + t.dx    t.y = t.y + t.dyend subsub rotatePoints(tt as TANK)  'rotates points by tt.angle        dim as single x,y,z,scale    'rotate    dim as single cosAngleX,sinAngleX,angleX    dim as single cosAngleY,sinAngleY,angleY    dim as single cosAngleZ,sinAngleZ,angleZ        angleZ = tt.angle*DtoR    'angle to rotate points    cosAngleZ = cos(angleZ)    sinAngleZ = sin(angleZ)    scale = 1/sqr(2)        for i as integer = 0 to TOT_DOTS - 1  'rotate each point        'rotate z axis        x = abs3D(i).x        y = abs3D(i).y        z = abs3D(i).z        rot3D(i).x = ((cosAngleZ * x) - (sinAngleZ * y))*scale        rot3D(i).y = ((sinAngleZ * x) + (cosAngleZ * y))*scale        rot3D(i).z = z*0.5        rot3D(i).c = abs3D(i).c    next i        'sort by distance along z axis    '***dodisort***    Qsortz(rot3D(),Lbound(rot3D),TOT_DOTS - 1)    end subsub drawSprite(t as TANK)        'clear image    line image,(0,0)-(imgW-1,imgH-1),rgb(255,0,255),bf    line image,(0,0)-(imgW-1,imgH-1),rgb(0,0,0),b  'show edge of image        rotatePoints(t)  'rotate abs3D() points by t.angle to produce rot3D() points        'draw rotated points onto image bitmap    for i as integer = 0 to TOT_DOTS - 1         plot3D(rot3D(i).x, rot3D(i).y, rot3D(i).z, rot3D(i).c)    next i        'cartesian to isometric coordinates of image    dim as single tempX = (t.x - t.y) + 640 - imgW/2    dim as single tempY = (t.x + t.y) / 2 + 30 - imgH/2        'put rotated image on display    put (tempX,tempY),image,trans    end subsub drawPoints()    screenlock    cls    draw string (20,20),"FRAMERATE  " &fps    'draw isometric cubes    for y as integer = 0 to 24        for x as integer = 0 to 24            put ( (x*16-y*16) + SCRW/2 - 16, (x*16+y*16)/2 + 0 + 30 ),cube1,trans        next x    next y        moveTank(t1)    drawSprite(t1)  'draw rotated pixels onto image and place on screen        moveTank(t2)    drawSprite(t2)  'draw rotate pixels onto image and place on screen        locate 2,2    print t1.angle,t2.angle,TOT_DOTS        screenunlock()end subdim as single now1now1 = timerdo        if timer - now1 > 0.01 then        now1 = timer                drawPoints()                '==================================================        'cursor keys to control tank1        t1.v = 0            if multikey(&H50) then t1.v = -2 'REVERSE        if multikey(&H48) then t1.v =  2 'FORWARD                'rotate around z axis        if multikey(&H4D) then            t1.angle = t1.angle + 1            if t1.angle > 360 then t1.angle = t1.angle - 360        end if        if multikey(&H4B) then            t1.angle = t1.angle - 1            if t1.angle < 0 then t1.angle = t1.angle + 360        end if                '==================================================        'ASDW keys to control tank2        t2.v = 0                if multikey(&H11) then t2.v = -2 'REVERSE        if multikey(&H1F) then t2.v =  2 'FORWARD                'rotate around z axis        if multikey(&H20) then            t2.angle = t2.angle + 1            if t2.angle > 360 then t2.angle = t2.angle - 360        end if        if multikey(&H1E) then            t2.angle = t2.angle - 1            if t2.angle < 0 then t2.angle = t2.angle + 360        end if            end if        sleep regulate(60,fps) '<---------------  set fps here   ' sleep 2     loop until multikey(&H01)sleep'coordinates of back, top and front of side edge of ambulance image to join using colors in top2 bitmapdata 0,30, 0,29, 0,28, 0,27, 1,27, 1,26, 1,25, 1,24, 1,23, 1,22, 1,21, 1,20, 1,19, 1,18, 1,19, 1,18, 1,17, 1,16data 1,15, 1,14, 1,13, 1,12, 1,11, 1,10, 1,9, 1,8, 1,7, 1,6, 1,5, 1,4, 1,3, 1,2, 2,1, 3,0data 4,0, 5,0, 6,0, 7,0, 8,0, 9,0, 10,0, 11,0, 12,0, 13,0, 14,0, 15,0, 16,0, 17,0, 18,0, 19,0, 20,0, 21,0data 22,0, 23,0, 24,0, 25,0, 26,0, 27,0, 28,0, 29,0, 30,0, 31,0, 32,0, 33,0, 34,0, 35,0, 36,0, 37,0, 38,0, 39,0data 40,0, 41,0, 42,0, 43,0, 44,0data 44,1, 45,2, 45,3, 46,4, 46,5, 47,6, 47,7, 48,8, 48,9, 49,10, 49,11, 50,12, 51,13, 52,14, 53,14, 54,15, 55,15data 56,16, 57,16, 58,17, 58,18, 58,19, 58,20, 58,21, 58,22, 58,23, 58,24, 58,25, 58,26, 58,27, 59,27, 60,27, 60,28, 60,29, 60,30 `
Posts: 2047
Joined: May 24, 2007 22:10
Location: The Netherlands

### Re: rotatable isometric image - still has a bug

There it is. No search needed.

dodicat wrote:If you sort within the array range of i it seems OK
Qsortz(rot3D(),Lbound(rot3D),TOT_DOTS - 1)

Also a clear speed improvement now.
Posts: 2047
Joined: May 24, 2007 22:10
Location: The Netherlands

### Re: rotatable isometric image - still has a bug

I ripped out all the shared variables (and the squared tiles accidentally):

Code: Select all

`const ScrW = 1280const ScrH = 480const imgW = 100const imgH = 100'some useful definesConst Pi = 4 * Atn(1)const As single TwoPi = 8 * Atn(1)const As single RtoD = 180 / Pi   ' radians * RtoD = degreesconst As single DtoR = Pi / 180   ' degrees * DtoR = radiansconst as integer MAX_DOTS = 50000'=============================== Types & subroutines ===========================type Point3D   x as single   y as single   z as single   c as ulongend typesub plot3D(pImage as any ptr, x as single,y as single,z as single, c as ulong)   'circle ( (x-y) + imgW/2, (x+y)/2 + z + imgH/2 ),1,c,,,,f   pset pImage,( (x-y) + imgW/2, (x+y)/2 + z + imgH/2 ),cend sub'dodicat's fast qsort of points according to distanceSub QsortZ(array() As Point3D,begin As Long,Finish As Ulong)   Dim As Long i=begin,j=finish   Dim As Point3D x =array(((I+J)\2))   While I <= J      While array(I).z > X .z:I+=1:Wend      While array(J).z < X .z:J-=1:Wend      If I<=J Then Swap array(I),array(J): I+=1:J-=1   Wend   If J >begin Then QsortZ(array(),begin,J)   If I <Finish Then QsortZ(array(),I,Finish)End Subtype TANK   as single  x          'x position of center of disc   as single  y          'y position of center of disc   as single  angle      'direction in degrees   as single  dx         'change in x position per cycle   as single  dy         'change in y position per cycle   as single  v          'speed restricted to -1.0 to +1.0end type' ============   create absolute point positions for ambulance  =========='edge data to draw back,top and bottom pixels of objectsub read_calc_points(pAmbu as any ptr, pTop as any ptr, abs3D() as Point3D, byref numDots as integer)   dim as ulong v,v2   dim as integer x,y,z,flag   dim as integer edgeX(0 to 110),edgeY(0 to 110)   for i as integer = 0 to 110      read edgeX(i),edgeY(i)   next i   for j as integer = 1 to 46      flag = 0      for i as integer = 0 to 60         v = point(i,j,pAmbu)         if v <> rgb(255,0,255)  then            abs3D(numDots).x = i  - imgW/4            abs3D(numDots).y = 15            abs3D(numDots).z = j            abs3D(numDots).c = v            if numDots < MAX_DOTS then numDots += 1                    end if      next i   next j   for j as integer = 0 to 46      for i as integer = 0 to 60         v = point(i,j,pAmbu)         if v <> rgb(255,0,255) then            abs3D(numDots).x = i   - imgW/4            abs3D(numDots).y = -15            abs3D(numDots).z = j            abs3D(numDots).c = v            if numDots < MAX_DOTS then numDots += 1         end if      next i   next j   for i as integer = 0 to 109      for y as integer = -15 to 15         abs3D(numDots).x = edgeX(i) -imgW/4         abs3D(numDots).y = y         abs3D(numDots).z = edgeY(i)         abs3D(numDots).c = point(i,y+15,pTop)         if numDots < MAX_DOTS then numDots += 1      next y   next iend sub'=====================================================================sub moveTank(t as TANK)    t.dx = cos(t.angle*DtoR) * t.v    t.dy = sin(t.angle*DtoR) * t.v    t.x = t.x + t.dx    t.y = t.y + t.dyend sub'rotates points by tt.anglesub rotatePoints(tt as TANK, rot3D() as Point3D, abs3D() as Point3D, byref numDots as integer)   dim as single x,y,z,scale   'rotate   dim as single cosAngleX,sinAngleX,angleX   dim as single cosAngleY,sinAngleY,angleY   dim as single cosAngleZ,sinAngleZ,angleZ   'angle to rotate points   angleZ = tt.angle*DtoR   cosAngleZ = cos(angleZ)   sinAngleZ = sin(angleZ)   scale = 1/sqr(2)   'rotate each point   for i as integer = 0 to numDots - 1      'rotate z axis      x = abs3D(i).x      y = abs3D(i).y      z = abs3D(i).z      rot3D(i).x = ((cosAngleZ * x) - (sinAngleZ * y))*scale      rot3D(i).y = ((sinAngleZ * x) + (cosAngleZ * y))*scale      rot3D(i).z = z * 0.5      rot3D(i).c = abs3D(i).c   next i   'sort by distance along z axis   '***dodisort***   Qsortz(rot3D(), 0, numDots-1)end subsub drawSprite(pImage as any ptr, t as TANK, rot3D() as Point3D, abs3D() as Point3D, numDots as integer)   'clear image   line pImage, (0,0)-(imgW-1,imgH-1),rgb(255,0,255),bf   line pImage, (0,0)-(imgW-1,imgH-1),rgb(0,0,0),b  'show edge of image   rotatePoints(t, rot3D(), abs3D(), numDots)  'rotate abs3D() points by t.angle to produce rot3D() points   'draw rotated points onto image bitmap   for i as integer = 0 to numDots - 1      plot3D(pImage, rot3D(i).x, rot3D(i).y, rot3D(i).z, rot3D(i).c)   next i   'cartesian to isometric coordinates of image   dim as single tempX = (t.x - t.y) + 640 - imgW/2   dim as single tempY = (t.x + t.y) / 2 + 30 - imgH/2   'put rotated image on display   put (tempX,tempY), pImage, transend subsub drawPoints(pImage as any ptr, t1 as TANK, t2 as TANK, rot3D() as Point3D, abs3D() as Point3D, numDots as integer)   screenlock   cls   moveTank(t1)   drawSprite(pImage, t1, rot3D(), abs3D(), numDots)  'draw rotated pixels onto image and place on screen   moveTank(t2)   drawSprite(pImage, t2, rot3D(), abs3D(), numDots)  'draw rotate pixels onto image and place on screen   locate 2,2   print t1.angle, t2.angle, numDots   screenunlock()end sub'================================== Main init ==================================dim as integer totalDotsdim as TANK t1 = type (0, 0, 0) 'x, y, angledim as TANK t2 = type(100, 200, 0)screenres ScrW,ScrH,32color rgb(0,0,0),rgb(155,155,255):clsdim as any ptr pAmbu = imagecreate(61,47)bload "ambulance4.bmp", pAmbudim as any ptr pTop = imagecreate(110,31)bload "top2.bmp", pTopdim as any ptr pImage = imagecreate(imgW,imgH) 'image of rotated points'now dimension array of absolute position of points and array of rotated pointsdim shared as Point3D abs3D(MAX_DOTS)  'absolute positionsdim shared as Point3D rot3D(MAX_DOTS)  'relative positions after any rotationread_calc_points(pAmbu, pTop, abs3D(), totalDots)'================================== Main loop ==================================dim as double now1 = timerdo   if timer - now1 > 0.01 then      now1 = timer      drawPoints(pImage, t1, t2, rot3D(), abs3D(), totalDots)      '==================================================      'cursor keys to control tank1      t1.v = 0      if multikey(&H50) then t1.v = -2 'REVERSE      if multikey(&H48) then t1.v =  2 'FORWARD      'rotate around z axis      if multikey(&H4D) then         t1.angle = t1.angle + 1         if t1.angle > 360 then t1.angle = t1.angle - 360      end if      if multikey(&H4B) then         t1.angle = t1.angle - 1         if t1.angle < 0 then t1.angle = t1.angle + 360      end if            '==================================================      'ASDW keys to control tank2      t2.v = 0      if multikey(&H11) then t2.v = -2 'REVERSE      if multikey(&H1F) then t2.v =  2 'FORWARD      'rotate around z axis      if multikey(&H20) then         t2.angle = t2.angle + 1         if t2.angle > 360 then t2.angle = t2.angle - 360      end if      if multikey(&H1E) then         t2.angle = t2.angle - 1         if t2.angle < 0 then t2.angle = t2.angle + 360      end if   end if   sleep 2loop until multikey(&H01)sleep'coordinates of back, top and front of side edge of ambulance image to join using colors in top2 bitmapdata 0,30, 0,29, 0,28, 0,27, 1,27, 1,26, 1,25, 1,24, 1,23, 1,22, 1,21, 1,20, 1,19, 1,18, 1,19, 1,18, 1,17, 1,16data 1,15, 1,14, 1,13, 1,12, 1,11, 1,10, 1,9, 1,8, 1,7, 1,6, 1,5, 1,4, 1,3, 1,2, 2,1, 3,0data 4,0, 5,0, 6,0, 7,0, 8,0, 9,0, 10,0, 11,0, 12,0, 13,0, 14,0, 15,0, 16,0, 17,0, 18,0, 19,0, 20,0, 21,0data 22,0, 23,0, 24,0, 25,0, 26,0, 27,0, 28,0, 29,0, 30,0, 31,0, 32,0, 33,0, 34,0, 35,0, 36,0, 37,0, 38,0, 39,0data 40,0, 41,0, 42,0, 43,0, 44,0data 44,1, 45,2, 45,3, 46,4, 46,5, 47,6, 47,7, 48,8, 48,9, 49,10, 49,11, 50,12, 51,13, 52,14, 53,14, 54,15, 55,15data 56,16, 57,16, 58,17, 58,18, 58,19, 58,20, 58,21, 58,22, 58,23, 58,24, 58,25, 58,26, 58,27, 59,27, 60,27, 60,28, 60,29, 60,30`
BasicCoder2
Posts: 3536
Joined: Jan 01, 2009 7:03

### Re: rotatable isometric image

dodicat wrote:My little regulator takes care of the framerate.

Thanks dodicat I will leave it in the evolving program.
Last edited by BasicCoder2 on Sep 30, 2018 6:54, edited 1 time in total.
BasicCoder2
Posts: 3536
Joined: Jan 01, 2009 7:03

### Re: rotatable isometric image

badidea wrote:I ripped out all the shared variables (and the squared tiles accidentally):

Yep removing shared variables is a good thing.
There are many things "to do" next, but too numerous to list here, starting with a list of points for a tank object and probably having them in their own file so they don't have to be created from bitmaps. Then I can provide an isometric display of the tank game program.
BasicCoder2
Posts: 3536
Joined: Jan 01, 2009 7:03

### Re: rotatable isometric image

Made some 3dPoint data of a simple tank for testing. The turret can be rotated independently to tank rotation. 