/// <summary> /// Computa el area donde se proyecta el rayo. /// </summary> /// <returns></returns> private Rectangle ComputeRayArea() { Vector2 a = this.Source; Vector2 b = MathTools.Move(this.Source, this.Radius, Math.Abs(this.Direction)); this.Hit = b; if (a.X > b.X) { Helper.Swap <float>(ref a.X, ref b.X); } if (a.Y > b.Y) { Helper.Swap <float>(ref a.Y, ref b.Y); } /* En caso de que la direccion sea perpendicular, para evitar que el area de interseccion sea plana (sin volumen) * segun la direccion incrementamos o decrementamos en 1 la altura o anchura del area: */ switch ((int)this.Direction) { case 0: case 180: a.Y--; b.Y++; break; case 90: case 270: a.X--; b.X++; break; } return(new Rectangle((int)a.X, (int)a.Y, (int)(b.X - a.X), (int)(b.Y - a.Y))); }
/// <summary> /// Dibuja la representacion grafica del cuerpo. /// </summary> public void Draw() { // Si se definio el metodo de pre dibujado lo ejecutamos: if (this.PreDraw != null) { PreDraw(this); } // Dibujamos el area del cuerpo: Helper.DrawBox(Rectangle, Color); // Escribimos el angulo: if (Debug) { string directions = (Left ? "Left\n" : "") + (Up ? "Up\n" : "") + (Right ? "Right\n" : "") + (Down ? "Down" : ""); if (!Fixed) { Helper.DrawText(Direction.ToString() + "º\n" + directions, new Vector2(Rectangle.X + 1, Rectangle.Y + 1), Color.White); } } // Si no es un cuerpo fijo y este se ha movido en la ultima iteracion dibujamos una linea que represente la direccion: if (!Fixed && Direction > -1) { // Obtenemos el extremo de la linea desplazando las coordenadas xy 32 pixeles en la direccion recorrida: Vector2 endPoint = MathTools.Move(Center, 32, Direction); // Dibujamos la linea: Helper.DrawLine(Center, endPoint, Color.Blue); } // Si se definio el metodo de post dibujado lo ejecutamos: if (this.PostDraw != null) { PostDraw(this); } }
/// <summary> /// Actualiza el estado de la escena. /// </summary> public void Update() { // Actualizamos los estados de todos los cuerpos de la escena que no sean fijos y esten activos: foreach (Body body in bodies) { // Si se definio, ejecutamos el metodo de pre actualizacion del cuerpo: if (body.PreUpdate != null) body.PreUpdate(body); body.Update(); } // Recorremos la lista de cuerpos de la escena y calculamos sus colisiones y su respuesta en caso de haber colision: foreach (Body currentBody in bodies) { // Buscamos colisiones con el resto de cuerpos de la escena: collisions.Clear(); foreach (Body body in bodies) { // Descartamos al cuerpo actual en la busqueda: if (currentBody != body && currentBody.Enabled) if (currentBody.Rectangle.Intersects(body.Rectangle)) collisions.Add(body); } // Evaluamos la respuesta a la colision: if (collisions.Count > 0) { // Si hay colisiones con el cuerpo actual lanzamos el evento y enviamos la lista de cuerpos que colisionan: if (currentBody.OnCollision != null) currentBody.OnCollision(collisions.ToArray()); // Descartamos primero cualquier cuerpo que no sea solido para no calcular respuesta con el: List<Body> collisionsToResponse = new List<Body>(); foreach (Body body in collisions) if (body.Solid && body.Fixed) collisionsToResponse.Add(body); if (collisionsToResponse.Count > 0) { // Invertimos el angulo de direccion que tenia el cuerpo: float dir = currentBody.Direction + (currentBody.Direction > 180 ? -180 : 180); // Si hay colisiones obtenemos la respuesta a la colision para recolocar el cuerpo: int count; do { // Retrocediendo un pixel en la direccion opuesta que recorria el cuerpo: currentBody.Location = MathTools.Move(currentBody.Location, 1, dir); // Comprobamos las colisiones restantes: count = collisionsToResponse.Count; foreach (Body b in collisionsToResponse) if (!currentBody.Rectangle.Intersects(b.Rectangle)) count--; } while (count > 0); // Igualamos la ultima posicion con la actual de la correccion para anular la direccion tomada en el proximo Update() del cuerpo: currentBody.lastPoint = currentBody.Location; } } } // Si se definio, ejecutamos el metodo de post actualizacion del cuerpo: foreach (Body body in bodies) if (body.PostUpdate != null) body.PostUpdate(body); }