Game Development Community

Four-round bursts

by Daniel Buckmaster · in Torque Game Engine · 12/01/2006 (11:47 am) · 10 replies

I've started playing with the CodeSampler tutorials, and I've added a weapon to my level. I want to modify it so that when the mouse is held down, the weapon will fire four rapid-fire shots, then stop until the mouse is released (or maybe just times out).
Is there an efficient way to do this?
The only way I can see is to have fire1, fire2, fire3 and fire4 states, with each leading on to the next through their stateTransitionOnTriggerDown values. fire4 leads to a waiting state which forces the weapon to wait for a certain amount of time before going back to the ready state.

About the author

Studying mechatronic engineering and computer science at the University of Sydney. Game development is probably my most time-consuming hobby!


#1
12/01/2006 (12:02 pm)
Sounds good to me.
#2
12/01/2006 (12:58 pm)
Then how would I structure the states?
There'd have to be 'Ready', with stateTransitionOnTriggerDown = "Fire1"
Then in Fire1, how would I go to Fire2 next time the trigger was pulled?
Sorry, I'm really new to the engine... as you can probably tell...
#3
12/01/2006 (1:05 pm)
Also have another state (action/script.. i cant remember) for stateTransitionOnTriggerUp with a short pause in it before going back to the ready state. That way it wont fire again until the mouse button is released. I did this for my weapons. I'd show u code now, but im not at home.
#4
12/01/2006 (1:18 pm)
So that will get me a single-shot weapon... that's a step in the right direction, thanks :)
In the past I've used an engine where behaviour for an object is run through each frame, unlike the datablock system. So in the old system I could just say 'if the current shot count is so high, go to this state'. And in that state, 'raise the current shot count'.
I know I can do something like this by modifying the C++ code, but I'm not up to that yet.

Thanks for the quick replies, guys!
#5
12/01/2006 (1:58 pm)
Here is some pseudo code of how I would handle the problem. It is to be noted that the variable names are not correct (I shortened them).

state "Ready"
onTriggerDown "Fire1"

state "Fire1"
onTimeOut "Ready2"
timeOutValue 1.0

state "Ready2"
onTriggerDown "Fire2"
onTriggerUp "Ready"

You can continue this for as many shots as you want in a single bound. When you reach the 4th and final shot you could do something like this:

state "Fire4"
onTimeOut "DoneBurst"
timeOutValue 1.0

//Make sure we release the trigger before we can fire again.
state "DoneBurst"
onTriggerUp "Ready"


*You would set the timeOutValue for the amount of time you want between shots. 1 Second would probably be a bit too much. I hope this helps.

*You could do this without the extra ready states but then you would not be able to specify a time between shots.
#6
12/01/2006 (11:34 pm)
Thanks a lot! I'll have a go at it...
#7
12/01/2006 (11:37 pm)
Just wanted to reinforce that Joshua's method is the most appropriate.

You could of course cheat and just set up a schedule within the ::onFire() script that creates 4 projectiles over time, but this wouldn't allow for multiple animations, sounds, etc, etc.
#8
12/01/2006 (11:54 pm)
I'm getting console errors after adding 'Wait', 'Wait1' etc states. It says 'could not resolve state "whatever" for RocketLauncherImage. Strangely, no errors come from the EndBurst state.

Here's the relevant code:

//Wait between shots in a burst
	statename[8]			 = "Wait";
	stateTransitionOnTriggerDown	 = "Fire2";
	stateTransitionOnTriggerUp	 = "Ready";

	// Fire the weapon. Calls the onFire function when our player shoots.
	stateName[3]                     = "Fire1";
	stateTransitionOnTimeout[3]      = "Wait";
	stateTimeoutValue[3]             = 0.1;
	stateFire[3]                     = true;
	stateRecoil[3]                   = LightRecoil;
	stateAllowImageChange[3]         = false;
	stateSequence[3]                 = "Fire";
	stateScript[3]                   = "onFire";
	stateEmitterTime[3]              = 0.3;

	//Wait between shots in a burst
	statename[8]			 = "Wait1";
	stateTransitionOnTriggerDown	 = "Fire3";
	stateTransitionOnTriggerUp	 = "Ready";

	// Fire the weapon. Calls the onFire function when our player shoots.
	stateName[7]                     = "Fire2";
	stateTransitionOnTimeout[7]      = "Wait1";
	stateTimeoutValue[7]             = 0.1;
	stateFire[7]                     = true;
	stateRecoil[7]                   = LightRecoil;
	stateAllowImageChange[7]         = false;
	stateSequence[7]                 = "Fire";
	stateScript[7]                   = "onFire";
	stateEmitterTime[7]              = 0.3;

	//Wait between shots in a burst
	statename[8]			 = "Wait2";
	stateTransitionOnTriggerDown	 = "Fire4";
	stateTransitionOnTriggerUp	 = "Ready";

	// Fire the weapon. Calls the onFire function when our player shoots.
	stateName[9]                     = "Fire3";
	stateTransitionOnTimeout[9]      = "Wait2";
	stateTimeoutValue[9]             = 0.1;
	stateFire[9]                     = true;
	stateRecoil[9]                   = LightRecoil;
	stateAllowImageChange[9]         = false;
	stateSequence[9]                 = "Fire";
	stateScript[9]                   = "onFire";
	stateEmitterTime[9]              = 0.3;

	//The end of the burst
	statename[8]			 = "EndBurst";
	stateTransitionOnTriggerUp	 = "Ready";

	// Fire the weapon. Calls the onFire function when our player shoots.
	stateName[11]                    = "Fire4";
	stateTransitionOnTimeout[11]     = "EndBurst";
	stateTimeoutValue[11]            = 0.1;
	stateFire[11]                    = true;
	stateRecoil[11]                  = LightRecoil;
	stateAllowImageChange[11]        = false;
	stateSequence[11]                = "Fire";
	stateScript[11]                  = "onFire";
	stateEmitterTime[11]             = 0.3;

I probably should have commented the code a bit better, but it's a test and pretty basic stuff...
#9
12/02/2006 (6:54 am)
You're getting console errors because you keep resetting your stateName[8] variable. As your datablock loads, stateName[8] is changed to "wait1", "wait2", "wait3", etc. By the time the engine's done loadng your datablock, stateName[8] equals "EndBurst" (which is why there is no console error there), and all your wait functions no longer exist. You need to define your wait functions as stateName[11] = wait, stateName[12] = wait1, etc.

Your stateTransitionOnTriggerDown and stateTransitionOnTriggerUp variables are also being overwritten by one another, you should define them as part of an array.

The below definitions of your wait states and your EndBurst state should work.
//set up "wait" state
stateName[11] = wait;
stateTransitionOnTriggerDown[11] = fire2;
stateTransitionOnTriggerUp[11] = Ready;
//
//set up "wait1" state
stateName[12] = wait1;
stateTransitionOnTriggerDown[12] = fire3;
stateTransitionOnTriggerUp[12] = Ready;
//
//set up "wait2" state
stateName[13] = wait2;
stateTransitionOnTriggerDown[13] = fire4;
stateTransitionOnTriggerUp[13] = Ready;
//
//set up "EndBurst" state
stateName[14] = EndBurst;
stateTransitionOnTriggerUp[14] = Ready;
Fix those bugs, and the weapon should work. Just make sure that there are no gaps between the numbers in the brackets (like not having variable[2] defined when you have both variable[1] and variable[3] defined) after you copy the above code, or else the engine will "miss" part of your datablock. I don't have all the code for your datablock, so I dont know what numbers you already have "used".
#10
12/03/2006 (12:10 am)
Gah! Thanks a lot for that, but a swift kick in the rear would have worked as well. Stupid newbie mistake, that... :P
Thank you very much!

EDIT: The weapon works. Thanks again.