Страницы

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

Показаны сообщения с ярлыком libgdx. Показать все сообщения
Показаны сообщения с ярлыком libgdx. Показать все сообщения

воскресенье, 26 января 2020 г.

Загрузка и хранение изображений в Java

#java #изображения #разработка_игр #libgdx


У меня есть определенная текстура var1.jpg, и необходимо вывеси ее на экран. Проблема
в том, что если при инициализации переменной, хранящей текстуру, указать просто var1.jpg,
то программа файл не находит, а если указать полный путь, то все норм.

Собственно, сам вопрос: как сделать так, чтобы текстура вызывалась, к примеру, из
пакета, который будет находиться внутри самой программы? То есть чтобы в итоге получилось
так: есть программа program.jar, в которой есть 2 пакета - com.start и com.image; при
работе программа загружала изображения, лежащие в com.image, а сами классы программы
находились в com.start, при этом не важно, в какой директории находится непосредственно
program.jar.
    


Ответы

Ответ 1



Точно не скажу, путь должен быть примерно таким "src\com\image\var1.jpg"

пятница, 24 января 2020 г.

Как рисовать много объектов без потери производительности? Java

#java #разработка_игр #оптимизация #libgdx


Всем привет, я начинающий developer пишущий разные игры и приложения на java (практикуюсь,
нарабатываю навыки). Меня давно преследует проблема рисования большого количества объектов.
Все они сильно тормозят игровой процесс, даже если не обновляются, я конечно понимаю,
что метод перерисовки играет и роль обновления, но если вызывать метод отрисовки только
при создании объекта, он сразу перекрывается фоном приложения, который стирает всю
остаточную мишуру. Но ведь люди как-то это делают - ниже будет пример. В данном примере
объекты не просто лежат на поле, но и имеют свой hit-box судя по всему, так как при
коллизии с ними, игрок оставляет след. Я бы хотел достичь примерно такого результата,
и прошу всех кто знаком с данной проблемой поделится материалом или своим опытом. Возможно
моя проблема заключается в самом алгоритме отрисовки, но так как я новичок, как сделать
лучше пока не знаю. Буду очень признателен! 
На данный момент стараюсь разобраться в libGDX, с целью поиска большей оптимизации,
но видимо проблема кроется во мне... 
        
    


Ответы

Ответ 1



Как рисовать много объектов без потери производительности? Общие техники оптимизации При отрисовке кадра в очень много времени занимает вызов функции отрисовки. Поэтому первое что делаю для ускорение графические движки - бачинг. Бачинг - это процесс группировки объектов которые могут быть отрисованы в один подход. Например, в системе частиц вместо того чтобы рисовать сотни квадратов по одному за раз создают одну сетку полигонов и рисуют за один подход все сразу. Бачинг всех объектов, как правило, не возможен. Самый простой бачинг можно сделать так: отсортировать все объекты по глубине, сгруппировать по материалу (шейдер+текстуры), посчитать финальное положение всех сеток в текущей камере, соединить все сетки в одну. Это динамический бачинг. Есть ещё статический когда, например, в 3д сцене детали ландшафта соединяют в одну большую сетку. Вообще я каждый раз удивляюсь насколько быстрее все работает когда включаешь бачинг. Чтобы улучшить бачинг нужно использовать атласы - одна большая текстура со множеством маленьких текстур. Это позволит сгруппировать больше объектов. Есть случаи когда генерируют шейдер который использует одновременно несколько атласов динамически выбирая правильный для правильного объекта. Вторая техника для оптимизации рендера - отбраковка. Тут есть несколько элементов. Отбраковка поверхностей, которые не направлены в камеру (в основном для 3Д) - back face culling. Отбраковка объектов, находящихся за пределами пирамиды обзора - view frustum culling. И в помощь ей - замощение (тесселяция) объектов, находящихся частично в пирамиде. Для эффективного рендера текстур нужно чтобы пиксели текстуры максимально совпадали с пикселями буфера в который они будут рисоваться (масштаб 1:1). Это еще и улучшит качество финальной картинки. Оптимизация в частных случаях Первое, что нужно сделать при оптимизации, - понять что именно нужно оптимизировать. Для этого используют профайлер. Профайлер покажет сколько времени занимает каждая часть кода. После этого можно заняться оптимизацией кода. Ещё очень важно понимать где проблема имплементации, а где - алгоритма. Про оптимизацию каждого конкретного случая лучше спрашивать отдельно.

