Movement of a point along the coordinates of a circle

Hello friends! Is it possible to direct a point along the coordinates of a circle knowing the radius? Maybe there is some kind of formula?

Maybe have a look at the code of my game “Square Nose”. It has rotations with the character Squiddy and its ball.

Thanks for the tip, but unfortunately this is not enough. I guess I did not explain well what I want to achieve …
The radius can be different, so the point must go in different coordinates, depending on the size of the radius. I want to understand if it is possible to achieve this using some method or formula, so as not to write coordinates for each individual radius.

So … if you know the starting point and you know the radius, can’t you just use COS & SIN to work out the coordinates?

To speed thinks up, you might want to have the SIN / COS tables pre-defined.

Some links >

1 Like

as far as i remember from school X^2+Y^2=R^2 so |Y|=sqrt(R^2-X^2)
but if you need to make jumping game hero you’ll better to follow filmote’s advice )

This is true … however, I think the OP will have a radius and an angle so can calculate X / Y using Sin / Cos.

@filmote @ESPboy
Thanks for answers! To clarify the situation a little. Ultimately I need to bend a line that is always different in length. The top of this line is the point I mentioned earlier. I want to do something like this: drawLine (32, 0, X, Y). Tell me, did I choose the right strategy? Thanks for the links, but it’s too difficult for me, I’m afraid I can’t figure it out without an example. If possible, could you please demonstrate this method? Or can you tell the game where this is implemented? Thank you anyway!

maybe this one

1 Like

This will definitely not be superfluous, thanks! somehow I didn’t think of the clockwise :smiley:

If you want to draw part of a circle that has specific length l, you can do it like:

  1. Compute the circumfence of the circle c = 2 * pi * r.
  2. Compute what fraction of this circumfence has the length you want: x = l / c.
  3. Draw the circle with sin/cos to which you feed values from 0 to x * 2 * pi. (2 * pi draws the whole circle).

Or is this like a racing game where you’re drawing a straight line that suddenly starts to curve and the goes straight again? I’d do this by keeping track of the point coordinates (which should be in some fractions of a pixel) as well as its direction angle, then at each step you shift the point to a new position and draw a line from previous position to the new position. Keeping the angle the same will be drawing a straight line, changing the angle will be curving it.

Next time I will immediately throw off the video of what I want to achieve :grin: This will be a remake of this wonderful and addictive game. I thought I would do it in a day, but I got stuck on lowering the bridge …I hope I can extract the necessary piece of code from the example with the clock

1 Like

so you have constant R and angle changing from 90 grad to 0 grad
let’s angle is A so it could be like this:

uint8_t radius=20; 
for (int8_t A=90; A>0; A--)
  drawline (0, 0, radius*cos(radians(A)), radius*sin(radians(A)), COLOR);

and to make it faster it’s better to take sin and cos in grads (with radians transformation) from the precalculated tables

1 Like

with precalculated sin/cos and fixed point math i think it should be like this

  uint8_t sintabl[90];
  uint8_t costabl[90];
        
   //sin and cos values are always less than 1 so we have to use float but it slow. so we use fixed point math with integers. we can *100 and then /100 but it's faster to devide by 2,4,8,16,32,64,128... so we use *128

  for (uint8_t i=0; i<90; i++){
    sintabl[i]=sin(radians(i))*128; 
    costabl[i]=cos(radians(i))*128; 
  };
  
  uint8_t radius=50;

  for (int8_t A=90; A>0; A--){
    drawLine (0, 0, radius*costabl[A]>>7, radius*sintabl[A]>>7, COLOR);
    // right shift is like deviding. >>7 is equal to /128 but >> maybe faster then /
  }
2 Likes

Here you have a complete working code, try it here:

out

#include <Arduboy2.h>

#define ANIMATION_FRAMES 60 // how many frames bridge animation has, lower => faster animation
#define PI_HALF (3.1415 / 2)
 
Arduboy2 arduboy;

void setup() {
  arduboy.begin();
  arduboy.setFrameRate(30);
}

