using System; using System.Collections.Generic; using System.Text; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; namespace WindowsGame1 { class Physics { const int PUSH_UP_DIVISOR = 4; const int GRAVITY = 5; const int MAX_JUMP_TIME = 300; const int JUM_STICK_TIME = 50; const int JUMP_PER_TICK = -5; public enum Directions { UP, DOWN, LEFT, RIGHT }; public static void actOn(Mob m, GameTime t) { Console.WriteLine(Physics.GRAVITY); if (!m.IsJumping || m.jumpTime > MAX_JUMP_TIME) { m.IsOnGround = CheckGroundCollide(m, Directions.DOWN); if (m.IsOnGround) { m.resetJumping(); } Rectangle bottomRect = new Rectangle(m.X, m.Y + m.height, m.width, 1); if (!IntersectPixels(bottomRect, null, m.level.rect, m.level.textureData)) { m.Y += (int)TryMove(m, 0, GRAVITY).Y; } } else { int dy = (int) TryMove(m, 0, JUMP_PER_TICK).Y; m.Y += dy; m.jumpTime += t.ElapsedGameTime.Milliseconds; if (dy != JUMP_PER_TICK) { //collision, stop jumping m.jumpTime = MAX_JUMP_TIME + 1; } } } public static bool CheckGroundCollide(Mob m, Directions d) { Rectangle use = new Rectangle(); switch (d) { case Directions.RIGHT: use = new Rectangle(m.X + m.width, m.Y, 1, m.height); break; case Directions.LEFT: use = new Rectangle(m.X, m.Y, 1, m.height); break; case Directions.UP: use = new Rectangle(m.X, m.Y, m.width, 1); break; case Directions.DOWN: use = new Rectangle(m.X, m.Y + m.height, m.width, 1); break; } return IntersectPixels(m, use); } //returns new mx, my public static Vector2 TryMove(Mob m, int mx, int my) { int rx = mx, ry = my; //final values if (mx > 0) { //moving right Rectangle rightRect = new Rectangle(m.X + m.width, m.Y, 1, m.height); for (int i = 0; i < mx; i++) { if (IntersectPixels(m, rightRect)) { rx = i; ry -= PushUpIntersect(m, rightRect); break; } } } else if (mx < 0) { //moving left Rectangle leftRect = new Rectangle(m.X, m.Y, 1, m.height); for (int i = 0; i > mx; i--) { if (IntersectPixels(m, leftRect)) { rx = i; ry -= PushUpIntersect(m, leftRect); break; } } } if (my < 0) { //moving up Rectangle upRect = new Rectangle(m.X, m.Y, m.width, 1); for (int i = 0; i > my; i--) { if (IntersectPixels(m, upRect)) { ry = i; break; } } } else if (my > 0) { //moving down Rectangle downRect = new Rectangle(m.X, m.Y + m.height, m.width, 1); for (int i = 0; i < my; i++) { if (IntersectPixels(m, downRect)) { ry = i; break; } } } return new Vector2(rx, ry); } public static bool IntersectPixels(Mob m, Rectangle useRect) { return IntersectPixels(useRect, null, m.level.rect, m.level.textureData); } public static int PushUpIntersect(Mob m, Rectangle rect) { Rectangle rectangleA = rect; Rectangle rectangleB = m.level.rect; Color[] dataB = m.level.textureData; // Find the bounds of the rectangle intersection int top = Math.Max(rectangleA.Top, rectangleB.Top); int bottom = Math.Min(rectangleA.Bottom, rectangleB.Bottom); int left = Math.Max(rectangleA.Left, rectangleB.Left); int right = Math.Min(rectangleA.Right, rectangleB.Right); // Check every point within the intersection bounds for (int y = top; y < bottom; y++) { for (int x = left; x < right; x++) { Color colorB = dataB[(x - rectangleB.Left) + (y - rectangleB.Top) * rectangleB.Width]; if (colorB.A != 0) { Rectangle pushRect = new Rectangle(rect.X, rect.Y + (rect.Height - rect.Height / PUSH_UP_DIVISOR), rect.Width, rect.Height / PUSH_UP_DIVISOR); Rectangle oppRect = new Rectangle(rect.X, rect.Y, rect.Width, rect.Height - pushRect.Height); if (pushRect.Contains(x, y) && !IntersectPixels(oppRect, null, m.level.rect, m.level.textureData)) { return rect.Bottom - y + GRAVITY; } } } } // No pushing can be done return 0; } public static bool IntersectPixels(Rectangle rectangleA, Color[] dataA, Rectangle rectangleB, Color[] dataB) { // Find the bounds of the rectangle intersection int top = Math.Max(rectangleA.Top, rectangleB.Top); int bottom = Math.Min(rectangleA.Bottom, rectangleB.Bottom); int left = Math.Max(rectangleA.Left, rectangleB.Left); int right = Math.Min(rectangleA.Right, rectangleB.Right); // Check every point within the intersection bounds for (int y = top; y < bottom; y++) { for (int x = left; x < right; x++) { Color colorB = dataB[(x - rectangleB.Left) + (y - rectangleB.Top) * rectangleB.Width]; if (colorB.A != 0) { return true; } } } // No intersection found return false; } } }