Java-Gaming.org    
Featured games (91)
games approved by the League of Dukes
Games in Showcase (581)
games submitted by our members
Games in WIP (500)
games currently in development
News: Read the Java Gaming Resources, or peek at the official Java tutorials
 
    Home     Help   Search   Login   Register   
Pages: [1]
  ignore  |  Print  
  Arrow Ballistic - Something is Wrong and Feel Unrealistic  (Read 545 times)
0 Members and 1 Guest are viewing this topic.
Offline Andre Lopes
« Posted 2014-01-07 21:59:18 »

Hello.I have a big problem here, i dont know if anyone can actually spend some time helping me.
I dont have classes until 4/february and last year i spent some time off-classes with him , well he teached me alot about it. I tried my best to absorb everything, and i did absorb like 80% of the knowledge he passed me. But, im being slow in this movingAngle part, what i mean with that (will try my best to explain it in english).

When the arrow is shot, it starts a    parabola movement , so, first i need to set the angle of the shot,

1  
  sprite.setRotation((float) Math.toDegrees(shotAngle));


First of, i want to say that, if i only use the shotAngle, i get an almost-perfect simulation.But then again i come with two stupid problems :

-First, im unsure how to make the arrow perform the parabola.Im unsure how to set the gravity and the velocity to make it reasonable.

-Second, when i activate the code to set the moving angle, weird things happens :

*Watch in 480p or + for better reading.

http://www.youtube.com/watch?v=j1ODvCb1S1c

The video Debug complete output is here :
http://sharetext.org/yO3y

Thats what happens,its like, the movingAngle Code is projecting a not-happening parabola. Its like a different one.

So.
Thats my issue. Any Tip or piece of knowledge , anything is welcome.I need start fixing from somewhere/something (tip) .


Video Showing only shot-Angle Working :
http://www.youtube.com/watch?v=RjgjjkjASlw


Now The Classes im Using , they are a bit Huge, so i will try to point the methods im Using :

Below, Its the Arrow Class, which LightArrow Class Extends to.
The Update Method and Render Method Are Used each frame.
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
33  
34  
35  
36  
37  
38  
39  
40  
41  
42  
43  
44  
45  
46  
47  
48  
49  
50  
51  
52  
53  
54  
55  
56  
57  
58  
59  
60  
61  
62  
63  
64  
65  
66  
67  
68  
69  
70  
71  
72  
73  
74  
75  
76  
77  
78  
79  
80  
81  
82  
83  
84  
85  
86  
87  
88  
89  
90  
91  
92  
93  
94  
95  
96  
97  
98  
99  
100  
101  
102  
103  
104  
105  
106  
107  
108  
109  
110  
package br.weapons;
public class Arrow {

    private static int xVertice = -1;

    public int type_Arrow;
    public float posX, posY, shotPosX;
    public int damage;
    public double shotAngle, movingAngle;
    private boolean shotAngleUsed = false;
    public Sprite sprite;
    public int manaWaste = 0;

    public int shotToQuadrant = -1;

    public double time;

    public Vector3 touch;
    public Vector2 vector;

    public boolean isInsideWindow;

    public boolean hit = false;
    public boolean toRemoveThis = false;
    public SmokeEffect smokeEffect;

    private TiledMapTileLayer.Cell Cell_Temp;

    public Arrow(double posX, double posY, double angle, int quadrant) {
        shotPosX = (int) posX;

        this.posX = (int) posX;
        this.posY = (int) posY;
        this.shotAngle = angle;

        time = 0;
        isInsideWindow = true;

        smokeEffect = new SmokeEffect();
        damage = 0;
        shotToQuadrant = quadrant;
        touch = new Vector3();
        vector = new Vector2();
        //System.out.println("Shot To Quadrant : " + shotToQuadrant);

    }

    public void render(SpriteBatch sb) {
        if (hit) {
            smokeEffect.render(sb, posX, posY);
            if (smokeEffect.isFinished()) {
                toRemoveThis = true;
            }
        } else {
            if (toRemoveThis == false) {
                //System.out.println("Sprite Rotation" + (float) toDegrees(shotAngle));

                sprite.setPosition(posX, posY);
                sprite.draw(sb);

            }
        }
    }

