Announcement

Collapse
No announcement yet.

True Angry Birds style projectile system. [90% How-To 10% I need help] Fully Functional.

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

    True Angry Birds style projectile system. [90% How-To 10% I need help] Fully Functional.

    Here is my BluePrint set up for an Angry Birds Style launching mechanism, I would say it is about 90% done, it just needs a few little things improved/added to it. I have tried to lay the BluePrint out as organized as I can, and have collapsed several sections into Functions to make things a bit easier to lay out and keep organized. I made this in Paper2D, but it should be applicable to a 3D game as well.

    First we have the Viewport of the BluePrint. (Viewport.jpg)
    Click image for larger version

Name:	Viewport.jpg
Views:	1
Size:	674.7 KB
ID:	1226570

    I have a projectile (Cone_Sprite), a PhysicsConstraint, a hidden sprite (Dot) that I use as an anchor point and a Box Collison (Box) that I use to make "grabbing" the projectile easier. For the PhysicsConstraint it is set up to constrain my projectile (Cone_Sprite) and my anchor point (Box), the anchor point is right under the PhysicsConstraint, and cannot be seen from the ViewPort, it is also hidden in game. For PhysicsConstraint, the important settings are to make sure you have soft constraint enabled, make sure that your anchor point is the first object listed in the PhysicsConstraint (you will have to manually enter the names of the two objects) and make sure you have X/ZMotion set to Limited and YMotion set to locked (assuming you are making a game where X is left to right and Z is up and down). For your projectile, make sure that physics is enabled, gravity is disabled, and the sleep family is set to sensitve. For your BoxCollison (or Circle depending on the shape of your projectile), make sure that it is set to generate hit events, and make sure that you scale it down along the Y axis, and pull it a bit forward in Y space, so that it is not colliding with your projectile. FOr your anchor point, make sure collison is enabled, and it is hidden in game, or you could keep it as a visual cue of what angle your shot is going to launch.

    Now to the BluePrint (LauncherBP.jpg)
    Click image for larger version

Name:	LauncherBP.jpg
Views:	1
Size:	702.2 KB
ID:	1226571

    What sets the whole BluePrint off is the On Input Touch Begin, to get this we select our Box Collison (Box) and scroll down in the details panel to events, and click on On Input Touch Begin, this will bring up the On Input Touch Begin even in your Event Graph, and you can start building the BluePrint. From this event, we will trigger a Sequence, which we will then use to open two different Gates, which I have labeled in the BluePrint picture. Gate 1 is used to set the location of our projectile, and gate 2 is used to launch our projectile, so let's focus on Gate 1 for now.
    We'll need an 'Event Tick' and the 'Moved' execution from our 'Input Touch', with both Execution wires going into the Enter input of Gate 1. The reason we use the 'Event Tick' as well as the 'Input Touch', is because if we only use the Moved Execution from our 'Input Touch' to set the location of our Projectile, as soon as the player stops moving their finger, the 'PhysicsConstraint' will start pulling the projectile back to the anchor point, which we don't want. With our two execution wires entering our gate, we will now set the position of our projectile, so lets take a look at our first macro we will set up, which will give us the location that our player is touching on the screen. We need to create a Macro with an 'ETouch Index' input, and a 'Position' output, save the Macro as Finger_To_Vector, and open up your new Macro.

    Finger_To_Vector Macro (FingerToVector.jpg)
    Click image for larger version

