#1 2015-04-18 02:47:11

gaya
Member

Grenade launcher

I'm trying to create a grenade launcher, but i'm not able to make the projectile fall down after some time. It looks like a rocket. Any ideas on how to apply physics to it?

Offline

#2 2015-04-18 18:30:40

chasester1
Member

Re: Grenade launcher

@gaya
What i suggest, If you are planing on having many projectiles with a lil more compictated interface. Or want to have weapons that can do more. Simply:

struct projectile
    {
        vec dir, o, to, offset;
        float speed, distance;
        fpsent *owner;
        int gun;
        bool local;
        int offsetmillis;
        int id;
        entitylight light;
        vec gravity 
//NOTE: you could just have a global gravity defined as a const or a var but this makes for more cool effects
        projectile () {init}
        void init () { //write any initionalization functionality here}
        vec update(int time, float deltat){                            
            offsetmillis = max(offsetmillis-time, 0);
            float dspeed = speed/4.f*deltat
            //do a quick hit test on the world to see if i hit a cube or not
            float barrier = dspeed ? raycube(o, dir, dspeed, RAY_CLIPMATE, RAY_ALPHAPOLY) : 0; 
            //idk if this is the correct enums they may be different for tess
            
            vec v(dir);
            v.mul(min(dspeed, barrier);
            distance += v.magnitude(); 
//distance is a R+R functionality to determine how far a proj has gone; this is used to make projectiles that are shot closer do more damage (this encourages players to move closer together when fighting)
            v.add(o);
            v.add(gravity); // or GRAVITY or if gravity is just in the z; off.z += GRAVITY;
//so some vector math here, v is our new origin, so we start at the normalize direction scale it by our speed (or if there is a barrier we move up to, and not pass the barrier, then we figure out how far we have gone and add that to our total distance since shot, and then we add in our world space (the position we were last frame cycle). Then apply gravity to move the projectile downward or sideward etc.
        vec off(offset); // offset is where we are going to put the projectile effects.
        off.mul(offset/float(OFFSETMILLIS)); // i think tess has this set but its set to 500;
        off.add(gravity) // what ever way we did this above
        //if you see above we have actually 2 projectiles positions, i suggest just setting up a struct structure in your static guninfo struct to allow for a vector of these offsetpositions, simply just defining the projectile attr and the position of offset, then just apply them here with the data given.
        loopv(offsetpos){
            offsetpositon &o = offsetpos[i];
            vec pos (v);
            pos.add(offset);
            pos.add(o.offset/float(OFFSETMILLIS));
            //then add the projectiles here, using your attr data from o; you will have to determine what this is but heres an example
           partpreset(projpartpresets[WEAP(p.gun,projparts)[2]], pos, p.owner, &pos2);
           retrun v;
}
        hit(){
// your hit detection should go here, but the way it's written you would have to rewrite a lot of code;
}
        render(){
         //simply render your projectile if it has something to render
}
        destroy(){
        // you should move all the fuction explode, explode radius etc to something more simplified but im not gonna write that much code;
}
};



IN GAME.H
enum { // all your different preset particals by type so that weapons can share particles } // the enum should link in the projpartpresets
 static const structparticlepreset { short type, part, num, fade, radius, gravity; int color; float size; } projpartpresets[PP_NUM] =
{
	// type				part				num	fade	radius	gvt	color		size
        
 }



//then above the struct projectiles put to defile all your types:
void partpreset(const projpartpreset &pp, const vec &pos, fpsent *owner = NULL, const vec *to = NULL)
	{
		switch (pp.type)
		{
		case PT_REGULAR_SPLASH:
			regular_particle_splash(pp.part, pp.num, pp.fade, pos, pp.color, pp.size, pp.radius, pp.gravity);
			break;
		case PT_REGULAR_FLAME:
			regular_particle_flame(pp.part, pos, pp.radius, pp.num, pp.color, 3, pp.size, 200.0f, pp.fade, pp.gravity);
			break;
		case PT_SPLASH:
            particle_splash(pp.part, pp.num, pp.fade, pos, pp.color, pp.size, pp.radius, pp.gravity, 1.0f, false);
			break;
		case PT_TRAIL:
            particle_trail(pp.part, pp.fade, pos, *to, pp.color, pp.size, pp.gravity, false, pp.radius);
			break;
		case PT_FLARE:
			particle_flare(pos, *to, pp.fade, pp.part, pp.color, pp.size, owner);
			break;
		case PT_FIREBALL:
			particle_fireball(pos, pp.radius, pp.part, pp.fade, pp.color, pp.size);
		}
}
//of course if you are using the non-conventional particles you will have to change up how you do this;

//and then lastly your new updateprojectiles() should look like

void updateprojectiles(int time){
float deltat = time / 100.f;
        loopv(projs)
        {
              projectile &p = projs[i];
              vec v (p.update);
              //and hit detection;
              //yes this code is defined twice because we need it for hit detection
              float dspeed = p.speed/4.f * deltat;
              float barrier = dspeed? raycube(p.o, p.dir, dspeed, RAY_CLIPMAT|RAY_ALPHAPOLY): 0;
//of course remove all this code should be inside of projectile.hit() but a lot of stuff would need to be shifted

              bool exploded = false;
	      hits.setsize(0);
	      if (barrier < dspeed || p.distance > WEAP(p.gun,range))
	      {
	             projsplash(p, v, NULL, qdam);
		     exploded = true;
	       }//world detection
	       bool directhit = false;
	       bool headshot = false;
	       
               if(p.local) // this just asks if we are the one that shot it (or if one of our ai buddies did)
               //NOTE: AI is passed to players to help pull the weight off the server;
               //NOTE: local is also true in modes that dont have any server aka sp mode
	       {
		dynent *o = intersectclosest(p.o, v, p.owner, barrier);
		if (o && projdamage(o, p, v, qdam, headshot))
		{
			exploded = true;
			directhit = true;
			}
		} //player detection 


                if(exploded)
		{
			if(p.local)
			addmsg(N_EXPLODE, "rci5v", p.owner, lastmillis-maptime, p.gun, p.id-maptime, WEAP_IS_EXPLOSIVE(p.gun)?      (int)directhit: (int)headshot, hits.length(), hits.length()*sizeof(hitmsg)/sizeof(int), hits.getbuf());
			projs.remove(i--);
			continue;
			}

		else p.o = v;
        }
}              

Why put everything in your projectile struct instead of just doing it in a function like it has been done. Simple duck typing, basically all you have to do is tell projectile.update() and its done. You don't care what it does. This becomes powerful when you want to say, do a projectile basided system like the rocket launcher in the half life series. (The projectile moves to the players crosshair, in relation to the world).

This was done in R+R or you can google it if your curious.

 
struct homeproj : projectile {
         homeproj { projectile::init(); //write any initionalization functionality here }
         vec update (int time, float deltat) {
         vecfromyawpitch(owner->yaw, owner->pitch, 1, 0, to);
         projectile::upadate(time, deltat);
         }
};

so now we simply are using the same code to call different fuctionality, completely changing the projectile without having to use something like

switch (guntype){
     case(Projectile):
//run code
     case(Home):
run some of the same code as above but some different
     case(bullet):
run some of the same code with different modifiers
     case(bouncer):
run very lil of the same code
     case(flame):
run something completely different but use the same hit detection
}

Trust me it gets really confusing after a while, and really limits your abilities. Plus if you want to add in variable for just a particle type of proj you dont have to add them too all of them (wasting memory).

Any way if you have any more question do ask.
chasester


Ps if you want the simple answer its

In weapons.cpp:

void updateprojectiles (int time){
...
v(dir);
...
v.add(vec(p.gravity).mul(deltat)); // or GRAVITY or guns[p.gun].gravity or v.z-= GRAVTIY*deltat;
v.add(o);
...
}

Last edited by chasester1 (2015-04-18 19:42:44)

Offline

#3 2015-04-18 19:37:26

chasester1
Member

Re: Grenade launcher

Hypernova^ wrote:

...

Ok I'm gone. Sorry for spreading spam.

No i appreciate the feedback, but its not helpful to any one just throwing words out into the air. If you wanna help some one just go and google it and do a lil research, or talk about thing you know. Just putting ideas into peoples heads, isnt helpful to any one because it will just get them frustrated.

Your mostly right tho but elasticity is the wrong word. Elasticity is the the ability of something to change and adapt; adaptability.

chasester

Last edited by chasester1 (2015-04-18 19:38:43)

Offline

#4 2015-04-18 23:55:49

Hypernova^
Member

Re: Grenade launcher

Ok I see what you mean. I'll try to give more accurate/informative answers in the future. Thx for pointing this out btw.

Offline

#5 2015-04-22 22:15:59

gaya
Member

Re: Grenade launcher

Thanks a lot for the attention and the detailed help, guys. :D

Offline

Board footer