How do I make a boomerang in a 2d sidescroller

Hi i am trying to make a bommerang weapon in a 2d side scroller for a game that I am making. Any help is appreciated. Thank you!

Alright quick edit as I made the first post on my phone and didnt really want to type out all of the details on the small keyboard. So as stated above I want to make a boomerang like weapon in a 2D sidescroller game. I just want to projectile to go in a straight line for a certain distance then come back to the player. I have tried to do this by myself and was semi-confused as it would not work 100%. Once again any help is appreciated and thank you!

what have you got thus far?

i imagine you could use a timeline to pretty good effect. you just need to have a curve that goes from zero to one then back to zero. have the timeline as a alpha for setting the location of the projectile.

havent tried using a timeline yet. will try that right now and see how it does.

yea so that didnt work the way i did it. although i probably did it wayyy wrong
they all want to go to the center of the stage instead of in front of me. they dont even return to me when im done

There are lots of ways to do this, and choosing a proper course will depend on what kind of behavior you want to have, and how your game is set up.

Do you want the boomerang to always return to the player no matter where they are on the screen? I.E. if the player throws the boomerang and then jumps up to a higher platform, does the boomerang turn to return to the player, or does it just go back and forth in a straight line?
If the player “misses” catching it, does the boomerang continue in a straight line off screen, does it fly back and forth? Does it do a few loops and then disappear, or then fly off screen?
Does the boomerang fly at a constant speed, or does it slow down at the end of its arc? Does it return at the same speed?
Does the boomerang fly for a certain distance and then return, or does it fly for a certain amount of time?
Will there be different boomerangs that have different flight speeds/times? Different return behavior?

All these depend on the design of your game, there is no “right” or “wrong”; but once decided they can change the “right” and “wrong” ways to implement.

If you can provide more detail on the behavior you want to create, you’ll probably get more and better advice on how.

Hi! The way I would like the boomerang to work is to have it go forward in a straight line for a bit (but not off the screen or something like that) then have it always return to the player moving a little faster that it was when it was being thrown so the player isnt able to just keep running from the boomerang. Whenever it its an enemy it would return back to the player instead of going through the enemy. It would also be preferable if the player could throw it based on rotation so they can throw it both ways. I would also want to try to make it so they can only throw out one boomerang as it is out instead of…a lot more than one. Thank you so much for helping!

Alright, this isn’t the only way to do this, but given what you’ve said this is what I’d likely try. I keep meaning to go build this in BP and post screenshots, but I just haven’t had the time, so you’ll have to deal with my notes. Hopefully you’ll get the idea. Please bear with me if I have some node names or arguments wrong.

For the purposes of this example I’m going to make the following assumptions:

  • Z is up/down
  • Y is into the screen
  • X is left and right
  • You know the screen edge positions and can retrieve them each frame
  • You know how to determine which direction your character is facing (plus or minus X)
  • You have your Player Character already setup and it has an animation you want to use for “Throw”
  • You have a Boomerang Actor that you can spawn, animate, etc.
  • The Boomerang is a permanent part of the player’s inventory
  • You want the Boomerang to be able to retrieve pickup items
  • The Boomerang has a looping “Flying” animation
  • Your character has a function that allows it to collect pickup items
  • You have one “Enemy” class that all your enemy characters derive from
  • You have one “Item” class that all your pickup items derive from

You should have the Boomerang Actor spawned in the level, but hidden, not ticking, and collisions disabled. The Boomerang collision should be set to Overlap the Player Character, Overlap Enemies, and Overlap Items. It should be set to Ignore everything else.

First, we’ll look at the Character.



CHARACTER


You’ll need to have a few variables set:

  • bHasBoomerang (bool) - TRUE when the character has the boomerang
  • ThrowHeight (float) - the height above the ground the boomerang should move along when thrown
  • ThrowOffset (float) - the distance from the player the boomerang should begin when thrown (this allows for the player’s arm length or other animation so the boomerang doesn’t start inside the player)
  • ThrowMaximumDistance (float) - the maximum distance the boomerang can travel before turning around
  • Boomerang (obj reference) - pointer to the Boomerang Actor you’ve spawned in the level and associated with this character

