001         package com.croftsoft.apps.chat.model.seri;
002    
003         import java.awt.Shape;
004    
005         import com.croftsoft.core.animation.model.ModelId;
006         import com.croftsoft.core.animation.model.seri.SeriModel;
007         import com.croftsoft.core.math.geom.Circle;
008         import com.croftsoft.core.math.geom.Point2DD;
009         import com.croftsoft.core.math.geom.PointXY;
010         import com.croftsoft.core.lang.NullArgumentException;
011    import com.croftsoft.core.util.consumer.Consumer;
012    
013         import com.croftsoft.apps.chat.ChatConstants;
014         import com.croftsoft.apps.chat.event.MoveEvent;
015         import com.croftsoft.apps.chat.model.ChatModel;
016    import com.croftsoft.apps.chat.model.ChatWorld;
017    
018         /*********************************************************************
019         * The base class for a game world object Model.
020         *
021         * @version
022         *   2003-06-17
023         * @since
024         *   2003-06-05
025         * @author
026         *   <a href="https://www.croftsoft.com/">David Wallace Croft</a>
027         *********************************************************************/
028    
029         public class  SeriChatModel
030           extends SeriModel
031           implements ChatModel
032         //////////////////////////////////////////////////////////////////////
033         //////////////////////////////////////////////////////////////////////
034         {
035    
036         private static final long  serialVersionUID = 0L;
037    
038         //
039    
040         private final String  avatarType;
041    
042         private final Circle  circle;
043    
044         //
045    
046         private transient ChatWorld  chatWorld;
047    
048         private transient Consumer   eventConsumer;
049    
050         //
051    
052         private PointXY  destination;
053    
054         private boolean  updated;
055    
056         private boolean  active;
057    
058         //////////////////////////////////////////////////////////////////////
059         //////////////////////////////////////////////////////////////////////
060    
061         public  SeriChatModel (
062           ModelId    modelId,
063           Consumer   eventConsumer,
064           ChatWorld  chatWorld,
065           String     avatarType,
066           double     x,
067           double     y )
068         //////////////////////////////////////////////////////////////////////
069         {
070           super ( modelId );
071    
072           setEventConsumer ( eventConsumer );
073    
074           NullArgumentException.check ( this.chatWorld = chatWorld );
075    
076           NullArgumentException.check ( this.avatarType = avatarType );
077    
078           circle = new Circle ( x, y, ChatConstants.RADIUS );
079    
080           active = true;
081         }
082    
083         //////////////////////////////////////////////////////////////////////
084         //////////////////////////////////////////////////////////////////////
085    
086         public String   getAvatarType ( ) { return avatarType; }
087    
088         //////////////////////////////////////////////////////////////////////
089         //////////////////////////////////////////////////////////////////////
090    
091         public boolean  isActive   ( ) { return active;  }
092    
093         public double   getCenterX ( ) { return circle.getCenterX ( ); }
094    
095         public double   getCenterY ( ) { return circle.getCenterY ( ); }
096    
097         public Shape    getShape   ( ) { return circle;  }
098    
099         public boolean  isUpdated  ( ) { return updated; }
100    
101         public double   getZ       ( ) { return 0.0;     }
102    
103         //////////////////////////////////////////////////////////////////////
104         //////////////////////////////////////////////////////////////////////
105    
106         public void  setActive ( boolean  active )
107         //////////////////////////////////////////////////////////////////////
108         {
109           this.active = active;
110         }
111    
112         public void  setDestination ( PointXY  destination )
113         //////////////////////////////////////////////////////////////////////
114         {
115           if ( destination != null )
116           {
117             destination = new Point2DD ( destination );
118           }
119    
120           this.destination = destination;
121    
122           eventConsumer.consume (
123             new MoveEvent ( modelId, circle.getCenter ( ), destination ) );
124         }
125    
126         public void  setEventConsumer ( Consumer  eventConsumer )
127         //////////////////////////////////////////////////////////////////////
128         {
129           NullArgumentException.check ( this.eventConsumer = eventConsumer );
130         }
131    
132         //////////////////////////////////////////////////////////////////////
133         //////////////////////////////////////////////////////////////////////
134    
135         public void  setCenter (
136           double  x,
137           double  y )
138         //////////////////////////////////////////////////////////////////////
139         {
140           circle.setCenter ( x, y );
141    
142           updated = true;
143         }
144    
145         public void  prepare ( )
146         //////////////////////////////////////////////////////////////////////
147         {
148           updated = false;
149         }
150    
151         public void  update ( double  timeDelta )
152         //////////////////////////////////////////////////////////////////////
153         {
154           updatePosition ( timeDelta );
155         }
156    
157         //////////////////////////////////////////////////////////////////////
158         //////////////////////////////////////////////////////////////////////
159    
160         private void  updatePosition ( double  timeDelta )
161         //////////////////////////////////////////////////////////////////////
162         {
163           if ( destination == null )
164           {
165             return;
166           }
167    
168           PointXY  center = circle.getCenter ( );
169    
170           double  centerX = center.getX ( );
171    
172           double  centerY = center.getY ( );
173    
174           double  deltaX = destination.getX ( ) - centerX;
175    
176           double  deltaY = destination.getY ( ) - centerY;
177    
178           if ( ( deltaX == 0.0 )
179             && ( deltaY == 0.0 ) )
180           {
181             destination = null;
182    
183             return;
184           }
185    
186           double  aimHeading = Math.atan2 ( deltaY, deltaX );
187    
188           if ( aimHeading < 0.0 )
189           {
190             aimHeading += 2.0 * Math.PI;
191           }
192    
193           double  moveX
194             = timeDelta * ChatConstants.SPEED * Math.cos ( aimHeading );
195    
196           double  moveY
197             = timeDelta * ChatConstants.SPEED * Math.sin ( aimHeading );
198    
199           if ( Math.abs ( moveX ) > Math.abs ( deltaX ) )
200           {
201             moveX = deltaX;
202           }
203                 
204           if ( Math.abs ( moveY ) > Math.abs ( deltaY ) )
205           {
206             moveY = deltaY;
207           }
208    
209           double  newX = centerX + moveX;
210    
211           double  newY = centerY + moveY;
212    
213           circle.setCenter ( newX, newY );
214    
215           if ( ( chatWorld == null )
216             || !chatWorld.isBlocked ( circle, this ) )
217           {
218             updated = true;
219           }
220           else
221           {
222             circle.setCenter ( centerX, centerY );
223    
224             if ( chatWorld.isBlocked ( circle, this ) )
225             {
226               circle.setCenter ( newX, newY );
227    
228               updated = true;
229             }
230             else
231             {
232               setDestination ( null );
233             }
234           }
235         }
236    
237         //////////////////////////////////////////////////////////////////////
238         //////////////////////////////////////////////////////////////////////
239         }