thank you for helping me.
I'm making random panel generator.
first, user chooses what shape to draw and my code randomly draw 1~10 shapes on JFrame.
Next, user can choose Kth panel and change its color.
But, here's the problem: Once it added to JFrame, it won't change color.
for example, if I change 1st shape color to red and show it, its color change to red. But I change 1st shape color to blue, it won't change.
Before show it, its color changes well if I don't show it on JFrame.
I discovered that I can solve this by making a new application each time before showing it, but My purpose is to use only one JFrame.
Here's my code.
import java.awt.*;
import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;
import java.util.Scanner;
public class Shapes
{
private class TransparentPanel extends JPanel
{
{
setOpaque(false);
}
}
public static void main(String[] args)
{
enginePart();
}
static void enginePart()
{
JFrame application= new JFrame();
btnConstructor makeBtn = new btnConstructor();
makeShapes panel = new makeShapes(0,0,0,0,0,0,0);
randomNumMemorize memorizeIt = new randomNumMemorize();
Random getRandomNum = new Random();
int[] thirdChoice = new int[2], KthShapeCntField = new int[10000];
int memorizeItArr[][][] = new int[10000][25][10];
//3차원 배열을 선언하여 저장. 1번째 칸에는 도형의 코드, 2번째 칸에는 k번째 도형의 각각 갯수, 3번째 칸에는 k번째 도형의 정보를 담습니다.
int makeItCnt, thirdChoiceOfK, thirdChoiceOfColor;
int applicationWidth=500, applicationHeight=500, choiceCnt=0;
application.setSize(applicationWidth, applicationHeight);
application.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
while(true)
{
int first_choice = makeBtn.optionBtn();
//입력하기, 색깔바꾸기, 종료하기 중 하나 선택
if(first_choice==0)
{//입력하기 선택
int secondChoice = makeBtn.drawSelected();//사용자 도형 설정
makeItCnt = getRandomNum.nextInt(9)+1;//생성할 도형 개수 지정
KthShapeCntField[choiceCnt] = makeItCnt;
for(int i=0;i<makeItCnt;i++)
{
memorizeItArr[choiceCnt][i] = memorizeIt.randomNumMemorize(secondChoice, 0);
}
choiceCnt+=1;
//k번째 도형 == choiceCnt
continue;
}
else if(first_choice==1)
{//k번째 도형 색깔 바꾸기 선택
System.out.println("==============REDRAW!!================");
thirdChoice = makeBtn.changeColorSelected();//k 선택부
thirdChoiceOfK = thirdChoice[0] - 1;//콤퓨타는 0부터 세니까 여기서 1 빼줍니다.
thirdChoiceOfColor = thirdChoice[1];
int temp= thirdChoiceOfK, i=0;
if(thirdChoiceOfK == -1 || thirdChoiceOfColor==-1) continue;
while(temp-KthShapeCntField[i]>=0)
{
temp-=KthShapeCntField[i++];
}
memorizeItArr[i][temp][5] = thirdChoiceOfColor;
continue;
}
else
{//추가동작 선택
/*JFrame application= new JFrame();
application.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
application.setSize(500,500);*/
int fourthChoice = makeBtn.additionalActionSelected();
if(fourthChoice==0)
{//도형 숨기기
hide(panel, application, applicationWidth, applicationHeight);
continue;
}
else if(fourthChoice==1)
{//도형 보이기
int temp=0;
application.revalidate();
application.repaint();
for(int i=0;i<choiceCnt;i++)
{
for(int j=0; j<KthShapeCntField[i]; j++)
{
panel = new makeShapes(choiceCnt, memorizeItArr[i][j][0], memorizeItArr[i][j][1], memorizeItArr[i][j][2], memorizeItArr[i][j][3], memorizeItArr[i][j][4], memorizeItArr[i][j][5]);
panel.validate();
panel.repaint();
application.add(panel);
panel.setOpaque(false);//투명화
System.out.printf("%dth Shape color is: %d\n",temp++, memorizeItArr[i][j][5]);
application.setVisible(true);
}
}
}
else
{//종료
System.exit(0);
}
}
}
}
static void hide(makeShapes panel, JFrame application, int width, int height)
{
panel = new makeShapes(-1,100,0,0,width,height,100);
application.add(panel);
application.setVisible(true);
}
}
class makeShapes extends JPanel
{
private int choice, x, y, size1, size2;
private int color=0, cnt;// 0:red, 1:green, 2:blue, 3:yellow, 4:purple 5:black
public makeShapes(int cnt, int choice, int x, int y, int size1, int size2, int usrColor)
{
this.choice = choice;
this.x = x;
this.y = y;
this.size1 = size1;
this.size2 = size2;
this.color = usrColor;
this.cnt = cnt;
}
public void paintComponent(Graphics g)
{
super.paintComponent(g);
String s_cnt = Integer.toString(this.cnt);
switch(color)
{
case 100:
g.setColor(Color.WHITE);
break;
case 1:
g.setColor(Color.red);
break;
case 2:
g.setColor(Color.green);
break;
case 3:
g.setColor(Color.blue);
break;
case 4:
g.setColor(Color.yellow);
break;
case 5: case 0:
g.setColor(Color.BLACK);
break;
}
switch (choice)
{
case 100:
g.fillRect(0,0,500,500);
break;
case 0:
g.drawOval(x, y, size1, size2);
break;
case 1:
g.drawRect(x, y, size1, size2);
break;
case 2:
g.drawLine(x,y, x+size1, x+size2);
break;
}
}
}
class randomNumMemorize
{
Random getRandom = new Random();
private int choice, x, y, size1, size2, cnt;
private int color=1;
public int[] randomNumMemorize(int usrchoice, int usrcolor)
{
this.choice = usrchoice;
this.x = getRandom.nextInt(400);
this.y = getRandom.nextInt(400);
this.size1 = getRandom.nextInt(100)+1;
this.size2 = getRandom.nextInt(100)+1;
this.color = usrcolor;
int[] retArr = {choice, x, y, size1, size2, color};
return retArr;
}
}
class btnConstructor
{
public int optionBtn()
{
String btn_msg[] = {"Draw Shapes", "Change Color", "Additional Action"};
int num = JOptionPane.showOptionDialog(null,"Choose what you want.","User choice",JOptionPane.YES_NO_CANCEL_OPTION,JOptionPane.QUESTION_MESSAGE,null,btn_msg,"Draw Shapes");
return num;
}
public int drawSelected()
{
String btn_msg[] = {"Circle", "Rectangle", "Line"};
int num = JOptionPane.showOptionDialog(null,"Choose your shape","Shape choice",JOptionPane.YES_NO_OPTION,JOptionPane.QUESTION_MESSAGE,null,btn_msg,"Circle");
return num;
}
public int[] changeColorSelected()
{
int choiceOfK, choiceOfColor;
String numOfK = JOptionPane.showInputDialog("Enter number that you want to change color");
String numOfColor = JOptionPane.showInputDialog("Which Color do you prefer?\nRed:1 Green:2 Blue:3 Yellow:4 Black:5");
if(numOfK==null || numOfColor==null) choiceOfK = choiceOfColor=-1;
else {
choiceOfK = Integer.parseInt(numOfK);
choiceOfColor = Integer.parseInt(numOfColor);
}
int[] return_it = {choiceOfK, choiceOfColor};
return return_it;
}
public int additionalActionSelected()
{
String btn_msg[] = {"Hide", "Show", "Exit"};
int num = JOptionPane.showOptionDialog(null,"Choose your action","User choice",JOptionPane.YES_NO_OPTION,JOptionPane.QUESTION_MESSAGE,null,btn_msg,"Restore");
return num;
}
}
I've tried this:
panel.revalidate();
panel.repaint();
application.revalidate();
application.repaint();
Related
I'm currently making a snake game in java. First I created a class named GamePanel for my snake. And here I wrote the codes of the apple eaten by the snake, the codes of the snake, and the movements of the snake in this class. Now I want to create another class by taking some codes from them. So I created a separate Data class for this and put the information I wrote at the beginning of the GamePanel.
There was a method in the GamePanel that I called newApple. I placed it in a separate class called SnakeFoodApple. After that, come to GamePanel and
public SnakeFoodApple apple = new SnakeFoodApple();
I wrote this code. Where there is newApple, I said apple.newApple.
I'm running the game now and I'm not getting any errors. But it does not perform the event of throwing apples at random different places, which is the feature of newApple. So the apple is always in the same coordinates. How can I solve this?
Also, how is it possible to transfer information on both sides in this transition between classes? So, can I switch from class A to class B and from class B to class A? If I can, with what code can I do it?
My code;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.Random;
public class GamePanel extends JPanel implements ActionListener {
public SnakeFoodApple apple = new SnakeFoodApple();
static final int SCREEN_WIDTH = 600;
static final int SCREEN_HEIGHT = 600;
static final int UNIT_SIZE = 25;
static final int GAME_UNITS = (SCREEN_WIDTH * SCREEN_HEIGHT) / UNIT_SIZE;
static final int DELAY = 75;
final int X[] = new int[GAME_UNITS];
final int Y[] = new int[GAME_UNITS];
int bodyParts = 6;
int applesEaten;
int appleX;
int appleY;
char direction = 'R';
boolean running = false;
Timer timer;
Random random = new Random();
GamePanel() {
random = new Random();
this.setPreferredSize(new Dimension(SCREEN_WIDTH, SCREEN_HEIGHT));
this.setBackground(Color.black);
this.setFocusable(true);
this.addKeyListener(new MyKeyAdapter());
startGame();
}
public void startGame() {
apple.newApple();
running = true;
timer = new Timer(DELAY, this);
timer.start();
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
draw(g);
}
public void draw(Graphics g) {
if (running) {
g.setColor(Color.red);
//g.fillOval(int X, int Y, Width, Height)
g.fillOval(appleX, appleY, UNIT_SIZE, UNIT_SIZE);
for (int i = 0; i < bodyParts; i++) {
if (i == 0) {
g.setColor(Color.green);
g.fillRect(X[i], Y[i], UNIT_SIZE, UNIT_SIZE);
} else {
g.setColor(new Color(random.nextInt(255), random.nextInt(255), random.nextInt(255)));
g.fillRect(X[i], Y[i], UNIT_SIZE, UNIT_SIZE);
}
}
g.setColor(Color.red);
g.setFont(new Font("Ink Free", Font.BOLD, 40));
FontMetrics metrics = getFontMetrics(g.getFont());
g.drawString("SCORE: " + applesEaten, (SCREEN_WIDTH - metrics.stringWidth("SCORE: " + applesEaten)) / 2, g.getFont().getSize());
} else {
gameOver(g);
}
}
public void move() {
for (int i = bodyParts; i > 0; i--) {
X[i] = X[i - 1];
Y[i] = Y[i - 1];
}
switch (direction) {
case 'U':
Y[0] = Y[0] - UNIT_SIZE;
break;
case 'D':
Y[0] = Y[0] + UNIT_SIZE;
break;
case 'L':
X[0] = X[0] - UNIT_SIZE;
break;
case 'R':
X[0] = X[0] + UNIT_SIZE;
break;
}
}
public void checkApple() {
if ((X[0] == appleX) && (Y[0] == appleY)) {
bodyParts++;
applesEaten++;
apple.newApple();
}
}
public void checkCollisions() {
for (int i = bodyParts; i > 0; i--) {
if ((X[0] == X[i]) && (Y[0] == Y[i])) {
running = false;
}
}
if (X[0] < 0) {
running = false;
}
if (X[0] > SCREEN_WIDTH) {
running = false;
}
if (Y[0] < 0) {
running = false;
}
if (Y[0] > SCREEN_HEIGHT) {
running = false;
}
if (!running) {
timer.stop();
}
}
public void gameOver(Graphics g) {
g.setColor(Color.red);
g.setFont(new Font("Ink Free", Font.BOLD, 40));
FontMetrics metrics1 = getFontMetrics(g.getFont());
g.drawString("SCORE: " + applesEaten, (SCREEN_WIDTH - metrics1.stringWidth("SCORE: " + applesEaten)) / 2, g.getFont().getSize());
g.setColor(Color.red);
g.setFont(new Font("Ink Free", Font.BOLD, 75));
FontMetrics metrics2 = getFontMetrics(g.getFont());
g.drawString("GAME OVER", (SCREEN_WIDTH - metrics2.stringWidth("GAME OVER")) / 2, SCREEN_HEIGHT / 2);
}
//class GamePanel' ı implements (implıments) ettiğimiz için otomotik olarak geldi
#Override
public void actionPerformed(ActionEvent e) {
if (running) {
move();
checkApple();
checkCollisions();
}
repaint();
}
public class MyKeyAdapter extends KeyAdapter {
#Override
public void keyPressed(KeyEvent e) {
switch (e.getKeyCode()) {
case KeyEvent.VK_LEFT:
if (direction != 'R') {
direction = 'L';
}
break;
case KeyEvent.VK_RIGHT:
if (direction != 'L') {
direction = 'R';
}
break;
case KeyEvent.VK_UP:
if (direction != 'D') {
direction = 'U';
}
break;
case KeyEvent.VK_DOWN:
if (direction != 'U') {
direction = 'D';
}
break;
}
}
}
}
public class SnakeFoodApple extends Data{
public void newApple(){
appleX = random.nextInt((int) (SCREEN_WIDTH / UNIT_SIZE)) * UNIT_SIZE;
appleY = random.nextInt((int) (SCREEN_HEIGHT / UNIT_SIZE)) * UNIT_SIZE;
}
}
import java.util.Random;
import javax.swing.Timer;
public class Data {
static final int SCREEN_WIDTH = 600;
static final int SCREEN_HEIGHT = 600;
static final int UNIT_SIZE = 25;
static final int GAME_UNITS = (SCREEN_WIDTH * SCREEN_HEIGHT) / UNIT_SIZE;
static final int DELAY = 75;
final int X[] = new int[GAME_UNITS];
final int Y[] = new int[GAME_UNITS];
int bodyParts = 6;
int applesEaten;
int appleX;
int appleY;
char direction = 'R';
boolean running = false;
Timer timer;
Random random = new Random();
}
Your code is a bit of a mess - sorry to be that harsh, but could not find a "softer" expression:
You have the same member fields in GamePanel and in Data.
You extend Data with SnakeFoodApple but the only thing you add or change in the extended class is a method to set some member fields of the parent class.
You did not declare any field with a visibility other than default (aka package private).
What you see is cause from a combination of the three topics above. You have to get rid of the class SnakeFoodApple, that single method can easily go into Data (you can rename Data afterwards back to SnakeFoodApple if you like that name.
Also all those static fields in Data should not be static, but normal member fields, and initialized in a constructor rather than having fixed initializers.
Finally you must not store appleX and appleY in your main class GamePanel but access them from Data every time you need the values. Create getters for that.
Also clean up Data from all values you are not actually using inside there. Don't forget to remove unnecessary imports.
Per request: this would be my implementation of Data (renamed to SnakeFoodApple):
package examples.stackoverflow.q71987622;
import java.util.Random;
public class SnakeFoodApple {
private final int screenWidth;
private final int screenHeight;
private final int unitSize;
private final Random random = new Random();
private int appleX;
private int appleY;
public SnakeFoodApple(int screenWidth, int screenHeight, int unitSize) {
this.screenWidth = screenWidth;
this.screenHeight = screenHeight;
this.unitSize = unitSize;
}
public void newApple() {
appleX = random.nextInt(screenWidth / unitSize) * unitSize;
appleY = random.nextInt(screenHeight / unitSize) * unitSize;
}
public int getX() {
return appleX;
}
public int getY() {
return appleY;
}
}
To fix your problem, you have then to replace every appleX and appleY in the class GamePanel with a apple.getX() respectively apple.getY().
Since you didn't provide a [mre], and the code doesn't run on it's own, I could not really test this, but there are a lot of possible improvements left in the GamePanel.
I might be missing something, but it looks as though you have forgotten to fillOval using apple here:
public void draw(Graphics g) {
if (running) {
g.setColor(Color.red);
//g.fillOval(int X, int Y, Width, Height)
g.fillOval(appleX, appleY, UNIT_SIZE, UNIT_SIZE);
Should probably be:
g.fillOval(this.apple.appleX, this.apple.appleY, this.apple.UNIT_SIZE, this.apple.UNIT_SIZE);
I'm not clear why you have all this in GamePanel still, is this not supposed to be happening in Data (SnakeFoodApple) now?
static final int SCREEN_WIDTH = 600;
static final int SCREEN_HEIGHT = 600;
static final int UNIT_SIZE = 25;
static final int GAME_UNITS = (SCREEN_WIDTH * SCREEN_HEIGHT) / UNIT_SIZE;
static final int DELAY = 75;
final int X[] = new int[GAME_UNITS];
final int Y[] = new int[GAME_UNITS];
int bodyParts = 6;
int applesEaten;
int appleX;
int appleY;
char direction = 'R';
boolean running = false;
Timer timer;
Random random = new Random();
In general, it is good practice to set fields as private and use getters and setters. It would be good to look at that.
I'm not sure what you mean by your second question.
I have created a game similar to snake in which the user is first prompted with a jpanel asking which difficulty they want, and whatever JButton they pick influences the size of the map as well as the delay between the snake movements. I have the map size working just fine, but the delay variable never seems to change. I suspect it has something to do with the way the timer is being casted, but I have no idea how to fix it. I am also wondering how when the program is first ran it seems some of the variables don't update, but the second time it is ran all of them are updated. Here is my class with the original variables and collision detection:
import java.util.Random;
import javax.swing.JLabel;
public class GameEngine extends JPanel implements ActionListener{
//creates the size of the panel as well as creating the resolution for all objects, including the players and food.
static final int sWidth = 600;
static final int sHeight = 600;
public static int size = 24;
static int objectSize = (sHeight*sWidth) / size;
public static int delay = 100;
final int playerX[] = new int[objectSize];
final int playerY[] = new int[objectSize];
int bodySize = 4;
int score = 0;
int appleX;
int appleY;
char direction = 'D';
boolean started = false;
Random random;
Timer timer;
boolean easy;
JLabel score1;
public static String difficulty;
GameEngine(){
random = new Random();
this.setPreferredSize(new Dimension(sWidth,sHeight));
this.setBackground(Color.black);
this.setFocusable(true);
this.addKeyListener(new UserMovement());
gameStart();
}
public void gameStart() {
newApple();
started = true;
timer = new Timer(delay,this);
timer.start();
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
draw(g);
}
public void drawHead(Graphics g) {
g.setColor(new Color(100,252,0));
g.fillRect(playerX[0], playerY[0], size, size);
}
public void draw(Graphics g) {
if(started) {
//draws the apples
g.setColor(Color.red);
g.fillOval(appleX, appleY, size, size);
for (int i = 0; i < bodySize; i++) {
if(i == 0) {
drawHead(g);
}
else {
g.setColor(new Color(60,180,0));
g.fillRect(playerX[i], playerY[i], size, size);
}
}
g.setColor(Color.white);
g.setFont(new Font("Bold", Font.BOLD, 20));
FontMetrics metrics = getFontMetrics(g.getFont());
g.drawString("Score: " + score,(sWidth - metrics.stringWidth("Score: " + score))/2,g.getFont().getSize());
}
}
public void newApple(){
appleX = random.nextInt((int)(sWidth/size))*size;
appleY = random.nextInt((int)(sHeight/size))*size;
}
//moves the player by using and modifying their coordinates
public void move() {
for (int i = bodySize; i > 0; i--) {
playerX[i] = playerX[i-1];
playerY[i] = playerY[i-1];
}
switch(direction) {
case 'W':
playerY[0] = playerY[0] - size;
break;
case 'S':
playerY[0] = playerY[0] + size;
break;
case 'A':
playerX[0] = playerX[0] - size;
break;
case 'D':
playerX[0] = playerX[0] + size;
break;
}
}
public void checkFood() {
if(playerX[0] == appleX && playerY[0] == appleY)
{
bodySize++;
score++;
newApple();
}
}
public void checkCol() {
//checks for head collision with the body
for(int i = bodySize; i > 0; i--) {
if((playerX[0] == playerX[i]) && (playerY[0] == playerY[i])) {
started = false;
}
}
//checks if head touches any of the walls of the program
if(playerX[0] < 0) {
started = false;
}
if(playerX[0] > sWidth) {
started = false;
}
if(playerY[0] < 0) {
started = false;
}
if(playerY[0] > sHeight) {
started = false;
}
if(started != true) {
timer.stop();
}
}
public void actionPerformed(ActionEvent e){
if(started == true) {
move();
checkFood();
checkCol();
}
repaint();
}
public class UserMovement extends KeyAdapter {
#Override
public void keyPressed(KeyEvent e) {
switch(e.getKeyCode()) {
case KeyEvent.VK_LEFT:
if(direction != 'D') {
direction = 'A';
}
break;
case KeyEvent.VK_RIGHT:
if(direction != 'A') {
direction = 'D';
}
break;
case KeyEvent.VK_UP:
if(direction != 'S') {
direction = 'W';
}
break;
case KeyEvent.VK_DOWN:
if(direction != 'W') {
direction = 'S';
}
break;
}
}
public void keyReleased(KeyEvent e) {
}
public void keyTyped(KeyEvent e) {
}
}
}
and here is the code calling and changing the delay and size variables:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class StartMenu extends JPanel {
StartMenu()
{
JButton easy = new JButton();
JButton hard = new JButton();
this.setPreferredSize(new Dimension(350,240));
this.setLayout(null);
this.setBackground(Color.black);
this.setFocusable(true);
easy.setBounds(75,40,200,40);
hard.setBounds(75,120,200,40);
this.add(easy);
this.add(hard);
easy.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
setVisible(false);
new SnakeStart();
GameEngine.size = 48;
GameEngine.delay = 140;
}
});
hard.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
setVisible(false);
new SnakeStart();
GameEngine.size = 24;
GameEngine.delay = 70;
}
});
}
}
I assume your GameEngine instance is created before the StartMenu action listeners are executed. If that assumption is correct, that means that GameEngine.timer with the default value of delay is created in the GameEngine constructor and is not updated after the delay is changed.
You need to make sure that you explicitly update your timer with the new delay value after StartMenu actions are called.
I've been looking for answers in similar threads here but I can't find out what's wrong with my code.
I'm trying to make an agar.io simulator and the agar object doesn't draw. Food draws but agar doesn't draw regardless of what I do.
Agar class code:
import java.awt.*;
import java.awt.event.*;
public class Agar {
//instance field
public static final int DEFAULT_SIZE = 1000, DEFAULT_X =
ArenaPanel.PANEL_WIDTH/2, DEFAULT_Y = ArenaPanel.PANEL_HEIGHT/2;
private int x, y, size;
private Color clr;
public Agar(Color c) {
x = DEFAULT_X;
y = DEFAULT_Y;
clr = c;
}
public void move() {
//blank for now, not used yet
}
//grows by 10% width
public void grow() {
size += 10;
}
public void draw(Graphics fred) {
fred.setColor(clr);
fred.fillOval(0,0,size,size);
fred.setColor(Color.black);
fred.drawOval(0,0,size,size);
}
}
Panel class code:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.ArrayList;
public class ArenaPanel extends JPanel {
//instance field
public static final int PANEL_WIDTH = 1000, PANEL_HEIGHT = 500;
private ArrayList<Food> food;
private Timer foodAdder;
private Agar agar;
public ArenaPanel() {
//agar stuff
agar = new Agar(getRandomColor());
//food stuff
food = new ArrayList<Food>();
//add some initial food
for (int i = 0; i < 50; i++)
addRandomFood();
//"this will last a while"
foodAdder = new Timer(3000, new FoodAdder());
foodAdder.start();
//listeners
addComponentListener(new ResizeListener());
//more basic stuff
setPreferredSize(new Dimension(PANEL_WIDTH, PANEL_HEIGHT));
setBackground(Color.white);
}
public void paintComponent(Graphics fred) {
super.paintComponent(fred);
agar.draw(fred);
for (int i = 0; i < food.size(); i++)
food.get(i).draw(fred);
}
//put it here so I can use it for both agar and food
private Color getRandomColor() {
int rand = (int)(Math.random()*7);
Color c;
switch (rand) {
case 0:
c = Color.red;
break;
case 1:
c = Color.orange;
break;
case 2:
c = Color.yellow;
break;
case 3:
c = Color.green;
break;
case 4:
c = Color.cyan;
break;
case 5:
c = Color.blue;
break;
default:
c = Color.pink;
}
return c;
}
private void addRandomFood() {
int x = (int)(Math.random()*PANEL_WIDTH);
int y = (int)(Math.random()*PANEL_HEIGHT);
food.add(new Food(x,y,getRandomColor()));
}
private class FoodAdder implements ActionListener {
public void actionPerformed(ActionEvent e) {
addRandomFood();
repaint();
}
}
private class ResizeListener extends ComponentAdapter {
public void componentResized(ComponentEvent e) {
setPreferredSize(getSize());
}
}
}
I tried debugging (placing System.out.println command into draw(), paintComponent(), agar's constructor) and all methods are in fact running properly. So I thought maybe it was just not showing up, but even when I tried changing agar's colour to black square (which should contrast a lot to colourful circular food) located at 0,0 but it still doesn't show.
What could be the problem here?
It has zero size. Call method grow at leas once.
I made a program to display interference patterns for light waves. I did this by using the paint method on a JPanel to draw 2 sources and then drawing concentric circles around them. This would be double slit interference, so I allowed one of the sources to move around to experiment with the slit width.
The problem is that when I run this, my computer says it is using 80% of my CPU! There's really not much to it. Circle in the middle, circles around it, and it moves. My code follows.
main class:
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
public class main {
static final int UP = -1;
static final int DOWN = 1;
static final int RIGHT = 1;
static final int LEFT = -1;
static final int NOMOVEMENT = 0;
static int verticalMovement = NOMOVEMENT;
static int horizontalMovement = NOMOVEMENT;
public static void main(String[] args) {
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
Point s1 = new Point((int)(screenSize.getWidth()/3), 50);
Point s2 = new Point((int)(2*screenSize.getWidth()/3), 50);
JFrame frame = new JFrame("Physics Frame");
frame.setPreferredSize(screenSize);
PhysicsPane pane = new PhysicsPane(screenSize, 15, s1, s2);
pane.setPreferredSize(screenSize);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(pane);
frame.pack();
Timer time = new Timer(1000 / 20, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
switch (verticalMovement){
case UP:
s2.changeY(UP);
break;
case DOWN:
s2.changeY(DOWN);
break;
default:
break;
}
switch (horizontalMovement){
case RIGHT:
s2.changeX(RIGHT);
break;
case LEFT:
s2.changeX(LEFT);
break;
default:
break;
}
pane.repaint();
}
});
frame.addKeyListener(new KeyListener() {
#Override
public void keyTyped(KeyEvent e) {
}
#Override
public void keyPressed(KeyEvent e) {
if(e.getKeyCode()==37){
horizontalMovement = LEFT;
} else if (e.getKeyCode()==38){
verticalMovement = UP;
} else if (e.getKeyCode()==39){
horizontalMovement = RIGHT;
} else if (e.getKeyCode()==40){
verticalMovement = DOWN;
}
if(e.getKeyChar()=='a'){
pane.setWaveLength(2);
}
if(e.getKeyChar()=='s'){
pane.setWaveLength(-2);
}
}
#Override
public void keyReleased(KeyEvent e) {
switch (e.getKeyCode()){
case 37:
horizontalMovement = NOMOVEMENT;
break;
case 38:
verticalMovement = NOMOVEMENT;
break;
case 39:
horizontalMovement = NOMOVEMENT;
break;
case 40:
verticalMovement = NOMOVEMENT;
break;
}
}
});
frame.setVisible(true);
time.start();
}
}
Panel class. If there's an inefficiency with the drawing method, it would be here.
import javax.swing.*;
import java.awt.*;
public class PhysicsPane extends JPanel {
private Dimension size;
private Point[] pointArray = new Point[2];
private double waveLength;
public PhysicsPane(Dimension size, double wavelength, Point source1, Point source2) {
this.size = size;
pointArray[0] = source1;
pointArray[1] = source2;
setPreferredSize(size);
this.waveLength = wavelength;
}
#Override
public void paintComponent(Graphics g){
for (int i = 0; i < 2; i++) {
g.setColor(Color.black);
double x = this.pointArray[i].getX();
double y = this.pointArray[i].getY();
g.fillOval((int)x, (int)y, 2, 2);
for (int j = (int)waveLength; j < 1500; j+=waveLength) {
g.setColor(Color.red);
g.drawOval((int)x-(j/2+1), (int)y-(j/2+1), 2 + j, 2 + j);
}
}
}
public void setWaveLength(double increment){
this.waveLength+=increment;
}
}
Point Class: Really just puts x and y coordinates into one construct. Not important particularly
public class Point {
private double x;
private double y;
public Point(double x, double y) {
this.x = x;
this.y = y;
}
public double getX() {
return x;
}
public void setX(double x) {
this.x = x;
}
public double getY() {
return y;
}
public void setY(double y) {
this.y = y;
}
public void changeX(double dX){
this.x+=dX;
}
public void changeY(double dY){
this.y+=dY;
}
}
So what is wrong with my program? Why is such a simple animation consuming so much of my processor?
UPDATED CODE SECTION:
#Override
public void paintComponent(Graphics g){
BufferedImage bi = new BufferedImage(size.width, size.height, BufferedImage.TYPE_INT_RGB);
Graphics graphics = bi.getGraphics();
for (int i = 0; i < 2; i++) {
graphics.setColor(Color.black);
double x = this.pointArray[i].getX();
double y = this.pointArray[i].getY();
graphics.fillOval((int)x, (int)y, 2, 2);
for (int j = (int)waveLength; j < 1500; j+=waveLength) {
graphics.setColor(Color.red);
graphics.drawOval((int)x-(j/2+1), (int)y-(j/2+1), 2 + j, 2 + j);
}
}
g.drawImage(bi, 0, 0, new ImageObserver() {
#Override
public boolean imageUpdate(Image img, int infoflags, int x, int y, int width, int height) {
return false;
}
});
}
The improvement that I recommend is removal of unnecessary tasks being performed, notably how your code updates the pane being drawn on, even when there aren't changes.
The following update reduced CPU usage from 12% to 0% (static frame):
Timer time = new Timer(1000 / 20, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
boolean refresh = false;
switch (verticalMovement) {
case UP:
s2.changeY(UP);
refresh = true;
break;
case DOWN:
s2.changeY(DOWN);
refresh = true;
break;
default:
break;
}
switch (horizontalMovement) {
case RIGHT:
s2.changeX(RIGHT);
refresh = true;
break;
case LEFT:
s2.changeX(LEFT);
refresh = true;
break;
default:
break;
}
if (refresh == true) {
pane.repaint();
}
}
});
I'm very new to Java and programming in general and I'm having a bit of trouble with my homework assignment.
We're supposed to give a variation of 4 different shapes, 10 shape in each picture with variation of at least 20, also variation of at least 20 different colors and variation of position.
I've made classes for each of my 5 shapes. But I somehow don't know how to add them to my ArrayList randomShape so that they can be called in the paintComponent section.
Also I'm having trouble coming up with the code the positions :(
Its a bit frustrating that I've hit a road block of thoughts.
Thank you for any help/advice you give me
It's very much appreciated
Here is my code that I have so far
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;
public class Cara extends JPanel implements ActionListener {
Random random = new Random();
public static final int MAX_AMOUNT_OF_SHAPES = 50,AMOUNT_OF_DISTINCT_SHAPES=5, AMOUNT_OF_DISTINCT_COLORS = 20, SIZE_MAX_X_COORDINATE = 400, SIZE_MAX_Y_COORDINATE = 300;;
public static ArrayList<RandomShape> randomShape = new ArrayList<RandomShape>();
int x = 0;
int xMax = 400;
int y = 0;
int yMax = 300;
int width = 0;
int height = 0;
int arcWidth = 0;
int arcHeight = 0;
int R = (int)(Math.random()*256);
int G = (int)(Math.random()*256);
int B = (int)(Math.random()*256);
Color randomColor = new Color(R,G,B);
public Cara(){
setPreferredSize( new Dimension(400,300));
}
abstract class RandomShape {
protected Color color;
protected int x,y;
abstract void draw(Graphics g);
}
public class Circle extends RandomShape{
#Override
public void draw(Graphics g) {
g.drawOval(x,y,width,width);
g.fillOval(x,y,width,width);
g.setColor(randomColor);
}
//constructor for random position
Circle (){
for ( int x; x < xMax; x++){
}
for ( int y; y < yMax; y++){
}
}
}
public class Rectangle extends RandomShape{
#Override
public void draw( Graphics g){
g.drawRect(x,y,width,height);
g.fillRect(x,y,width,height);
g.setColor(randomColor);
}
//constructor for random position
}
public class RoundRectangle extends RandomShape{
#Override
public void draw(Graphics g){
g.drawRoundRect(x,y,width,height,arcWidth,arcHeight);
g.fillRoundRect(x,y,width,height,arcWidth,arcHeight);
g.setColor(randomColor);
}
//constructor for random position
}
public class Oval extends RandomShape{
#Override
public void draw(Graphics g){
g.drawOval(x,y,width,height);
g.fillOval(x,y,width,height);
g.setColor(randomColor);
}
//constructor for position
}
public class Square extends RandomShape{
Square square = new Square();
#Override
public void draw(Graphics g){
g.drawRect(x,y,width,width); //because is a rectangle with sides of equal size
g.fillRect(x,y,width,width);
g.setColor(randomColor);
}
//constructor for position
}
protected void paintComponent(Graphics g) {
//clear the background
super.paintComponent(g);
//draw all shapes
for ( RandomShape rs: randomShape){
rs.draw(g);
}
}
public void actionPerformed (ActionEvent e){
regenerate();
repaint();
}
private void regenerate() {
//clear the shapes list
randomShape.clear();
// create random shapes
RandomShape shape = null;
for (int i = 0; i < 10 + random.nextInt(MAX_AMOUNT_OF_SHAPES); i++){
int randomInt = random.nextInt(AMOUNT_OF_DISTINCT_SHAPES);
switch (randomInt) {
case 0: shape = new Oval(400,300);
break;
case 1: shape = new Circle(400,300);
break;
case 2: shape = new Rectangle(400,300);
break;
case 3: shape = new Square(400,300);
break;
case 4: shape = new RoundRectangle(400,300);
break;
}
}
//random position
RandomShape position = null;
for (int i = 0; i < (MAX_SIZE_X_COORDINATE*MAX_SIZE_Y_COORDINATE) ; i++){
int randomIntpos = random.nextInt();
}
}
public static void main(String[] args) {
final Cara cara = new Cara();
SwingUtilities.invokeLater(new Runnable(){
#Override
public void run(){
final JFrame frame = new JFrame("Computer Assisted Random Artist");
JButton button = new JButton("regenerate");
button.addActionListener(cara);
frame.add(button, BorderLayout.SOUTH);
frame.pack();
cara.regenerate();
frame.setVisible(true);
}
});
}
}
public class Cara extends JPanel implements ActionListener {
private static ArrayList<RandomShape> randomShape;
public Cara() {
randomShape = new ArrayList<RandomShape>();
}
}
private void regenerate() {
//clear the shapes list
randomShape.clear();
// create random shapes
RandomShape shape = null;
int randomInt;
for(int i = 0; i < 10 + random.nextInt(MAX_AMOUNT_OF_SHAPES); i++) {
randomInt = random.nextInt(AMOUNT_OF_DISTINCT_SHAPES);
switch (randomInt) {
case 0:
shape = new Oval(400,300);
break;
case 1:
shape = new Circle(400,300);
break;
case 2:
shape = new Rectangle(400,300);
break;
case 3:
shape = new Square(400,300);
break;
case 4:
shape = new RoundRectangle(400,300);
break;
}
randomShape.add(shape);
}
//random position
RandomShape position = null;
int randomIntpos;
for (int i = 0; i < (MAX_SIZE_X_COORDINATE*MAX_SIZE_Y_COORDINATE) ; i++){
randomIntpos = random.nextInt();
}
}
public class RoundRectangle extends RandomShape {
private int x;
private int y;
//constructor for random position
public RoundRectangle(int x, int y) {
this.x = x
this.y = y
}
#Override
public void draw(Graphics g){
g.drawRoundRect(x,y,width,height,arcWidth,arcHeight);
g.fillRoundRect(x,y,width,height,arcWidth,arcHeight);
g.setColor(randomColor);
}
}