OPTION STRICT 'Require I declare variables
VAR MAP_W%, MAP_H% 'Size of the map
VAR I%, J%, ROW$, CH$ 'For decoding the data statements
VAR TILE%, PX% = 0, PY% = 0 'Tile to write to the background, and the player's start x,y coordinates
VAR T_LADDER% = 806 'Tile codes for the various characters. Makes it easier to read and change things in one place
VAR T_ROCK% = 159 'I could have put these in data statements too, I just thought this might be easier to read.
VAR T_WALL% = 570 'You could also try 543
VAR T_WALL_UL% = 442 + (1 << 14) 'adding 1 << 14 turns on the horizontal flip flag
VAR T_WALL_UR% = 442 'UL = Upper Left, UR = Upper Right, LL = Lower Left, LR = Lower Right
VAR T_WALL_LL% = 506 + (1 << 14)
VAR T_WALL_LR% = 506 'You can choose other numbers I just went into SMILE tools and chose BG numbers that looked nice.
VAR T_PLATFORM_L% = 577 'Left side of the platform
VAR T_PLATFORM_M% = 578 'Middle of the platform (repeatable)
VAR T_PLATFORM_R% = 579 'Right side of the platform
VAR T_SPADE% = 5 'Didn't know what these were on the map so I just chose CHESS pieces.
VAR T_DIAMOND% = 6
VAR T_HEART% = 7
VAR T_CLUB% = 9 'I may have type-o's here and there from re-typing in things manually. You will have to debug.
VAR T_BG% = 639 'I am going to fill a background layer with this since some of the other tiles have transparent portions
VAR HERO% = 496 'Sprite number to use for the player character.
VAR HERO_SP% 'Will receive the sprite number of the player character
ACLS 'Let's rid the screen of any junk
RESTORE @LEVEL_01 'We want to make sure we read from where we are expecting
READ MAP_W%, MAP_H% 'The first two variables are the width and height of the map.
'Please note I didn't add anything for scrolling. That would require some extra world versus screen coordinates code.
'Resize then fill in layer 0 with T_BG%
BGSCREEN 0, MAP_W%, MAP_H%
BGFILL 0, 0, 0, MAP_W% - 1, MAP_H% - 1, T_BG% 'Zero based so it goes from 0 to 1 minus the width/height
BGSCREEN 1, MAP_W%, MAP_H% 'We will be putting non-empty tiles here.
BGCLR 1 'Make sure the layer is empty
FOR J% = 0 to MAP_H% - 1
READ ROW$ 'Each row is a string we will chop up into characters. We could have done it character by character but that would make the data statements ugly.
FOR i% = 0 TO MIN(LEN(ROW$), MAP_W%) - 1 'Extra bit of code to make sure we don't over-run the string length if it is too small or go too far if it is too big.
CH$ = MID$(ROW$, I%, 1)
'Note had to change some characters around to be more keyboard friendly on the PC
'Big giant if/then/else to change a character to a tile number. I probably should have put this in data statements and arrays or at least a function.
IF CH$ == "[" THEN
TILE% = T_WALL_UL%
ELSEIF CH$ == "]" THEN
TILE% = T_WALL_UR%
ELSEIF CH$ == "(" THEN
TILE% = T_WALL_LL%
ELSEIF CH$ == ")" THEN
TILE% = T_WALL_LR%
ELSEIF CH$ == "X" THEN
TILE% = T_WALL%
ELSEIF CH$ == "H" THEN
TILE% = T_LADDER%
ELSEIF CH$ == "O" THEN
TILE% = T_ROCK%
ELSEIF CH$ == "<" THEN
TILE% = T_PLATFORM_L%
ELSEIF CH$ == "=" THEN
TILE% = T_PLATFORM_M%
ELSEIF CH$ == ">" THEN
TILE% = T_PLATFORM_R%
ELSEIF CH$ == "S" THEN
TILE% = T_SPADE%
ELSEIF CH$ == "H" THEN
TILE% = T_HEART%
ELSEIF CH$ == "D" THEN
TILE% = T_DIAMOND%
ELSEIF CH$ == "C" THEN
TILE% = T_CLUB%
ELSEIF CH$ == "@" THEN
'Special case, this is a blank but we record this is where the position the player should start at in the level.
TILE% = -1 'Don't draw a tile
PX% = I% * 16 'Multiply by 16 to change from tile coordinates to pixel/screen coordinates.
PY% = I% * 16
ELSE 'CH$ = " " or some other unrecognized character
TILE% = -1 'Skip the tile
ENDIF
IF TILE% >= 0 THEN
BGPUT 1, I%, J%, TILE% 'Write the tile out.
ENDIF
NEXT I%
NEXT J%
'Now let's see about setting up the hero character a little.
SPSET HERO% OUT SP_HERO% 'Let SmileBasic choose the ID for us, we don't care
SPOFS SP_HERO%, PX%, PY% 'Warp us to the location the level asked for.
'Write a message telling the user how to exit this demo.
LOCATE 0, 25 '12 rows of 16 pixels / 8 pixels per character = 24. Add one for a bit of spacing = 25. In case you wondered where that came from.
PRINT "PRESS [B] TO EXIT"
'Just wait for the user to click the B button. Then exit the program
REPEAT
VSYNC
UNTIL (BUTTON() AND #B) != 0
'Lets clean up before we go.
SPCLR SP_HERO%
BGCLR 0
BGCLR 1 'Probably should have used a loop, oh well.
END 'It is nice to end purposefully.
@LEVEL_01
DATA 24, 12
DATA "[XXXXXXXXXXXXXXXXXXXXXX]"
DATA "X X"
DATA "X X"
DATA "X X"
DATA "X X"
DATA "X H<==> X"
DATA "X H X"
DATA "X H X"
DATA "X H X"
DATA "X H OO S X"
DATA "X H @ OO HDC X"
DATA "(XXXXXXXXXXXXXXXXXXXXXX)"
Is that sort of what you are looking for? Note that I am filling up BG tiles, not making a bunch of sprites. You only have a few hundred sprites and they take more processing than a BG tile, so do try to conserve them. For the record if I was selecting the tile with mapping arrays, I would have had some code like the following:
VAR TILE_CHAR$[0], TILE_NUM%[0], T_CHAR$, T_NUM%, DONE% = FALSE
RESTORE @TILE_LOOKUP
WHILE DONE% == FALSE
READ T_CHAR$, T_NUM%
IF (LEN(T_CHAR$) > 0) THEN
'END WHEN T_CHAR$ IS EMPTY
DONE% = TRUE
ELSE
PUSH TILE_CHAR$, T_CHAR$
PUSH TILE_NUM%, T_NUM%
ENDIF
WEND
'THEN INSTEAD OF THE BIG IF/THEN/ELSE LOOP YOU COULD HAVE SOMETHING LIKE
VAR K%
TILE% = -1 'DEFAULT VALUE
IF CH$ == "@" THEN
PX% = I% * 16
PY% = J% * 16
TILE% = -1
ELSE
FOR K% = 0 TO LEN(TILE_CHAR$) - 1
IF CH$ == TILE_CHAR$[K%] THEN
TILE% = TILE_NUM%[K%]
BREAK
END IF
NEXT K%
ENDIF
IF TILE% >= 0 THEN
BGPUT 1, I%, J%, TILE%
ENDIF
'....
@TILE_LOOKUP
DATA "H", 806
DATA "O", 159
DATA "X", 570
DATA "]", 442 + (1 << 14) 'Not sure if I can leave in the math or not.
DATA "[", 442
DATA "(", 506 + (1 << 14)
DATA ")", 506
DATA "<", 577
DATA "=", 578
DATA ">", 579
DATA "S", 5
DATA "D", 6
DATA "H", 7
DATA "C", 9
DATA "", 0 'Last record flag
Anyway if you typed it all in right (Ignore the second block that says how I would have done it with a lookup table), it should look something like this:
There is a lot left to code if you want to move around and have collision detection and such.