Астероиды libGDX уравнения косинуса и вращения синусов, стрельба пулями под неправильным углом - PullRequest
0 голосов
/ 09 июня 2018

Я сделал игру «Астероиды» для устройства Android, но с трудом заметил, что игрок стоит в каком-то направлении, но стреляет из пули в другом слегка смещенном направлении.Я просмотрел код, и это происходит только тогда, когда игрок ускоряется и вращается.Не когда игрок только вращается.Я надеюсь, что этого кода достаточно, чтобы рассказать вам кое-что об этом, чтобы дать мне совет.

Игрок вращается в правильном направлении, а пуля - нет.Я пытался разместить функции обновления в разных порядках, но это тоже не помогло.Я не вижу, в чем проблема, потому что при стрельбе класс игрока создает пулю каждый раз с радианами от игрока.Так что я думаю, что это как-то связано с тем, что радианы не обновляются при запуске пули.

private void initForces() {
    maxSpeed = 300;
    acceleration = 200;
    friction = 10;
}

private void initRotationSpeed() {
    // Radians are used to determine the angle the player points in
    radians = MathUtils.PI / 2;

    rotationSpeed = 3;
}

public void shoot() {
    final int MAX_BULLETS = 4;
    if (bullets.size() == MAX_BULLETS || isHit()) return;
    bullets.add(new Bullet(x, y, radians));
}

   public void update(float dt) {
        if (updateCheckIfPlayerHit(dt)) {
            return;
        }

        updateCheckExtraLives();

        // Forces
        updateAcceleration(dt);
        updateRotationSpeed(dt);
        updateTurning(dt);
        updateFriction(dt);

        // Set shape
        setShape();

        // Screen wrap
        wrap();
    }

   private void updateTurning(float dt) {
        // Turning: Tilt the screen to left or right to rotate the ship
        final float ROTATION_SENSITIVITY = 3;
        if (left || Gdx.input.getAccelerometerX() > ROTATION_SENSITIVITY) {
            radians += rotationSpeed * dt;
        }
        else if (right || Gdx.input.getAccelerometerX() < -ROTATION_SENSITIVITY) {
            radians -= rotationSpeed * dt;
        }
    }

    private void updateRotationSpeed(float dt) {
        x += dx * dt;
        y += dy * dt;
    }

    private void updateAcceleration(float dt) {
        // Accelerating
        if (up || Gdx.input.isTouched() && Gdx.input.getX() > 0 && Gdx.input.getX() < Gdx.graphics.getWidth() / 2) {
            dx += MathUtils.cos(radians) * acceleration * dt;
            dy += MathUtils.sin(radians) * acceleration * dt;
        }
    }

    private void updateFriction(float dt) {
        // Friction
        float vector = (float)Math.sqrt(dx * dx + dy * dy);
        if (vector > 0) {
            dx -= (dx / vector) * friction * dt;
            dy -= (dy / vector) * friction * dt;
        }

        if (vector > maxSpeed) {
            dx = (dx / vector) * maxSpeed;
            dy = (dy / vector) * maxSpeed;
        }
    }

Bullet.java

package com.mygdx.entities;

import com.badlogic.gdx.graphics.glutils.ShapeRenderer;
import com.badlogic.gdx.math.MathUtils;

public class Bullet extends SpaceObject {

    private float lifeTime;
    private float lifeTimer;

    private boolean remove;

    Bullet(float x, float y, float radians) {
        this.x = x;
        this.y = y;
        this.radians = radians;

        float speed = 350;
        dx = MathUtils.cos(radians) * speed;
        dy = MathUtils.sin(radians) * speed;

        width = height = 2;

        lifeTimer = 0;
        lifeTime = 1;
    }

    public boolean shouldRemove() {
        return remove;
    }

    public void update(float dt) {

        updateRotationSpeed(dt);
        wrap();

        updateLifeTime(dt);
    }

    private void updateRotationSpeed(float dt) {
        x += dx * dt;
        y += dy * dt;
    }

    private void updateLifeTime(float dt) {
        // How long time the bullet is supposed to live
        lifeTimer += dt;
        if (lifeTimer > lifeTime) {
            remove = true;
        }
    }

    public void draw(ShapeRenderer shapeRenderer) {
        shapeRenderer.setColor(1, 1, 1, 1);
        shapeRenderer.begin(ShapeRenderer.ShapeType.Line);
        shapeRenderer.circle(x - width / 2, y - height / 2, width / 2);
        shapeRenderer.end();
    }

}

И для стрельбы игроком код:

    if (Gdx.input.justTouched() &&
                    Gdx.input.getX() > Gdx.graphics.getWidth() / 2 &&
                    Gdx.input.getX() < Gdx.graphics.getWidth()) {
        player.shoot();
    }

1 Ответ

0 голосов
/ 12 июня 2018

Ответ на мой вопрос в том, что я немного забыл математику.Так что в конструкторе Bullet у меня нет скорости игрока в направлении x или y, поэтому я сделал две статические переменные в классе Player и установил их равными dx и dy игрока в функции обновления скорости вращения.Обе эти переменные являются числами с плавающей точкой.

private void updateRotationSpeed(float dt) {
    x += dx * dt;
    y += dy * dt;

    dxStatic = dx;
    dyStatic = dy;
}

public static float getPlayerDeltaX() {
    return dxStatic;
}

public static float getPlayerDeltaY() {
    return dyStatic;
}

В конструкторе класса Bullet мне нужно было добавить следующее:

Bullet(float x, float y, float radians) {
    this.x = x;
    this.y = y;
    this.radians = radians;

    float speed = 350;
    dx = speed * MathUtils.cos(radians) + Player.getPlayerDeltaX();
    dy = speed * MathUtils.sin(radians) + Player.getPlayerDeltaY();

    width = height = 2;

    lifeTimer = 0;
    lifeTime = 1;
}

Итак, именно это заставило пули двигаться внемного другое направление.

РЕДАКТИРОВАТЬ: Или вы можете просто добавить некоторые переменные с плавающей точкой в ​​конструктор Bullet и взять dx и dy игрока, так как пуля создается каждый раз внутри класса игрока.В моем случае это как минимум.Это может быть лучшей альтернативой.

Bullet(float x, float y, float playerDeltaX, float playerDeltaY, float radians) {
    this.x = x;
    this.y = y;
    this.radians = radians;

    float speed = 350;
    dx = speed * MathUtils.cos(radians) + playerDeltaX;
    dy = speed * MathUtils.sin(radians) + playerDeltaY;

    width = height = 2;

    lifeTimer = 0;
    lifeTime = 1;

}
...