    public void update(TiledMapTileLayer collisionLayer, Camera camera) {
        if (hit == false) {

            lookNearbyCells(collisionLayer);

            System.out.println("\n &Arrow Update&");
            System.out.println("Update Tick :" + time);

            posX = (float) ArrowBallistic.getSX(posX, posY, ArrowBallistic.vo, ArrowBallistic.gravity, shotAngle, time);
            posY = (float) ArrowBallistic.getSY(posY, ArrowBallistic.vo, ArrowBallistic.gravity, shotAngle, time);

            //Fix Needed
           movingAngle = ArrowBallistic.getMovingAngle(shotAngle, shotPosX, posX, shotToQuadrant);

            System.out.println("Moving Angle : " + movingAngle);
            System.out.println("posX : " + posX);
            System.out.println("posY : " + posY);
            System.out.println("Shot Angle :" + shotAngle);

            if (!shotAngleUsed) {
                sprite.setRotation((float) Math.toDegrees(shotAngle));
                shotAngleUsed = true;
            } else {
                sprite.setRotation((float) Math.toDegrees(movingAngle));
            }
           
            time += 0.1;    //0.001

            touch.set(posX, posY, 0);
            camera.project(touch);
            vector.set(touch.x, touch.y);

            isInsideWindow = (vector.x > (-Gdx.graphics.getWidth()) && vector.x < (Gdx.graphics.getWidth() * 2)) && (vector.y > (-Gdx.graphics.getHeight()));

            if (!isInsideWindow) {

                toRemoveThis = true;

            }

        }
    }

    public boolean isIsInsideWindow() {
        return isInsideWindow;
    }




Below Now, its the ArrowBallistic Class, which i use to make the Math.

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
33  
34  
35  
36  
37  
38  
39  
40  
41  
42  
43  
44  
45  
46  
47  
48  
49  
50  
51  
52  
53  
54  
55  
56  
57  
58  
59  
60  
61  
62  
63  
64  
65  
66  
67  
68  
69  
70  
71  
72  
73  
74  
75  
76  
77  
78  
79  
80  
81  
82  
83  
84  
85  
86  
87  
88  
89  
90  
91  
92  
93  
94  
95  
96  
package br.weapons;

/**
 * AndrĂ© V Lopes
 */

public class ArrowBallistic {

    private static int normal = 1; //TEST
   public static double vo = 20 / normal;
    public static double gravity = 2 / normal;

    public static int FIRST_QUADRANT = 1;
    public static int SECOND_QUADRANT = 2;
    public static int THIRD_QUADRANT = 3;
    public static int FOURTH_QUADRANT = 4;

    private static double atan = 0;
    private static double dx, dy;

    public static double getAngle(double posXplayer, double xClick, double posYPlayer, double yClick) {

        if (xClick < posXplayer && yClick < posYPlayer) {
            atan = Math.PI + (Math.atan((posYPlayer - yClick) / (posXplayer - xClick)));
        } else if (xClick >= posXplayer && yClick >= posYPlayer) {

            atan = Math.atan((posYPlayer - yClick) / (posXplayer - xClick));
        } else if (xClick < posXplayer && yClick >= posYPlayer) {

            atan = Math.PI - (Math.atan((yClick - posYPlayer) / (posXplayer - xClick)));

        } else if (xClick > posXplayer && yClick < posYPlayer) {
            atan = (2 * Math.PI) - (Math.atan((yClick - posYPlayer) / (posXplayer - xClick)));
        } else {
            atan = 0;
        }

        return atan;
    }

    public static double getSX(double xo, double yo, double vo, double gravity, double angle, double time) {
        dx = (xo) + vo * Math.cos(angle) * time;

        return dx;
    }

    public static double getSY(double yo, double vo, double gravity, double angle, double time) {

        dy = yo + vo * (Math.sin(angle) * time) - ((gravity / 2) * (time * time));

        return dy;
    }

