? An Extensive Tutorial on RPG Movement using Sprite to Map Collision ● SmileBASIC Source

Sign In

Register
*Usernames are case-sensitive
Forgot my password
💀

An Extensive Tutorial on RPG Movement using Sprite to Map Collision

This guide assumes you basically know how to program. I'm not going to explain how a FOR loop works or anything. I don't care about explanations; I want code

What

So we've all played those top-down games where you walk around and you DON'T walk through trees/walls/lava. You know, like Pokemon, Zelda, Final Fantasy, and literally any other RPG-style game. Usually these games place the player in the center of the screen and have the map appear to move under your feet as you mush your big dumb fingers against the buttons. I'm gonna teach you how to do this. One way to do it, anyway. There are lots of ways to do this, so don't assume this is the only way. This is gonna be a long tutorial; make sure you have time.

The Beginning

This is a big problem to tackle, so we're going to break it down into pieces like I suggest in my general programming tutorials. The first thing to figure out is... what are we even doing? We want a player to be able to move around a map and have collision detection to block solid objects just like all the other top-down RPGs. Think of Pokemon if you have no clue what this is. We are going to make the player a sprite and the map the background layer. Collision detection will use these two items and nothing else. There will be no "map data"; the collision will be based on the ID of the tiles. We'll see why we're doing it this way later.

The Player (Initialize)

The player is a sprite. So, we'll need to figure out how to set up a sprite. Sprites have a 2 layer system: there is the sprite definition number and the sprite identification number. The definition number is what the sprite looks like, and the identification number is how you work with a particular sprite. This way, you can have many sprites all look the same. For instance, if you had 100 sprites that all looked like the same bullet, each sprite would have a different ID (because they are individual sprites) but they would all have the same definition number. To set up a sprite, you use SPSET to tell the identification number you want and the image you want the sprite to have (the definition number): SPSET 1,856 'NEKOOO This makes sprite 1 into the cat (definition 856). You can use the SmileTool to see what each definition is. Now we need to put it in the middle of the screen. We use SPOFS to move the sprite to an X and Y location. All sprite commands start with the ID of the sprite your want to manipulate. X is pixels across the screen from the left, Y is pixels down from the top: SPSET 1,856 SPOFS 1,200,120 'The screen is 400x240, so divide by 2 for the middle Oh jeez, the sprite isn't actually in the middle. It's a little off. The sprite position is based on the upper-left corner of the sprite, so that CORNER is in the middle of the screen. To fix this, we will use the middle of the sprite as the offset with SPHOME: SPSET 1,856 SPHOME 1,8,8 'The sprite is 16x16, so we make the position use the center SPOFS 1,200,120 'Across 200, down 120 The order of SPHOME and SPOFS doesn't really matter. Cool, we have a player in the middle of the screen.

The Map (Initialize)

Maps in SB are usually drawn on the BG (background). The BG is a set of 4 big sheets of tiles. Tiles are small 16x16 (or 8x8 or 32x32) pictures that can create a repeating pattern. Each picture has a definition number, just like sprites. Most 2D RPGs use this tile format: think about Pokemon and the grass/water tiles. Or Zelda with the same thing: the world is split up into repeatable tiles. We're not going to create a fancy map; we just need stuff to collide with to test. We're going to randomly generate some tiles on one of the four BG layers. We use the BGPUT command to put tiles by definition number into the BG, and RND to randomly spread out the tiles. First, we have to set the layer size. There are limits: look at the manual to see. It's something like 127x127. Next, we fill the perimeters so you can't go out of bounds Finally, we fill random spots so there's SOMETHING. I'm using 107 (a rock) for the perimeter and 100 (trees) for the obstacles. Again, try the SmileTool to see what each tile is. BGCLR 'Get rid of everything in the BG layers BGSCREEN 0,100,100 'Set BG layer 0 to 100 tiles wide and 100 tiles tall FOR I=0 TO 99 '0 to 99 because size is 100 but it starts at 0 'The 4 perimeter walls: top, bottom, left, and right BGPUT 0,I,0,107 BGPUT 0,I,99,107 BGPUT 0,0,I,107 BGPUT 0,99,I,107 NEXT FOR I=1 TO 98 FOR J=1 TO 98 'Loop over every single tile within the layer IF RND(4)==0 THEN BGPUT 0,J,I,100 'A 1 in 4 chance to put a tree for each space (tree is tile 100) NEXT NEXT In your game, you can fill the BG your own way. Draw your game map or something. We now have a map to work with.

Moving Around

Sprites are moved with SPOFS. The coordinates are relative to the upper left corner of the screen, as we saw earlier. The BG is moved with a similar command: BGOFS. It is also relative to the upper left corner of the screen. For instance, if we wanted to move layer 0 of the BG right 50 and down 100, it would be: BGOFS 0,50,100 If you add this to the above map code, you can see the new map position. It updates immediately. In a standard RPG, the player stays in the middle of the screen while the map moves around them as they walk. Thus, our program will only move the BG as the player walks and not the sprite. Notice that the 50,100 is once again using the top left corner of the BG layer as the origin. Setting the BGOFS to 0,0 will put the upper left corner of the layer right up against the upper left corner of the screen. But think about this: where is the player when the BGOFS is 0,0? The player is at 200,120 and hovering over some BG tile in the middle, but the BG location is 0,0. We don't want this: the player should line up with BGOFS. So, a BGOFS of 0,0 should put the upper left corner of the BG underneath our player. We want this because there is a magical command that converts screen coordinates to BG coordinates, and it would be easier to check the screen coordinates under the player rather than over in the corner of the screen. There is a BGHOME command that works similarly to SPHOME: we use it to make BGOFS line up with the center of the screen rather than the upper-left corner. Altogether, the setup code is thus: ACLS 'Clear EVERYTHING (including BG) 'Player sprite setup SPSET 1,856 SPHOME 1,8,8 SPOFS 1,200,120 'Map setup (a random map with perimeter) BGSCREEN 0,100,100 BGHOME 0,200,120 'Make BGOFS line up with center of screen. FOR I=0 TO 99 BGPUT 0,I,0,107 BGPUT 0,I,99,107 BGPUT 0,0,I,107 BGPUT 0,99,I,107 NEXT FOR I=1 TO 98 FOR J=1 TO 98 IF RND(4)==0 THEN BGPUT 0,J,I,100 NEXT NEXT You should get a cat in the middle of the screen at the top left corner of a randomly generated map with rock walls. If you do not, check your code and try again (or maybe I messed up).

