Author Topic: Isometric Mapping Demo  (Read 10653 times)

0 Members and 1 Guest are viewing this topic.

Offline SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3972
    • View Profile
    • Steve’s QB64 Archive Forum
Isometric Mapping Demo
« on: November 19, 2019, 06:25:58 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:

Code: QB64: [Select]
  1. SCREEN _NEWIMAGE(1024, 720, 32)
  2.  
  3. DIM SHARED GridSize AS INTEGER
  4. CONST Red = &HFFFF0000, Green = &HFF00FF00
  5. GridSize = 16 'My demo map is only going to be 16x16 pixels
  6.  
  7.  
  8. DIM grid(9, 9) AS _BYTE 'create a grid to layout our map
  9.  
  10. FOR i = 0 TO 9 'and let's create that map.  It's just going to be 4 walls and a floor...
  11.     grid(i, 0) = 1 'wall
  12.     grid(i, 9) = 1
  13.     grid(0, i) = 1
  14.     grid(9, i) = 1
  15.  
  16. FOR y = 1 TO 8
  17.     FOR x = 1 TO 8
  18.         grid(x, y) = 2 'floor
  19.     NEXT
  20.  
  21.  
  22. 'Now, let's just draw grids one at a time to compare.
  23. _PRINTSTRING (100, 80), "Normal 2D grid"
  24. FOR y = 0 TO 9
  25.     FOR x = 0 TO 9
  26.         'normal grid first
  27.         IF grid(x, y) = 1 THEN Kolor = Red ELSE Kolor = Green
  28.         xpos = x * GridSize + 100: ypos = y * GridSize + 100
  29.         xpos2 = xpos + GridSize: ypos2 = ypos + GridSize
  30.         LINE (xpos, ypos)-(xpos2, ypos2), Kolor, BF
  31.         LINE (xpos, ypos)-(xpos2, ypos2), &HFFFFFFFF, B
  32.         'and that's all it takes for the normal grid.  Can't get any simpler for 2d maps!
  33.     NEXT
  34.  
  35.  
  36. _PRINTSTRING (350, 80), "Normal 2D grid in Isometic Perspective"
  37. FOR y = 0 TO 9
  38.     FOR x = 0 TO 9
  39.         'And now, let's do the same thing with our isometic map.
  40.         IF grid(x, y) = 1 THEN Kolor = Red ELSE Kolor = Green
  41.         xpos = x * GridSize + 100: ypos = y * GridSize + 100
  42.         xpos2 = xpos + GridSize: ypos2 = ypos + GridSize
  43.         IsoLine xpos, ypos, xpos2, ypos2, 500, 0, Kolor
  44.         'And that's basically all the takes to rotate our map to make it a 2D isometic perspective
  45.     NEXT
  46.  
  47.  
  48. _PRINTSTRING (350, 360), "Normal 2D grid in 3D Isometic Perspective"
  49. FOR y = 0 TO 9
  50.     FOR x = 0 TO 9
  51.         'And here, I'm going to make it a 3D isometic map
  52.         IF grid(x, y) = 1 THEN Kolor = Red ELSE Kolor = Green
  53.         IF grid(x, y) = 1 THEN z = 16 ELSE z = 0 'Give my walls a height of 16, for a cube
  54.  
  55.         xpos = x * GridSize + 100: ypos = y * GridSize + 100
  56.         xpos2 = xpos + GridSize: ypos2 = ypos + GridSize
  57.         IsoLine3D xpos, ypos, xpos2, ypos2, z, 500, 300, Kolor
  58.     NEXT
  59.  
  60.  
  61.  
  62.  
  63.  
  64.  
  65.  
  66.  
  67.  
  68. FUNCTION CX2I (x AS LONG, y AS LONG) 'Convert Cartesian X To Isometic coordinates
  69.     CX2I = x - y
  70.  
  71. FUNCTION CY2I (x AS LONG, y AS LONG) 'Convert Cartesian Y To Isometic coordinates
  72.     CY2I = (x + y) / 2
  73.  
  74. SUB IsoLine (x, y, x2, y2, xoffset, yoffset, kolor AS _UNSIGNED LONG)
  75.     'since we're drawing a diamond and not a square box, we can't use Line BF.
  76.     'We have to manually down the 4 points of the line.
  77.     LINE (CX2I(x, y) + xoffset, CY2I(x, y) + yoffset)-(CX2I(x2, y) + xoffset, CY2I(x2, y) + yoffset), kolor
  78.     LINE -(CX2I(x2, y2) + xoffset, CY2I(x2, y2) + yoffset), kolor
  79.     LINE -(CX2I(x, y2) + xoffset, CY2I(x, y2) + yoffset), kolor
  80.     LINE -(CX2I(x, y) + xoffset, CY2I(x, y) + yoffset), kolor
  81.     PAINT (CX2I(x, y) + xoffset, CY2I(x, y) + 4), kolor 'and fill the diamond solid
  82.     LINE (CX2I(x, y) + xoffset, CY2I(x, y) + yoffset)-(CX2I(x2, y) + xoffset, CY2I(x2, y) + yoffset), &HFFFFFFFF
  83.     LINE -(CX2I(x2, y2) + xoffset, CY2I(x2, y2) + yoffset), &HFFFFFFFF
  84.     LINE -(CX2I(x, y2) + xoffset, CY2I(x, y2) + yoffset), &HFFFFFFFF
  85.     LINE -(CX2I(x, y) + xoffset, CY2I(x, y) + yoffset), &HFFFFFFFF
  86.  
  87. SUB IsoLine3D (x, y, x2, y2, z, xoffset, yoffset, kolor AS _UNSIGNED LONG)
  88.     'Like IsoLine, we're going to have to draw our lines manually.
  89.     'only in this case, we also need a Z coordinate to tell us how THICK/TALL/HIGH to make our tile
  90.  
  91.     'Let's just do all the math first this time.
  92.     'We need to turn those 4 normal points into 4 isometric points (x, y, x1, y1)
  93.  
  94.     TempX1 = CX2I(x, y) + xoffset: TempY1 = CY2I(x, y) + yoffset
  95.     TempX2 = CX2I(x2, y) + xoffset: TempY2 = CY2I(x2, y) + yoffset
  96.     TempX3 = CX2I(x2, y2) + xoffset: TempY3 = CY2I(x2, y2) + yoffset
  97.     TempX4 = CX2I(x, y2) + xoffset: TempY4 = CY2I(x, y2) + yoffset
  98.  
  99.     'The top
  100.     LINE (TempX1, TempY1 - z)-(TempX2, TempY2 - z), kolor 'draw the diamond
  101.     LINE -(TempX3, TempY3 - z), kolor
  102.     LINE -(TempX4, TempY4 - z), kolor
  103.     LINE -(TempX1, TempY1 - z), kolor
  104.     PAINT (TempX1, TempY1 - z + 4), kolor 'and fill the diamond solid
  105.     LINE (TempX1, TempY1 - z)-(TempX2, TempY2 - z), -1 'and redraw the grid
  106.     LINE -(TempX3, TempY3 - z), -1
  107.     LINE -(TempX4, TempY4 - z), -1
  108.     LINE -(TempX1, TempY1 - z), -1
  109.  
  110.     IF z <> 0 THEN 'no need to draw any height, if there isn't any.
  111.         'the left side
  112.         LINE (TempX4, TempY4 - z)-(TempX4, TempY4), kolor 'draw it
  113.         LINE -(TempX3, TempY3), kolor
  114.         LINE -(TempX3, TempY3 - z), kolor
  115.         LINE -(TempX4, TempY4 - z), kolor
  116.         PAINT (TempX3 - 2, TempY3 - z + 2), kolor 'fill it
  117.         LINE (TempX4, TempY4 - z)-(TempX4, TempY4), -1 'redraw the grid lines
  118.         LINE -(TempX3, TempY3), -1
  119.         LINE -(TempX3, TempY3 - z), -1
  120.         LINE -(TempX4, TempY4 - z), -1
  121.         'and then for the right side
  122.         LINE (TempX3, TempY3 - z)-(TempX3, TempY3), kolor 'draw it
  123.         LINE -(TempX2, TempY2), kolor
  124.         LINE -(TempX2, TempY2 - z), kolor
  125.         LINE -(TempX3, TempY3 - z), kolor
  126.         PAINT (TempX3 + 2, TempY3 - z + 2), kolor 'fill it
  127.         LINE (TempX3, TempY3 - z)-(TempX3, TempY3), -1 'redraw the grid lines
  128.         LINE -(TempX2, TempY2), -1
  129.         LINE -(TempX2, TempY2 - z), -1
  130.         LINE -(TempX3, TempY3 - z), -1
  131.     END IF
  132.  
  133.  
  134.  


