shoot direction mouse [SOLVED]

Hello,

I wish to shoot in the direction of my mouse. My cursor is somewhere on the screen, and my ship is on the center of the screen, and wish that the shoot goes where the cursor goes.

How can I convert mouse position to a direction?

For information I have done something like that:

x=base.mouseWatcherNode.getMouseX()
y=base.mouseWatcherNode.getMouseY()

quat=shipNode.getQuat()
quat2=Quat()
quat2.setR(quat.getR())
quat2.setI(quat.getI()+(y/2))
quat2.setJ(quat.getJ())
quat2.setK(quat.getK()+(x/2))
bulletNode.setQuat(quat2)

It works in the case of ship is in position initial, if my ship turns and goes in other direction, shoot is going in inverse direction of the mouse, etcetc… I think I have not the good way to do, it was only a test… :frowning:

I presume that your game uses a top-down camera, and that all gameplay takes place on a single plane (I’ll use the x-z plane below, but it should be easy enough to convert as called for); if not, the solution is a little more complicated (likely involving the “base.camLens.extrude”).

So, presuming a top-down camera and the x-z plane, you should be able to simply use trigonometry to convert your mouse x-y coordinates to a heading angle, and then apply that:

import math

angle = math.atan2(mousePos.y, mousePos.x)
#  Depending on your situation, you may find that you want to
# fiddle with either the order or the sign of one or both
# of the parameters to atan2 above.

bulletNode.setH(angle)

the game is full 3d directionnal. It is a space game into a space environnement…

Ah, I see–you said that the ship was in the centre of the screen, which I took to mean a top-down perpsective–my mistake.

In that case, the “extrude” method (to which I linked in my previous post, I believe) should help you. I think that you should be able to simply use “extrudeVec” (a little below the method to which I linked) to get a world-space direction vector corresponding to the line made by the mouse. Once you have that, align your bullet to that vector.

(If you want to align your bullet’s “up” direction with that of your ship then you might have a little more work to do.)

I think I need help… I don’ t find any algorithm to do that :frowning:
I am poor with 3D maths I think…

What I do next, is yo use collision through ray tracing.
I create a fake nodepath hidden, set position to my ship, and looking at the point of collision (objet, ennemy, or skybox).

This is not perfect, byt it gives some result.

If you have other idea…

To do what? Extrude or align the bullet’s “up” direction? If the former–which appears to be what you’re talking about, given your description of our current solution, then I linked to the relevant method in a previous post in this thread, I believe. o_0

(In particular, I suspect that you’d likely be well-served by the “extrudeVec” method, a few entries below the method to which I linked, on the same page.)

Feed it your mouse-position and a vector object in which to store the result, and it should produce an appropriate vector for your bullet, I believe.

Don’t forget that this just gives you the direction in which to send the bullet: you’ll presumably still want to set the bullet’s starting position appropriately (such as at the muzzle of whatever gun your ship uses, or even just at the ship’s position).

Hello,

I thank you for your patience and answer.

In fact, I tried something like that :

x=base.mouseWatcherNode.getMouseX() #contains between -1 / 1
y=base.mouseWatcherNode.getMouseY() #contains between -1 / 1

pp=LVector3f(0,0,0)
lens = MatrixLens() # or OrthographicLens, or PerspectiveLens
lens.extrudeVec(Point2(x,y),pp)
print pp  

pp contains always value : LVector3f(0, 1, 0)
So I tried other way…

Many you have clues on why it returns always this value… I didn’t found much example on how to use ExtrudeVec :frowning:

Thank you

I think that the problem there is that you’re constructing a new lens (without initialising it to useful values or connecting it to the camera) and attempting to extrude from that, rather than extruding from the lens being used by the current camera.

If I’m not much mistaken, and you’re using the default camera (“base.camera”), then the lens used by that camera should be “base.camLens”.

I switch the lens, but result is the same :frowning:

ret=base.camLens.extrudeVec(Point2(x,y),pp)
print ret
print pp

result :
ret = True
pp = Vector3f(0,1,0)

Is there some initialization I missed?

That’s… very odd. Have you changed the camera or its lens at all? Have you perhaps assigned an orthographic lens to the camera? If not, then I’m honestly not sure why that’s not working.

My best guess at the moment is that the vector is, for some reason, in the coordinate space of the camera, and that either you’re using an orthographic lens (thus always producing a vector pointing along the local y-axis) or your mouse-coordinates are (for some reason) always (0, 0).

You might try using the non-vector version of “extrude”, which produces two points–one on each of the near- and far- planes. Your vector would then be something along the lines of “farPt - nearPt”–although you may well want ot normalise it as well.

Otherwise, perhaps someone with better knowledge of the method might have more insight. :confused:

