Ejemplo n.º 1
0
        // handleParticleInfluence -- Handles interaction between entities and particles
        public void handleParticleInfluence(string levelUid, Particle particle)
        {
            for (int i = 0; i < particle.entityInfluenceCount; i++)
            {
                int entityId = particle.entitiesToInfluence[i];
                ParticleInfluenceComponent particleInfluenceComponent = _entityManager.getComponent(levelUid, entityId, ComponentType.ParticleInfluence) as ParticleInfluenceComponent;

                particleInfluenceComponent.particleCount++;
                if (particleInfluenceComponent.type == ParticleInfluenceType.Physical)
                {
                    // Physical body influences -- body-to-particle influences are usually already handled by resolveCollisions()
                    PhysicsComponent physicsComponent = _entityManager.getComponent(levelUid, entityId, ComponentType.Physics) as PhysicsComponent;

                    physicsComponent.body.ApplyLinearImpulse(particle.oldPosition - particle.position, particle.oldPosition);
                }
                else if (particleInfluenceComponent.type == ParticleInfluenceType.Dynamite)
                {
                    // Dynamite influence
                    PhysicsComponent physicsComponent = _entityManager.getComponent(levelUid, entityId, ComponentType.Physics) as PhysicsComponent;
                    Vector2          bodyVelocity     = physicsComponent.body.LinearVelocity;

                    physicsComponent.body.LinearVelocity  = bodyVelocity * 0.98f + particle.velocity;
                    physicsComponent.body.AngularVelocity = physicsComponent.body.AngularVelocity * 0.98f;
                    particle.velocity += bodyVelocity * 0.003f;
                }
                else if (particleInfluenceComponent.type == ParticleInfluenceType.Character)
                {
                    // Character influence
                    PhysicsComponent physicsComponent = _entityManager.getComponent(levelUid, entityId, ComponentType.Physics) as PhysicsComponent;
                    Vector2          bodyVelocity     = physicsComponent.body.LinearVelocity;

                    physicsComponent.body.LinearVelocity = bodyVelocity * 0.95f + particle.velocity;
                    particle.velocity += bodyVelocity * 0.003f;
                }
                else if (particleInfluenceComponent.type == ParticleInfluenceType.Explosion)
                {
                    ExplosionComponent explosionComponent = _entityManager.getComponent(levelUid, entityId, ComponentType.Explosion) as ExplosionComponent;
                    Vector2            relative;
                    float   distanceSq;
                    Vector2 force;

                    relative   = particle.position - explosionComponent.position;
                    distanceSq = relative.LengthSquared();
                    relative.Normalize();
                    force              = relative * (explosionComponent.strength / Math.Max(distanceSq, 1f));
                    particle.velocity += force * 0.0055f;
                }
            }
        }
