• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • 🏆 Hive's 6th HD Modeling Contest: Mechanical is now open! Design and model a mechanical creature, mechanized animal, a futuristic robotic being, or anything else your imagination can tinker with! 📅 Submissions close on June 30, 2024. Don't miss this opportunity to let your creativity shine! Enter now and show us your mechanical masterpiece! 🔗 Click here to enter!

[JASS] 2D bouncing math / GetSpellTargetX

Status
Not open for further replies.
Level 9
Joined
Sep 5, 2007
Messages
358
Hey!

Ok, in the game I'm developing I need to calculate the bouncing angle when an object hits the walls.

It's in 2D perspective so no Z axis is required.

Also I don't use speed and angle to make my objects move, I use velocityX and velocityY instead.

I tried the angle = Pi - angle formula, but since I have to calculate back to vX and vY both velocities become inverted somehow.

Any help would be appreciated, if you are going to post a formula be sure to explain it, although I like it, math isn't my area of expertise.

I'll attach a simple draw of the effect I want to achieve, I think the draw is enough to understant.
Black Lines -> walls
Red Lines -> Object trajectory

GetSpellTargetX/Y Issue

I have the latest patch installed, I've updated my JNGP with the new hashtable native functions, however I don't seem to have the GetSpellTargetX and GetSpellTargetY functions on the functions list.
Any idea on how this happens and how it can be solved. Well it isn't that of a big deal, but would be good to know how to fix it.

Thanks in advance
 

Attachments

  • example.jpg
    example.jpg
    16.4 KB · Views: 92
Last edited:
Level 9
Joined
Nov 28, 2008
Messages
704
WC3 is incredibly limited. When I did this, I was forced to restrict myself to horizontal and vertical walls.

If you want the formulas, just imagine what you want to happen.

Say you are apporaching a verticle wall at an angle of 45 degrees. When you bounce off, you want to be going 135 degrees. And if you approach a wall at 135 degrees, you want to go 45 degrees when you collide. Thus, we can say when approaching a vertical wall:

newAngle = PI - oldAngle (replace pi with 180 if you are using degrees, not radians)

Now, when we approach a horizontal wall, say at 45 degrees again, we are going up and to the right. We will be going down and to the right when we are done. Precisely at 315 degrees. If we hit a vertical wall, we will be going 45 degrees. Thus, for horizontal wall collisions:

newAngle = 2PI - oldAngle

Now for the fun part: finding out if your colliding with a horizontal or vertical wall.

This is strictly a collision issue. In your collision checker, your going to have to try moving your collision item to the new x/y, and seeing if it is unable to be moved there, right? Well, go one step farther. If moving to the new x/y doesnt work, then try moving to the new x and keeping the old y. If that works, you can assume that your y is out of sync. That means that the wall is horizontal (going from 180 degrees to 360 degrees, if you look at it in wc3 angles) or you hit a corner.

Repeat again, this time keeping the old y and trying the x. If the item ends up at the same coordinates as you find, then you can assume you have a vertical wall (going from 90 degrees to 270) or a corner. If both x and y fail, then you are in a corner and to reflect properly, merely add pi to your angle, like so:

newAngle = oldAngle + PI

JASS:
private function CheckPathability takes real x, real y, real z returns int:
        real x2
        real y2
        bool checkX = false
        bool checkY = false
        if x > MAX_X or x < MIN_X:
            if y > MAX_Y or y < MIN_Y:
                return XY_BLOCKED
            else:
                return X_BLOCKED
        if y > MAX_Y or y < MIN_Y:
            return Y_BLOCKED
        call MoveRectTo(ItemRect, x, y)
        call EnumItemsInRect(ItemRect, FILTER_NULL, function HideItem)
        call SetItemPosition(ItemChecker, x, y)
        call SetItemPosition(ItemChecker, x, GetItemY(ItemChecker))
        set x2 = GetItemX(ItemChecker)
        if x2 + LEEWAY > x and x2 - LEEWAY < x then
            set checkX = true
        endif
        call SetItemPosition(ItemChecker, x, y)
        call SetItemPosition(ItemChecker, GetItemX(ItemChecker), y)
        set y2 = GetItemY(ItemChecker)
        if y2 + LEEWAY > y and y2 - LEEWAY < y then
            set checkY = true
        endif
        call EnumItemsInRect(ItemRect, FILTER_NULL, function ShowItem)
        call SetItemVisible(ItemChecker, false)
        if ((checkX and checkY) or (z >= GetZ(x, y) and not IsTerrainPathable(x, y, PATHING_TYPE_FLYABILITY))):
            return NOT_BLOCKED
        elseif checkX:
            return Y_BLOCKED       //Explanation: This function checks a spot, and 
        elseif checkY:         //determines if the X or the Y is blocked.
            return X_BLOCKED
        return XY_BLOCKED

