Arrow Ballistic + Collision issue + Pos Issue + Slow Method?

Hi guys… Im having an issue with My 2D Game.

My game is about an archer.
I already have the TMX and items etc.

I shoot the arrow and hmm… Well, i changed the gravity and velocity of the arrow to balance it.
And, well, it kinda worked BUT, since the functions that i use request the time as a parameter, the Ypos Changes between each time makes the collision hard to check…

[quote]Arrow Shot
Arrow x;y 0 = { + 497;501} Angle : 1.3555892098163311
Arrow = 497.08328441112764;501.3809525522973
Arrow = 497.24985323338296;502.1427556568918
Arrow = 497.49970646676593;503.28530731378356
Arrow = 497.8328441112766;504.80850552297255
Arrow = 498.2492661669149;506.7122482844588
Arrow = 498.74897263368086;508.9964335982422
Arrow = 499.3319635115745;511.66095946432296
Arrow = 499.99823880059574;514.705723882701
Arrow = 500.7477985007447;518.1306248533762
Arrow = 501.5806426120213;521.9355603763487
Arrow = 502.49677113442556;526.1204284516184
Arrow = 503.4961840679575;530.6851270791853
Arrow = 504.578881412617;535.6295542590495
Arrow = 505.74486316840427;540.953607991211
Arrow = 506.99412933531914;546.6571862756697
Arrow = 508.3266799133617;552.7401871124256
Arrow = 509.7425149025319;559.2025085014787
Arrow = 511.2416343028298;566.0440484428292
Arrow = 512.8240381142554;573.2647049364768
[/quote]
Thats just a small quote for the sake of it.

Well.

Heres a little video test of it :

package br.weapons;

import com.badlogic.gdx.graphics.g2d.Sprite;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;

public class Arrow {

    public int type_Arrow;
    public double posX, posY;
    public int damage;
    public double angle;
    public Sprite sprite;
    
    
    public final int light_Arrow = 0;
    public final int heavy_Arrow = 1;
    public final int fire_Arrow = 2;
    public final int ice_Arrow = 3;
    
    public double frameTime;

    public Arrow(double posX, double posY,double angle) {
        this.posX = posX;
        this.posY = posY;
        this.angle = angle;
        frameTime = 0;

    }
    
    public void render(SpriteBatch sb)
    {
        sb.draw(sprite,(float) posX,(float) posY);
    }

    
    public void update()
    {
        
        frameTime = frameTime + 0.001;
        posX = ArrowBallistic.getSX(posX,posY, ArrowBallistic.vo, ArrowBallistic.gravity,angle,frameTime);
        posY = ArrowBallistic.getSY(posY, ArrowBallistic.vo, ArrowBallistic.gravity,angle,frameTime);
        
        System.out.println("Arrow = " + posX + ";" + posY);
        
    }
    


}

package br.weapons;

/**
 *
 */
public class ArrowBallistic {

    private static int normal = 1; //TEST
    public static double vo = (60 * 6.5)/normal;
    public static double gravity = (60 * 1.7)/normal;

    public static double getAngle(double xi, double xf, double yi, double yf) {

        double atan = Math.atan((yi - yf) / (xi - xf));

        return atan;
    }

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

        return dx;
    }

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

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

        return dy;
    }
}

I have a list of Arrow in player Class. And i use them.

package br.player;

public class Player extends Sprite implements InputProcessor {
....    
    @Override
    public void draw(SpriteBatch spriteBatch) {
    
         .....

        for (int i = 0; i < playerWeapon.arrows.size(); i++) {
            Arrow arrow_TEMP = playerWeapon.arrows.get(i);
            arrow_TEMP.update();
            arrow_TEMP.render(spriteBatch);

        }

    }

Please, i really need help!

It would be good to know at wich frame rate your update() happens. Do you calculate delta time between the updates? If yes you could use the delta value to calculate the distance the arrow flew after the last update. Then you could check for collisions based on the distance. Or do i get you completely wrong? xD

That seems a good idea… i will have to think on how i might do that.

Hmm, seems to me like you’re doing it wrong or at the very least doing it weird.

You’re having a separate frame counter for every arrow and you calculate the arrows next position by incrementing the counter, like you say, “since the functions that i use request the time as a parameter”, as if straight from a physics text book of calculating a projectiles (an Arrow in this case) position at any given time t (frameTime in this case).

Instead you could calculate the required speed and/or angle for the arrow to reach your desired point (e.g. mouse_x, mouse_y) and “let the arrow loose” so to speak in your game loop where it should be for proper movement (delta or not), collision detection etc.

“you could calculate the required speed and/or angle for the arrow to reach your desired point (e.g. mouse_x, mouse_y) and “let the arrow loose” so to speak in your game loop where it should be for proper movement (delta or not), collision detection etc.”

i dont get it… how would that be possible??

With maths http://en.wikipedia.org/wiki/Trajectory_of_a_projectile#Angle_required_to_hit_coordinate_.28x.2Cy.29

Here’s a basic template that shoots directly towards the target (doesn’t arch smartly like the above wiki explains to reach its target)

import java.awt.Canvas;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.image.BufferStrategy;
import java.util.ArrayList;
import java.util.List;

import javax.swing.JFrame;

class Main extends Canvas implements Runnable {