Ejemplo n.º 2
0
        public void update(GameTime gameTime)
        {
            if (!_paused || _singleStep)
            {
                LevelSystem levelSystem = _systemManager.getSystem(SystemType.Level) as LevelSystem;

                if (levelSystem.finalized)
                {
                    string     levelUid          = LevelSystem.currentLevelUid;
                    List <int> characterEntities = _entityManager.getEntitiesPosessing(levelUid, ComponentType.CharacterMovement);

                    for (int i = 0; i < characterEntities.Count; i++)
                    {
                        PhysicsComponent           physicsComponent           = _entityManager.getComponent(levelUid, characterEntities[i], ComponentType.Physics) as PhysicsComponent;
                        ParticleInfluenceComponent particleInfluenceComponent = _entityManager.getComponent(levelUid, characterEntities[i], ComponentType.ParticleInfluence) as ParticleInfluenceComponent;
                        CharacterMovementComponent characterMovementComponent = _entityManager.getComponent(levelUid, characterEntities[i], ComponentType.CharacterMovement) as CharacterMovementComponent;
                        RopeGrabComponent          ropeGrabComponent          = _entityManager.getComponent(levelUid, characterEntities[i], ComponentType.RopeGrab) as RopeGrabComponent;
                        Body  body         = physicsComponent.body;
                        float currentSpeed = body.LinearVelocity.Length();

                        // Handle fluid properties
                        characterMovementComponent.inFluid = particleInfluenceComponent.particleCount > 2;

                        // Handle rope grabs
                        if (characterMovementComponent.allowRopeGrab && characterMovementComponent.doRopeGrab)
                        {
                            attemptRopeGrab(levelUid, characterEntities[i], characterMovementComponent, physicsComponent, ropeGrabComponent);
                        }

                        // Calculate movement vector
                        if (characterMovementComponent.collisionNormals.Count > 0)
                        {
                            characterMovementComponent.movementUnitVector = Vector2.Zero;
                            for (int j = 0; j < characterMovementComponent.collisionNormals.Count; j++)
                            {
                                characterMovementComponent.movementUnitVector += characterMovementComponent.collisionNormals[j] / characterMovementComponent.collisionNormals.Count;
                            }
                            characterMovementComponent.movementUnitVector = new Vector2(characterMovementComponent.movementUnitVector.Y, -characterMovementComponent.movementUnitVector.X);
                            characterMovementComponent.movementUnitVector.Normalize();
                        }
                        else
                        {
                            characterMovementComponent.movementUnitVector = new Vector2(-1, 0);
                        }

                        // On surface movement
                        if (characterMovementComponent.onSurface)
                        {
                            if (characterMovementComponent.walkLeft || characterMovementComponent.walkRight)
                            {
                                // Adjust friction
                                if (body.LinearVelocity.X < -0.1f && characterMovementComponent.walkRight)
                                {
                                    body.Friction = 10f;
                                }
                                else if (body.LinearVelocity.X > 0.1f && characterMovementComponent.walkLeft)
                                {
                                    body.Friction = 10f;
                                }
                                else
                                {
                                    body.Friction = 0.1f;
                                }

                                // Walk
                                if (currentSpeed <= characterMovementComponent.speedLimit)
                                {
                                    Vector2 impulse = characterMovementComponent.movementUnitVector * _baseWalkMultiplier;

                                    if (characterMovementComponent.walkRight)
                                    {
                                        impulse *= -1;
                                    }
                                    if (characterMovementComponent.inFluid)
                                    {
                                        impulse *= 0.5f;
                                    }
                                    body.ApplyLinearImpulse(ref impulse);
                                }
                            }
                            else
                            {
                                body.Friction = 10f;
                            }
                        }
                        else  // In-air movement
                        {
                            if (characterMovementComponent.walkLeft || characterMovementComponent.walkRight)
                            {
                                if (ropeGrabComponent != null)
                                {
                                    // Swing
                                    Vector2 impulse = characterMovementComponent.movementUnitVector * _baseSwingMultiplier;

                                    if (characterMovementComponent.walkRight)
                                    {
                                        impulse *= -1;
                                    }

                                    body.ApplyLinearImpulse(ref impulse);
                                }
                                else
                                {
                                    // Air walk
                                    if ((body.LinearVelocity.X < 0 && characterMovementComponent.walkRight) ||
                                        (body.LinearVelocity.X > 0 && characterMovementComponent.walkLeft) ||
                                        (body.LinearVelocity.X > -characterMovementComponent.speedLimit && characterMovementComponent.walkLeft) ||
                                        (body.LinearVelocity.X < characterMovementComponent.speedLimit && characterMovementComponent.walkRight))
                                    {
                                        Vector2 impulse = characterMovementComponent.movementUnitVector * _baseAirWalkMultiplier;

                                        if (characterMovementComponent.walkRight)
                                        {
                                            impulse *= -1;
                                        }

                                        body.ApplyLinearImpulse(ref impulse);
                                    }
                                }
                            }
                        }

                        // Jump
                        if (characterMovementComponent.attemptJump)
                        {
                            // While holding rope
                            if (ropeGrabComponent != null)
                            {
                                RopeComponent ropeComponent = _entityManager.getComponent(levelUid, ropeGrabComponent.ropeEntityId, ComponentType.Rope) as RopeComponent;
                                Vector2       impulse       = new Vector2(0, -1.2f);

                                if (ropeComponent != null && ropeComponent.destroyAfterRelease)
                                {
                                    ropeComponent.timeToLive = 100;
                                }

                                _ropeSystem.releaseRope(ropeGrabComponent, physicsComponent.body);
                                _entityManager.removeComponent(levelUid, characterEntities[i], ropeGrabComponent);
                                ropeGrabComponent = null;

                                body.ApplyLinearImpulse(ref impulse);
                            }

                            if (characterMovementComponent.onSurface)
                            {
                                Vector2 impulse    = new Vector2(0, -2f);
                                float   adjustment = 0f;

                                // Try to limit the impulse based on the current y velocity.
                                // This is done to prevent jumps from contributing too much to the y velocity when
                                // the player is already moving upwards too fast (which results in a super-jump).
                                adjustment = (body.LinearVelocity.Y / 6f);
                                impulse.Y -= adjustment;

                                body.ApplyLinearImpulse(ref impulse);
                                characterMovementComponent.attemptJump = false;
                            }
                        }

                        // Swim
                        if (characterMovementComponent.inFluid && characterMovementComponent.swimUp)
                        {
                            Vector2 impulse = new Vector2(0, -0.25f);

                            body.ApplyLinearImpulse(ref impulse);
                        }

                        // Climbing
                        if (ropeGrabComponent != null)
                        {
                            float climbSpeed = characterMovementComponent.climbAmount * CLIMB_SPEED;
                            if (characterMovementComponent.climbUp)
                            {
                                _ropeSystem.moveAttachedBody(ropeGrabComponent, physicsComponent.body, climbSpeed);
                            }
                            else if (characterMovementComponent.climbDown)
                            {
                                _ropeSystem.moveAttachedBody(ropeGrabComponent, physicsComponent.body, -climbSpeed);
                            }
                        }
                    }
                }
            }
            _singleStep = false;
        }
