public override void Update_Active(object sender, FrameUpdateEventArgs e) { //sinex += WobbleSpeed * e.ElapsedMilliseconds; // frame rate independend sinex += WobbleSpeed * 25; // used for nonuniformly continuous behavior IElasticBody ESprite = Sprite as IElasticBody; if (ESprite != null) { Vector dpos = new Vector(Math.Sin(sinex) * 2, Math.Sin(sinex) * 5); dpos *= WobbleAmplitude; Vector dsize = new Vector(dpos.X / 2.0, -dpos.Y); ESprite.Deformation = new Rect(ESprite.Deformation.Location + dpos, (Vector)ESprite.Deformation.Size + dsize); } }
public override void Update_Active(object sender, FrameUpdateEventArgs e) { if (Sprite.IsMovable) { Vector nSpeed = new Vector(); IElasticBody ESprite = Sprite as IElasticBody; if (ESprite != null) { ESprite.Deformation = new Rect(0, 0, 1, 1); } // check collisions first if (Sprite.IsObstacle) { (Sprite as IGFXObject).ParentContainer.Collider.Check(Sprite as IGameObject, e); } // speed threshold in order to avoid oscillations nSpeed.X = (Math.Abs(Sprite.NormSpeed.X) < 0.1) ? 0 : Sprite.NormSpeed.X; nSpeed.Y = (Math.Abs(Sprite.NormSpeed.Y) < 0.1) ? 0 : Sprite.NormSpeed.Y; Vector dpos = GFXAnimation.NormToPixelSpeed(nSpeed) * (e.ElapsedMilliseconds / 1000); Sprite.Position += dpos; // Reset deformation } }
public void ProcessCollision(IGameObject me, IGameObject other, Rect overlap, Rect rme, Rect rother, double dt) { double eps = 1; Vector voverlap = new Vector(overlap.Width, overlap.Height); Vector dx = new Vector(0, 0); if ((int)overlap.Width == (int)rme.Width) { dx = voverlap; if (rme.Top < rother.Top) { dx *= -1; } dx.X = 0; } else if ((int)overlap.Height == (int)rme.Height) { dx = voverlap; if (rme.Left < rother.Left) { dx *= -1; } dx.Y = 0; } else { Vector v1 = rme.TopLeft - rother.TopLeft; Vector v2 = rme.TopRight - rother.BottomLeft; Vector v3 = rme.BottomRight - rother.TopLeft; Vector v4 = rme.BottomLeft - rother.TopRight; if (Math.Abs(voverlap.Length - v3.Length) < eps) { dx = -v3; } else if (Math.Abs(voverlap.Length - v4.Length) < eps) { dx = -v4; } else if (Math.Abs(voverlap.Length - v2.Length) < eps) { dx = -v2; } else if (Math.Abs(voverlap.Length - v1.Length) < eps) { dx = -v1; } // avoid insane jumping off cliffs dx = new Vector(Math.Sign(dx.X) * Math.Min(Math.Abs(dx.X), Math.Abs(dx.Y)), Math.Sign(dx.Y) * Math.Min(Math.Abs(dx.X), Math.Abs(dx.Y))); } #region Animation // animation if (other.IsMovable) { if (me is IElasticBody) { IElasticBody mel = (me as IElasticBody); //if mel.IsMovable double SpringC = mel.SpringC; double Damping = mel.DampingC; bool liquid = false; // me - other; Position is COG; Vector dCOG = me.Position - other.Position; if (dCOG.Length > 0) { dCOG.Normalize(); } if (other is IElasticBody) { IElasticBody otherel = (other as IElasticBody); SpringC = 1 / ((1 / SpringC) + (1 / otherel.SpringC)); Damping = (Damping + otherel.DampingC) / 2; liquid = otherel.IsLiquid; if (otherel.isPointMass) { dx = dCOG * dx.Length; // force Vector df = dx * SpringC; mel.NormSpeed += df * dt / me.Weight; // damping double fdamp = Vector.Multiply(other.NormSpeed - me.NormSpeed, dCOG) * Damping; // force against me Vector vdamp = dCOG * fdamp * dt / me.Weight; mel.NormSpeed += vdamp; } else { dCOG = dx; if (dx.Length > 0) { double fme = (other.Weight / (me.Weight + other.Weight)); double fother = (me.Weight / (me.Weight + other.Weight)); me.Position += dx * fme; dx.Normalize(); me.NormSpeed -= -Math.Abs(Vector.Multiply(me.NormSpeed, dx)) * dx * fme; other.NormSpeed += -Math.Abs(Vector.Multiply(other.NormSpeed, dx)) * dx * fother; } } } else { dCOG = dx; } // deformation: double bend = dx.Length / ((Vector)me.Shape.Size).Length; if (bend > 0.2) { bend = 0.2; // maximales eindellen } // choose one axis to avoid shrinking if (Math.Abs(dCOG.X) > Math.Abs(dCOG.Y)) { dCOG = new Vector(dCOG.X, 0); } else { dCOG = new Vector(0, dCOG.X); } if (mel.IsDeformable) { mel.Deformation = new Rect(mel.Deformation.X + Math.Min(0, dCOG.X * bend), mel.Deformation.Y + Math.Min(0, dCOG.Y * bend), // change position is force from top/left (dCOG*bend >0) mel.Deformation.Width - Math.Abs(dCOG.X * bend), mel.Deformation.Height - Math.Abs(dCOG.Y * bend)); // size shrinks always } } } else // not Movable: { if (me is IElasticBody) { IElasticBody mel = (me as IElasticBody); //if mel.IsMovable double SpringC = mel.SpringC; double Damping = mel.DampingC; bool liquid = false; if (other is IElasticBody) { IElasticBody otherel = (other as IElasticBody); SpringC = 1 / ((1 / SpringC) + (1 / otherel.SpringC)); Damping = (Damping + otherel.DampingC) / 2; liquid = otherel.IsLiquid; if (dx.Length > 0) { //Vector deform = new Vector(dx.X, dx.Y); mel.NormSpeed += dx * dt * SpringC; // masse ignorieren double bend = dx.Length / ((Vector)me.Shape.Size).Length; if (bend > 0.5) { bend = 0.5; // maximales eindellen } dx.Normalize(); if (liquid) { // Water animator Vector vdamp = -Math.Abs(Vector.Multiply(mel.NormSpeed, dx)) * Damping * dt * mel.NormSpeed / mel.NormSpeed.Length; // masse ignoriert mel.NormSpeed += vdamp; } else { // Ground animator Vector vdamp = -(Vector.Multiply(mel.NormSpeed, dx)) * Damping * dt * (dx / dx.Length); // masse ignoriert mel.NormSpeed += vdamp; if (mel.IsDeformable) { mel.Deformation = new Rect(mel.Deformation.X, mel.Deformation.Y, mel.Deformation.Width + (dx.X * bend), mel.Deformation.Height + (dx.Y * bend)); } } } } else // RigidBody: { if (dx.Length > 0) { me.Position += dx; dx.Normalize(); me.NormSpeed -= -Math.Abs(Vector.Multiply(me.NormSpeed, dx)) * dx; } } } } #endregion }