понедельник, 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(); } }

суббота, 7 декабря 2019 г.

Рисование кругов в libgdx

#java #android #libgdx


Имеется 3 круга, каждый круг разбит на 3 части в которых задается цвет, каждый круг
должен вращаться в разные стороны. Как это сделать?


    


Ответы

Ответ 1



Мой ответ не для libgdx, а для просто Android. Но может быть кому-то будет интересно. Это кастомное представление: public class ProgressView extends View { private Paint paint; private float mProgress; private final RectF oval = new RectF(); public ProgressView(Context context) { super(context); initPaint(); } public void setProgress(final float progress) { if (progress == mProgress) { return; } mProgress = progress; invalidate(); } private void initPaint() { paint = new Paint(); paint.setStyle(Paint.Style.FILL); paint.setStyle(Paint.Style.STROKE); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); float width = (float)getWidth(); float height = (float)getHeight(); float radius; if (width > height){ radius = height/4; } else{ radius = width/4; } float center_x, center_y; center_x = width/2; center_y = height/2; oval.set(center_x - radius, center_y - radius, center_x + radius, center_y + radius); int initialAngle = (int)(mProgress / 100 * 360); drawCircle(canvas, oval, 15, initialAngle); oval.set(center_x - 2*radius/3, center_y - 2*radius/3, center_x + 2*radius/3, center_y + 2*radius/3); initialAngle = -initialAngle; drawCircle(canvas, oval, 10, initialAngle); oval.set(center_x - radius/3, center_y - radius/3, center_x + radius/3, center_y + radius/3); initialAngle = -initialAngle; drawCircle(canvas, oval, 5, initialAngle); } private void drawCircle(Canvas canvas, RectF rectF, int strokeWidth, int initAngle) { paint.setStrokeWidth(strokeWidth); paint.setColor(Color.RED); canvas.drawArc(rectF, initAngle, 120, false, paint); paint.setColor(Color.YELLOW); canvas.drawArc(rectF, initAngle + 120, 120, false, paint); paint.setColor(Color.WHITE); canvas.drawArc(rectF, initAngle + 240, 120, false, paint); } } Это активность, использующая этот View, где движение в разные стороны достигается с помощью ValueAnimator: public class MainActivity extends AppCompatActivity { private ProgressView progressBar; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); progressBar = new ProgressView(this); setContentView(progressBar); ValueAnimator anim = ValueAnimator.ofInt(0, 1000); anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { progressBar.setProgress((int)animation.getAnimatedValue()); } }); anim.setDuration(40000); anim.setRepeatCount(ValueAnimator.INFINITE); anim.start(); } }

вторник, 16 июля 2019 г.

Libgdx плавный поворот/вращение физического тела на определенный угол

Хочу поворачивать физическое тело на определенный угол, но никак не выходит, использую конструкцию
rotateToAction = new RotateToAction(); rotateToAction.setRotation(90); rotateToAction.setDuration(5f); player.addAction(rotateToAction);
внутри метода touchDown, сам метод вызывается, я проверил в логах, но визуальных изменений никаких не наблюдаю. можете подсказать, что делаю не так и где ошибся?


Ответ

