Making a laser not go through and behind an object in its path

Basically in my game your character is killed and the scene restarts when a laser hits the property “YOU” which is on the cube that is you. However the only way I can figure this out is to make the laser a solid shadeless red cylinder that, when it strikes you, kills you. The problem with this is that the laser, being an object, has to be long enough to cover all the walls in the level, but that makes it able to go through other objects in an unrealistic manner. The object I have to demonstrate in my .blend is the supports of the one platform.

The only solution I see is to make the laser have a scaling animation from full length to the hole it is shot from, and when it touches any object it jumps to the point in the animation to where it no longer passes through the object. I’m not sure how to approach this though.

If anyone knows how to do this or if there is a simpler way, please let me know. I don’t really know how to program in Python but I can get by. Thanks in advance :slight_smile:

Game controls:
WASD- move
Mouse- look around
Spacebar- jump
LeftClick- activate button
Escape- pause (don’t press Q at the pause screen, I deleted the Main Menu scene and it will probably crash the game)
End- force quit

Using Blender 2.70
Here is a link to the .blend from Dropbox, this website’s attachment option has been acting up for me: https://db.tt/JvF8Cnfp

Python, my friend, is the answer :smiley:
If you’re OK with the laser just being a solid line, you can use drawLine in python to draw a line from a laser’s launching point to its impact point using a ray.
Some basic code:


import GameLogic
import mathutils
scene = GameLogic.getCurrentScene()
cont = GameLogic.getCurrentController()
own = cont.owner

# sensors
ray = cont.sensors["ray"]

hitObj = ray.hitObject

if ray.positive:
    # Get info
    pos_vec = mathutils.Vector(ray.hitPosition)
    # Make color, draw line
    red = 1.0
    green = 0.0
    blue = 0.0
    color = [ red, green, blue]
    bge.render.drawLine( own.worldPosition, pos_vec, color)
    #                        ^starting point, ^end point, ^color

Hook this up in your laser’s firing object with a ray sensor (named “ray”) connected to a python controller with this script in it. This works in Blender 2.66; I don’t know why it wouldn’t in 2.7. So, yeah! Good luck!

If you will use a mesh You can use python to get the distance from the start of the ray to the hit position, and use it as value in one of the axis of scale.


import bgecont = bge.logic.getCurrentController()
own = cont.owner

ray = cont.sensors[0] #Get the ray sensor
shape = own.children[0] #Get the children

distance = own.getDistanceTo(ray.hitPosition) #This fuction return the distance between objects or vectors
shape.localScale.y = distance #Set the local scale of the children object as the value of distance


Example: ray.blend (88.1 KB)

here you are sir :smiley:

set to fire with space

Attachments

FreekingLaserBeams.blend (443 KB)

-carlo697
Your file is working the best for me, thanks a lot! It’s working beautifully now

@ torogadude: You could size the mesh to 0.01 unit and than multiply by 100 in the code:

shape.localScale.y = distance * 100

Also, I realized that it is not necessary have the object parent(i don’t know why i did it), just delete:

shape = own.children[0] #Get the children

in the script, replace “shape” in the last line with “own”, and put the same logic bricks in the mesh.

Thanks, Carlo. Now, the method works as far as the laser goes, but since it is set to No Collision in the Physics settings it no longer can kill me. I have tried collision in both materials and properties to restart the scene but it doesn’t work, it just stops when it hits my bounding box instead of killing me. Is there any way to make the laser ignore my body or make it restart the scene when it touches my material or property while still having it set to No Collision?


Target=sens.hitObject
if 'Health' in sens.hitObject:
    Target['Health']=Target['Health']-1

have property Health in player and this logic

if Health interval min:-100 max:0--------and------------restart scene

Not working. This is attached to the laser’s script too, right? I have this in it:


import bge
cont = bge.logic.getCurrentController()
own = cont.owner

ray = cont.sensors[0] #Get the ray sensor
own = own.children[0] #Get the children

distance = own.getDistanceTo(ray.hitPosition) #This fuction return the distance between objects or vectors
own.localScale.y = distance #Set the local scale of the children object as the value of distance

Target=sens.hitObject
if 'Health' in sens.hitObject:
    Target['Health']=Target['Health']-1

I gave the player an integer property called “Health” and set it to 1, and have the logic bricks set up like you said. Though would it not be easier to set Evaluation Type to “Equal” instead of “Interval”?

I see you don’t know much about python, the line: “Target=sens.hitObject” make reference to a variable(sens) that does not exist.

This work:

import bge
cont = bge.logic.getCurrentController()
own = cont.owner

ray = cont.sensors[0] #Get the ray sensor

distance = own.getDistanceTo(ray.hitPosition) #This fuction return the distance between objects or vectors
own.localScale.y = distance #Set the local scale of the children object as the value of distance

hitObject = ray.hitObject
if "Health" in hitObject:
    hitObject["Health"] -= 1

Example: ray.blend (88.1 KB)

Also, the physics type of a object no matter when it cast a ray.

@BluePrintRandom: instead of use: variable = variable-1, you can use: variable -= 1

Yep, I don’t know much about Python. It works beautifully now, Carlo, thanks a lot!

I know, I often do, this was because he was new to python :smiley: