Author Topic: Tile Editor that exports out DATA statements for games that use READ/DATA  (Read 5938 times)

0 Members and 1 Guest are viewing this topic.

Offline Abacus

  • Newbie
  • Posts: 12
  • I like programming in QB64, C, & Python
    • View Profile
I'm sitting at work and doing some Old School programming in a new version QBASIC called QB64. I wrote this test program to save a 6x10 grid of DATA statements to a file. The reason I made this test program because I later will make a Graphical Tile Editor. The Tile Editor will be very basic and will help me build this Old School style RPG game in QB64 using READ/DATA statements.

The main problem I faced was when using READ/DATA in QB64 or QBASIC, the data could not be changed in the DATA statements. Therefor, I wrote this test program to get around that problem.

The test was successful and can move on to make the Tile Editor. This will allow me to not type out large DATA statements by hand. Instead, I will be able to use a mouse to pick a color square and fill it on a grid to build a map.  I can then export a file of DATA statements to import into the game project.

Sure, I could do this in a different program language such as C/C++ or use a powerful game engine to build a game easier...still, that takes way the fun challenge to do this all in QB64/QBASIC.

So, I wanted to share a screen shot of my test program.

I will share the test code...although, there will be lots of changes on this programming adventure!

Code: QB64: [Select]
  1. 'This program creates a 6x10 grid of numbers with the word DATA
  2. 'in front of each line. The program then saves the 6x10 grid to
  3. 'a file called map_test.bi. The reason for this test program is
  4. 'so that I can later build a graphical editor for tile based games.
  5. 'The games will use READ/DATA statements and the DATA in a READ/
  6. 'DATA statement can't be changed. That lead to creating this pro-
  7. 'gram. The exported file can be added to the game project and
  8. 'the user will not have to type large DATA statements; instead,
  9. 'with the graphical interface they will be able to layout color
  10. 'squarse using the mouse in the grid. Example: A green squre will
  11. 'be for grass...ie., etc.
  12. '
  13. 'By: Abacus 5/8/2021
  14.  
  15.  
  16. 'declare some arrays
  17. Dim a1$(10)
  18. Dim a2$(10)
  19. Dim a3$(10)
  20. Dim a4$(10)
  21. Dim a5$(10)
  22. Dim a6$(10)
  23.  
  24.  
  25. 'this will be used to place the word DATA in front
  26. name$ = "DATA"
  27.  
  28. 'loading the arrays with numerical valuse for the grid
  29. a1$(1) = "1": a2$(1) = "2": a3$(1) = "0": a4$(1) = "0": a5$(1) = "0": a6$(1) = "0":
  30. a1$(2) = "0": a2$(2) = "0": a3$(2) = "3": a4$(2) = "0": a5$(2) = "0": a6$(2) = "1":
  31. a1$(3) = "1": a2$(3) = "0": a3$(3) = "0": a4$(3) = "0": a5$(3) = "0": a6$(3) = "0":
  32. a1$(4) = "0": a2$(4) = "0": a3$(4) = "0": a4$(4) = "0": a5$(4) = "0": a6$(4) = "0":
  33. a1$(5) = "0": a2$(5) = "0": a3$(5) = "0": a4$(5) = "0": a5$(5) = "0": a6$(5) = "2":
  34. a1$(6) = "0": a2$(6) = "0": a3$(6) = "0": a4$(6) = "5": a5$(6) = "0": a6$(6) = "0":
  35. a1$(7) = "0": a2$(7) = "0": a3$(7) = "0": a4$(7) = "0": a5$(7) = "0": a6$(7) = "0":
  36. a1$(8) = "0": a2$(8) = "0": a3$(8) = "0": a4$(8) = "0": a5$(8) = "0": a6$(8) = "0":
  37. a1$(9) = "0": a2$(9) = "0": a3$(9) = "0": a4$(9) = "0": a5$(9) = "0": a6$(9) = "0":
  38. a1$(10) = "0": a2$(10) = "0": a3$(10) = "0": a4$(10) = "0": a5$(10) = "0": a6$(10) = "0":
  39.  
  40. 'explains what the program is doing
  41. Print " This program displays a 6x10 grid of DATA statments and"
  42. Print " will write this information to a file named map_test.bi"
  43. Print " Hit the Spcaebar to start."
  44. 'wait for keypress
  45.  
  46. 'a loop to print all the numbers out correctly in the grid format
  47. For clr = 1 To 10
  48.  
  49.     Print name$; " "; a1$(clr); ","; a2$(clr); ","; a3$(clr); ",";
  50.     Print a4$(clr); ","; a5$(clr); ","; a6$(clr)
  51. Next clr
  52.  
  53. 'tells that the file is being saved
  54. Print "Saving to file..."
  55.  
  56.  
  57. 'open a file for output
  58. Open "map_test.bi" For Output As #1
  59.  
  60. 'a loop to save the grid to a file in the correct format
  61. For clr = 1 To 10
  62.     Print #1, name$; " "; a1$(clr); ","; a2$(clr); ","; a3$(clr); ",";
  63.     Print #1, a4$(clr); ","; a5$(clr); ","; a6$(clr)
  64. Next clr
  65.  
  66. 'close file
  67.  
  68. 'tells that the file is saved
  69. Print "Save complete!": Sleep 1: Print: Print "Goodbye!": Sleep 1
  70.  
  71.  
  72. 'end of program
  73.  
  74.  