Create a function on your character called “ThrowBoomerang”

The ThrowBoomerang function needs two local variables:

  • NewStartLocation
  • NewTargetLocation

When called, ThrowBoomerang function should first check if bHasBoomerang is TRUE

If it is FALSE, the method should just end.

If it is TRUE, then the function should:
  1. Set bHasBoomerang to FALSE
  2. Get the current world location of the player
  3. Add ThrowHeight to that location’s Z
  4. Add/Subtract ThrowOffset from that location’s X value based on facing direction
  5. Set the result to the StartLocation
  6. Add the ThrowMaximumDistance to StartLocation.X
  7. Set the result to TargetLocation
  8. Call “BeginThrow” on the Boomerang object, sending it NewStartLocation and NewTargetLocation
  9. Begin the character’s “Throw” animation

Create a function on your character called “CatchBoomerang”

When called, CatchBoomerang function should first check if bHasBoomerang is FALSE

If it is TRUE, the method should just end.

If it is FALSE, then the function should:

  1. Set bHasBoomerang to TRUE.

  2. Loop through the Boomerang->CarriedItems array

    1. Call your Item Pickup function for each entry
  3. Empty the Boomerang->CarriedItems array


Next, we’ll look at the Boomerang.



BOOMERANG


You’ll need to have a few variables set:

  • bIsReturning (bool) - flag telling the boomerang which behavior to use, make the default FALSE
  • TargetLocation (vector) - the location the boomerang is currently flying to, make the default 0,0,0
  • MinDistanceFromEdge (float) - the minimum distance from the edge of the screen the boomerang has to stay
  • ThrowVelocity (float) - the speed the boomerang moves when thrown away from the character, in units/second
  • ReturnVelocity (float) - the speed the boomerang moves when returning to the character, in units/second
  • CarriedItems (array - Items) - array of pickup items currently held by this boomerang
  • Character (obj reference) - pointer to the Character associated with this boomerang

Create a function on the Boomerang called “BeginThrow”

  • It should accept two vectors: StartLocation and NewTargetLocation

When called, the BeginThrow function should:

  1. Set bIsReturning to FALSE
  2. Set SetActorLocation with StartLocation and set Sweep to FALSE and Teleport to TRUE
  3. Set TargetLocation to passed in NewTargetLocation
  4. Set a Delay for the duration of the Character’s “Throw” animation - it shouldn’t be more than a couple frames or there will be too much lag after the player presses the throw boomerang button

After the Delay:

  1. Call SetActorHiddenInGame with FALSE
  2. Call SetActorEnableCollision with TRUE
  3. Call SetActorTickEnabled with TRUE
  4. Begin the “Flying” animation

Create a function on the Boomerang called “UpdateThrow”

  • It should accept a float: DeltaTime

The UpdateThrow function needs three local variables:

  • TravelDistance (float)
  • TraceMod (float)
  • NewLocation (vector)

When called, the UpdateThrow function should:

  1. Multiply input DeltaTime by ThrowVelocity

  2. Set the result to TravelDistance

  3. Set HalfWidth to TraceMod

  4. Call GetActorLocation

  5. Subtract ActorLocation.X from TargetLocation.X

  6. Get the Abs of the result:

    If it is GREATER than or EQUAL to TravelDistance

    1. Set TravelDistance to original (not absolute) result
    2. Set bIsReturning to TRUE
    3. If TravelDistance is Negative, NEGATE TraceMod
    4. If TravelDistance is 0, set TraceMod to 0

    If it is LESS, then:

    1. If ActorLocation.X is GREATER than TargetLocation.X, NEGATE TravelDistance
  7. Add TravelDistance to the ActorLocation.X

  8. Set the result to NewLocation

  9. If NewLocation.X is GREATER than RightScreenEdge

  10. Set NewLocation.X to RightScreenEdge - MinDistanceFromEdge