Name:	FingerToVector.jpg
Views:	1
Size:	283.0 KB
ID:	1226572


    Inside of our new Finger_To_Vector Macro we need to set up a few things. First we drag a wire off of our input, which should now be called Finger Index, and connect that to the 'Finger Index' input of our 'Get Hit Result Under Finger By Channel' node. On our Get Hit Reuslts node, we also need to set the target to our Player Controller, so create a 'Get Player Controller' node and drag a wire from its return to the 'Target' input of our Get Hit Reusults node. Now we need to get the position information out of our hit results, so we will drag a wire from the 'Hit Result' output to a 'Break Hit Result' node, this will take all of the information from the hit result, and allow us to get the information that we need, which is the position. From the 'Position' output of our 'Break Hit' node, we drag a wire off and conect it to a 'Break Vector'. This will split the position information into 3 seperate float values for each axis, the reason we want to do this, is so that we can insure that our finger position will never return anything other than a value of 0 for the Y axis (as is, it never does, but if I were to change the camera, I am unsure if that would still be true, and this just let me know for sure). From our 'Break Vector' node, we create a 'Make Vector' node that we connect the X and Z wire to, but not the Y, and we make sure to set the Y value to 0, or whatever value you want your projectile to be in Y space. We connect the output of our Make Vector to our output, and our Macro is ready to go. Back in our BluePrint we attach a wire from the 'Finger Index' output of the Input Touch node to our the 'Finger Index' input of our Finger_To_Vector Macro.
    We are almost ready to set the location of our projectile, but we need to do one more thing first. As you will notice, before the 'SetRelativeLocation' node, I have a 'Branch', the reason for this, is that while testing with a print string connected to my position output, I noticed that occsionaly it would return a value of 0,0,0 when I let go of the mouse button, and this was no good, as it would move the projectile to the middle of the screen, and completely throw off what we are trying to do. To remedy this issue we simply attach our 'Position' output from our Finger_To_Vector Macro, and connect that to a 'Get Vector Length' node. From here we create an 'Equal (Float)' node that we connect our 'Get Vector Length' node to, in the A input (the top one), we set the value of B as 0, and then connect the boolean output (red wire) from our 'Equal (Float)' node to a Branch. We don't do anything with the 'True' output of our 'Branch' as when the location is 0,0,0 we don't want to set the location of our projectile, as that would mess everything up. So, we pull a wire off of the 'False' output of our 'Branch' and plug that into the execution input of a 'Set Relative Location' node. Now we take another wire off of the 'Position' output of our Finger_To_Vector Macro, and connect that to the position input of the 'Set Relative Location' node. Finally, we need to tell the 'Set Relative Location' node what object it needs to set the location of, so we grab the projectile (Cone_Sprite) from our component panel, and drag it into our BluePrint, and connect its output to the 'Target' input of our 'Set Relative Location' node. If we save our BluePrint and launch our game in the editor, we should now be able to grab our projectile and move it around with our mouse, assuming you have dragged the launcher BluePrint into the level. Now we will handle the release of our projectile.

    Time to launch our projectile into the world!
    We need to pull a wire off of the 'Released' output of our 'Input Touch' node, and connect it to the 'Enter' input of Gate 2, from the 'Exit' output of Gate 2, we will create a 'Sequence' with 3 outputs, we will use these to trigger the launch, and close our 'Gates'. The first and third outputs from Gate 2 are used to close Gate 1 and Gate 2, the middle output is where the fun happens, and where we get to make a new Macro. Create a new Macro with an execution input and output, name it Launch_Projectile, save it, and open up your new Macro.

    The Launch. (Launch_Projectile.jpg)
    Click image for larger version

