Thank you to anyone who has already donated - your generous donations helped make three months of treatment possible.

My brother Nate continues to fight stage IV Hodgkin's lymphoma. He's just 31, with a wife and baby girl. They have no active income (since he's been unable to return to work), no insurance, and cannot afford the treatment he needs. Nate and his family need your help. Please consider a donation, every dollar helps. Thanks.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
public static class RectangleExtensions
{
	public static float GetHorizontalIntersectionDepth(this Rectangle rectA, Rectangle rectB)
	{
		// Calculate half sizes.
		float halfWidthA = rectA.Width / 2.0f;
		float halfWidthB = rectB.Width / 2.0f;

		// Calculate centers.
		float centerA = rectA.Left + halfWidthA;
		float centerB = rectB.Left + halfWidthB;

		// Calculate current and minimum-non-intersecting distances between centers.
		float distanceX = centerA - centerB;
		float minDistanceX = halfWidthA + halfWidthB;

		// If we are not intersecting at all, return (0, 0).
		if (Math.Abs(distanceX) >= minDistanceX)
			return 0f;

		// Calculate and return intersection depths.
		return distanceX > 0 ? minDistanceX - distanceX : -minDistanceX - distanceX;
	}

	public static float GetVerticalIntersectionDepth(this Rectangle rectA, Rectangle rectB)
	{
		// Calculate half sizes.
		float halfHeightA = rectA.Height / 2.0f;
		float halfHeightB = rectB.Height / 2.0f;

		// Calculate centers.
		float centerA = rectA.Top + halfHeightA;
		float centerB = rectB.Top + halfHeightB;

		// Calculate current and minimum-non-intersecting distances between centers.
		float distanceY = centerA - centerB;
		float minDistanceY = halfHeightA + halfHeightB;

		// If we are not intersecting at all, return (0, 0).
		if (Math.Abs(distanceY) >= minDistanceY)
			return 0f;

		// Calculate and return intersection depths.
		return distanceY > 0 ? minDistanceY - distanceY : -minDistanceY - distanceY;
	}
}

public enum Direction
{
	Horizontal,
	Vertical
}

public void HandleInput(float elapsed)
{
	KeyboardState state = Keyboard.GetState();

	// Handle Keyboard Input
	int horizontal = state.IsKeyDown(Keys.Left) ? -1 : (state.IsKeyDown(Keys.Right) ? 1 : 0);
	int vertical = state.IsKeyDown(Keys.Up) ? -1 : (state.IsKeyDown(Keys.Down) ? 1 : 2);

	// Handle Horizontal Movement
	if (horizontal != 0)
	{
		_playerPosition += Vector2.UnitX * Math.Min(PlayerSpeed * elapsed, Math.Min(_playerSize.X, TileSize)) * horizontal;
		_playerPosition = new Vector2((float)Math.Round(_playerPosition.X), _playerPosition.Y);
		HandleCollisions(Direction.Horizontal);
	}

	// Handle Vertical Movement
	if(vertical != 0)
	{
		_playerPosition += Vector2.UnitY * Math.Min(PlayerSpeed * elapsed, Math.Min(_playerSize.Y, TileSize)) * vertical;
		_playerPosition = new Vector2(_playerPosition.X, (float)Math.Round(_playerPosition.Y));
		HandleCollisions(Direction.Vertical);
	}
}

private void HandleCollisions(Direction direction)
{
	Rectangle playerBounds = GetPlayerBounds();
	int leftTile = playerBounds.Left / TileSize;
	int topTile = playerBounds.Top / TileSize;
	int rightTile = (int)Math.Ceiling((float)playerBounds.Right / TileSize) - 1;
	int bottomTile = (int)Math.Ceiling(((float)playerBounds.Bottom / TileSize)) - 1;

	for (int y = topTile; y <= bottomTile; ++y)
	{
		for (int x = leftTile; x <= rightTile; ++x)
		{
			Vector2 depth;
			if (TileIsObstacle(x, y) && TileIntersectsPlayer(playerBounds, GetTileBounds(y, x), direction, out depth))
			{
				_playerPosition += depth;
				playerBounds = GetPlayerBounds();
			}
		}
	}
}

private static Rectangle GetTileBounds(int y, int x)
{
	return new Rectangle(x * TileSize, y * TileSize, TileSize, TileSize);
}

public Rectangle GetPlayerBounds()
{
	return new Rectangle((int)Math.Round(_playerPosition.X), (int)Math.Round(_playerPosition.Y), (int)Math.Round(_playerSize.X), (int)Math.Round(_playerSize.Y));
}

private static bool TileIntersectsPlayer(Rectangle player, Rectangle block, Direction direction, out Vector2 depth)
{
	depth = direction == Direction.Vertical ?  new Vector2(0, player.GetVerticalIntersectionDepth(block)) :  new Vector2(player.GetHorizontalIntersectionDepth(block), 0);
	return depth.Y != 0 || depth.X != 0;
}

private bool TileIsObstacle(int x, int y)
{
	if (x < 0 || y < 0 || x >= _width || y >= _height) return true;
	return _blocks[x, y] != ' ';
}