Projectiles - How can I get the wall 'normals' orientation?

Hi,
i’m new there and I’d like to ask something about projectiles and ‘normals’ orientation.

Here is the problem :I’ve made a basic character that is able to send projectiles.
When the projectile touches a wall or the ground (‘wall’ or ‘ground’ properties), an object is added through Python.
Actually, this object is just a plane. I may replace it with a more complex object later.
Problem 1 :

  • I’d like to set the orientation of this plane toward (is that the good word, I can’t speak english anymore :confused:) the wall ‘normals’ direction.
    How would you get that information?
    And how would you apply it to the plane?

I’ve made a quick drawing :

http://aandria.com/wp-content/images/diary/throwing.jpg

Problem 2 :
How can i record the object position just before it touches the wall?
I use a ‘collision’ sensor.
I want that variable because I’d like my plane (the yellow teleporter on the picture) to be a little away from the wall (to avoid collision problems).

Problem 3 :

  • If those yellow zones were portals, how would you add an object there and avoid the problem of collision with the wall?
    Ex : My character enters a teleporter entry and, then, appears close to the wall.
    (Even if I find a solution with my problem 2, i may have an issue with big meshes I think)

I’ve read a lot of threads about portals, but I think that my problems are different (or I misread).
Ah, I’d prefer a Python solution :slight_smile:

Thank you for your help.

:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
Scripts submitted by BlenderArtists Users

13.01.09
PhilB
Projectile_portals.blend

12.12.08
Almost
portal_placement.blend

19.12.08
Bluesocarrot
projectiles_normals.blend

And much help from all the people here.

You can use emptys close to the wall to add an object.

Welcome to BA, cray!

Problem 1:
To get the normal of a face, you have to point a ray sensor to it and used the python method “getHitNormal()” of the ray sensor. this will return the face’s normal vector. reference

then you can apply that vector to the projectile with the function called “alignAxisToVect()” with the vector you got before reference

problem 2:

you can use a collision sensor and a global variable like this


if colision.isPositive():
    GameLogic.obPosition = own.position

problem 3
try not to pass meshes bigger than the portal trough it xD :slight_smile:

Minifig > Even if I use emptys, the problem is the same as the one i’ve described previously.
I need to create my object dynamically. I wouldn’t know empty’s coordinates too.

cyborg_ar > Thank you for references!
That will be helpful. But, if I understand well, getHitNormal has to be used with a Ray sensor.
I can’t use it with my projectiles (let’s precise, “tennis balls”, “grenades”) as they are not being thrown straight to the wall. The Ray sensor might not detect the good collision location, am I right?

then you can apply that vector to the projectile with the function called “alignAxisToVect()”

You mean, apply that vector to my plane, my teleporter, don’t you?

Problem 2 : I don’t understand how is the collision sensor working exactly?
If the collision is positive, I apply the object position to GameLogic.obPosition right?
I thought that I’d be better to record the object position just before it enters the collision area?
I thought that after, it’s just ‘too late’ and I would have collision issues between my new object and the wall?

Problem 3 :
:slight_smile: that’s ‘so’ right
[Or I just think about changing the mesh size before entering my teleporter, teleport, put the mesh away from the teleporter, and get back to normal size]

Thank you for your answers :slight_smile:

Look in the game resources section, I have a portal tutorial.

Thank you for answering but I don’t think that my problem is ‘another basic portal problem’ (but not far, i should admit).
I’ve already got to the point where i’m able to move from a teleporter to another one (an empty) and apply velocity and orientation to my character.
And I had already read your thread wich was informative.

Here i’m trying to create a teleporter dynamically, and I have to get the wall normals (check the picture above) to do it the way i want.

The collision algorithm actually computes the collision points but unfortunately this information is not returned to the collision sensor. This could be a nice feature to add.

For the time being I advise you to use the object rayCast() method to estimate the collision point position and normal. This function allows you to cast a ray from any point to any point and filter objects by property.
You could cast a ray from the player or from the center of the room towards the projectile, extending the ray long enough to make sure that the ray will hit the wall and setting a filter on a property that is specific to the wall: the ray will ignore all objects except the wall and return the hit point coordinates and normal, which should be very close to the actual hit point if you choose a good start point for the ray.

