my goal is, that if my mouse is inside a square, that exact suqare lights up. But that isnt happening. If i move my mouse in the lower right corner all squares light up.
I've already looked up a similar post to this, but it didnt quite help me.
this is the code of my mouse class
public void mouseMoved(MouseEvent e) {
int mouseX = e.getX();
int mouseY = e.getY();
for (int y = 100; y < 500; y += 106) {
for (int x = 10; x < 700; x += 86) {
Rectangle rec = new Rectangle(x + 2, y + 2, x + 80, y + 100);
if (mouseX > rec.getMinX() && mouseX < rec.getMaxX()
&& mouseY > rec.getMinY() && mouseY < rec.getMaxY())
{
GUI.MousePos = true;
} else {
GUI.MousePos = false;
}
}
}
}
}
this is the code of my GUI class, where I create the rectangles and the colors
for (int y = 100; y < 500; y += 106) {
for (int x = 10; x < 700; x += 86) {
if (counter != Tag.MaxDay()) {
if (Tag.getArray(counter) == dayOfMonth - 1 && MousePos == true){
g.setColor(myGreenSpecial);
}
else if (Tag.getArray(counter) == dayOfMonth - 1 && MousePos == false)
g.setColor(myGreen_Date);
else if (MousePos == true)
g.setColor(myGreen_Date);
else {
g.setColor(myGreen);
}
g.fillRoundRect(x + 2, y + 2, 80, 100, 10, 10); // tage rechteck
g.setColor(Color.WHITE);
g.drawRoundRect(x + 2, y + 2, 80, 100, 10, 10);
counter++;
g.drawString("" + counter, x + 10, y + 70);
}
}
}
The problem is in your first block of code. You seem to be correctly identifying whether or not the mouse is inside the rectangles, but you aren't storing that information correctly. There's only one boolean, GUI.MousePos, that's trying to track the state of every rectangle. In effect, every rectangle is set to be highlighted the same way, and only the last value (the bottom right corner) is actually displayed.
You either need to change that to an array of booleans, one for each rectangle, or keep track of the index of the highlighted rectangle, instead of just using a boolean.
Related
I'm trying to have a square change colors from black to white and from white to black whenever the square is clicked on. I use the mouseClicked function to do so, but the problem is that the mouseClicked is not clicking correctly. When I click on the bottom of one square, the square underneath of it is pressed.
Here's my mouseClicked code:
addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
mouseX = e.getX();
mouseY = e.getY();
System.out.println(mouseX + ", " + mouseY + ", " + (screenW / squares));
colorFlip();
}
});
My colorFlip code:
private void colorFlip() {
for (int i = 0; i < cells.size(); i++) {
Cell cell = cells.get(i);
int x = cell.getX();
int y = cell.getY();
int side = cell.getSide();
if (mouseX >= x && mouseX < x + side && mouseY >= y && mouseY < y + side) {
if (cell.getR() == 0) {
cell.setRGB(255, 255, 255);
} else if (cell.getR() == 255) {
cell.setRGB(0, 0, 0);
}
}
}
mouseX = -1;
mouseY = -1;
}
And my cell initialization code:
Cell(double xVal, double yVal, double sideVal) {
x = xVal;
y = yVal;
side = sideVal;
}
Thanks,
Pranav
I am creating a game sort of based on the Game of Life and Death. The goal of the project is when the cells turn white they will reproduce with other nearby cells, and when they are black they will die randomly. This part of the game I want to implement and have it run based on the state of the cells (life or death).
Currently, when the cells are white and the mouse is pressed the cell will turn white and stay white until the mouse is unclicked and clicked again. When they are black they will be erased if the mouse is over them. Unfortunately, that also removes the array value from the matrix I use to keep track of the current cells. How can I use matrixes without getting an Array Index out of bounds error? I've tried adding a second if statement to search for nearby cells, but it searches even if the cells aren't drawn. I including the entire code here as I do not want to exclude any parts. For reference, I am using Processing 3 for Java.
int value = 0;
int cols, rows;
int scl = 20;
boolean[][] matrix = new boolean[scl+1][scl+1];
boolean life;
boolean death;
void setup() {
frameRate(25);
size(400, 400);
int w = 400;
int h = 400;
cols = w / scl;
rows = h / scl;
}
void draw() {
background(255);
for (int x = 0; x < cols; x++) {
for (int y = 0; y < rows; y++) {
int xpos = x*scl;
int ypos = y*scl;
//cell border color
stroke(55);
if ((mouseX >= xpos && mouseX <= xpos+scl) &&
(mouseY >= ypos && mouseY <= ypos+scl)) {
if (mousePressed == true) {
//println("Clicked at: " + xpos + " and " + ypos);
if (!matrix[xpos/scl][ypos/scl]) {
matrix[xpos/scl][ypos/scl] = true;
if (life){
matrix[xpos/scl][ypos/scl] = true;
println("Living at " + xpos + " and " + ypos);
}
if (death){
matrix[xpos/scl][ypos/scl] = false;
println("Dying at " + xpos + " and " + ypos);
}
} else {
matrix[xpos/scl][ypos/scl] = false;
}
//fill(100);
fill(value);
}
//println("Mouse at: " + xpos + " and " + ypos);
} else {
fill(50);
}
if (matrix[x][y]) {
fill(value);
}
rect(xpos, ypos, scl, scl);
}
}
}
void mousePressed() {
if (value == 0) {
life = true;
death = false;
value = 245;
} else {
life = false;
death = true;
value = 0;
}
}
I am creating a battle ship game, where each round the player can select 4 ship routes by selecting the 4 closest tiles to him, with a mouse.
Now in the following gif, you can see if I will hover on the very edge of a tile, it will select two tiles at once, or even 4 at once if you're holding your mouse in middle of 4 tiles:
(source: gyazo.com)
This should not really be happening in the game, how can I prevent that?
This is the updating code:
/**
*
* #param x mouse X
* #param y mouse Y
*/
public void checkHover(int x, int y) {
for (int i = 0; i < tiles[0].length; i++) {
for (int j = 0; j < tiles[1].length; j++) {
// get coordinates from tile
int x1 = i * (sprite.getWidth() - 1);
int y1 = j * (sprite.getHeight() - 1);
// If we have screen translate, we can cancel it for
// this situation
int realX = x - this.translate.getX();
int realY = y - this.translate.getY();
// checking if mouse inside tile
if (realX >= x1 && realX <= x1 + sprite.getWidth() &&
realY >= y1 && realY <= y1 + sprite.getHeight()) {
// set tile to hovered sprite
this.tiles[i][j].setHover(true);
}
else {
// cancel hovered sprite
this.tiles[i][j].setHover(false);
}
}
}
}
How can I prevent that?
Instead of the two loops I would calculate the index of the 2d array based off the x and y position of the mouse, by dividing the x and y position by how much space there is from one tile to the next (which looks to be the tile width plus 1, the empty border). This will cause border hovers to favor a certain side, but it looks like you don't want to select two tiles anyways.
Once you have the index of the tile, switch the highlight on, and keep a reference to it with an instance variable like lastHighlightedTile, but before you do that, also call lastHighlightedTile.setHover(false);.
If the index of the tile is invalid, as if the mouse is out of the tile area, don't access the array and still call lastHighlightedTile.setHover(false);.
This should fix highlighting multiple tiles, and will also allow you to turn off the previous highlight (the solution of breaking out of the current loop might not turn off the previous highlight).
Assuming width of sprite is equal to 50, I see that first title has x1 to x2 coordinate (0 - 50), second title has (49 - 100), third has (99 - 150)... Same for y dimension.
So when pointer is at (x) = (50), it hovers (x1 - x2) (0-50) and (49-100) titles.
Why are you subtracting 1 from sprite width / height?
try with this:
// get coordinates from tile
int x1 = i * (sprite.getWidth());
int y1 = j * (sprite.getHeight());
Edit: I wrote sample app, which shoved me solution:
public class App {
Tile[][] tiles;
Sprite sprite;
public static void main(String[] args) {
App app = new App();
app.init();
app.checkHover(50, 50);
app.printHovers();
}
private void init() {
sprite = new Sprite();
tiles = new Tile[10][10];
for (int i = 0; i < tiles[0].length; i++) {
for (int j = 0; j < tiles[1].length; j++) {
tiles[i][j] = new Tile();
}
}
}
public void checkHover(int x, int y) {
for (int i = 0; i < tiles[0].length; i++) {
for (int j = 0; j < tiles[i].length; j++) {
// get coordinates from tile
int x1 = i * (sprite.getWidth());
int y1 = j * (sprite.getHeight());
// If we have screen translate, we can cancel it for
// this situation
// int realX = x - this.translate.getX();
// int realY = y - this.translate.getY();
int realX = x;
int realY = y;
// checking if mouse inside tile
if (realX >= x1 && realX < x1 + sprite.getWidth()
&& realY >= y1 && realY < y1 + sprite.getHeight()) {
// set tile to hovered sprite
this.tiles[i][j].setHover(true);
} else {
// cancel hovered sprite
this.tiles[i][j].setHover(false);
}
}
}
}
public void printHovers() {
for (int i = 0; i < tiles[0].length; i++) {
for (int j = 0; j < tiles[i].length; j++) {
System.out.print((tiles[i][j].isHover() ? "Y" : "O") + " ");
}
System.out.println();
}
}
public class Sprite {
public int getWidth() {
return 50;
}
public int getHeight() {
return 50;
}
}
public class Tile {
private boolean hover;
public boolean isHover() {
return hover;
}
public void setHover(boolean hover) {
this.hover = hover;
}
}
}
It works fine for (49, 49), (49, 50), (50, 49) and (50, 50) coords.
So, first you have to remove -1 subtractions, and change <= test to <.
EDIT: Different solution:
Simply declare a boolean at the beginning of the method, and set only if that boolean is still false. Once you set the tile on, also set the boolean to true, which will prevent others from being set on.
public void checkHover(int x, int y) {
boolean hasTurnedOneOn = false;
for (int i = 0; i < tiles[0].length; i++) {
for (int j = 0; j < tiles[1].length; j++) {
// get coordinates from tile
int x1 = i * (sprite.getWidth() - 1);
int y1 = j * (sprite.getHeight() - 1);
// If we have screen translate, we can cancel it for
// this situation
int realX = x - this.translate.getX();
int realY = y - this.translate.getY();
// checking if mouse inside tile
if (realX >= x1 && realX <= x1 + sprite.getWidth() &&
realY >= y1 && realY <= y1 + sprite.getHeight() && !hasTurnedOneOn) {
// set tile to hovered sprite
this.tiles[i][j].setHover(true);
hasTurnedOneOn = true;
}
else {
// cancel hovered sprite
this.tiles[i][j].setHover(false);
}
}
}
}
Pardon my naivety, its my first time here and first time dealing with animation of graphics in java. I'm trying to accomplish an animation of star shapes that moves along a sort of arc(trying to simulate an orbit on a 2d wise). The orbit Action is used with a Timer to animate the stars.
Simply put, I have drawn several stars at various positions in a jpanel. The translation of the stars y position depends on how far that star is away from the the x axis of decline which is initialized to 300(the center of the jpanel). The closer a star is to the point of decline, the less their y position is going to change. When a star reaches or passes the right side of the panel(or goes out of view), reset to the left side at its original y position(ugly, i know). I chose to do it this way since the stars are placed at random. I cant have all the stars start with the same dy, if it were so, all the stars would move along their own arc instead.
However, when I run this, after the third pass, the x positions of all the stars become smaller(into the negative ranges and out of view). Any suggestions for a better way to accomplish the original task are welcome. Thanks.
private Action orbit = new AbstractAction() {
int declineAxis = 300; //if a stars top left x is greater than this, move downwards
double distFromDecline;
AffineTransform at = new AffineTransform();
#Override
public void actionPerformed(ActionEvent ae) {
for (int i = 0; i < 12; i++) {
distFromDecline = Math.abs(declineAxis - stars.getStar(i).getBounds().getCenterX());
if (distFromDecline <= 50) {
if (stars.getStar(i).getBounds().getX() < declineAxis) {
at.translate(5, -2);
} else {
at.translate(5, 2);
}
} else if (distFromDecline <= 100 && distFromDecline > 50) {
if (stars.getStar(i).getBounds().getX() < declineAxis) {
at.translate(5, -3);
} else {
at.translate(5, 3);
}
} else if (distFromDecline <= 200 && distFromDecline > 100) {
if (stars.getStar(i).getBounds().getX() < declineAxis) {
at.translate(5, -4);
} else {
at.translate(5, 4);
}
} else if (distFromDecline >200) {
if (stars.getStar(i).getBounds().getX() < declineAxis) {
at.translate(5, -5);
} else {
at.translate(5, 5);
}
}
stars.move(at, i);
}
}
};
public class Stars {
private int[] yOrigins;
private Path2D[] stars;
private Random rand = new Random();
public Stars(int n) {
stars = new Path2D[n];
yOrigins = new int[n];
int dx = 700 / n;
int x = 0;
for (int i = 0; i < n; i++) {
int y = rand.nextInt(401);
generateStar(i, x, y);
yOrigins[i] = y;
x += dx;
}
}
private void generateStar(int i, int x, int y) {
stars[i] = new Path2D.Double();
Path2D.Double cur = (Path2D.Double) stars[i];
cur.moveTo(x, y);
cur.lineTo(cur.getCurrentPoint().getX() + 6, y - 2);
cur.lineTo(cur.getCurrentPoint().getX() + 2, cur.getCurrentPoint().getY() - 6);
cur.lineTo(cur.getCurrentPoint().getX() + 2, cur.getCurrentPoint().getY() + 6);
cur.lineTo(cur.getCurrentPoint().getX() + 6, cur.getCurrentPoint().getY() + 2);
cur.lineTo(cur.getCurrentPoint().getX() - 6, cur.getCurrentPoint().getY() + 2);
cur.lineTo(cur.getCurrentPoint().getX() - 2, cur.getCurrentPoint().getY() + 6);
cur.lineTo(cur.getCurrentPoint().getX() - 2, cur.getCurrentPoint().getY() - 6);
cur.closePath();
}
public void paintStars(Graphics2D g) {
//super.paintComponent(g);
g.setColor(new Color(246, 246, 255));
for (int i = 0; i < stars.length; i++) {
g.fill(stars[i]);
}
}
public Shape getStar(int i) {
return stars[i];
}
void move(AffineTransform at, int i) {
stars[i] = (Path2D) stars[i].createTransformedShape(at);
System.out.println(i+": " + stars[i].getBounds());
if(stars[i].getBounds().getX()>700){
at.translate(-(stars[i].getBounds().x+stars[i].getBounds().getWidth()), yOrigins[i]);
stars[i] = (Path2D) at.createTransformedShape(stars[i]);
}
}
}
java.awt.geom.FlatteningPathIterator
http://docs.oracle.com/javase/6/docs/api/java/awt/geom/FlatteningPathIterator.html
You pass your arc (or any another Shape) and use the points to position star.
You can use stars frm here
http://java-sl.com/shapes.html
WarpImage from the Sun/Oracle Java2D demo, java2d/demos/Images/WarpImage.java, is an appealing example of an animation that follows a CubicCurve2D using PathIterator. You might see if it offers any guidance.
I jumped into Processing (the language) today. I've been trying to implement a line without the line() function. In other words, I'm trying to replicate the line() function with my own code. I'm almost there, but not. (There's a screen, and you can click around, and this function connects those clicks with lines.)
There are four different line slopes I'm dealing with (m>1, 0
If you could just glance at the following code, and tell me where I've gone wrong, I'd be grateful.
int xStart = -1; // Starting x and y are negative.
int yStart = -1; // No lines are drawn when mouseReleased() and x/y are negative.
boolean isReset = false; // Turns true when 'r' is pressed to reset polygon chain.
int clickCounter = 0; // Changes background color every 10 clicks (after c is pressed).
color backgroundColor = 0; // Starting background color. Changed occasionally.
color lineColor = 255;
int weight = 1;
void setup() {
size(800, 800); // Initial size is 800x800
background(backgroundColor); // ...background is black.
smooth();
stroke(lineColor); //... lines/points are white.
strokeWeight(weight);
}
void draw() {
}
void mousePressed(){
clickCounter++;
}
void mouseReleased(){ // mouseReleased used instead of mousePressed to avoid dragged clicks.
point(mouseX, mouseY); // Draws white point at clicked coordinates.
if((xStart < 0 && yStart < 0) || isReset){ // If x/y negative or if r was pressed, set start points and return. No line drawn.
xStart = mouseX;
yStart = mouseY;
isReset = false; // Reset isReset to false.
return;
}
// Sends starting and ending points to createLine function.
createLine(xStart, yStart, mouseX, mouseY); // createLine(...) - Creates line from start point to end point.
xStart = mouseX; // Start point = last click location. End point = Current click location.
yStart = mouseY; // Sets starting coordinates for next click at current click point.
}
void keyPressed(){
if(key == 'x') // EXTRA CREDIT ADDITION: If x is pressed -> Exit program.
exit();
else if(key == 'c'){ // EXTRA CREDIT ADDITTION: If c pressed -> Set background black to clear all lines/points on screen.
if(clickCounter > 10){
backgroundColor = color(random(255), random(255), random(255)); // EXTRA CREDIT ADDITION: If cleared and clickCounter is greater
clickCounter = 0; // ...than 10, background changes to random color.
}
background(backgroundColor);
xStart = -1; // Must set points negative so line is not drawn after next new point is made (since there will only be one point on the screen).
yStart = -1;
}
else if(key == 'r'){ // If r pressed -> Reset: Next click will create new point that isn't connected with line to current points.
isReset = true;
lineColor = color(random(255), random(255), random(255)); // EXTRA CREDIT ADDITION: When dot chain is "reset", line changes color.
weight = (int)random(10);
strokeWeight(weight); // EXTRA CREDIT ADDITION: ...and line/dot thickness changes.
stroke(lineColor);
}
else
return;
}
// createLine(): Function which draws line from (x0,y0) to (x1,y1).
void createLine(int x0, int y0, int x1, int y1){
// 1) Line function draws from left to right. (Does not work right to left.) Check and swap points if ending point is left of starting point.
if(x1 < x0){
print("LEFT TO RIGHT SWITCH. \n");
createLine(x1, y1, x0, y0); // Drawing the line left to right cuts the number of line types we have to deal with to 4 regions.
return; // Regions: slope > 1; 0 < slope < 1; -1 < slope < 0; slope < -1.
}
// Declare/Initialize data needed to draw line with midpoint algorithm.
int dx = x1 - x0;
int dy = y1 - y0; //dy = Negative when y0 is lower on screen than y2, because origin is top left.
print(y0 + " " + x0 + " " +y1 + " " + x1+ " x y \n");
print(dy + " " + dx + " dx dy\n");
// Handle vertical & horizontal lines...
if(dx == 0 || dy == 0){ // If slope is vertical or horizontal, create line with simple function.
while(y1 != y0){ // If vertical -> Paint by incrementing/decrementing y until points connect.
if(y1 > y0){ // If new point is above -> Draw upwards.
y0 = y0 + 1;
point(x0, y0);
}
else{ // It new point below -> Draw downwards.
y0 = y0 - 1;
point(x0, y0);
}
}
while(x1 != x0){ // If horizontal -> Paint by incrementing x until points connect (will be left to right line always).
x0 = x0 + 1;
point(x0, y0);
}
return;
}
// Handle slanted lines...
double tempDX = x1 - x0;
double tempDY = y1 - y0; // Had to create dx and dy as doubles because typecasting dy/dx to a double data type wasn't working.
double m = (-tempDY / tempDX); // m = line slope. (Note - The dy value is negative because positive y is downwards on the screen.)
print("SLOPE CALCULATED: " + m + "\n");
int deltaN = (2 * -dx); // deltaX is the amount to increment d after choosing the next pixel on the line.
int deltaNE = (2 * (-dy - dx)); // ...where X is the direction moved for that next pixel.
int deltaE = (2 * -dy); // deltaX variables are used below to plot line.
int deltaSE = (2 * (dy + dx));
int deltaS = (2 * dx);
int x = x0;
int y = y0;
int d = 0; // d = Amount d-value changes from pixel to pixel. Depends on slope.
int region = 0; // region = Variable to store slope region. Different regions require different formulas.
if(m > 1){ // if-statement: Initializes d, depending on the slope of the line.
d = -dy - (2 * dx); // If slope is 1-Infiniti. -> Use NE/N initialization for d.
region = 1;
}
else if(m == 1)
region = 2;
else if(m > 0 && m < 1){
d = (2 * -dy) - dx; // If slope is 0-1 -> Use NE/E initialization for d.
region = 3;
}
else if(m < 0 && m > -1){
d = (2 * dy) + dx; // If slope is 0-(-1) -> Use E/SE initliazation for d.
region = 4;
}
else if(m == -1)
region = 5;
else if(m < -1){
d = dy + (2 * dx); // If slope is (-1)-(-Infiniti) -> Use SE/S initialization for d.
region = 6;
}
while(x < x1){ // Until points are connected...
if(region == 1){ // If in region one...
if(d <= 0){ // and d<=0...
d += deltaNE; // Add deltaNE to d, and increment x and y.
x = x + 1;
y = y - 1;
}
else{
d += deltaN; // If d > 0 -> Add deltaN, and increment y.
y = y - 1;
}
}
else if(region == 2){
x = x + 1;
y = y - 1;
}
else if(region == 3){
if(d <= 0){
d += deltaE;
x = x + 1;
}
else{
d += deltaNE;
x = x + 1;
y = y - 1;
}
}
else if(region == 4){
if(d <= 0){
d += deltaSE;
x = x + 1;
y = y + 1;
}
else{
d += deltaE;
x = x + 1;
}
}
else if(region == 5){
x = x + 1;
y = y + 1;
}
else if(region == 6){
if(d <= 0){
d += deltaSE;
x = x + 1;
y = y + 1;
}
else{
d += deltaS;
y = y + 1;
}
}
point(x, y);
}
return;
}
When programs pause, look for while() loops that don't resolve properly. I inserted the following println statements into your while loop to print out what was happening. Then I recreated the problematic condition and quit the program, and checked the console for signs of what was going wrong.
println("top of the while loop to ya...");
println("x: " + x + ", x1: " + x1);
println("region: " + region + ", d: " + d);
It looks like region 6 is causing the pausing problem. If d > 0, it is never decreased and x is never increased, so there is no way to satisfy the while condition.
With the same set of statements you can troubleshoot the inaccurate line issue. It occurs in region 4, but I'll leave the details as an exercise.