Putting ASCII chr's into an array and converting it...
Root / Programming Questions / [.]
DefaultioCreated:
Into background tiles/invisible sprites so that is has collision.
How would I set this up? Would I just create an array like:
'Setting up map array, it has 7 rows, each with different chr's 'Think of the "=" symbols as the blocks in the alternate keyboard DIM MAP$[8] MAP$[0] = "==========" MAP$[1] = "= +====+ =" MAP$[2] = "= ====== =" ... 'and so on until... MAP$[7] = "=========="So, would I have to read the individual characters in the string, and if it reads a certain character, it would place a certain "block" of bg/sprite tiles in a set of start and end coordinates; Or would I just have to make a bigger map so that one character represents one bg/sp tile? Like:
FOR I = 0 TO 7 READ MAP$[8] 'check for certain characters using string commands 'and display sprites/bg tiles according to those 'ASCII characters NEXTOr do you have your own way of doing that you could show? I know I could use a FOR loop, READ, and String commands to attempt to start this, but I'm not that great with String commands, but i'll learn them. So If I got the character to bg/sprite conversion to work, would I then have to just set up collision like I normally would? Thanks in advance for answering and/or reading.
I think they are attempting to make a stage level kind of set up, like a dungeon and chests sort of thing. If that's the case, then I must ask is sprite collision necessary? If you have a tiled world and tile characters which may only move and exist on tiles, would it not be better to check tile states where the player attempts to move (for say, a wall or an empty space), rather than creating a collision system?
I'm only basing my assumption of what they are attempting on the tile-map-looking strings in their code.
Hm, hm, sorry I didn't clarify.
http://petitcomputer.wikia.com/wiki/G-ZERO
Basically what that program does. It converts ASCII characters that are assigned to an array and gets into sprites/bg sprites and displays them on the screen.
Then collision is added, based on those sprites with the player's ship. I wanted to try something like that, but with other types of genres.
Here's the code borthers: https://pastebin.com/T8iZ50nT
Okay, I understand this a little better now. The ASCII characters embedded in the MAP$ array constitute a form of storing map data. It doesn't necessarily have to be that method, i.e., you could use a 2D array of values instead. But, with the ASCII method, it would work basically as you describe. You need to describe a program which can identify elements of your MAP$ array and recognize their BG tile/sprite counterparts.
Here's some psuedocode (again, I'm not familiar with sprites, someone else'll have to come along and tie this part up)
DIM MAP_X% = 8, MAP_Y% =8 DIM MAP$[0] PUSH MAP$, "--------" PUSH MAP$, "- ---- -" '... PUSH MAP$, "--------" DIM X%, Y% FOR Y% = 0 TO MAP_Y%-1 FOR X% = 0 TO MAP_X%-1 IF MAP$[Y%][X%]=="-" THEN 'Draw a specific sprite ENDIF NEXT X% NEXT Y%Because you're working with strings, you need to address MAP$ as if it were a 2D array. Strings function as arrays themselves, more or less. Calling MAP$[Y%] returns the horizontal cross-section of the array, let's say "--------". That string can then be referenced as an array itself, hence MAP$[Y%][X%], or ("--------")[X%]. They both will yield the same results, if you decide to test it.
I might be wrong, but what I think you're trying to do is this: How do I create maps using DATA? but without the DATA part. It would be much easier to use DATA to accomplish this (does not have to be as complicated as the linked page)
I am working on another version of this program but instead of exporting the hex number and all (even empty space) tiles, it exports a print character, x location, and y location for all tiles excluding empty spaces. If you would like to see this in action, I may be able to put something together for you to see, but it could take a bit.
I might be wrong, but what I think you're trying to do is this: How do I create maps using DATA? but without the DATA part. It would be much easier to use DATA to accomplish this (does not have to be as complicated as the linked page) I am working on another version of this program but instead of exporting the hex number and all (even empty space) tiles, it exports a print character, x location, and y location for all tiles excluding empty spaces. If you would like to see this in action, I may be able to put something together for you to see, but it could take a bit.Yea, I wanted to change it to data, but I thought it wouldn't work with what I was trying to do. I'll try it with data. I would love to see what you made! Thanks MZ for helping, I'll get on it right away!
Great! I will try to annotate my program so that it makes sense and have it up tonight or tomorrow evening
Hi, I'm back. So I tried to annotate this project as much as possible and I apologize if it is still difficult to understand. I didn't really set it up for use outside of my game but I tried to fix that. Anyway, expand the "spoilers" below to read what each file is.
Key: Q3K33XLM
I hope this helps and I will try my best to answer any questions you might have. Also, I do not plan on making a page for this just yet but I will when it has more definitive gameplay.
I will leave this up for ~24 hours or so.
READMAP
This is probably the most relevant file. I will explain what it does in just a moment but first it requires a little set up. In direct mode:LOAD "GRP5:TESTBG",0' the custom BG is important to this program fileOpen the SmileTool map editor and create a map using the first grouping of gray tiles (essentially, a floor tile, wall tile and edge tiles. When finished, save the layers using SC SAVE. Now, copy the files into the MAPPING folder (or if you saved the SC saves in that folder that is fine too) and run READMAP file. Name the map layer and select the SC file. It will ask if you want to export another layer and save the file. SO with all that said, what this file does is exports a print character (based on the gray tile used), x location, y location of the tile from the map into PRG3. Next, in editor mode, you will have to set the print character associations with whatever tile you want (at this point, you can ACLS as to get rid of custom BG). After you have set the tile associations then you can draw the map with NewDrawMap function. This is how you use that:
NewDrawMap "3:@label",layer number
TESTDATA
You can ignore this file. It is important for the TECHDEMO file (it is loaded automatically into slot 3)TECHDEMO
This file is a tech demo of a game I am working on. If you have played Kingdom Hearts Chains of Memories back in the GBA days, then this may feel familiar. You move a character around a map to arrows (exits), select a map template for the next zone and repeat. If you don't like the untextured gray you can change "@UNTEXTURED" in line 57 to "@GREEN" to get an untextured green map. The purpose of this project is to separate maps and textures to use as little "maps" as possible but still have an extensive gameplay experience. And also I wanted to see if I could recreate the mapping system in KHCoM.Hi, I'm back. So I tried to annotate this project as much as possible and I apologize if it is still difficult to understand. I didn't really set it up for use outside of my game but I tried to fix that. Anyway, expand the "spoilers" below to read what each file is. Key: Q3K33XLMDo you think I could also have the txt files (if you have homebrew and SBFM that is), because my 3ds likes to die really fast now, and I have Citra on my PC to run SmileBASIC on. If you can't then that's fine, I will let you know when I get the files onto my 3ds. Thank you for the help in understanding your method of map loading!READMAP
This is probably the most relevant file. I will explain what it does in just a moment but first it requires a little set up. In direct mode:LOAD "GRP5:TESTBG",0' the custom BG is important to this program fileOpen the SmileTool map editor and create a map using the first grouping of gray tiles (essentially, a floor tile, wall tile and edge tiles. When finished, save the layers using SC SAVE. Now, copy the files into the MAPPING folder (or if you saved the SC saves in that folder that is fine too) and run READMAP file. Name the map layer and select the SC file. It will ask if you want to export another layer and save the file. SO with all that said, what this file does is exports a print character (based on the gray tile used), x location, y location of the tile from the map into PRG3. Next, in editor mode, you will have to set the print character associations with whatever tile you want (at this point, you can ACLS as to get rid of custom BG). After you have set the tile associations then you can draw the map with NewDrawMap function. This is how you use that:NewDrawMap "3:@label",layer numberTESTDATA
You can ignore this file. It is important for the TECHDEMO file (it is loaded automatically into slot 3)I hope this helps and I will try my best to answer any questions you might have. Also, I do not plan on making a page for this just yet but I will when it has more definitive gameplay. I will leave this up for ~24 hours or so.TECHDEMO
This file is a tech demo of a game I am working on. If you have played Kingdom Hearts Chains of Memories back in the GBA days, then this may feel familiar. You move a character around a map to arrows (exits), select a map template for the next zone and repeat. If you don't like the untextured gray you can change "@UNTEXTURED" in line 57 to "@GREEN" to get an untextured green map. The purpose of this project is to separate maps and textures to use as little "maps" as possible but still have an extensive gameplay experience. And also I wanted to see if I could recreate the mapping system in KHCoM.
I am sorry, I do not have homebrew or SBFM...Do you think I could also have the txt files (if you have homebrew and SBFM that is), because my 3ds likes to die really fast now, and I have Citra on my PC to run SmileBASIC on. If you can't then that's fine, I will let you know when I get the files onto my 3ds. Thank you for the help in understanding your method of map loading!
It is fine brother, I have received the package, thanks again.I am sorry, I do not have homebrew or SBFM...Do you think I could also have the txt files (if you have homebrew and SBFM that is), because my 3ds likes to die really fast now, and I have Citra on my PC to run SmileBASIC on. If you can't then that's fine, I will let you know when I get the files onto my 3ds. Thank you for the help in understanding your method of map loading!
It sounds like you already have this figured out, but since you mentioned G-Zero, I thought I would post the G-Zero code I ported from Petit Computer to SmileBasic. If you notice, I added a second track, just swap one M$ array for the other to get the new track. You can make your own tracks too. X marks where the player starts. The exhaust is a linked sprite now and I think its code is more elegant than the original.
Enjoy
OPTION STRICT VAR LAYER = 0, X, Y, I, J, FONT$, GAME_OVER VAR ANG, DA, B, BX, BY, START_LINE, TMP VAR FRICTION, SPEED, SPEED_MAX, ANG_RAD VAR T1, T2, DX, DY, EXHAUST_DIST VAR MAP_W = 9, MAP_H = 9 VAR T_WALL = 842, T_ROAD = 584 VAR T_FINISH = 349, T_SHIP = 1217 VAR T_EXHAUST = 1347 VAR SCREEN_W = 400, SCREEN_H = 240 VAR HALF_W = SCREEN_W / 2 VAR HALF_H = SCREEN_H / 2 VAR ANY_DIR = #UP OR #DOWN OR #LEFT OR #RIGHT '---------- G-ZERO DIM M$[MAP_H] M$[0] = "" M$[1] = " X " M$[2] = " " M$[3] = " " M$[4] = " " M$[5] = " " M$[6] = " " M$[7] = " " M$[8] = "" 'M$[0] = "" 'M$[1] = " " 'M$[2] = " " 'M$[3] = " X " 'M$[4] = " " 'M$[5] = " " 'M$[6] = " " 'M$[7] = " " 'M$[8] = "" CLS BGSCREEN 0, MAP_W * 8, MAP_H * 8 DX = 0 : DY = 0 FOR X = 0 TO MAP_W - 1 ' DRAW MAP FOR Y = 0 TO MAP_H - 1 FONT$ = CHRREAD(MID$(M$[Y], X, 1)) FOR J = 0 TO 7 FOR I = 0 TO 7 T1 = VAL(MID$(FONT$, I + (J * 8), 1)) BX = I + X*8 : BY = J + Y*8 TMP= RND(4) + T_WALL 'WALL IF T1 == 1 THEN TMP = RND(4) + T_ROAD 'ROAD ELSEIF T1 == 2 THEN TMP = T_FINISH 'FINISH LINE IF DX == 0 AND DY == 0 THEN DX = X * 8 * 16 + (4 * 16) DY = Y * 8 * 16 + (4 * 16) ENDIF ENDIF BGPUT LAYER, BX, BY, TMP NEXT I NEXT J NEXT Y NEXT X GCLS '--------PLAYER INIT SPCLR SPSET 0, T_SHIP 'SHIP SPHOME 0, 8, 8 SPOFS 0, HALF_W, HALF_H SPSET 1, T_EXHAUST 'EXHAUST SPHOME 1, 8, 8 SPOFS 1, HALF_W - 16, HALF_H SPLINK 1, 0 'LINK TOGETHER EXHAUST_DIST = 0 : START_LINE = 1 X = DX : Y = DY DX = 0 : DY = 0 ANG = 180 : DA = 2 : SPEED_MAX = 16 GAME_OVER = FALSE : T1 = MILLISEC '--------MAIN WHILE GAME_OVER == FALSE B = BUTTON() FRICTION = 0.99 IF B AND #Y THEN GAME_OVER = TRUE IF B AND #RIGHT THEN ANG = ANG + DA IF B AND #LEFT THEN ANG = ANG - DA IF B AND (ANY_DIR) THEN FRICTION = 0.98 IF ANG < 0 THEN ANG = ANG + 360 IF ANG > 360 THEN ANG = ANG + 360 DX = DX * FRICTION : DY = DY * FRICTION SPEED = (DX * DX) + (DY * DY) IF ((B AND #A) != 0) AND SPEED < SPEED_MAX THEN ANG_RAD = RAD((ANG + 180) MOD 360) DX = DX + COS(ANG_RAD)/20 DY = DY + SIN(ANG_RAD)/20 ENDIF SPROT 0, (ANG + 90) MOD 360 X = X + DX : Y = Y + DY X = MAX(0, MIN(X, (MAP_W * 16 * 8) - 16)) Y = MAX(0, MIN(Y, (MAP_H * 16 * 8) - 16)) TMP = BGGET(LAYER, X / 16, Y / 16) IF TMP >= T_ROAD AND TMP <= T_ROAD + 3 THEN DX = -DX DY = -DY ENDIF BX = MIN(MAX(0, X - HALF_W), (MAP_W * 16 * 8) - SCREEN_W) BY = MIN(MAX(0, Y - HALF_H), (MAP_H * 16 * 8) - SCREEN_H) BGOFS LAYER, BX, BY SPOFS 0, X - BX, Y - BY IF ((B AND #A) != 0) AND SPEED < SPEED_MAX THEN EXHAUST_DIST = EXHAUST_DIST + 1 : SPEED = SPEED * 700 IF EXHAUST_DIST > 16 THEN EXHAUST_DIST = 6 : BEEP 1 SPOFS 1, 0, -EXHAUST_DIST SPSHOW 1 ELSE SPHIDE 1 ENDIF TCHK X, Y VSYNC WEND END DEF TCHK X, Y VAR I, J '------------TIME I = FLOOR(X / 16) : J = FLOOR(Y / 16) IF BGGET(LAYER, I, J) != T_FINISH THEN START_LINE = 0 RETURN ENDIF IF START_LINE != 0 THEN RETURN ELSE START_LINE = 1 ENDIF BEEP 7 'COIN T2 = MILLISEC IF T1 THEN LOCATE 15, 1 PRINT "TIME: " + FORMAT$("%03.2F", (T2 - T1) / 1000) + " SEC "; T1 = T2 ENDIF END 'POLYFILL FOR PTC ONLY FUNCTION DEF CHRREAD(CH$) VAR RET$ = "" VAR I, J GCLS GPUTCHR 0, 0, CH$ FOR J = 0 TO 7 FOR I = 0 TO 7 IF CH$ == "X" THEN RET$ = RET$ + "2" ELSE IF GSPOIT(I, J) != 0 THEN RET$ = RET$ + "1" ELSE RET$ = RET$ + "0" ENDIF ENDIF NEXT I NEXT J RETURN RET$ END
It sounds like you already have this figured out, but since you mentioned G-Zero, I thought I would post the G-Zero code I ported from Petit Computer to SmileBasic. If you notice, I added a second track, just swap one M$ array for the other to get the new track. You can make your own tracks too. X marks where the player starts. The exhaust is a linked sprite now and I think its code is more elegant than the original. EnjoyOk so, this might be a huge request, but could you comment your code? I would love to be able to read a nice, neat, polished piece of programmed code.
OPTION STRICT 'REQUIRE VARIABLES BE DECLARED BEFORE USE 'THIS IS A PORT OF G-ZERO BY SMILEBOOM ORIGINALLY FOR PETIT COMPUTER ON THE NINTENDO DS ' 'IT WAS FOUND IN THE PETIT COMPUTER OFFICIAL STRATEGY TECHNIC 'STARTING ON PAGE 94 IN THE 100 LINE PROGRAM CHALLENGE SECTION. ' 'YOU RACE A SHIP AROUND A RACE TRACK COMPETING AGAINST YOUR OWN BEST TIME. ' 'CONTROLS. '[LEFT] TURN THE SHIP LEFT '[RIGHT] TURN THE SHIP RIGHT '[A] ACCELERATE '[Y] EXIT PROGRAM ' VAR LAYER = 0 'WHAT BACKGROUND LAYER TO READ/WRITE TO VAR X, Y, I, J 'ITERATE OVER A GRID VAR FONT$ 'VARIABLE TO WHICH THE PIXEL PATTERN OF A LETTER WILL BE UNPACKED TO VAR GAME_OVER 'FLAG TO SAY IF THE GAME SHOULD KEEP RUNNING. VAR ANG 'CURRENT ANGLE OF THE SHIP VAR DA 'HOW MUCH TO CHANGE THE ANGLE WHEN TURNING VAR B 'USED TO STORE BUTTON STATE VAR BX, BY 'BACKGROUND LAYER X AND Y COORDINATES VAR START_LINE 'FLAG TO SAY IF YOU PASSED THE STARTING LINE VAR TMP 'THROW AWAY TEMPORARY VARIABLE VAR FRICTION 'SLOWLY REDUCE SPEED OVER TIME WHEN NO FORCE APPLIED VAR SPEED 'HOW FAST THE SHIP IS MOVING (SQUARED ACTUALLY) VAR SPEED_MAX 'TOP ALLOWABLE SPEED VAR ANG_RAD 'CURRENT ANGLE ADJUSTED TO POINT THE SHIP CORRECTLY AND CONVERTED TO RADIANS VAR T1, T2 'TIMER VARIABLES TO KEEP TRACK OF TIME SPENT RUNNING A LAP VAR DX, DY 'HOW FAST WE ARE MOVING IN THE X AND Y DIRECTION VAR EXHAUST_DIST 'DISTANCE OF THE EXHAUST FROM THE SHIP (MOVES BACK AND FORTH) VAR MAP_W = 9, MAP_H = 9 'WIDTH AND HEIGHT OF THE MAP, CHANGE THE WIDTH TO 15 (WIDTH OF THAT MAP) IF YOU USE THE OPTIONAL MAP VAR T_ROAD = 842 'TILE ID FOR THE ROAD. WE ACTUALLY USE A RANGE OF TILES STARTING HERE AND UP TO ID + 3 VAR T_WALL = 584 'TILE ID FOR THE WALL. WE ACTUALLY USE A RANGE OF TILES STARTING HERE AND UP TO ID + 3 VAR T_FINISH = 349 'TILE ID FOR THE FINISH LINE VAR T_SHIP = 1217 'SPRITE ID FOR THE SHIP/PLAYER VAR T_EXHAUST = 1347 'SPRITE ID OF THE EXHAUST FLAME VAR SCREEN_W = 400, SCREEN_H = 240 'THE SCREEN WIDTH AND HEIGHT VAR HALF_W = SCREEN_W / 2 'HALF OF THE SCREEN WIDTH (CONVENIENCE VARIABLE) VAR HALF_H = SCREEN_H / 2 'HALF OF THE SCREEN HEIGHT (CONVENIENCE VARIABLE) 'FLAG TO COMBINE ALL OF THE DIRECTION BUTTONS TOGETHER IN A FLAG, USED TO SEE IF 'ANY DIRECTION KEY PRESSED. VAR ANY_DIR = #UP OR #DOWN OR #LEFT OR #RIGHT '---------- G-ZERO 'THE MAP WE ARE RACING ON. EACH PIXEL OF EACH CHARACTER BECOMES A TILE ON THE BACKGROUND. DIM M$[MAP_H] M$[0] = "" M$[1] = " X " M$[2] = " " M$[3] = " " M$[4] = " " M$[5] = " " M$[6] = " " M$[7] = " " M$[8] = "" 'ALTERNATE MAP (REMEMBER TO UPDATE MAP_W IF YOU USE THIS) 'M$[0] = "" 'M$[1] = " " 'M$[2] = " " 'M$[3] = " X " 'M$[4] = " " 'M$[5] = " " 'M$[6] = " " 'M$[7] = " " 'M$[8] = "" 'CLEAR OUT ANY OLD STUFF FROM THE SCREEN. CLS 'SET UP THE BACKGROUND SCREEN 'EVERY PIXEL OF EACH CHARACTER COUNTS SO THE MAP IS 8 TIMES BIGGER DUE TO AN 8X8 FONT. BGSCREEN LAYER, MAP_W * 8, MAP_H * 8 'SET DIRECTION TO STOPPED DX = 0 : DY = 0 'DRAW THE MAP. X, Y ITERATE OVER THE CHARACTERS IN THE MAP DATA 'I, J ITERATE OVER THE PIXELS OF EACH CHARACTER. FOR X = 0 TO MAP_W - 1 ' DRAW MAP FOR Y = 0 TO MAP_H - 1 'GET THE X,Y CHARACTER OF THE MAP FONT$ = CHRREAD(MID$(M$[Y], X, 1)) FOR J = 0 TO 7 FOR I = 0 TO 7 'READ THE I,J PIXEL FOR THAT CHARACTER T1 = VAL(MID$(FONT$, I + (J * 8), 1)) 'CALCULATE HOW THAT MAPS TO A BACKGROUND TILE BX = I + X*8 : BY = J + Y*8 'GIVE THE MAP A BIT OF VARIETY BY OFFSETING THE ROAD TEXTURE 0 TO 3 TILES TMP= RND(4) + T_ROAD 'ROAD IF T1 == 1 THEN 'IF WE ARE WALL INSTEAD OF ROAD DO THE SAME THING FOR THE ROAD TILE ID TMP = RND(4) + T_WALL 'WALL ELSEIF T1 == 2 THEN 'THE FINISH LINE IS ALWAYS JUST THE ONE TILE. TMP = T_FINISH 'FINISH LINE IF DX == 0 AND DY == 0 THEN 'SINCE X AND Y ARE BUSY, STORE WHERE WE SHOULD START IN DX, DY 'WHEN WE FIND THE FINISH LINE '8 IS FOR THE FONT WIDTH, 16 IS FOR THE TILE WIDTH AND THE 4*16 IS TO PUT IT IN THE CENTER OF THE FINISH LINE. DX = X * 8 * 16 + (4 * 16) DY = Y * 8 * 16 + (4 * 16) ENDIF ENDIF 'WRITE THE TILE OUT TO THE BACKGROUND LAYER BGPUT LAYER, BX, BY, TMP NEXT I NEXT J NEXT Y NEXT X 'CLEAR OUT THE GRAPHICS SCREEN. WE MODIFIED IT WHEN CHECKING PIXELS IN A CHARACTER. GCLS '--------PLAYER INIT 'CLEAN UP ANY PREVIOUSLY SET UP SPRITES SPCLR 'SPRITE ID = 0 WILL BE THE PLAYER SHIP. 'SET THE HOME TO 8,8 SO IT ROTATES AROUND ITS CENTER, THEN PLACE IT IN THE 'CENTER OF THE SCREEN. SPSET 0, T_SHIP 'SHIP SPHOME 0, 8, 8 SPOFS 0, HALF_W, HALF_H 'SPRITE ID = 1 WILL BE THE SHIP'S EXHAUST. 'SET THE HOME TO THE MIDDLE JUST LIKE THE SHIP AND FOR THE SAME REASON. 'WE PLACE IT THE SAME POSITION AS THE SHIP, BUT BACK A TILE WIDTH SPSET 1, T_EXHAUST 'EXHAUST SPHOME 1, 8, 8 SPOFS 1, HALF_W - 16, HALF_H 'LINK THE EXHAUST TO THE SHIP SO THAT IT MOVE/ROTATES WITH THE SHIP. IT SIMPLIFIES THINGS. SPLINK 1, 0 'LINK TOGETHER 'THE EXHAUST IS AT THE ZERO DISTANCE FOR THE MOMENT AND WE ARE ON THE STARTING LINE EXHAUST_DIST = 0 : START_LINE = 1 'MOVE THE CURRENT POSITION BACK INTO THE X AND Y VARIABLES X = DX : Y = DY 'SET THE X,Y SPEED VARIABLES BACK TO ZERO. DX = 0 : DY = 0 'WE ARE CURRENTLY POINTED AT 180 DEGREES, MOVE BY TWO DEGREES WHEN TURNING AND TOP SPEED IS 16 PIXELS/FRAME ANG = 180 : DA = 2 : SPEED_MAX = 16 'WE SHOULD KEEP PLAYING, AND SET THE TIMER AT NOW. GAME_OVER = FALSE : T1 = MILLISEC '--------MAIN 'THIS IS THE MAIN GAME LOOP. KEEP GOING UNTIL THE GAME OVER FLAG IS SET TO FALSE (BY CLICKING Y) WHILE GAME_OVER == FALSE 'GET BUTTON STATE B = BUTTON() 'DEFAULT VALUE FOR FRICTION FRICTION = 0.99 'CHECK IF WE SHOULD EXIT THE GAME IF B AND #Y THEN GAME_OVER = TRUE 'CHANGE THE ANGLE IF TURNING LEFT OR RIGHT. IF B AND #RIGHT THEN ANG = ANG + DA IF B AND #LEFT THEN ANG = ANG - DA 'IF ANY DIRECTION IS PRESSED, REDUCE THE FRICTION TO 98% IF B AND (ANY_DIR) THEN FRICTION = 0.98 'MAKE SURE THE ANGLE STAYS IN THE 0 TO 360 RANGE IF ANG < 0 THEN ANG = ANG + 360 IF ANG > 360 THEN ANG = ANG - 360 'SLOW DOWN SPEED DUE TO FRICTION DX = DX * FRICTION : DY = DY * FRICTION 'GET THE SQUARED MAGNITUDE OF THE SPEED. SPEED = (DX * DX) + (DY * DY) 'IF WE HAVEN'T REACHED TOP SPEED AND A IS PRESSED INCREASE SPEED BY 1/20 OF UNIT VECTOR IF ((B AND #A) != 0) AND SPEED < SPEED_MAX THEN ANG_RAD = RAD((ANG + 180) MOD 360) DX = DX + COS(ANG_RAD)/20 DY = DY + SIN(ANG_RAD)/20 ENDIF 'ROTATE THE SHIP TO MATCH THE CURRENT ANGLE. SPROT 0, (ANG + 90) MOD 360 'MODIFY THE X, Y COORDINATES BY THE SPEED X, Y COMPONENTS X = X + DX : Y = Y + DY 'DON'T LET THE SHIP LEAVE THE BACKGROUND X = MAX(0, MIN(X, (MAP_W * 16 * 8) - 16)) Y = MAX(0, MIN(Y, (MAP_H * 16 * 8) - 16)) 'GET THE BACKGROUND TILE WE ARE CURRENTLY LOCATED OVER TMP = BGGET(LAYER, X / 16, Y / 16) 'BUMP BACK IF WE HIT A WALL IF TMP >= T_WALL AND TMP <= T_WALL + 3 THEN DX = -DX DY = -DY ENDIF 'FIND THE SPOT TO POSITION THE BACKGROUND LAYER TO KEEP THE 'SHIP AT THE MIDDLE OF THE SCREEN OR AT LEAST WITHIN THE BACKGROUND LAYER. BX = MIN(MAX(0, X - HALF_W), (MAP_W * 16 * 8) - SCREEN_W) BY = MIN(MAX(0, Y - HALF_H), (MAP_H * 16 * 8) - SCREEN_H) 'MOVE THE BACKGROUN TO THE CORRECT SPOT. BGOFS LAYER, BX, BY 'IF WE ARE ON THE EDGE OF THE MAP WE WON'T BE AT THE CENTER OF THE SCREEN. 'CONVERT THE WORLD COORDINATES TO SCREEN CORRDINATES FOR THE SHIP SPOFS 0, X - BX, Y - BY 'CHECK TO SEE IF WE ARE HOLDING [A] TO ACCELERATE AND ARE NOT AT TOP SPEED. IF ((B AND #A) != 0) AND SPEED < SPEED_MAX THEN 'MOVE THE EXHAUST BACK FROM THE SHIP A BIT AND SCALE UP THE SPEED. EXHAUST_DIST = EXHAUST_DIST + 1 : SPEED = SPEED * 700 'IF THE EXHAUST GOT TOO FAR AWAY MOVE IT BACK AND PLAY A SPEED UP SOUND. IF EXHAUST_DIST > 16 THEN EXHAUST_DIST = 6 : BEEP 1 SPOFS 1, 0, -EXHAUST_DIST SPSHOW 1 ELSE 'HIDE THE EXHAUST SPRITE WHEN WE AREN'T ACCELERATING. SPHIDE 1 ENDIF 'CHECK TO SEE IF WE PASSED INTO THE FINISH LINE TCHK X, Y 'LIMIT SPEED TO REFRESH RATE VSYNC WEND END 'CHECK TO SEE IF WE ENTERED THE FINISH LINE. IF SO, PRINT THE LAP TIME AND PLAY A 'COIN SOUND. 'PARAMETERS: '* X: LOCATION OF THE SHIP X-COORDINATE '* Y: LOCATION OF THE SHIP Y-COORDINATE 'RETURNS: '* NONE ' DEF TCHK X, Y VAR I, J 'BACKGROUND TILE COORDINATES '------------TIME 'TRANSLATE THE WORLD COORDINATES INTO BACKGROUND COORDINATES BY 'DIVIDING BY 16 OR THE SIZE OF A TILE. I = FLOOR(X / 16) : J = FLOOR(Y / 16) 'IF WE ARE NOT ON THE FINISH LINE SET THE FLAG SO THAT CROSSING INTO THE 'FINISH LINE COUNTS IF BGGET(LAYER, I, J) != T_FINISH THEN START_LINE = 0 RETURN ENDIF IF START_LINE != 0 THEN 'IF WE WERE ON THE FINISH LINE LAST FRAME, DON'T CHECK IT AGAIN. RETURN ELSE 'TO GET THIS FAR WE MUST BE ON THE FINISH LINE AND WEREN'T LAST TIME 'THE FUNCTION WAS CALLED, SO SET THE FLAG. START_LINE = 1 ENDIF BEEP 7 'COIN 'SAVE THE CURRENT TIME. T2 = MILLISEC 'CONTINUE ONLY IF WE HAVE A STARTING TIME. IF T1 THEN LOCATE 15, 1 'PRINT OUT THE LAP TIME. NOTE THE FORMAT$ CALL IS TURNING THE NUMBER INTO A 'NICE STRING VALUE WITH A TWO DIGIT DECIMAL AMOUNT (SO 3.333333 WILL PRINT AS 3.33 PRINT "TIME: " + FORMAT$("%03.2F", (T2 - T1) / 1000) + " SEC "; 'NEW START TIME IS THE FINISH TIME T1 = T2 ENDIF END 'POLYFILL FOR PTC ONLY FUNCTION 'THIS GETS THE PATTERN OF PIXELS FOR A CHARACTER IN AN 8X8 FONT. 'PETIT COMPUTER HAD A NICE CALL FOR THIS THAT SMILEBASIC DOESN'T HAVE. 'TO WORK AROUND IT, I PRINT THE CHARACTER TO POSITION 0, 0 THEN READ 'EACH PIXEL IN THE 8X8 GRID AND RETURN IT AS A STRING OF 0, 1. 'UNLESS IT IS THE SPECIAL CHARACTER X THAT MARKS THE FINISH LINE, IN THAT 'CASE YOU JUST GET ALL 2'S. 'PARAMETERS: '* CH$ - CHARACTER TO READ, ASSUMED TO BE ONE SINGLE CHARACTER. 'RETURNS: '* A STRING OF 64 2'S IF THE SPECIAL CHARACTER X (START/FINISH LINE). OTHERWISE ' IT WILL RETURN EACH PIXEL OF THE CHARACTER WITH A 0 IF BLACK/EMPTY AND 1 IF FILLED. IT WILL GO LEFT TO RIGHT, TOP TO BOTTOM. ' DEF CHRREAD(CH$) VAR RET$ = "" 'RETURN VALUE VAR I, J 'LOOP OVER THE X, Y COORDINATES OF THE CHARACTER 'CLEAR OUT OLD JUNK THE LAZY WAY. GCLS 'WRITE THE CHARACTER TO POSITION 0, 0 ON THE SCREEN. GPUTCHR 0, 0, CH$ FOR J = 0 TO 7 FOR I = 0 TO 7 IF CH$ == "X" THEN 'RETURN ALL 2'S IF THE START/FINISH LINE. RET$ = RET$ + "2" ELSE 'CHECK TO SEE IF THE PIXEL IS FILLED OR NOT ON THE SCREEN. IF GSPOIT(I, J) != 0 THEN 'YES, WRITE A 1 RET$ = RET$ + "1" ELSE 'NO, WRITE A 0 RET$ = RET$ + "0" ENDIF ENDIF NEXT I NEXT J 'RETURN THE ENCODED STRING TO THE CALLER. RETURN RET$ ENDHopefully that works for you. I found a few bugs here and there for instance, the wall/road tiles were reversed. I just edited the text file locally, so if there are comments that are too long or are missing the comment marker, I apologize. The function CHRREAD is something I added to cover up for a font reading function that Petit Computer had that Smile Basic apparently does not. The real trick with this one is that we have not just a tile per character, but we have a tile per pixel in each character. You have to use the box drawing characters to not have strange holes everywhere. To try to make things less monotonous, each road/wall tile is taken from the 0 to 3 spaces from id of the road/wall tile. If you play the game two times in a row, you should get a slightly different looking road/wall pattern. You can easily cheat in the game by going in circles in and out of the finish line. If you are playing fair, the trick is to drift through the turns by turning a bit early and having the trajectory slowly take you the correct path instead of just how you are pointed. If you touch the walls you get bumped back in the opposite direction which will cost you time. Oh, and I forgot if you use the new map I made, make sure to update the map_w and map_h variables to match. It should be fairly simple to make your own track if desired.