Little hint:
it would read a bit better when you write gameObject.visible = True (rather than 0).
While your code is fine here are some remarks:rayCastTo
will be None when the measure does not detect an object. In your code: None when nothing is detected between the owner and the flare (excluding both objects). From bottom-up-view this is perfectly fine (it is the actual implementation).
From top-down-view it causes distortions as you got them. I assume you want to show the flare when it is not covered by other objects. When you rename “ray” to something that expresses what you mean the code suddenly makes more sense:
flareIsCovered = own.rayCastTo(flare)
if not flareIsCovered:
flare.visible = True
else:
flare.visible = False
You have more visibility conditions:
for flare in scene.objects:
if "flare" in flare:
flareIsCovered = own.rayCastTo(flare)
if (not flareIsCovered and
inViewDistance(flare)):
flare.localScale = [getOwner().getDistanceTo(flare) * 0.2 ]*3
flare.visible = True
else:
flare.visible = False
Here are the used functions. You can either import them form a separate module or place it before the using code (the function definition needs to be executed before you call the function).
def inViewDistance(flare):
minViewDistance = flare["flare"]
maxViewDistance = flare["flareDist"]
distance = getOwner().getDistanceTo(flare)
return (distance > minViewDistance and
distance > maxViewDistance)
def getOwner():
return bge.logic.getCurrentController().owner
You might noticed that the property names do not match the purpose of the properties:
“flare”: A) identifies a flare B) contains minimum view distance
“flareDist”: contains maximum view distance
A reader who did not understand the code will not know what the properties are good for.
Other implementations are possible:
import bge
controller = bge.logic.getCurrentController()
owner = controller.owner
scene = bge.logic.getCurrentScene()
flares = [object for object in scene.objects
if object.get("flare", 0) > 0.0]
for flare in flares:
minViewDistance = flare["flare"]
maxViewDistance = flare["flareDist"]
distance = owner.getDistanceTo(flare)
scale = (distance
if (distance > minViewDistance and
distance > maxViewDistance) * 0.2
else None)
visibility = False
if scale:
flareIsCovered = owner.rayCastTo(flare)
if not flareIsCovered:
flare.localScale = [scale]*3
visibility = True
flare.visible = visibility
The calculated scale contains the limit check. objects without property flare and value <= zero are ignored (allows to dynamically disable them).
Maybe it provides you some ideas.