如何在旧版本的处理中选择和拖动椭圆?

问题描述

//The following game has been designed as an educational resource
//for Key Stage 1 and 2 children. Children are the future of
//civil engineering,and to inspire them to get involved in the
//industry is important for innovation. However,today the
//national curriculum is very structured,and many children
//can find themselves falling behind even at the age of 7 or 8.
//It is essential that children can be supported with material
//they find difficult,and given the resources to learn in a
//fun and engaging manner.
//One of the topics that many children struggle to grasp is
//fractions. It is necessary to prevent young children feeling
//like stem subjects are too difficult for them,so that they
//have the opportunity and confidence to explore science and
//engineering subjects as they move into secondary education and
//careers.
//This game intends to set a precedent for teaching complex
//subjects to children in a simple,but fun and interactive 
//manner. It will show them that fractions can be fun,and that
//they are capable,building confidence once they return to 
//the classroom.

//The game will work by challenging the user to split a group
//of balls into three buckets depending on the fraction
//displayed on the bucket.

int number_of_balls;
float bucket_1,bucket_2,bucket_3;
int bucket_1_correct,bucket_2_correct,bucket_3_correct;
PVector basket_position,basket_dimensions;
Ball[] array_of_balls;
int linethickness;



//Random generator to give number of balls,ensuring that 
//they can be divided into the number of buckets available.
void setup()
{
  size(500,500);
  linethickness = 4;
 
  number_of_balls = int(random(1,11))*6;
  
println(number_of_balls);

  bucket_1 = 1/6;
  bucket_2 = 1/2;
  bucket_3 = 1/3;
  
//Working out the correct answers
  
  bucket_1_correct = number_of_balls*bucket_1;
  bucket_2_correct = number_of_balls*bucket_2;
  bucket_3_correct = number_of_balls*bucket_3;
  
println (bucket_1,bucket_3);
println (bucket_1_correct,bucket_3_correct);

//Creating the basket

  basket_position = new PVector(width/4,height/8);
  basket_dimensions = new PVector(width/2,height/4);

//Creating the balls & placing inside basket

  array_of_balls = new Ball[number_of_balls];
  
  for (int index=0; index<number_of_balls; index++)
  {
  array_of_balls[index] = new Ball(); 
  }
  
}
 
//Drawing the balls and basket outline

void draw()
{
  background (125,95,225);
  for (int index=0; index<number_of_balls; index++)
  {
    array_of_balls[index].Draw();
  }
  
  noFill();
  stroke(180,0);
  strokeWeight(linethickness);
  rect(basket_position.x,basket_position.y,basket_dimensions.x,basket_dimensions.y);
}

 void mouseDragged()
  {
   if ((mouseX >= (ball_position.x - radius)) && (mouseX <= (ball_position.x + radius)) && (mouseY >= (ball_position.y - radius)) && (mouseY <= (ball_position.y + radius))) 
   {
  ball_position = new PVector (mouseX,mouseY);
   }
  }

 //Ball_class
 
 int radius;
 
 Ball()
 {
   radius = 10;
   ball_position = new PVector (random(basket_position.x + radius + linethickness,basket_position.x + basket_dimensions.x - radius - linethickness),random(basket_position.y + radius + linethickness,basket_position.y + basket_dimensions.y - radius - linethickness));
   colour = color(random(255),random(255),random(255)); 
 }
 
 void Draw()
 {
  nostroke();
  fill(colour); 
  ellipse(ball_position.x,ball_position.y,radius*2,radius*2);
  }
  
 
  
  
    
}

enter image description here

在此先感谢您的帮助!我正在使用 Processing 2.2.1,我知道它已经过时了,所以很难找到帮助。

我有一段代码创建了许多球,我希望能够将它们“拖放”到屏幕上的不同位置,作为教育游戏的一部分。我试过玩弄 mousepressed()mouseDragged() 但还没有运气。任何建议将不胜感激!

解决方法

我对您使用的语言有些困惑。 Processing 是 Java 的包装器,而不是 JavaScript。 Processing.js 升级到 1.6.6 版本,然后被 p5.js 接替。我假设您使用的是 p5.js。

我不知道这是否是 p5.js 中的新事物,但为了简单但不是非常用户友好的点击和拖动功能,我喜欢使用内置变量 mouseIsPressed

如果椭圆坐标存储在向量数组中,您可能会执行以下操作:

let balls = [];
let radius = 10;

function setup() {
  createCanvas(400,400);
  for (let i = 0; i < 10; i++) {
    balls.push(createVector(random(width),random(height)));
  }
}

function draw() {
  background(220);
  for (let i = 0; i < balls.length && mouseIsPressed; i++) {
    if (dist(mouseX,mouseY,balls[i].x,balls[i].y) < radius) {
      balls[i] = createVector(mouseX,mouseY);
      i = balls.length;
    }
  }
  for (let i = 0; i < balls.length; i++) {
    ellipse(balls[i].x,balls[i].y,2 * radius,2 * radius
           );
  }
}

这是我能想到的最快的方法,但还有更好的方法(至少,在 p5.js 中有)。您可以创建一个 Ball 类,其中包含 x、y 和半径的数字,以及一个表示是否被拖动的布尔值。在该类中,您可以创建一个方法 mouseOn() 来检测光标是否在半径内(如果不是圆形,您可以使用两个半径:sq((this.x - mouseX)/r1) + sq((this.y - mouseY)/r2) < 1)。

