Game Development Community

Any ideas for making a grappling hook?

by Alaric Karczag · in Game Design and Creative Issues · 07/12/2004 (6:47 pm) · 36 replies

I'm trying to find a way to make a harpoon. I'd like to be able to shoot an item and then drag it behind me.
ie:
fire = shoots out harpoon + rope, it hits object.
hold down button = to drag on item without shortening the rope,
release button = recoils the harpoon or drags item towards player

I've looked through the forums for any code for this...

Help would be great!
Thanks all for your help
Page «Previous 1 2
#1
08/29/2004 (6:47 am)
I'm not ready to look in to a grapple yet, a grapple hook is my favorite feature in fps.

I have a src to a real grapple for quake 2 written in "c". This third party swinging grapple is loaded with all the goodies a grapple needs , ( it wont pull stuff to it though, although i like the "idea").

heres a link, maybe someone will get it done before i could.

cleverace.home.comcast.net/~cleverace/quake/hook.HTM
#2
08/29/2004 (6:50 am)
Heh that is an old page and hasnt been updated ever, hooked14 works perfect also (in q2)
#3
08/30/2004 (6:55 pm)
Nice, and thank you for the link!
#4
08/31/2004 (4:07 am)
Your welcome , please share it, if you port it over to torque. This is on my list of todo's.
#5
09/01/2004 (4:32 am)
I made a grappling hook that lets you swing from static objects fairly realistically, but it doesnt let you pull other objects or attach yourself to moving things like vehicles or other players. I'll post it later.
#6
09/01/2004 (4:44 am)
Eric cool, i would be very interested in seeing it. No fps should be with out it. :}
#7
09/02/2004 (8:49 am)
DEFINITIONS:

in player.h,
add these lines to the public section of the player class definition
//EGH  //grapling hook stuff
Point3F	hookPos;
F32 hookLen;
void setHookPos(const VectorF& newHookPos) { hookPos = newHookPos; };
void setHookLen(const F32& newHookLen) { hookLen = newHookLen; };

void Player::renderObject(SceneState* state, SceneRenderImage* image);
//<-EGH

PHYSICS:

in player.cc,
in the function player::updateMove, find the code that looks like this
// Add in force from physical zones...
   acc += (mAppliedForce / mMass) * TickSec;

   // Adjust velocity with all the move & gravity acceleration
   // TG: I forgot why doesn't the TickSec multiply happen here...
   mVelocity += acc;

and add this underneath it, this code is what applies the actual physics of the hook

//EGH: grapling hook forces
	VectorF t;
	t = getPosition() - hookPos;
	float dist;
	if( hookLen != -1 )
	{
		//if beyond hook length, apply force proportional to distance
		dist = ((t.x * t.x) + (t.y * t.y) + (t.z * t.z));
		
		if(dist > (hookLen*hookLen) )
		{
			//Con::warnf("Beyond HookLen");
			mVelocity += (1000 * moveVec/ mMass) * TickSec;
			//do something!
			t.normalize();
			F32 vMag;
			vMag = mSqrt((mVelocity.x * mVelocity.x) + (mVelocity.y * mVelocity.y) + (mVelocity.z * mVelocity.z));
			if(vMag != 0)
			{
				if(mAcos(mDot(t, mVelocity)/vMag) < 1.57)
				{
					mVelocity -= (mDot(t, mVelocity)/mDot(t, t)) * t ;
					mVelocity.normalize();
					mVelocity *= vMag;
				}
			}			
		}
		else
		{
			//Con::warnf("Inside HookLen");
		}
	}
	//<-EGH

RENDERING:

add this function to the end of player.cc
this function lets us draw a line for the grappling hook rope

//EGH
void Player::renderObject(SceneState* state, SceneRenderImage* image)
{
	Parent::renderObject(state, image);

	if(hookLen != -1 )
	{
			//draw the rope
		   MatrixF xf(true);
		   getMountTransform(0,&xf);

		   Point3F pos;
		   xf.getColumn(3,&pos);

			VectorF t;
			t = getPosition() - hookPos;

			float dist;

			dist = mSqrt((t.x * t.x) + (t.y * t.y) + (t.z * t.z));

			float zoffset;
			zoffset = sqrt(hookLen*hookLen - dist*dist);

			zoffset *= 1/10;
			t	*= 1/10;
		
		glColor4fv(ColorF(1.0, 1.0, 1.0, 0.5));

		glBegin(GL_LINE_LOOP);
		
		MatrixF mat;
		getRenderImageTransform(0, &mat);
		pos = mat.getPosition();
		// Draw Vertex.
		/*for(int i = 0; i < 10; i++)
		{
			glVertex3f(	hookPos.x + (t.x * i),
					hookPos.y + (t.y * i),
					hookPos.z + (t.z * i) + (i%2));
		}*/
		glVertex3f(	(hookPos.x + (t.x * 5)),
					(hookPos.y + (t.y * 5)),
					(hookPos.z + (t.z * 5)) );
		glVertex3f(	pos.x,
					pos.y,
					pos.z);
		glEnd();
	}
}
//<-EGH


