using System; using System.Collections.Generic; using System.Text; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; namespace Peanuts { public class PeanutsView { private PeanutsModel model; private BasicEffect effect; private GraphicsDevice device; private SpriteBatch spriteBatch; private SpriteFont font; public PeanutsView(PeanutsModel m, BasicEffect e, GraphicsDevice d) { model = m; effect = e; device = d; spriteBatch = new SpriteBatch(device); } public void SetFont(SpriteFont f) { font = f; } public void Draw() { // draw score and time if (font != null) { spriteBatch.Begin(SpriteBlendMode.AlphaBlend, SpriteSortMode.Deferred, SaveStateMode.SaveState); spriteBatch.DrawString(font, "" + model.GetPlayerScore(), new Vector2(20, 20), Color.White); spriteBatch.DrawString(font, "" + model.GetTimeLeft(), new Vector2(200, 20), Color.White); spriteBatch.End(); } // draw sprites and play field IList sprites = model.GetSprites(); device.VertexDeclaration = new VertexDeclaration(device, VertexPositionNormalColor.VertexElements); effect.Begin(); foreach (EffectPass pass in effect.CurrentTechnique.Passes) { pass.Begin(); // draw all of the sprites foreach (Sprite s in sprites) { if (s is ValueDisplay) { } else { DrawSprite(s); } } // draw the playfield Vector3[] fieldFan = new Vector3[] { new Vector3(0.0f, 0.0f, 0.0f), new Vector3((float)model.GetWidth(), 0.0f, 0.0f), new Vector3((float)model.GetWidth(), (float)model.GetHeight(), 0.0f), new Vector3(0.0f, (float)model.GetHeight(), 0.0f), new Vector3(0.0f, 0.0f, 0.0f) }; renderTriangleFan(fieldFan, Color.Green); pass.End(); } effect.End(); } /// /// Draws the given sprite. The current implementation draws sprites as /// four-sided pyramids /// /// the sprite to draw private void DrawSprite(Sprite s) { // get the center and radius float centerX = (float)s.GetX(); float centerY = (float)s.GetY(); float r = (float)s.GetBoundingRadius(); // compute top, bottom, left, and right float top = centerY - r; float bottom = centerY + r; float left = centerX - r; float right = centerX + r; // define z-values float peakZ = -0.1f; float baseZ = -0.05f; // create fan of vertices for sides of pyramid Vector3[] pyramid = new Vector3[] { new Vector3(centerX, centerY, peakZ), // top of pyramid new Vector3(left, top, baseZ), new Vector3(right, top, baseZ), new Vector3(right, bottom, baseZ), new Vector3(left, bottom, baseZ), new Vector3(left, top, baseZ) }; renderTriangleFan(pyramid, s.GetColor()); } /// /// Draws the given triangle fan on the current graphics device. /// This should be invoked within a technique's pass. /// /// A list of points on the fan, with the fan point in element 0 /// The color of the triangles in the fan void renderTriangleFan(Vector3[] fan, Color c) { // we convert the fan to a list so we can give each face its // proper normal int numTriangles = fan.Length - 2; VertexPositionNormalColor[] verts = new VertexPositionNormalColor[numTriangles * 3]; // go over all triangles in the fan for (int t = 0; t < numTriangles; t++) { // do positions of vertices of triangle number t verts[t * 3].Position = fan[0]; verts[t * 3 + 1].Position = fan[t + 1]; verts[t * 3 + 2].Position = fan[t + 2]; // and set colors for (int i = 0; i < 3; i++) { verts[t * 3 + i].Color = c; } // compute normal and assign to vertices Vector3 side1 = fan[t + 1] - fan[0]; Vector3 side2 = fan[t + 2] - fan[0]; Vector3 normal = Vector3.Cross(side2, side1); normal.Normalize(); for (int i = 0; i < 3; i++) { verts[t * 3 + i].Normal = normal; } } // draw the triangle list device.DrawUserPrimitives(PrimitiveType.TriangleList, verts, 0, numTriangles); } } }