KD_Tree_example_loading_bubble.blend (769.2 KB)
this randomly generates a bunch of locations - you could use a look up table / dictionary or something instead as well
KD_Tree_example_loading_bubble.blend (769.2 KB)
KD_Tree_example_loading_bubble_with_terrain_planes_Start.blend (872.6 KB)
this picks from 4 types of objects and randomly spawns them per tile - and also spawns a tile
you could use perlin noise instead of random - and use perlin noise to deform the terrain too
Thank you for your help, this looks really impresive.
Can you set it up for the player to have this bubble?
I’m not sure how far can this grid expand without loosing the performance.
What I wanted to achieve is:
To have Empty objects on map instead of a static objects.
Then activate the static objects when you are in range.
I guess it’s similar to what you are suggesting but it seems this calculate the whole map.
yeah you can do this - so when I build the KDTree I do it from a grid - / list
you can do
#scrape scene objects and get all objects with the property ‘Spawn_Location’
obList =[]
for obj in own.scene.objects:
if 'Spawn_Location' in obj:
obList.append(obj)
and use this list instead
when I get a chance I will set it up.
Since the grid didn’t work for me yet, I’ve been trying something else.
I’m not sure if this would be fast for processing or not.
for obj in scene.objects:
if "Box" in obj:
dist = obj.getDistanceTo(player)
obj['dist'] = dist
if obj['dist'] < 5 and obj['distState'] == False:
addBox = obj.scene.addObject('Box', obj, 0)
addBox.setParent(obj)
obj['distState'] = True
elif obj['dist'] >= 5 and obj['distState'] == True:
for child in obj.children:
if "BoxSpawned" in child:
child.endObject()
obj['distState'] = False
The Empty objects have a Box property and when you are near them, they’ll spawn static objects for a collision. If you are far enough, the static objects are deleted.
you can use a collision sensor / objects on a collision layer for this (empty with a sphere bound for instance)
however this does not scale -
we need to store multiple objects data in a single empty and then spawn / despawn them
we can store a bunch of data in a string and use ast.literal_eval()
to convert it back into a list of lists or a list of tuple etc
what you could do is make a ‘converter’ in bpy - that takes a scene and stores it in empties
Yes, but I didn’t want to use physics for this. I wanted to apply the static objects only when you are at a certain distance from the Empty.
I’m testing my game on an old notebook and less static objects mean better performance.
yes - so instead we use the kdtree - one sec
Thank you, I’ll try it later.
The thing is I’m not using UPGE so this all doesn’t work right away.
Thank you, it looks really interesting.
keep in mind this works best for ‘kit’ - where all the object in the kit are using 1 material
you can spawn a cluster like this - and then use KX_BatchGroup to batch the draw calls in upbge - making the game render much much faster.
if it’s just a few objects it does not make sense - but like a whole little scene that batches is good
(like a 20+ objects)
It has been a while since I’ve replied last time. I’ve been trying several methods to load and unload the objects but the KDtree you’ve mentioned seems to be the most interesting one.
The problem is that you’ve made an example on the newest Blender version with UPBGE. I on the other hand have been using Blender 2.79.
I’ve managed to make it work on Blender 2.79 by appending the objects.
How can I change the properties of an object that is appended to the loading grid?
EDIT: Ok, I’ve managed to add a property for the object.
stored[i].append( ( 'Object', (x3,y3,0), value ) )
and then I had to write this for some reason:
added['Property'] = ob[-1]
What I was expecting was to write ob[2]
but that didn’t work.
Also what happens to the object if you move it?
The individual segements of the grid are created from bottom to top. Is there a way to change it to from left to right and start the grid from x0 and y0?
here is an example on how to do this in a flexible way.
here gets all the objects in the game scene who got a game property “someproperty” stored in a custom class that keep track of all data related to that object (this could be anything).
# init.py
import bge
import mathutils
cont = bge.logic.getCurrentController()
own = cont.owner
# a class to store relevant data
class GameObject:
def __init__(self,name,position):
self.name = name # name of object to spawn.
self.position = position
self.orientation = [[1,0,0],[0,1,0],[0,0,1]]
self.scale = [1,1,1]
self.color = [1,1,1,1]
self.objref = None
own["objects"] = []
for obj in own.scene.objects:
if "someproperty" in obj:
name = obj.name.split(".")
# create instance of class GameObject and store relevant data
gameobject = GameObject(name[0],list(obj.worldPosition))
gameobject.orientation = [list(obj.worldOrientation[0]),list(obj.worldOrientation[1]),list(obj.worldOrientation[2])]
gameobject.scale = list(obj.worldScale)
gameobject.color = list(obj.color)
# add the created gameobject to a list
own["objects"].append(gameobject)
# end KX_Gameobject from scene
obj.endObject()
own["KDtree"] = mathutils.kdtree.KDTree(len(own["objects"]))
for index,gameobj in enumerate(own["objects"]):
own["KDtree"].insert(gameobj.position,index)
own["KDtree"].balance()
and here you draw or remove based on the distance to the player Cube
# draw.py
import bge
cont = bge.logic.getCurrentController()
own = cont.owner
playerpos = own.scene.objects["player"].worldPosition
placer = own.scene.objects["placer"]
maxdist = 40
mindist = maxdist - 2
result = own["KDtree"].find_range(list(playerpos), maxdist)
if result:
for item in result:
co,index,dist = item
if dist < mindist:
if own["objects"][index].objref == None:
placer.worldPosition = own["objects"][index].position
obj = own.scene.addObject(own["objects"][index].name,"placer",0)
obj.color = own["objects"][index].color
obj.worldOrientation = own["objects"][index].orientation
obj.worldScale = own["objects"][index].scale
own["objects"][index].objref = obj
else:
if own["objects"][index].objref != None:
own["objects"][index].objref.endObject()
own["objects"][index].objref = None
Demo blend to try it in action (BGE 2.79 version)
dynamic.blend (1.5 MB)
a KDTree is best used for static objects, unless you want to recreated it every time a object moves ( not the best way to do things)
Thank you for your suggestion.
How is this code taxing on processing? It still adds objects based on distance.
Is it possible to make the bubble around the player another shape than a circle? Can you make it a square or a triangle?
I’ve tried to create a map with the KDtree and I have used your script for it. It works great but I’d like to ask for help if you have time.
This is the file I’ve been working on: KDTree_002.blend (703.8 KB)
The map is a 100 x 100 grid and I have two bubbles around the player.
The first one is for physics and the second one is for high polygon graphics.
What I wanted to do is to have the rest of the map, to be created for the low poly graphics.
Right now it adds a green plane if you leave a place where the bubble was before.
That green plane is a placeholder for the low poly objects.
If there was a way to place the green planes at the start inside the grid. Like the bubble around the player but add it to the whole level.
Then delete the green planes when the bubble overlaps those green planes.
Basically for it to look like this in the end: