Форум программистов, компьютерный форум, киберфорум
Наши страницы
Программирование Android
Войти
Регистрация
Восстановить пароль
 
m210
0 / 0 / 0
Регистрация: 17.12.2013
Сообщений: 10
#1

Организация структуры объектов - Программирование Android

17.12.2013, 15:53. Просмотров 813. Ответов 15
Метки нет (Все метки)

Всем привет!
Хочу задать вопрос по поводу организации структуры объектов в игре для дальнейшей обработки коллизий:
например есть у меня класс World - уровень
На уровне есть кирпич, игроки и монстры (используются разные классы без унаследований)

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

Я так понимаю что в классе каждого объекта нужно создать переменную isCollision и присваивать в эту переменную true.
А дальше у объектов, в которые переменная isCollision = true производить действие.

Но как мне менять значение переменной, если используются разные класс? Писать отдельные методы для каждого класса?
Разъясните этот момент, уже 2й день голову ломаю из-за этих классов...
Пока у меня был только игрок с кирпичами, все было хорошо...был один метод, куда я передавал игрока и там проверял наличие пересечения с кирпичом....а теперь мне нужно написать точно такой же метод, только вместо игрока указывать монстров....но так будет как то не эстетично и больше похоже на быдло-код... надеюсь я правильно передал свою мысль
http://www.cyberforum.ru/android-dev/thread807321.html
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
17.12.2013, 15:53
Я подобрал для вас темы с готовыми решениями и ответами на вопрос Организация структуры объектов (Программирование Android):

Организация поиска в listview
Всем привет... вообщем как сделать поиск по списку listview? подскажите...

Организация обновления программы
Добрый день! Подскажите, как можно организовать обновление программы на новые...

Организация структуры игровых объектов
Первый опыт создания внутриигровой структуры объектов немного провалился :)...

Организация движение объектов по выбору
Не получается организовать движение объектов по выбору , всё время мерещиться...

Организация хранения объектов по координатам
Доброго времени суток! Передо мной стала задача, хочу спросить совета....

15
GukZiLLA
35 / 35 / 2
Регистрация: 30.11.2013
Сообщений: 102
17.12.2013, 16:24 #2
Ну, я когда делал игры, обычно в классе родительском описывал метод, который возвращал прямоугольник объекта.

А также были методы движения, стрельбы и т.п.

Все объекты находились в одном массиве, но у каждого класса была своя пометка.

В общем цикле игры я пробегался по своему массиву так:

Java
1
2
3
4
5
6
7
8
for(Class s : listClass) {
      for(Class s2 : listClass) {
              if(s != s2 && s.getRect().intersect(s2.getRect())) {
                     // здесь уже производил действия, например отталкивание или нанесение урона
                     s.lifeDamage(10);
              }
      }
}
0
m210
0 / 0 / 0
Регистрация: 17.12.2013
Сообщений: 10
17.12.2013, 16:37  [ТС] #3
GukZiLLA, спасибо за пример...теперь например действие будет - присвоение переменной о наличие коллизии...а сравниваться будут не два класса, а три:
Class s - будет статический объект, т.е. кирпич

Java
1
2
3
4
5
6
7
8
9
10
11
12
for(Class s : listClass) {
      for(Class s2 : listClass) {
              if(s != s2 && s.getRect().intersect(s2.getRect())) {
                     void setreflect(s2);
              }
      }
      for(Class s3 : listClass) {
              if(s != s3 && s.getRect().intersect(s3.getRect())) {
                    void setreflect(s3);
              }
      }
}
это то, чего я хочу добиться....т.е. void setreflect(); - это метод с объемными вычислениями, куда передается класс s2 или s3 для вытягивания оттуда переменных, например координат x и y, сравнение с координатами класса S а далее записи в эти классы(s2 или s3) переменной Reflect = 1.

Два раза один и тот же код писать вроде как не стоит, а по-другому получить значение одноименной переменной от разных классов не получается. Как быть?
0
GukZiLLA
35 / 35 / 2
Регистрация: 30.11.2013
Сообщений: 102
17.12.2013, 16:42 #4
Не надо два цикла делать, добавляйте только проверку if(...)

Цитата Сообщение от m210 Посмотреть сообщение
это то, чего я хочу добиться....т.е. void setreflect(); - это метод с объемными вычислениями, куда передается класс s2 или s3 для вытягивания оттуда переменных, например координат x и y, сравнение с координатами класса S а далее записи в эти классы(s2 или s3) переменной Reflect = 1.
Два раза один и тот же код писать вроде как не стоит, а по-другому получить значение одноименной переменной от разных классов не получается. Как быть?
Вот здесь я ничего не понял, зачем вытягивать переменные?
Создайте массив классов
0
m210
0 / 0 / 0
Регистрация: 17.12.2013
Сообщений: 10
17.12.2013, 16:46  [ТС] #5
Цитата Сообщение от GukZiLLA Посмотреть сообщение
Создайте массив классов
А пример реализации можете показать? Я пока не представляю как потом работать с таким массивом
0
GukZiLLA
35 / 35 / 2
Регистрация: 30.11.2013
Сообщений: 102
17.12.2013, 16:58 #6
Юзайте наследование, иначе циклов будет куча.
0
m210
0 / 0 / 0
Регистрация: 17.12.2013
Сообщений: 10
18.12.2013, 16:57  [ТС] #7
Ладно, спасибо хоть на этом)

