09-23-2023, 05:50 AM
I was thinking of working up a simple little game which utilizes isometric mapping to create a pseudo-3d environment, and I couldn't find a demo of anything similar on the forums. So, in the spirit of "can do", I did, and here's what I came up with some time ago and now retweaked and improved for QB64PE:
Code: (Select All)
SCREEN _NEWIMAGE(1024, 720, 32)
_SCREENMOVE _MIDDLE
DIM SHARED GridSize AS INTEGER
DIM Kolor AS _UNSIGNED LONG
CONST Red = &HFFFF0000, Green = &HFF00FF00
GridSize = 16 'My demo map is only going to be 16x16 pixels
DIM grid(9, 9) AS _BYTE 'create a grid to layout our map
FOR i = 0 TO 9 'and let's create that map. It's just going to be 4 walls and a floor...
grid(i, 0) = 1 'wall
grid(i, 9) = 1
grid(0, i) = 1
grid(9, i) = 1
NEXT
FOR y = 1 TO 8
FOR x = 1 TO 8
grid(x, y) = 2 'floor
NEXT
NEXT
'Now, let's just draw grids one at a time to compare.
_PRINTSTRING (100, 80), "Normal 2D grid"
FOR y = 0 TO 9
FOR x = 0 TO 9
'normal grid first
IF grid(x, y) = 1 THEN Kolor = Red ELSE Kolor = Green
xpos = x * GridSize + 100: ypos = y * GridSize + 100
xpos2 = xpos + GridSize: ypos2 = ypos + GridSize
LINE (xpos, ypos)-(xpos2, ypos2), Kolor, BF
LINE (xpos, ypos)-(xpos2, ypos2), &HFFFFFFFF, B
'and that's all it takes for the normal grid. Can't get any simpler for 2d maps!
NEXT
NEXT
SLEEP
_PRINTSTRING (350, 80), "Normal 2D grid in Isometic Perspective"
FOR y = 0 TO 9
FOR x = 0 TO 9
'And now, let's do the same thing with our isometic map.
IF grid(x, y) = 1 THEN Kolor = Red ELSE Kolor = Green
xpos = x * GridSize + 100: ypos = y * GridSize + 100
xpos2 = xpos + GridSize: ypos2 = ypos + GridSize
IsoLine xpos, ypos, xpos2, ypos2, 500, 0, Kolor
'And that's basically all the takes to rotate our map to make it a 2D isometic perspective
NEXT
NEXT
SLEEP
_PRINTSTRING (350, 360), "Normal 2D grid in 3D Isometic Perspective"
FOR y = 0 TO 9
FOR x = 0 TO 9
'And here, I'm going to make it a 3D isometic map
IF grid(x, y) = 1 THEN Kolor = Red ELSE Kolor = Green
IF grid(x, y) = 1 THEN z = 16 ELSE z = 0 'Give my walls a height of 16, for a cube
xpos = x * GridSize + 100: ypos = y * GridSize + 100
xpos2 = xpos + GridSize: ypos2 = ypos + GridSize
IsoLine3D xpos, ypos, xpos2, ypos2, z, 500, 300, Kolor
NEXT
NEXT
FUNCTION CX2I (x AS LONG, y AS LONG) 'Convert Cartesian X To Isometic coordinates
CX2I = x - y
END FUNCTION
FUNCTION CY2I (x AS LONG, y AS LONG) 'Convert Cartesian Y To Isometic coordinates
CY2I = (x + y) / 2
END FUNCTION
SUB IsoLine (x, y, x2, y2, xoffset, yoffset, kolor AS _UNSIGNED LONG)
'since we're drawing a diamond and not a square box, we can't use Line BF.
'We have to manually down the 4 points of the line.
LINE (CX2I(x, y) + xoffset, CY2I(x, y) + yoffset)-(CX2I(x2, y) + xoffset, CY2I(x2, y) + yoffset), kolor
LINE -(CX2I(x2, y2) + xoffset, CY2I(x2, y2) + yoffset), kolor
LINE -(CX2I(x, y2) + xoffset, CY2I(x, y2) + yoffset), kolor
LINE -(CX2I(x, y) + xoffset, CY2I(x, y) + yoffset), kolor
PAINT (CX2I(x, y) + xoffset, CY2I(x, y) + 4), kolor 'and fill the diamond solid
LINE (CX2I(x, y) + xoffset, CY2I(x, y) + yoffset)-(CX2I(x2, y) + xoffset, CY2I(x2, y) + yoffset), &HFFFFFFFF
LINE -(CX2I(x2, y2) + xoffset, CY2I(x2, y2) + yoffset), &HFFFFFFFF
LINE -(CX2I(x, y2) + xoffset, CY2I(x, y2) + yoffset), &HFFFFFFFF
LINE -(CX2I(x, y) + xoffset, CY2I(x, y) + yoffset), &HFFFFFFFF
END SUB
SUB IsoLine3D (x, y, x2, y2, z, xoffset, yoffset, kolor AS _UNSIGNED LONG)
'Like IsoLine, we're going to have to draw our lines manually.
'only in this case, we also need a Z coordinate to tell us how THICK/TALL/HIGH to make our tile
'Let's just do all the math first this time.
'We need to turn those 4 normal points into 4 isometric points (x, y, x1, y1)
TempX1 = CX2I(x, y) + xoffset: TempY1 = CY2I(x, y) + yoffset
TempX2 = CX2I(x2, y) + xoffset: TempY2 = CY2I(x2, y) + yoffset
TempX3 = CX2I(x2, y2) + xoffset: TempY3 = CY2I(x2, y2) + yoffset
TempX4 = CX2I(x, y2) + xoffset: TempY4 = CY2I(x, y2) + yoffset
'The top
FillQuad TempX1, TempY1 - z, TempX2, TempY2 - z, TempX3, TempY3 - z, TempX4, TempY4 - z, kolor
LINE (TempX1, TempY1 - z)-(TempX2, TempY2 - z), -1 'and redraw the grid
LINE -(TempX3, TempY3 - z), -1
LINE -(TempX4, TempY4 - z), -1
LINE -(TempX1, TempY1 - z), -1
IF z <> 0 THEN 'no need to draw any height, if there isn't any.
'the left side
FillQuad TempX4, TempY4 - z, TempX4, TempY4, TempX3, TempY3, TempX3, TempY3 - z, kolor
LINE (TempX4, TempY4 - z)-(TempX4, TempY4), -1 'redraw the grid lines
LINE -(TempX3, TempY3), -1
LINE -(TempX3, TempY3 - z), -1
LINE -(TempX4, TempY4 - z), -1
'and then for the right side
FillQuad TempX3, TempY3 - z, TempX3, TempY3, TempX2, TempY2, TempX2, TempY2 - z, kolor
LINE (TempX3, TempY3 - z)-(TempX3, TempY3), -1 'redraw the grid lines
LINE -(TempX2, TempY2), -1
LINE -(TempX2, TempY2 - z), -1
LINE -(TempX3, TempY3 - z), -1
END IF
END SUB
SUB FillTriangle (x1, y1, x2, y2, x3, y3, K AS _UNSIGNED LONG)
DIM D AS LONG
STATIC a&
D = _DEST
IF a& = 0 THEN a& = _NEWIMAGE(1, 1, 32): _DONTBLEND a& '<< fix ??
_DEST a&
PSET (0, 0), K
_DEST D
_MAPTRIANGLE _SEAMLESS(0, 0)-(0, 0)-(0, 0), a& TO(x1, y1)-(x2, y2)-(x3, y3)
END SUB
SUB FillQuad (x1, y1, x2, y2, x3, y3, x4, y4, K AS _UNSIGNED LONG)
FillTriangle x1, y1, x2, y2, x3, y3, K
FillTriangle x3, y3, x4, y4, x1, y1, K
END SUB