	public final int WIDTH = 300;
	public final int HEIGHT = (WIDTH * 9) / 16;
	public final JFrame jframe;

	List<Arrow> arrows = new ArrayList<Arrow>();
	List<Arrow> swap = new ArrayList<Arrow>();
	List<Arrow> newArrows = new ArrayList<Arrow>();

	public static final double gravity = 0.1;

	public Main() {
		Dimension size = new Dimension(WIDTH, HEIGHT);
		this.setSize(size);

		jframe = new JFrame();
		jframe.add(this);
		jframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		jframe.setMinimumSize(size);

		jframe.pack();
		jframe.setVisible(true);

		this.addMouseListener(new MouseAdapter() {
			@Override
			public void mouseReleased(MouseEvent e) {
				fireArrow(e.getPoint());
			}
		});
		new Thread(this).start();
	}

	private void fireArrow(Point p) {
		Arrow a = new Arrow(p);
		newArrows.add(a);
	}

	class Arrow {
		double x = WIDTH / 2;
		double y = HEIGHT - HEIGHT / 10;
		int r = 2; // radius

		double xSpeed;
		double ySpeed;

		boolean removed = false;
		boolean removeMe = false;
		long timeOfDeath = System.currentTimeMillis();
		long despawnTime = 1000 * 10; // 10 seconds

		public Arrow(Point destination) {
			/* figure out angle to reach destination:
			 * http://en.wikipedia.org/wiki/Trajectory_of_a_projectile#Angle_required_to_hit_coordinate_.28x.2Cy.29
			 */
			
			// Basic shoot straight towards target.
			double speed = 4;
			double dx = destination.x - this.x;
			double dy = destination.y - this.y;
			
			double angle = Math.atan2(dy, dx);
			
			xSpeed = Math.cos(angle) * speed;
			ySpeed = Math.sin(angle) * speed;
		}

		public void tick() {
			if (removed) {
				long now = System.currentTimeMillis();
				if (now - timeOfDeath > despawnTime) {
					removeMe = true;
				}
				return;
			}

			ySpeed += gravity;

			x += xSpeed;
			y += ySpeed;

			if (y > getHeight() - r) {
				removed = true;
				timeOfDeath = System.currentTimeMillis();
				y = getHeight() - r;
			}
		}

		public void render(Graphics g) {
			int hr = r >> 1;
			g.drawRect((int) x - hr, (int) y - hr, (int) r, (int) r);
		}
	}

	@Override
	public void run() {
		while (true) {

			tick();
			render();

			try {
				Thread.sleep(33);
			} catch (InterruptedException ie) {
			}
		}
	}

	private void tick() {
		for (Arrow a : newArrows) {
			arrows.add(a);
		}
		newArrows.clear();

		for (Arrow a : arrows) {
			a.tick();
			if (!a.removeMe)
				swap.add(a);
		}
		List<Arrow> t = arrows;
		arrows = swap;
		swap = t;
		t.clear();
	}

	private void render() {
		BufferStrategy bs = this.getBufferStrategy();
		if (bs == null) {
			this.createBufferStrategy(2);
			return;
		}

		Graphics g = bs.getDrawGraphics();
		g.setColor(Color.DARK_GRAY);
		g.fillRect(0, 0, this.getWidth(), this.getHeight()); // clear screen
		g.setColor(Color.WHITE);

		// draw arrows
		for (Arrow a : arrows) {
			a.render(g);
		}

		g.dispose();
		bs.show();
	}

	public static void main(String[] args) {
		new Main();
	}
}