Я пытаюсь сделать что-то вроде Piano Tiles в студии Android и хочу, чтобы плитки начинали появляться при нажатии кнопки воспроизведения с той же скоростью.

Я делаю это с помощью handler.postdelayed, но всякий раз, когда я начинаю нажимать на плитки, postdelayed не работает, иногда это происходит быстро, а иногда медленно. Вот код частного обработчика mhandler = new Handler();

private Runnable mcontinue = new Runnable() {
    @Override
    public void run() {

        //row5
        RockLocationRow5 = RockLocationRow4;
        setRockLocation(RockLocationRow5, 5);

        //row4
        RockLocationRow4 = RockLocationRow3;
        setRockLocation(RockLocationRow4, 4);

        //row3
        RockLocationRow3 = RockLocationRow2;
        setRockLocation(RockLocationRow3, 3);

        //row2
        RockLocationRow2 = RockLocationRow1;
        setRockLocation(RockLocationRow2, 2);

        //row1
        RockLocationRow1 = r.nextInt(3) + 1;
        setRockLocation(RockLocationRow1, 1);
        mhandler.postDelayed(this, 3000);

    }
};

Я вызываю его в функции initgame всякий раз, когда игра начинается, и если я нажимаю на любую плитку, я также называю этот Runnable своим

iv_13.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            if(RockLocationRow1 == 3){
                mcontinue.run();
       }
            else{
                //endGame();
            }
        }
    });

или их что-нибудь еще, что я могу использовать?? Я новичок...

вот как инициализируется RockLocationRow

    //row3
    RockLocationRow3 = 1;
    iv_31.setImageResource(tapImage);
   
    //row2
    RockLocationRow2 = r.nextInt(3) + 1;
    setRockLocation(RockLocationRow2, 2);

    //row1
    RockLocationRow1 = r.nextInt(3) + 1;
    setRockLocation(RockLocationRow1, 1);

и это setRockLocation

     private void setRockLocation(int place, int row){
        if(row == 1){
           iv_11.setImageResource(emptyImage);
           iv_12.setImageResource(emptyImage);
           iv_13.setImageResource(emptyImage);

        switch (place) {
            case 1:
                iv_11.setImageResource(tapImage);
                break;
            case 2:
                iv_12.setImageResource(tapImage);
                break;
            case 3:
                iv_13.setImageResource(tapImage);
                break;
        }
    }

то же самое для строк 2,3,4 и 5


person CS_Student    schedule 13.07.2020    source источник
comment
Является ли RockLocationRow каждой строкой плиток, проходящей через экран?   -  person LoukasPap    schedule 13.07.2020
comment
да это плитка   -  person CS_Student    schedule 13.07.2020
comment
Вы можете предоставить больше своего кода?   -  person LoukasPap    schedule 14.07.2020
comment
да, теперь вы можете проверить, что я также включил этот код (RockLocationRow)   -  person CS_Student    schedule 14.07.2020
comment
IV означает просмотр изображений?   -  person LoukasPap    schedule 14.07.2020
comment
да и 11,12,13,21... находятся в сетке   -  person CS_Student    schedule 15.07.2020


Ответы (1)


Я думаю, что нашел проблему. Проблема в том, когда вы нажимаете плитку. Если я правильно понял, этот код таков:

iv_13.setOnClickListener(new View.OnClickListener() {
  //rest of your code...
});

Видите ли, когда вы нажимаете на плитку, вы вызываете метод run() из Runnable: mcontinue.run();

Вызывая этот метод, вы выполняете СНОВА postDelayed: mhandler.postDelayed(this, 3000); Таким образом, для каждого щелчка по плитке вы выполняете postDelayed. В результате каждые 3 секунды С МОМЕНТА НАЖАТИЯ НА ПЛИТКУ будут появляться новые плитки. Если вы нажмете много плиток, postDelayed будет выполняться много раз, и плитки будут отображаться быстро.

Решение, которое может быть правильным, состоит в том, чтобы удалить mcontinue.run();, когда вы нажимаете плитку. Так:

iv_13.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            if(RockLocationRow1 == 3){
            }
            else {
                //endGame();
            }
        }
    });

