I am working on a 2D top-view grid-based game. A ball that rolls on the grid made up of different tiles. The tiles interact with the ball in a variety of ways.

I am having difficulty cleanly implementing the turning tile. The image below represents a single tile in the grid, which turns the ball by a right angle.

Turning tile

If the ball rolls in from the bottom, it smoothly changes direction and rolls to the right. If it rolls in from the right, it is turned smoothly to the bottom. If the ball rolls in from top or left, its trajectory remains unchanged by the tile.

The tile shouldn't change the magnitude of the velocity of the ball - only change its direction.

The ball has Velocity and Position vectors, and the tile has Position and Dimension vectors.

I have already implemented this, but the code is messy and buggy. What is an elegant way to achieve this, preferably by modification of the ball's Velocity vector by a formula?


1 Answer 1


I assume you know how to find out when the ball enters that specific tile. Based on which side the ball enters the tile, you should move it until the ball leaves that specific tile. Based on your problem, when you detect the ball entered from top or left edge, you just let it move without changing it's velocity at all. Let's assume the ball enters from right edge, you should make the ball move on a quarter of a circle. There are two possible scenarios:

  1. if you are not using a physics engine for ball movement, or you don't mind setting ball position, you should just use a temporary variable theta and increase it based on the time passed, here is the exact formula:

    theta += delta_time * (Ball_speed / Circle_radius)
    position = circle_center + circle_radius * vec2(sin(theta), cos(theta))

    in which circle_radius is equal to half of your grid width, and circle_center in your example is the right bottom corner of tile

  2. if you are using a physics engine and you don't want to mess with it, you should apply force to keep the ball on the track. in this case you should compute acceleration in every update which is also simple, based on this formula:

    acceleration = (Circle_center - Ball_position) * (Ball_speed ^ 2) / (circle_radius ^ 2)

    this time circle_radius is the distance between ball position and circle center. I know it should be equal to half block size, but due to all kinds of computation errors the ball might move out of it's path a little bit, and using dynamic distance helps just a little. still I recommend setting ball position forcefully when it's going to go out of that tile.

In case the ball enters from bottom edge, in the first method you should decrease theta instead of increasing it every frame. but you don't need to change anything in the second method.

  • \$\begingroup\$ I do use a physics engine and hence went for method 2. There are a few mistakes in your equation, but it pointed me in the right direction (Uniform Circular Motion). The correct equation would be: acceleration = (circle_center - ball_position).Normalize() * (ball_velocity.Length() ^ 2) / circle_radius. This code is derived from the equation for centripetal acceleration whose magnitude is given by: a = v^2 / r, and direction is from the object to the center of circular motion. \$\endgroup\$
    – ApoorvaJ
    Commented Dec 9, 2012 at 14:15
  • \$\begingroup\$ @ApoorvaJ so it means I should only change Ball_Speed in my equation to Ball_Speed ^ 2 right? \$\endgroup\$
    – Ali1S232
    Commented Dec 9, 2012 at 17:37
  • \$\begingroup\$ And also change the (ball_position - circle_center) to its reverse. That way the acceleration vector points to the turn corner and not away from it. \$\endgroup\$
    – ApoorvaJ
    Commented Dec 9, 2012 at 17:51
  • 1
    \$\begingroup\$ A little clarification since the expression seems to be subject to a lot of edits: the formula is a = v²/r or in vector form: a = -r v²/r², hence the radius squared in the denominator. (The bold-face 'a' doesn't agree with me.) \$\endgroup\$ Commented Dec 9, 2012 at 21:27

You must log in to answer this question.

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