It's a simple enough little demo with nothing more than a green floor and red walls, but I think it highlights the process well enough for us.

My question for all you math folks out there: What's a simple little formula to use to get a paint point inside those boxes?  I really don't care for the hardcoded + 2 which I used, as it can paint the wrong things if the user draws a box too small for it.  There should be a simple, failsafe method which we can use that won't paint out of bounds, like this little demo does, but I'll be danged if I can come up with it at the moment.  It's too early in the morning, and I haven't drunk enough coffee, for my brain to work good enough for any more math already...
https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!

Offline STxAxTIC

  • Library Staff
  • Forum Resident
  • Posts: 1091
  • he lives
    • View Profile
Re: Isometric Mapping Demo
« Reply #1 on: November 19, 2019, 08:47:55 am »
My first thought on this is - what's the end result supposed to look like? That totally influences the beginning...

... Because insert spiel about doing things in proper 3D ... but forgetting that for a second ...

It seems that getting the pseudo-height correct isn't going to be the main problem, but is instead going to be plotting. If you have monsters, projectiles, speech bubbles, or whatever else, the question is how to do draw them in the proper layers so you don't have overlaps? The quick solution I see is to stick your data layers together like a cake, and then slice the scene not horizontally, but in the so-called z-direction (int the screen) from background to foreground. That way, you can just do the painter's algorithm, which is especially easy because of the locked perspective.




You're not done when it works, you're done when it's right.

Offline SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3972
    • View Profile
    • Steve’s QB64 Archive Forum
Re: Isometric Mapping Demo
« Reply #2 on: November 19, 2019, 09:09:07 am »
You draw it farthest to closest, or, in this case, from 0 to 9.

No need for a spiel on “proper 3D” here; that’s not what we’re doing.  All we’re shooting for here is something like the screenshot below, which is a nice isometric map:

275010AF-6679-4398-A79B-CE7258424A43.png
* 275010AF-6679-4398-A79B-CE7258424A43.png (Filesize: 2.08 MB, Dimensions: 1536x2048, Views: 354)
https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!

Offline STxAxTIC

  • Library Staff
  • Forum Resident
  • Posts: 1091
  • he lives
    • View Profile
Re: Isometric Mapping Demo
« Reply #3 on: November 19, 2019, 09:27:43 am »
If you were just shooting for the screenshot, the project must be finished.

What was the question again?
You're not done when it works, you're done when it's right.

Offline Cobalt

  • QB64 Developer
  • Forum Resident
  • Posts: 878
  • At 60 I become highly radioactive!
    • View Profile
Re: Isometric Mapping Demo
« Reply #4 on: November 19, 2019, 10:26:09 am »
set your grid size to 10 and you get some issues in the Iso3d view. and the height doesn't seem to be affected by changing the gridsize either.
GridGlitch.png
* GridGlitch.png (Filesize: 2.95 KB, Dimensions: 383x168, Views: 265)
Granted after becoming radioactive I only have a half-life!

Offline SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3972
    • View Profile
    • Steve’s QB64 Archive Forum
Re: Isometric Mapping Demo
« Reply #5 on: November 19, 2019, 10:33:31 am »
set your grid size to 10 and you get some issues in the Iso3d view. and the height doesn't seem to be affected by changing the gridsize either.

That’s from the current paint fill routine, as I mentioned above.  I’ll work in a different fill method later, which won’t suffer from that problem.  ;)

(Honestly, I think all I really need to do is draw the grid in a separate step and not during the line drawing/painting process.  It’s those stray white lines that act as a boundary, which I think is the issue.  I’ll do some testing later to see if my assumption is correct, or not.). ;)
https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!

Offline Cobalt

  • QB64 Developer
  • Forum Resident
  • Posts: 878
  • At 60 I become highly radioactive!
    • View Profile
Re: Isometric Mapping Demo
« Reply #6 on: November 19, 2019, 11:23:41 am »
Ah, Rereading that its clicking now, must have just been not quite awake the first time through(nightmares of Frost Blossom keeping me up! XD ).

Wonder how hard it would be to make a LINE()-(),,BF that could be used for NON-Square shapes made, which would probably be easier with a TRIANGLE()-()-(), LINECOLOR, FILLCOLOR kind of thing, where FILLCOLOR would act like BF in the line statement so if a fill color is present it would fill otherwise it would just be lines. Would take 2 calls to make a "box" but might be easier in the end. maybe manipulating the image memory directly to fill it.
« Last Edit: November 19, 2019, 12:05:22 pm by Cobalt »
Granted after becoming radioactive I only have a half-life!