    public static double getMovingAngle(double angle, double xo, double sx, int shotToQuadrant) {

        double tanO = 0;

        if (shotToQuadrant == FIRST_QUADRANT) {
            tanO = Math.atan(Math.tan(angle) - (gravity / ((vo * vo) * (Math.cos(angle) * Math.cos(angle)))) * (sx - xo));
        } else if (shotToQuadrant == SECOND_QUADRANT) {
            tanO = Math.atan(Math.PI / 2 + (Math.tan(angle) - (gravity / ((vo * vo) * (Math.cos(angle) * Math.cos(angle)))) * (sx - xo)));
        } else if (shotToQuadrant == THIRD_QUADRANT) {
            tanO = Math.atan(Math.PI + (Math.tan(angle) - (gravity / ((vo * vo) * (Math.cos(angle) * Math.cos(angle)))) * (sx - xo)));
        } else if (shotToQuadrant == FOURTH_QUADRANT) {
            tanO = Math.atan(Math.PI * 2 + (Math.tan(angle) - (gravity / ((vo * vo) * (Math.cos(angle) * Math.cos(angle)))) * (sx - xo)));
        }

        //Change quadrant Calculations
       if (shotToQuadrant == FIRST_QUADRANT && sx <= getXVertice(angle, gravity, vo, xo, sx)) {
            shotToQuadrant = FOURTH_QUADRANT;
        } else if (shotToQuadrant == SECOND_QUADRANT && sx <= getXVertice(angle, gravity, vo, xo, sx)) {
            shotToQuadrant = THIRD_QUADRANT;
        }

        return tanO;
       
       
       
    }

    public static double getXVertice(double angle, double gravity, double velocity, double xo, double dx) {
        double xv = 0;
        double b = 0;
        double a2 = 0;

        //-b
       b = -((xo * gravity) / ((velocity * velocity) * (Math.cos(angle) * Math.cos(angle))));

        //2a
       a2 = 2 * (-gravity / ((2 * (velocity * velocity)) * Math.cos(angle) * Math.cos(angle)));

        xv = b / a2;

        return xv;
    }

}




I hope this isnt too complicated for anyone to help me.

I am working on this project "by-myself", i get help from friends here or in chat or my teachers but its just me, so i hope you understand that im really trying.

Thanks Smiley
Offline Andre Lopes
« Reply #1 - Posted 2014-01-07 22:12:55 »

While you continue to troubleshoot this and await additional comments, I recommend that you refactor the math where you are multiplying variables by themselves at a minimum.

Then I recommend turning all "magic numbers" into organized, self-describing variables or constants coded inline or externalized in a file (db, etc.) and allow for real-time reload so you can test on-the-fly.

Then you can tweak behavior to see how modifying your reality-shaping "constants" affect the verisimilitude of something like an arrow in flight.

This is potentially another development tool in the ol' toolbox when a theorized algorithm does not provide what you expect.

And even if it becomes clear--or someone points out where the algorithm is flawed--you can still benefit from what-if scenarios like the above enables because you can then introduce "game-y" variations, power-ups, environmental factors, etc., that alter how an intuitively understood (physics) behavior is presented.

I love you dude, great idea! Working on it now, i was working in levels code, but im halting it!

Ok, i will make it read the file every frame just for debug purpose, so i can change it!

Thanks!!!!!
Offline Andre Lopes
« Reply #2 - Posted 2014-01-07 23:17:53 »

Awesome...have fun!   Grin
Im tweaking it, seems fun! But im still having problems with movingAngle.
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline Andre Lopes
« Reply #3 - Posted 2014-01-08 01:41:59 »

Well i was able to make it slower.

1  
2  
3  
 
