Need Help With Diagonal Sprite Movement

#1TriforceOfKirbyPosted 8/29/2012 9:54:12 AM
So how would I make my sprite move diagonally? this is my code for movement:
SPSET 0,68,2,0,0,0
SPOFS 0,120,88
@CONTROLS
SPREAD(0),X,Y
SPANIM 0,1,0
B=BUTTON()
IF B AND 1 THEN SPCHR 0,76:SPANIM 0,4,8:GOTO @UP
IF B AND 2 THEN SPCHR 0,68:SPANIM 0,4,8:GOTO @DOWN
IF B AND 4 THEN SPCHR 0,72:SPANIM 0,4,8:GOTO @LEFT
IF B AND 8 THEN SPCHR 0,64:SPANIM 0,4,8:GOTO @RIGHT
GOTO @CONTROLS
@UP
WAIT 1
B=BUTTON()
IF B AND 1 THEN Y=Y-1:SPOFS 0,X,Y:GOTO @UP
GOTO @CONTROLS
@DOWN
WAIT 1
B=BUTTON()
IF B AND 2 THEN Y=Y+1:SPOFS 0,X,Y:GOTO @DOWN
GOTO @CONTROLS
@LEFT
WAIT 1
B=BUTTON()
IF B AND 4 THEN X=X-1:SPOFS 0,X,Y:GOTO @LEFT
GOTO @CONTROLS
@RIGHT
WAIT 1
B=BUTTON()
IF B AND 8 THEN X=X+1:SPOFS 0,X,Y:GOTO @RIGHT
GOTO @CONTROLS
so could someone please help with this? and also if there's any way I can simplify my code that would be great.
---
3DS Friend Code: 1246-9643-6385
#2SirGoukiPosted 8/29/2012 11:07:12 AM
The problem appears to be that you're only checking for one button press each time. Because of how this software works, you have to check for both, using math.

For example, assume up is 2 and right is 4:
SpritePos will be the position of the sprite as SpritePos(Xpos, Ypos)

IF BUTTON() AND 2 THEN SpritePos(0, +1)
IF BUTTON() AND 4 THEN SpritePos(+1, 0)
IF BUTTON() AND 6 THEN SpritePos(+1,+1)

and so on. To check for diagonals, as in the example, you have to add the numbers of both inputs together and update the position in one line. Because SmileBASIC is interpreted instead of compiled, it is already slowed down. Add on to that how much limits they've added and it starts becoming clear why it works the way it does.