Name:	Launch_Projectile.jpg
Views:	1
Size:	168.8 KB
ID:	1226573

    This part is pretty simple and straight forward (I have a sound effect in the picture, but you don't need to have one to make it work, but this would be a godo place in the blueprint to place it). From our Macro input we drag a wire and connect to a 'Delay' which we will set at 0.1 (you can play around with this and the 'stiffness' value in your Physics Constraint to get a good result depending on the size of your projectile and its mass). From our delay we connect to a 'Break Constraint' node, for this node we will need to drag our Physics Constraint into the BluePrint and connect a wire from it's output to the 'Target' input of the 'Break Constraint' node. Next we need to enable gravity on our projectile, so we create a 'Set Enable Gravity Node' which we will also need to provide a target, so we drag in our projectile and use that as the target, now we can connect the output of the 'Set Enable Gravity' node to the Macro output and contiune to our next step (We disable gravity by default on our projectile, because if we don't it will fall and swing under the anchor point when we load the level). But if we save and launch our game, we should be able to grab our projectile, pull it back, release it, and watch it fly.
    Post Launch actions.
    After we launch our projectile, we need to do a few things, like be able to launch another projectile. So next we shall cover that, and our Angry Birds style projectile launcher will be done!
    Instead of spawning a new projectile and attaching it to the Physics Constraint, I figured it would be easier to just spawn a replacement projectile, destory the original launcher BluePrint, then spawn a new launcher BluePrint, so we will go over how to do that. First we are going to need to create a copy of our projectile, and then make a new BluePrint from it. Next we go back to our launcher BluePrint and put a 'Delay' (how long you want to set the delay is up to you, if you wanted you could even just skip it, but I want to give the projectile a bit of time to interact with the level before I spawn a new one) after our Launch_Projectile Macro, after the delay we will create a 'Spawn Actor From Class' node, in that node, from the drop down menu we will select the BluePrint that we made with our duplicated projectile. Now we need to tell that node where to spawn the replacement projectile, which brings us to our third Macro. We will create a new Macro, name it Projectile_Replacement_Transform give it a 'Transform' output, save it and open it up.

    Projectile Replacement Transform (Replacement.jpg)
    Click image for larger version

Name:	Replacement.jpg
Views:	1
Size:	166.9 KB
ID:	1226574


    This one is pretty simple, we just drag our projectile in, from it drag off a wire and create a 'Get World Position' node. From that we will create a 'Break Vector' node and a 'Make Vector' node. We will connect the output of our 'Get World Position node to our 'Break Vector' node, then attach the 'Position' and 'Rotation' outputs of the 'Break Vector' into the 'Make Vector'. The reason we do this, is because the projectile will often be too big or too small if we just use the transform information that we get from the 'Get World Position' node, this allows us to make sure our replacement projectile spawns at the correct size, you will probably need to play arouund with the scale value to get it right. From our 'Make Vector' node, we drag a wire to the output of our Macro, and we're good to go. Back in our BluePrint we will connect the output of our Replacement_Projectile_Transform node to the 'Position' input of our Spawn Actor From Class node, now our replacement projectile will spawn in the correct location, and at the correct size!

    Setting the Velocity of our reaplacement projectile (Velocity.jpg)
    Click image for larger version

Name:	Velocity.jpg
Views:	1
Size:	225.1 KB
ID:	1226575


    Next we need to set the Linear and Angular Velocity of our replacement projectile so that the new projectil will contiue the same path and rotation that the original projectile was on, which brings us to our final Macro. Create a new Macro named Clone_Velocity give it an execution input and ouutput, and also an input that is a refrence to your replacement projectile (to do this, click on the create new input button and type the name of the BluePrint of your replacement projectile, it should now be a blue colored input) save your Macro and open it up.
    This part is pretty straight forward. From the execution output of the Macro input, connect in order, a 'Get Physics Linear Velocity', 'Get Physics Angular Velocity', 'Set Physics Linear Velocity' and 'Set Physics Angular Velocity'. Next we will connect the return values of the Get Linear and Angular Velocities, and connect them to the Set Linear and Angular velocities inputs, respectivly. Now we drag our original projectile from our BluePrint in and connect its output to the 'Target' input of the 'Get' nodes, then we drag a wire off of the refrence output of our Macro input (blue wire) and type in the name of our duplicated projectile, and connect the output of that to the 'Target' input of our 'Set' nodes. Next we connect the last Get node to our Macro output, save and go back to our main BluePrint, where we will connect the blue output of our Spawn Actor From Class to the blue input of our Clone_Velocity, you may need to do this first before you are able to get a refrence to your duplicate projectile.
    Now we just need to destory our original launcher and spawn a new one. This is pretty easy. We attach a Destroy Actor node to our Clone_Velocity Macro, then a another Spawn Actor From Class node. On our final Spawn Actor From Class node, we will set the actor to our Current Launcher, and for orange 'Spawn Transform' input, we will right click it, promote it to a variable, and copy/paste the transformation of our original Launcher that we placed in the level, so that our new launcher spawns in the exact same spot. We're done!
    I'm sure I forgot a few things, and I will update the post to reflect that when I think of what I forgot. If you have any questions or issues, let me know and I will do my best to help you out.
    Now for what I want to change about my launching mechanism.

    Smooth out touch input. I'm guessing as a consequence of trying to figure out a one pixel location from a finger press that covers what I'm guessing is a lot more than a one square pixel area on my screen, sometimes I will notice my projectile kind of moving back and forth rapidly between two close points. I'm hoping there is a way to sort of smooth that out.

    Proper Rotation on my projectile. Due to how I have the Physics Constraint set up, it usually does a pretty good job, but since my projectile is longer and more like an arrow, it is important that before launch, it is rotated to always be facing the anchor point, as it is now, it's pretty close, but if I move it around a bunch it will start to sway and get way off rotation.

    Circular Constraint. I'm guessing this is a setting in the Physics Constraint, but I want to be able to have a set distance that you can pull back your projectile, as it is now you can pull it back as far as you have screen space, but I want something like Angry Birds, where you can only pull it back so far. I though about just using a clamp, but then I'd have a square shaped area where you could pull the projectile back, and as a consequence, certain angles would be able to generate more velocity than other, plus it would just look ugly, and make aiming more difficult.

    Disable Collision on the projectile before launch. As it is right now, I am unable to get the Physics Constraint to work unless both constrained object have collision enabled. My issue is that occasionally the new projectile will spawn while there are still things moving around in the level, and sometimes they will collide with my new projectile, causing it to swing around.

    Other than that I am pretty happy with this launching mechanism. I'm hoping that some people get some good use out of this, as I have been unable to find any sort of tutorials on making a true Angry Birds style launching mechanism, and I'm also hoping some people have some ideas to help me address the few small issues I am having. Also I'm sure I forgot some stuff, and I will be sure to edit the OP when I find my mistakes.
Working...
X