Thank you I’m actually trying to make it work.

I’m sorry but my english isn’t that good so I’d like to be sure that I understood you well.
So here is my question :
is your suggestion ok in the case that my projectiles are physicals objects (balls) and that the impact on the floor or on the wall will be determined by the distance and the weight of my projectiles (and gravity, etc…)?

http://aandria.com/wp-content/images/diary/ray.jpg

In that case, the ray is going straight and the hit point will not be same as the impact coordinates i’m looking for.
That would be good for a gun or a laser, but maybe different from my needs?
Do I mistake?

Sorry for those questions, I’m just learning and trying to understand :confused:

Edit :

I think I got it! I’m lacking of something : english skills or logic. Maybe both.
http://aandria.com/wp-content/images/diary/ray_ok.jpg

http://s1.subirimagenes.com/privadas/268566ray2.jpg

cyborg_ar > This hit doesn’t count because we are looking for the “wall” property but it would be ok if i wanted to use it on the floor (‘floor’ property)too, right?

I think I got it thank you for your time :slight_smile:

I just noticed that cyborg_ar’s and ben2610’s solution are the same.

yeah, i was assuming you only wanted the wall property,like ben’s explanation

btw, checked your portfolio you are an awesome illustrator!

Cray: yes you got it right.

Just one clarification: you don’t have to cast the ray all the time, but just when the projectile hits the wall, which will trigger the collision sensor, which in turns triggers a python controller in which you run the rayCast() function.

The rayCast() function is a game object method. This means you have to select an object to run the function like this: obj.rayCast(…). The object you choose does matter: the ray will ignore it. So don’t choose the wall! The projectile is the most logical object to use, because the collision sensor will be on it too.

cyborg_ar > ah, thank you! but i’m a complete Blender beginner too :wink:
I try to spend time learning BGE basics (through Python) now that I am on “holidays” (just finished working on a book) so that I can later concentrate on game design, graphics, and have some [professional] fun.

ben2610 > I was actually trying and searching a lot before asking again for any kind of help, and your message was what I was looking for :slight_smile:
I was on the good way before reading your message, but i had connected the Ray sensor to my gun (hand). The controller was ok.
Now I’ve moved the sensor to my projectile.
Question:

  • you said i have to select an object to run the fonction obj.rayCast(…)

The object you choose does matter: the ray will ignore it

On this page it’s said that obj is defined by # get game object rayCast is attached
So, in that case, do i choose my projectile because the sensor is attached to it (no other choice) or is it because we want to use the fact that the ray will ignore it?

  • I’ve read your previous several times, how would you

extend the ray long enough to make sure that the ray will hit the wall
with a dynamically created object (projectile)?

  • Is there a way so that I can visually have a preview of my ray?

  • here is where i am :

get GameObject, hit position and angle.

hit = bullet.rayCast( bullet, gun, 0, “wall”)

and… getHitNormal (getHitObject, getHitPosition, etc) how do you use it?
I couldn’t extract any value from ‘hit’.
tuple object has no attribute getHitObject

[ i don’t know how to delete, sorry ]

[ i don’t know how to delete, sorry ]

cyborg_ar > ah, thank you! but i’m also a complete Blender beginner :slight_smile:
I want to spend time learning BGE basics (through Python) now that I am on “holidays” (just finished working on a book) so that I can later concentrate on game design, graphics, and have some [professional] fun.

ben2610 > I was actually trying and searching a lot before asking again for any kind of help, and your message was what I was looking for :slight_smile:

Edit : i could figure out some things by myself.
I could get the normals, hit object, hit point.

Now here is my last problem :
My projectile creates an object “explosion” (wich actually is just a plane) when it touches a wall.
This plane is dynamically called through a collision sensor.
It seems that my raycast script is called before my collision script :
so when i try to update my plane with alignAxistoVect i get a message that “explosion_plane” is not in the list yet.

Here is my basic script :


hit = bullet.rayCast( bullet, gun, 0, "wall")
portal_exit = objects["OBgun_portal_exit"]
portal_exit.alignAxisToVect(hit[2], 0, 1.0)
portal_exit.alignAxisToVect(hit[2], 1, 1.0)
portal_exit.alignAxisToVect(hit[2], 2, 1.0)
  • How can i avoid this problem?

  • I don’t know yet much about alignAxisToVect, my plane doesn’t get the good orientation. Am I mistaking again with the way to use it?
    Can i use variables vect0, etc… like portal_exit.alignAxisToVect([vect0, vect1, vect2], 1, 1.0)?