Actually Moving Around

At this point the setup is done. You don't need to fill the map like I did; this is just for the purposes of the tutorial. Now to get the player moving around. But remember the player is stationary in the middle of the screen, so what we're REALLY moving around is the BG. If the player walks right, the BG should move left underneath them. Note the various coordinate systems used: screen coordinates for things like sprites, tile coordinates (the 0 through 99) used for the BG tiles, and the BG offset coordinates (which are per BG pixel and not related to the screen). If your BG tiles are 16x16, the BGOFS range is just the BG tile width or height times 16 (so 1600x1600 in our case). Trying to use all these coordinate systems at once is a confusing pain. Instead, we'll pick ONE coordinate system for all collision, movement, and positioning. There is an idea of a "world" coordinate system, where all things (the player, enemies, whatever) are positioned relative to the world. For instance, the player might be 1000 pixels across and 550 pixels down from the upper left corner of the map. This is precisely the BG pixel coordinates, or the BGOFS. It might be counter-intuitive to have the player position be the background offset, but deep down it makes sense. The player is stuck in the middle of the screen. The BG is what moves. You should know how to make movement from my previous tutorials. The basic idea is to convert button inputs to X and Y velocities, then apply those velocities to the position. The position is BGOFS. Check it out: 'Insert this after the setup code above PLX=100 PLY=100 'Player X and Y position. SPD=2 'How fast you can move per frame WHILE TRUE VX=0 VY=0 'Player X and Y velocity (assume none) B=BUTTON(0) 'Set player velocity based on directional input. IF B AND #UP THEN VY=-SPD ELSEIF B AND #DOWN THEN VY=SPD IF B AND #LEFT THEN VX=-SPD ELSEIF B AND #RIGHT THEN VX=SPD PLX=PLX+VX PLY=PLY+VY 'Update player position based on current velocity BGOFS 0,PLX,PLY 'Update the map position to reflect the new player position VSYNC 'Waits for the next screen refresh. Makes game run at 60fps rather than sporadically WEND Together with the setup code, you should be able to "move" the cat around the map (even though you're actually moving the map). You may notice this isn't optimal. We could, for instance, directly update the position in the button checks. However, we need to split position and velocity for the collision code, as you'll see later.

Collision

We want the player sprite to collide with BG tiles. We will use SPCOL and SPHITRC for collision. SPCOL sets collision parameters for a sprite, like the hitbox size and location relative to SPHOME. SPHITRC detects collisions between a sprite and an arbitrary rectangle (hence the RC). The BG tiles are the arbitrary rectangles. The main idea is that we want to check the 3x3 section of tiles around the player to see if any are colliding with where the player WILL be. There's no point checking after moving the player: they'll be in a wall and you have to push them out. The tiles are just rectangles on the screen, so we calculate where they are and use SPHITRC to check the player's new position against each of the 9 surrounding tiles.

Sprite Setup

