You forgot the @ under: "Or something like this." Correct syntax: GOTO@MNLOOP
IntroductionWhen programming, we want to make things as generic as possible so our tricks and "hacks" can work on any occasion we need them to. That's why we declare bunch of DEFs, bunch of generic variables and constants... All for that specific goal. But what happend if we want to go beyond generic code? When i mean "beyond", i mean adding bunch of predefined pieces of code that allow us to have: Levels (on the most part); Menus... If you think about it, you would say something like: "Well, that can't go wrong". But can't be? Let's take a look. Imagine we have a generic geim that has bunch of levels. When using the classic approach most users use when coding, it would look like this:
LEVEL%=5 WHILE <Some Condition> VSYNC IF LEVEL%==1 THEN '... ENDIF IF LEVEL%==2 THEN '... ENDIF IF LEVEL%==3 THEN '... ENDIF WENDOr something like this:
LEVEL%=5 @MNLOOP VSYNC IF LEVEL%==1 THEN GOTO @LEVEL1 IF LEVEL%==2 THEN GOTO @LEVEL2 IF LEVEL%==3 THEN GOTO @LEVEL3 GOTO MNLOOP @LEVEL1 '... GOTO @MNLOOP @LEVEL2 '... GOTO @MNLOOP @LEVEL3 '... GOTO @MNLOOPThese two examples shares a common problem: It destroys code readability and makes it near impossible to debug if you end up adding like 30 segments of predefined code. So, what's the solution for this? The solution is using DATA.
What is DATADATA is the most closest thing SB will have to a "list" of arbitrary data. It allows us to encapsulate a set of predefined data together that we can access later, hence the name.
DATA <data 1>, <data 2>... DATA "This is data",2,3.5,&HFF00FF00,&B0010,#UP 'Note: all the functions, including user functions, won't work on DATA. Since DATA only handles constant expressions
Accessing to the DATAAccessing to the DATA is handled by READ command. READ gets the data in the order it's executed. If READ is executed for the first time, it will get the first data of a DATA set, if it is executed again, it will return the second data of the DATA set, and so on...
DATA 1,2,3,4,5 READ X ? XOUTPUT: 1
DATA 1,2,3,4,5 READ X READ Y ? YOUTPUT: 2 So, if you want to access to the 5th element of a DATA set, you need to run READ 4 times before. So, on much cases you will end up using a FOR loop.
Locating the DATA setYou can "define" segments of DATA sets by using labels (@ABC) and the RESTORE command. Since DATA is being read from the very beginning of the source code to the end, RESTORE will define the start line so we can arbitrariely read what we want.
DATA 1 READ X ? X DATA 2OUTPUT: 1
RESTORE @B DATA 1 READ X ? X @B DATA 2OUTPUT: 2 With this now we can start.
1.- Creating a DATA Parser
1.1.- What is a DATA Parser?This doesn't have an official name, but i call it "DATA Parser" for the way how it works. On summary: a DATA Parser is a generic piece of code that can handle specific kinds of data and perform certain actions based on the data it receives. Pretty much like a DEF with multiple commands, with the exception that we don't need to call it over and over again, just give him the data it needs. The structure of the DATA list will directly influence the way you setup the DATA parser. And the structure of the DATA list depends on what you want to achieve. Here, i'm going to use a very typical example: Showing a message. Let's suppose i want to show a message on screen with the following arguments: - Author - Message - Color of the message - Duration in seconds when using DATA, it should look like this:
DATA "Author","Message",&HFFFFFF,5 ' White message with a duration of 5 secondsNow, we set an "ID" to the DATA segments we are going to use, by using a @Label:
@TEST DATA "Author","Message",&HFFFFFF,5With this setup, we can start making the DATA Parser.
1.2.- Setting up the parserAs explained early, DATA parsers are generic code, so we must do a code that can handle most, if not, all the possible parameters we parse to him. For this example, if we combine READ and RESTORE, we will get something like this:
DIM ARG$, DELAY%,GC,PREV_MILI% RESTORE @TEST WHILE 1 VSYNC GCLS 'DATA Parser for messages IF !DELAY% THEN 'I read the necessary arguments before showing anything. Yours can vary based on your needs. READ ARG$ READ ARG$ READ GC READ DELAY% ELSE GPUTCHR 10,120,ARG$ GCOLOR GC GPUTCHR 10,130,ARG$ ENDIF 'Clock in seconds IF PREV_MILI%+1000 < MILLISEC THEN DELAY%=DELAY%-1 PREV_MILI%=MILLISEC ENDIF WEND @TEST DATA "Author","Message",&HFFFFFF,5Aaaaannndddd... Well, that's all, for a very simple reason: When the DATA Parser is ready, most of your editions will go on the DATA statements and not on the core structure. With that you can sepparate the logic from the arguments, and have a more cleaner code that will not only look "good" (every code is a mess, but anyways), but it will save you time when you want to make quick edits to the levels or the stuff you're showing. What if you want to add or erase messages? Just add more DATA like this:
@TEST DATA "Me","This is a message using DATA statements (DUR: 5 secs)",&HFFFFFFFF,5 DATA "Me","Is amazing because i don't have to touch the core structure to add more and more (DUR: 5 secs)",&HFFFFFFFF,5 DATA "Someone else","Also, this message is plain red (DUR: 5 secs)",&HFFFF0000,5 DATA "Me","And this message last 3 seconds and is blue (DUR: 3 secs)",&HFF0000FF,3