Export_DATA_Grid.jpg
* Export_DATA_Grid.jpg (Filesize: 580.11 KB, Dimensions: 1366x768, Views: 224)
« Last Edit: June 12, 2021, 02:13:39 am by Abacus »
If obj1x% > obj2x% And obj1y% > obj2y% Then
    If obj1x% < obj2x% + tilewidth% And obj1y% < obj2y% + tilelength% Then Print: Print "collisoin"
End If

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Welcome @Abacus,

Great way to get your feet wet!

Data statements are great for saving/processing data inside your .bas file but if you save data to another file you don't need "Data" because you will likely read the file data directly into an array.
« Last Edit: May 08, 2021, 12:33:33 pm by bplus »

Offline Abacus

  • Newbie
  • Posts: 12
  • I like programming in QB64, C, & Python
    • View Profile
Thanks @bplus

Cool! I can dig that understanding for sure all the way. I have messed with some assembly code and binary file formats and such. I just want to build this Tile editor with READ/DATA in mind at a very beginner level. I welcome your feedback and support. Thank you for responding to my post as well. It makes me happy! :)
« Last Edit: May 08, 2021, 12:45:52 pm by Abacus »
If obj1x% > obj2x% And obj1y% > obj2y% Then
    If obj1x% < obj2x% + tilewidth% And obj1y% < obj2y% + tilelength% Then Print: Print "collisoin"
End If

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Hey, I like the idea of mouse selection for tiles, I've done that for for colors when designing tiles.

If you have less than 256 tiles you could load your entire map into a long string of ASCII characters, using 1 char per tile then you could save several maps as strings in a single file. Read the string from the file and use mid$() for getting individual tiles to load a map array.  Something to think about :)

Offline Abacus

  • Newbie
  • Posts: 12
  • I like programming in QB64, C, & Python
    • View Profile
@bplus  That takes me back to my BBS and DOS 6.22 days working on a 9600 baud modem and sending an image in that format. I will for sure keep your recommendation in mind.

Thank you!!!

Much love and respect!
If obj1x% > obj2x% And obj1y% > obj2y% Then
    If obj1x% < obj2x% + tilewidth% And obj1y% < obj2y% + tilelength% Then Print: Print "collisoin"
End If

Offline Abacus

  • Newbie
  • Posts: 12
  • I like programming in QB64, C, & Python
    • View Profile
@bplus and I had a fun conversation in messages. I shared a program example that lends to the old way in QBASIC and explains a little more of why I posted the example code for my Tile Editor project. @bplus felt we should share these code examples and I agreed. So, here are the code examples. I hope people that don't know about this find it interesting or helpful.

----------------------
Messages
----------------------

------------------------------------
Well, I did a test and it worked.

This part is in a bi file called test.bi

Code: QB64: [Select]
  1.  
  2. Data 0,0,1,0,0
  3. Data 0,0,1,0,0
  4. Data 1,1,1,1,1
  5. Data 0,0,1,0,0
  6. Data 0,0,1,0,0
  7.  


Here is a test program that used the DATA statement in the .bi file and saves the graphic to a binary image file.

