Game Development Community

Aim and fire with mouse

by Richard Pettyjohn · in Torque Game Builder · 05/29/2006 (12:37 pm) · 27 replies

I'm tring to use an aiming system where you click the mouse to fire and the character fires toward the mouse. I thought that moveMap.bind(mouse0, "button0 ", "$pShip.isFiring();", "$pShip.notFiring();"); would have the ship fire when I click the mouse but it does't seem to. As for the second part I don't have a clue how to do it.

Help would be appretiated.

Edit: typos
Page «Previous 1 2
#1
05/29/2006 (12:58 pm)
I think it's been mentioned in another thread that mouse binding doesn't work in the current beta. I'm guessing this is a bug, but until it's sorted, you'll need to use callbacks instead.
#2
05/29/2006 (1:39 pm)
Due to the issues Philip mentioned, I'm using the following instead of binding. It'll get you there...

function sceneWindow2D::onMouseMove(%this, %modifier, %worldPosition, %mouseClicks) 
{
     %xPos = getWord(%worldPosition, 0);
     %yPos = getWord(%worldPosition, 1);
     // insert code to point at (%xPos, %yPos)
}

function sceneWindow2D::onMouseDown()
{
     // insert code to start shooting...
}


function sceneWindow2D::onMouseUp()
{
     // insert code to stop shooting...
}

If you don't have a machine gun and you want to click for each shot, then ignore the onMouseUp() stuff...
#3
05/29/2006 (1:55 pm)
Kenneth Finney's "Advanced 3D Game Programming All in One" (for the 3D TGE engine) has a great chapter on Vectors and Matrices. If you combine that essential math for game programmers with the functions listed in the reference under "Vector Manipulation", then you'll be able to point the projectile (or the player or whatever) at the mouse. Some other game programmer's math resources are at www.garagegames.com/index.php?sec=mg&mod=resource&page=category&qid=28
#4
05/29/2006 (2:46 pm)
Here's some code that will shoot garage game logos from your ship... It has the following assumptions:
- you defined $pShip (when I tested the code I added a ship in the level editor, then in the Scripting section of its properties I put "myShip" under "Name". Then, in the startGame() function of game.cs I added the line "$pShip = myShip;" after the loadLevel call...)
- you want to shoot towards the mouse, but not turn the ship towards the mouse
- you have the "ggLogo.png" graphic in /data/images and it's defined as "ggLogoImageMap" (This is the default case in the T2D directory when you start with a fresh copy of TGE beta 4)

function sceneWindow2D::onMouseDown(){
   // start shooting in 100 milliseconds
   $nextScheduledShot = schedule(100, 0, "shoot");	
}

function sceneWindow2D::onMouseUp(){
   // stop shooting
   cancel($nextScheduledShot);	
}

function shoot() {
   // determine shot angle
   %shipPosition = $pShip.getPosition();
   %mousePosition = sceneWindow2D.getMousePosition();
   %shotAngle = t2dAngleBetween(%shipPosition, %mousePosition);

   // create the projectile (bullet)
   %bullet = new t2dStaticSprite() { scenegraph = sceneWindow2D.getSceneGraph(); };
   %bullet.setPosition( %shipPosition ); // bullet starts at the ship
   %bullet.setImageMap( "ggLogoImageMap" );
   %bullet.setSize = "8 8";
   %bullet.setLinearVelocityPolar( %shotAngle, 100 );	// shoot at speed 100		
	
   // schedule the next shot in 500 milliseconds (mouse button is still down, so keep shooting)
   $nextScheduledShot = schedule(500, 0, "shoot");	
}
#5
05/29/2006 (4:43 pm)
Thank you! It works great!
#6
05/29/2006 (7:32 pm)
Here's a version with collision detection enabled:
function startGame(%level)
{
   // Set The GUI.
   Canvas.setContent(mainScreenGui);
   Canvas.setCursor(DefaultCursor);
   
   moveMap.push();
   sceneWindow2D.loadLevel(%level);
   $pShip = myShip;   // assumes "myShip" is the name of a static sprite added in the level editor
   $pShip.setGraphGroup(1);
}
function endGame()
{
   sceneWindow2D.endLevel();
   moveMap.pop();
}
function sceneWindow2D::onMouseDown(){
	// start shooting in 100 milliseconds
	$nextScheduledShot = schedule(100, 0, "shoot");	
}
function sceneWindow2D::onMouseUp(){
	// stop shooting
	cancel($nextScheduledShot);	
}
function shoot() {
	// determine shot angle
	%shipPosition = $pShip.getPosition();
	%mousePosition = sceneWindow2D.getMousePosition();
	%shotAngle = t2dAngleBetween(%shipPosition, %mousePosition);
	
	// create the projectile (bullet)
	%bullet = new t2dStaticSprite() { 
			scenegraph = sceneWindow2D.getSceneGraph(); 
			class = "bulletClass"; 
		};
	%bullet.setPosition( %shipPosition ); // bullet starts at the ship
	%bullet.setImageMap( "ggLogoImageMap" );
	%bullet.setSize = "8 8";
	%bullet.setLinearVelocityPolar( %shotAngle, 100 ); // shoot at speed 100 

	// collision settings
	%bullet.setCollisionActive(true, true);
	%bullet.setCollisionResponse("KILL");
	%bullet.setCollisionDetection("FULL");
	%bullet.setCollisionCallback(true);

	// kill the bulet after it leaves the screen (
	%bullet.setWorldLimit( "KILL", sceneWindow2D.getCurrentCameraArea(), true);
	
	// schedule the next shot in 500 milliseconds (mouse button is still down, so keep shooting)
	$nextScheduledShot = schedule(500, 0, "shoot"); 
}
function bulletClass::onCollision(%srcObj, %dstObj, %srcRef, %dstRef, %time, %normal, %contactCount, %contacts)
{
	switch(%dstObj.getGraphGroup()) {
		case 0:	// destroyable object
			%dstObj.safeDelete();
		case 1:	// ship 
			// do nothing (to allow the bullet to launch from the ship safely)
		case 2: // bullet 
			// do nothing
	}
}