First, setup the sprite's collision parameters. SPSET 1,856 SPHOME 1,8,8 SPOFS 1,200,120 SPCOL 1,-7,-7,14,14,TRUE,&HFFFFFFFF SPCOL takes an ID, X and Y hitbox position, Width and Height of hitbox, Scaling collision, and a Collision Mask. The X and Y position is relative to SPHOME: our home is the sprite's middle but our hitbox should be at the edge, so it's negative. I'm lenient on collision so there's a 1 pixel free zone around the sprite: instead of the hitbox being 16x16 and lining up perfectly with the sprite, it is 14x14 so the outer edge isn't detected. TRUE means the hitbox will scale with SPSCALE. There are very few cases where this will be FALSE. The &HFFFFFFFF is the collision mask. This value is ANDed with the colliding object's mask and collision is detected if the value is nonzero. For instance, if the player had mask &B101 and the colliding object had mask &B100, collision would be detected. However, if the colliding object's mask is &B010, no collision is detected because no bits match up. &HFFFFFFFF has all the bits set, so collision with anything should be detected (unless the other object's mask is 0). Remember, &B is binary and &H is hexadecimal.

BG Tiles

For each of the surrounding 9 tiles, we first check the tile ID to see if it's something we want to be "solid". Then if it's solid we run SPHITRC to see if we're colliding. A reminder: Our player position is in BG pixels. Our player's sprite is at 200,120 in screen pixels. We need to convert our player's position into the BG tile coordinate (0-99) so we can get the surrounding tile IDs to check if they're solid. BGCOORD is a function which converts BG pixel coordinates to screen coordinates, screen coordinates to BG tile coordinates, or screen coordinates to BG pixel coordinates. The conversion "mode" is specified by a parameter: 0 for BG pixel -> screen, 1 for screen -> BG tile, and 2 for screen -> BG pixel. We will use this function to convert units back and forth; sometimes we will need to apply it twice as it is missing a few modes. We can get the BG tile position underneath the player with code like this: BGCOORD 0,200,120,1 OUT PBGX,PBGY The parameters are BG Layer, X, Y, Mode. It produces a converted X and Y. In this case, we convert Screen coordinates 200,120 (player position on screen) to BG tile coordinates (mode 1) for layer 0. PBGX and PBGY is now the location of the player in BG tile units. You use BGGET to retrieve the ID of a tile on a BG layer. For this example, we'll assume any nonzero tile ID is solid. You can make this check anything you want. You check collision after determining the velocity but before updating the player position. This way, you know the player's movement but you can intercept it and stop it before the actual position update occurs. The code for checking collision with each tile will start like this (within your game loop): BGCOORD 0,200,120,1 OUT PBGX,PBGY FOR X=-1 TO 1 FOR Y=-1 TO 1 'Don't check collision for empty tiles (make this check anything you want) IF BGGET(0,PBGX+X,PBGY+Y)==0 THEN CONTINUE 'Run SPHITRC here? NEXT NEXT The FOR loops check the surrounding tiles (-1 to 1, so 3x3). This will skip tiles that are empty on layer 0. Now the actual hard part: SPHITRC detects collisions with rectangles on the screen. But we're working with BG tile coordinates. BGCOORD to the rescue. One of the BGCOORD modes converts BG pixel coordinates to screen coordinates. There isn't one for BG tile coordinates to screen coordinates, but we can figure out the BG pixel coordinate of the top-left of the tile (the start of the rectangle) with a little math. Using BGCOORD, we can get the screen rectangle coordinates for each of the surrounding BG tiles. While we're at it, we can get SPHITRC set up. Basic SPHITRC takes the ID, Rectangle X and Y, and Rectangle Width and Height and returns TRUE if the sprite with ID is colliding with the given rectangle on screen. The SPHITRC we use is more advanced: we also give the collision mask and the movement speed of the rectangle. The rectangle movement speed is negative: the player might be moving forward, but the map moves in reverse. If the player is moving right (positive X velocity), the map is moving left (negative X velocity). The loop now looks like this: BGCOORD 0,200,120,1 OUT PBGX,PBGY FOR X=-1 TO 1 FOR Y=-1 TO 1 IF BGGET(0,PBGX+X,PBGY+Y)==0 THEN CONTINUE BGCOORD 0,(PBGX+X)*16,(PBGY+Y)*16,0 OUT RCX,RCY IF SPHITRC(1,RCX,RCY,16,16,&H1,-VX,-VY) THEN VX=0:VY=0 NEXT NEXT RCX and RCY is the screen location of the upper left corner of the BG tile we're checking. Each tile is 16x16, so those are the width and height. If a hit is detected, we want to stop the player's movement (solid objects, you know), so we set their velocity to 0. The mask is &H1: it can be anything because our player mask is the full set &HFFFFFFFF.

All Together Now (Lv. 1)

Here's the whole thing together. Try it out and see how it runs: ACLS 'Player Setup SPSET 1,856 SPHOME 1,8,8 SPOFS 1,200,120 SPCOL 1, -7,-7,14,14,TRUE,&HFFFFFFFF 'Map Setup BGSCREEN 0,100,100 BGHOME 0,200,120 FOR I=0 TO 99 BGPUT 0,I,0,107 BGPUT 0,I,99,107 BGPUT 0,0,I,107 BGPUT 0,99,I,107 NEXT FOR I =1 TO 98 FOR J=1 TO 98 IF RND(4)==0 THEN BGPUT 0,J,I,100 NEXT NEXT 'Movement and Collision (the game) PLX=100 PLY=100 SPD=2 BGOFS 0,PLX,PLY 'Make sure the BG is set to the player's position before starting. WHILE TRUE VX=0 VY=0 B=BUTTON(0) IF B AND #UP THEN VY=-SPD ELSEIF B AND #DOWN THEN VY=SPD IF B AND #LEFT THEN VX=-SPD ELSEIF B AND #RIGHT THEN VX=SPD 'Our collision loop from just earlier: BGCOORD 0,200,120,1 OUT PBGX,PBGY FOR X=-1 TO 1 FOR Y=-1 TO 1 IF BGGET(0,PBGX+X,PBGY+Y)==0 THEN CONTINUE BGCOORD 0,(PBGX+X)*16,(PBGY+Y)*16,0 OUT RCX,RCY IF SPHITRC(1,RCX,RCY,16,16,&H1,-VX,-VY) THEN VX=0:VY=0 NEXT NEXT PLX=PLX+VX PLY=PLY+VY BGOFS 0,PLX,PLY VSYNC WEND You may notice some... undesired features. For starters, if you spawn in a block (a 1 in 4 chance), you can't move. At all. If this happens while testing, you can restart the program until you're free. Alternatively, you can remove all blocks generated around the player. A bigger problem: you can't move diagonally across a flat surface and slide along it. This feature is present in basically all RPGs but not here. If you are OK with this, you can stop here and use just this code. We're going to complicate this further by overcoming this diagonal sliding limitation.

Wall-Sliding Magic

To slide along the wall, you have to determine WHICH velocity should be blocked and ONLY block that. For instance, if there is a wall to your right and you're trying to move diagonally up and right, only the X velocity should be blocked since that's where the wall (solid object) is. To do this, we have to individually test each direction to see which one gets blocked. Checking movement on each axis individually lets you block only the direction which put you into an obstacle. But what happens if you hit a corner perfectly? The player is allowed to move and gets stuck in the corner. Thus, we still must perform the original check for a total of 3 collision checks per tile. However, the 3 collision checks (up/down, left/right, original) are not all equally important. For instance, what happens if one tile has a corner collision but another tile only has a sideways collision? The solution is to keep track of all single direction hits and only do a corner block if absolutely necessary. We accumulate the direction hits so that if one tile blocks your horizontal and a different blocks your vertical, you are blocked from both directions (for instance, if you're in a corner). We'll use value &H1 to represent horizontal and &H2 to represent vertical. Together (as a corner) this is &H3. To make the code run faster, we check the corner hit first, then only check the 2 axis hits if the corner was hit. This way, we save 2 collision checks if the tile simply isn't colliding. To make this work, we assume the corner hit is the only hit (set value to &H3), then check the 2 axis hits and remove the impossible ones (remove horizontal &H1 if vertical collision, remove vertical &H2 if horizontal collision). This is in contrast to checking all 3 collision types and setting the hit value accordingly. Our updated tile checking loop: CORNERS=0 'How many corners we're colliding with ALLHITS=0 'All single directional hits for all tiles BGCOORD 0,200,120,1 OUT PBGX,PBGY FOR X=-1 TO 1 FOR Y=-1 TO 1 IF BGGET(0,PBGX+X,PBGY+Y)==0 THEN CONTINUE BGCOORD 0,(PBGX+X)*16,(PBGY+Y)*16,0 OUT RCX,RCY IF SPHITRC(1,RCX,RCY,16,16,&H1,-VX,-VY) THEN 'Corner hit test HIT=&H3 'Assume hitting from two directions IF SPHITRC(1,RCX,RCY,16,16,&H1,-VX,0) THEN HIT=HIT AND NOT &H2 'If hitting from sides, assume not hitting from top/bottom IF SPHITRC(1,RCX,RCY,16,16,&H1,0,-VY) THEN HIT=HIT AND NOT &H1 'If hitting from top/bottom, assume not hitting from sides IF (HIT AND &H3)==&H3 THEN CORNERS=CORNERS+1 'If no hit directions were removed, this is a pure corner collision ELSE ALLHITS=ALLHITS OR HIT 'A single direction hit. Combine with other detected single hits ENDIF ENDIF NEXT NEXT 'Only update position if no hits in that direction IF !(ALLHITS AND &H1) THEN PLX=PLX+VX IF !(ALLHITS AND &H2) THEN PLY=PLY+VY Notice the single direction collision checks have -VX,0 and 0,-VY as velocities (respectively). That's movement only in X for the first, and movement only in Y for the second.

Optimizations / Better stuff

If you run that above code, you'll run into some weird bugs. This is because we're performing more checks so we're "spreading out" the amount of things we can collide with... like blocks behind us. We don't need to check those: we only need to check the blocks in an "arrow" around the player rather than all 9 blocks. Furthermore, we still have a problem with corners. What if we hit JUST a corner (no other tiles so no sliding)? The player will stop entirely. Instead, we PICK a direction for them based on which directional velocity is greater. It's like you're cutting the corner: if you're walking more straight up and down (but still a bit diagonal), you'll cut on the side of the tile and move up (or down). If you're walking more left and right (but still a bit diagonal), you'll cut on the bottom of the tile and move right (or left). We can skip unnecessary tiles with this check inside the loop: IF !((Y==0 && X==0) || (VY!=0 && SGN(VY)==SGN(Y) || VX!=0 && SGN(VX)==SGN(X))) THEN CONTINUE It creates those shapes above. Basically it says "always check the center tile (0,0), then only check tiles in the direction we're moving". SGN returns 1,0, or -1 based on if the parameter is positive, 0 or negative. It means "give me the sign of the number". The "cut corners" code looks like this: IF CORNERS>0 && ALLHITS==0 THEN IF ABS(VX)>ABS(VY) THEN ALLHITS=&H2 ELSE ALLHITS=&H1 ENDIF Remember, we ONLY want to process corners if there are no alternatives. ALLHITS is all single direction hits for all checked tiles, so if it's 0 there were no single direction hits. ABS removes the sign on the parameter so the value is always positive. It is the "magnitude" of the number, so ABS(6) == 6 and ABS(-5) == 5.

All Together Now (Final)

ACLS 'Clear everything 'Player Setup SPSET 1,856 'Set our player (1) to the cat (856) SPHOME 1,8,8 'Set player position relative to center of sprite SPOFS 1,200,120 'Put player in the center of the screen SPCOL 1, -6.99,-6.99,13.98,13.98,TRUE,&HFFFFFFFF 'Set sprite collision boundaries. 'SPCOL is relative to SPHOME (the center), so -6.99,-6.99 is nearly 7 to the left and up from the center, and 13.98,13.98 is the width/height. 'TRUE says the sprite collision scales with SPSCALE. &HFFFFFFFF is the 32 bit collision mask (collide with anything) 'Map Setup BGSCREEN 0,100,100 'Set BG layer 0 to be 100 tiles width and tall BGHOME 0,200,120 'Place BGOFS 0,0 in the middle of the screen 'These FOR loops fill the map for our collision test. You can use your own map here/ FOR I=0 TO 99 'The rock perimeter BGPUT 0,I,0,107 '107 is a weird rock BGPUT 0,I,99,107 BGPUT 0,0,I,107 BGPUT 0,99,I,107 NEXT FOR I =1 TO 98 FOR J=1 TO 98 'Random trees (1 in 4 chance) IF RND(4)==0 THEN BGPUT 0,J,I,100 NEXT NEXT 'Movement and Collision (the game) PLX=100 'Player position (relative to BG pixels) PLY=100 SPD=2 WHILE TRUE VX=0 'Assume no player velocity VY=0 B=BUTTON(0) 'Set player velocity based on directional input. IF B AND #UP THEN VY=-SPD ELSEIF B AND #DOWN THEN VY=SPD IF B AND #LEFT THEN VX=-SPD ELSEIF B AND #RIGHT THEN VX=SPD ALLHITS=0 'Collect all hit directions. &H1 is left/right hit and &H2 is up/down hit CORNERS=0 'Count corner hits. You get stuck on corners if you don't handle them special BGCOORD 0,200,120,1 OUT PBGX,PBGY 'Get the TILE location the player is in. FOR X=-1 TO 1 FOR Y=-1 TO 1 'Scan the 3x3 section of tiles around the player 'Only check tiles in an "arrow" shape pointing towards the movement IF !((Y==0 && X==0) || (VY!=0 && SGN(VY)==SGN(Y) || VX!=0 && SGN(VX)==SGN(X))) THEN CONTINUE 'This is where you'd figure out if a tile is solid. I say any non-zero tile is solid. IF BGGET(0,PBGX+X,PBGY+Y)==0 THEN CONTINUE 'Convert BG pixel coordinates of tile's upper left corner to screen coordinates. BGCOORD 0,(PBGX+X)*16,(PBGY+Y)*16,0 OUT RCX,RCY 'Check collision of tile rectangle with sprite. 'Rectangle shifted by negative velocity (map moves in opposite direction of player). 'Mask (&H1) can be anything set in player mask (so anything) IF SPHITRC(1,RCX,RCY,16,16,&H1,-VX,-VY) THEN HIT=&H3 'Assume hitting from two directions IF SPHITRC(1,RCX,RCY,16,16,&H1,-VX,0) THEN HIT=HIT AND NOT &H2 'If hitting from sides, assume not hitting from top/bottom IF SPHITRC(1,RCX,RCY,16,16,&H1,0,-VY) THEN HIT=HIT AND NOT &H1 'If hitting from top/bottom, assume not hitting from sides IF (HIT AND &H3)==&H3 THEN CORNERS=CORNERS+1 'If no hit directions were removed, this is a pure corner collision ELSE ALLHITS=ALLHITS OR HIT 'A single direction hit. Add it to the "all possible hit directions" ENDIF ENDIF NEXT NEXT 'If the only hit we have is a corner, choose a direction based on velocity magnitude IF CORNERS>0 && ALLHITS==0 THEN IF ABS(VX)>ABS(VY) THEN ALLHITS=&H2 ELSE ALLHITS=&H1 ENDIF 'Only update position if no hits in that direction IF !(ALLHITS AND &H1) THEN PLX=PLX+VX IF !(ALLHITS AND &H2) THEN PLY=PLY+VY BGOFS 0,PLX,PLY 'Update the map position to reflect the new player position VSYNC 'Waits for the next screen refresh. Makes game run at 60fps rather than sporadically WEND
Author
randomous
Updated
Rating
15 votes
Categories
Keywords
  • collision
  • sprite
  • map
  • movement
  • bg
  • random
  • bgofs
  • sphome
  • bghome
60 Comment(s) spaceturtles spaceturtles Video Games I like to play video games! Hobbies Avatar Block I didn't change my avatar for 30 days. Website Intermediate Programmer I can make programs, but I still have trouble here and there. Programming Strength Couldn't INC CORNERS be used instead of CORNERS=CORNERS+1? randomous randomous Owner Robot Hidden Easter Eggs Second Year My account is over 2 years old Website Drawing I like to draw! Hobbies Yes; I just like the explicit version lol. MochaProbably MochaProbably Expert Programmer Programming no longer gives me any trouble. Come to me for help, if you like! Programming Strength Night Person I like the quiet night and sleep late. Express Yourself Drawing I like to draw! Hobbies randomous, you dare devil spaceturtles spaceturtles Video Games I like to play video games! Hobbies Avatar Block I didn't change my avatar for 30 days. Website Intermediate Programmer I can make programs, but I still have trouble here and there. Programming Strength Back to top "button": https://smilebasicsource.com/page?pid=958 Waffles_X Waffles_X Night Person I like the quiet night and sleep late. Express Yourself Intermediate Programmer I can make programs, but I still have trouble here and there. Programming Strength Touhou Project Is Awesome! I love Touhou Project! Express Yourself Great tutorial, one question though. When we make the bg move, how could I make it move to just the edges of the screen and also have the sprite go into the corners of the screen. I know that we would have to move the sprite not letting it go past x=399 and y=239. What else would I need to do to make it work? randomous randomous Owner Robot Hidden Easter Eggs Second Year My account is over 2 years old Website Drawing I like to draw! Hobbies Basically you'd have two modes: one where the BG moves and one where the sprite moves. If the sprite is in a certain X/Y range (the middle of the map), you'd be in "bg moving" mode and your inputs would shift the bg. Otherwise if it's in the other range (the edges) you'd shift the sprite instead. You'll have to tweak some other stuff too; for instance, you can't assume the sprite is at 200,120 like I do here. I have a generalized approach in Random's Big Dumb Library; you can look at the GAMECOLLIDE (or something like that) functions to see the general approach. It's a bit more work though. Waffles_X Waffles_X Night Person I like the quiet night and sleep late. Express Yourself Intermediate Programmer I can make programs, but I still have trouble here and there. Programming Strength Touhou Project Is Awesome! I love Touhou Project! Express Yourself Thanks. I never thought to do things like that. In terms of modes, I mean. Thanks for the tutorial. randomous randomous Owner Robot Hidden Easter Eggs Second Year My account is over 2 years old Website Drawing I like to draw! Hobbies Yeah, no problem! Waffles_X Waffles_X Night Person I like the quiet night and sleep late. Express Yourself Intermediate Programmer I can make programs, but I still have trouble here and there. Programming Strength Touhou Project Is Awesome! I love Touhou Project! Express Yourself So far I have this. IF (PLY>=0 AND PLY<=YMIN) OR (PLY>=YMAX AND PLY<=1575) OR (PLX>=0 AND PLX<=XMIN) OR (PLX>=XMAX AND PLX<=1575) THEN MODE=1 ELSE MODE=0 Then later on we the velocities get added... IF !(ALLHITS AND &H1) && MODE==0 THEN PLX=PLX+VX IF !(ALLHITS AND &H2) && MODE==0 THEN PLY=PLY+VY IF !(ALLHITS AND &H1) && MODE==0 THEN PX=PX+VX IF !(ALLHITS AND &H2) && MODE==0 THEN PY=PY+VY I was gonna worry about collision later. As far as what I have, it works to an extent. What do you think I should add or change? Because when I exit the range I am getting atuck and the sprite is forced to a certain position. randomous randomous Owner Robot Hidden Easter Eggs Second Year My account is over 2 years old Website Drawing I like to draw! Hobbies I'm sorry, there are too many things it could be. I'd have to look at the whole code and even then I might not be able to figure it out. It's hard enough to debug your own code, let alone someone else's. Waffles_X Waffles_X Night Person I like the quiet night and sleep late. Express Yourself Intermediate Programmer I can make programs, but I still have trouble here and there. Programming Strength Touhou Project Is Awesome! I love Touhou Project! Express Yourself Ohh... Well thanks anyways. I am close to figuring it out now. ToadIsTheBest ToadIsTheBest Video Games I like to play video games! Hobbies Drawing I like to draw! Hobbies Expert Programmer Programming no longer gives me any trouble. Come to me for help, if you like! Programming Strength The SPHOME 1,8,8 keeps on giving me Illegal function call in 0:4(SPHOME:1) am I supposed to put it in The FOR loop or something? spaceturtles spaceturtles Video Games I like to play video games! Hobbies Avatar Block I didn't change my avatar for 30 days. Website Intermediate Programmer I can make programs, but I still have trouble here and there. Programming Strength No, it should be right after the sprite definition. Did you set the right sprite number in it and in SPHOME? ToadIsTheBest ToadIsTheBest Video Games I like to play video games! Hobbies Drawing I like to draw! Hobbies Expert Programmer Programming no longer gives me any trouble. Come to me for help, if you like! Programming Strength all i put was SPHOME 1,8,8 spaceturtles spaceturtles Video Games I like to play video games! Hobbies Avatar Block I didn't change my avatar for 30 days. Website Intermediate Programmer I can make programs, but I still have trouble here and there. Programming Strength So you must be trying to set the offset home of a nonexistent sprite? ToadIsTheBest ToadIsTheBest Video Games I like to play video games! Hobbies Drawing I like to draw! Hobbies Expert Programmer Programming no longer gives me any trouble. Come to me for help, if you like! Programming Strength No, the cat is set to sprite slot 1 spaceturtles spaceturtles Video Games I like to play video games! Hobbies Avatar Block I didn't change my avatar for 30 days. Website Intermediate Programmer I can make programs, but I still have trouble here and there. Programming Strength What does your code look like? If it's long I would suggest using github or pastebin. ToadIsTheBest ToadIsTheBest Video Games I like to play video games! Hobbies Drawing I like to draw! Hobbies Expert Programmer Programming no longer gives me any trouble. Come to me for help, if you like! Programming Strength ACLS BGMSTOP XSCREEN 3 LOAD GRP4:E,FALSE SPDEF 0,0,0,48,72,0,0,1 SPSET 0,0 SPSCALE 0,2,2 SPOFS 0,155,40 BEEP 39 BACKCOLOR RGB(0,0,0) WAIT 100 BGMSTOP ACLS BGMPLAY 9 SPSET 0,856 SPOFS 0,190 105 SPSCALE 0,1,1 SPHOME 1,8,8 while writing this i noticed i used the wrong management number lol spaceturtles spaceturtles Video Games I like to play video games! Hobbies Avatar Block I didn't change my avatar for 30 days. Website Intermediate Programmer I can make programs, but I still have trouble here and there. Programming Strength Problem solved ;) 12Me21 12Me21 Admin Syntax Highlighter Received for creating the code syntax highlighter on SBS Night Person I like the quiet night and sleep late. Express Yourself Second Year My account is over 2 years old Website I've never understood the reason that websites have links that take you to the top of a page... until now. Actually no, mobile browsers just suck. MasterR3C0RD MasterR3C0RD Helper Received for being very helpful around SmileBASIC Source Achievements Second Year My account is over 2 years old Website osu! Is Awesome! I love osu! Express Yourself +1 Add "Back to top" link plz Y_ack Y_ack Head Admin use [Home] or C-UpArr or Alt-Shift-s 12Me21 12Me21 Admin Syntax Highlighter Received for creating the code syntax highlighter on SBS Night Person I like the quiet night and sleep late. Express Yourself Second Year My account is over 2 years old Website press enter lumage spaceturtles spaceturtles Video Games I like to play video games! Hobbies Avatar Block I didn't change my avatar for 30 days. Website Intermediate Programmer I can make programs, but I still have trouble here and there. Programming Strength MasterR3CORD what browser are you using? Shelly Shelly Wait guys, I figured it outThis post is a SECRET contest to see who can make the most edits to a single post MochaProbably MochaProbably Expert Programmer Programming no longer gives me any trouble. Come to me for help, if you like! Programming Strength Night Person I like the quiet night and sleep late. Express Yourself Drawing I like to draw! Hobbies 0o0 Nice! I’m going to participate! No frick frack that 12Me21 12Me21 Admin Syntax Highlighter Received for creating the code syntax highlighter on SBS Night Person I like the quiet night and sleep late. Express Yourself Second Year My account is over 2 years old Website It might be simpler to generate the map using 2 BGFILLs instead of a for loop. randomous randomous Owner Robot Hidden Easter Eggs Second Year My account is over 2 years old Website Drawing I like to draw! Hobbies It might be less code but is it more understandable? I'm not sure... plus I don't want to go back and edit all that lol. ToadIsTheBest ToadIsTheBest Video Games I like to play video games! Hobbies Drawing I like to draw! Hobbies Expert Programmer Programming no longer gives me any trouble. Come to me for help, if you like! Programming Strength what’s a for loop? it sounds stupid when goto loops exist Chemicalex Chemicalex Drawing I like to draw! Hobbies RNG Hidden Easter Eggs Video Games I like to play video games! Hobbies Oh goodness, you have a lot to learn, child. FOR loops are much more practical and useful than *shiver* "goto" loops. Look into them in the manual. ToadIsTheBest ToadIsTheBest Video Games I like to play video games! Hobbies Drawing I like to draw! Hobbies Expert Programmer Programming no longer gives me any trouble. Come to me for help, if you like! Programming Strength @LOOP PRINT “Loop” GOTO @LOOP TheV360 TheV360 Intermediate Programmer I can make programs, but I still have trouble here and there. Programming Strength First Day Joined on the very first day of SmileBASIC Source Website Night Person I like the quiet night and sleep late. Express Yourself GOTO loops are a mistake in reality. WHILE loops are better. They
  1. look better in your code and it's clear what they do
  2. easily check a condition and if it's true, run the code until the condition is not true
  3. don't have to have a unique name
  4. are still used in modern languages
REPEAT UNTIL loops are better. They
  1. look better in the code and it's clear what they do
  2. easily check a condition (after running once) and if it's false, continue looping until the condition is true
  3. don't have to have a unique name
  4. are still used in modern languages
FOR loops are better. They
  1. look better in the code and it's clear what they do
  2. easily loop a specific number of times with a variable
  3. don't have to have a unique name, just need a variable to increment
  4. are still used in modern languages
Also, before you ask, DEFs are better than GOSUBs. They
  1. look better in the code and it's clear what they do
  2. easily let you make your own commands and functions
  3. have parameters built-in
  4. are still used in modern languages
ProKuku ProKuku Avatar Taboo I didn't change my avatar for 180 days Website First Year My account is over 1 year old Website Pokemon Is Awesome! I love Pokemon! Express Yourself You should almost always use either FOR, WHILE, or REPEAT loops, GOTO loops just make everything harder to look at and understand. ToadIsTheBest ToadIsTheBest Video Games I like to play video games! Hobbies Drawing I like to draw! Hobbies Expert Programmer Programming no longer gives me any trouble. Come to me for help, if you like! Programming Strength Goto loops are extremely easy to understand ProKuku ProKuku Avatar Taboo I didn't change my avatar for 180 days Website First Year My account is over 1 year old Website Pokemon Is Awesome! I love Pokemon! Express Yourself Yes, the general concept of a GOTO loop is simple, but when you have many, many loops with different names, you get confused about what goes where quickly. TheV360 TheV360 Intermediate Programmer I can make programs, but I still have trouble here and there. Programming Strength First Day Joined on the very first day of SmileBASIC Source Website Night Person I like the quiet night and sleep late. Express Yourself Look at this code: @LOOP1 THING=0 @LOOP2 PRINT THING THING=THING+1 IF THING<10 THEN:GOTO @LOOP2 WAIT 60 GOTO @LOOP1 and look at this code: WHILE TRUE FOR THING=0 TO 9 PRINT THING NEXT THING WAIT 60 WEND Which one has a clearer function, is shorter, and is easily portable? The second one. GOTO loops are easy to understand, but so are WHILE, REPEAT UNTIL, and FOR loops. GOTO loops make a FOR loop and a WHILE loop look the same, causing confusion. In short: Instead of this:@LOOP PRINT "GOTO LOOPS 4EVER" GOTO @LOOPuse this:WHILE TRUE PRINT "FRIENDSHIP ENDED WITH GOTO" WEND Instead of this:IF COUNTER>4 THEN GOTO @SKIP @LOOP PRINT "counter is ";COUNTER COUNTER=COUNTER-1 IF COUNTER<=0 THEN GOTO @SKIP GOTO @LOOP @SKIPuse this:WHILE COUNTER<=4 && COUNTER>0 PRINT "counter is ";COUNTER COUNTER=COUNTER-1 WEND Instead of this:COUNTER=0 @LOOP PRINT "the counter is ";COUNTER COUNTER=COUNTER+1 IF COUNTER>=10 THEN GOTO @SKIP GOTO @LOOP @SKIPuse this:FOR COUNTER=0 TO 9 PRINT "the counter is ";COUNTER NEXT COUNTER ToadIsTheBest ToadIsTheBest Video Games I like to play video games! Hobbies Drawing I like to draw! Hobbies Expert Programmer Programming no longer gives me any trouble. Come to me for help, if you like! Programming Strength I’m confused... ProKuku ProKuku Avatar Taboo I didn't change my avatar for 180 days Website First Year My account is over 1 year old Website Pokemon Is Awesome! I love Pokemon! Express Yourself Basically, GOTO loops are good for learning the basics of programming, but you need to move on to the other three once you get the hang of it. TheV360 TheV360 Intermediate Programmer I can make programs, but I still have trouble here and there. Programming Strength First Day Joined on the very first day of SmileBASIC Source Website Night Person I like the quiet night and sleep late. Express Yourself It's just a list of different situations where using non-GOTO commands make the code clearer. I recommend the How to program series and the Petit Professor series (despite my absolute hatred of GOTO loops, the Petit Professor videos are very helpful) ToadIsTheBest ToadIsTheBest Video Games I like to play video games! Hobbies Drawing I like to draw! Hobbies Expert Programmer Programming no longer gives me any trouble. Come to me for help, if you like! Programming Strength I watch petit professor MasterR3C0RD MasterR3C0RD Helper Received for being very helpful around SmileBASIC Source Achievements Second Year My account is over 2 years old Website osu! Is Awesome! I love osu! Express Yourself The only practical use for GOTO is if you need raw performance, which is rare for the most part. So use FOR, WHILE, REPEAT, etc if you're doing things that don't need super-speed.
SpiderLily SpiderLily Thank you random! This should help a lot! randomous randomous Owner Robot Hidden Easter Eggs Second Year My account is over 2 years old Website Drawing I like to draw! Hobbies No problem! I hope it's actually helpful in the end Shelly Shelly It sucks that now that miiverse is gone, there aren't any more posts with screenshots. Tutorial for good photo-taking of screens? Might be useful. randomous randomous Owner Robot Hidden Easter Eggs Second Year My account is over 2 years old Website Drawing I like to draw! Hobbies I was hoping people with hacked 3DS's would be nice and take screenshots for other users or something. Shelly Shelly Would that be appreciated? I would love to get that setup on my Luma3ds if it would be appreciated! I would just download keys, and take screenshots? randomous randomous Owner Robot Hidden Easter Eggs Second Year My account is over 2 years old Website Drawing I like to draw! Hobbies I was thinking there'd be a thread and people would request screenshots of certain parts of their games and other people would provide them. I'll make the thread at some point. Shelly Shelly Okay then, let me get started on making that possible. Autz64 Autz64 End of 2017 Contest Participant I participated in the SmileBASIC Source End of 2017 Contest! Programming Contest Avatar Taboo I didn't change my avatar for 180 days Website Deep Sleep Hidden Website Thing is that CFW screenshot programs are kinda broken when it comes to SB, because the way SB handle colors. The best bet is using an external camera, but anyone can do that regardless of having CFW. randomous randomous Owner Robot Hidden Easter Eggs Second Year My account is over 2 years old Website Drawing I like to draw! Hobbies Oh shoot really? That sucks; thanks for letting me know Y_ack Y_ack Head Admin It might be possible to repair Trinitro hypothesizes that it's CFW assuming 24-bit color(?) where SB uses 16-bit Shelly Shelly Really? That sucks, but its good that you let me know before I got deep into the process. Also, I recently learned that CFW options only work on the new 3ds, and I have an old one (and don't feel like forking over money for the new one). Anyways, I am doing research into the LCDs the 3ds uses. From what I've heard it should be fairly easy to make a pcb for video capture. I'll comment again once I have a better foundation of technical details. 12Me21 12Me21 Admin Syntax Highlighter Received for creating the code syntax highlighter on SBS Night Person I like the quiet night and sleep late. Express Yourself Second Year My account is over 2 years old Website It should be super easy to fix the color as long as the screenshots are saved in a lossless format. MochaProbably MochaProbably Expert Programmer Programming no longer gives me any trouble. Come to me for help, if you like! Programming Strength Night Person I like the quiet night and sleep late. Express Yourself Drawing I like to draw! Hobbies Take a picture with the external camera and set the photo to support only 16 bit colors and resize/adjust the picture to make the screen look like it’s a near perfect rectangle. Shelly Shelly If its possible I would like to solder some pcbs for capture cards, and distribute the capture cards to people on this forum. First I need to do some pricing, but I would need a list of who would be interested. Also, please message me for the schematic if you want it. I'll keep you updated. Also @randomouscrap, sorry for turning this into a capture card/ screen recorder discussion. Autz64 Autz64 End of 2017 Contest Participant I participated in the SmileBASIC Source End of 2017 Contest! Programming Contest Avatar Taboo I didn't change my avatar for 180 days Website Deep Sleep Hidden Website Yeah. Fixing the colors would be "easy", and more with uncompressed format. Thing is when two different colors merges to form one single color, as happened at a screenshot i made, it will be difficult to sepparate. I think modifying Luma's screenshot could help a lot to avoid the color-guess game. ChangeV ChangeV Expert Programmer Programming no longer gives me any trouble. Come to me for help, if you like! Programming Strength Staff Pick "Your program is one of our favorites!" - Staff Achievements There are several ways to capture the screenshot. This is Loopy mod screenshot of old 3DS US. Screenshot is saved as .PNG. These are Nisetro mod screenshots of old 3DS LL JP. 3DS viewer software has no screenshot option. Alt + PrintScreen key to capture screenshot including the 3DS viewer too. then paste/save as png in graphic editor such as paint.net. The second screenshot is 3D side-by-side mode. you can see 3D using cross-eye method. These are non-modded normal WiiU JP screenshots captured with Hauppauge! HDPVR2 Screenshot is saved as .BMP (I converted these images as smaller jpg file. original BMP is 6 MB) This is combined display mode. both upper and lower screen are displayed on TV and it can be captured with any HDMI TV capture device. Pressing SELECT will change display mode. upper screen is displayed as fullscreen on TV(it can be captured with any HDMI TV capture device). lower screen is displayed on WiiU gamepad. There is no way to capture the lower gamepad screen only. both combine/full display modes are pretty bad because SmileBASIC added unnecessary border and scaled badly. It is not pixel perfect. Perska Perska Summer 2016 Contest Winner I won the SmileBASICSource Summer 2016 Contest! Programming Contest Expert Programmer Programming no longer gives me any trouble. Come to me for help, if you like! Programming Strength Great Page Hidden Achievements @Autz64 While Luma3DS's screenshot function isn't the best with SB, NTR CFW does take accurate screenshots. Autz64 Autz64 End of 2017 Contest Participant I participated in the SmileBASIC Source End of 2017 Contest! Programming Contest Avatar Taboo I didn't change my avatar for 180 days Website Deep Sleep Hidden Website @Perska For real? I though that NTR was the same case. Going to test. EDIT: It works! spaceturtles spaceturtles Video Games I like to play video games! Hobbies Avatar Block I didn't change my avatar for 30 days. Website Intermediate Programmer I can make programs, but I still have trouble here and there. Programming Strength If using an external camera is too ugly and cfw is acting up, then petit modem and an image editing program like gimp or paint could be used to make a "screenshot". Just copy/paste your sprites, bg tiles, etc. and add whatever else. Text could be a little difficult though.