I'm creating a Hangman game where a player enters a word and the other player tries to guess that word. There are 26 JButtons on the screen (with each letter of the alphabet).
Each time a correct letter is chosen a counter variable increments. The number of the counter variable dictates how much of the hangman is drawn (7 is when the hangman is fully drawn). I can get counter to increment when the correct letter is chosen but I cannot get parts of the hangman to be drawn when it does increment.
Here is my Hangman class that draws the Hangman and includes the incrementCounter method:
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
public class HangMan extends JPanel implements ActionListener {
private int xS = 8;
private int yS = 30;
public int counter;
private Color hatColor = Color.BLACK;
private int dx = 0;
private int dy = 0;
public HangMan(int initalX, int initalY) {
// starting location
xS = initalX;
yS = initalY;
counter = 0;
Dimension dim = new Dimension(250, 475);
this.setPreferredSize(dim);
setFocusable(true);
requestFocusInWindow();
this.setVisible(true);
}
public void drawHangMan(Graphics g) {
g.setColor(Color.BLACK);
if (counter == 0) {
repaint();
}
if (counter == 1) {
drawHat(xS + 15, yS - 1, 20, 25, g); // hat
drawBrim(xS + 10, yS + 25, 30, 6, g); // brim
repaint();
}
if (counter == 2) {
drawHat(xS + 15, yS - 1, 20, 25, g); // hat
drawBrim(xS + 10, yS + 25, 30, 6, g); // brim
drawHead(xS, yS + 30, 50, 50, g); // head
repaint();
}
if (counter == 3) {
drawHat(xS + 15, yS - 1, 20, 25, g); // hat
drawBrim(xS + 10, yS + 25, 30, 6, g); // brim
drawHead(xS, yS + 30, 50, 50, g); // head
drawBody(xS + 25, yS + 80, xS + 25, yS + 175, g); // body
repaint();
}
if (counter == 4) {
drawHat(xS + 15, yS - 1, 20, 25, g); // hat
drawBrim(xS + 10, yS + 25, 30, 6, g); // brim
drawHead(xS, yS + 30, 50, 50, g); // head
drawBody(xS + 25, yS + 80, xS + 25, yS + 175, g); // body
drawLeftLeg(xS - 20, yS + 225, xS + 25, yS + 175, g); //left leg
repaint();
}
if (counter == 5) {
drawHat(xS + 15, yS - 1, 20, 25, g); // hat
drawBrim(xS + 10, yS + 25, 30, 6, g); // brim
drawHead(xS, yS + 30, 50, 50, g); // head
drawBody(xS + 25, yS + 80, xS + 25, yS + 175, g); // body
drawLeftLeg(xS - 20, yS + 225, xS + 25, yS + 175, g); //left leg
drawRightLeg(xS + 25, yS + 175, xS + 65, yS + 225, g); //right leg
repaint();
}
if (counter == 6) {
drawHat(xS + 15, yS - 1, 20, 25, g); // hat
drawBrim(xS + 10, yS + 25, 30, 6, g); // brim
drawHead(xS, yS + 30, 50, 50, g); // head
drawBody(xS + 25, yS + 80, xS + 25, yS + 175, g); // body
drawLeftLeg(xS - 20, yS + 225, xS + 25, yS + 175, g); //left leg
drawRightLeg(xS + 25, yS + 175, xS + 65, yS + 225, g); //right leg
drawLeftArm(xS - 20, yS + 90, xS + 25, yS + 120, g); //left arm
repaint();
}
if (counter == 7) {
drawHat(xS + 15, yS - 1, 20, 25, g); // hat
drawBrim(xS + 10, yS + 25, 30, 6, g); // brim
drawHead(xS, yS + 30, 50, 50, g); // head
drawBody(xS + 25, yS + 80, xS + 25, yS + 175, g); // body
drawLeftLeg(xS - 20, yS + 225, xS + 25, yS + 175, g); //left leg
drawRightLeg(xS + 25, yS + 175, xS + 65, yS + 225, g); //right leg
drawLeftArm(xS - 20, yS + 90, xS + 25, yS + 120, g); //left arm
drawRightArm(xS + 25, yS + 120, xS + 70, yS + 90, g); //right arm
repaint();
}
}
public void drawLeftArm(int a, int b, int x, int y, Graphics g) {
g.drawLine(a, b, x, y); //left arm
repaint();
}
public void drawRightArm(int a, int b, int x, int y, Graphics g) {
g.drawLine(a, b, x, y); //left arm
repaint();
}
public void drawLeftLeg(int a, int b, int x, int y, Graphics g) {
g.drawLine(a, b, x, y); //left arm
repaint();
}
public void drawRightLeg(int a, int b, int x, int y, Graphics g) {
g.drawLine(a, b, x, y); //left arm
repaint();
}
public void drawBody(int a, int b, int x, int y, Graphics g) {
g.drawLine(a, b, x, y); //left arm
repaint();
}
public void drawHead(int a, int b, int x, int y, Graphics g) {
g.drawOval(a, b, x, y); //left arm
repaint();
}
public void drawHat(int a, int b, int x, int y, Graphics g) {
g.drawRect(a, b, x, y); //left arm
repaint();
}
public void drawBrim(int a, int b, int x, int y, Graphics g) {
g.drawRect(a, b, x, y); //left arm
repaint();
}
public void drawHanger(Graphics g) {
g.fillRect(xS - 125, yS + 300, 80, 20);
g.drawLine(xS - 85, yS + 300, xS - 85, yS + 80);
g.drawLine(xS - 85, yS + 80, xS + 22, yS + 80);
}
public void incrementCounter() {
counter++;
System.out.println("counter = " + counter);
repaint();
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
drawHangMan(g);
drawHanger(g);
repaint();
g.setFont(new Font("Sherif", Font.BOLD, 40));
}
public void actionPerformed(ActionEvent e) {
repaint();
}
}
Now here is my Button Class that draws the 26 JButtons and includes the ActionListener that will call the update method every time a button is clicked
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JPanel;
public class Button extends JPanel {
JButton[] grid = new JButton[26];
Dashes dash;
public Button(String str, Dashes dash) {
this.dash = dash;
final String alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
Dimension dim = new Dimension(360, 360);
this.setPreferredSize(dim);
ActionListener listener = new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
String action = e.getActionCommand();
System.out.println(action);
dash.update(action);
dash.repaint();
/*
add(new JLabel(action + ""));
setVisible(true);
*/
}
};
for (int i = 0; i < grid.length; i++) {
grid[i] = (JButton) this.add(new JButton(alphabet.charAt(i) + ""));
grid[i].addActionListener(listener);
this.setVisible(true);
}
}
}
and here is my Dashes class that contains the update method
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.Line2D;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class Dashes extends JPanel {
JLabel label;
String word;
String guess = "";
HangMan hang;
public Dashes(String word) {
this.word = word;
hang = new HangMan(150, 150);
for (int i = 0; i < word.length(); i++) {
guess += " ";
}
word = word.toUpperCase();
Dimension dim = new Dimension(1500, 300);
this.setPreferredSize(dim);
this.setVisible(true);
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
drawDashes(g2d);
}
private void drawDashes(Graphics2D g2d) {
for (int i = 0; i < word.length() * 50; i += 50) {
g2d.draw(new Line2D.Double(100.0 + i, 200.0, 125.0 + i, 200.0));
for (int j = 0; j < guess.length(); j++) {
g2d.drawString(guess.charAt(j) + "", 108 + j * 50, 198);
}
// g2d.drawString("m", 108 + i, 198);
}
}
public void update(String str) {
for (int i = 0; i < word.length(); i++) {
if (str.equals(word.charAt(i) + "")) {
guess = guess.substring(0, i) + str + guess.substring(i + 1);
hang.incrementCounter();
hang.repaint();
}
}
}
}
I'm sorry for making such a small problem so long. I would like to mention that if I initially set counter to be 2, for example, it would correctly draw the hat, brim and head. Some background: I was assigned a Java graphics project without ever actually having been taught graphics!
1 - Remove repaint() from the paint logic (as said in comment)
2 - in Dashes.update() use String.equalsIgnoreCase() instead of String.equals() (probably you have lowercase word and are comparing with uppercase charactere from the Button class).
3 - in Dashes.update() increment counter and repaint HangMan only if you miss:
public void update(String str) {
boolean found = false;
for (int i = 0; i < word.length(); i++) {
if (str.equalsIgnoreCase(word.charAt(i) + "")) {
guess = guess.substring(0, i) + str + guess.substring(i + 1);
found = true;
}
}
if(!found) {
hang.incrementCounter();
hang.repaint();
}
}
Related
How can I create a slider with two arrow buttons from the side? The arrows/triangle should turn white when clicked. And the slider should move each time the arrow button is clicked.
here's the link to what it should look like
and here's what I've done so far
int x=75;
void setup() {
size(600,400);
}
void draw() {
background(100);
fill (200);
rect (75, 25, 400, 50);
stroke(0);
if(mousePressed) {
if (mouseX >75 && mouseX <= 475)
{x=mouseX;}
}
fill(127,0,0);
rect (x, 20, 9, 60);
fill (255);
fill (200);
rect (10, 25, 50, 50);
{
if (mousePressed == true) {
fill(255);
} else {
fill(0);
}
triangle (50, 60, 50, 40, 15, 50);
}
fill (200);
rect (490, 25, 50, 50);
{
if (mousePressed == true) {
fill(255);
} else {
fill(0);
}
triangle (500, 60, 500, 40, 535, 50);
}
println(x);
}
When I click anywhere on the screen, my problem is that both arrows turn white. I need it to individually function. And the slider is not moving every time I click the arrow buttons
The following approach to this problem uses 4 different classes: ForwardArrow, BackArrow, Slider, and ValueField. Arrow fill color is controlled by the press() method of its respective class.
color BLUE = color(64, 124, 188);
color LTGRAY = color(185, 180, 180);
color YELLOW = color(245, 250, 13);
color RED = color(255, 0, 0);
color BLACK = color(0, 0, 0);
color WHITE = color(255, 255, 255);
color GREEN = color(32, 175, 47);
ForwardArrow _fwdArrw;
BackArrow _backArrw;
ValueField _valueFld;
Slider _slider;
final int _sliderX = 90;
final int _sliderY = 40;
final int _sliderW = 200;
final int _sliderH = 30;
final int _txtSize = 22;
final int _initValue = 40;
final int _maxValue = 200;
final int _minValue = 0;
int value = _initValue;
class ValueField {
float x, y, w, h;
String title;
color fldColor;
color txtColor;
// Constructor
ValueField(int xpos, int ypos, float wt, float ht, String valueStr, color background, color foreground) {
x = xpos;
y = ypos;
w = wt;
h = ht;
title = valueStr;
fldColor = background;
txtColor = foreground;
}
void display(int val) {
// **** Value Field **** //
fill(fldColor); // erase old value
rect(x, y, w, h);
fill(txtColor); // text color
textSize(_txtSize);
textAlign(CENTER);
text(str(val), x, y, w, h);
// **** Slider bar **** //
fill(255);
rect(_sliderX, _sliderY, _sliderW*val/_maxValue, _sliderH);
}
}
class ForwardArrow {
float x, y, w, h;
color arrwColor;
// Constructor
ForwardArrow(int xpos, int ypos, float wt, float ht, color background) {
x = xpos;
y = ypos;
w = wt;
h = ht;
arrwColor = background;
}
void display() {
fill(arrwColor); // arrow color
noStroke();
triangle(x, y, x, y + h, x + w, y + h/2 );
}
void press() {
fill(255); // arrow color
noStroke();
triangle(x, y, x, y + h, x + w, y + h/2 );
}
}
class BackArrow {
float x, y, w, h;
color arrwColor;
// Constructor
BackArrow(int xpos, int ypos, float wt, float ht, color background) {
x = xpos;
y = ypos;
w = wt;
h = ht;
arrwColor = background;
}
void display() {
fill(arrwColor);
noStroke();
triangle(x, y + h/2, x + w, y, x + w, y + h );
}
void press() {
fill(255);
noStroke();
triangle(x, y + h/2, x + w, y, x + w, y + h );
}
}
class Slider {
float x, y, w, h;
color barColor;
color trimColor;
// Constructor
Slider(int xpos, int ypos, float wt, float ht, color background, color foreground) {
x = xpos;
y = ypos;
w = wt;
h = ht;
barColor = background;
trimColor = foreground;
}
void display() {
stroke(0);
strokeWeight(1);
noFill();
rect(x, y, w, h);
}
}
void setup() {
size(500, 250);
background(BLUE);
_slider = new Slider(_sliderX, _sliderY, _sliderW, _sliderH, WHITE, BLACK);
_backArrw = new BackArrow(50, 40, 30, 30, GREEN);
_fwdArrw = new ForwardArrow(300, 40, 30, 30, GREEN);
_valueFld = new ValueField(380, 40, 60, 30, str(_initValue), WHITE, BLACK);
}
void draw() {
background(BLUE);
_valueFld.display(value);
_fwdArrw.display();
_backArrw.display();
_slider.display();
// FwdArrw Long Press
if ((mouseX >= _fwdArrw.x) && (mouseX <= _fwdArrw.x + _fwdArrw.w) && (mouseY >= _fwdArrw.y) && (mouseY <= _fwdArrw.y + _fwdArrw.h)) {
if (mousePressed == true) {
_fwdArrw.press();
value++;
if (value > _maxValue) {
value = _maxValue;
}
_valueFld.display(value);
}
}
// BackArrw Long Press
if ((mouseX >= _backArrw.x) && (mouseX <= _backArrw.x + _backArrw.w) && (mouseY >= _backArrw.y) && (mouseY <= _backArrw.y + _backArrw.h)) {
if (mousePressed == true) {
_backArrw.press();
value--;
if (value < _minValue) {
value = _minValue;
}
_valueFld.display(value);
}
}
}
A revision of your code follows;
int x=75;
void setup() {
size(600, 400);
}
void draw() {
background(100);
fill (200);
rect (75, 25, 400, 50); // slider bar
stroke(0);
fill(127, 0, 0);
rect (x, 20, 9, 60); // slider thumb
fill (200);
rect (10, 25, 50, 50); // back arrow
fill(0);
triangle (50, 60, 50, 40, 15, 50);
if ((mouseX >= 10) && (mouseX <= 10 + 50) && (mouseY >= 25) && (mouseY <= 25 + 50) ) {
if (mousePressed == true) {
fill(255);
triangle (50, 60, 50, 40, 15, 50);
x--;
if (x<75) {
x = 75; // minValue
}
} else {
fill(0);
triangle (50, 60, 50, 40, 15, 50);
}
}
fill (200);
rect (490, 25, 50, 50); //forward arrow
fill(0);
triangle (500, 60, 500, 40, 535, 50);
if ((mouseX >= 490) && (mouseX <= 490 + 50) && (mouseY >= 25) && (mouseY <= 25 + 50) ) {
if (mousePressed == true) {
fill(255);
triangle (500, 60, 500, 40, 535, 50);
x++;
if (x>466) {
x = 466; // maxValue
}
} else {
fill(0);
triangle (500, 60, 500, 40, 535, 50);
}
}
}
You've got part of the logic right for the slider/trackbar so it changes x only within a range. This happens horizontally only at this stage, but you can use the same logic to check horizontal limits as well. Similarly, you can check if the cursor is within the bounds of any rectangle (be it the slider or either of the buttons):
int x=75;
void setup() {
size(600, 400);
}
void draw() {
background(100);
// slider
fill (200);
rect (75, 25, 400, 50);
stroke(0);
if (mousePressed) {
if (mouseX >75 && mouseX <= 475)
{
x=mouseX;
}
}
fill(127, 0, 0);
rect (x, 20, 9, 60);
fill (255);
// left arrow button
fill (200);
rect (10, 25, 50, 50);
fill(0);
if (mousePressed == true) {
if (mouseX > 10 && mouseX <= 10 + 50 && mouseY > 25 && mouseY <= 25 + 50){
fill(255);
}
}
triangle (50, 60, 50, 40, 15, 50);
// right arrow button
fill (200);
rect (490, 25, 50, 50);
fill(0);
if (mousePressed == true) {
if (mouseX > 490 && mouseX <= 490 + 50 && mouseY > 25 && mouseY <= 25 + 50){
fill(255);
}
}
triangle (500, 60, 500, 40, 535, 50);
println(x);
}
Wouldn't it be nice if you could take that logic and instead of copy/pasting the different x,y,width,height parameters for the same 4 statements you could group that functionality in a reusable block of code ?
That what functions are for. You're already using them already (defining setup()/draw(), calling background()/fill()/etc.
The Processing Button example already provides the boolean overRect(int x, int y, int width, int height) function which is perfect for you're trying to achieve: pass in the x,y,width,height or a button and get back boolean value.
Here's your code using the overRect():
int x=75;
void setup() {
size(600, 400);
}
void draw() {
background(100);
// slider
fill (200);
rect (75, 25, 400, 50);
stroke(0);
if (mousePressed) {
if (mouseX >75 && mouseX <= 475)
{
x=mouseX;
}
}
fill(127, 0, 0);
rect (x, 20, 9, 60);
fill (255);
// left arrow button
fill (200);
rect (10, 25, 50, 50);
fill(0);
if (mousePressed && overRect(10, 25, 50, 50)) {
fill(255);
x--;
}
triangle (50, 60, 50, 40, 15, 50);
// right arrow button
fill (200);
rect (490, 25, 50, 50);
fill(0);
if (mousePressed && overRect(490, 25, 50, 50)){
fill(255);
x++;
}
triangle (500, 60, 500, 40, 535, 50);
// ensure x remains within the slide limits
x = constrain(x, 75, 475);
println(x);
}
boolean overRect(int x, int y, int width, int height) {
if (mouseX >= x && mouseX <= x+width &&
mouseY >= y && mouseY <= y+height) {
return true;
} else {
return false;
}
}
I'm getting this error: The nested type cannot hide an enclosing type. I have looked it up, and other people seem to be declaring their class twice, which I am not.
What's weird is if I copy and paste the code into a new processing document, it works with no error. But as I'm converting it to js i need it to work with no errors after saving and opening again.
MotorBike Bike1, Bike2, Bike3, Bike4, Bike5, Bike6, Bike7, Bike8, Bike9;
int Score_Bike1 = 0;
int Score_Bike2 = 0;
int Score_Bike3 = 0;
int Score_Bike4 = 0;
int Score_Bike5 = 0;
int Score_Bike6 = 0;
int Score_Bike7 = 0;
int Score_Bike8 = 0;
int Score_Bike9 = 0;
String Score_Spacing = " ";
int GameState = 0;
class MotorBike {
float Pos_X;
int Pos_Y;
float Speed;
int Size = 30;
float WheelSize = Size / 3;
color Color;
MotorBike(int Declare_X, int Declare_Y, int Declare_Speed, color Declare_Color)
{
this.Pos_X = Declare_X;
this.Pos_Y = Declare_Y;
Speed = Declare_Speed;
Color = Declare_Color;
}
void move()
{
if (GameState == 1) {
Speed = (random(0, 50) / 10);
Pos_X = Pos_X + Speed;
}
}
void render()
{
fill(Color);
triangle(Pos_X, Pos_Y, Pos_X + Size, Pos_Y, Pos_X + Size / 2, Pos_Y -Size / 2);
fill(255);
strokeWeight(1.5);
ellipse(Pos_X, Pos_Y, WheelSize, WheelSize);
ellipse(Pos_X + Size, Pos_Y, WheelSize, WheelSize);
}
}
void setup()
{
size(700, 600);
background(200);
SpawnBikes();
}
void draw()
{
background(200);
strokeWeight(3);
line(50, 10, 50, 590);
line(650, 10, 650, 590);
strokeWeight(1);
MoveBikes();
DetectWinner();
DisplayScore();
}
void MoveBikes()
{
Bike1.render();
Bike1.move();
Bike2.render();
Bike2.move();
Bike3.render();
Bike3.move();
Bike4.render();
Bike4.move();
Bike5.render();
Bike5.move();
Bike6.render();
Bike6.move();
Bike7.render();
Bike7.move();
Bike8.render();
Bike8.move();
Bike9.render();
Bike9.move();
}
void DetectWinner()
{
textSize(15);
fill(0);
if (Bike1.Pos_X >= 620) {
noLoop();
text("Bike 1 Wins", 310, 10, 350, 50);
Score_Bike1 += 1;
GameState = 2;
}
if (Bike2.Pos_X >= 620) {
noLoop();
text("Bike 2 Wins", 310, 10, 350, 50);
Score_Bike2 += 1;
GameState = 2;
}
if (Bike3.Pos_X >= 620) {
noLoop();
text("Bike 3 Wins", 310, 10, 350, 50);
Score_Bike3 += 1;
GameState = 2;
}
if (Bike4.Pos_X >= 620) {
noLoop();
text("Bike 4 Wins", 310, 10, 350, 50);
Score_Bike4 += 1;
GameState = 2;
}
if (Bike5.Pos_X >= 620) {
noLoop();
text("Bike 5 Wins", 310, 10, 350, 50);
Score_Bike5 += 1;
GameState = 2;
}
if (Bike6.Pos_X >= 620) {
noLoop();
text("Bike 6 Wins", 310, 10, 350, 50);
Score_Bike6 += 1;
GameState = 2;
}
if (Bike7.Pos_X >= 620) {
noLoop();
text("Bike 7 Wins", 310, 10, 350, 50);
Score_Bike7 += 1;
GameState = 2;
}
if (Bike8.Pos_X >= 620) {
noLoop();
text("Bike 8 Wins", 310, 10, 350, 50);
Score_Bike8 += 1;
GameState = 2;
}
if (Bike9.Pos_X >= 620) {
noLoop();
text("Bike 9 Wins", 310, 10, 350, 50);
Score_Bike9 += 1;
GameState = 2;
}
}
void DisplayScore()
{
textSize(15);
fill(0);
text("Bike 1: " + Score_Bike1 + Score_Spacing + "Bike 2: " + Score_Bike2 + Score_Spacing + "Bike 3: " +
Score_Bike3 + Score_Spacing + "Bike 4: " + Score_Bike4 + Score_Spacing + "Bike 5: " + Score_Bike5 + Score_Spacing +
"Bike 6: " + Score_Bike6 + Score_Spacing + "Bike 7: " + Score_Bike7 + Score_Spacing + "Bike 8: " + Score_Bike8 +
Score_Spacing + "Bike 9: " + Score_Bike9, 65, 530, 635, 700);
}
void keyPressed()
{
if (keyPressed) {
if (key == ' ')
{
if (GameState == 0) {
GameState = 1;
}
if (GameState == 2) {
loop();
background(200);
SpawnBikes();
GameState = 0;
}
}
}
}
void SpawnBikes()
{
Bike1 = new MotorBike(50, 100, 2, color(255, 0, 0));
Bike2 = new MotorBike(50, 150, 2, color(0, 255, 0));
Bike3 = new MotorBike(50, 200, 2, color(0, 0, 255));
Bike4 = new MotorBike(50, 250, 2, color(255, 255, 0));
Bike5 = new MotorBike(50, 300, 2, color(0, 255, 255));
Bike6 = new MotorBike(50, 350, 2, color(255, 0, 255));
Bike7 = new MotorBike(50, 400, 2, color(100, 255, 0));
Bike8 = new MotorBike(50, 450, 2, color(0, 100, 255));
Bike9 = new MotorBike(50, 500, 2, color(255, 0, 100));
}
Your problem is caused by the fact that you're naming your sketch the same thing as a class you're using inside your sketch. Your sketch can't be named MotorBike if you have a MotorBike class inside that sketch.
Either rename your sketch, or rename your class.
Behind the scenes, this is because Processing exports your sketch as a Java class, and any classes in your sketch become inner classes of that Java class. So your sketch becomes something like this:
class MotorBike{
void draw(){
//whatever
}
class MotorBike{
int x;
//whatever
}
}
This is illegal Java, which is what's causing your error. You can't have an inner class with the same name as a parent class. In other words, a nested type cannot hide an enclosing type.
This is also why it works okay when you copy it into a new sketch- Processing gives your sketch a random default name, so you don't have this name collision until you save your sketch as something else.
I have a programme where there are sticky notes. You click on them to pick them up and click again to place them somewhere. My problem is when there are two or more sticky notes on top of each other they both get picked up I only want the top one to be picked up. How can I fix this here is my code so far:
public class PhoneMsg {
public int x, y, id, hour, minute;
public boolean drag = false;
public String name, lastname, msg, msg2, msg3;
public Rectangle rx = new Rectangle(x + 290, y, 20, 20);
public Rectangle rdrag = new Rectangle(x, y, 310, 20);
public boolean remove;
private Image img;
public PhoneMsg(int x, int y, String name, String lastname, int hour, int minute, int id) {
this.x = x;
this.y = y;
this.name = name;
this.lastname = lastname;
this.hour = hour;
this.minute = minute;
this.id = id;
rdrag = new Rectangle(x, y, 310, 20);
rx = new Rectangle(x + 290, y, 20, 20);
genMsg();
}
public void tick() {
rx = new Rectangle(x + 290, y, 20, 20);
rdrag = new Rectangle(x, y, 310, 20);
if (rx.intersects(Comp.mx, Comp.my, 1, 1)) {
if (Comp.ml) {
remove = true;
for (int i = 0; i < play.ph.pp.toArray().length; i++) {
// play.ph.pp.get(i).canreadtxt = true;
}
}
}
// dragging
if (drag) {
x = Comp.mx - 140;
y = Comp.my - 10;
}
if (msg == null) {
genMsg();
}
}
public void render(Graphics g) {
Graphics2D g2 = (Graphics2D) g;
RenderingHints rh = new RenderingHints(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_GASP);
g2.setRenderingHints(rh);
// display
g.setColor(new Color(19, 165, 34));
g.fillRect(x, y, 310, 150);
g.setColor(new Color(27, 53, 16));
g.drawRect(x, y, 310, 150);
g.setColor(new Color(27, 53, 16));
g.drawRect(x, y, 310, 20);
// Exit part
g.setColor(new Color(27, 53, 16));
g.drawRect(rx.x, rx.y, rx.width, rx.height);
g.setColor(Color.red);
g.setFont(new Font("italic", Font.BOLD, 12));
g.drawString("X", rx.x + 7, rx.y + 15);
// name
g.setColor(Color.black);
g.setFont(new Font("italic", Font.BOLD, 12));
g.drawString("" + name + " " + lastname + "'s Recent Messages", x + 5, y + 15);
// details
String msg11 = String.format("%02d:%02d", hour, minute);
String msg21 = String.format("%02d:%02d", hour, minute);
String msg31 = String.format("%02d:%02d", hour, minute);
if(play.hud.wifi >= 1){
g.setColor(Color.CYAN);
g.setFont(new Font("italic", Font.BOLD, 12));
g.drawString(" " + msg, x + 2, y + 38);
g.setColor(Color.white);
g.setFont(new Font("italic", Font.BOLD, 12));
g.drawString(" " + msg2, x + 2, y + 58);
g.setColor(Color.cyan);
g.setFont(new Font("italic", Font.BOLD, 12));
g.drawString(" " + msg3, x + 2, y + 78);
}else if(play.hud.wifi <= 0){
g.setColor(Color.red);
g.setFont(new Font("italic", Font.PLAIN, 18));
g.drawString("Lost Connection", x +90, y +85);
g.setColor(Color.red);
g.setFont(new Font("italic", Font.PLAIN, 18));
g.drawString("_________________", x +70, y +88);
}
}
}
and this is the part in the mouse listener that lets u pick up the sticky notes:
// dragging msg's
for (int i1 = 0; i1 < play.ph.pm.toArray().length; i1++) {
if (play.ph.pm.get(i1).drag == false && play.holding == false) {
if (play.ph.pm.get(i1).rdrag.contains(Comp.mx, Comp.my)) {
play.ph.pm.get(i1).drag = true;
play.holding = true;
}
} else {
play.ph.pm.get(i1).drag = false;
play.holding = false;
}
}
If you break out of the for loop you can pick up the first sticky note the code gets to when they're overlapping.
if (play.ph.pm.get(i1).rdrag.contains(Comp.mx, Comp.my)) {
play.ph.pm.get(i1).drag = true;
play.holding = true;
break; // Found sticky note, exits loop
}
Or if this conflicts with your else statement, simply create a flag.
// dragging msg's
boolean gotCard = false;
for (int i1 = 0; i1 < play.ph.pm.toArray().length; i1++) {
if (play.ph.pm.get(i1).drag == false && play.holding == false && gotNote == false) { // Added gotNote check
if (play.ph.pm.get(i1).rdrag.contains(Comp.mx, Comp.my)) {
play.ph.pm.get(i1).drag = true;
play.holding = true;
gotNote = true; // Set flag to true
}
} else {
play.ph.pm.get(i1).drag = false;
play.holding = false;
}
}
However you should probably have a z-index implemented to be able to tell which sticky note is on top then sort your array by that z-index.
Ive created a game of Craps which is a dice based game. Ive created my game logic but am trying to implement a GUI. Ive created my Dice and Dice Component for both dice. If i add my Dice to the frame one at a time they both work, but as soon as i try and add both to the frame at the same time and run my Craps game, the frame is empty.
CrapsGame code:
package crapsgame;
import java.awt.FlowLayout;
import javax.swing.*;
public class CrapsGameTester
{
/**
* #param args the command line arguments
*/
public static void main(String[] args)
{
JFrame frame = new JFrame("Craps-Game");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setResizable(false);
final int FRAME_WIDTH = 400;
final int FRAME_HEIGHT = 600;
frame.setSize(FRAME_HEIGHT, FRAME_WIDTH);
CrapsGame game = new CrapsGame();
JPanel panel = new JPanel(new FlowLayout());
frame.add(panel);
Dice1Component dice1 = new Dice1Component(6);
Dice2Component dice2 = new Dice2Component(6);
panel.add(dice1);
panel.add(dice2);
String message = game.doFirstRoll();
System.out.println(message);
while(!game.isOver())
{
message = game.rollAgain();
System.out.println(message);
}
if(game.isWon())
System.out.println("You win, big man!");
else
System.out.println("Loser ...");
frame.setVisible(true);
}
}
Dice1 code:
package crapsgame;
import java.awt.*;
public class Dice1
{
int sides;
int xCoord = 150;
int yCoord = 130;
public Dice1(int s)
{
sides = s;
}
/**
*
* #param g2 Graphics2D object used by draw method
*/
public void draw(Graphics2D g2)
{
g2.setColor(Color.BLACK);
g2.fillRect(xCoord, yCoord, 100, 100);
g2.setColor(Color.WHITE);
switch (sides)
{
case 1:
g2.fillOval(xCoord + 40, yCoord + 40, 20, 20);
break;
case 2:
g2.fillOval(xCoord + 15, yCoord + 15, 20, 20);
g2.fillOval(xCoord + 65, yCoord + 65, 20, 20);
break;
case 3:
g2.fillOval(xCoord + 15, yCoord + 15, 20, 20);
g2.fillOval(xCoord + 40, yCoord + 40, 20, 20);
g2.fillOval(xCoord + 65, yCoord + 65, 20, 20);
break;
case 4:
g2.fillOval(xCoord + 15, yCoord + 15, 20, 20);
g2.fillOval(xCoord + 15, yCoord + 65, 20, 20);
g2.fillOval(xCoord + 65, yCoord + 15, 20, 20);
g2.fillOval(xCoord + 65, yCoord + 65, 20, 20);
break;
case 5:
g2.fillOval(xCoord + 15, yCoord + 15, 20, 20);
g2.fillOval(xCoord + 15, yCoord + 65, 20, 20);
g2.fillOval(xCoord + 65, yCoord + 15, 20, 20);
g2.fillOval(xCoord + 65, yCoord + 65, 20, 20);
g2.fillOval(xCoord + 40, yCoord + 40, 20, 20);
break;
case 6:
g2.fillOval(xCoord + 20, yCoord + 20, 20, 20);
g2.fillOval(xCoord + 20, yCoord + 45, 20, 20);
g2.fillOval(xCoord + 20, yCoord + 70, 20, 20);
g2.fillOval(xCoord + 60, yCoord + 20, 20, 20);
g2.fillOval(xCoord + 60, yCoord + 45, 20, 20);
g2.fillOval(xCoord + 60, yCoord + 70, 20, 20);
break;
}
}
}
Dice1Component code:
package crapsgame;
import java.awt.*;
import javax.swing.*;
public class Dice1Component extends JComponent
{
private int sides;
public Dice1Component(int s)
{
sides = s;
}
public void setSide(int s)
{
sides = s;
}
#Override
public void paintComponent(Graphics g)
{
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
Dice1 dice1 = new Dice1(sides);
dice1.draw(g2);
}
}
I read that to add more than one component to a frame you must use a JPanel but this doesn't seem to work for me either.
There are a couple of issues (in addition to those mentioned in comments), but these should make the code work:
You should override the preferred size in Dice1Component so that the layout manager can
reserve it the correct space
#Override
public Dimension getPreferredSize() {
return new Dimension(100, 100);
}
remove xCoord and yCoord from Dice1. The coordinates used are relative to the component, so a large offset will try to draw outside the component area
Take a look at the tutorial how you should create and access components only in the event dispatch thread.
I've come across a problem when trying to move a custom polygon around a JPanel with the mouse; the location for the polygon never updates, even on repaint:
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.MouseMotionAdapter;
import java.awt.event.MouseMotionListener;
import java.awt.event.MouseEvent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import java.util.ArrayList;
import java.util.List;
public class Figure extends JPanel{
/**
*
*/
private static final long serialVersionUID = 1L;
public int nPoints = 17, x = 120, y = -60;
int MouseX, MouseY;
final static int SIZE = 400;
public int[] xPoints = {x + 100, x + 85, x + 70, x + 55, x + 40, x + 55, x + 55, x + 40, x + 25, x + 55, x + 55, x + 85, x + 85, x + 115, x + 100, x + 85, x + 85};
public int[] yPoints = {y + 375, y + 385, y + 340, y + 385, y + 375, y + 335, y + 200, y+ 240, y + 225, y + 185, y + 175, y + 175, y + 185, y + 220, y + 240, y + 200, y + 335, y + 375};
List<Integer> xList = new ArrayList<Integer>();
List<Integer> yList = new ArrayList<Integer>();
static final Figure m = new Figure();
public static void main(String[] args){
final JFrame frame = new JFrame();
frame.setTitle("Figure");
frame.getContentPane().add(m);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(SIZE, SIZE);
frame.setResizable(true);
frame.setVisible(true);
m.setBackground(Color.darkGray);
}
public void mouseMovement(){
addMouseMotionListener(new MouseMotionAdapter(){
public void mouseDragged(MouseEvent e){
if(((e.getX() >= xPoints[8] && e.getX() <= xPoints[13]) && (e.getY() >= yPoints[10] && e.getY() <= yPoints[1])) || ((e.getX() >= (x + 45) && e.getX() <= (x + 45 + SIZE / 8)) && (e.getY() >= (y + 102) && e.getY() <= (y + 102 + SIZE / (57 / 10))))){
x = e.getX() - 75;
y = e.getY() - 150;
repaint();
}else{
repaint();
}
}
});
}
public Figure(){
mouseMovement();
}
#Override
public void paint(Graphics g){
super.paint(g);
g.setColor(Color.black);
g.fillPolygon(xPoints, yPoints, nPoints);
g.fillPolygon(xPoints, yPoints, nPoints);
g.setColor(Color.white);
g.fillOval(x + 45, y + 102, SIZE / 8, SIZE / (57 / 10));
}
}
My thoughts on this are that the integer array is not updating properly using my predefined variables, but then I come across the problem of not knowing how to properly update it. It seems like it should, considering the location for the oval i made to represent the figure's "head" does, but apparently I'm wrong on that, so I'd like to know why just using the array in fillPolygon doesn't work and how I'd get the location to update. Many thanks in advance.
Use the Polygon class to create a Polygon using your Array of points.
Then in the painting method you can cast the Graphics object to a Graphics2D object and use the Graphics2D.fill(Shape) method to paint the polygon.
When you need to move the Polygon you can use the translate(...) method of the Polygon class.
Also, you should NOT be overriding the paint() method. Custom painting is done by overriding the paintComponent() method.