(And is there a way so that I can visually have a preview of my ray?)

Thanks again for your help.

cray: you must not access object reference through the object list because this is not extendible: if you have two “explosion_plane” objects at a time in the scene (possible as you create them dynamically), using objects[“explosion_plane”] will only return one of them and probably not the one you want.

To get object reference in a safe way, you must always start from the controller, sensor or actuators like in these expressions:
obj = controller.getOwner()
obj = controller.getSensor(“somesensor”).getOwner()
obj = controller.getActuator(“someactuator”).getOwner()

The advantage with these expression is that they return “local” references: “somesensor” and “someactuator” refers to names of sensor and actuators attached to the controller, which itself can be obtained locally with GameLogic.getCurrentController().

When you spawn several objects, the above expressions will always refer to the object that triggered the controller or to an object that is linked to this object through sensors or actuators. In the later case, as long as these objects are spawned together (through dupligroup or parent/child relationship), the “inner” links remain local: the references you get through these expressions point to objects in that group.

To answer your question more specically: indeed the order of execution of controllers is not predictable. The best solution to this problem is to have only one script that does everything => you control the order of operation.

Note that you can dynamically create an object in a script using instantAddObject() method of the AddObject actuator and retrieve a reference to that object using getLastCreatedObject(). After that, it’s easy to set the object at the right location. So you will attach an AddObject actuator but you will not actually activate it, you will simply use its instantAddObject() method.

Alternatively, you can attach the script that sets the explosion position to the explosion object itself and activate it with an always sensor: as soon as the object is created, it will trigger the script. The difficulty is to retrieve the explosion position: you can save it in a property of the player, which you can get via object list, because there is only one player.

About the alignAxisToVect() function, you should only use it once to set the z axis of the plane along the normal. The X and Y axis will automatically take some orientation parallel to the wall.

About the preview of the ray, you can draw line in the world using Rasterrizer.drawLine() method. The line will only be visible for one frame, so you must repeat the operation on several consecutive frame if you want to see the line more clearly.

Your advices are always helpful, thank you very much.

I could include the addInstantAddObject() and getLastCreatedObject() method to my script and understand the use of multiple references.
The console don’t return any errors.

Last issues…
Major issue :

  • if i send a projectile and hide quickly behind a wall (‘wall’ property) the ray hits the wall and my portal appears in the air, before touching anything.
    Does it mean that i should forget about rayCast and use a collision sensor instead?

Minor issue :

  • My portal follows the normal of vertical walls. But when it’s not vertical, it seems that i can’t use alignAxistovect() the right way
  • My portal should be a green plane, with a white arrow pointing to the top.
    Actually, it’s always pointing to the left.

Can you please take a look at my .blend?
(I’m sorry if I’m asking too much…)

The main problem you would have had with the vectors:

    hitx=wall_hit[2][0]
    hity=wall_hit[2][1]
    hitz=wall_hit[2][1]

will work best as:

    hitx=wall_hit[2][0]
    hity=wall_hit[2][1]
    hitz=wall_hit[2][2]

To remedy the rayCast is to get the position of the gun object when it is thrown and use that as the rayCast position instead of your gun object.

If the arrow always points to the left, rotate it to the right =P (The actual model)

I’ve implemented these things in your .blend, just to see if they would work. And I think it might! :smiley:

Attachments

projectiles_normals.blend (236 KB)

Thank you very much :slight_smile:

hity=wall_hit[2][1]
hitz=wall_hit[2][1]
Let’s say that i needed some sleep!

Thank you for modifying the “destroy portals” lines, I was working on that after i posted yesterday.
I noticed that sometimes portals are hidden behind the wall (ok in wireframe mode, but not in solid mode) or don’t disappear the right way.
I’ll check it today.

rayCast pb : In fact i’ve noticed that changing the gun object to its position as a reference didn’t do the trick : if i send a projectile behind a wall, the ray still hits a wall before my projectile collides anything.
mm…
I will think about it today.