I have a ball class that creates a ball object. I want to created a ball object when the mouse is pressed, if the mouse is pressed and held the ball should follow the mouse(while the mouse is pressed). When the mouse is releases, the ball should stay at the current mouseX and mouseY, and no longer follow the mouse.
When the mouse is pressed again, another ball object is created and does the same as the first object and so on...A new ball object is created every time the mouse is pressed.
I have some code that creates an object, it follows the mouse and it puts on the canvas when I release the mouse. But if i press my mouse again the original ball goes back to the mouse. How do I "disengage" the ball object so i can make more ball objects that doesnt effect the position of the previously placed balls?.
I plan to use ArrayLists to make many objects .
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);
}
}
Ball ball1;
Ball ball2;
ArrayList<Ball> ballList = new ArrayList<Ball>();
void setup() {
size(600, 600);
ball1=new Ball(900, 900);
ball2=new Ball(900, 900);
}
void draw() {
background(150);
if (mousePressed ) {
ball1.xPos= mouseX;
ball1.yPos=mouseY;
}
ball1.drawBall();
}
The issue here are that you're not managing the array at all, and instead are working with the same object all the time. I re-wrote your example using the arraylist to store the Ball objects, and also to create new balls when the user clicks a mouse button.
Please note here that I'm deliberately using the "last item added to the arraylist" instead of creating an object which would be a reference to the this object. This is because I don't want to confuse you with references and such.
ArrayList<Ball> ballList = new ArrayList<Ball>();
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) {
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;
}
// draw every ball in the array (the weird format is just shorthand for a "for each" loop)
for(Ball b : ballList) {
b.drawBall();
}
}
// this method will trigger once every time the user press a mouse button
void mousePressed() {
ballList.add(new Ball(mouseX, mouseY));
}
class Ball {
float xPos, yPos;
Ball(float xPos, float yPos) {
this.xPos= xPos;
this.yPos= yPos;
}
void drawBall() {
ellipse(xPos, yPos, 50, 50);
}
}
By targeting the last created ball instead of a specific ball, you ensure that you're always using the right object. Also, notice how I just let the ball objects draw themselves in a loop. The 'for each' form ensure that whatever number of balls there currently is in the arrayList, they will all be printed anyway.
Good luck with this project and if something is confusing about my answer don't hesitate to reach out and ask questions about it.
Have fun!
Related
I am programming a game of sorts which would be kinda long to explain, but in short the player is an ellipse() and follows the mouse around, whilst the rect() is the obstacle that moves down the screen and needs to be dodged by the player, otherwise it's game over. There are multiple rect as I am using an ArrayList to store each obstacle object.
Currently, the player can just pass straight through the rect without anything happening to it. I have tried to solve it multiple times but it got extremely messy and I couldn't understand much due to being extremely new to Java (only 1 week of experience), so I have just placed the empty code below.
tldr; I need to figure out how to get an ellipse/rect collision to work (in its own method). I only have 1 week of Processing/Java experience. I've cut out most of the code that you don't need to look at, mainly just kept the variables used to define the shapes and the code for the shapes just in case you need that. Also, if possible could the collision method could be placed inside the Enemy Class.
Enemy Class (all the variables used to define the rect)
class Enemy {
int enemyNumber; // used to determine enemy type
//VARIABLES FOR ENEMY
boolean redEnemy = false; // determine enemy colour
color enemyColour = color(#B9B9E8); // sets default colour to blue
PVector position, velocity;
float xDist, yDist; // x and y distance for Bar
float smallCircleRad, bigCircleRad; // radius for circles
// **************************************************************************
Enemy() { //CONSTRUCTOR
position = new PVector(width/2, random(-300000, -250));
//println(position.y);
velocity = new PVector(0, 10);
smallCircleRad = 200;
bigCircleRad = 400;
xDist = width;
yDist = 200;
enemyNumber = int(random(1, 6));
}
// **************************************************************************
void redBar(float xPos, float yPos, float xDist, float yDist) {
redEnemy = true;
noStroke();
enemyColour = color(#E38585);
fill(enemyColour);
rect(xPos, yPos, xDist, yDist);
}
void blueBar(float xPos, float yPos, float xDist, float yDist) {
redEnemy = false;
noStroke();
enemyColour = color(#B9B9E8);
fill(enemyColour);
rect(xPos, yPos, xDist, yDist);
}
Player Class (all the variables used to define the ellipse)
class Player {
int r = 50; //player radius
float playerX = width/2; //starting x coordinate
float playerY = height/2+500; //starting y coordinate
float speed = 20; //player speed
float angle; //angle used to calculate trajectory for player
void playerChar() { //method for player model and general rules
stroke(10);
rectMode(CENTER);
fill(playerColour);
ellipse(playerX, playerY, r*2, r*2);
}
Make your life easier by treating the player as a rectangle instead of a circle. You can still draw them as a circle, but for collision detection, use a rectangle. This is called a bounding box and is very popular in collision detection.
Then you can use rectangle-rectangle collision detection, which is much simpler.
Some basic google searches return these results:
Axis-Aligned Bounding Box
What is the fastest way to work out 2D bounding box intersection?
Processing Collision Detection
If for some reason you absolutely need the player to be a circle when calculating the collision, then I'd start by googling something like "circle rectangle collision detection".
If you still can't get it figured out, please post a MCVE in a new question and we'll go from there. Good luck.
In my program, I want a sphere to represent a globe. I want the user to press down the mouse1 button and rotate the sphere. When the user is not pressing the mouse1 down, the sphere should just be staying still regardless of how the mouse is moving. In simple terms, I want a sphere to rotate only when the mouse is pressed. Here is my code for the sphere rotating.
float lockXRotation;
float lockYRotation;
void setup() {
size(1000,700,P3D); //reference
}
void draw() {
mouseAction();
fill(200, 0, 160);
if(mousePressed == false){
rotateX(lockXRotation);
rotateY(lockYRotation);
}
sphere(100);
}
void mouseAction () {
translate(500, 350, 0); //reference starts here'
if(mousePressed){
rotateX(mouseY * -0.01);
rotateY(mouseX * -0.01); //ends here
lockXRotation = 0;//what should i put so it will stay still?
lockYRotation = 0;
}
}
I have tried mouseX * -0.01 for lockXRotation but it offsets by the distance of the x to the origin. Is there a function to find the rotation an object is in?
Okay, so you want the sphere's location to lock when the user presses the mouse.
I took a look at your code and ran it on Processing, I believe that your lockXRotation is not doing what it is suppose to.
If you look at lines 12 - 15, where it says if (mousePressed == false), then it should rotateX(lockXRotation), those lines don't belong in the draw function, but if you put them in the mouseAction function, that might solve the problem.
I am creating a simple 2D game for my computer class. I already have a box that moves around through a level. But, i want to change this box to instead display a stickman standing that I drew. Then, more specifically, i would like in my MovementInput class (where i assign movements to the buttons), I want when neither A(my moving left button) or D(my moving right button) OR when both A and D are held down to display this standing.png image. How would i go about doing this?!
This is my code for drawing the box
public class Man extends AbstractMoveableEntity {
public Man(double x, double y, double width, double height) {
super(x, y, width, height);
}
#Override
public void draw() {
glColor3d(0, 0, 255);
glRectd(x - width / 2, y, x + width / 2, y + height);
}
}
And in my MovementInput class, this is my code for the A&D thing
if ((Keyboard.isKeyDown(Keyboard.KEY_D) &&Keyboard.isKeyDown(Keyboard.KEY_A))||(!Keyboard.isKeyDown(Keyboard.KEY_D) && !Keyboard.isKeyDown(Keyboard.KEY_A))) {
man.setDX(0);
}
Use something called Texture Atlases for multiple frames of animation and a simple timer to loop through the frames. ThinMatrix on YouTube has a really good tutorial for this here as well as many other concepts.
I'm trying to figure out how to make a yellow circle around the cursor in Java. The thing is that we've got a screen-recorder that (obviously) records the screen. Using the keywords "Yellow circle around cursor in Java" on Google only takes me to how to add a yellow circle around the cursor on a MAC, on WM and other applications, but not how to do it in Java on a users computer when the application starts.
How can I do it without using existing images? Drawing a simple yellow circle with some opacity would be the easiest thing to do, making it follow the mouse on the screen. And also, if it is possible to make it disappear and reappear when the user clicks a mouse-button, that'd be awesome.
It is possible to do this by attaching a MouseMotionListener to your component, but it will take a little work to get it working exactly how you want it.
I would start from something like this:
private static final double RADIUS = 15.0;
private static final double DIAMETER = 2.0 * RADIUS;
private static final Color XOR_COLOR = Color.yellow;
private static Shape m_circle = null;
#Override
public void mouseMoved(MouseEvent e)
{
Graphics2D g2 = (Graphics2D) getGraphics();
Point p = e.getPoint();
Shape circle = new Ellipse2D.Double(p.getX() - RADIUS, p.getY() - RADIUS, DIAMETER, DIAMETER);
clearCircle(g2);
g2.setXORMode(XOR_COLOR);
g2.draw(circle);
g2.setPaintMode();
m_circle = circle;
}
private void clearCircle(Graphics2D g2)
{
if (m_circle != null)
{
g2.setXORMode(XOR_COLOR);
g2.draw(m_circle);
g2.setPaintMode();
m_circle = null;
}
}
It will also be necessary to make sure that the old circle is cleared on the mouseExited event which you can listen for by adding a MouseListener. This also has the mousePressed/mouseReleased/mouseClicked events that you need for making it disappear/reappear on a user's mouse click.
Using XOR is convenient because it is very easy to restore the screen by repainting the same shape with the same color and style but it isn't quite what you asked for. It is possible to repair the screen by capturing an image of the area that you are about to draw the circle into. The circle can be removed from the screen by repainting the damaged area before painting a circle in a new position.
It's not possible to add a circle around the existing mouse pointer. You can only set the mouse pointer to a complete image.
My code plots 5000 points of time series data in a panel that is 581 pixels wide by default, but this width changes when the user resizes the window. My code also plots several rectangular markers that each identify a local maximum/peak in this same space.
I need to enable the user to right click on any of the rectangular-peak-markers so that the user can manually delete any false peak. The problem is that my code is reporting different x-coordinates than expected when the user right-clicks on a peak-marker. I suspect that the reason may have to do with rounding error in converting from 581 x-pixels back to 5000 data indices. But I am not certain of the reason.
Can anyone suggest a solution that enables my users to manually select one of the above-described peak markers by right-clicking on it?
I am enclosing relevant sections of the code below. My actual code is very, very long, and too complicated to post. But the relevant portions below should be enough for someone to see the logic of my approach, and to then suggest a more effective approach.
The code that declares the class in question is:
class SineDraw extends JPanel implements MouseMotionListener, MouseListener {
// lots of code, including the two segments excerpted below
}
This segment of code overloads the paintComponent of the JPanel so that my data is plotted:
// declare some variables
ArrayList<Double> PeakList = new ArrayList<Double>() // this ArrayList is populated by an extraneous process
visiblePoints = 5000
hstep = getWidth()/visiblePoints //=581/5000 by default, but will change when user resizes window
int numPeaks = PeakList.size();
// scale (y-coordinate) data relative to height of panel
pts = new double[visiblePoints]
for (int i = 0; i < pts.length-1; i++){pts[i]=//data vertical scaled to fill panel;}
// plot the 5000 time-series-data-points within the 581 pixels in x-axis
for (int i = 1; i < visiblePoints; i++) {
int x1 = (int) ((i - 1) * hstep);
int x2 = (int) (i * hstep);
int y1 = (int)pts[i - 1];
int y2 = (int)pts[i];
g2.drawLine(x1, y1, x2, y2);
}
// plot a rectangle for each of the local peaks
for(int m=0;m<=(numPeaks-1);m++){
if(i==(int)(PeakList.get(m)){
int currentVal = (int)pts[(int)(PeakList.get(m)];
g2.drawRect((int)(PeakList.get(m), currentVal, 6, 6);
}
}
This section of code is for handling the right-clicking of the mouse:
public void mousePressed(MouseEvent e){
// check to see if right mouse button was clicked
boolean jones = (e.getModifiers()&InputEvent.BUTTON3_MASK)==InputEvent.BUTTON3_MASK;
if(jones==true){
// test the value returned as x-coordinate when user right-clicks (code always underestimates x-coordinate of local peaks by this test)
double ReverseHstep = visiblePoints/getWidth();
int getX_ConvertedTo_i = (int) (e.getX()*ReverseHstep);
System.out.println("getX_ConvertedTo_i is: "+getX_ConvertedTo_i );
// check to see if peaklist contains a value within the x-coordinates of the user-selected-rectangle
if(PeakList.contains((double)(e.getX()-3))
||PeakList.contains((double)(e.getX()-2))
||PeakList.contains((double)(e.getX()-1))
||PeakList.contains((double)(e.getX()))
||PeakList.contains((double)(e.getX()+1))
||PeakList.contains((double)(e.getX()+2))
||PeakList.contains((double)(e.getX()+3))
){
// handling code will go here, but for now it is a print test that never succeeds because x-coordinate is always underestimated
System.out.println("You just selected a peak!");
}
}
repaint();
}
I suggest you create objects (in this case Rectangles) for each thing you want to be clickable. Here is an over-simplified example of how you can make something you draw clickable. The key thing to take away from this is the mouseClicked method which will display a dialog only if the mouse clicked within the rectangle.
One tricky point is that I wasn't able to figure out how to make the rectangle filled in with color without drawing another rectangle over it. I'll leave that one for you ;-)
public class Canvas extends JPanel implements MouseListener{
private Rectangle rect = new Rectangle(100,100);
public Canvas(){
this.addMouseListener(this);
rect.setSize(100, 100);
}
#Override
public void paintComponent(Graphics g){
g.setClip(rect);
g.setColor(Color.RED);
g.fillRect(0, 0, 100, 100);
}
#Override
public void mouseClicked(MouseEvent e){
if(rect.contains(e.getPoint())){
JOptionPane.showConfirmDialog(this, "Click!");
}
}
// The rest of the MouseListener methods have been cut out
public static void main(String[] a){
JFrame frame = new JFrame("Canvas Thingy");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setBounds(0, 0, 300, 300);
frame.add(new Canvas());
frame.setVisible(true);
}
}