Страницы

Поиск по вопросам

понедельник, 6 января 2020 г.

Проблема обработки пересечения Rectangle-ов (текстур)

#android #разработка_игр #libgdx


Делаю простенькую игрушку. Логика заключается в том, что у левого края экрана стоит
объект, назовем его человеком для удобства. У правого края хаотичным образом спавнятся
другие объекты, для удобства, назовем их зомби. Человек убивает их из постоянно стреляющего
автомата, "пули" которого при пересечении с "зомби" должны удалять "зомби" с экрана.

Проблема заключается в том, что эти "пули" просто пролетают мимо "зомби". То-есть,
я не могу отследить пересечения рендеров "пуль" и "зомби". 

Как я понял, проблема в многочисленном объявлении Rectangle-ов "зомби" и "пуль",
что приводит к неразберихе в коде и той проблеме, что у меня, в частности. Есть ли
возможность объявить его только 1 раз и потом всюду использовать? Если да, то как?

Кстати, просто объявить его на уровне на уровне класса, как тот же Rectangle человека
не получается, ибо вылетает NullPointerException, со ссылкой на spawncrowd и spavbullet.
Заранее спасибо_)

import com.badlogic.gdx.ApplicationAdapter;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input;

import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.math.MathUtils;
import com.badlogic.gdx.math.Vector3;
import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.TimeUtils;

import com.badlogic.gdx.math.Rectangle;
import java.util.Iterator;


public class  MyGdxGame extends ApplicationAdapter {
    OrthographicCamera camera;
    SpriteBatch batch;

    Texture manImage, bulletImage, CrowdImage;
    Rectangle manRect;
    Vector3 touchPos;
    Array bulletsArray, CrowdElemArray;

long lastbultime, lastcrowdeltime;
int counter_miss;

@Override
public void create () {

    camera = new OrthographicCamera();
    camera.setToOrtho(false, 960, 540);

    touchPos = new Vector3();

    batch = new SpriteBatch();

    manImage = new Texture("man.jpg");
    bulletImage = new Texture("bullet.jpg");
    CrowdImage = new Texture("Crowd.jpg");

    manRect = new Rectangle();
    manRect.x = 0;
    manRect.y = 540/2;
    manRect.height = 256;
    manRect.width = 256;

    CrowdElemArray = new Array();
    spawncrowdel();
    bulletsArray = new Array();
    spawnbullet();
}

public void spawncrowdel() {
    Rectangle CrowdelementRect = new Rectangle();
    CrowdelementRect.y = MathUtils.random(0, 540-256);
    CrowdelementRect.x = 960;
    CrowdelementRect.height = 256;
    CrowdelementRect.width = 64;
    CrowdElemArray.add(CrowdelementRect);
    lastcrowdeltime = TimeUtils.nanoTime();

}
public void spawnbullet() {
    Rectangle bulletRect = new Rectangle();
    bulletRect.y = manRect.getY() + manRect.height/2;
    bulletRect.x = manRect.getX();
    bulletRect.height = 256;
    bulletRect.width = 64;
    bulletsArray.add(bulletRect);
    lastbultime = TimeUtils.nanoTime();

}

@Override
public void render () {
    Gdx.gl.glClearColor(0, 1, 0.5f, 1);
    Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);

    camera.update();
    batch.setProjectionMatrix(camera.combined);

    batch.begin();

    batch.draw(manImage, manRect.x, manRect.y);

    for (Rectangle CrowdelementRect: CrowdElemArray) batch.draw(CrowdImage, CrowdelementRect.x,
CrowdelementRect.y);
    for (Rectangle bulletRect: bulletsArray) batch.draw(bulletImage, bulletRect.x,
bulletRect.y);

    batch.end();


    // Сенсорное урправление
    if (Gdx.input.isTouched()){
        touchPos.set(Gdx.input.getX(), Gdx.input.getY(), 0);
        camera.unproject(touchPos);
        manRect.y = (int) (touchPos.y - 128/2);
    }

    if (Gdx.input.isKeyPressed(Input.Keys.UP)) manRect.y += 200 * Gdx.graphics.getDeltaTime();
    if (Gdx.input.isKeyPressed(Input.Keys.DOWN)) manRect.y -= 200 * Gdx.graphics.getDeltaTime();


    if (manRect.y < 0) manRect.y = 0;
    if (manRect.y > 540-256) manRect.y = 540-256;

    //TODO Спавнинг зомби
    if (TimeUtils.nanoTime() - lastcrowdeltime > 2000000000) spawncrowdel();
    //TODO Спавнинг пули
    if (TimeUtils.nanoTime() - lastbultime > 800000000) spawnbullet();

    //TODO Движение зомби
    Iterator move = CrowdElemArray.iterator();
    while (move.hasNext()){
        Rectangle CrowdelementRect = new Rectangle();
        CrowdelementRect = move.next();
        CrowdelementRect.x -= 100 * Gdx.graphics.getDeltaTime();
        if (CrowdelementRect.x <= 10) {
            counter_miss += 1;
            move.remove();
        }
        if (CrowdelementRect.overlaps(manRect)) move.remove();
    }

    //TODO Движение пули
    Iterator movebul = bulletsArray.iterator();
    Rectangle CrowdelementRect = new Rectangle();
    while (movebul.hasNext()){
        Rectangle bulletRect = movebul.next();
        bulletRect.x += 100 * Gdx.graphics.getDeltaTime();
        if (bulletRect.x > 960) {
            movebul.remove();
        }
        if (bulletRect.overlaps(CrowdelementRect)) movebul.remove();
    }
}
@Override
public void dispose() {
    super.dispose();
    CrowdImage.dispose();
    manImage.dispose();
    bulletImage.dispose();
    batch.dispose();
}


}
`

PS

Делал все по шаблону со "стартандроида". 
    


Ответы

Ответ 1



Решение взято отсюда. Человек решает аналогичную задачу через следующий код: private void testCollision() { Iterator b = ball.iterator(); while(b.hasNext()) { Bullet balls = b.next(); Iterator i = enemy.iterator(); while(i.hasNext()) { Enemy enemies = i.next(); if ((Math.abs(balls.x - enemies.x) <= (balls.width + enemies.width) / 2f) && (Math.abs(balls.y - enemies.y) <= (balls.height + enemies.height) / 2f)) { i.remove(); b.remove(); } } } } когда-то пробовал сам - у меня работало.

Ответ 2



В классе Rectangle есть метод overlaps(Rectangle anotherRectangle) У путль есть массив и у "зомби" есть массив. Прогоняем массив пуль, если координата X пули < (screenWidth - zimbieWidth), то проверяем следующую пулю. Если условие не верно то данную пулю гоним по массиву зомби, где выполняем: for (int i = 0; i < zombies.size; i++) { if (bullet.overlaps(zombie.get(rect)[i])) { bullet.destroy(); zombie.destroy(); } }

Комментариев нет:

Отправить комментарий