Search code examples
optimizationphysicsgame-physicsphysics-enginecartesian-coordinates

'Grenade' projection based on angle + bounce


I'm having some trouble with synthesizing an advanced object projection formula. I have already figured out few basic physic simulation formulas such as:

  • Velocity of object: x += cos(angle); y += sin(angle); *where angle can be obtained by either mouse position or with tan(...target and intial values)

but that only travels straight based on the angle.

  • Gravity: Yvelocity = Yvelocity - gravity; if(!isHitPlatform) { Obj.y += YVelocity }

  • Bounce:// No point if we've not been sized... if (height > 0) { // Are we bouncing... if (bounce) { // Add the vDelta to the yPos // vDelta may be postive or negative, allowing // for both up and down movement... yPos += vDelta; // Add the gravity to the vDelta, this will slow down // the upward movement and speed up the downward movement... // You may wish to place a max speed to this vDelta += gDelta; // If the sprite is not on the ground... if (yPos + SPRITE_HEIGHT >= height) { // Seat the sprite on the ground yPos = height - SPRITE_HEIGHT; // If the re-bound delta is 0 or more then we've stopped // bouncing... if (rbDelta >= 0) { // Stop bouncing... bounce = false; } else { // Add the re-bound degregation delta to the re-bound delta rbDelta += rbDegDelta; // Set the vDelta... vDelta = rbDelta; } } } }

I need help way to combine these three formulas to create an efficient and lightweight algorithm that allows an object to be projected in an arch determined by the angle, yet continues to bounce a few times before coming to a stop, all with an acceptable amount of discontinuity between each point. *Note: Having the grenade be determined by a f(x) = -x^2 formula creates a larger jump discontinuity as the slope increases, forcing you to reverse the formula to find x = +-y value (to determine whether + or -, check the bounds).


Solution

  • something like:

    class granade
    {
        private static final double dt = 0.1; // or similar
    
        private double speedx;
        private double speedy;
        private double positionx;
        private double positiony;
    
        public granade(double v, double angle)
        {
            speedx = v * Math.cos(angle);
            speedy = v * Math.sin(angle);
    
            positionx = 0;
            positiony = 0;
        }
    
        public void nextframe()
        {
            // update speed: v += a*dt
            speedy -= gravity* dt;
    
            // update position: pos += v*dt
            positionx += speedx * dt;
            double newpositiony = positiony + speedy*dt;
    
            // bounce if hit ground
            if (newpositiony > 0)
                positiony = newpositiony;
            else {
                // bounce vertically
                speedy *= -1;
                positiony = -newpositiony;
            }
        }
    
        public void draw() { /* TODO */ }
    }
    

    OT: avoid Math.atan(y/x), use Math.atan2(y, x)