0

I've looked around here for some answers on this, I've found a few good ones, but when I implement them in my code, I get some unexpected results.

Here's my problem:

I'm creating a top down geometry shooter, and when an enemy is hit by a bullet, the enemy should explode into smaller clones, shooting out from the center of the enemy in a circular fashion, in even intervals around the enemy. I assumed I could accomplish this by getting an initial vector, coming straight out of the side of the enemy shape, then rotate that vector the appropriate amount of times. Here's my code:

void Game::spawnSmallEnemies(s_ptr<Entity> e)
{
    int vertices = e->cShape->shape.getPointCount();
    float angle = 360.f / vertices;

    double conv = M_PI / 180.f;

    double cs = cos(angle * (M_PI / 180));
    double sn = sin(angle * (M_PI / 180));

                                        // Radius of enemy shape
    Vec2 velocity { e->cTransform->m_pos.m_x + m_enemyCfg.SR , e->cTransform->m_pos.m_y} ;
    velocity = velocity.get_normal();
    Vec2 origin {e->cTransform->m_pos};

    for (int i = 0; i < vertices; i++) 
    {
        auto small = m_entityMgr.addEntity("small");

        small->cTransform = std::make_shared<CTransform>(origin, velocity * 3, 0);

        small->cShape = std::make_shared<CShape>(m_enemyCfg.SR / 4, vertices, 
            e->cShape->shape.getFillColor(), e->cShape->shape.getOutlineColor(), 
            e->cShape->shape.getOutlineThickness(), small->cTransform->m_pos);

        small->cCircleCollider = std::make_shared<CCircleCollider>(m_enemyCfg.SR / 4);

        small->cLife = std::make_shared<CLifespan>(m_enemyCfg.L);

        velocity.m_x = ((velocity.m_x - origin.m_x) * cs) - ((origin.m_y - velocity.m_y) * sn) + origin.m_x;
        velocity.m_y = origin.m_y - ((origin.m_y - velocity.m_y) * cs) + ((velocity.m_x - origin.m_x) * sn);
    }
}

I got the rotation code at the bottom from this post, however each of the smaller shapes only shoot toward the bottom right, all clumped together. I would assume my error is logic, however I have been unable to find a solution.

slinky55
  • 33
  • 6
  • The velocity being calculated based on the position looks wrong. Not sure if you compensate for this anywhere in your code though... – fabian Jul 31 '22 at 08:32
  • The position of the origin? And the only thing I do with velocity is add it to the entity position in my move system. – slinky55 Jul 31 '22 at 08:34
  • 1
    One issue is that the calculation of `velocity.m_y` uses the updated value of `velocity.m_x` but should use the original value. I would recommend writing a "rotate vector around point" function instead of messing around at this low abstraction level. – molbdnilo Jul 31 '22 at 08:36
  • Velocities should be completely independent of the position of the exploding enemy. The velocity is simply the difference in position that an object moves in a certain time interval. – fabian Jul 31 '22 at 08:39
  • 1
    On a side note, it's better to rotate the original vector through increasing angles than to rotate one vector repeatedly. The numerical inaccuracies of the latter method accumulate pretty quickly. – molbdnilo Jul 31 '22 at 08:39
  • I just printed out some debug statements, and plugged the coordinates into desmos and I see that as the issue now, completely slipped my mind. – slinky55 Jul 31 '22 at 08:39
  • Btw: not sure, if dynamically allocating transformations is necessarily a good idea. Copying them should be reasonably cheap, since there should only be 6 floating point values to copy making dynamic allocations+shared object management probably more expensive than copying... – fabian Jul 31 '22 at 08:46
  • Created a function to handle the rotations, and there are improvements, the distribution of the smalls are even, however now in an arc, still going towards the bottom left. My velocity vector to my understanding is not relying on the position, simply just starting out relative to it. – slinky55 Jul 31 '22 at 09:07
  • About the dynamic allocation, the entity component system I'm currently using stores all components as smart pointers, what would be an alternative? – slinky55 Jul 31 '22 at 09:08
  • 1
    You can just start with radians (`rad = 0.;`) and increment your angle `double inc = 2. * M_PI / nclones` for each new clone. That allows you to loop `nclones` times positioning your clones at `clonex = enemy.x + r * cos(rad);` and `cloney = enemy.y + r * sin(rad);` incrementing `rad += inc;` each time where `r` is the radius from the enemy you want your clone placed. – David C. Rankin Jul 31 '22 at 09:09
  • I want them to start at the origin of the enemy, so could I simply take the normal of that calculated position for velocity? – slinky55 Jul 31 '22 at 09:13
  • The start position for placing the clones is at the enemy's position (doesn't matter where the enemy is -- that's considered the origin for clone placement). That's why you have the final clone coordinates of `clonex = enemy.x + r * cos(rad);`. You just add the clone placement to the position of the enemy. Rather than dynamically allocating, set a max number of clones you can make (e.g. 36, one every 10 deg, etc..) Then just create an array of clones with automatic storage duration. If just just create 2, fine, you have a counter for the number you create. (just an idea) – David C. Rankin Jul 31 '22 at 09:18
  • Got it, this works great for simply placing them, however I'm running into the issue of actually moving them out in the respective directions – slinky55 Jul 31 '22 at 09:21
  • That's up to you and your game physics engine. Likely registering them as new object to propagate with each frame. Can't help you there, I don't do game programming -- just an old engineer. I presume each new clone will have the same initial velocity and direction as the enemy before whatever forces act on the clones -- start acting on them to change their velocity and direction. Or you can make their initial direction outward along their radial from the enemy at some initial velocity -- up to you. – David C. Rankin Jul 31 '22 at 09:23
  • If you haven't found [Gaffer On Games](https://gafferongames.com/) yet, worth a visit and bookmark -- you will use it over and over. – David C. Rankin Jul 31 '22 at 09:29
  • I'll definitely check it out, I used your method and was able to solve my problem, many thanks to you – slinky55 Jul 31 '22 at 09:31

0 Answers0