Assuming checking seperately would work, your sprite would jagedly move up and right because thats the order we are telling it to move. In XNA (which is what I use mostly, it's designed for indie PC, phone, and 360 games), this wouldn't be a problem because the code updates so fast that you'd see it as one motion even though it's 2.

On PetitComputer, however, the code usually updates slow enough that even drawing one line of text, clearing it and then looping back through can be seen easily. For this reason, you have to check for both directions to be pushed, and move in both directions in the same instruction. The reason you add the numbers together is because button input is handled using bits. In my example, up would really look like this: 0100 and right would be 0010. When you add them together you get 0110. This is why the numbers for all the buttons are double the previous value.

I don't know what direction the 3DS rights binary in, but for simplicity I'm going to go from smallest to highest (1-1024):

This is what input actually looks like to Petit computer (0 off, 1 on)

U D Le Ri A B X Y L R
=================
0 0 0 0 0 0 0 0 0 0

and for us it's
Up = 1
Down = 2
Left = 4
Right = 8
A = 16
B = 32
X = 64
Y = 128
L = 256
R = 512

Thankfully, they made it much easier than having to convert from binary to decimal and back, and you just have to know the last chart. But whats going on behind our code is that Petit Computer is checking the bits (binary values) for each button and direction. I understand this is probably way more information than you asked for, but I find that understanding why it works that way makes it stick easier.
---
Anyone whom uses the pseudo-term "pwn", excepting this statement, is undeniably a n00b.
#3SamKitsunePosted 8/29/2012 11:25:12 AM
I recalled creating a topic that helps it. It's uses trigonometry to move the sprite.

http://www.gamefaqs.com/boards/663843-petit-computer/63636675

I don't know if I can simplify it, but it's a good start if you want to move a sprite diagonally in a more realistic approach. I wish there's an easier way to read button presses simultaneously. The real issue is that BUTTON() function reads in bit, and it's only one variable, combining the bits of the buttons. UP is "1", and RIGHT is "8". You would think that if you hold these two buttons together, it would read "up button is down and right button is down". Actually, it reads BUTTON() == "9", because you combine "1" and "8".

I'm sure that someone or some topic already provides something like this. In the meantime, you can use my code for yourself.
#4TriforceOfKirby(Topic Creator)Posted 8/29/2012 11:45:10 AM
so you are saying that I have to check for combinations of buttons then change both coordinates at once? what would be the best way to do that? for example up-right, would I put that in @UP and @RIGHT, or would I make a separate label @UP-RIGHT? btw the other information was helpful, thanks for that.
---
3DS Friend Code: 1246-9643-6385
#5TriforceOfKirby(Topic Creator)Posted 8/29/2012 11:56:07 AM
using trigonometry to move the sprite? never thought about that, I'll try that
---
3DS Friend Code: 1246-9643-6385
#6TriforceOfKirby(Topic Creator)Posted 8/29/2012 12:13:27 PM
using trigonometry works perfectly! thanks for the help, your fourm helped alot too :D
---
3DS Friend Code: 1246-9643-6385
#7SamKitsunePosted 8/29/2012 12:39:57 PM
I'm glad to help you. ^-^
#8UncleSporkyPosted 8/30/2012 11:35:01 AM(edited)
The problem was not that he was doing the button reads wrong. "B AND 1" etc. is the right way to do it, the AND strips out everything but the first bit and checks if they're pressing up.

The real problem was that you were going directly to the result of the button press, and then going right back to the start of control detection. If you were pressing up, the program never got to check any other directions!

Let's just look at it simply:

@POOP
GOTO @THING
GOTO @MAN
GOTO @HATS
GOTO @RADIO
GOTO @POOP

@THING
<do something>
GOTO @POOP

@MAN
<do something>
GOTO @POOP

@HATS
<do something>
GOTO @POOP

@RADIO
<do something>
GOTO @POOP

Do you see how it will never go to any labels except @THING?

The solution is gosub:

@POOP
GOSUB @THING
GOSUB @MAN
GOSUB @HATS
GOSUB @RADIO
GOTO @POOP

@THING
<do something>
RETURN

@MAN
<do something>
RETURN

@HATS
<do something>
RETURN

@RADIO
<do something>
RETURN

This way the program will do something/check each of the other items before going back to the start of button detection.

You also should not be checking if B AND 1 inside the @UP area. Because you made it to @UP, you already know that the player is pressing up, no need to check again. Just change the variable and the sprite offset and return.
#9dragoneyes718Posted 8/30/2012 11:56:21 AM
I'm about 80% done with a fully functional RPG similar to Dragon Warrior. I'll upload it when I finish. It has some examples of how to do this type of thing. I just need to finish the enemy stats, and place some events and secrets around the map. The cool thing is that you never have to load to get into a town or dungeon. It's all seamless, and I think my battle system is (while being a little simple) quite intuitive. The map itself is 256x256 32x32 pixel tiles. That part took a long time. I think the world map alone takes up 2070ish lines in the program.
---
"Link puts his pants on just like the rest of you -- one leg at a time. Except, once his pants are on, he makes gold cartridges." - BlueGunstarHero
#10TriforceOfKirby(Topic Creator)Posted 8/30/2012 5:57:45 PM
thank you uncle sporky for explaining that, I actually got rid of @UP also I changed my code quite a bit, I will post it, if you see anything that can be done better let me know, it's based off the Fun with trigonometry topic, I did change a few things though
---
3DS Friend Code: 1246-9643-6385