(For what it’s worth, I’ve used the non-vector version of “extrude” before, and it seems to have worked for me, I believe.)

No change on Lens by my side.

I test extrude, and it returns some results varying depending on mouse position. Sounds good.

Sorry, but I’m poor in 3d math … and I don’t know how to transform this in something I can use to have a direction to my bullet.

Maybe with a look at to far point?

Yep it’s explained here… Lens::extrude_vec_impl that extrudeVec is really only useful for curved lenses. So what you want is far - near, or more specifically:

near = Point3()
far = Point3()
base.camLens.extrude(Point2(base.mouseWatcherNode.getMouseX(),base.mouseWatcherNode.getMouseY()),near,far)
pp = render.getRelativePoint(camera,far) - render.getRelativePoint(camera,near)

Something like that. That’s a line from the mouse cursor straight into the screen to the far plane. Use your muzzle position instead of near to get a path from your gun, obviously. However this might not be quite the effect you want (you’ll shoot past targets not directly on that path). You might want to first do a ray collision test along far-near, and if it collides with something then get hitpos-muzzle for your bullet path.

Understood for extrude_vec

For now, extrude is working fine, if the model is keeping the same plane (like for a human fps).

For now, my ship is in space, and can rotate in any sens, and can have head bottom if necessary. It seems that using this method, extrude will not keep in head this precision.

In certain case, my ship rotated, and when I shoot, the bullet is going total inverse direction of my mouse :frowning:

I used lookAt (far_point), instead calculating direction vector… I don’t know how to use this vector? How to determine quaternion for my bullet from this vector?

ps: sorry for my questions, but lot of thank you for your time wasted for me! :smiley:

I’m glad that you’ve made progress. :slight_smile:

The vector that you want should, I believe, simply be as follows:
“directionVector = farPt - nearPt”

When you use lookAt, do you set the bullet’s position to its starting position (whether gun muzzle, ship position or otherwise) before you call “lookAt”? If not, then the direction will indeed be incorrect as a result of being calculated relative to the position of the bullet at the time at which “lookAt” is called, I believe.

Otherwise, how are you updating the bullet’s position? Are you just moving it along its Y-axis?

In fact, perhaps it might help if you were to post the code in which you spawn and orient the bullet, and the code in which you move the bullet.

With regards to extrudeVec, that makes some sense but does suprise me a little–I wonder why it has that behaviour? The method name seems to imply that it’s the same as “extrude”, save that it produces a vector instead of two points.

In all fairness, I seem to recall that the documentation that I linked to (which is for version 1.8.1, I believe) does mention that the vector corresponds to the normal to the surface of the lens–the implication of which I missed previously.

Hi,

I put my sample on dropbox : dropbox.com/sh/ca4xxfgz087h … 27uN1WBJoa.

It contains code, models…

I used bullet to move models… so I jsut put linearVelocity to my bullet.

I named testmouse2.py actual test code, using extrude (just go to function fire)
and I named testmouse2withray.py the code using raytracing to determine differently the right direction.

Thank you for your help

The point is in camera space. To get it in world space, you can call render.getRelativePoint(camera, ret) I guess. I’m not sure how that’s with extrudeVec, otherwise try the extrude method …

thank you… It gives some more clue.

I transform my extrude far_point through getRelativePoint, and I got good coordinate.

I think far_point is really too far… so I divide it per 100.

Next, beacause far point is far away from object I clicked on.

So what I did, is to use collision ray to detect collision with space object.
if My mouse is over an object, I use the position of the object to look at, else I use extrude far point divide per 100 to look At.

It gives some good result.

def pickmouse(self,task)::
	mpos=base.mouseWatcherNode.getMouse()
	self.pickerRay.setFromLens(base.camNode, mpos.getX(), mpos.getY())

	self.picker.traverse(render)
	if self.pq.getNumEntries() > 0:
		self.pq.sortEntries() #this is so we get the closest object
		nodeInQueue=self.pq.getEntry(0).getIntoNodePath()
		
		self.pointToLookAt=None
		if str(nodeInQueue).find('earth')==-1:
			if str(nodeInQueue).find("Ast_")>0:
				index= str(nodeInQueue).find("Ast_")
				ast=str(nodeInQueue)[index:index+6]
				self.pointToLookAt=self.listOfAsteroid[ast].getPos()
def fire(self):
/***       code here creating bullet stuff  ***/

              if self.pointToLookAt!=None:
			bodyNP.lookAt(self.pointToLookAt)
		else:
			ret=base.camLens.extrude(Point2(x,y),t1,t2)
			t2=t2/100
			t2relative=render.getRelativePoint(camera,t2)   	
			bodyNP.lookAt(t2relative)