Code: QB64: [Select]
  1.  
  2. '$INCLUDE: 'test.bi'
  3.  
  4. 'put sprite information onscreen for capture
  5. For y = 1 To 5: For x = 1 To 5
  6.         Read icolor%: PSet (x, y), icolor%
  7. Next x: Next y
  8. 'capture the sprite
  9. Dim sprite%(25)
  10. Get (1, 1)-(5, 5), sprite%() 'tile now captured in sprite% array
  11. Def Seg = VarSeg(sprite%(0))
  12. BSave "sprite.bsv", VarPtr(sprite%(0)), 25
  13.  
  14.  
  15. 'cover the screen with the tile image
  16. For x = 0 To 319 Step 5: For y = 0 To 199 Step 5
  17.         Put (x, y), sprite%()
  18. Next y: Next x
  19.  


I think in my tile editor I will use both save methods. A save to Data statements for a map and a save for tiles or sprites.

Have a good day!

--------------------------------------
Hi Mike,

Finally got some time to play with your code. It works for me but took me awhile to find where sprite file went (in QB64.exe folder).

I have two more Methods to do same thing for your consideration.

First a modified .bi file, same design different colors for my own tests of screen 12 capabilities:

Code: QB64: [Select]
  1. sprite:
  2. Data 12,12,9,12,12
  3. Data 12,12,9,12,12
  4. Data 14,14,14,14,14
  5. Data 12,12,9,12,12
  6. Data 12,12,9,12,12
  7.  

notice the sprite: line label, this is what I was really curious about to see if RESTORE will work in the .BI file, apparently it works fine.

Here is the bas source for redrawing sprite right from BI, over and over again using a SUB.
That is Method 1 and I admit kind of crude and inefficient. I just wanted to see if it would work.

The 2nd is the modern way to create and capture an image and use over and over as demo'd here:

Code: QB64: [Select]
  1. _Title "Test sprite bi, press any key for 2 methods of sprite display " 'b+ 2021-05-10
  2.  
  3.  
  4. '$include: 'sprite.bi'
  5.  
  6. '  Method 1
  7. 'cover the screen with the tile image
  8. For x = 0 To 639 Step 5: For y = 0 To 479 Step 5
  9.         drawSprite x, y
  10. Next y: Next x
  11.  
  12. ' Method 2 of sprite drawing: draw one, capture in container spriteImg handle,
  13. '  use _putimage (x, y), spriteImg, 0    ' x, y top left corner of rectangle to place image
  14. ' to put anywhere on screen we want 0 is the handle for the screen
  15.  
  16. ' setup to contain sprite image
  17.  
  18. Dim spriteImg As Long  ' sprite handle
  19.  
  20. spriteImg = _NewImage(5, 5, 12)  ' container size and color pallette  12 is like Screen 12's
  21.  
  22. drawSprite 0, 0 ' use first method to draw one sprite in upper left corner
  23. _PutImage , 0, spriteImg, (0, 0)-(4, 4) ' capture image in a spriteImg container
  24. '           (0, 0)-(4, 4) is the source on screen rectangle that we just drew one of                  
  25. For x = 320 To 639 Step 5: For y = 240 To 479 Step 5 ' fill bottom right corner
  26.         _PutImage (x, y), spriteImg ' now place image any where on screen
  27. Next y: Next x
  28.  
  29. '  Sub for Method 1  reads bi file and draws image every time its called
  30. Sub drawSprite (x As Integer, y As Integer)
  31.     Restore sprite ' <<<<<<<<<<<<<<<<<<<<<<<<<<<< here is what I wanted to test from Bi
  32.     For yy = 0 To 4
  33.         For xx = 0 To 4
  34.             Read icolor%: PSet (xx + x, yy + y), icolor%
  35.         Next
  36.     Next
  37.  


The first screen full is drawing from BI file over and over until filled.
press any key

The second screen fills the bottom right corner screen with the image with spriteImg handle
press key again and done.

Mike with your permission I'd like to post these two codes of ours on forum so people might learn past and present ways.

What do you think?

-----------------------------------

So, that was pretty much what we discussed and I will add this last bit of code that shows how to load the sprite.bsv file.

