0
\$\begingroup\$

I am trying to implement basic Snake game with movement based on timestep. For now I've got something along those lines:

Update function:

glm::vec2 headPosition = glm::vec2(m_segments.begin()->m_sprite.get_position());
float angle = m_segments.begin()->m_sprite.get_angle();

m_segments.begin()->move();
    
for (auto it = m_segments.begin() + 1; it != m_segments.end(); it++)
{
    glm::vec2 oldPosition = it->m_sprite.get_position();
    float oldAngle = it->m_sprite.get_angle();

    it->m_sprite.set_position(headPosition);
    it->m_sprite.set_angle(angle);

    headPosition = oldPosition;
    angle = oldAngle;
}

Move function:

glm::vec2 position(m_sprite.get_position());
position.x +=  cosf(glm::radians(90.0f - m_sprite.get_angle())) * VELOCITY_SCALAR;
position.y += -sinf(glm::radians(90.0f - m_sprite.get_angle())) * VELOCITY_SCALAR;

m_sprite.set_position(position);

Basically I set next segment position to the old position of previous segment. As expected spacing between those segments is equal to timestep value. How can I calculate position so I can manipulate spacing between those segments?

EDIT

I've found following implementation of snake segments following each other:

float distance = sqrt( pow( ( snakeParts[i-1].x - snakeParts[i].x ), 2) + pow( ( snakeParts[i-1].y - snakeParts[i].y ), 2 ) );

        // Rotate to look at previous part
        snakeParts[i].r = atan2( snakeParts[i-1].y - snakeParts[i].y, snakeParts[i-1].x - snakeParts[i].x ) + ( M_PI / 2 );
        

        // If the distance is too far, move to the correct distance
        if( distance > FOLLOW_DISTANCE )
        {
            snakeParts[i].x += sin( snakeParts[i].r ) * ( distance - FOLLOW_DISTANCE );
            snakeParts[i].y -= cos( snakeParts[i].r ) * ( distance - FOLLOW_DISTANCE );
        }

Source (follow function): https://github.com/Grzybojad/vitaSnake/blob/master/src/player.cpp

Could somebody help me to understand what's happening here so I can apply it to my implementation?

\$\endgroup\$
1

1 Answer 1

0
\$\begingroup\$

The answer to my question is as follows:

auto currentPosition = it->m_sprite.get_position();
auto previousPosition = (it - 1)->m_sprite.get_position();

float distance = 
sqrtf
(
    powf(abs(currentPosition.x - previousPosition.x), 2.0f) +
    powf(abs(currentPosition.y - previousPosition.y), 2.0f)
);

float a = currentPosition.x - previousPosition.x;
float b = currentPosition.y - previousPosition.y;
float angle = glm::degrees(atan2(b, a)) - 90.0f;
it->m_sprite.set_angle(angle);

if (distance > SPACING)
    it->move({ sinf(glm::radians(angle)) * (distance - SPACING), -cosf(glm::radians(angle)) * (distance - SPACING) });

Basic idea is that segments excluding snake's head are following each other with spacing between them applied.

\$\endgroup\$
1
  • \$\begingroup\$ Hey! You might want to tell the system that this is the answer to this question, this could help other users see that this is a working solution if they ever get a similar issue. \$\endgroup\$
    – Vaillancourt
    May 5, 2021 at 15:38

You must log in to answer this question.

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