Offline Petr

  • Forum Resident
  • Posts: 1720
  • The best code is the DNA of the hops.
    • View Profile
Re: Isometric Mapping Demo
« Reply #7 on: November 19, 2019, 01:21:56 pm »
Hi Steve.
Thank you for a nice demonstration. I would solve the textures differently. I would use MAPTRIANGLE 2D because it uses the same coordinate system as normal 2D graphics. I have to study your code deeply because I still miss the Z-axis calculation, even though I'm on steps... At the moment, I have come across the ceiling of my abilities.

I do now some experiments with this total pseudo 3D code:

Code: QB64: [Select]
  1. 'Pseudo3D Cube
  2. SCREEN _NEWIMAGE(640, 480, 32)
  3. 'rotation point is 320, 240. Rotation radius is 100.
  4. 'is needed 8* X, 8* Y, 8* Z
  5.  
  6. DIM X(8), Y(8), Z(8)
  7.  
  8.  
  9. texture = _NEWIMAGE(100, 100, 32)
  10. _DEST texture
  11. CLS , &H0DEED0C4
  12. FOR f = 0 TO 100 STEP 20
  13.     LINE (50 + f, 50 + f)-(50 - f, 50 - f), _RGB32(RND * 255, RND * 255, RND * 255), B
  14. r1 = 100
  15. r2 = 50
  16.  
  17.     i$ = INKEY$
  18.     SELECT CASE i$
  19.         CASE " ": fill = fill + 1: IF fill > 1 THEN fill = 0
  20.         CASE "+": r1 = r1 + 1: r2 = r2 + 1
  21.         CASE "-": r1 = r1 - 1: r2 = r2 - 1
  22.         CASE "*": XX1 = XX1 + 1
  23.         CASE "/": YY1 = YY1 + 1
  24.         CASE "9": XX2 = XX2 + 1
  25.         CASE "8": YY2 = YY2 + 1
  26.  
  27.         CASE "7": XX1 = XX1 - 1
  28.         CASE "6": YY1 = YY1 - 1
  29.         CASE "5": XX2 = XX2 - 1
  30.         CASE "4": YY2 = YY2 - 1
  31.  
  32.  
  33.  
  34.     END SELECT
  35.  
  36.     FOR L = 1 TO 4
  37.         angle = angle + _PI / 2
  38.         X(L) = XX1 + 320 + SIN(angle + r) * r1
  39.         Y(L) = YY1 + 170 + COS(angle + r) * r2
  40.  
  41.         X(4 + L) = XX2 + 320 + SIN(angle + r) * r1
  42.         Y(4 + L) = YY2 + 240 + COS(angle + r) * r2
  43.     NEXT
  44.     angle = 0
  45.     CLS
  46.     SELECT CASE fill
  47.         CASE 0
  48.             FOR d = 1 TO 3
  49.                 LINE (X(d), Y(d))-(X(d + 1), Y(d + 1))
  50.                 LINE (X(d + 4), Y(d + 4))-(X(d + 5), Y(d + 5))
  51.                 LINE (X(d), Y(d))-(X(d + 4), Y(d + 4))
  52.             NEXT
  53.             LINE (X(1), Y(1))-(X(4), Y(4))
  54.             LINE (X(5), Y(5))-(X(8), Y(8))
  55.             LINE (X(4), Y(4))-(X(8), Y(8))
  56.  
  57.         CASE 1
  58.             FOR d = 1 TO 3
  59.                 '   EXIT FOR
  60.                 _MAPTRIANGLE (0, 0)-(99, 0)-(0, 99), texture TO(X(d), Y(d))-(X(d + 1), Y(d + 1))-(X(d + 4), Y(d + 4))
  61.                 _MAPTRIANGLE (99, 0)-(0, 99)-(99, 99), texture TO(X(d + 1), Y(d + 1))-(X(d + 4), Y(d + 4))-(X(d + 5), Y(d + 5))
  62.  
  63.  
  64.             NEXT
  65.  
  66.  
  67.             _MAPTRIANGLE (0, 0)-(99, 0)-(0, 99), texture TO(X(1), Y(1))-(X(4), Y(4))-(X(5), Y(5)) 'last side
  68.             _MAPTRIANGLE (99, 0)-(0, 99)-(99, 99), texture TO(X(4), Y(4))-(X(5), Y(5))-(X(8), Y(8)) 'last side
  69.  
  70.             _MAPTRIANGLE (0, 0)-(99, 0)-(0, 99), texture TO(X(1), Y(1))-(X(4), Y(4))-(X(2), Y(2)) 'ceil
  71.             _MAPTRIANGLE (99, 0)-(0, 99)-(99, 99), texture TO(X(4), Y(4))-(X(2), Y(2))-(X(3), Y(3))
  72.  
  73.             _MAPTRIANGLE (0, 0)-(99, 0)-(0, 99), texture TO(X(5), Y(5))-(X(8), Y(8))-(X(6), Y(6)) 'bottom
  74.             _MAPTRIANGLE (99, 0)-(0, 99)-(99, 99), texture TO(X(8), Y(8))-(X(6), Y(6))-(X(7), Y(7))
  75.  
  76.  
  77.     END SELECT
  78.     r = r + .01
  79.     _DISPLAY
  80.     _LIMIT 25
  81.  

