1 using System;
2 using System.Collections.Generic;
3 using Microsoft.Xna.Framework;
4 using Microsoft.Xna.Framework.Graphics;
5 using Microsoft.Xna.Framework.Input;
6
7 namespace DreamLibrary
8 {
9 public class Player : Sprite
10 {
11 #region Player Variables
12 protected Vector2 v2Dim; // dimension for the single frame of sprite
13 private Face playerFace; // face for the player
14 private Arm playerArm; // arm object for player
15 private int healthNodes;
16 public State prevState; // previous state of player
17 private float speedModifier;
18 private bool enemiesVis;
19 private bool reachPeak = false;
20 public bool hasLanded = false; // determine if player has landed from a jump
21 public bool isDying = false; // true if player is in death animation
22
23 double hurtTimer;
24 public bool hurt;
25 bool speedBoostAvailable;
26 bool useSpeedBoost;
27 #endregion
28
29 #region Properties
30 public float SpeedModifier
31 {
32 get { return speedModifier; }
33 set { speedModifier = value; }
34 }
35
36 public bool SpeedBoostAvailable
37 {
38 get { return speedBoostAvailable; }
39 set { speedBoostAvailable = value; }
40 }
41
42 public bool UseSpeedBoost
43 {
44 get { return useSpeedBoost; }
45 set { useSpeedBoost = value; }
46 }
47
48 public int HealthNodes
49 {
50 get { return healthNodes; }
51 set { healthNodes = value; }
52 }
53
54 public bool EnemiesVisible
55 {
56 get { return enemiesVis; }
57 }
58
59 /// <summary>
60 /// Returns the arm object attached to the player.
61 /// </summary>
62 public Arm PlayerArm
63 {
64 get { return playerArm; }
65 }
66
67 public Face PlayerFace
68 {
69 get { return playerFace; }
70 }
71 #endregion
72
73 #region Initialize
74 public Player(Sprite sprite)
75 {
76 Type = sprite.Type;
77 Position = sprite.Position;
78 v2Dim = new Vector2(64, 64);
79 Origin = new Vector2(32, 32);
80 Name = sprite.Name;
81 TextureAsset = sprite.TextureAsset;
82 Rotation = sprite.Rotation;
83 Scale = sprite.Scale;
84 Attitude = 0;
85 this.Texture = sprite.Texture;
86 Velocity = Vector2.Zero;
87 eDirection = Direction.Right;
88 LayerDepth = sprite.LayerDepth;
89 healthNodes = 4;
90 Health = healthNodes * 2;
91 playerFace = new Face(this); // create attached face object
92 playerArm = new Arm(this); // create attached arm object
93 SetAnimations();
94 speedModifier = 1;
95 Collidable = true;
96 }
97 #endregion
98
99 #region Update
100 public override void Update(GameTime gameTime, List<Sprite> sprites)
101 {
102 if (eHealth <= 0)
103 {
104 if (VelocityY > 0)
105 VelocityY = 0;
106 Collidable = false;
107 playerFace.IsVisible = false;
108 playerArm.CurrentAnimation = "Invis";
109 isDying = true;
110
111 eState = State.Dead;
112 CurrentAnimation = "Dead";
113 if (!IsVisible || PositionY > 720)
114 IsAlive = false;
115 eForces.Add(new Force(12.0, 90));
116 Rotation = 0;
117 double teste = Math.Cos(gameTime.TotalGameTime.Milliseconds);
118 eForces.Add(new Force(teste * 100, 0));
119 }
120 else // If the player IS ALIVE
121 {
122 isDying = false;
123 ApplyAnimations();
124
125 if (eState == State.Hurting)
126 hurtTimer = gameTime.TotalGameTime.TotalSeconds;
127
128 if (hurtTimer != 0 && gameTime.TotalGameTime.TotalSeconds - hurtTimer < 1)
129 {
130 hurt = true;
131 Invulnerable = true;
132 }
133 else
134 {
135 hurt = false;
136 Invulnerable = false;
137 }
138
139 // Rotate sprite with ground collision
140 if (eState == State.OnGround)
141 {
142 float distance = float.MaxValue;
143 for (int x = (int)(Position.X - Origin.X); x < (int)(Position.X + Width) && x < iHeightMap.Length; x++)
144 if (SpriteHelpers.GetDistance(Position, new Vector2(x, iHeightMap[x])) < distance)
145 {
146 Vector2 place = new Vector2(x, iHeightMap[x]);
147 distance = SpriteHelpers.GetDistance(Position, place);
148 Rotation = SpriteHelpers.SetRotation(Position, place);
149 }
150 if (eDirection == Direction.Left)
151 Rotation -= MathHelper.PiOver2;
152 else
153 Rotation -= MathHelper.PiOver2;
154 }
155 else
156 Rotation = 0;
157
158 // Clamp player X velocity
159 VelocityX = MathHelper.Clamp(VelocityX, -100f, 100f);
160
161 enemiesVis = false;
162 foreach (Sprite s in sprites)
163 {
164 if (s.Type == "Enemy")
165 if (s.IsVisible)
166 {
167 enemiesVis = true;
168 // If the player is in range to do damage
169 if (Math.Abs(ePosition.X - s.PositionX) < (s.Width + 48) && Math.Abs(ePosition.Y - s.PositionY) < (s.Height + 48))
170 {
171 // If player is attacking
172 if (playerArm.attacking)
173 {
174 // If the player's arm has collided with enemy
175 if (playerArm.IntersectPixels(s))
176 {
177 if (!s.Invulnerable)
178 // Cause the enemy damage
179 s.Health--;
180
181 s.eState = State.Hurting;
182 if (eDirection == Direction.Left)
183 s.AddForce(new Force(200.0, 170));
184 else
185 s.AddForce(new Force(200.0, 10));
186 s.Invulnerable = true;
187 break;
188 }
189 }
190 }
191 }
192 }
193
194 DebugString = eState.ToString();
195
196 playerFace.Update(this, gameTime); // update face animation
197 playerArm.UpdateArm(this, gameTime); // update arm attack and animation
198 base.Update(gameTime, sprites);
199 }
200 }
201
202 /// <summary>
203 /// Calculates all of the player sprite animations.
204 /// </summary>
205 public void ApplyAnimations()
206 {
207 if (IsAlive)
208 {
209 // If player is beginning or in a jump
210 if (eState == State.Jumping)
211 {
212 reachPeak = false;
213 // If the player is beginnign a jump
214 if (CurrentAnimation != "Jump")
215 CurrentAnimation = "Jump";
216 // Else, if player has reached the end of jump animation
217 else if (CurrentFrameAnimation.IsAtEnd)
218 eState = State.Falling;
219 }
220 // Else, if player is in falling or rising
221 else if (eState == State.Falling)
222 {
223 // If peak activation hasn't been triggered
224 if (!reachPeak)
225 {
226 // If player is reaching the peak of the jump
227 if (VelocityY > -160 && VelocityY < 0)
228 {
229 reachPeak = true; // trigger peak activation
230 // Do peak animation
231 if (CurrentAnimation != "Peak")
232 CurrentAnimation = "Peak";
233 }
234 // Else, if the player is rising or falling
235 else
236 if (CurrentAnimation != "Fall")
237 CurrentAnimation = "Fall";
238 }
239 else // Else, if peak has already been triggered
240 {
241 if (CurrentAnimation == "Peak")
242 if (CurrentFrameAnimation.PlayCount > 0)
243 CurrentAnimation = "Fall"; // Do fall animation
244 }
245 }
246 // Else, if player is on the ground
247 else if (eState == State.OnGround)
248 {
249 // If player was previously FALLING
250 if (prevState == State.Falling)
251 hasLanded = true; // allow for landing sound
252 else
253 hasLanded = false;
254
255 reachPeak = false;
256 // If the player is NOT moving
257 if (Math.Abs(VelocityX) < 10)
258 {
259 // Do idle animation
260 if (CurrentAnimation != "Idle")
261 CurrentAnimation = "Idle";
262 }
263 // Else, if the player IS moving
264 else
265 {
266 // Do move animation
267 if (CurrentAnimation != "Move")
268 CurrentAnimation = "Move";
269 }
270 }
271 }
272 prevState = eState;
273 }
274 #endregion
275
276 #region Methods
277 /// <summary>
278 /// Manually creates all of the animations from the sprite sheet.
279 /// </summary>
280 public void SetAnimations()
281 {
282 AddAnimation("Idle", 0, 0, (int)v2Dim.X, (int)v2Dim.Y, 4, 0.2f, "Idle");
283 AddAnimation("Move", 0, (int)v2Dim.Y, (int)v2Dim.X, (int)v2Dim.Y, 12, 0.1f, "Move");
284 AddAnimation("Jump", (int)v2Dim.X * 2, (int)v2Dim.Y * 2, (int)v2Dim.X, (int)v2Dim.Y, 3, 0.08f, "Fall");
285 AddAnimation("Peak", (int)v2Dim.X * 5, (int)v2Dim.Y * 2, (int)v2Dim.X, (int)v2Dim.Y, 3, 0.15f, "Fall");
286 AddAnimation("Fall", (int)v2Dim.X * 4, (int)v2Dim.Y * 2, (int)v2Dim.X, (int)v2Dim.Y, 1, 0.1f, "Fall");
287 AddAnimation("Dead", 0, (int)v2Dim.Y * 4, (int)v2Dim.X, (int)v2Dim.Y, 1, 1.0f, "Dead");
288
289 CurrentAnimation = "Idle";
290 IsAnimating = true;
291 }
292 public override void OnFirstPass(List<Sprite> sprites)
293 {
294 sprites.Add(playerArm);
295 }
296 #endregion
297
298 #region Draw
299 /// <summary>
300 /// Draws the sprite to the screen
301 /// </summary>
302 /// <param name="spriteBatch">SpriteBatch</param>
303 public override void Draw(SpriteBatch spriteBatch)
304 {
305 base.Draw(spriteBatch);
306
307 playerFace.Draw(spriteBatch); // call face object's draw method
308 //playerArm.Draw(spriteBatch); // call arm object's draw method
309 }
310 #endregion
311 }
312 }