00001
00002
00003
00004
00005
00006
00007 namespace Grendel.Base {
00008 using System;
00009 using System.Collections.Generic;
00010 using System.Diagnostics;
00011 using Grendel.Extra;
00012
00019 public interface IDynamicObject : ICanvasObject {
00027 bool AnimationStep(int frame);
00028 }
00029
00034 public abstract class BaseDynamicObject : BaseCanvasObject, IDynamicObject {
00035
00036 public BaseDynamicObject(Canvas canvas) : base(canvas) {}
00037
00038 public abstract bool AnimationStep(int frame);
00039 }
00040
00045 public abstract class Animator : BaseDynamicObject {
00046 IShape animatedObject;
00047
00048 public Animator(Canvas canvas, IShape animatedObject)
00049 : base(canvas) {
00050 this.animatedObject = animatedObject;
00051 }
00052
00053 public IShape AnimatedObject {
00054 get {
00055 return animatedObject;
00056 }
00057 }
00058
00059 }
00060
00066 public class Shifter : Animator {
00067 private IShape shiftedObject;
00068 private Queue<Position> targets;
00069 private double velocity;
00070
00071 public double Velocity {
00072 get {
00073 return velocity;
00074 }
00075 }
00076
00077 public IShape ShiftedObject {
00078 get {
00079 return shiftedObject;
00080 }
00081 }
00082
00083 public Shifter(Canvas canvas, IShape shiftedObject, List<Position> LocationPath,
00084 double velocity)
00085 : base(canvas, shiftedObject){
00086 this.targets = new Queue<Position>(LocationPath);
00087 this.velocity = velocity;
00088 this.shiftedObject = shiftedObject;
00089 }
00090
00091 public Shifter(Canvas canvas, IShape shiftedObject, Position LocationTarget,
00092 double velocity)
00093 : base(canvas, shiftedObject){
00094 this.targets = new Queue<Position>();
00095 targets.Enqueue(LocationTarget);
00096 this.velocity = velocity;
00097 this.shiftedObject = shiftedObject;
00098 }
00099
00100 public override bool AnimationStep (int frame) {
00101 if(targets.Count == 0) {
00102 Canvas.Forget(this);
00103 return false;
00104 }
00105 double step = Canvas.AnimationInterval * Velocity;
00106 double distance = targets.Peek().Distance(shiftedObject.Location);
00107 if(distance < step * 1.5) {
00108 Position target = targets.Dequeue();
00109 ShiftedObject.Location = target;
00110 return true;
00111 }
00112 Vector targetshift = targets.Peek() - shiftedObject.Location;
00113 Vector stepshift = (step / targetshift.Length) * targetshift;
00114 ShiftedObject.Location += stepshift;
00115 return true;
00116 }
00117 }
00118
00123 abstract class TemporaryShape : BaseShape, IDynamicObject {
00124 private int startFrame;
00125 private double lifeTime;
00126
00127 public TemporaryShape(Canvas canvas, double lifeTime)
00128 : base(canvas) {
00129 this.lifeTime = lifeTime;
00130 this.startFrame = Canvas.Frame;
00131 }
00132
00133 public bool AnimationStep (int frame) {
00134 if((frame - startFrame)*Canvas.AnimationInterval > lifeTime) {
00135 Canvas.Forget(this);
00136 return true;
00137 }
00138 else
00139 return false;
00140 }
00141 }
00142
00147 class TemporaryMarker : TemporaryShape {
00148 IInteractiveShape shape;
00149
00150 public TemporaryMarker(Canvas canvas, IInteractiveShape shape, double lifeTime)
00151 : base(canvas, lifeTime) {
00152 this.shape = shape;
00153 Location = shape.AbsolutePosition;
00154 Layer = int.MaxValue;
00155 }
00156
00157 public override void Painting () {
00158 Location = shape.AbsolutePosition;
00159 Canvas.DrawRectangle(this, shape.LeftTopCorner, shape.RightBottomCorner, BaseColor);
00160 }
00161
00162 }
00163
00168 public class DeltaListNode {
00169 private int frame;
00170 private Action<int> action;
00171 private DeltaListNode next = null;
00172
00177 public DeltaListNode Next {
00178 get {
00179 return next;
00180 }
00181 }
00182
00187 public DeltaListNode(int startFrame, Action<int> action) {
00188 this.frame = startFrame;
00189 this.action = action;
00190 }
00191
00198 public static DeltaListNode Insert(DeltaListNode oldNode, DeltaListNode newNode) {
00199 if(oldNode == null)
00200 return newNode;
00201 if(oldNode.frame > newNode.frame) {
00202 oldNode.frame -= newNode.frame;
00203 newNode.next = oldNode;
00204 return newNode;
00205 }
00206 else {
00207 newNode.frame -= oldNode.frame;
00208 oldNode.next = Insert(oldNode.next, newNode);
00209 return oldNode;
00210 }
00211 }
00212
00225 public Action<int> FrameDecrement() {
00226 frame--;
00227 return frame == -1 ? action : null;
00228 }
00229 }
00236 public class ActionLauncher : BaseDynamicObject {
00237 private DeltaListNode deltaList = null;
00238
00244 public ActionLauncher(Canvas canvas)
00245 : base(canvas) {}
00246
00252 public ActionLauncher(Canvas canvas, IDictionary<int, Action<int>> actions)
00253 : base(canvas) {
00254 foreach(int frame in actions.Keys) {
00255 AddAction(frame, actions[frame]);
00256 }
00257 }
00258
00259
00265 public void AddAction(int framesAfter, Action<int> action) {
00266 deltaList = DeltaListNode.Insert(deltaList,
00267 new DeltaListNode(framesAfter, action));
00268 }
00269
00270 public override bool AnimationStep (int frame) {
00271 while(deltaList != null) {
00272 Action<int> action = deltaList.FrameDecrement();
00273 if (action == null)
00274 return false;
00275 action(frame);
00276 deltaList = deltaList.Next;
00277 }
00278 return true;
00279 }
00280 }
00281 }