Code: QB64: [Select]
  1.  
  2. DIM sprite%(25)
  3. DEF SEG = VARSEG(sprite%(0))
  4. BLOAD "sprite.bsv", VARPTR(sprite%(0))
  5. FOR x = 0 TO 319 STEP 5
  6.     FOR y = 0 TO 199 STEP 5
  7.         PUT (x, y), sprite%()
  8.     NEXT y
  9.  
  10.  

Well, that's about it for today.

Thanks for viewing!
« Last Edit: May 11, 2021, 04:00:12 am by Abacus »
If obj1x% > obj2x% And obj1y% > obj2y% Then
    If obj1x% < obj2x% + tilewidth% And obj1y% < obj2y% + tilelength% Then Print: Print "collisoin"
End If

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Yeah, I always wondered what the BLOAD BSAVE keywords were used for in the old QB4.5 manuals, nice to see them illustrated by Mike. I think the DEFSEG = VARSEG might have been off putting for me back then.

A little error correction line 19 was supposed to say
Code: QB64: [Select]
  1. Dim spriteImg As Long  ' sprite handle
but ran fine with the miss.
« Last Edit: May 10, 2021, 11:30:19 pm by bplus »

Offline Abacus

  • Newbie
  • Posts: 12
  • I like programming in QB64, C, & Python
    • View Profile
@bplus I'll edit and make the new correction.
If obj1x% > obj2x% And obj1y% > obj2y% Then
    If obj1x% < obj2x% + tilewidth% And obj1y% < obj2y% + tilelength% Then Print: Print "collisoin"
End If

Offline Abacus

  • Newbie
  • Posts: 12
  • I like programming in QB64, C, & Python
    • View Profile
Well, I made it clear there will be changes for my test code on this project. I never plan to use that many arrays for this project, but it got the ball rolling. Last night, I made a quick test program to use the MID$() function and the concept will reduce the a1$(10)...a2$(10)...a3$(10)...etc down to one array. I like to share this very raw concept change on this project with you guys/gals now.

Code: QB64: [Select]
  1. Dim datnum$(5)
  2. Dim tile_num$
  3. Dim dat_name$
  4. Dim num%
  5.  
  6. datnum$(1) = "0,0,0,0,0"
  7. dat_name$ = "DATA "
  8. tile_num$ = "0"
  9. num% = 0
  10.  
  11. Print dat_name$; datnum$(1) 'Print before change
  12.  
  13. 'Use MID$() to make change
  14. tile_num$ = "5"
  15. num% = 3
  16.  
  17. Mid$(datnum$(1), num%) = tile_num$
  18.  
  19. Print dat_name$; datnum$(1) 'Print after change
  20.  
  21. 'Write info to a file
  22.  
  23. 'open a file for output
  24. Open "mid_test.bi" For Output As #1
  25. Print #1, dat_name$; datnum$(1) 'Write to file after change
  26.  

Thanks for viewing!
If obj1x% > obj2x% And obj1y% > obj2y% Then
    If obj1x% < obj2x% + tilewidth% And obj1y% < obj2y% + tilelength% Then Print: Print "collisoin"
End If

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Hey just what I suggested in Reply #3 of this thread :)

Great minds think alike.

To elaborate more of that reply, you can save the strings for many arrays into single file and more importantly load and save from an array of strings.

The next thing you might want to think about is names for tiles and names for strings, it's easier to do things by name than by number. So maybe another array to translate tile name to tile number or vice versa, and another array to translate sprite array name to number and back.

Then if you want different sized sprites, maybe even some not square you can save width and height with names.
Some more things to think ahead about :)
« Last Edit: May 14, 2021, 12:37:28 pm by bplus »

Offline 191Brian

  • Newbie
  • Posts: 91
    • View Profile
    • My Itch page
Hi

When I did my version of a tile map editor in QB64 https://191brian.itch.io/qb64-tile-map-editor which is for image tiles rather than coloured blocks it uses the image file names in the map files rather than having to cross reference codes to files/image names. It outputs the maps as files instead of data statements.
Brian ...

Offline Abacus

  • Newbie
  • Posts: 12
  • I like programming in QB64, C, & Python
    • View Profile