Добавлено через 18 часов 44 минуты
GukZiLLA, каким образом вы формируете список объектов?
Допустим у меня есть список кирпичей, который я хочу добавить в общий массив классов (если я правильно понял, то массив классов включает в себя все объекты одного класса?)

Класс кирпичей у меня наследуется от общего класса Block
В конструкторе мира приходится писать вот так:
Java
1
2
3
Block br = new Brick(this, x, y, 700, level.Level[i][1]); //создание кирпича
bricks.add((Brick) br);  //список кирпичей для прорисовки
blockList.add(br); //общий список объектов для коллизии
Как то неудобно...удалять объекты из списков тоже приходится двумя строками...

Ну и все было хорошо, пока мне не потребовался доступ к отдельным дочерним классам.

Под общим классом Block у меня пока два дочерних класса - Player и Brick
В Brick у меня есть метод, который проигрывает анимацию при попадания в него шарика...этот метод есть только в Brick, и он не нужен Playerу.

Java
1
2
3
4
5
public void isCollision(Objects obj) { 
            for(int i = 0; i < blockList.size(); i++) {            
                Block br = blockList.get(i);
((Brick br).setGloss(); //в этом случае происходит вылет программы
}
Что я делаю не так?
0
GukZiLLA
35 / 35 / 2
Регистрация: 30.11.2013
Сообщений: 102
18.12.2013, 20:14 #8
Ну, массив классов - это массив родительских объектов.
Все остальные объекты мира наследуются всегда от родительского.
В родительском классе описаны самые основные методы и переменные.

Объявите в родительском классе переменную type и у вас будут разные типы объектов по их именам.
У кирпича String type = "brick", у монстра, например, "monster" и т.п.

Если грамотно делать, то расчеты и отрисовка должны происходить в одном цикле.
А чтобы при тормозах отрисовки не возникало замедления - юзайте deltaTime (разница по времени между двумя ближайшими кадрами) - она должна быть равна единице, и все рассчеты умножайте на deltaTime.

Создайте в каком-нибудь из базовых классов метод draw и отрисовывайте персонажей в потомках.
Также у каждого персонажа живого свои методы переопределяются.

Не нужно создавать отдельные массивы для отрисовки. просто в цикле прогона по всем объектам детектите их по типу(type), о котором говорил выше.

Если type == brick, то его можно привести под (Brick) и вытянуть все методы и переменные.


Например вот так:
Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
List<Obj> listObj = new ArrayList<Obj>();
    
    class Obj {
        String type;
        
    }
    
    class Brick extends Obj {
 
        int x;
        int y;
        int width;
        int height;
        
        Brick(String name, int x, int y, int width, int height) {
            this.type = name; // parent type
            this.x = x;
            this.y = y;
            this.width = width;
            this.height = height;
        }
        
        public void draw(Canvas c) {
            // .........
            Log.i("brick", "draw");
        }
        
        
        
    }
    
    
    class Monster extends Obj {
 
        int x;
        int y;
        int width;
        int height;
        float speed;
        int damage;
        
        Monster(String name, int x, int y, int width, int height, float speed, int damage) {
            this.type = name; // parent type
            this.x = x;
            this.y = y;
            this.width = width;
            this.height = height;
            this.speed = speed;
            this.damage = damage;
        }
        
        public void move(float deltaTime) {
            // .......
            Log.i("monster", "move");
        }
        
        public void draw(Canvas c) {
            // .........
            Log.i("monster", "draw");
        }
        
    }
Проверим, сработает ли))

Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// for example
        for(int i = 0; i <= 10; i++) {
            listObj.add(new Brick("brick", i*10, i*10, 100, 100));
            listObj.add(new Monster("monster", i*10, i*10, 20, 40, 5, 10));
        }
        
        // main loop
        for(Obj o : listObj) {
            if(o.type.hashCode() == "brick".hashCode()) {
                Brick b = (Brick) o;
                b.draw(null);
            }
            if(o.type.hashCode() == "monster".hashCode()) {
                Monster m = (Monster) o;
                m.draw(null);
                m.move(1);
            }
        }
На выходе видим:

