0
\$\begingroup\$

I'm working on a 2D game and I've come across something strange which I've been working to fix the whole day but can't.

I'm trying to make an arrow fly, but modifying it's class affects my Player class. It seems that any Vector2 variable that is created changes the Player velocity somehow.

I have a GameObject class which all object classes extends from which looks like this:

public abstract class GameObject {

protected Vector2 position;
protected boolean isVisible = true;
protected Rectangle rectangle;
protected int width;
protected int height;
protected boolean solid;
protected float boundsOffset = 0;

public GameObject(Vector2 position) {
    this.position = position;
}

public Vector2 getPosition() {
    return position;
}

public void setPosition(Vector2 pos) {
    this.position = pos;
}

public boolean isVisible() {
    return isVisible;
}

public void setVisible(boolean b) {
    this.isVisible = b;
}

public Rectangle getBounds() {
    return new Rectangle(this.getPosition().x + boundsOffset, this.getPosition().y, (width * Main.SCALE) - boundsOffset, (height * Main.SCALE) - boundsOffset);
}

public Vector2 getCenter() {
    return new Vector2(position.x - (Width()/2), position.y + (Height()/2));
}

public Vector2 getTop() {
    return new Vector2(position.x - (Width()/2), position.y + (Height()));
}

public Vector2 getBottom() {
    return new Vector2(position.x - (Width()/2), position.y);
}

public void setWidth(int n) {
    width = n;
}

public void setHeight(int n) {
    height = n;
}

public int Width() {
    return width;
}

public int Height() {
    return height;
}

public boolean isSolid() {
    return solid;
}

public void setSolid(boolean b) {
    solid = b;
}

public void setBoundsOffset(float value) {
    boundsOffset = value;
}

public float getBoundsOffset() {
    return boundsOffset;
}

public abstract void update(float delta);

public abstract void render(SpriteBatch b);

}

I also have a Player class which I said previously, extends the GameObjects class. The Player movement works by using GameObjects position Vector2 and adding a Velocity vector which is declared in the Player class.

Heres the movement:

if(gs.getInputManager().isKeyDown(Keys.W)) {
        if(getVelocity().y < maxSpeed) {
            getVelocity().y += accel;
        } else {
            getVelocity().y = maxSpeed;
        }
        if(!rangedMode)
            setDirection(Main.DIR_UP);
    } else if(gs.getInputManager().isKeyDown(Keys.S)) {
        if(getVelocity().y > -maxSpeed) {
            getVelocity().y -= accel;
        } else {
            getVelocity().y = -maxSpeed;
        }
        if(!rangedMode)
            setDirection(Main.DIR_DOWN);
    } else {
        getVelocity().y -= Math.min(Math.abs(getVelocity().y), damp*Math.signum(getVelocity().y));
    }

    if(gs.getInputManager().isKeyDown(Keys.D) ) {
        if(getVelocity().x < maxSpeed) {
            getVelocity().x += accel;
        } else {
            getVelocity().x = maxSpeed;
        }
        if(!rangedMode)
            setDirection(Main.DIR_RIGHT);
    } else if(gs.getInputManager().isKeyDown(Keys.A)) {
        if(getVelocity().x > -maxSpeed) {
            getVelocity().x -= accel;
        } else {
            getVelocity().x = -maxSpeed;
        }
    } else {
        getVelocity().x -= Math.min(Math.abs(getVelocity().x), damp*Math.signum(getVelocity().x));
    }

getPosition().x += getVelocity().x;
getPosition().y += getVelocity().y;

And now to the problematic class, the Projectile class:

public class Projectile extends GameObject {

float speed = 3;
float travelDistance = 0;
float distanceTraveled = 0;
float angle;
Vector2 velocity = Vector2.Zero;
AnimatedSprite projectile;
boolean inAir = true;

public Projectile(Vector2 position, int type, float angle) {
    super(position);

    this.angle = angle;
    LoadItem(type);

}

private void LoadItem(int type) {
    switch(type) {
    case ItemID.WoodenArrow:
        speed = 3;
        travelDistance = 200;
        projectile = new AnimatedSprite(16, 5);
        projectile.isAnimating = false;
        projectile.currentFrame = AssetLoader.arrowRegions[0][0];
        projectile.setRotation(getAngle());
        projectile.setOrigin(32, 8);
        break;
    }

}

@Override
public void update(float delta) {
    velocity.x = (float) ((speed) * Math.cos(getAngle()));
    velocity.y = (float) ((speed) * Math.sin(getAngle()));
    this.setPosition(new Vector2(this.getPosition().x + velocity.x, this.getPosition().y + velocity.y));
}

public float getAngle() {
    return angle;
}

@Override
public void render(SpriteBatch b) {
    projectile.render(b, position);

     }
}

I update and render all my objects by adding them in a list and using a for loop. Now when I run the game my player starts sliding with the arrow. The funny thing is that I tried to do this with my Projectile class:

        @Override
    public void update(float delta) {
//      velocity.x = (float) ((speed) * Math.cos(getAngle()));
//      velocity.y = (float) ((speed) * Math.sin(getAngle()));
//      this.setPosition(new Vector2(this.getPosition().x + velocity.x, this.getPosition().y + velocity.y));
        velocity.x = 1;
        this.position.x += speed;
    }

And I would get the same thing. I even tried renaming the velocity vector to something completely random, but as soon as I assign a vector object a value the player gets affected.

I'm so sorry for just throwing a lot of code in your faces, but I felt that it was necessary since to me this problem is very strange, but I might just be blind and miss something completely obvious. Anyways thanks in advance!

\$\endgroup\$
0
\$\begingroup\$
Vector2 velocity = Vector2.Zero;

With that you are effectively assigning each object's velocity to the same vector object, instead you should create a new one for each object.

Vector2 velocity = new Vector2();

Like this.

\$\endgroup\$
  • \$\begingroup\$ Thank you, I've been working to fix this for a lot of hours now! I'm a little curious though as to how this behavior works? Why does a new field get assigned to another Vector? Thanks! \$\endgroup\$ – Dennis Björk Apr 22 '17 at 22:16
  • \$\begingroup\$ Vector2.Zero is just a static field inside Vector2 holding a vector with x and y equal to 0.0f. So by assigning the value of your velocity fields to this vector you will have the same Vector2 object across all instances of your Projectile. By updating them you are overriding the values for x and y of your velocity vector so in the end it just holds the values from the last calculation. Those are then used for setting the position, and because every Projectile has the same velocity vector with the same x and y all of them will move in the same way. \$\endgroup\$ – cozmic Apr 23 '17 at 6:33
0
\$\begingroup\$

In your abstract class, you are using a Vector2 which will be shared by all the subclasses due to how Vector2s work in LibGdx. In order to prevent this, you need to make a copy of the Vector being passed into your abstract class.

public GameObject(Vector2 position) {
    this.position = position.cpy();
}
\$\endgroup\$
  • \$\begingroup\$ Thanks for your response! I've already treid this, but itdid sadly not solve it. In my Projectile update, simply adding "position.x += 1" works like a charm, it's only when i declare a new vector2 and add a value to it in the class which breaks the game. \$\endgroup\$ – Dennis Björk Apr 21 '17 at 23:01
  • \$\begingroup\$ could it be a problem with Eclipse itself? \$\endgroup\$ – Dennis Björk Apr 22 '17 at 11:25

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.