If NewLocation.X is **LESS** than LeftScreenEdge
1. Set NewLocation.X to LeftScreenEdge + MinDistanceFromEdge
  1. Call LineTraceForObjects
    - Set ActorLocation to Start
    - Add TraceMod to NewLocation.X and set the result to End
    - Make an array holding the the Enemy class and set it to Object Types

  2. If Return Value is TRUE:

    1. Break the Hit Result
    2. Get the Impact Point, set its X to NewLocation.X
  3. Call SetActorLocation, pass it NewLocation and set Sweep to TRUE

Create a function on the Boomerang called “UpdateReturn”

  • It should accept a float: DeltaTime

The UpdateReturn function needs three local variables:

  • TravelDistance (float)
  • NewLocation (vector)
  • TravelVector (vector)

When called, the UpdateThrow function should:

  1. Multiply input DeltaTime by ThrowVelocity
  2. Set the result to TravelDistance
  3. Call Character->GetActorLocation
  4. Set the result to TargetLocation
  5. Call GetActorLocation
  6. Subtract ActorLocation from TargetLocation
  7. Set the result to TravelVector
  8. Call VectorLength on TravelVector
  9. Get the Abs of the result
  10. If the Abs is GREATER or EQUAL to TravelDistance:
    1. Set TargetLocation to NewLocation
If it is **LESS**:
1. Call Normalize on the TravelVector
2. Multiply the result by TravelDistance
3. Add the result to ActorLocation
4. Set the result to NewLocation
5. If NewLocation.X is **GREATER** than RightScreenEdge
  1. Set NewLocation.X to RightScreenEdge.X - MinDistanceFromEdge

  If NewLocation.X is **LESS** than LeftScreenEdge
  1) Set NewLocation.X to LeftScreenEdge.X + MinDistanceFromEdge

6. If NewLocation.Z is **GREATER** than TopScreenEdge
  1. Set NewLocation.Z to TopScreenEdge - MinDistanceFromEdge

  If NewLocation.Z is **LESS** than BottomScreenEdge
  1. Set NewLocation.Z to BottomScreenEdge + MinDistanceFromEdge
  1. Call SetActorLocation, pass it NewLocation and set Sweep to TRUE

Add a Tick event

  • If you already have one, add to the end
  1. If bIsReturning is TRUE
  2. Call “UpdateReturn”, passing in DeltaTime

If it’s FALSE

  1. Call “UpdateThrow”, passing in DeltaTime

Add an ActorBeginOverlap event

  • If you already have one, add to the end:
  1. Cast OtherActor to the Enemy class

    Success Branch:

    1. Get the AsEnemy actor and do whatever damage you want to do
    2. Set bIsReturning to TRUE

    Fail Branch:

    1. Cast OtherActor to Item class

    Success Branch:

    1. Get the AsItem actor
    2. Add AsItem to the CarriedItems array
    3. Call SetActorHiddenInGame with AsItem and TRUE
    4. Call SetActorEnableCollision with AsItem and FALSE
    5. Call SetActorTickEnabled with AsItem and FALSE

    Fail Branch:

    1. Cast OtherActor to Character class
    **Success Branch:**
    1. If AsCharacter is EQUAL to Boomerang's Character
      1. Call SetActorHiddenInGame with FALSE
      2. Call SetActorEnableCollision with TRUE
      3. Call SetActorTickEnabled with TRUE
      4. Stop the "Flying" animation
      5. Call Character->CatchBoomerang
    


That should at least get you started.

Sorry to revive an old thread, but I am following the intructions layed out and everything is working fine up to ‘UpdateThrow’ line 3 “Set HalfWidth to TraceMod”. What is HalfWidth? It is not a variable. Is it supposed to half the length of TravelDistance? I am not understanding this part.