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
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 at 15:38

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.