处理从屏幕上拾取椭圆
Processing Picking up ellipse from screen
我有一个创建球(椭圆)数组列表的项目。当我按下鼠标(左键)并按住它时,一个椭圆跟随我的鼠标。当我松开时,椭圆会出现在我鼠标所在的屏幕上。
我希望能够右键单击并按住一个椭圆(任何随机椭圆)并让它像以前一样再次跟随我的鼠标。如果我再次松开鼠标按钮,它应该放回我鼠标当前所在的屏幕上。
我很难理解如何找到屏幕上已经存在的椭圆的 x y 位置并将椭圆从列表中删除并让它再次跟随我的鼠标。
任何建议让我知道-
这是我的主要 class
ArrayList<Ball> ballList = new ArrayList<Ball>();boolean touching;
void setup() {
size(600, 600);
}
void draw() {
background(150);
// if the mouse button is held down, set the ball's coordinates to the mouse coordinates
if (ballList.size() > 0 && mousePressed && mouseButton==LEFT) {
ballList.get(ballList.size() - 1).xPos = mouseX; // 'ballList.get(ballList.size() - 1)' is the java way to get the last item added to an arrayList
ballList.get(ballList.size() - 1).yPos = mouseY;
}
for (Ball b : ballList) {
b.drawBall();
}
}
// this method will trigger once every time the user press a mouse button
void mousePressed() {
if (mouseButton==LEFT) {
ballList.add(new Ball(mouseX, mouseY));
}
}
这是我的球class
class Ball {
float xPos, yPos;
Ball(float xPos, float yPos) {
this.xPos= xPos;
this. yPos= yPos;
}
void drawBall() {
ellipse(xPos, yPos, 50, 50);
println("X" + xPos + " Y:"+ yPos);
}
void moveBall(){
}
}
您可以通过检查小球位置和鼠标位置之间的距离(dist()
)来检查小球是否在光标下:
if(dist(ball.x, ball.y, mouseX, mouseY) < ball.radius){
println("mouse over ball");
}
目前您正在硬编码球直径 (50),但您可以轻松添加 radius
属性:
class Ball {
float xPos, yPos;
float diameter = 50;
float radius = diameter * 0.5;
Ball(float xPos, float yPos) {
this.xPos= xPos;
this. yPos= yPos;
}
void drawBall() {
ellipse(xPos, yPos, diameter, diameter);
}
}
条件可以包含在一个 for 循环中以对每个球进行相同的检查并进入一个函数,该函数 return 是第一个匹配条件的球或 null
(如果有光标下没有球):
Ball getBall(float x, float y){
// for each ball
for(Ball ball : ballList){
// check if the x,y coordinates are inside any of the existing balls
if(dist(ball.xPos, ball.yPos, x, y) < ball.radius){
// return the 1st match
return ball;
}
}
// return null if nothing was found
return null;
}
您已经在使用 类 和函数,但以防万一上面的语法看起来不熟悉:
- 函数开头的
Ball
类型替换了 void
,这意味着函数必须 return 类型为 Ball
的对象(相对于 void
)
return
关键字既退出函数又 return 对球的引用(如果找到,null
否则)
要辨别是否有选定的球(在左键和右键单击之间切换时),您可以使用 Ball
变量,该变量最初是 null
,但在左键单击时被分配pressed or right click is pressed 并且鼠标坐标落在球的 position/radius.
内
这是使用上述代码修改后的版本:
ArrayList<Ball> ballList = new ArrayList<Ball>();
// reference to selection
Ball selectedBall;
void setup() {
size(600, 600);
}
void draw() {
background(150);
// render all balls
for (Ball ball : ballList) {
ball.drawBall();
}
}
// this method will trigger once every time the user press a mouse button
void mousePressed() {
if (mouseButton == LEFT) {
// reset the selection to the newest ball
selectedBall = new Ball(mouseX, mouseY);
// append it to the list
ballList.add(selectedBall);
println("added new ball and updated selection", selectedBall);
}
if (mouseButton == RIGHT) {
// check if a ball is under the cursor, if so select it
selectedBall = getBall(mouseX, mouseY);
println("right click selection", selectedBall);
}
}
void mouseDragged() {
// update dragged ball coordinates if there is a previous selection
if (selectedBall != null) {
selectedBall.xPos = mouseX;
selectedBall.yPos = mouseY;
println("dagging selected ball", selectedBall);
}
}
void mouseReleased() {
// clear selection
selectedBall = null;
println("selection cleared");
}
Ball getBall(float x, float y) {
// for each ball
for (Ball ball : ballList) {
// check if the x,y coordinates are inside any of the existing balls
if ( dist(ball.xPos, ball.yPos, x, y) < ball.radius ) {
// return the 1st match (exits loop and function immediately)
return ball;
}
}
// return null if nothing was found
return null;
}
class Ball {
float xPos, yPos;
float diameter = 50;
float radius = diameter * 0.5;
Ball(float xPos, float yPos) {
this.xPos = xPos;
this.yPos = yPos;
}
void drawBall() {
ellipse(xPos, yPos, diameter, diameter);
}
// pretty print info
String toString(){
return "[Ball x=" + xPos + " y="+ yPos + "]";
}
}
我删除了一些未使用的变量,添加了 toString()
(因此它可以使用 println()
很好地显示信息)并添加了一些可选的 println()
语句,因此更容易看到是什么继续测试代码。
最后的笔记:
- 目前,如果您左键单击多次,您可以添加多个重叠的球。您可以调整实现以更新检查是否首先有一个球,如果有,则仅在该位置没有任何现有球的情况下添加一个新球
- 遍历每个球并检查距离(使用
sqrt()
)对于大量球来说计算量会很大。在这个阶段,代码的可读性更为重要,但如果你的代码发展成更复杂的东西,你可以使用平方距离而不是 dist()
并使用其他优化技术。
更新
这是上面草图的一个调整版本,如果鼠标位置上还没有球,它只会添加一个新球(只允许鼠标左键拖动):
ArrayList<Ball> ballList = new ArrayList<Ball>();
// reference to selection
Ball selectedBall;
void setup() {
size(600, 600);
}
void draw() {
background(150);
// render all balls
for (Ball ball : ballList) {
ball.drawBall();
}
}
// this method will trigger once every time the user press a mouse button
void mousePressed() {
// update selection
selectedBall = getBall(mouseX, mouseY);
// if there isn't a ball already, add one:
if (selectedBall == null) {
ballList.add(new Ball(mouseX, mouseY));
}
}
void mouseDragged() {
// update dragged ball coordinates if there is a previous selection
if (selectedBall != null) {
selectedBall.xPos = mouseX;
selectedBall.yPos = mouseY;
}
}
void mouseReleased() {
// clear selection
selectedBall = null;
}
Ball getBall(float x, float y) {
// for each ball
for (Ball ball : ballList) {
// check if the x,y coordinates are inside any of the existing balls
if ( dist(ball.xPos, ball.yPos, x, y) < ball.radius ) {
// return the 1st match (exits loop and function immediately)
return ball;
}
}
// return null if nothing was found
return null;
}
class Ball {
float xPos, yPos;
float diameter = 50;
float radius = diameter * 0.5;
Ball(float xPos, float yPos) {
this.xPos = xPos;
this.yPos = yPos;
}
void drawBall() {
ellipse(xPos, yPos, diameter, diameter);
}
// pretty print info
String toString(){
return "[Ball x=" + xPos + " y="+ yPos + "]";
}
}
如果您想立即选择新添加的球,您当然可以添加新球并更新选择:
ArrayList<Ball> ballList = new ArrayList<Ball>();
// reference to selection
Ball selectedBall;
void setup() {
size(600, 600);
}
void draw() {
background(150);
// render all balls
for (Ball ball : ballList) {
ball.drawBall();
}
}
// this method will trigger once every time the user press a mouse button
void mousePressed() {
// update selection
selectedBall = getBall(mouseX, mouseY);
// if there isn't a ball already, add one:
if (selectedBall == null) {
selectedBall = new Ball(mouseX, mouseY);
ballList.add(selectedBall);
}
}
void mouseDragged() {
// update dragged ball coordinates if there is a previous selection
if (selectedBall != null) {
selectedBall.xPos = mouseX;
selectedBall.yPos = mouseY;
}
}
void mouseReleased() {
// clear selection
selectedBall = null;
}
Ball getBall(float x, float y) {
// for each ball
for (Ball ball : ballList) {
// check if the x,y coordinates are inside any of the existing balls
if ( dist(ball.xPos, ball.yPos, x, y) < ball.radius ) {
// return the 1st match (exits loop and function immediately)
return ball;
}
}
// return null if nothing was found
return null;
}
class Ball {
float xPos, yPos;
float diameter = 50;
float radius = diameter * 0.5;
Ball(float xPos, float yPos) {
this.xPos = xPos;
this.yPos = yPos;
}
void drawBall() {
ellipse(xPos, yPos, diameter, diameter);
}
// pretty print info
String toString(){
return "[Ball x=" + xPos + " y="+ yPos + "]";
}
}
我有一个创建球(椭圆)数组列表的项目。当我按下鼠标(左键)并按住它时,一个椭圆跟随我的鼠标。当我松开时,椭圆会出现在我鼠标所在的屏幕上。
我希望能够右键单击并按住一个椭圆(任何随机椭圆)并让它像以前一样再次跟随我的鼠标。如果我再次松开鼠标按钮,它应该放回我鼠标当前所在的屏幕上。
我很难理解如何找到屏幕上已经存在的椭圆的 x y 位置并将椭圆从列表中删除并让它再次跟随我的鼠标。
任何建议让我知道- 这是我的主要 class
ArrayList<Ball> ballList = new ArrayList<Ball>();boolean touching;
void setup() {
size(600, 600);
}
void draw() {
background(150);
// if the mouse button is held down, set the ball's coordinates to the mouse coordinates
if (ballList.size() > 0 && mousePressed && mouseButton==LEFT) {
ballList.get(ballList.size() - 1).xPos = mouseX; // 'ballList.get(ballList.size() - 1)' is the java way to get the last item added to an arrayList
ballList.get(ballList.size() - 1).yPos = mouseY;
}
for (Ball b : ballList) {
b.drawBall();
}
}
// this method will trigger once every time the user press a mouse button
void mousePressed() {
if (mouseButton==LEFT) {
ballList.add(new Ball(mouseX, mouseY));
}
}
这是我的球class
class Ball {
float xPos, yPos;
Ball(float xPos, float yPos) {
this.xPos= xPos;
this. yPos= yPos;
}
void drawBall() {
ellipse(xPos, yPos, 50, 50);
println("X" + xPos + " Y:"+ yPos);
}
void moveBall(){
}
}
您可以通过检查小球位置和鼠标位置之间的距离(dist()
)来检查小球是否在光标下:
if(dist(ball.x, ball.y, mouseX, mouseY) < ball.radius){
println("mouse over ball");
}
目前您正在硬编码球直径 (50),但您可以轻松添加 radius
属性:
class Ball {
float xPos, yPos;
float diameter = 50;
float radius = diameter * 0.5;
Ball(float xPos, float yPos) {
this.xPos= xPos;
this. yPos= yPos;
}
void drawBall() {
ellipse(xPos, yPos, diameter, diameter);
}
}
条件可以包含在一个 for 循环中以对每个球进行相同的检查并进入一个函数,该函数 return 是第一个匹配条件的球或 null
(如果有光标下没有球):
Ball getBall(float x, float y){
// for each ball
for(Ball ball : ballList){
// check if the x,y coordinates are inside any of the existing balls
if(dist(ball.xPos, ball.yPos, x, y) < ball.radius){
// return the 1st match
return ball;
}
}
// return null if nothing was found
return null;
}
您已经在使用 类 和函数,但以防万一上面的语法看起来不熟悉:
- 函数开头的
Ball
类型替换了void
,这意味着函数必须 return 类型为Ball
的对象(相对于void
) return
关键字既退出函数又 return 对球的引用(如果找到,null
否则)
要辨别是否有选定的球(在左键和右键单击之间切换时),您可以使用 Ball
变量,该变量最初是 null
,但在左键单击时被分配pressed or right click is pressed 并且鼠标坐标落在球的 position/radius.
这是使用上述代码修改后的版本:
ArrayList<Ball> ballList = new ArrayList<Ball>();
// reference to selection
Ball selectedBall;
void setup() {
size(600, 600);
}
void draw() {
background(150);
// render all balls
for (Ball ball : ballList) {
ball.drawBall();
}
}
// this method will trigger once every time the user press a mouse button
void mousePressed() {
if (mouseButton == LEFT) {
// reset the selection to the newest ball
selectedBall = new Ball(mouseX, mouseY);
// append it to the list
ballList.add(selectedBall);
println("added new ball and updated selection", selectedBall);
}
if (mouseButton == RIGHT) {
// check if a ball is under the cursor, if so select it
selectedBall = getBall(mouseX, mouseY);
println("right click selection", selectedBall);
}
}
void mouseDragged() {
// update dragged ball coordinates if there is a previous selection
if (selectedBall != null) {
selectedBall.xPos = mouseX;
selectedBall.yPos = mouseY;
println("dagging selected ball", selectedBall);
}
}
void mouseReleased() {
// clear selection
selectedBall = null;
println("selection cleared");
}
Ball getBall(float x, float y) {
// for each ball
for (Ball ball : ballList) {
// check if the x,y coordinates are inside any of the existing balls
if ( dist(ball.xPos, ball.yPos, x, y) < ball.radius ) {
// return the 1st match (exits loop and function immediately)
return ball;
}
}
// return null if nothing was found
return null;
}
class Ball {
float xPos, yPos;
float diameter = 50;
float radius = diameter * 0.5;
Ball(float xPos, float yPos) {
this.xPos = xPos;
this.yPos = yPos;
}
void drawBall() {
ellipse(xPos, yPos, diameter, diameter);
}
// pretty print info
String toString(){
return "[Ball x=" + xPos + " y="+ yPos + "]";
}
}
我删除了一些未使用的变量,添加了 toString()
(因此它可以使用 println()
很好地显示信息)并添加了一些可选的 println()
语句,因此更容易看到是什么继续测试代码。
最后的笔记:
- 目前,如果您左键单击多次,您可以添加多个重叠的球。您可以调整实现以更新检查是否首先有一个球,如果有,则仅在该位置没有任何现有球的情况下添加一个新球
- 遍历每个球并检查距离(使用
sqrt()
)对于大量球来说计算量会很大。在这个阶段,代码的可读性更为重要,但如果你的代码发展成更复杂的东西,你可以使用平方距离而不是dist()
并使用其他优化技术。
更新 这是上面草图的一个调整版本,如果鼠标位置上还没有球,它只会添加一个新球(只允许鼠标左键拖动):
ArrayList<Ball> ballList = new ArrayList<Ball>();
// reference to selection
Ball selectedBall;
void setup() {
size(600, 600);
}
void draw() {
background(150);
// render all balls
for (Ball ball : ballList) {
ball.drawBall();
}
}
// this method will trigger once every time the user press a mouse button
void mousePressed() {
// update selection
selectedBall = getBall(mouseX, mouseY);
// if there isn't a ball already, add one:
if (selectedBall == null) {
ballList.add(new Ball(mouseX, mouseY));
}
}
void mouseDragged() {
// update dragged ball coordinates if there is a previous selection
if (selectedBall != null) {
selectedBall.xPos = mouseX;
selectedBall.yPos = mouseY;
}
}
void mouseReleased() {
// clear selection
selectedBall = null;
}
Ball getBall(float x, float y) {
// for each ball
for (Ball ball : ballList) {
// check if the x,y coordinates are inside any of the existing balls
if ( dist(ball.xPos, ball.yPos, x, y) < ball.radius ) {
// return the 1st match (exits loop and function immediately)
return ball;
}
}
// return null if nothing was found
return null;
}
class Ball {
float xPos, yPos;
float diameter = 50;
float radius = diameter * 0.5;
Ball(float xPos, float yPos) {
this.xPos = xPos;
this.yPos = yPos;
}
void drawBall() {
ellipse(xPos, yPos, diameter, diameter);
}
// pretty print info
String toString(){
return "[Ball x=" + xPos + " y="+ yPos + "]";
}
}
如果您想立即选择新添加的球,您当然可以添加新球并更新选择:
ArrayList<Ball> ballList = new ArrayList<Ball>();
// reference to selection
Ball selectedBall;
void setup() {
size(600, 600);
}
void draw() {
background(150);
// render all balls
for (Ball ball : ballList) {
ball.drawBall();
}
}
// this method will trigger once every time the user press a mouse button
void mousePressed() {
// update selection
selectedBall = getBall(mouseX, mouseY);
// if there isn't a ball already, add one:
if (selectedBall == null) {
selectedBall = new Ball(mouseX, mouseY);
ballList.add(selectedBall);
}
}
void mouseDragged() {
// update dragged ball coordinates if there is a previous selection
if (selectedBall != null) {
selectedBall.xPos = mouseX;
selectedBall.yPos = mouseY;
}
}
void mouseReleased() {
// clear selection
selectedBall = null;
}
Ball getBall(float x, float y) {
// for each ball
for (Ball ball : ballList) {
// check if the x,y coordinates are inside any of the existing balls
if ( dist(ball.xPos, ball.yPos, x, y) < ball.radius ) {
// return the 1st match (exits loop and function immediately)
return ball;
}
}
// return null if nothing was found
return null;
}
class Ball {
float xPos, yPos;
float diameter = 50;
float radius = diameter * 0.5;
Ball(float xPos, float yPos) {
this.xPos = xPos;
this.yPos = yPos;
}
void drawBall() {
ellipse(xPos, yPos, diameter, diameter);
}
// pretty print info
String toString(){
return "[Ball x=" + xPos + " y="+ yPos + "]";
}
}