| Part 3: Shooting Bullets Back to the overview |
|||||||
Creating a lot of bullet-objects and moving them around can make your application very slow when copying and deleting them in-game. This is why a lot of games choose not to have real bullet-objects flying around but to use a lot of nice decals, marks and particle-systems instead. However, sometimes you really need the visual effect of a real flying bullet or grenade, especially when the bullets are traveling at lower speeds. We don’t want to go for the easy way out so for this tutorial we will show you how you can create a workable bullet-object and its script. Next, we’ll create a group of bullets and we’ll position, orientate and activate them when we need them. This poses a new problem we need to overcome: how can we shoot the bullet exactly at the centre of the screen, the crosshair. Next, the firing of a bullet will be synchronized to the character-animation of “shooting a bullet”. We need to set up a system that detects the impact of bullet and marks the impact spot with a nice decal. To create a good bullet we need to use a Per Second BB and a Translate BB. We need to create conditions for the bullet to stop (after a couple of seconds or when it hits something) using a Delayer BB and Ray Intersection BB as well. Next we’ll use this Ray Intersection BB to retrieve more accurate impact data which we can use later on with the Mark System BB. The bullet management system uses the Object Copy BB and shows you how to dynamically create objects and how to activate and deactivate objects and their scripts. To time the firing of a bullet (and maybe a nice muzzleflash) we use an Animation Synchronizer BB. We’ll cover the creation an impact effect (a decal, sound and maybe some particle effects). You can continue with your own project or open tutorial_part_3_start.CMO.
|
|||||||
1 Preparing The Composition To have a better view of what’s going on it’s a good idea to hide all unnecessary dummy objects (if you haven’t done so already). Now we can start work on the bullet object. Import _bullet.NMO from the Resource (3D Entities) into your composition (it’s located on (0,0,0)). Notice that it’s pretty long: this is done to make sure that the bullet remains visible when it’s viewed from the camera-perspective. Let’s import the _crosshair.NMO as well, just to start of with a good aim referential. Drag it from the 3D Entities folder of the Resource (3D Entities). It’s actually a 2D entity that is already prepared. Take a look at the Setup of the crosshair. Make sure you are running the 3D viewport in a 640*480 resolution and that “Ignore camera aspect” isn’t checked (in the General Preferences). Otherwise the crosshair won’t be centered! We’ll create something to keep the crosshair centered in other resolutions later on.
|
![]() |
||||||
|
2
The Bullet Script This is actually the easiest and smallest script of the tutorial. This is a good thing because we’ll probably have a lot of these executing at the same time. It’s important to know that you can’t test your bullet just yet: we have to create a bullet management script before we can do that.
• Back to the script on the bullet. It consists of three parts: the movement, the collision and the disappearance of the bullet. Let’s start with the movement: create a script on your _bullet and create a Per Second BB and a Translate BB. Connect them (setting the speed to (0,0,80) meters per second) and loop it. Don’t forget that you need to change the pOut type of the Per Second BB to vector by double-clicking on the little triangle! You can set the Referential of the Translate BB to “This” or you can leave it as it is. Connect the Per Second BB to Start. Now add something to make the bullet appear 20ms after it is fired (otherwise it would be possible that the bullet will appear inside the character, due to its length). Add a Delayer BB (20ms) and a Show BB (add a This parameter and make this the Target by pressing “T” when the BB is selected). | ||||||
| 3
Ray Intersection For the collision we’ll use a Ray Intersection BB: the bullet will shoot a short ray from behind itself to test if it’s about to hit something. We chose this BB instead of a Collision Detection BB because at high speed a collision is often not detected! For optimization purposes, we need to put all shootable objects in a group called “shootable_group” (leave all dummy and character objects out of this group please). To do this, select them in the Level Manager and press “G”.
• Back in the script, insert a Ray Intersection BB and a Send Message BB. The parameters for the Ray Intersection BB should be set as follows: • Now we are going to send al this data in a message to a script that is going to handle our bullet impacts. Set the Message “bullet_impact” and the Destination “Level” (we’re going to create a Level Script later on to handle this message…). Create local parameters (“Alt+L”) and construct parameter inputs for your Send Message BB: | ![]() |
||||||
|
4
Deactivation Of The Bullet First we need a group to hold all bullet objects when we create them later on. Select the bullet object from the Level Manager and press “G” to create a new group (“bullets_group”). Now, the last part of the bullet script is its own deactivation. Instead of dynamically creating and deleting bullets as we need them, we are going to create a whole bunch of deactivated and hidden bullets. When we need them we will position them and activate/show them. When we are done with them (when the bullet hits something or when it’s far away) we need to deactivate them again.
• Drag a Delayer BB, a Hide BB, an Add To Group BB and a Deactivate Object BB into your script underneath the rest. Connect them all in a linear way (and the Delayer BB to Start of course). The Delayer BB specifies the “lifespan” for the bullet. Set it to 2,5 seconds (so the bullet can fly 2,5 x 80 meters = 200 meters, this should be far enough). The Hide BB is okay like it is. Specify the “bullets_group” in the Add To Group BB. Create a This parameter as pIn for the Deactivate Object BB. Connect the bOut of the Send Message BB to the bIn of the Hide BB to make sure these BBs also run when the bullet hits something (there’s no need to let bullets fly around for nothing, is there?). Before we go any further, we need to deactivate the bullet object and its script when the scene starts. • You can do this in the Level Manager by clicking a red cross through the capital As behind the objects and the scripts name. Click the Eye icon to make it invisible and use the right click menu to set a new IC on the _bullet. Now you don’t have to worry about your original bullet flying away and deactivating itself when you play your composition.
| ||||||
| 5
Bullet Copying One bullet is never enough for this game, we need more! We’ll make a Level Script called “fire” to manage the bullet copying, bullet firing and the impacts on objects. To create 20 bullets and put them in a temporary group we need an Add To Group BB, a Counter BB and an Object Copy BB. Create a Target for the Add To Group BB and specify the bullet object (just in case the bullet object is not in the group as the composition starts). Set the bullets_group as the group. For the Counter BB set the Count to 20. Edit the Object Copy BB: set the original to the bullet object. Specify custom dependencies: make sure to check Unique Name and Group Belongings (in the Behavioral Object folder). Loop the Object Copy BB into the Counter BB and create a nice BG called “bullets_copy”. Remember that if you want your bullets to fly longer, you probably need more of them!
| ![]() |
||||||
![]() |
6 Bullet Firing When the fire script receives the message “fire” (we’ll handle the sending later) we need to grab an available bullet from the bullets_group, orientate and position it and then activate it. First insert a Wait Message BB and specify “fire” as the message. Now we need an Identity BB and a paramOp (Get Element). Feed the paramOp the bullet_group and a integer “0” to receive the first element of the group (a free bullet) and output this 3D Entity into the Identity BB and output that pOut into a new local 3D Entity parameter called “new_bullet”. Create a BG “get new bullet” around it and connect the Identity BB as shown in the picture.
|
||||||
| 7
Aiming Now we’ve arrived at the tricky part of the script. We want to have the bullet fly exactly towards the point we are aiming at. This would be easy if we we’re to orientate the bullet on the camera and then let it fly forwards, but the bullet would seem to originate from the camera! We could orientate the bullet on the gun or the character, but then the bullet would never hit the exact center of your screen. We could use one of the two methods mentioned for a quick fix, but we decided to make things difficult for ourselves. So we want a bullet that flies exactly towards the aim of the crosshair and that originates from the gun. To do this we need to: 1. Get the exact point the bullets needs to be flying towards, 2 Calculate the starting point and orientation of the bullet, 3 Activating and showing the bullet as it flies off.
• To calculate the destination point we need a Ray Intersection BB. Set the thirdperson_camera as the Target and the Referential, because we want to hit the thing that is exactly in the centre of this view. This ray needs to originate from some distance exactly in front of the current camera-position (otherwise you would be able to shoot things behind the character!). Paste a shortcut to the referential camera position “camera_position” far above the Ray Intersection BB (you can find this parameter in the direction_frame script). To transform this into a vector in front of the character, where the bullet/ray needs to begin, we need to: multiply this vector with -1, get only the z value and add (0,0,1) to it. Do this with a couple of paramOps (as shown in the picture) and insert this vector into the Ray Origin pIn. Set the Depth to 150 and the Filter to “shootable_group”. Create a couple of parameters underneath the pOuts of the Ray Intersection BB: intersection_object, intersection_point, intersection_normal and intersection_distance. We’re going to need them in the next step. | ![]() |
||||||
![]() |
8
Creating A Bullets 3D Frame After the calculation of the intersection_point, we need to calculate the direction vector for the bullet using this vector (intersection_point) and the current position of the gun. Since the gun is not a real object but a part of the whole mesh (and also for accuracy reasons) we need to create a 3D frame that acts as origin of the bullet. Create one and name it “bullets_frame”. Insert a little piece of code inside your direction_frame script to keep this thing exactly right positioned and orientated. Create a “set bullets frame” BG behind the “camera_collision_adjustments” BG and the “set camera” BG. Inside this BG, insert a Set Position BB and a Set Orientation BB. For both BBs, set the Target to bullets_frame. For the Set Position BB, set the position to (0.38, 0.01, 0.98) and the Referential to The Hammer Spine1. For the Set Orientation BB set the Referential to the direction_frame. Don’t forget to incorporate the BG into the big loop!
| ||||||
| 9
Setting The Bullet Let’s go back to the fire script. After the Ray Intersection BB we are going to do a couple of things with our “new_bullet”, keep in mind that for most of the BBs the “new_bullet” needs to be the Target parameter:
• Remove From Group BB it from the bullets_group (making it unavailable). • Set Position BB the “new_bullet” on the bullets_frame (Referential). • Set Orientation BB it. Use a Get Position paramOp to insert the location of the bullets_frame into the right pIn of a new Subtraction paramOp. This Subtraction paramOp should subtract a shortcut to the intersection_point (left pIn) from the bullets_frame position (right pIn) This creates a vector that makes sure the bullet points towards the point you are looking. Insert this into the Dir pIn of the Set Orientation BB. • Activate Object BB it. In the parameters of this BB, make sure to check Activate All Scripts and Reset Scripts. | ![]() |
||||||
![]() |
10
Sending The Fire Message Although it won’t work perfectly yet, maybe it’s a good idea to create the Send Message BB that sends the “fire” message. This way you can finally see what you’ve been working on the last 9 steps!
• Go to the animation script on TheHammerAk character. Add an Animation Synchronizer BB. This BB will send a specific message to the owner of the script on a specific frame of a character animation. Double-click on it to enter the setup of the Animation Synchronizer BB. For each animation that involves shooting (the blended ones and the stand_shooting animation) Add a “fire” message (remember that the blended ones have double names). • Add a Wait Message BB (“fire” from the Animation Synchronizer BB) a Binary Switch BB testing “left_button” (a shortcut to the parameter in the temp script) and a Send Message BB (sending “fire” to the Level). Loop the Binary Switch BBs False bOut and the Send Message BBs bOut back to the Wait Message BBs bIn. Create a nice BG called “fire message” around the whole thing and run your script! Note: when your bullet doesn’t hit anything the loop of the fire script will be broken and you won’t be able to shoot any more bullets! |
||||||
| 11
Debugging If you run your composition now, you will probably have noticed that something weird happens when you’re shooting in the air. This is because the Ray Intersection BBs False bOut is activated and it is not connected. We can’t use the “intersection_point” vector to calculate the orientation in this case (the parameter doesn’t work when the Ray Intersection BB doesn’t hit anything). We’ll use the direction of the direction_frame to set the orientation of the bullet in this case. Alternatively, you could create a sky object, but then you’d need to increase the Depth of your Ray Intersection BB I guess.
• Back in the fire script, copy the “set bullet” BG and rename it “set bullet2”. Remove the Get Position and Subtraction paramOps (keeping the bullets_frame as the Referential for the Set Position BB) and change the Dir pIn of the Set Orientation BB back to its reset value (0,0,1). Set the thirdperson_camera as the Referential. Connect this BGs bIn to the False bOut of the Ray Intersection BB. Connect the “set bullet2” bOut to the bOut of the “firing bullet” BGs bOut. Test your script. We have saved our progress up to now as tutorial_part_3_halfway.CMO. You can always check this file if you are really stuck! | ![]() |
||||||
|
12
Bullet Impact To see where we have fired our bullet, we need a nice impact. For this we are going to use the Mark System BB and feed it data from the “bullet_impact” messages sent by our bullets on impact.
• Insert a Wait Message BB, a Get Message Data BB and a Mark System BB in the lower part of your fire script. For the Wait Message BB, specify “bullet_impact” as the message and also insert this one as the pIn for the Get Message Data BB. For this last BB, construct three pOut parameters: one 3D Entity (the hit impact object), one vector (the impact point) and another vector (the impact normal). We don’t need the 3D Entity just yet, but you can connect the other two pOuts of the Get Message Data BB to the right pIns of the Mark System BB (don’t insert them directly into the BB or you will lose the parameters). Before we edit the BB, we need to create an impact mark. • Drag the “mark_default.Bmp” from the Textures Resource into the scene. Create a new Material (by clicking the little sphere in the main toolbar). In the material setup rename it “mark_default_mtl” (you can select its name and then press “F2”), set the Mode to Transparent and specify the “mark_default” as the Texture. • Back in the Schematic, edit the parameters of the Mark System BB. Set the Size to 0.3, the Material to “mark_default_mtl”, Lifespan to 10s, Fading Time to 3s and the Position Offset to -0.001. You can also edit the settings of the BB, set the Maximum Marks to 100 and check Random Orientation. Loop the Exit Mark bOut of the BB back into the Wait Message BBs bIn and connect that bOut to the Get Message Data BB, and that bOut into the Mark bIn of the Mark System BB. Drag a nice BG “bullet impact” around the whole thing and connect this to Start. Don’t forget to connect the bIns of the Wait Message BB and of the Mark System BB to the bIn of the BG! | ||||||
13 Fire Effect For a nice feedback when you fire, we are now going add a muzzle flash and a sound effect. Drag muzzleflash.NMO from your 3D Entities Resources into your scene. This .NMO file contains a 3D Sprite, its script, its material, texture and a sound effect. We will take a look at the setups for these objects. You can do so by selecting them in the Level Manager and selecting Setup from the right click menu. Take a look at the setup for the 3D Sprite. Notice that Billboard isn’t checked, but Orientable is. We want the muzzleflash to have a slightly different orientation each time it is displayed, so we scripted or own billboard-behavior. Inspect the material settings of the muzzleflash. They have been changed to produce a more glowing effect. In the sound setup, notice that Streaming has been unchecked and that Point has been checked. We want the sound to come from the newly imported muzzleflash, so this has been set as the Attached Object. The Min/Max perception distances have been set to 3 and 50 to make sure the sound isn’t so loud from a distance. • Now let’s take a look at the muzzleflash script (you can find it in the 3D Sprites folder of the Level Manager). The Get Current Camera BB and the Identity BB fetch some parameters for the top part of the script. The top part starts with a Set Position BB. You must set the bullets_frame as the referential (where it says: bullets_frame_here !) because we want it on the location of the bullets_frame. The script then goes on to do some obvious things: show the muzzleflash (did you notice in the Level Manager that it starts out hidden?) and it plays the sound. Next up is a Timer BB that keeps a Set Orientation BB and a Rotate BB active for 30ms. The Set Orientation gets its Dir form the current camera and makes the sprite point towards the camera. The Rotate BB changes that orientation slightly with a random angle (this has to be set for each frame). When the Timer BB is done the sprite hides and deactivates itself (it isn’t activated when the composition starts, you can check this in the Level Manager). • All we have to do now is add an Activate Object BB behind the “firing bullet” BG in the fire script. Specify the muzzleflash (3D Sprite) as the Object and check Activate All Scripts and Reset Scripts. Connect it to the bOut of the “firing bullet” BG. Why don’t you turn the volume up and give your new muzzleflash a try? |
![]() |
||||||
![]() |
14 Impact Effect The bullet impact mark still looks a bit dull. Let’s use a small particle system to create some dirt flying around. From the 3D Entities folder of your Resources, drag impact_frame.NMO into your composition. This file contains a 3D Frame with a script attached to it, a texture for the particle system inside the script and a sound effect. Take a look at the attached script.
• The script starts off by setting itself on the position of the last mark. To make this work we need to paste a shortcut to the Position parameter of the Mark System BB (in the bullet script) above the Position parameter of the Set Position BB (now called • Back in the impact_frame, we must set an orientation for the frame. To make the dirt fly away from the impact point you can take the orientation of the bullets_frame and multiply it with -1 (using the impact normal doesn’t seem to work…). Select the bullets_frame as the value for the parameter “bullets_frame_here”. Next a sound is played with a Play Sound Instance BB. You don’t have to change anything here. • That big BB is used to produce only a few particles. You usually want to use a 3D Frame like this to be the host of a particle system. In this case it will spray in the direction of the frame. While the BB is selected, press “S” to take a look at it’ settings. Notice that a lot of features have been unchecked to save some processing time. Give the parameters a look as well. Notice that debris_txt is the texture used for the dirt. • When the Point Particle System BB is activated, a Delayer BB is triggered so that the particles stop after 100ms or so. When this is done the object and its script are deactivated. Try your new particle system!
| ||||||
| 15
Shells This last effect we are going to add creates some shells when you fire. This is done with a 3D Frame containing a particle system as well, but it also needs another 3D Frame to make the shells fall to the ground and bounce a little before disappearing. From the 3D Entities folder of your Resources, drag shell_frame.NMO into your composition. This file contains the shell_frame and its script, a texture for the particle-system and another 3D Frame called particle_frame. First look up particle_frame in the Level Manager and view the 3D Frame setup by right clicking on it and selecting Setup. In the Setup, select Attribute on the left side, this will show you the objects attributes. Notice that it has two attributes assigned. We’ll get back to assigning and creating your own attributes in the next tutorial.
• In the script of the shell_frame, you can see that this frame gets its position and orientation from the bullets_frame. Specifiy it as the Referential for both BBs. Select the Point Particle System BB and press “S” to inspect its settings. Notice that in the Manage Deflectors section, the Infinite Plane attribute is checked and that in the Manage Interactors section the Gravity attribute is checked. If you wish you can take a look at the BBs parameters. This BB is deactivated as soon as the Exit On bOut is activated to make sure it doesn’t spray too much shells. | ![]() |
||||||
![]() |
16
Finishing Touch To make the frame active (this one also starts out deactivated, see the Level Manager), we need to insert another Activate Object BB, this time behind the other Activate Object BB, the one for muzzleflash (in the fire script of course). Specify the shell_frame as the Object and again check Activate All Scripts and Reset Scripts. Connect its bIn to the other Activate Object BBs bOut. Test your shells!
Wouldn’t it be cool if there was a ringing sound when a shell hit the floor? Or maybe that the deflector for the particle system would change position if you were standing on something? With a little more scripting this would be easy, so feel free to try! If not, why not continue with the next tutorial, when we finally add something proper to shoot at… |
||||||
End of part 3. |
|
||||||