(Use space, +,-,*,/,9,8,7,6,5,4)

Of course, this is just an experimental program, nothing miraculous is expected of it.

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Isometric Mapping Demo
« Reply #8 on: November 19, 2019, 03:30:38 pm »
Nice work Petr! That space option is really cool!

I am trying to find your post on your start to real 3D rendering that STxAxTIC made comment to a month or 2 ago?

Offline Petr

  • Forum Resident
  • Posts: 1720
  • The best code is the DNA of the hops.
    • View Profile
Re: Isometric Mapping Demo
« Reply #9 on: November 19, 2019, 04:21:17 pm »
This? It use hardware images + hardware MAPTRIANGLE https://www.qb64.org/forum/index.php?topic=300.msg102623#msg102623

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Isometric Mapping Demo
« Reply #10 on: November 19, 2019, 08:22:09 pm »
Steve could you just stack cube images, back to front, bottom to top?

Offline Lucky_Strikez

  • Newbie
  • Posts: 7
    • View Profile
Re: Isometric Mapping Demo
« Reply #11 on: November 19, 2019, 09:43:28 pm »
Super cool work guys! Keep it going

Offline AndyA

  • Newbie
  • Posts: 73
    • View Profile
Re: Isometric Mapping Demo
« Reply #12 on: November 19, 2019, 11:29:02 pm »
@Steve

The easiest way to do isometric cubes that I can think of is to:

1) Draw an isometric cube, paint the three iso-squares facing viewer with desired color.

2) GET the image.

3) PUT the cubes using grid coordinates plus appropriate X/Y offsets.

Using this method allows you to create as many different colored iso-cubes as desired at run time.

The other thing is that using PUT is a whole lot faster than painting each individual cube face.

Just my 2 cents :)


Offline SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3972
    • View Profile
    • Steve’s QB64 Archive Forum
Re: Isometric Mapping Demo
« Reply #13 on: November 19, 2019, 11:43:39 pm »
What I’ll probably end up using is just a bunch of textures for the walls and then _MAPTRIANGLE them to the proper coordinates.  It seems the fastest/easiest way to go.
https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Isometric Mapping Demo
« Reply #14 on: November 20, 2019, 12:48:37 am »
Forget PAINT use fquad (fill quadrilateral) which is just a double ftri (fill triangle):
Code: QB64: [Select]
  1.  
  2. 'this text was fetched
  3. SUB ftri (x1, y1, x2, y2, x3, y3, K AS _UNSIGNED LONG)
  4.     DIM a&
  5.     a& = _NEWIMAGE(1, 1, 32)
  6.     _DEST a&
  7.     PSET (0, 0), K
  8.     _DEST 0
  9.     _MAPTRIANGLE _SEAMLESS(0, 0)-(0, 0)-(0, 0), a& TO(x1, y1)-(x2, y2)-(x3, y3)
  10.     _FREEIMAGE a& '<<< this is important!
  11.  
  12. 'need 4 non linear points (not all on 1 line) list them clockwise so x2, y2 is diagonal of x4, y4
  13. SUB fquad (x1, y1, x2, y2, x3, y3, x4, y4, K AS _UNSIGNED LONG)
  14.     ftri x1, y1, x2, y2, x4, y4, K
  15.     ftri x3, y3, x2, y2, x4, y4, K
  16.  

Here is demo: https://www.qb64.org/forum/index.php?topic=1905.0
« Last Edit: November 20, 2019, 01:05:45 am by bplus »