Ejemplo n.º 3
0
        // resolveCollisions
        private void resolveCollision(string levelUid, int index)
        {
            Particle particle = liquid[index];

            // Resolve collisions between particles and fixtures
            for (int i = 0; i < particle.numFixturesToTest; i++)
            {
                Fixture fixture = particle.fixturesToTest[i];
                if (fixture.Shape == null)     // fixtures can be destroyed before they're tested
                {
                    continue;
                }

                Vector2 newPosition = particle.position + particle.velocity + _delta[index];
                if (fixture.TestPoint(ref newPosition, 0.01f))
                {
                    Body body     = fixture.Body;
                    int  entityId = (int)body.UserData;
                    SkipFluidResolutionComponent skipFluidResolutionComponent = _entityManager.getComponent(levelUid, entityId, ComponentType.SkipFluidResolution) as SkipFluidResolutionComponent;
                    ParticleInfluenceComponent   particleInfluenceComponent   = _entityManager.getComponent(levelUid, entityId, ComponentType.ParticleInfluence) as ParticleInfluenceComponent;
                    bool influenceEntity = particleInfluenceComponent != null;

                    if (skipFluidResolutionComponent == null)
                    {
                        Vector2 closestPoint     = Vector2.Zero;
                        Vector2 normal           = Vector2.Zero;
                        Vector2 resolvedPosition = Vector2.Zero;

                        if (fixture.ShapeType == ShapeType.Polygon)
                        {
                            // Polygons
                            PolygonShape shape = fixture.Shape as PolygonShape;
                            Transform    collisionXF;
                            body.GetTransform(out collisionXF);

                            for (int v = 0; v < shape.Vertices.Count; v++)
                            {
                                particle.collisionVertices[v] = MathUtils.Multiply(ref collisionXF, shape.Vertices[v]);
                                particle.collisionNormals[v]  = MathUtils.Multiply(ref collisionXF.R, shape.Normals[v]);
                            }

                            // Find closest edge
                            float shortestDistance = 9999999f;
                            for (int v = 0; v < shape.Vertices.Count; v++)
                            {
                                float distance = Vector2.Dot(particle.collisionNormals[v], particle.collisionVertices[v] - particle.position);
                                if (distance < shortestDistance)
                                {
                                    shortestDistance = distance;
                                    closestPoint     = particle.collisionNormals[v] * (distance) + particle.position;
                                    normal           = particle.collisionNormals[v];
                                }
                            }
                            resolvedPosition            = closestPoint + 0.025f * normal;
                            particle.skipMovementUpdate = true;
                            particle.pressure           = MAX_PRESSURE;
                        }
                        else if (fixture.ShapeType == ShapeType.Circle)
                        {
                            // Circles
                            CircleShape shape      = fixture.Shape as CircleShape;
                            Vector2     center     = shape.Position + body.Position;
                            Vector2     difference = particle.position - center;

                            normal = difference;
                            normal.Normalize();
                            closestPoint                = center + difference * (shape.Radius / difference.Length());
                            resolvedPosition            = closestPoint + 0.025f * normal;
                            particle.skipMovementUpdate = true;
                            particle.pressure           = MAX_PRESSURE;
                        }

                        // Update particle position and velocity
                        particle.position = resolvedPosition;
                        particle.velocity = (particle.velocity - 1.2f * Vector2.Dot(particle.velocity, normal) * normal) * 0.85f;

                        // Handle fast moving bodies
                        if (body.LinearVelocity.LengthSquared() > 50f)
                        {
                            Vector2 bodyVelocity = body.GetLinearVelocityFromWorldPoint(particle.oldPosition);
                            body.LinearVelocity  = body.LinearVelocity * 0.995f;
                            body.AngularVelocity = body.AngularVelocity * 0.95f;
                            particle.velocity   += bodyVelocity * 0.005f;
                        }
                    }

                    // Particle influences
                    if (influenceEntity)
                    {
                        if (particleInfluenceComponent.type == ParticleInfluenceType.Rope)
                        {
                            // Handle rope particle-to-body influences here, since trying to find the correct body through the list of rope nodes would be a pain
                            Vector2 bodyVelocity = body.LinearVelocity;

                            body.LinearVelocity = bodyVelocity * 0.98f + particle.velocity * 1.5f;
                            particle.velocity  += bodyVelocity * 0.003f;
                        }
                        else
                        {
                            // Add entityId to list of entities being influenced by this particle
                            particle.entitiesToInfluence[particle.entityInfluenceCount] = (int)body.UserData;
                            particle.entityInfluenceCount++;
                        }
                    }
                }
            }
        }