JASS:
pathable = CheckPathability(x, y, z)
                        if pathable == Y_BLOCKED:
                            .AngleXY = TWOPI - .AngleXY
                        elif pathable == X_BLOCKED:
                            .AngleXY = PI  - .AngleXY
                        else:
                            .AngleXY += PI

Sorry for the fail non regular syntax, Im just copying parts of my projectile system at this point.

Good luck with your system/map.

I look forward to seeing if anyone else has a better solution, because I find the whole walls can only be horizontal or vertical limitation annoying.
 
Level 9
Joined
Nov 28, 2008
Messages
704
How does the game engine know to recognize the boundaries of the wall?

It doesnt. You use a dummy item, and try setting it to a location to check if it is pathable. If it is not, the wc3 engine automatically moves it to the nearest pathable location. I take advantage of that and try setting my dummy item to a location and checking if wc3 moved it. From there, if you look at my JASS, you can see that I can find out if its horizontal of vertical from there.
 
Level 9
Joined
Sep 5, 2007
Messages
358
» Mooglefrooglian
I already got a check pathability library to check the boundaries of the walls.
Your method may solve my problem, however I don't believe engines like SEE or maDOS uses that method to realisticaly bounces objects and I'm too scared of checking the code of those systems.

I've a moving system made in GUI that it collides and reflects accuretly, and the method it uses doesn't work in Jass, or maybe I did it wrong, if someone wants to see, I'll post it here.

» Justify
I'll go search for that GUI solution right away
 