当按下鼠标时,您可以循环遍历球数组中的所有球,并使用 mouseOn() 测试每个球,并将它们的拖动布尔值设置为 true。释放鼠标后,您可以将所有拖动布尔值设置为 false。这是当前版本的 p5.js 中的样子:

function mousePressed() {
  for (let i = 0; i < balls.length; i++) {
    balls[i].drag = balls[i].mouseOn();
    if (balls[i].drag) {
      i = balls.length;
    }
  }
}

function mouseReleased() {
  for (let i = 0; i < balls.length; i++) {
    balls[i].drag = false;
  }
}

我希望这会有所帮助。

,

有很多方法可以解决这个问题,但我建议的一种方法是做这样的事情:

// "Ellipse" object

function Ellipse (x,y,width,height) {
    
    // Each Ellipse object has their own x,height,and "selected" values
    
    this.x = x;
    this.y = y;
    
    this.width = width;
    this.height = height;
    
    this.selected = false;
    
    // You can call the draw function whenever you want something done with the object
    
    this.draw = function() {
        
        // Draw ellipse
        
        ellipse(this.x,this.y,this.width,this.height);
        
        // Check if mouse is touching the ellipse using math
        // https://www.desmos.com/calculator/7a9u1bpfvt
        
        var xDistance = this.x - mouseX;
        var yDistance = this.y - mouseY;
        
        // Ellipse formula: (x^2)/a + (y^2)/b = r^2
        
        // Assuming r = 1 and y = 0:
        
        // 0 + (x^2)/a = 1               Substitute values
        // ((width / 2)^2)/a = 1         x = width / 2 when y = 0
        // a = (width / 2)^2             Move numbers around
        // a = (width^2) / 4             Evaluate
        
        var a = Math.pow(this.width,2) / 4;
        
        // Assuming r = 1 and x = 0:
        
        // 0 + (y^2)/b = 1               Substitute values
        // ((height / 2)^2)/b = 1        y = height / 2 when x = 0
        // b = (height / 2)^2            Move numbers around
        // b = (height^2) / 4            Evaluate
        
        var b = Math.pow(this.height,2) / 4;
        
        // x^2
        
        var x2 = Math.pow(xDistance,2);
        
        // y^2
        
        var y2 = Math.pow(yDistance,2);
        
        // Check if coordinate is inside ellipse and mouse is pressed
        
        if(x2 / a + y2 / b < 1 && mouseIsPressed) {
            
            this.selected = true;
        }
        
        // If mouse is released,deselect the ellipse
        
        if(!mouseIsPressed) {
            
            this.selected = false;
        }
        
        // If selected,then move the ellipse
        
        if(this.selected) {
            
            // Moves ellipse with mouse
            
            this.x += mouseX - pmouseX;
            this.y += mouseY - pmouseY;
        }
    };
}

// New Ellipse object

var test = new Ellipse(100,100,90,60);

draw = function() {
    
    background(255);
    
    // Do everything associated with that object
    
    test.draw();
};

数学有点奇怪,我可能没有使用正确版本的 Processing,但希望你发现这至少有点帮助 :)

,

您的代码现在的方式在当前版本的 Processing 中也不起作用,但这是一个非常快速的修复。我将向您展示解决该问题的方法,希望它可以在早期版本中使用。

这里是我认为问题所在:当您使用 mouseDragged() 时,您尝试更改 ball_position,但您没有指定哪个球的位置。这是一种解决方案,更改 mouseDragged() 块和 Ball 类:

void mouseDragged() {
  for (int i = 0; i < array_of_balls.length; i++) {
    if ((mouseX > (array_of_balls[i].ball_position.x - array_of_balls[i].radius)) && 
        (mouseX < (array_of_balls[i].ball_position.x + array_of_balls[i].radius)) && 
        (mouseY > (array_of_balls[i].ball_position.y - array_of_balls[i].radius)) && 
        (mouseY < (array_of_balls[i].ball_position.y + array_of_balls[i].radius))
       ) {
      array_of_balls[i].ball_position = new PVector (mouseX,mouseY);
      i = array_of_balls.length;
    }
  }
}


//Ball_class

class Ball {
  int radius;
  PVector ball_position;
  color colour;
  Ball() {
    radius = 10;
    ball_position = new PVector (random(basket_position.x + radius + linethickness,basket_position.x + basket_dimensions.x - radius - linethickness),random(basket_position.y + radius + linethickness,basket_position.y + basket_dimensions.y - radius - linethickness));
    colour = color(random(255),random(255),random(255));
  }
  void Draw() {
    noStroke();
    fill(colour); 
    ellipse(ball_position.x,ball_position.y,radius*2,radius*2);
  }
}

附言由于您使用的是基于 Java 的语言,因此您可能应该遵守该语言的一些细节:

  • Java 中的数据类型非常严格。避免将任何可能是浮点数的变量分配给声明为 int 的变量。例如,在您的 setup() 块中,您说 bucket_1_correct = number_of_balls*bucket_1;。这似乎不是问题,因为 number_of_balls*bucket_1 始终是整数。但是由于计算机在保存 bucket_1 = 1/6 时会四舍五入,因此将其乘以 6 不一定会给出整数。在这种情况下,您可以只使用 round(): bucket_1_correct = round(number_of_balls*bucket_1);
  • 关于数据类型,您应该始终使用其数据类型声明变量。我有点难以判断,但在我看来,您从未在 ball_position 类中声明 colourBall,并且您从未使用典型的 {{ 1}}。不过,这可能是复制/粘贴错误。