Shooting question:automatic weapon

You are an experienced programmer and have a problem with the engine, shaders, or advanced effects? Here you'll get answers.
No questions about C++ programming or topics which are answered in the tutorials!
Post Reply
MessiaH
Posts: 55
Joined: Tue Jul 06, 2004 6:37 pm
Location: RUSSIA

Shooting question:automatic weapon

Post by MessiaH »

:cry: :cry: :cry: :cry: :cry: :cry: :cry: :cry: :cry: :cry: :cry: :cry: :cry:

I have no idea about its solution!
If mouse button is pressed event receiver doesnt work!
Try to create automatic weapon(which shoots,while you are pressing button)
and you'll understand what i am about!!!
I ve tryed everything-DOESNT WORK!
//Its OK with non-automatic weapon like pistol

:cry: :cry: :cry: :cry: :cry: :cry: :cry: :cry: :cry: :cry: :cry: :cry: :cry:
zola -

Post by zola - »

Irrlicht essentially sends one event and doesn't repeat it while the same state is beeing kept. (well, keyboard events get repeated after some time... anyway)

You 'll have to monitor/cache the state of the mousebuttons take a look here and do something similar for the mousebutton states

http://irrlicht.sourceforge.net/phpBB2/ ... .php?t=808

cheers
Electron
Posts: 874
Joined: Sun Mar 14, 2004 12:05 am
Location: Massachusetts USA

Post by Electron »

my solution to that was to make my keypress handling code change a trigger state variable as well as fire the weapon. The fire function would set a timed callback to itself (using a timed event system I designed, which uses templates to be able to call back non-static member functions). Each time before actually firing, the fire function checks to see what the trigger state is. Since I want the repeat rate to be fixed, yet different for different guns I would not want to rely on simply how often the event loop was gone thru to set the repeat rate, as I believe the bool keys[] solution would be
You do a lot of programming? Really? I try to get some in, but the debugging keeps me pretty busy.

Crucible of Stars
zola
Posts: 52
Joined: Thu Jul 15, 2004 2:31 pm
Location: switzerland
Contact:

Post by zola »

Hi Electron

You're right. The 'bool keys[]' array just holds the state and does nothing with respect to frequence of method calls or what ever you like to do with the information Your gathering in the array.

Because of the way the question was asked I think it's not a good idea to come up with a fully-fledged system but to introduce some basic aspects first to keep it simple :wink: (no offence MessiaH)

Could You elaborate a bit on how Your system works? Seems to be very interesting. Personally I use the signal/slot framework from boost to handle callbacks. For timed calling of methods I just have a vector of trigger structures that get checked every frame if it's time to fire the trigger.

Regards
Tom
Electron
Posts: 874
Joined: Sun Mar 14, 2004 12:05 am
Location: Massachusetts USA

Post by Electron »

hmm. I'm not sure how much of my system you want to see. Could get lengthy here, but I'll try and post most of it. For the timing system, I rely on these classes whcih I have in a file I named eventtimer.h

Code: Select all

#ifndef eventtimer_h
#define eventtimer_h

class CEventTimerBase
{
  public:
  virtual bool isTimeout(long time)=0;
};

//I'm testing speed optimizations with template programming here
template< typename returntype,typename T, returntype(T::*func)()>
class CEventTimer : public CEventTimerBase
{
  public:
  CEventTimer(long _timeout, T *_instance)
  {
     instance=_instance;
     timeout=_timeout;
  }  
  virtual bool isTimeout(long time)
  {
     
     if(time >= timeout)
     {
       (*instance.*func)();
       return true;  
     }
     return false;  
  }
  protected:
  T *instance; 
  long timeout;   
};

template< typename returntype,typename T,typename T1, returntype(T::*func)(T1)>
class CEventTimer1Param : public CEventTimerBase
{
  public:
  CEventTimer1Param(long _timeout,T *_instance,T1 _param1)
  {
     instance=_instance;
     param1=_param1;
     timeout=_timeout;
  }  
  virtual bool isTimeout(long time)
  {
     if(time >= timeout)
     {
       (*instance.*func)(param1);
       return true;  
     }
     return false;  
  }
  protected:
  T *instance;
  T1 param1;  
  long timeout;  
};

template<typename returntype,typename T,typename T1,typename T2, returntype(T::*func)(T1,T2)>
class CEventTimer2Param : public CEventTimerBase
{
  public:
  CEventTimer2Param(long _timeout,T *_instance,T1 _param1,T2 _param2)
  {
     instance=_instance;
     param1=_param1;
     param2=_param2;
     timeout=_timeout;
  }  
  virtual bool isTimeout(long time)
  {

     if(time >= timeout)
     {
       (*instance.*func)(param1,param2);
       return true;  
     }
     return false;  
  }
  protected:
  T *instance;
  T1 param1;
  T2 param2;
  long timeout;    
};

#endif
My main game class keeps a list CEventTimerBase and updates them all with isTimeout every frame. Each one is checked every frame, but it's an inexpensive test. My main game class has the list as a member like this

Code: Select all

static core::list<CEventTimerBase*> timedEvents;
in my main game loop I do this

Code: Select all

   //now check event timers
   core::list<CEventTimerBase*>::Iterator iterate=timedEvents.begin();
   time=getGameTime();
   while(iterate!= timedEvents.end())
   {
      if((*iterate)->isTimeout(time)) 
      {
         delete *iterate;
         iterate=timedEvents.erase(iterate); 
      }  
      else
      {
         iterate++;  
      }    
   }
use any other timing function in place of my getGameTime(). Internally that just calls the irrlicht timer anyway.

So that's my timing system. Now how to use it specifically with weapons. . .

each weapon maintains a triggerState enumeration variable. I was going to show you my enumeration, but I just realized a sligt problem with it that I need to tweak. The general method still works, however.
When the player presses the fire button or lets it up the triggerState is set differently. In my fire function I have something like this

Code: Select all

if(triggerState & TRIGGER_PRESSED)
   {
      //do other firing stuff
            //here we add the code to make this gun repeat
      CEventTimer<void, CWeaponProjectile, &CWeaponProjectile::fire> *event=new CEventTimer<void, CWeaponProjectile, &CWeaponProjectile::fire>(CGame::getGameTime() + rate,this);
      CGame::addTimedEvent(event); 
}
//test for any other important trigger states we may have
note that the fire function will always set a timed callback to itself, but if the TRIGGER_PRESSED bit of triggerState is no longer set the loop will end. In a way it's similar toa recursive function, except that the recursion is delayed


CGame::addTimedEvent is a function I forgot to show you. It simply adds a an event to our list to be processed

Code: Select all

static void addTimedEvent(CEventTimerBase* event){timedEvents.push_back(event);}
I know that was very long, so it may not be that helpful, but it's there if anyone wants to look at it. Please not that that event timer system is a core component of my game, it's a bit too complicated to put in merely for shooting and there are probably easier ways to get a similar effect for shooting if that's the only thing you need that sort of timed function calling for. I find it a useful and flexible system, however.
You do a lot of programming? Really? I try to get some in, but the debugging keeps me pretty busy.

Crucible of Stars
zola -

Post by zola - »

Cool

I find it always interesting to see how other people implement stuff. Sometimes it's nice to see how similar the solutions are.

Your the trick with the templateized events is very appealing, most of all You don't get a bloated class hierarchy :) .

Boost does almost the same for the callback mechanism (for the timing I have defined a struct which does almost the sime as Your system). One drawback of boost is that you have to link an extra library but then again I don't mind including stuff if I spare some lines of code instead :)

However, thanks for the insight.
Post Reply