Попытка заставить мяч подпрыгивать на экране при обработке с использованием классов

#processing

#обработка

Вопрос:

Я работаю над тем, чтобы заставить один мяч подпрыгивать по всему экрану, но у меня проблема с отскоком мяча функция bounce() отвечает за отскок мяча, но я сталкиваюсь с исключением array out of bounds, несмотря на то, что в массиве проходит только 1 элемент. Я предоставил приведенный ниже код. В этом коде используются 2 класса (Ball_Usage и Ball).

Код Ball_Usage:

 Ball ball1;

    void setup(){
     size(500,500);
     
     ball1 = new Ball();
     
    }
    
    void draw(){
     background(255);
     ball1.bounce();
    }
  

Мяч:

 class Ball{
 float [] xPos = {};
 float [] yPos = {};
 float [] dia = {};
 float [] xSpeed = {};
 float [] ySpeed = {};
 
 Ball(){
   
   }
   
   Ball(float x, float y, float argDia){
       xPos = append(xPos, x);
       yPos = append(yPos, y);
       dia = append(dia, argDia);
    }
 
void bounce(){
    for(int i=0; i<1; i  ){
    ellipse(xPos[i], yPos[i], 50, 50);
    xPos[i]  = xSpeed[i];
    yPos[i]  = ySpeed[i];
    if(xPos[i]<0 || xPos[i]>=width){
        xSpeed[i] = -xSpeed[i]; 
    }
    
    if(yPos[i]<0 || yPos[i]>=height){
        ySpeed[i] = -ySpeed[i];
    }
  }
}
}
  

Ответ №1:

Я считаю, что путаница возникает из-за того, что ваш класс имеет два конструктора:

  • пустой конструктор (который не принимает аргументов): Ball()
  • конструктор с аргументами position и argDia (предполагаемый диаметр?): Ball(float x, float y, float argDia)

В setup() вы вызываете пустой конструктор:

 ball1 = new Ball();
  

Это означает, что пять массивов с плавающей запятой по-прежнему имеют length значение 0, отсюда и исключение out of bounds.

Даже если вы вызовете версию конструктора position diameter xSpeed , ySpeed массивы , все равно будут иметь length 0 .

Вы могли бы исправить это, инициализировав два двух массива, а также используя эту версию конструктора:

 Ball ball1;

void setup() {
  size(500, 500);

  //ball1 = new Ball();
  ball1 = new Ball(250, 250, 50);
}

void draw() {
  background(255);
  ball1.bounce();
}

class Ball {
  float [] xPos = {};
  float [] yPos = {};
  float [] dia = {};
  float [] xSpeed = {};
  float [] ySpeed = {};

  Ball() {
  }

  Ball(float x, float y, float argDia) {
    xPos = append(xPos, x);
    yPos = append(yPos, y);
    dia = append(dia, argDia);
    xSpeed = append(xSpeed, random(-1, 1));
    ySpeed = append(ySpeed, random(-1, 1));
  }

  void bounce() {
    for (int i=0; i<1; i  ) {
      ellipse(xPos[i], yPos[i], 50, 50);
      xPos[i]  = xSpeed[i];
      yPos[i]  = ySpeed[i];
      if (xPos[i]<0 || xPos[i]>=width) {
        xSpeed[i] = -xSpeed[i];
      }

      if (yPos[i]<0 || yPos[i]>=height) {
        ySpeed[i] = -ySpeed[i];
      }
    }
  }
}
  

Это сработает, однако все еще остается небольшая путаница: зачем вообще использовать массивы, если вы выполняете цикл только один раз для первого элемента? Это делает массивы и цикл for в основном избыточными.

Вы можете сохранить, если планируете изменять диаметр с течением времени (который в вашем коде жестко 50 задан), возможно, положения и скорости и отображать историю изменений мяча.

Если вы этого не сделаете, вы можете просто использовать float свойства вместо массивов:

 Ball ball1;

void setup() {
  size(500, 500);

  ball1 = new Ball();
}

void draw() {
  background(255);
  ball1.bounce();
}

class Ball {
  float xPos;
  float yPos;
  float diameter = 50;
  float xSpeed;
  float ySpeed;

  Ball() {
    xPos = width / 2;
    yPos = height / 2;
    xSpeed = random(-1, 1);
    ySpeed = random(-1, 1);
  }

  void bounce() {
    ellipse(xPos, yPos, diameter, diameter);
    xPos  = xSpeed;
    yPos  = ySpeed;

    if (xPos < 0 || xPos >= width) {
      xSpeed = -xSpeed;
    }

    if (yPos < 0 || yPos >= height) {
      ySpeed = -ySpeed;
    }
  }
}
  

Это больше похоже на пример обработки отказов.
Вы можете на более позднем этапе создать массив Ball объектов.

Кроме того, стоит форматировать код, поскольку это экономит ваше время на чтение / прокрутку и визуально упрощает сканирование структуры программы (как вписывается каждая часть) и, следовательно, упрощает отладку / запуск мысленно. Это не требует никаких усилий, так как вы можете просто нажать Ctrl T на Windows / Linux или CMD T OSX. В долгосрочной перспективе это окупится, тем более что программы становятся длиннее и сложнее, поскольку вы тратите больше времени на чтение кода, чем на его написание. Это хорошая привычка, которую нужно усвоить на раннем этапе обучения программированию. Получайте удовольствие!