I am trying to write a program in Java that draws trees filling the screen. I have variables set to randomly place a tree on the x-axis and move down 10 steps each time. The problem I am encountering is when the new trees are drawn they overlap the old trees so the fill does not fill the tree. So my question is how can I fully fill a drawn shape filling over what is underneath. I have tried messing with the color I'm using but I just don't know what to do. I am brand new to Java but I have a fair bit of experience in Javascript.
Here is my code so far:
public class Turtle extends TurtleGraphicsWindow
{
public Turtle()
{
super(650, 550);
}
static void PrintTree() {
Turtle t = new Turtle();
t.speed(100);
for (int i = 0; i < 30; i++) { //to move the trees down
//randomizer
int min = -300;
int max = 300;
int random_int = (int)Math.floor(Math.random()*(max-min+1)+min);
var tWx = random_int;
int tWy = -10*i+150;
//trunk
t.pu();
t.setpensize(3);
t.setxy( (tWx-25) , (tWy-100) );
t.setpc(8); //brown
t.pd();
t.fd(50);
t.setx(t.xcor()+50);
t.bk(50);
t.setx(t.xcor()-50);
t.pu();
t.setxy(t.xcor()+5,t.ycor()+5);
t.setpc(9); //tan
t.fill();
//tree
t.setxy((tWx+100),(tWy-50));
t.setpencolor(31);
t.pd();
var tx = 50;
t.setx(t.xcor()-200);
t.setxy(t.xcor()+tx,t.ycor()+(tx+10));
t.setx(t.xcor()-(tx-15));
t.setxy(t.xcor()+(tx-5),t.ycor()+(tx+5));
t.setx(t.xcor()-(tx-20));
t.setxy(t.xcor()+(tx-10),t.ycor()+(tx));
t.setx(t.xcor()-(tx-30));
t.setxy(t.xcor()+(tx-15),t.ycor()+(tx-5));
t.setx(t.xcor()-(tx-35));
t.setxy(t.xcor()+(tx-20),t.ycor()+(tx-10));
//right side of tree
t.setxy(t.xcor()+(tx-20),t.ycor()-(tx-10));
t.setx(t.xcor()-(tx-35));
t.setxy(t.xcor()+(tx-15),t.ycor()-(tx-5));
t.setx(t.xcor()-(tx-30));
t.setxy(t.xcor()+(tx-10),t.ycor()-(tx));
t.setx(t.xcor()-(tx-20));
t.setxy(t.xcor()+(tx-5),t.ycor()-(tx+5));
t.setx(t.xcor()-(tx-15));
t.setxy(t.xcor()+tx,t.ycor()-(tx+10));
t.pu();
t.setpc(FOREST);
t.setxy(t.xcor()-10,t.ycor()+5);
t.fill();
}
}
public static void main(String[] args)
{
PrintTree();
}
}
This is what it has been looking like now:
https://i.stack.imgur.com/ipwhN.png
Related
Im trying to make lists of rectangles in matrix like manner, I would want them to scale depending on amount of rectangles in row to always fit to the fixed size of window. End of row is little cut or couple of them are outside of border, depending on amount of rectangles.
public class Main extends Application {
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage stage) {
final int size = 80;
stage.setWidth(1040);
stage.setHeight(920);
final double cellDimension = (stage.getWidth() / size) - 1;
stage.setScene(new Scene(render(20, size, cellDimension), Color.WHITE));
stage.show();
}
public static Region render(int generations, int size, double cellDimension) {
VBox results = new VBox(0);
Random random = new Random();
for (int y = 0; y < generations; y++) {
HBox hBox = new HBox(0);
hBox.getChildren().addAll(IntStream.range(0, size).
mapToObj(idx -> random.nextInt(2)).map(item -> createAppropriateRectangle(item == 1, cellDimension)).
collect(Collectors.toList()));
results.getChildren().add(hBox);
}
results.setSnapToPixel(true);
return results;
}
private static Rectangle createAppropriateRectangle(boolean state, double cellDimension) {
Rectangle rectangle = new Rectangle(cellDimension, cellDimension);
rectangle.setStroke(Color.GRAY);
if (state) {
rectangle.setFill(Color.WHITE);
}
return rectangle;
}
}
What am I doing wrong ? If something is unclear please let me know, thanks :)
for list of 90 values, up is original, bottom shows how much was outside of border
EDIT:
Made mwe using #DaveB stripped example
Building a MRE would probably have shown you the answer fairly quickly. It looks like using a GridPane was just an attempt to make the rectangles fit, but GridPane potentially adds complexity that may obscure the answer. So I went with a VBox holding a bunch of HBoxes. That handles the relative positioning of the elements without any fuss.
You didn't include the Generator class, meaning your code was un-runnable, so I've stripped it down to just the mechanics of putting some random black and white squares on the screen, and dumped everything else:
public class Squares extends Application {
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage stage) {
final int size = 80;
stage.setWidth(1040);
stage.setHeight(920);
final double cellDimension = (stage.getWidth() / size) - 1;
stage.setScene(new Scene(render(20, size, cellDimension), Color.WHITE));
stage.show();
}
public static Region render(int generations, int size, double cellDimension) {
VBox results = new VBox(0);
Random random = new Random();
for (int y = 0; y < generations; y++) {
HBox hBox = new HBox(0);
hBox.getChildren().addAll(IntStream.range(0, size).mapToObj(idx -> random.nextInt(2)).map(item -> createAppropriateRectangle(item == 1, cellDimension)).collect(Collectors.toList()));
results.getChildren().add(hBox);
}
return results;
}
private static Rectangle createAppropriateRectangle(boolean state, double cellDimension) {
Rectangle rectangle = new Rectangle(cellDimension, cellDimension);
rectangle.setStroke(Color.GRAY);
if (state) {
rectangle.setFill(Color.WHITE);
}
return rectangle;
}
}
It looks like you need to allow 1 extra pixel per rectangle to make the math work properly. Also, it seems to work only when the stage width divides nicely by the number of rectangles per row - there's probably some mechanics of partial pixels that comes into play here. You could probably find a rounding policy that would work when the row size is not an even divisor of the stage width.
You can bind it to stage or parent width, height property.
Binding is one of the most powerful concepts of JavaFX.
I have been working on a Java project for Uni, the classic arcade game Breakout, and so far have managed to create the bat and ball objects and they work as intended. I'd like to implement the brick wall using an array as making each brick its own object will result in inefficient code, but my experience with Java doesn't extend to Arrays and I understand, unlike Python, they are tricky to get working.
I'd like the bricks to be given different positions based on x and y parameters already established.
Here is the Model class where I'd like to add the array;
public class Model
{
// First, a collection of useful values for calculating sizes and layouts etc.
public int B = 6; // Border round the edge of the panel
public int M = 40; // Height of menu bar space at the top
public int BALL_SIZE = 30; // Ball side
public int BRICK_WIDTH = 50; // Brick size
public int BRICK_HEIGHT = 30;
public int BAT_MOVE = 5; // Distance to move bat on each keypress
public int BALL_MOVE = 3; // Units to move the ball on each step
public int HIT_BRICK = 50; // Score for hitting a brick
public int HIT_BOTTOM = -200; // Score (penalty) for hitting the bottom of the screen
View view;
Controller controller;
public GameObj ball; // The ball
public ArrayList<GameObj> bricks; // The bricks
public GameObj bat; // The bat
public int score = 0; // The score
// variables that control the game
public boolean gameRunning = true; // Set false to stop the game
public boolean fast = false; // Set true to make the ball go faster
// initialisation parameters for the model
public int width; // Width of game
public int height; // Height of game
// CONSTRUCTOR - needs to know how big the window will be
public Model( int w, int h )
{
Debug.trace("Model::<constructor>");
width = w;
height = h;
}
// Initialise the game - reset the score and create the game objects
public void initialiseGame()
{
score = 0;
ball = new GameObj(width/2, height/2, BALL_SIZE, BALL_SIZE, Color.RED );
bat = new GameObj(width/2, height - BRICK_HEIGHT*3/2, BRICK_WIDTH*3,
BRICK_HEIGHT/4, Color.GRAY);
bricks = new ArrayList<>();
// ***HERE***
}
And here is the corresponding code I'd like added to View class to draw the bricks in the GUI;
public void drawPicture()
{
// the ball movement is runnng 'i the background' so we have
// add the following line to make sure
synchronized( Model.class ) // Make thread safe (because the bal
{
GraphicsContext gc = canvas.getGraphicsContext2D();
// clear the canvas to redraw
gc.setFill( Color.WHITE );
gc.fillRect( 0, 0, width, height );
// update score
infoText.setText("BreakOut: Score = " + score);
// draw the bat and ball
displayGameObj( gc, ball ); // Display the Ball
displayGameObj( gc, bat ); // Display the Bat
// ***HERE***
}
}
The .jar project file in its current state can be viewed here.
On a side note, there is a slight bug with the bat, it does not stop when it hits either side, not sure what's the best way to go about making it stay within the parameters of the window.
Thanks in advance!!
You already have your ArrayList of bricks. Create a function to convert a row/column co-ordinate into an index for your array. Say you have a grid 3x4 (3 rows, 4 columns):
0 |_|_|B|_|
1 |_|_|_|_|
2 |_|_|_|_|
0 1 2 3
Your ArrayList would be of size 12 (3x4).
private int translateCoordToIndex(int row, int col) {
return row * TOTAL_COLS + col
}
So for the brick at row=0,col=2 in the diagram its position comes out as (0*4)+2 = 2 which means index 2 in your ArrayList bricks.get(2)
You can even just change the ArrayList into a general array of GameObj GameObj[]
Alternatively you can use a 2d array of GameObj to represent a grid of bricks.
GameObj[][] bricks = new GameObj[rows][cols] This way you can access the exact brick using its row and column position - e.g. bricks[0][0] for the first brick.
Both approaches are pretty much the same.
I want to create a program that can simulate the influence of a social structure of a matrix / grid. It's like an Erdos Renyi structure, but an nxn matrix where each node initially has a random value of +1 or -1. Each node has 4 neighbors (top, bottom, left, right) which also has values of +1 or -1. Thus, I can find the neighborhood of each node, which should be just a list / vector of the 4 values of those neighbors. The value of each node is then influenced by the neighbors' values, and the grid's values keep simulating and changing until an equilibrium is reached.
So far, I have a code which can create a grid with random -1 or +1 variables. Now, I am not sure how to get the values of each node (and its neighbors) inside the main method. I am a little confused as to how to go about this project so far, as in how to get the values.
In the main method, I cannot do like... int x = grid[0][1] etc. Sorry that I'm rusty in Java, but what topics can I look up in finding out the procedure to do this? I can't remember what it's called.
Also, is there a way that I can edit what each button (or node) on the grid says in the main method? Like, I can change it while it's looping, and I can also write what the values of its neighbors are? Thanks!
import javax.swing.JFrame;
import javax.swing.JButton;
import java.awt.GridLayout;
public class Grid {
JFrame frame = new JFrame(); // create frame
static JButton[][] grid;
// constructor
public Grid (int w, int l) {
frame.setLayout(new GridLayout(w, l));
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
// create grid
grid = new JButton[w][l];
for (int y = 0; y < l; y++) {
int value = 0;
for (int x = 0; x < w; x++) {
// probability p
double p = 0.5;
// randomly allocate opinion
double random = Math.random();
if (random <= p)
value = -1;
else if (random > p)
value = 1;
grid[x][y] = new JButton("" + value);
frame.add(grid[x][y]);
}
}
}
public static void main (String[] args) {
// DIMENSION
// int d = 2;
// LENGTH
int l = 2;
// WIDTH
int w = 2;
new Grid(l,w); // create new Grid with parameters
}
}
I changed your approach a little bit, so it is more object-oriented. I hope this example makes clear, what you have to do. To get an basic understanding, google keywords like "encapsulation" or "object-orientation". There are many tutorials out there.
public class Grid {
private JFrame frame = new JFrame();
private JButton[][] grid; // Has to be a field of the object. static would make it to an field of the class
public Grid (int w, int l) {
frame.setLayout(new GridLayout(w, l));
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
createGrid (w, l);
}
private void createGrid (int w, int l) {
// Your above implementation
}
public void stepInSimulation () {
// Your algorithm, you want to implement
}
public JButton[][] getGrid () {
return grid;
}
public static void main (String[] args) {
Grid grid = new Grid(2,2);
grid.getGrid ()[0][1]; // Access a value
grid.stepInSimulation (); // Do a step, call it in while loop, to do multiple steps
}
}
I hope this helps.
I would like to know how to make a simple graph using the method g.drawLine and using loops to update the coordinates, I am really really new at this and have no idea what I need to do or where to start, I do have this simple program that uses *'s instead of a line to create the graph, but what I need to do is change the graph from *'s to a line. Any help would greatly be appreciated
here is what I have:
import java.awt.*;
public class program5 {
public static void main(String[] args) {
graph1();
}
public static void graph1() {
DrawingPanel panel =new DrawingPanel(300,500);
Graphics g = panel.getGraphics();
double t=10;
for (int i=1; i<20; i++) {
t= t*(.8);
double z = t * 50;
int y= -(int)z + 430;
int x = 10 * i;
g.drawString("*",x,y);
}
}
}
Why not use JavaFX to make your chart? Java FX documentation - Line Charts
I am having a problem with my java code. I'm trying to make it so the top left quadrant produces a set number of lines input by a user through JOption Pane which are in random colors and in random positions. The programs builds successfully but it does not produce the number of lines the user input, nor does it set a random color (This it at the very bottom of my code). Can someone please explain how to fix this problem? Thanks very much.
Edit: fixed the curve braces but still will not work.
Edit: Everything works now except the random colors
import javax.swing.*; //for JFrame
import java.awt.*; //for Graphics and Container
import java.util.Random;
import javax.swing.JOptionPane;
// other import statements here
public class RandomGraphics
{
// constants are used to draw the grid, and for you to put shapes in the grid
public static final int MIDX = 400;
public static final int MIDY = 300;
public static final int MAXX = 799;
public static final int MAXY = 599;
public static final int COLOR = (int) (Math.random() * 256);
// make another constant for the color value that will
// be used to generate a random color
public static void main( String[] args )throws InterruptedException
{
//*** This next section sets up the graphics window.
//*** You are not required to understand it
Container contentPane;
Graphics g;
JFrame win = new JFrame("Random Graphics");
win.setSize(825,650);
win.setLocation(0,0);
win.setVisible(true);
win.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
contentPane = win.getContentPane();
contentPane.setBackground(Color.white);
g = contentPane.getGraphics();
Thread.sleep(50);
//*** done setting up graphics window
// Draws Grid - DO NOT CHANGE
// After you use JOptionPane to get the number of lines, you can move this
// section of code to just after that, so the lines will not disappear
g.drawRect(0,0,MAXX+1,MAXY+1);
g.drawLine(0,MIDY,MAXX,MIDY); // horizontal line
g.drawLine(MIDX,0,MIDX,MAXY); // vertical line
// Create Random object
Random r = new Random();
// Top left quadrant:
// Use a JOptionPane to ask the user to enter the number of lines 1 to 100.
int count = 0;
do
{
String morelines = JOptionPane.showInputDialog("Enter a number of lines between 1 to 100");
count = Integer.parseInt(morelines);
}
while(count > 100 || count < 1);
for(int i = 1; i >= count; i++)
{
g.setColor(new Color (r.nextInt(COLOR), r.nextInt(COLOR), r.nextInt(COLOR)));
g.drawLine(r.nextInt(MIDX), r.nextInt(MIDY), r.nextInt(MIDX), r.nextInt(MIDY));
}
g = contentPane.getGraphics();
Graphics objects are not persistent, the programmer needs to draw the GUI to them when asked to do so. For tips, see the Performing Custom Painting Lesson of the tutorial.
Beside the 'always include curly braces around loops advice', note..
for(int i = 1; i >= count; i++)
Should be..
for(int i = 1; i <= count; i++)
But don't ignore the advice about custom painting. The app. will not render reliably until that is fixed.
for(int i = 1; i >= count; i++)
g.setColor(new Color (r.nextInt(COLOR), r.nextInt(COLOR), r.nextInt(COLOR)));
g.drawLine(r.nextInt(MIDX), r.nextInt(MIDY), r.nextInt(MIDX), r.nextInt(MIDY));
Looking at your indenting, it looks like you want g.setColor(...) and g.drawLine(...) to be inside your for loop. You need to enclose them in curly braces {}, otherwise only the statement immediately following your for loop will be inside the loop.