Please, feel free to comment any of your thoughts/questions about this issue, and I will help as I can.
person LoukasPap    schedule 13.07.2020
comment
нет, я не смог найти setInterval() и clearInterval() в студии Android:/ - person CS_Student; 14.07.2020
comment
@CS_Student Вы программируете на Java или JavaScript? - person LoukasPap; 14.07.2020
comment
@Л.ПападопулосJava - person CS_Student; 14.07.2020
comment
@CS_Student Тогда у вас не должно быть javascript в качестве тега :). setInterval и clearInterval — это методы JavaScript. - person LoukasPap; 14.07.2020
comment
Не волнуйтесь, у нас все было впервые :) - person LoukasPap; 14.07.2020
comment
@CS_Student ты проверил мое решение? - person LoukasPap; 15.07.2020
comment
Да, в условии if, когда я удаляю mcontinue.run(), я копирую код run() в каждый прослушиватель кликов, но даже после этого у меня возникает та же проблема. И если я не скопирую код run() в прослушиватель кликов, плитки будут двигаться через 3 секунды. - person CS_Student; 16.07.2020
comment
У вас есть прослушиватель кликов для каждой плитки? - person LoukasPap; 16.07.2020
comment
все плитки последних 3 рядов. Должен ли я измениться? - person CS_Student; 16.07.2020
comment
Я думаю, что генерация тайлов (postDelayed) должна выполняться независимо от щелчка тайлов. Единственный случай, когда генерация должна ОСТАНОВИТЬСЯ, это только если вы нажмете не на ту плитку. Так что, возможно, вам нужно проверить нажатия неправильных кнопок, и если нажали, то остановить поколения. Скажи мне, если ты понимаешь, что я имею в виду, или я объясню снова. - person LoukasPap; 16.07.2020
comment
да, у меня есть такое условие, что всякий раз, когда кто-то нажимает на пустые плитки, игра завершается. Но я не могу понять, что вы подразумеваете под отложенным сообщением, которое должно работать независимо от щелчка плитки, теперь я также удалил mcontinue.run() из функции прослушивания кликов. - person CS_Student; 16.07.2020
comment
Подождите, я прочитал в одном из ваших предыдущих комментариев, что плитки двигаются через 3 секунды. Я думал, что это то, что вы хотели. Разве вы не хотите, чтобы плитки двигались каждые 3 секунды? - person LoukasPap; 16.07.2020
comment
Я хочу перемещать их каждые 3 секунды, но когда пользователь нажимает на плитку, она должна двигаться мгновенно и не должна ждать 3 секунды. - person CS_Student; 16.07.2020
comment
Затем при каждом щелчке плитки вы должны вызывать setRockLocation для последней плитки. Один из способов — заменить каждое значение rockLocation следующим значением rockLocation (rockLocation+1). - person LoukasPap; 16.07.2020
comment
Давайте попробуем это. Вы поместите postDelayed в метод, отдельный от того, которым вы заменяете rockLocation. Затем вы будете вызывать метод с postDelay при нажатии кнопки Play. В результате, когда вы щелкаете плитки, вы просто заменяете rockLocations и не запускаете postDelayed. - person LoukasPap; 16.07.2020
comment
не будет ли это так же, как когда я удалил часть mcontinue.run() и поместил часть кода run() (кроме postdelayed) в прослушиватель кликов? - person CS_Student; 16.07.2020
comment
да. Вы создадите ДРУГУЮ кнопку воспроизведения, при нажатии на которую она выполняет postDelay, и игра запускается. Затем каждый щелчок по плитке будет выполнять mcontinue.run() (но mcontinue.run() не будет включать postDelay), который будет генерировать следующие плитки. - person LoukasPap; 16.07.2020
comment
поэтому кнопка воспроизведения, которая выполняет постзадержку, должна просто вызвать эту постзадержку один раз или я должен поставить цикл до конца игры, но тогда он будет таким же, как mcontinue.run()... - person CS_Student; 17.07.2020