Approach: Use graph groups to determine what types of objects are involved in collisions. Group 0 = destroyable objects; Group 1 = friendly ships (not destroyable by bullets); Group 2 = bullets

So... the bad guys would need to be graph group 0 (which is the default when you add an item in the level editor anyway) and have collsion detection enabled for this to work.

The setWorldLimit causes the bullets to go away when the leave the screen, so they don't take up processing time as they drift off into eternity after they leave the visible screen area.
#7
05/29/2006 (8:32 pm)
Thanks, I don't have time right now but I'll try it as soon as I can.
#8
06/03/2006 (10:01 am)
Sorry it took me so long to post my iternet was down for a while (acorrding to Quest my modem died, but today I found out an easier fix, jiggling the cable). Anyway since I still had access to the earlier code (thanks agian Jason!) I combined it with playerMissile to get collisions. The last problem I have though is having the player face the mouse. Could somebody help me out?

EDIT:so many typos!
#9
06/03/2006 (11:34 am)
To rotate the player only when the mouse button is pressed, add "$pShip.setRotation(%shotAngle);" just before where the bullet is created above...

To rotate the player continuously as the mouse is moved (not just when the mouse button is pressed -- but whenever the mouse is moved), use something similar to this:

function sceneWindow2D::onMouseMove(%this, %modifier, %worldPosition, %mouseClicks) 
{
     %xPos = getWord(%worldPosition, 0);
     %yPos = getWord(%worldPosition, 1);
     // determine shot angle
     %shipPosition = $pShip.getPosition();
     %mousePosition = sceneWindow2D.getMousePosition();
     %shotAngle = t2dAngleBetween(%shipPosition, %mousePosition);
     // rotate ship towards mouse position
     $pShip.setRotation(%shotAngle);
}
#10
06/03/2006 (12:26 pm)
The player now rotates when the mouse is moved but since it doesn't start facing the mouse it never acually faces the mouse. So is there a way I can have the player face where ever the mouse is when the level starts?
#11
06/03/2006 (1:08 pm)
The %xPos and %ypos lines in the code above are actually not necessary... but anyway...

Add a call to "updateShipRotation();" to your startGame function to start out looking at the mouse... then change the following:

function updateShipRotation() {
        // determine angle
     %shipPosition = $pShip.getPosition();
     %mousePosition = sceneWindow2D.getMousePosition();
     %shotAngle = t2dAngleBetween(%shipPosition, %mousePosition);
     // rotate ship towards mouse position
     $pShip.setRotation(%shotAngle);
}

function sceneWindow2D::onMouseMove(%this, %modifier, %worldPosition, %mouseClicks) {
   updateShipRotation();
}

The code isn't optimized (redundant call to getMousePosition()), but it works...
#12
06/03/2006 (1:11 pm)
Getting really familiar with TGBReference.pdf and going thought the TDN tutorials will help you figure out that kind of stuff on your own. I enjoy charity teaching, though -- it's a good way to pay back the torque community and GG for all the help they've given me...
#13
06/03/2006 (2:36 pm)
Thanks! It works fine now, though I also added some code to keep the player rotating towards the mouse when the mouse is still and the player is moving.

Thanks agian for the help!
#14
06/05/2006 (7:31 am)
Jason, I have been play around with your code, nice code but some reason I cannot get bullet to fire. I know I probably missing something simple. There any thing I need to do special.
#15
06/05/2006 (1:55 pm)
@Michael - Is the bullet showing up at all? Just not moving, or not even there?
#17
06/05/2006 (6:46 pm)
The bullet is not show up. Try different ways, I sure it probably something simple.
#18
06/20/2006 (1:24 pm)
I'm trying to get this to work with the new release of tgb (the non early adopter one) but the code no longer seems to work. Now the when I move the mouse the ship radomly rotates. What should I add to the code?
#19
06/20/2006 (9:10 pm)
Hmmm... My enemys seem to be doing it to (I'm using: http://www.garagegames.com/mg/forums/result.thread.php?qt=45555) they all seem to think pShip is in a different place and and when I move they don't seem to rotate in any orderly way. Could someone please held me? I'm not sure what the problem is. Is some other object screwing up the rotation caculations? Is there new requirments for rotations in this release?
#20
06/20/2006 (11:07 pm)
It looks like they fixed the t2dAngleBetween so it computes the angle between two vectors, as the documentation implies. This is actually a good thing, since you can get the old behavior by using mAtan. The current functionality was slightly more involved to calculate, so this is a nice helper function now. To get this resource working again, this is what I think needs to happen (although I'm too tired to test it right now)

Change this line:
%shotAngle = t2dAngleBetween(%shipPosition, %mousePosition);

To these lines:
%difference = t2dVectorSub(%mousePosition, %shipPosition);
%dx = getWord(%difference, 0); 
%dy = getWord(%difference, 1);
%shotAngle = mRadToDeg(mAtan(%dy, %dx));

Let me know how that works.
Page «Previous 1 2