Level 9
Joined
Sep 5, 2007
Messages
358
  • Moving system
    • Events
      • Time - Every 0.04 seconds of game time
    • Conditions
    • Actions
      • For each (Integer A) from biginInteger to number, do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • RunOrNO[(Integer A)] Equal to True
              • Or - Any (Conditions) are true
                • Conditions
                  • MovedDeath[(Integer A)] Equal to True
                  • (moved[(Integer A)] is alive) Equal to True
            • Then - Actions
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                • Then - Actions
                  • Set realMove[(Integer A)] = (realMove[(Integer A)] - realStop[(Integer A)])
                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    • If - Conditions
                      • MovedAvtoFacing[(Integer A)] Equal to True
                    • Then - Actions
                      • Custom script: set udg_p = GetUnitLoc(udg_moved[GetForLoopIndexA()])
                      • Custom script: call MoveLocation(udg_p, GetLocationX(udg_p) + udg_realMove[GetForLoopIndexA()] * CosBJ(GetUnitFacing(udg_moved[GetForLoopIndexA()])), GetLocationY(udg_p) + udg_realMove[GetForLoopIndexA()] * SinBJ(GetUnitFacing(udg_moved[GetForLoopIndexA()])))
                      • Unit - Move moved[(Integer A)] instantly to p
                      • Set MovedPozition[(Integer A)] = p
                    • Else - Actions
                      • Custom script: set udg_p = GetUnitLoc(udg_moved[GetForLoopIndexA()])
                      • Custom script: call MoveLocation(udg_p, GetLocationX(udg_p) + udg_realMove[GetForLoopIndexA()] * CosBJ(udg_MoveFacing[GetForLoopIndexA()]), GetLocationY(udg_p) + udg_realMove[GetForLoopIndexA()] * SinBJ(udg_MoveFacing[GetForLoopIndexA()]))
                      • Unit - Move moved[(Integer A)] instantly to p
                      • Set MovedPozition[(Integer A)] = p
                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    • If - Conditions
                      • MovedIsSnorads[(Integer A)] Equal to True
                    • Then - Actions
                      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                        • If - Conditions
                          • (Distance between (Position of moved[(Integer A)]) and MovedPozition[(Integer A)]) Greater than (realMove[(Integer A)] / 5.00)
                        • Then - Actions
                          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                            • If - Conditions
                            • Then - Actions
                              • Unit - Kill moved[(Integer A)]
                            • Else - Actions
                        • Else - Actions
                      • Set Picked_Units_Groop = (Units within MovedRang[(Integer A)] of (Position of moved[(Integer A)]))
                      • Unit Group - Pick every unit in Picked_Units_Groop and do (Actions)
                        • Loop - Actions
                          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                            • If - Conditions
                              • ((Picked unit) is alive) Equal to True
                              • (Picked unit) Not equal to moved[(Integer A)]
                              • (Picked unit) Not equal to MovedCaster[(Integer A)]
                            • Then - Actions
                              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                                • If - Conditions
                                • Then - Actions
                                  • Unit - Kill moved[(Integer A)]
                                  • Unit - Cause MovedCaster[(Integer A)] to damage (Picked unit), dealing MovedDamage[(Integer A)] damage of attack type Spells and damage type Normal
                                • Else - Actions
                            • Else - Actions
                    • Else - Actions
                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    • If - Conditions
                      • MoveOforON[(Integer A)] Equal to False
                      • realMove[(Integer A)] Less than 1.00
                    • Then - Actions
                      • Set RunOrNO[(Integer A)] = False
                      • Custom script: set udg_moved[GetForLoopIndexA()] = null
                      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                        • If - Conditions
                          • (Integer A) Equal to number
                          • number Greater than biginInteger
                        • Then - Actions
                          • Set number = (number - 1)
                          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                            • If - Conditions
                              • RunOrNO[number] Equal to False
                              • number Greater than biginInteger
                            • Then - Actions
                              • Set number = (number - 1)
                              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                                • If - Conditions
                                  • RunOrNO[number] Equal to False
                                  • number Greater than biginInteger
                                • Then - Actions
                                  • Set number = (number - 1)
                                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                                    • If - Conditions
                                      • RunOrNO[number] Equal to False
                                      • number Greater than biginInteger
                                    • Then - Actions
                                      • Set number = (number - 1)
                                      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                                        • If - Conditions
                                          • RunOrNO[number] Equal to False
                                          • number Greater than biginInteger
                                        • Then - Actions
                                          • Set number = (number - 1)
                                        • Else - Actions
                                    • Else - Actions
                                • Else - Actions
                            • Else - Actions
                        • Else - Actions
                    • Else - Actions
                • Else - Actions
            • Else - Actions
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                • Then - Actions
                  • Set RunOrNO[(Integer A)] = False
                  • Custom script: set udg_moved[GetForLoopIndexA()] = null
                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    • If - Conditions
                      • (Integer A) Equal to number
                      • number Greater than biginInteger
                    • Then - Actions
                      • Set number = (number - 1)
                      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                        • If - Conditions
                          • RunOrNO[number] Equal to False
                          • number Greater than biginInteger
                        • Then - Actions
                          • Set number = (number - 1)
                          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                            • If - Conditions
                              • RunOrNO[number] Equal to False
                              • number Greater than biginInteger
                            • Then - Actions
                              • Set number = (number - 1)
                              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                                • If - Conditions
                                  • RunOrNO[number] Equal to False
                                  • number Greater than biginInteger
                                • Then - Actions
                                  • Set number = (number - 1)
                                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                                    • If - Conditions
                                      • RunOrNO[number] Equal to False
                                      • number Greater than biginInteger
                                    • Then - Actions
                                      • Set number = (number - 1)
                                    • Else - Actions
                                • Else - Actions
                            • Else - Actions
                        • Else - Actions
                    • Else - Actions
                • Else - Actions
 
Status
Not open for further replies.
Top