brick: draw
monster: draw
monster: move
brick: draw
monster: draw
monster: move
brick: draw
monster: draw
monster: move
brick: draw
monster: draw
monster: move
brick: draw
monster: draw
monster: move
brick: draw
monster: draw
monster: move
brick: draw
monster: draw
monster: move
brick: draw
monster: draw
monster: move
brick: draw
monster: draw
monster: move
brick: draw
monster: draw
monster: move
brick: draw
monster: draw
monster: move
Как-то так. Везде есть нюансы и лучше делать конечно все через движок, например LibGDX.

Добавлено через 12 минут
Вообще для динамического удаления монстров надо будет юзать Iterator

Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
    Iterator<Obj> iter = listObj.iterator();
        while(iter.hasNext()) {
            Obj o = iter.next();
            if(o.type.hashCode() == "brick".hashCode()) {
                Brick b = (Brick) o;
                b.draw(null);
            }
            if(o.type.hashCode() == "monster".hashCode()) {
                Monster m = (Monster) o;
                m.draw(null);
                m.move(1);
                
                // удаляем монстра
                if(m.life <= 0) {
                    iter.remove();
                }
            }
        }
1
m210
0 / 0 / 0
Регистрация: 17.12.2013
Сообщений: 10
18.12.2013, 21:02  [ТС] #9
Вроде пока все понятно, спасибо ) завтра буду пробовать. Кстати а в чем разница итератора от обычного цикла по листу?

Добавлено через 2 минуты
На счет использования движков уже думал...но надо сначало самому все изучить и понять...движки можно будет использовать позже....да и как то свой код роднее и понятнее))))
0
GukZiLLA
35 / 35 / 2
Регистрация: 30.11.2013
Сообщений: 102
18.12.2013, 21:37 #10
Цитата Сообщение от m210 Посмотреть сообщение
Кстати а в чем разница итератора от обычного цикла по листу?
http://dev64.wordpress.com/2013/03/1...ion-exception/
1
m210
0 / 0 / 0
Регистрация: 17.12.2013
Сообщений: 10
19.12.2013, 14:11  [ТС] #11
По таком алгоритму стало как то хуже только))) Вместо итератора я по прежнему начал использовать циклы по листы, иначе новый объект не добавить...все напрочь зависает и вылетает. Добавить элемент можно только с использованием такого кода

Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
private void drawWorld(World world) {
 
        g.drawPixmap(world.Background, 0, 0); //Прорисовка фона
        for(int j = 0; j < world.objList.size(); j++) {   
            Obj obj = world.objList.get(j);
            if(obj.type.hashCode() == "brick".hashCode()) {
                Brick br = (Brick) obj;
                br.onDraw(g);
            } else
            if(obj.type.hashCode() == "player".hashCode()) {
                pl = (Player) obj;
                pl.onDraw(g); 
                    
                if(input.isTouched()) {
                    pl.movePlayerTo(input.getTouchX());
                    
                    if(!Shoot && input.getTouchX() > 300 && input.getTouchY() < 20)
                            pl.newBall();
                            Shoot = true; 
                } else Shoot = false;
            } else
            if(obj.type.hashCode() == "ball".hashCode()) {
                Ball bl = (Ball) obj;
                bl.onDraw(g);
                bl.update();
            }
        }

А вот код определения коллизий в public void update(float deltaTime)

Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
               for(Obj s : objList) {
            for(Obj s2 : objList) {
                if(s != s2) {
                    if(s.type == "ball") {
                        Ball ball = (Ball) s;
                        //if(s2.type == "brick") {
                            for(int k = 0; k < 4; k++) { 
                                if(FrameMath.CircleIntersect(s.x + 4, s.y + 4, 4, s2.Vortex[k].x,s2.Vortex[k].y, s2.Vortex[k + 1].x, s2.Vortex[k + 1].y)) {
                                    crossx = FrameMath.CircleIntersectX(s.x + 4, s.y + 4, 4, s2.Vortex[k].x,s2.Vortex[k].y, s2.Vortex[k + 1].x, s2.Vortex[k + 1].y);
                                    crossy = FrameMath.CircleIntersectY(s.x + 4, s.y + 4, 4, s2.Vortex[k].x,s2.Vortex[k].y, s2.Vortex[k + 1].x, s2.Vortex[k + 1].y);
 
                                    int N = 0;
                                    double ang = ball.getAngle();
                                    if(k == 2) { N = 270; ball.setPosY((float) (crossy + ball.getSpeed())); }
                                    if(k == 0) { N = 90;  ball.setPosY((float) (crossy - ball.getSpeed() - 8)); }
                                    if(k == 3) { N = 180; ball.setPosX((float) (crossx - ball.getSpeed() - 8)); }
                                    if(k == 1) { N = 0; ball.setPosX((float) (crossx + ball.getSpeed())); }
                                    ball.setAngle(2*N - 180 - ang);
                                    
                                    //if(s2.getExtra() > 0) s2.setExtra(s2.getExtra() - 1);
                                }
                            }
                        //}
                    }       
                }
            }
        }
Столновение с первым созданным шаром вообще не происходит...второй шар вроде просчитывается...хотя в посл время прога просто вылетает при создании второго...но когда все работало (уже не помню, что менял) заметил, что если шар рисуется поверх кирпичей, происходит коллизия, если рисуется под кирпичами (как в случае с первым шаром) - коллизии нет.

P.S. Как же блин сложно угодить этой Яве...куда не влезешь - ошибки или вылеты))) Прям руки опускаются
0
GukZiLLA
35 / 35 / 2
Регистрация: 30.11.2013
Сообщений: 102
19.12.2013, 14:47 #12
Объекты надо сравнивать так - s.equals(s2) - return true/false
Строки надо сравнивать также через equals, либо для производительности юзать hashCode