NETWORK:

This part needs fixing as it's really inefficient network-wise. it gets it working though.
An ideal solution would be to predict this info on the client using a special property of a projectile

in Player::packUpdate, add these lines to the very beginning
//EGH
stream->write(hookPos.x);	//
stream->write(hookPos.y);	//
stream->write(hookPos.z);	//
stream->write(hookLen);		//
//<-EGH

and add these to the beginning of Player::unpackUpdate
//EGH
stream->read(&hookPos.x);
stream->read(&hookPos.y);
stream->read(&hookPos.z);	
stream->read(&hookLen);	      
//<-EGH
#8
09/02/2004 (8:51 am)
SCRIPT CONNECTIONS:

I made this before consolemethod was around so it uses the old style.

Put this above Player::consoleInit()
//EGH
static bool cSetHookPos(SimObject *ptr, S32, const char **argv)
{
   Player* obj = static_cast<Player*>(ptr);
   VectorF vel(0,0,0);
   dSscanf(argv[2],"%f %f %f",&vel.x,&vel.y,&vel.z);
   obj->setHookPos(vel);
   //obj->setControlDirty();
   return true;
}

static bool cSetHookLen(SimObject *ptr, S32, const char **argv)
{
   Player* obj = static_cast<Player*>(ptr);
   F32 Len;
   dSscanf(argv[2],"%f",&Len);
   obj->setHookLen(Len);
   //obj->setControlDirty();
   return true;
}
//<-EGH

add these to Player::consoleInit()
//EGH
Con::addCommand("Player", "setHookPos", cSetHookPos, "obj.setHookPos(Vector)", 3, 3);
Con::addCommand("Player", "setHookLen", cSetHookLen, "obj.setHookLen(Float)", 3, 3);
//<-EGH
#9
09/02/2004 (8:55 am)
SCRIPT:

Argh this is weak but i gotta go to work.
To get this working, all you need to do now is make a projectile called hookprojectile and add this function

function hookProjectile::onCollision(%this,%obj,%col,%fade,%pos,%normal)
{
	//messageall(type, 'projectile collision col = %1', %col);
   // Apply damage to the object all shape base objects

	if (%col.getType() & ($TypeMasks::StaticObjectType | $TypeMasks::InteriorObjectType | $TypeMasks::TerrainObjectType))
	{
		%obj.client.player.setHookPos(%pos);
		%len = vectorSub(%obj.client.player.getPosition(), %pos);
		echo("hook length = ", vectorLen(%len));

		%obj.client.player.setHookLen(vectorLen(%len));
	}
	
}

then make a weapon image called hookimage and add this script function
function hookImage::onFire(%this, %obj, %slot)
{
	%obj.client.player.setHookLen(-1);

   %projectile = %this.projectile;

   // Decrement inventory ammo. The image's ammo state is update
   // automatically by the ammo inventory hooks.
   //%obj.decInventory(%this.ammo,1);

   // Determin initial projectile velocity based on the 
   // gun's muzzle point and the object's current velocity
   %muzzleVector = %obj.getMuzzleVector(%slot);
   %objectVelocity = %obj.getVelocity();
   %muzzleVelocity = VectorAdd(
      VectorScale(%muzzleVector, %projectile.muzzleVelocity),
      VectorScale(%objectVelocity, %projectile.velInheritFactor));

   // Create the projectile object
   %p = new (%this.projectileType)() {
      dataBlock        = %projectile;
      initialVelocity  = %muzzleVelocity;
      initialPosition  = %obj.getMuzzlePoint(%slot);
      sourceObject     = %obj;
      sourceSlot       = %slot;
      client           = %obj.client;
   };
   MissionCleanup.add(%p);
   return %p;
}
#10
09/02/2004 (8:56 am)
I didnt test it but i think it works.
#11
09/02/2004 (7:00 pm)
Awesome , only one way to find out, i should get time this weekend (3day). Man that kinda gets my blood pumpin! Thanks.
#12
09/03/2004 (9:39 pm)
Holy crud thank you Eric! I'm new to programming and this is great!
I'm working on my bachelors in game design, and have started building characters and building for the game.

I don't know alot about the torque programming tho.

Everyone should own the All In One book, it's a great resource for the starters out there!