   public static double vo = 2;
   public static double gravity = 0.02;


And now i increment time in 1.0++

1  
2  
 
time += 1;



Should make things more readable.

Aside from that, i will have to find more theory knowledge.
Offline Axeman

Senior Member


Medals: 7



« Reply #4 - Posted 2014-01-08 02:13:25 »

I would try increasing your gravity first to 10 and then to 100, just to see if the arrow is actually going down at all. If it does then you know your calculations are correct and you can figure out how to tweak your numbers. Or do something simpler. The code for shooting an arrow does look overly complicated.
Offline Andre Lopes
« Reply #5 - Posted 2014-01-08 02:53:01 »

It does work, though the parabola seems.. weird.

Was my Engineer Teacher who teached me all the math.
He checked the code last year and said it was ok, except the movingAngle, which is incomplete if i shoot to the left side.

I will try to link him this post by email and see what he thinks.Just didnt want to bother him since hes too busy.
Offline saucymeatman
« Reply #6 - Posted 2014-01-08 02:53:56 »

Is all that complicated/hardToDebug math REALLY nesasary?
Why not :

(Assume)
xMomentum = 30;
yMomentum = 5;
gravity = .1;
airResistance = .975;

(Every Frame/Tick)
arrow.move(xMomentum, yMomentum);
yMomentum -= gravity;
xMomentum *= airResistance;
yMomentum *= airResistance;
Offline Varkas
« Reply #7 - Posted 2014-01-08 12:41:34 »

Basically you'll want to implement a time-discrete version of this formula:

p = a * t * t + v0 * t + p0

t is the time since the moment when the projectile was fired.
The other variables are vector types of the space in which the projectile travels.

p0 = starting position of the projectile
v0 = initial velocity of the projectile
a = acceleration (e.g. gravity or thrust) of the projectile

This is fairly realistic with exception of air or other media resistance and while the speed isn't very close to the speed of light. It also assumes a flat space.

if (error) throw new Brick(); // Blog (german): http://gedankenweber.wordpress.com
Offline StumpyStrust
« Reply #8 - Posted 2014-01-08 15:13:43 »

Good old way is to simply

1  
2  
3  
4  
5  
6  
7  
Vector2 pos,vel,accl;

public void method()
{
vel += acc;
pos += vel;
}

accl is gravity/other forces.


Launch the  arrow via
1  
2  
3  
4  
5  
float angle = 45;
float speed = 12;

vel.x = Math.cosDeg(angle)*speed;
vel.y = Math.sinDeg(angle)*speed;


This is not for say, "click this spot arrow moves to that spot along a cure" but "launch arrow with this velocity and seed what happens given wind and gravity."


All code is pseudo code.

Offline Andre Lopes
« Reply #9 - Posted 2014-01-11 02:14:53 »

I printed this topic, i will review this with my teacher and compare to our code/idea.

Thanks all! I will post again once i have some new "floor".


Thanks a lot! You guys are awesome for sharing knowledge Smiley
Pages: [1]
  ignore  |  Print  
 
 

 

Add your game by posting it in the WIP section,
or publish it in Showcase.

The first screenshot will be displayed as a thumbnail.

xsi3rr4x (53 views)
2014-04-15 18:08:23

BurntPizza (51 views)
2014-04-15 03:46:01

UprightPath (65 views)
2014-04-14 17:39:50

UprightPath (48 views)
2014-04-14 17:35:47

Porlus (65 views)
2014-04-14 15:48:38

tom_mai78101 (89 views)
2014-04-10 04:04:31

BurntPizza (149 views)
2014-04-08 23:06:04

tom_mai78101 (245 views)
2014-04-05 13:34:39

trollwarrior1 (203 views)
2014-04-04 12:06:45

CJLetsGame (210 views)
2014-04-01 02:16:10
List of Learning Resources
by SHC
2014-04-18 03:17:39

List of Learning Resources
by Longarmx
2014-04-08 03:14:44

Good Examples
by matheus23
2014-04-05 13:51:37

Good Examples
by Grunnt
2014-04-03 15:48:46

Good Examples
by Grunnt
2014-04-03 15:48:37

Good Examples
by matheus23
2014-04-01 18:40:51

Good Examples
by matheus23
2014-04-01 18:40:34

Anonymous/Local/Inner class gotchas
by Roquen
2014-03-11 15:22:30
java-gaming.org is not responsible for the content posted by its members, including references to external websites, and other references that may or may not have a relation with our primarily gaming and game production oriented community. inquiries and complaints can be sent via email to the info‑account of the company managing the website of java‑gaming.org
Powered by MySQL Powered by PHP Powered by SMF 1.1.18 | SMF © 2013, Simple Machines | Managed by Enhanced Four Valid XHTML 1.0! Valid CSS!