@bplus Well, like I said in messages...it's been awhile since I played around with QBASIC and QB64 has brought me the joy to play with it again. I think so far choosing this project in an old school fashion has brought me much joy on building it thus far. I hope by keeping this post alive it will show the process of one concept building to the next for a final design and allow other people struggling with programming in any language to think about each challenge as small parts and will find a solution for each part until the final visualization of the project in mind is complete.

@191Brian thanks for sharing, I will check it out! I should add though....I am doing READ/DATA in this old fashion way for a challenge on this project for myself. I will though, not use Assembly for mouse such as int 33h for the mouse interrupt unless it is requested. I have my goal and vision set on this project. Thank you so much for sharing your info and I will for sure check it out!
« Last Edit: May 14, 2021, 01:22:15 pm by Abacus »
If obj1x% > obj2x% And obj1y% > obj2y% Then
    If obj1x% < obj2x% + tilewidth% And obj1y% < obj2y% + tilelength% Then Print: Print "collisoin"
End If

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
I am glad you are enjoying return to Basic, I sure did!

Yes @191Brian  tile editor specially first version (I dont know which one he linked) is easy to follow and on same line of thinking as @Abacus, I think :)

Brain do you have link here of your first editor? I forgot thread title.

Update: I found it here:
https://www.qb64.org/forum/index.php?topic=3680.0

I like to show where Brian started from before it took off into making real games from it.

Johnno started and I picked up on Tiles Editing I think it's still in top 10 posts most views or most replies?
https://www.qb64.org/forum/index.php?topic=313.0
« Last Edit: May 14, 2021, 01:25:59 pm by bplus »

Offline Abacus

  • Newbie
  • Posts: 12
  • I like programming in QB64, C, & Python
    • View Profile
@bplus Thanks for the links! It will be something for me to look over with respect to @191Brian on the subject and others that wish to chime in on the discussion for this project. I would like to add my project is not an absolute way for whatever in code or games I show to build from it. I hope in the end, that stays true and clear in this project  (^_^).
« Last Edit: May 14, 2021, 01:52:30 pm by Abacus »
If obj1x% > obj2x% And obj1y% > obj2y% Then
    If obj1x% < obj2x% + tilewidth% And obj1y% < obj2y% + tilelength% Then Print: Print "collisoin"
End If

Offline Abacus

  • Newbie
  • Posts: 12
  • I like programming in QB64, C, & Python
    • View Profile
This is a little off topic on my project, but I wanted to share. Years ago, I wrote a program for a GUI template. During that time in QBASIC to make a box and fill it in with the very basic drawing graphic statements you would use drawing statements such as LINE for drawing the lines for a box and you had to use PSET to fill in the box with a color.

There was no simple box fill (BF) in the DOS version of QBASIC for the LINE statement I used during that time. Here is a screen shot of what I made with those basic draw statements with LINE. I even made the letters in this GUI using LINE. I hope to show you can build any idea you have in mind, even if the graphics are with the so called primitive graphic statements such as LINE in mind. I will add there is no mouse action in this program. Each highlighted letter made a pop down or pop up box for options when you used the keyboard to hit that letter.

Example: If you had hit the N that is in underline, it would pop up a box just like it would do in Windows. Each highlighted letter would do the same such as the O for Options to pop down a box...etc. Each box could be filled with options and commands as it was a template.

Note: The gui.bas file was lost, but I still have the .exe build from the QBASIC 4.5 (full version) for the GUI project I built. I could rebuild it again from my programming notes or wing it. The point I am trying to make is...you can build anything you have in mind for your program even if there are limitations. So, if you think, I can't build an IDE/GUI interface graphically with just the basic draw statements such as LINE...etc. Well, you can.

Huh, after thinking about it...maybe after this Old School Tile/Map project....I will use this GUI.EXE for an example on how to reverse engineer code using a hex editor and some basic assembly tools. I lost the .bas and the program was made by me, so why not? LOL!

Thanks for viewing! (^_^)
 
gui.jpg
* gui.jpg (Filesize: 52.22 KB, Dimensions: 642x505, Views: 190)
« Last Edit: May 14, 2021, 08:21:13 pm by Abacus »
If obj1x% > obj2x% And obj1y% > obj2y% Then
    If obj1x% < obj2x% + tilewidth% And obj1y% < obj2y% + tilelength% Then Print: Print "collisoin"
End If