Eric you will be put into the credits!
#13
09/20/2004 (5:23 pm)
I just tried it and I dont know if its just me but when I start the game, I see a white string from my hand that goes to the ground and I cant move. Whats going on?
#14
09/21/2004 (7:29 am)
Thats the grappling hook. Firing the hook into the air should clear it out and allow you to move
#15
05/09/2005 (11:21 am)
Anyone attempt to move this code into a new projectile class?
#16
10/20/2006 (11:48 am)
Question: I tried to put in a simple "gather" action that just decrements hooklen repeatedly while you hold down the trigger, and the hookLen variable is definitely diminishing, but the player doesn't move (and the line doesn't get shorter) until I cause update move to be called again by jumping or running....
how do I make this update from the script?

function HookImage::onGather(%this, %obj, %slot)
{
	echo("onGather: pre-hook length = ", %obj.client.player.getHookLen());

	%tt = %obj.client.player.getHookLen();

	if (%tt > 0.1)
	{
		%tt = %tt - 0.1;
	}
	else
	{
		%tt = 0;
	}
	%obj.client.player.setHookLen(%tt);
	echo("onGather: post-hook length = ", %obj.client.player.getHookLen());
}
#17
10/24/2006 (4:23 pm)
Lol

ok some wacky things when I implemented this:
first I get a straight white line comming out of the bottom of the player, and all the AIs
my 'w' now works as a left side step for no apparant reason at all lol

I mounted the image to the player (using just the crossbow right nowas the 'image') and nothing happens when I shoot, im sure I have overlooked something just not sure as to what.

Any ideas?
#18
02/04/2007 (12:29 am)
Anyone have this working with 1.5? Getting a bunch of errors during the compile.

c:\torque\sdk\engine\game\player.cc(1621) : error C2065: 'hookPos' : undeclared identifier
c:\torque\sdk\engine\game\player.cc(1623) : error C2065: 'hookLen' : undeclared identifier
c:\torque\sdk\engine\game\player.cc(3511) : error C2228: left of '.x' must have class/struct/union
        type is ''unknown-type''
c:\torque\sdk\engine\game\player.cc(3512) : error C2228: left of '.y' must have class/struct/union
        type is ''unknown-type''
c:\torque\sdk\engine\game\player.cc(3513) : error C2228: left of '.z' must have class/struct/union
        type is ''unknown-type''
c:\torque\sdk\engine\game\player.cc(3587) : error C2228: left of '.x' must have class/struct/union
        type is ''unknown-type''
c:\torque\sdk\engine\game\player.cc(3588) : error C2228: left of '.y' must have class/struct/union
        type is ''unknown-type''
c:\torque\sdk\engine\game\player.cc(3589) : error C2228: left of '.z' must have class/struct/union
        type is ''unknown-type''
c:\torque\sdk\engine\game\player.cc(3825) : error C2039: 'setHookPos' : is not a member of 'Player'
        c:\torque\sdk\engine\game\player.h(236) : see declaration of 'Player'
c:\torque\sdk\engine\game\player.cc(3835) : error C2039: 'setHookLen' : is not a member of 'Player'
        c:\torque\sdk\engine\game\player.h(236) : see declaration of 'Player'
c:\torque\sdk\engine\game\player.cc(4381) : error C2509: 'renderObject' : member function not declared in 'Player'
        c:\torque\sdk\engine\game\player.h(236) : see declaration of 'Player'
Creating browse information file...
Microsoft Browse Information Maintenance Utility Version 8.00.50727
Copyright (C) Microsoft Corporation. All rights reserved.
Build log was saved at "file://c:\Torque\SDK\engine\out.VC8.DEBUG\BuildLog.htm"
Torque Demo - 11 error(s), 0 warning(s)
========== Build: 0 succeeded, 1 failed, 6 up-to-date, 0 skipped ==========
#19
03/12/2007 (12:38 pm)
This is basicly what ive been searching for i havent dowloaded and tested yet but i want to see if it works with 1.5 ...awsome
#20
04/04/2007 (12:34 pm)
Christian, you forgot the header definitions.

player.h -> somewhere in a public section
//EGH  //grapling hook stuff
Point3F	hookPos;
F32 hookLen;
void setHookPos(const VectorF& newHookPos) { hookPos = newHookPos; };
void setHookLen(const F32& newHookLen) { hookLen = newHookLen; };

void Player::renderObject(SceneState* state, SceneRenderImage* image);
//<-EGH

FYI, it compiles with 1.5, haven't tested it in a game yet.
Initializing the hook members in the Player::Player() should also fix the "stuck when I start the game" and "white line that points down" problems I read about in this thread. But again, not tested.
Add these to the Player constructor:
hookLen = -1;
hookPos.set(0, 0, 0);

I'm sort of hoping that I can modify this easilly so that I can drag objects along with it.
Page «Previous 1 2