LoginLogin
Nintendo shutting down 3DS + Wii U online services, see our post

Circular Motion using sin&cos?

Root / Programming Questions / [.]

KrondeloCreated:
So I figured out circular motion, pretty simple really. However I can't figure out how to CONTROL it. Like if you hold up you will travel along the circle CCW, and down for CW movement. I imagine you could easily code being able to move in and out as well by simply adjusting the radius.
TPI=6.2831855  '(2*PI)
DEF CIRC D
 WHILE A<TPI
    CX=399/2+COS(A)*D
    CY=239/2+SIN(A)*D
    GCIRCLE CX,CY,CR,RGB(R,G,B)
    A=A+.05
    VSYNC
    GCLS
  WEND
END
So there is the function, but which variable would you manipulate to move along that path or is it not that simple? I tried only increasing A on button press, or only updating the CX and CY positions with pressing DOWN, then for UP simply switch CX to be minus COS. Nothing happens though? Any thoughts?

Uhg, as usual I figure it out shortly after posting. All you have to do is remove the A=A+.05. Then do this:
IF B AND #UP THEN A=A-.05
IF B AND #DOWN THEN A=A+.05

Like you have already noticed, an increase of argument of sin and cos stands for CW rotation, and a decrease stands for CCW rotation. And I recommend you to add the following code in order to avoid overflow/underflow of A variable.
A=A+2*PI()*((A<0)-(A>=(2*PI())))

Here's how I learned circular trajectories.
DEF CIRC X,Y,RX,RY,C
 VAR I,T=PI()*2
 FOR(I)=(0)TO(T)STEP(T/(T*MAX(RX,RY)))
  GPSET(COS(I)*RX+X),(SIN(I)*RY+Y),(C)
 NEXT(I)
END
This function draws an ellipse centered at X,Y with a width of 2*RX and a height 2*RY (with color C). However, you seem to want circular motion. If you follow the math behind drawing an ellipse, you should be able to plot the thing-that's-in-motion at it's position along it's circular path per time.

Thanks @Hanzo and @MZ952, I will study these further. I reset A at the end of the loop but it can cause an object in rotation to suddenly snap back to it's initial position. I think I need to learn more how to implement logical arguments such as the one Hanzo mentioned rather than using weird flags or resets at times that don't always make sense.

Here's how I learned circular trajectories.
DEF CIRC X,Y,RX,RY,C
 VAR I,T=PI()*2
 FOR(I)=(0)TO(T)STEP(T/(T*MAX(RX,RY)))
  GPSET(COS(I)*RX+X),(SIN(I)*RY+Y),(C)
 NEXT(I)
END
This function draws an ellipse centered at X,Y with a width of 2*RX and a height 2*RY (with color C). However, you seem to want circular motion. If you follow the math behind drawing an ellipse, you should be able to plot the thing-that's-in-motion at it's position along it's circular path per time.
You've got a lot of unnecessary parentheses there... Note also that while older BASICs required putting the variable name after NEXT, SmileBASIC actually just ignores it. Also, x/(x*y) simplifies to 1/y, so your step can be simplified.
DEF CIRC X,Y,RX,RY,C
 VAR I,T=PI()*2
 FOR I=0 TO T STEP 1/MAX(RX,RY)
  GPSET COS(I)*RX+X,SIN(I)*RY+Y,C
 NEXT
END

Here's how I learned circular trajectories.
DEF CIRC X,Y,RX,RY,C
 VAR I,T=PI()*2
 FOR(I)=(0)TO(T)STEP(T/(T*MAX(RX,RY)))
  GPSET(COS(I)*RX+X),(SIN(I)*RY+Y),(C)
 NEXT(I)
END
This function draws an ellipse centered at X,Y with a width of 2*RX and a height 2*RY (with color C). However, you seem to want circular motion. If you follow the math behind drawing an ellipse, you should be able to plot the thing-that's-in-motion at it's position along it's circular path per time.
You've got a lot of unnecessary parentheses there... Note also that while older BASICs required putting the variable name after NEXT, SmileBASIC actually just ignores it. Also, x/(x*y) simplifies to 1/y, so your step can be simplified.
DEF CIRC X,Y,RX,RY,C
 VAR I,T=PI()*2
 FOR I=0 TO T STEP 1/MAX(RX,RY)
  GPSET COS(I)*RX+X,SIN(I)*RY+Y,C
 NEXT
END
Ah, good catch with my flawed math there. I came up with it on the fly, didn't think much about rounding it out. The parenthesis I like to put there for structure. My eye catches and reads the code better that way, and it's basically a habit now. And it doesn't exactly affect the performance of the code, either. Oh, and I'm aware of the ignoring thing, too. Sometimes, just for kicks, I'll toss a SQR(-1) in there.

Just for kicks. ;D You guys make me laugh sometimes.

Like you have already noticed, an increase of argument of sin and cos stands for CW rotation, and a decrease stands for CCW rotation. And I recommend you to add the following code in order to avoid overflow/underflow of A variable.
((A<0)-(A>=(2*PI()))))
Actually can someone explain to me what this part does exactly?

Okay, take this example: You have a program that prints things to the screen, but it obviously can't print outside the screen coordinates, because that would produce an error, and the function can print on any screen.
DEF PRNT X,Y,S$
VAR D=DISPLAY()
(X)=MAX(49*!D,39*D)
(Y)=MIN(Y,29)
LOCATE(X),(Y)?S$;
I used a logical argument to set the value of X by saying: X will be the largest of either 49*(logical NOT of D) or 39*(logical value of D). Logically, D will be either 0 or 1, so I could use it for this purpose. If the display was set to 0, then 49*(!0) = 49*(1) which is 49, while 39*(0) is 0. MAX(49,0) is 49. But if D was 1, the opposite would occur. MAX(0,39) is 39. This works for any logical argument ==, <=, >=, !, !=, &&, ¦ ¦ , etc. That's how IF statements work. They're checking for logical TRUE. By saying IF(A==B)THEN you're not checking if A is equal to B, you're checking if A equals B is TRUE. If it is true, it returns 1, otherwise, 0, and because they return a tangible binary value, you can use these logical statements in your mathematics if you'd like.

don't do this lol

A=A+2*PI()*((A<0)-(A>=(2*PI())))
is same as
IF A<0 THEN
 A=A+2*PI()
ELSEIF A>=(2*PI())THEN
 A=A-2*PI()
ENDIF

It would be better to just make a working MOD function and use that:
A=FMOD(A,PI()*2)

DEF FMOD(N,D)
 RETURN N-FLOOR(N/D)*D
END
Though it would probably take several years of moving in the same direction for actual problems to happen if you don't do anything.

It takes somewhere around 2,867,092,000,000,000 degrees before there's an error of even 1 degree between N and DEG(RAD(N)), so I don't think wrapping is really necessary.
OPTION STRICT

VAR DEGREES=0,ERROR
REPEAT
 ERROR=ABS(DEG(RAD(DEGREES)) - DEGREES)
 INC DEGREES,1000000000
UNTIL ERROR>=1
?DEGREES,ERROR
Put another way, if something could do a full 360-degree rotation in one second, and rotated in one direction forever, it would take about 252374 years before its rotation was off by one degree.

Thanks guys, the computational aspect is interesting but I'm certainly not worried. You would never hold one direction in this game for long anyway.