I’m trying to create a hyperbolic version of Pong in a Poincaré disk, using C++ and SFML.

Here is my problem: when the ball rebounds on a paddle, I deduce two coordinates allowing me to recover the equation of the hyperbola (as a circle in the Poincaré disc), in implicit form:

$$x^2 + y^2 + ax + by + 1 = 0$$

So, I have my equation, and I can only move my sprite using its x and y Cartesian coordinates - I don’t know how to do it differently.

How can I move my sprite following this circle equation?

Moreover, I would like to represent the Poincaré metric, so the ball's velocity will also vary as a function of the metric and its position (slowing down on the screen as it gets closer to the edge of the disc where space is compressed)…


1 Answer 1


We can solve this by completing the square:

$$\begin{align} x^2 + y^2 + ax + by + 1 &= 0\\ \left(x^2 + ax \right) + \left(y^2 + by \right) + 1 &= 0\\ \left(x^2 + ax + \frac {a^2} 4\right) + \left(y^2 + by + \frac {b^2} 4\right) + 1 - \frac{a^2}4 - \frac{b^2} 4 &= 0\\ \left(x + \frac a 2 \right)^2 + \left(y + \frac b 2 \right)^2 &= \frac {a^2 + b^2} 4 - 1 \end{align}$$

This means the circle's center is at \$\left(-\frac a 2, -\frac b 2\right)\$ and has radius \$r =\frac {\sqrt {a^2 + b^2 - 4}} 2\$ (meaning we lack a real solution if \$a^2 + b^2 < 4\$)

You can compute an offset from the circle's center to your sprite's current coordinates to get its phase angle theta:

theta = atan2(sprite.y + b/2, sprite.x + a/2)

And then move your sprite along this circular arc by incrementing/decrementing theta (depending on whether you want to move counter-clockwise or clockwise).

newPosition.x = cos(theta) * radius - a/2
newPosition.y = sin(theta) * radius - b/2

I'll have to punt for now on the magnitude of the increment to theta that corresponds to a consistent speed under the Poincaré metric, but hopefully this gives you enough to get started. :)


You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .