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;
}
}
}