Это норма, если вы неправильно переопределили метод draw() для своего "Актёра" player, у меня тоже был такой затык когда-то. Дело в том, что в методе draw() вашего актёра нужно использовать не короткую конструкцию SpriteBatch.draw() с 4-мя параметрами, а есть более длинная конструкция, там можно задать и параметры масштабирования и т.п., вот её вам и нужно задать и правильно передавать параметры, тогда и анимация будет работать. Вот конструкция SpriteBatch.draw(Texture texture, float x, float y, float originX, float originY, float width, float height, float scaleX, float scaleY, float rotation, int srcX, int srcY, int srcWidth, int srcHeight, boolean flipX, boolean flipY) Вот ссылка. Только чтобы вы не задавали вопрос в будущем по поводу повторного использования анимации вам необходимо после каждого завершения анимации обновлять её, а именно в вашем случае объект rotateToAction методом reset() или restart(), уже точно не помню, вот ссылка на обновление анимации. Также будет полезным знать о том, когда же анимация завершилась, для этого есть метод, который позволяет отслеживать завершение анимации, но на эту тему уже сами поищите

среда, 10 июля 2019 г.

Как удалить обьект в Java

Я создал выстрел пули:
for (Bullet bullet : bullets) { bullet.x = bullet.x + 10; System.out.println(bullet.x); batch.draw(tbullet, bullet.x, bullet.y); }
Как удалить объект(пулю), когда она вылетает за экран?
Дополнение:
for (Bullet bullet : bullets) { bullet.x = bullet.x + 10; System.out.println(bullet.x); batch.draw(tbullet, bullet.x, bullet.y); if (bullet.x>=500) { tbullet.dispose();// Картинка Освобождаеться bullets.remove(bullet);// Вызывает ошибку } }

Exception in thread "LWJGL Application" java.util.ConcurrentModificationException at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:859) at java.util.ArrayList$Itr.next(ArrayList.java:831) at com.mygdx.game.MyGdxGame.render(MyGdxGame.java:265) at com.badlogic.gdx.backends.lwjgl.LwjglApplication.mainLoop(LwjglApplication.java:223) at com.badlogic.gdx.backends.lwjgl.LwjglApplication$1.run(LwjglApplication.java:124)


Ответ

Java - язык с автоматическим управлением памятью. Поэтому явно вручную освободить память, выделенную для объекта, нельзя.
Вы можете удалить объект из коллекции bullets
bullets.remove(bullet);
и тогда, если на него не осталось других ссылок, сборщик мусора когда-нибудь почистит его.

Если пуль много, и они появляются и исчезают очень часто, вы можете захотеть держать конечное количество пуль всегда в памяти в некотором пуле (коллекции) и добавить им поле boolean active. После этого вместо создания новой пули - брать из пула любую неактивную пулю и выставлять ей active = true. Когда пуля должна быть удалена - сбрасывать поле active в false

Не двигается шейдерный рисунок в прямоугольнике ShapeRenderer когда двигаю проекционную матрицу

Использую ShapeRenderer из Libgdx чтобы нарисовать прямоугольник и с помощью шейдеров рисую волны. В игре двигаю объекты для создания эффекта паралакса, с помощью транслейта матрицы проекции. Транслейчу матрицу у ShapeRenderer - рисуемый прямоугольник двигается, почему рисуемые волны через шейдеры в прямоугольнике не двигаются ? в фрагментном шейдере учитывать матрицу проекции ? Благодарен за любую помощь

package com.mygdx.game;
import com.badlogic.gdx.ApplicationAdapter; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.InputProcessor; import com.badlogic.gdx.graphics.GL20; import com.badlogic.gdx.graphics.glutils.ShaderProgram; import com.badlogic.gdx.graphics.glutils.ShapeRenderer; import com.badlogic.gdx.graphics.glutils.ShapeRenderer.ShapeType; import com.badlogic.gdx.math.Matrix4; import com.badlogic.gdx.math.Vector2;
public class MyGdxGame extends ApplicationAdapter implements InputProcessor {
private float mX; private float mY; private ShaderProgram mGradientShader;
private Matrix4 mProjection = new Matrix4();
private ShapeRenderer mShapeRender;
public MyGdxGame() {
}
private float iGlobalTime = 0.0f; private Vector2 mScreenResolution; @Override public void create () { final float screenWidth = Gdx.graphics.getWidth(); final float screenHeight = Gdx.graphics.getHeight(); mScreenResolution = new Vector2( screenWidth, screenHeight ); mX = screenWidth / 2.0f; mY = screenHeight / 2.0f;
String vertexShader = Gdx.files.local( "vertex.glsl" ).readString(); String fragmentShader = Gdx.files.local( "fragment.glsl" ).readString(); ShaderProgram.pedantic = false; mGradientShader = new ShaderProgram( vertexShader, fragmentShader ); String s = ""; if( false == mGradientShader.isCompiled() ) { s = mGradientShader.getLog(); Gdx.app.log( "Asteroid", s ); }
mProjection.setToOrtho2D( 0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight() );
mShapeRender = new ShapeRenderer( 19, mGradientShader );
Gdx.input.setInputProcessor( this ); }
@Override public void render () { Gdx.gl.glClearColor( 1, 0, 0, 1 ); Gdx.gl.glClear( GL20.GL_COLOR_BUFFER_BIT ); Gdx.gl.glBlendFunc( GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA ); Gdx.gl.glEnable( GL20.GL_BLEND );
mProjection.translate( 1.0f, 0.0f, 0.0f );
final int width = 400; final int height = 400;
mGradientShader.begin(); mGradientShader.setUniformf( "u_parentAlpha", 1.0f ); mGradientShader.setUniformf( "iGlobalTime", iGlobalTime ); mGradientShader.setUniformf( "iResolution", mScreenResolution ); mGradientShader.setUniformf( "u_size", width, height ); mGradientShader.setUniformMatrix("u_projTrans", mProjection ); mGradientShader.setUniformf("u_center", mX, mY ); mGradientShader.end();
mShapeRender.begin( ShapeType.Filled ); mShapeRender.rect( mX - width / 2.0f, mY - height / 2.0f, width - 100, height ); mShapeRender.end();
iGlobalTime += Gdx.graphics.getDeltaTime(); }
@Override public boolean keyDown(int keycode) { // TODO Auto-generated method stub return false; }
@Override public boolean keyUp(int keycode) { // TODO Auto-generated method stub return false; }
@Override public boolean keyTyped(char character) { // TODO Auto-generated method stub return false; }
@Override public boolean touchDown(int screenX, int screenY, int pointer, int button) {
mX = screenX; mY = Gdx.graphics.getHeight() - screenY; return false; }
@Override public boolean touchUp(int screenX, int screenY, int pointer, int button) { // TODO Auto-generated method stub return false; }
@Override public boolean touchDragged(int screenX, int screenY, int pointer) { mX = screenX; mY = Gdx.graphics.getHeight() - screenY;
return false; }
@Override public boolean mouseMoved(int screenX, int screenY) { // TODO Auto-generated method stub return false; }
@Override public boolean scrolled(int amount) { // TODO Auto-generated method stub return false; } }
//###########################Vertex shader attribute vec4 a_position; attribute vec4 a_color; attribute vec2 a_texCoord0; uniform mat4 u_projTrans; varying vec4 v_color; varying vec2 v_texCoords;
void main() { v_color = a_color; v_color.a = v_color.a * (255.0/254.0); v_texCoords = a_texCoord0; gl_Position = u_projTrans * a_position ; }
//###########################Fragment shader #ifdef GL_ES #define LOWP lowp precision mediump float; #else #define LOWP #endif
varying LOWP vec4 v_color; varying vec2 v_texCoords;
uniform sampler2D u_texture;
uniform float u_outterRadius;
uniform vec2 u_center; uniform float u_parentAlpha; uniform float iGlobalTime; uniform vec2 iResolution; uniform vec2 u_size;
float speed = 0.03; float invAr = iResolution.y / iResolution.x;
void main() { //determine origin vec2 position = ( gl_FragCoord.xy - u_center ) / u_size.xy;
//determine the vector length of the center position float len = length( abs( position ) );
float softness = 0.01;
float waves_count = 2.0; float wave_spliter = 0.05;
vec2 center = u_center / iResolution;
vec2 uv = gl_FragCoord.xy / iResolution.xy;
// vec3 col = vec4( uv, 0.5 + 0.5 * sin( iGlobalTime ), 0.0 ).xyz; // vec3 col = vec4( uv, 0.5, 0.0 ).xyz; vec3 col = vec3( 0.5, 0.5, 0.5 );
vec3 texcol;
float x = ( center.x - uv.x ); float y = ( center.y - uv.y ) * invAr;
float r = ( - 1.0 ) * sqrt( x * x + y * y ); //uncoment this line to symmetric ripples //float r = ( - 1.0 ) * ( x * x + y * y); float z = 1.0 + 0.5 * sin( ( r - iGlobalTime * speed ) / 0.003 );
texcol.x = z; texcol.y = z; texcol.z = z;
gl_FragColor = vec4( col * texcol, z * ( 1.0 - 2.0 * len ) ); }


Ответ

Спасибо за помощь Я нашел решение:
private Vector3 mMatrixGetTranslation = new Vector3();
в render ()
mProjection.getTranslation( mMatrixGetTranslation ); float tranX = ( Gdx.graphics.getWidth() + mMatrixGetTranslation.x * Gdx.graphics.getWidth() ) / 2.0f; float tranY = ( Gdx.graphics.getHeight() + mMatrixGetTranslation.y * Gdx.graphics.getHeight() ) / 2.0f;
и наконец
mGradientShader.setUniformf("u_center", mX + tranX, mY + tranY );

суббота, 15 июня 2019 г.

Как получить столкновение объектов в игре?

Есть класс в библиотеке LIBGDX для проверки столкновений
import com.badlogic.gdx.math.Intersector; Intersector.intersectRectangles(rectangle1, rectangle2, intersection);
Как реализовать его не понимаю. У меня имеются два класса Bullet и Enemy у них имеются свои координаты Rectangles.
К примеру, пуля летит по горизонтали и нужно сделать проверку на столкновение. В гугле искал код реализации, вроде находил что то похожее, но как то не получается реализовать это в коде.
Кто сталкивался с подобным классом столкновений? Подскажите, куда смотреть.
Пытаюсь написать условие с циклом for но выдает ошибку в r2:
java.lang.IndexOutOfBoundsException: index can't be >= size: 1 >= 1
Вот код, который я пытаюсь выполнить:
if(arrayBullet.size != 0){ Rectangle intersection = new Rectangle(); for(int k=0;knum — переменная объявлена в поле класса для быстрого доступа в циклах for который находится в методе render


Ответ

Все разобрался... невнимательность дает о себе знать... Всего лишь поменял буковку в r2 на букву k :)))
if(arrayBullet.size != 0){ Rectangle intersection = new Rectangle(); for(int k=0;k

четверг, 14 февраля 2019 г.

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

Делаю простенькую игрушку. Логика заключается в том, что у левого края экрана стоит объект, назовем его человеком для удобства. У правого края хаотичным образом спавнятся другие объекты, для удобства, назовем их зомби. Человек убивает их из постоянно стреляющего автомата, "пули" которого при пересечении с "зомби" должны удалять "зомби" с экрана.
Проблема заключается в том, что эти "пули" просто пролетают мимо "зомби". То-есть, я не могу отследить пересечения рендеров "пуль" и "зомби".
Как я понял, проблема в многочисленном объявлении 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
Делал все по шаблону со "стартандроида".


Ответ

Решение взято отсюда. Человек решает аналогичную задачу через следующий код:
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(); } } } }
когда-то пробовал сам - у меня работало.