// Draws bridge of given length starting at pixel [x,y], frame is the frame for animation.
void drawBridge(int x, int y, int length, int frame)
{
  if (frame < ANIMATION_FRAMES / 2) // rising the bridge: draw growing vertical line
    arduboy.drawLine(x,y,x,y - (frame * 2 * length) / ANIMATION_FRAMES);
  else if (frame < ANIMATION_FRAMES) // bridge falling: draw rotating line
  {
    float phase = ((frame - ANIMATION_FRAMES / 2) * PI_HALF) / ((float) ANIMATION_FRAMES / 2); // by reordering the operations here we avoid using float :)
    arduboy.drawLine(x,y,x + sin(phase) * length,y - cos(phase) * length);
  }
  else // bridge on the ground: just draw a horizontal line
    arduboy.drawLine(x,y,x + length,y);
}

void loop() {
  if (!(arduboy.nextFrame()))
    return;

  arduboy.clear();

  drawBridge(10,40,30,arduboy.frameCount);
  
  if (arduboy.frameCount >= 20)
    drawBridge(40,50,21,arduboy.frameCount - 20);

  arduboy.display();
}

This is probably the easiest way to do it, with just one function and without global state, sin/cos is only computed when the bridge is falling.

You don’t really need sin/cos tables here because you’re not calling these functions very often – basically 2x a frame – precalculated values won’t produce any noticeable speedup here. You should only consider this with orders of magnitude larger number of sin/cos calls, like each frame for every pixel.

3 Likes

A drive-by solution that might be half-baked…

(Completely untested, no warranties, I’m a programmer not a mathematician et cetera…)

// If you use int16_t for this then you can just use the one from Arduboy2,
// otherwise, if you want to use float components, you'll have to have your own Point type
struct Point
{
	float x;
	float y;
};

struct Line
{
	Point start;
	Point end;
};

Arduboy2 arduboy;
Line bridge;

void draw()
{
	arduboy.drawLine(bridge.start.x, bridge.start.y, bridge.end.x, bridge.end.y, WHITE);
}

float bridgeAngle = 0;

// 90 Degrees (top/negative Y)
constexpr float raisedBridgeAngle = 1.0f;

// 0 Degrees (right/positive X)
constexpr float loweredBridgeAngle = 0.0f;

// Adjust as required
constexpr float bridgeAngleStep = -0.1f;

// Completely untested, purely theoretical.
void step()
{
	if(bridgeAngle > loweredBridgeAngle)
	{
		// Adjust the angle of the line
		bridgeAngle += bridgeAngleStep;

		// Then recalculate the end of the bridge with the new angle
		recalculateBridgeEnd()
	}
}

// Move the bridge
void setBridge(Point position)
{
	bridge.start = position;
	bridgeAngle = raisedBridgeAngle;

	recalculateBridgeEnd();
}

void recalculateBridgeEnd()
{
	// If the range might exceed int16_t's limits,
	// it might be better to promote to float here
	const int16_t vectorX = (bridge.end.x - bridge.start.x);
	const int16_t vectorY = (bridge.end.y - bridge.start.y);

	// I can't remember if sqrt returns float or double,
	// so I'll let the compiler figure it out for me
	const auto length = sqrt(vectorX * vectorX + vectorY * vectorY);

	// Again, can't remember the return types.
	const auto baseX = cos(bridgeAngle);
	const auto baseY = sin(bridgeAngle);
		
	bridge.end.x = baseX * length; 
	bridge.end.y = baseY * length;
}

Some resources for understanding the theory (since I can’t explain myself at the moment)…

Vectors:
https://www.mathsisfun.com/algebra/vectors.html

The Unit Circle:

A good Youtube series about video game physics including vectors and angles (mostly 2D):

A sneaky link to my ‘Resource Collection’ (which has a link to the above video series among other things):

3 Likes

@ESPboy @filmote @drummyfish @Pharap @JuiceLizard
Guys, thank you so much for your help! Every time I am surprised at the responsiveness of this community😊
With you, any idea can be brought to life, I really appreciate it!

4 Likes

Not sure if it’s exactly what you’re looking for, but I’ve been working on a game with a similar mechanic and I’ve got a demo on GitHub of just how to rotate one point around another on Arduboy: GitHub - poevoid/RotatingBodyDemo: very simple demo demonstrating how to rotate one point around another, for arduboy

1 Like

thanks for the example! I’ve already used the tips above, but your example will definitely come in handy in future projects, thanks! :slightly_smiling_face:

2 Likes