Lets analyze your requirements:
This description is a bit distracting but I guess you want following
We define an entry as an object that contains enough data to create a new game object within the current scene. To do that it should have:
- coordinates (x,y,z)
- the name of the game object to get copied from
- (maybe more)
Your input is
- a position with coordinates i = (Ix, Iy, Iz)
- a distance around the coordinates
Your output is a list of entries with coordinates within the distance to the position
Basically what the near sensor does with game objects, but with entries
Your entry is a key/value pair in a dictionary. The key is the name if the game object and the value is the position.
This is no good structure in many ways.
The major problem is that you limit yourself to one possible object. For example you can have just one “bob”. This might be no problem with bob, but how about “stone”, “fence”?
The next problem is that this structure supports access by name. But you need access by position. It is still possible but really inefficient.
I suggest you create a separate “entry” object that keeps all relevant data in one place.
How could it look like?
class Entry:
def __init__(self, name, position):
self.name = name
self.position = position
You can create such objects pretty simple via constructor:
def createSampleEntries():
entries = [
Entry("bob", [10.0, 50.0, 0.0]),
Entry("jon", [30.0, -20.0, 0.0]),
Entry("sam", [-20.0, 40.0, 0.0])
]
for entry in entries:
print("name:", entry.name, "position:", entry.position)
return entries
Finding near entries. This is no trivial tasks. It you use the option above, you would get a list of entries. A list is not efficient on large number of entries. Imagine you have one million entries. You would need to loop through all of them. This takes way to much time.
So you need a better way to organize the entries (which are no game objects!) that finding them by coordinates or more specific by and era of coordinates. The best is to touch only relevant entries (no entries that are far away).
mathutils.kdtree can help here.
If you have a closer look you will realize this does not care entries. It cares positions and a numeric key (index).
Just now we have no numeric key. But wait! Isn’t a list organized by index? Index is a numeric key. So we can indeed use a list of entries. We feed the kdtree with positions and indices and let it doe it’s magic.
import mathutils
...
def createSearchTree(entries):
size = len(entries)
tree = mathutils.kdtree.KDTree(size)
for index, entry in enumerate(entries):
tree.insert(entry.position, index)
tree.balance()
return tree
with that we can find the keys of near entries. We lookup the entries in the list of entries:
import bge
...
def findNearEntries():
# prepare the world
entries = createSampleEntries()
searchTree = createSearchTree(entries)
# prepare the input
measurePosition = (15, 30,0)
distance = 30
# perform search
searchResults = searchTree.find_range(measurePosition, distance)
# convert to entries
nearEntries = [entries[searchResult[1]] for searchResult in searchResults]
# show result
print()
print("look from", measurePosition, "at a range of", distance)
for entry in nearEntries:
print(entry.name, "is near")
# add game objects
scene = bge.logic.getCurrentScene()
for entry in nearEntries:
gameObject = scene.addObject(entry.name, entry.name)
gameObject.worldPosition = entry.position
print(gameObject.name,"added at", gameObject.worldPosition)
I hope you get the idea.