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
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136 |
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Brains.Framework;
using Microsoft.Xna.Framework;
namespace Brains.Spatial
{
public class SpatialTable
{
public Dictionary<int, List<Agent>> Buckets;
public float SceneWidth;
public float SceneHeight;
public float CellSize;
public int Rows;
public int Cols;
private List<int> bucketsObjIsIn = new List<int>(4);
private List<int> tmpIds = new List<int>(4);
private List<Agent> objects = new List<Agent>();
public SpatialTable()
{
}
//Called on Load
public void Setup(int scenewidth, int sceneheight, int cellsize)
{
Cols= scenewidth / cellsize;
Rows= sceneheight / cellsize;
Buckets = new Dictionary<int, List<Agent>>();
SceneWidth = scenewidth;
SceneHeight = sceneheight;
CellSize = cellsize;
}
//Called when the object is created and every frame to update
internal void RegisterObject(Agent obj)
{
tmpIds= GetIdForObj(obj);
for (int i = 0; i < tmpIds.Count; i++)
{
if (!Buckets.Keys.Contains(tmpIds[i]))
Buckets.Add(tmpIds[i], new List<Agent>());
((List<Agent>)Buckets[tmpIds[i]]).Add(obj);
List<Agent> b = (List<Agent>)Buckets[tmpIds[i]];
}
}
//Called every update
internal void ClearBuckets()
{
foreach (var item in Buckets)
{
item.Value.Clear();
}
}
public List<int> GetIdForObj(Agent obj)
{
bucketsObjIsIn.Clear();
Vector2 min = new Vector2(
obj.Position.X - (obj.Radius),
obj.Position.Y - (obj.Radius));
Vector2 max = new Vector2(
obj.Position.X + (obj.Radius),
obj.Position.Y + (obj.Radius));
float width = SceneWidth / CellSize;
//TopLeft
AddBucket(min,width,bucketsObjIsIn);
//TopRight
AddBucket(new Vector2(max.X, min.Y), width, bucketsObjIsIn);
//BottomRight
AddBucket(new Vector2(max.X, max.Y), width, bucketsObjIsIn);
//BottomLeft
AddBucket(new Vector2(min.X, max.Y), width, bucketsObjIsIn);
return bucketsObjIsIn;
}
private void AddBucket(Vector2 vector,float width,List<int> buckettoaddto)
{
int cellPosition = (int)(
(Math.Floor(vector.X / CellSize)) +
(Math.Floor(vector.Y / CellSize)) *
width
);
//float conv = 1f / CellSize;
//int cellPosition = (int)(vector.X * conv + vector.Y * conv * width);
if(!buckettoaddto.Contains(cellPosition))
buckettoaddto.Add(cellPosition);
}
internal List<Agent> GetNearbyItems(Agent agent, int distance)
{
Vector2 min = new Vector2(
agent.Position.X - (agent.Radius),
agent.Position.Y - (agent.Radius));
Vector2 max = new Vector2(
agent.Position.X + (agent.Radius),
agent.Position.Y + (agent.Radius));
Vector2 topLeftCell = new Vector2(
(int)Math.Floor(min.X / CellSize),
(int)Math.Floor(min.Y / CellSize));
Vector2 bottomRight = new Vector2(
(int)Math.Floor(max.X / CellSize),
(int)Math.Floor(max.Y / CellSize));
List<Agent> _agents = new List<Agent>();
for (int y = (int)topLeftCell.Y; y <= bottomRight.Y; y++)
{
for (int x = (int)topLeftCell.X; x <= bottomRight.X; x++)
{
int cellPosition = (int)(
x +
y *
Cols
);
if(Buckets.Keys.Contains(cellPosition))
_agents.AddRange(this.Buckets[cellPosition]);
}
}
return _agents;
}
}
} |