Цитата Сообщение от m210 Посмотреть сообщение
По таком алгоритму стало как то хуже только)))
А должно быть лучше
0
m210
0 / 0 / 0
Регистрация: 17.12.2013
Сообщений: 10
19.12.2013, 15:06  [ТС] #13
Ну в целом удобнее работать с таким алгоритмом, но во время работы цикла в него хрен влезешь, возникают исключения, с которыми я не умею работать а объекты я и через хэшкод пробовал, разницы никакой...проблема где то в другом...но где я определить не смогу о чем там эта ява думает
0
GukZiLLA
35 / 35 / 2
Регистрация: 30.11.2013
Сообщений: 102
19.12.2013, 15:09 #14
Цитата Сообщение от m210 Посмотреть сообщение
но во время работы цикла в него хрен влезешь, возникают исключения, с которыми я не умею работать
Например?
0
m210
0 / 0 / 0
Регистрация: 17.12.2013
Сообщений: 10
19.12.2013, 23:27  [ТС] #15
Например добавить новый шар (чтобы было одновременно два) не получается...программа вываливается с исключением при попытке добавить шар в лист. Видимо с добавлением объекта изменяется общий список в момент, когда цикл уже производит обработку. Кстати да...вроде бы прога вылетает при попытке добавить объект внутри цикла

Добавлено через 7 часов 40 минут
Причину вылетов я нашел...это условие

Java
1
if(FrameMath.CircleIntersect(s.x + 4, s.y + 4, 4, s2.Vortex[k].x,s2.Vortex[k].y, s2.Vortex[k + 1].x, s2.Vortex[k + 1].y))
А точнее доступ к Vortex[]
Это массив точек кирпича, который создается в конструкторе для прохождения по всем граням кирпича... массив класса Obj, который у меня задается так
Java
1
2
3
4
5
6
7
void setVortex(float x, float y, int width, int height) {
        this.Vortex[0] = new PointF(x,y);
        this.Vortex[1] = new PointF(x + width,y);
        this.Vortex[2] = new PointF(x + width,y + height);
        this.Vortex[3] = new PointF(x,y + height);
        this.Vortex[4] = new PointF(x,y);
    }
Может идея не самая лучшая?)
Добавил эти точки шарам и вылеты пропали, хотя самый первый шар по прежнему пролетает сквозь кирпичи, последующие выполняют условия циклов. Как-нить можно отловить первый шар и понять, почему он не сравнивается с кирпичами?
Он кстати может пролететь мимо нескольких кирпичей, а потом вдруг начать от них отлетать))) в общем, живет своей жизнью
0
m210
0 / 0 / 0
Регистрация: 17.12.2013
Сообщений: 10
20.12.2013, 16:30  [ТС] #16
Ну все, с коллизией полностью разобрался, теперь все работает))))
Проблема с коллизией первого шара решилась сама собой, когда я перед началом игры проигрывал анимацию бликов кирпичей...лист обновлялся и шар становился "видимым"

Теперь могу показать, чего я добился собственно )
Осталось сделать нормальное выталкивание (старое отключил совсем, поэтому шар застревает в кирпичах) остальные недочеты легко решаемы
0
Вложения
Тип файла: rar Powball.rar (389.0 Кб, 3 просмотров)
20.12.2013, 16:30
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
20.12.2013, 16:30
Привет! Вот еще темы с решениями:

Динамические структуры данных. Организация данных в списковые структуры
Написать программу вставки нового элемента в список за некоторым заданным по-...

Динамические структуры данных. Организация данных в списковые структуры
Написать программу, формирующую два списка, заполняя их числами из файлов....

Организация коллекции объектов пользовательского класса
Есть некий пользовательский класс Mob. И есть класс MobAssistant, существующий...

Структуры и организация данных
Помогите написать программу с комментариями! :scratch: Все нулевые элементы...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
16
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2018, vBulletin Solutions, Inc.
Рейтинг@Mail.ru