UPDATE: I Figured out the problem and wrote it out below.If you'd like to see the full compliable code here it is on GitHub: https://github.com/scohen40/cohen-mco364-fall-2018/tree/mazeGUI/src/main/java/cohen/maze
I have a 2D Array of Cells, each with 4 walls. My generateMaze() class starts at a random point and digs out a maze. That part works correctly, and when I print out the maze in the console everything is fine.
My next goal is to have the maze painted out with a JComponent in a JPanel. The problem is that all I'm getting is one thick-lined box in the top left corner.
Here's the painting code:
public class AnimatedMaze extends JComponent {
private Maze maze;
private int componentHeight;
private int componentWidth;
private int seventhHeight;
private int seventhWidth;
protected void paintComponent(Graphics g) {
super.paintComponent(g);
componentHeight = this.getHeight();
componentWidth = this.getWidth();
seventhHeight = componentHeight/7;
seventhWidth = componentWidth/7;
maze = new Maze(7, 7);
g.setColor(Color.black);
paintMaze(g);
}
/**
* The paintMaze() method runs through the generated maze and paints the existing walls.
* #param g
*/
void paintMaze(Graphics g) {
for (int x = 0; x < maze.getHeight(); x++) {
System.out.println("|");
for (int y = 0; y < maze.getWidth(); y++) {
Cell current = maze.getMaze()[x][y];
if(current.isWestWall()) {
g.drawLine(x, y, x, y + seventhHeight);
}
if(current.isNorthWall()){
g.drawLine(x, y,x + seventhWidth, y);
}
if(current.isEastWall()) {
g.drawLine(x + seventhWidth, y, x+ seventhWidth, y + seventhHeight);
}
if(current.isSouthWall()) {
g.drawLine(x, y + seventhHeight, x + seventhWidth, y +seventhHeight);
}
}
}
}
}
You can see in the console the generated maze but in the JPanel it'sjust a box.
In your painting code you need to multiply every x and y coordinate by 'seventhHeight', otherwise you are not painting to correct coordinates.
Building on the answer by Krzysztof Cichocki, realized that coordinates work differently from rows and tables. I switched the x's for y's and vice versa, after multiplying everything by seventhHeight. Also any additions that I did to any coordinate is always seventhHeight now, to make everything proportional.
Here's the current code for the painting method:
void paintMaze(Graphics g) {
for (int x = 0; x < maze.getHeight(); x++) {
System.out.println("|");
for (int y = 0; y < maze.getWidth(); y++) {
Cell current = maze.getMaze()[x][y];
if(current.isWestWall()) {
g.setColor(Color.black);
g.drawLine((y+1)*seventhHeight, x*seventhHeight, (y+1)*seventhHeight, x*seventhHeight + seventhHeight);
}
if(current.isNorthWall()){
g.drawLine((y+1)*seventhHeight, x*seventhHeight,(y+1)*seventhHeight + seventhHeight, x*seventhHeight);
}
if(current.isEastWall()) {
g.drawLine((y+1)*seventhHeight + seventhHeight, x*seventhHeight, (y+1)*seventhHeight + seventhHeight, x*seventhHeight + seventhHeight);
}
if(current.isSouthWall()) {
g.drawLine((y+1)*seventhHeight, x*seventhHeight + seventhHeight, (y+1)*seventhHeight + seventhHeight, x*seventhHeight +seventhHeight);
}
}
}
}
This is now what happens:
Related
I'm new at Java and I'm trying to make a chess with it for training.
I'm having some trouble with the Graphic methods though.
I listed the functions which the mistake could have been in.
The code below shows a function called in main.
This function is inside my package that handle Graphic stuff.
public class GUI_main extends JComponent{
private final int tam = 100;
private final int tamTab = 8 * tam;
Image torre;
public void inicializaTabuleiro(Torre t)
{ //Sets the window properties and the "tile" proper image.
JFrame janela = new JFrame("Xadrez");
janela.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
janela.setSize(816, 839);
janela.getContentPane().add(new GUI_main());
janela.setLocationRelativeTo(null);
janela.setResizable(false);
janela.setVisible(true);
paintPeca(t); /*this one is the function that sets the correct image
for the tile that will be on the board*/
System.out.println("Janela inicializada com sucesso!");
}
...
next one is the "paintPeca" function, which should initialize "Image torre".
public void paintPeca(Torre t)
{
System.out.println(t.imgPeca());
torre = Toolkit.getDefaultToolkit().getImage(t.imgPeca());
}
and finally my paint function:
public void paint(Graphics g)
{
Graphics2D g2 = (Graphics2D) g;
g2.setPaint(Color.black);
int x = 0, y = 0;
while(y<tamTab) //draw board
{
if(y%200 == 0)
{
g2.draw(new Rectangle2D.Double(x, y, tam, tam));
x = x + tam;
g2.fill(new Rectangle2D.Double(x, y, tam, tam));
x = x + tam;
}
else
{
g2.fill(new Rectangle2D.Double(x, y, tam, tam));
x = x + tam;
g2.draw(new Rectangle2D.Double(x, y, tam, tam));
x = x + tam;
}
if(x == tamTab)
{
y = y + tam;
x = 0;
}
}
x = 14;
y = 19;
g2.drawImage(torre, x, y, this); //draw tower
g2.finalize();
...
Together these functions should have draw a board and a tower on it.
It's showing me the board, but not the tower (Image torre), and I do not have a clue on the reason.
"t.imgPeca()" returns a string (path to image), and it's correct, as I have tested before.
Since I'm new at Java this might be some kind of of silly mistake, but I have not found the answer in other pages of stack that talked about the drawImage function.
Let's say I have two classes, the first extends JPanel and using Graphics draws a playing board on it. The second makes a JFrame and adds the panel to it.
You can imagine the frame looking something like this:
I now want to add an ellipse to a specific rectangle on click. I understand that I would be using a two-dimensional array in order to get the position I wanted, but I don't understand how the ellipse itself would be drawn on to the existing panel since I used the paint(Graphics g) to draw the playing board.
Here is the code for drawing the board itself if you need it:
class MyBoard extends JPanel {
private static int height = 6;
private static int width = 7;
private static int squareSize = 100;
private int board[][] = new int[height][width];
public void paint(Graphics g) {
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
g.drawRect(j * squareSize, i * squareSize, squareSize, squareSize);
}
}
}
}
Thanks!
First two things that you should remember: Never override paint but paintComponent and call super.paintComponent in there so that borders and everything works as expected. Regarding why this is the case, reference this question: Difference between paint() and paintcomponent()?
Now to answer your question. Assuming you have an existing logic to determine in which square you want to draw your Ellipse (let's assume you have two Integers elX and elY that are the column and row of your square) you can simply go and draw it after you have finished drawing the board itself.
Imagine sample code like this:
#Override
public void paintComponent(Graphics g)
{
super.paintComponent(g);
// Draw the board
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
g.drawRect(j * squareSize, i * squareSize, squareSize, squareSize);
}
}
// Draw the ellipse at the correct location using half the size of a normal square.
g.drawOval(elX * squareSize + squareSize / 4, elY * squareSize + squareSize / 4, squareSize / 2 , squareSize / 2);
}
Now the final part of how to go about actually determining where to draw your ellipse.
A simple solution would be to add a MouseListener to your panel. And then in the mouseClicked method you calculate where you actually did click.
Could look like this:
this.addMouseListener(new MouseListener()
{
#Override
public void mouseClicked(MouseEvent e)
{
int column = e.getX() / squareSize;
int row = e.getY() / squareSize;
board[column][row] = 1;
}
[...] // add the other methods to override
}
Then you slightly adapt your paintComponent method with something like this:
for (int column = 0; column < width; ++column)
{
for (int row = 0; row < height; ++row)
{
if (board[column][row] == 1)
{
g.drawOval(column * squareSize + squareSize / 4, row * squareSize + squareSize / 4, squareSize / 2, squareSize / 2);
}
}
}
and now you draw an ellipse everywhere you click. You could also check if the clicked square already has 1 set as a value and reset it to 0 to have some toggle mechanism or increment it and draw different things based on the integer value... it's all up to you :)
A program I'm modifying is supposed to use a drawing panel to randomly move a square, starting from the center, either left or right and use an array to tally the position it moves to while the square stays on screen (the panel is 400 x 400 and the square is 10 x 10, so there are only 40 possible positions it can move to) After the square goes off screen, I have to print a histogram that shows how many times the square moved to that index (i.e if the square moved from the x coordinate of 200 to 190, index 19 would get a tally) Here is my code:
import java.awt.*;
import java.util.*;
public class RandomWalkCountSteps {
// DrawingPanel will have dimensions HEIGHT by WIDTH
public static final int HEIGHT = 100;
public static final int WIDTH = 400;
public static final int CENTER_X = WIDTH / 2;
public static final int CENTER_Y = HEIGHT / 2;
public static final int CURSOR_DIM = 10;
public static final int SLEEP_TIME = 25; // milliseconds
public static void main( String[] args ) {
DrawingPanel panel = new DrawingPanel( WIDTH, HEIGHT );
Random rand = new Random();
walkRandomly( panel, rand );
}
public static void walkRandomly( DrawingPanel panel, Random rand ) {
Graphics g = panel.getGraphics();
int[] positionCounts = new int[ WIDTH / CURSOR_DIM ];
// start in center of panel
int x = CENTER_X;
int y = CENTER_Y;
// Draw the cursor in BLACK
g.fillRect(x, y, CURSOR_DIM, CURSOR_DIM);
// randomly step left, right, up, or down
while ( onScreen( x, y ) ) {
panel.sleep( SLEEP_TIME );
// Show a shadow version of the cursor
g.setColor(Color.GRAY);
g.fillRect(x, y, CURSOR_DIM, CURSOR_DIM);
if ( rand.nextBoolean() ) { // go left
x -= CURSOR_DIM;
}
else { // go right
x += CURSOR_DIM;
}
positionCounts[ x / CURSOR_DIM ]++;
histogram(positionCounts, x, y);
// draw the cursor at its new location
g.setColor(Color.BLACK);
g.fillRect(x, y, CURSOR_DIM, CURSOR_DIM);
}
}
public static boolean onScreen( int x, int y ) {
return 0 <= x && x < WIDTH
&& 0 <= y && y < HEIGHT;
}
public static void histogram(int[] positionCounts, int x, int y) {
if (onScreen(x, y) == false) {
for (int i = 0; i < WIDTH / CURSOR_DIM; i++) {
System.out.print(i + ": ");
for (int j = 1; j <= positionCounts[i]; j++) {
System.out.print("*");
}
System.out.println();
}
}
}
}
My problem was that I couldn't find a good place to initialize the array so that it wouldn't re-initialize every time I passed the x coordinate to the histogram method. Now that I thought I had it in the right place, I get this error message on both calls to histogram in the method walkRandomly "error: method histogram in class RandomWalkCountSteps cannot be applied to given types;" I'm fairly new to java and programming in general, so there's probably something I'm missing regarding arrays as parameters. Thanks in advance.
histogram takes two parameters, positionCounts of type int[] and x of type int. In walkRandomly, you call histogram twice: once with an argument positionCounts of type int[] and once with an argument x of type int. That’s why the compiler complains that the method ”cannot be applied to given types”: the method histogram(int[], int) can’t be applied to (called with) the given types, i.e., histogram(int[]) and histogram(int).
I’m not sure what you’re trying to do with this code, but I’d guess that you want remove the first call and change the second call (inside of the while loop) to histogram(positionCounts, x).
(You’ve edited your code, so my answer doesn’t make much sense.)
In processing, I need to fill a screen with rectangles based on its height. However, the code below is giving me a white screen. Anyone know why?
void setup (){
size (600,600);
background (255);
fill (200,200,200);
noStroke();
}
int y = 10;
int spatie = 20;
int stop = height;
void draw(){
while(y < stop) {
rect (50,y,100,10);
y = y + spatie;
}
}
Your drawing loop is correct
void draw(){
while(y < stop) {
rect (50,y,100,10);
y = y + spatie;
}
}
but you cannot see rectangles because of other mistake.
When Processing object is intantiated all its fields (like y, spatie, stop in your case) are initialized. At this time variable height is set to 0 as screen height is unknown.
Next setup() is called and from this time height has value. But stop has value assigned at initialization phase. Next draw() is called in animation thread, but stop variable is frozen to value 0.
Consider these small examples:
int stop = height;
public void setup() {
size(800,600);
}
public void draw() {
println("stop = " + stop);
}
and:
int stop;
public void setup() {
size(800,600);
stop = height;
}
public void draw() {
println("stop = " + stop);
}
First will output: stop = 0
Second will print: stop = 600
Just ran your code and it is showing me 5 grey rectangles:
So to achive rectangles unti the end of the screen, maybe use
for (int y = 0; y < height / spatie; y++) {
rect (50, y * spatie, 100, 10);
}
Just set up you're sketch and only removed int stop = height; and changed your while loop a bit (use height and use height instead of stop)
If you run the following code, it should work:
void setup(){
size (600,800);
background (255);
fill (200,200,200);
noStroke();
noLoop();
}
int y = 10;
int spatie = 20;
void draw(){
while(y<height){
println(y);
rect(50,y,100,10);
y = y + spatie;
}
}
Before I ask my question I apologize for any inconsistencies. I´m fairly new at this.
I´m making a game that for now looks like this (the picture is not important):
The red dots are supposed to move to the right and they do that with a timer. This works fine. The graphics does not update though so I have to drag the side of the window back and forth to see that my dots are moving. What can I do to fix this?
My paintcomponent method in my mainclass:
public void paintComponent(Graphics g){
super.paintComponent(g);
for (int x = 0; x < SomeInts.amount; x++){
for (int y = 0; y < SomeInts.amount; y++){
tile[x][y].colorBody(g, x, y);
Tower temp;
for (int i = 0; i < towers.size(); i++){
temp = towers.get(i);
temp.colorBody(g, tile[x][y].getSize());
temp.guard.colorBody(g, tile[x][y].getSize());
}
}
}
}
My red dot class. Also called Guard class:
public class Guard {
int x, y, size = 10, towerx, towery;
Timer timer;
public Guard(int towerx1, int towery1){
towerx = towerx1;
towery = towery1;
x = towerx + 1;
y = towery;
new Timer().schedule(new MyTask(), 1000, 1000);
}
public void colorBody(Graphics g, int tilesize){
g.setColor(new Color(255, 0, 0));
g.fillOval(x * tilesize + tilesize / 4, y * tilesize + tilesize / 4, size, size);
}
public class MyTask extends TimerTask {
public void run() {
x++;
}
}
}
Thank you for your time.
I'm guessing a bit here, but I think you need to call the repaint() method to see the changes you've made.