在使用类进行处理时尝试使屏幕上的球反弹

问题描述

我正在使整个屏幕上的单个球弹跳,但是我对使球弹跳有问题,bounce()函数负责使球弹跳,但是我遇到了一个超出范围的异常,尽管仅遍历数组中的1个元素。我提供了下面的代码。该代码使用2个类(Ball_Usage和Ball)。

球使用代码

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];
    }
  }
}
}

解决方法

我相信混淆来自于您的类具有两个构造函数的事实:

  • 一个空的构造函数(不带参数):Ball()
  • 具有位置和argDia(猜测直径?)自变量的构造函数:Ball(float x,float y,float argDia)

setup()中,您调用空的构造函数:

ball1 = new Ball();

这意味着五个浮点数组的length仍为0,因此超出范围。

即使调用构造函数的位置+直径版本,xSpeedySpeed数组仍将具有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 argDia) {
    xPos = append(xPos,x);
    yPos = append(yPos,y);
    dia = append(dia,argDia);
    xSpeed = append(xSpeed,random(-1,1));
    ySpeed = append(ySpeed,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;
    }
  }
}

这看起来更像Bounce Processing Example。 您可以稍后再制作Ball个对象的数组。

另外,值得格式化代码,因为它可以节省您阅读/滚动代码的时间,并且从视觉上看,它更容易扫描程序的结构(每个部分的装配方式),因此,从精神上进行调试/运行也更容易。您无需费力,只需在Windows / Linux上按Ctrl+T或在OSX上按CMD+T。从长远来看,这是有回报的,尤其是当您花费更多的时间阅读代码而不是编写代码时,程序变得越来越长,越来越复杂。在学习编码的同时提早拾起这是一个好习惯。玩得开心!