How to make and draw a Perlin Noise on a JPanel [closed] - java

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
I want to make a application that draws a noise to a JPanel in Java. I came up with a really random noise, but i would like to draw a Perlin or Simplex Noise.
Here is the code:
import java.awt.*;
import java.util.*;
import javax.swing.*;
public class Paint extends JPanel {
private static boolean running = false;
private static Paint paint = new Paint();
private static Random random = new Random();
public static void main(String args[]) {
running = true;
JFrame f = new JFrame();
f.setSize(800, 800);
f.setResizable(running);
f.setUndecorated(running);
f.setLocationRelativeTo(null);
f.add(paint);
f.setVisible(running);
while(running) {
paint.repaint();
}
}
public void paint(Graphics g) {
noise(g);
}
private void noise(Graphics g) {
for(int i = 0; i < 800; i=i+10) {
for(int j = 0; j < 800; j=j+10) {
g.setColor(new Color(random.nextInt(255),random.nextInt(255),random.nextInt(255)));
g.fillRect(j, i, 10, 10);
}
}
running = false;
}
}
So how would I implant the Perlin Noise algorithm to this code, while not having to install external libraries.
EDIT: I am not lazy, or something. I read my way through all possible Noise generations, I just don't completely understand how to immigrate the noise methods into the class.

You are lucky, I recently did exactly this, heres my code:
BufferedImage tex;
float[] interpol;
int size;
float[] noise;
float[] workSet;
float r1,g1,b1,r2,g2,b2;
int octaves=4;
int octaveOffset=2;
public void init(int size)
{
this.size=size;
tex=new BufferedImage(size,size,BufferedImage.TYPE_INT_ARGB);
interpol=new float[size];
workSet=new float[size*size];
noise=new float[size*size];
float smult=(float) (Math.PI/size);
for(int i=0;i<size;i++)
{
interpol[i]=(1+(float) Math.cos(i*smult))/2;
}
r1=255;
g1=255;
b1=255;
r2=0;
g2=0;
b2=0;
}
public void generate()
{
Random r=new Random();
int[] pix=((DataBufferInt)(tex.getRaster().getDataBuffer())).getData();
int totalSize=size*size;
for(int i=0;i<totalSize;i++)
{
noise[i]=0.5f;
}
float[] randoms=new float[(size+1)*(size+1)];
int scale=size>>octaveOffset;
float max=0.50f;
for(int oct=0;oct<octaves;oct++)
{
int randsPerLine=size/scale+1;
int rands=randsPerLine*randsPerLine;
for(int i=0;i<rands;i++)
{
randoms[i]=max*(r.nextFloat()-0.5f);
}
for(int i=0;i<totalSize;i++)
{
int y=(i/size)/scale;
int suby=(i/size)%scale;
int x=(i%size)/scale;
int subx=(i%size)%scale;
float intp=interpol[subx*(size/scale)];
float colorA=randoms[y*randsPerLine+x]*intp+(1-intp)*randoms[y*randsPerLine+x+1];
float colorB=randoms[(1+y)*randsPerLine+x]*intp+(1-intp)*randoms[(1+y)*randsPerLine+x+1];
intp=interpol[suby*(size/scale)];
workSet[i]=colorA*intp+(1-intp)*colorB;
}
for(int i=0;i<totalSize;i++)
{
noise[i]+=workSet[i];
}
max/=2;
scale/=2;
}
for(int i=0;i<totalSize;i++)
{
int red=(int) (r1*noise[i]+r2*(1-noise[i]));
int g=(int) (g1*noise[i]+g2*(1-noise[i]));
int b=(int) (b1*noise[i]+b2*(1-noise[i]));
pix[i]=(255<<24)+(red<<16)+(g<<8)+b;
}
}
To draw it use g.drawImage(tex,[your coordinates],null).
My code generates a square image size x size with a noisy mixture between two colors, currently black and white, this can be changed by modifying r1, g1, b1, r2, g2, b2. Play around with the octaves and the octaveOffset values to make the noise suit your needs.
I only tested this code with size being a power of 2 and while merging with your code I found out that it only works if paint.init(1024) and paint.generate() are called right at the beginning of main().

Related

How can I completely fill new drawn shapes over old shapes

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

Collision detection between a circle and a rectangle without intersect method of awt

I am writing a code in which I am drawing two rectangles as obstacles and an oval as the robot. The robot moves while obstacles are stationary. The problem is as the robot's location is generated randomly in the beginning, it sometimes overlap the rectangles. I am trying continuously to fix this, but I am not able to find a good solution.
I tried checking the bounds of the rectangle with the x,y coordinate of circle before drawing it. But, it only checks for that single point and sometimes some other point of circle overlaps the rectangle. I tried intersect method but I am not able to implement that in my code as I am using fillOval and fillRect.
I know this question is already asked in the community multiple times. But, all answers revolve around the intersect method in AWT. I am not using the Rectangle/Ellipse classes. I am using fillRect and fillOval to create my shapes. Is there any other way to prevent collision when in the initialize method these shapes are being first time drawn on the JPanel randomly.
Code:
public void initializePanel(Graphics g)
{
createObstacle(g,150,225,100,40);
createObstacle(g,500,300,40,100);
drawNParticles(g);
createRobot(g);
}
private void createRobot(Graphics g)
{
ArrayList<Integer> robot_list= new ArrayList<Integer>();
robot_list=positionRobot(robot_x,robot_y);
robot_x=robot_list.get(0);
robot_y=robot_list.get(1);
System.out.println("Robot:"+robot_x+"--"+robot_y+"--"+robot_orientation);
if((robot_x>620)||(robot_y>395)||(robot_x<1)||(robot_y<1))
{
robot_orientation=180;
}
drawRobot(g,robot_x,robot_y,robot_radius);
}
private ArrayList<Integer> positionRobot(int x, int y)
{
int robot_radius=50;
ArrayList<Integer> list= new ArrayList<Integer>();
if(counter==0)
{
x=randomInteger(25,655);//so that it stays inside the content_Walls panel
y=randomInteger(25,425); //so that it stays inside the content_Walls panel
x=x-(robot_radius/2);
y=y-(robot_radius/2);
robot_orientation=randomFloat(0,360);
if((x<251&&x>149)&&(y<266&&y>224))
{
x=0;
y=0;
positionRobot(x,y);
}
else if((x<=541&&x>499)&&(y<401&&y>299))
{
x=0;
y=0;
positionRobot(x,y);
}
counter++;
}
else
{
setXPosition_robot(robot_x);
setYPosition_robot(robot_y);
}
list.add(x);
list.add(y);
return list;
}
private void drawNParticles(Graphics g)
{
ArrayList<Integer> list;
list = new ArrayList<Integer>(Collections.nCopies(n, 0));
for(int i=0;i<list.size();i++)
{
generateParticle(g);
}
}
private void generateParticle(Graphics g)
{
int radius = 4;
ArrayList<Integer> list= new ArrayList<Integer>();
list=positionParticles(particle_x,particle_y);
g.setColor(Color.RED);
g.fillOval(list.get(0),list.get(1), radius, radius);
}
private ArrayList<Integer> positionParticles(int x, int y)
{
int radius = 4;
ArrayList<Integer> list= new ArrayList<Integer>();
x=randomInteger(2,678); // bounds of x between which the particles should be generated
y=randomInteger(2,448); // bounds of y between which the particles should be generated
x=x-(radius/2);
y=y-(radius/2);
if((x<251&&x>149)&&(y<266&&y>224))
{
x=0;
y=0;
positionParticles(x,y);
}
if((x<541&&x>499)&&(y<401&&y>299))
{
x=0;
y=0;
positionParticles(x,y);
}
list.add(x);
list.add(y);
return list;
}
private void createObstacle(Graphics g, int x, int y, int width, int height)
{
//g.setColor(Color.YELLOW);
//g.fillRect(x, y, width, height);
}
private void drawRobot(Graphics g, int x, int y, int radius)
{
g.setColor(Color.GREEN);
g.fillOval(x, y, radius, radius);
}
private static Random rand;
private static int randomInteger(int min, int max)
{
if(rand==null)
rand=new Random();
int randomNum = rand.nextInt((max - min) + 1) + min;
return randomNum;
}
private static Random randFloat;
private static float randomFloat(float min, float max)
{
if(randFloat==null)
randFloat=new Random();
float randomNum = randFloat.nextFloat() *(max-min)+ min;
return randomNum;
}
I am not using the Rectangle/Ellipse classes. I am using fillRect and fillOval to create my shapes.
So change your code.
I tried checking the bounds of the rectangle with the x,y coordinate of circle before drawing it. But, it only checks for that single point and sometimes some other point of circle overlaps the rectangle.
Exactly, it is not easy code to write which is why you should take advantage of existing API's. Don't reinvent the wheel by trying to write your own intersection code! I know it is above my skill level to get all the geometry correct.
Check out Playing With Shapes for ideas that don't involve doing your own painting using the fillRect() and fillOval() methods.

Java GUI program to convert 2D array value into graphic [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
I am a beginner in Java & i have to make a java program that takes the input from a 2d array with dimensions 347*697 (array's value range from 2200 to 4200 ). I have to do such that for every 100 increase in range there is a set of specific color(for e.g 2200-2300 color(214,217,223) & so on). I have never done anything .. & this is the program i found little bit similar ... Can anyone give me idea how to convert it
I know its too much to ask for , but tomorrow i have to give a ppt. & when every option is closed i came here. Please guys, I need help badly
import javax.swing.*;
import java.awt.*;
import java.util.Random;
public class Map extends JPanel {
public static final Color CITY = new Color(214,217,223);
public static final Color DESERT = new Color(255,204,102);
public static final Color DIRT_ROAD = new Color(153,102,0);
public static final Color FOREST = new Color(0,102,0);
public static final Color HILLS = new Color(51,153,0);
public static final Color LAKE = new Color(0,153,153);
public static final Color MOUNTAINS = new Color(102,102,255);
public static final Color OCEAN = new Color(0,0,153);
public static final Color PAVED_ROAD = new Color(51,51,0);
public static final Color PLAINS = new Color(102,153,0);
public static final Color[] TERRAIN = {
CITY,
DESERT,
DIRT_ROAD,
FOREST,
HILLS,
LAKE,
MOUNTAINS,
OCEAN,
PAVED_ROAD,
PLAINS
};
public static final int NUM_ROWS = 215;
public static final int NUM_COLS = 300;
public static final int PREFERRED_GRID_SIZE_PIXELS = 10;
// In reality you will probably want a class here to represent a map tile,
// which will include things like dimensions, color, properties in the
// game world. Keeping simple just to illustrate.
private final Color[][] terrainGrid;
public Map(){
this.terrainGrid = new Color[NUM_ROWS][NUM_COLS];
Random r = new Random();
// Randomize the terrain
for (int i = 0; i < NUM_ROWS; i++) {
for (int j = 0; j < NUM_COLS; j++) {
int randomTerrainIndex = r.nextInt(TERRAIN.length);
Color randomColor = TERRAIN[randomTerrainIndex];
this.terrainGrid[i][j] = randomColor;
}
}
int preferredWidth = NUM_COLS * PREFERRED_GRID_SIZE_PIXELS;
int preferredHeight = NUM_ROWS * PREFERRED_GRID_SIZE_PIXELS;
setPreferredSize(new Dimension(preferredWidth, preferredHeight));
}
#Override
public void paintComponent(Graphics g) {
// Important to call super class method
super.paintComponent(g);
// Clear the board
g.clearRect(0, 0, getWidth(), getHeight());
// Draw the grid
int rectWidth = getWidth() / NUM_COLS;
int rectHeight = getHeight() / NUM_ROWS;
for (int i = 0; i < NUM_ROWS; i++) {
for (int j = 0; j < NUM_COLS; j++) {
// Upper left corner of this terrain rect
int x = i * rectWidth;
int y = j * rectHeight;
Color terrainColor = terrainGrid[i][j];
g.setColor(terrainColor);
g.fillRect(x, y, rectWidth, rectHeight);
}
}
}
public static void main(String[] args) {
// http://docs.oracle.com/javase/tutorial/uiswing/concurrency/initial.html
SwingUtilities.invokeLater(new Runnable() {
public void run() {
JFrame frame = new JFrame("Game");
Map map = new Map();
frame.add(map);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
}
});
}
}
Create a byte[] with the rgb values for each pixel of the image you want. The byte[] length will be width * height * 3 (3 values for each pixel). Look at this for an example of how create a BufferedImage from the byte[].
Another alternative is to create a BufferedImage and set the rgb value for each pixel directly. In this case, you have to bit twiddle all 3 rgb values into a single int value.

Java - I want to draw multiple 2D Ellipses using a timer, but it's not working

Already tried searching, but couldn't find anything.
I'm trying to draw multiple 2D Ellipses using an array, and a for loop, I'm repainting the frame every second. The thing is, I only get one Ellipse everytime I repaint, can somebody tell me what's wrong with me code, please?
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import javax.swing.*;
public class MovingDot extends JFrame{
static int posX = (int)Math.round(Math.random()*780);
static int posY = (int)Math.round(Math.random()*780);
static int width = (int)Math.round(Math.random()*780);
static int height = (int)Math.round(Math.random()*780);
static int dots = 0;
public static Timer timer;
public MovingDot(){
super("Moving Dot");
setDefaultCloseOperation(EXIT_ON_CLOSE);
setSize(800, 800);
Dot2 dot = new Dot2();
add(dot);
setVisible(true);
timer = new Timer((int)Math.round((1000)), timerAction);
timer.start();
}
private ActionListener timerAction = new ActionListener(){
#Override
public void actionPerformed(ActionEvent ae){
posX = (int)Math.round(Math.random()*780);
posY = (int)Math.round(Math.random()*780);
width = (int)Math.round(Math.random()*780);
height = (int)Math.round(Math.random()*780);
float r = (float)Math.random();
float g = (float)Math.random();
float b = (float)Math.random();
Color col = new Color(r,g,b);
setBackground(col);
dots++;
repaint();
}
};
public static void main(String[] args){
SwingUtilities.invokeLater(new Runnable(){
#Override
public void run()
{
new MovingDot();
}
});
}
}
class Dot2 extends JPanel{
#Override
public void paintComponent(Graphics c2){
int x = MovingDot.posX;
int y = MovingDot.posY;
int w = MovingDot.width;
int h = MovingDot.height;
float r,g,b;
Color col;
Graphics2D c = (Graphics2D) c2;
c.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
Ellipse2D.Float[] e = new Ellipse2D.Float[10];
for (int i = 0; i < 10; i++) {
if (i == 0)
r = (float)Math.random();
else
r = 0.163F;
g = (float)Math.random();
b = (float)Math.random();
col = new Color(r,g,b);
c.setColor(col);
e[i] = new Ellipse2D.Float(x, y, w, h);
c.fill(e[i]);
}
}
}
Found out what was wrong myself, I had to make x, y, w and h random in my paintComponent. And no, this is not for a school assignment, I'm trying to teach myself Java using a book.
And about making my methods static, I was planning on using them in my JPanel, but I realised I don't need them, so I'm going to delete them. Thanks for your advice!
You shouldn't be creating your Ellipse array inside of paintComponent, makes no sense.
Instead create the array in the class.
Your JPanel's paintComponent method should not have any program logic in it. It should only have code that paints the ellipses. That is, it should iterate through your array with a for loop, and if the item in the array is not null draw it.
You'd be even better off using an ArrayList<Ellipse2D> and not an array. That way you wouldn't have to check for nulls.
In the Timer's ActionListener, if your counter is < 10, you'd add an Ellipse2D to the array and call repaint.
If the counter >= 10 you'd stop the Timer
Also, none of your static variables should be static, and having them as static suggests that the program design is off. If this is for a school assignment, that could lead to deduction of your grade.

Mandelbrot set on Java - Is there something wrong with my algorithm?

I was asked to display the Mandelbrot set on Java but I have encountered a problem. My teacher and I both are stumped to why this doesn't run correctly.
I reckon it has something to do with the algorithm or the complex class since all values except positive/negative 1 and 0 escape to infinity after two iterations.
import javax.swing.*;
import java.awt.*;
public class fractal {
public class complex { double re; double im;
public complex(double x, double y){
this.re =x;
this.im =y;
}
public double mag(){
return (Math.sqrt(re*re+im*im));
}
}
static int xcord = 500;
static int ycord = 500;
public static void main(String[] args) {
JFrame myFrame = new JFrame("Question 10");
myFrame.setSize(xcord,ycord);
JPanel myPane = (JPanel) myFrame.getContentPane();
myPane.add(new paint());
myFrame.setVisible(true);
}
}
class paint extends JComponent {
public complex add(complex a, complex b){
return new complex(a.re+b.re,a.im+b.im);
}
public complex multiply(complex a,complex b) {
return new complex((a.re*b.re)-(a.im*b.im),(a.re*b.im)+(a.im*b.re));
}
public void paint (Graphics g){
final int SCALE =100; //pixels per unit
int itr = 0;
int max_itr = 30;
Color clr = Color.black;
g.translate(fractal.xcord/2, fractal.ycord/2); // Move origin to center of frame
for (int x = -2*SCALE; x <= 1*SCALE; x++){
for (int y = -1*SCALE; y <= 1*SCALE; y++){
complex C = new complex(x/SCALE,y/SCALE); // math done on unscaled values
complex z = C;
itr = 0;
while ( z.mag() <= 4.0 && itr < max_itr){
z = add(multiply(z,z),C);
itr++;
}
if (itr == max_itr){
clr = Color.black;
}
else{
clr = new Color((int) Math.round(itr*8.5),(int) Math.round(itr*8.5),(int) Math.round(itr*8.5)); // Colouring of fractal
}
g.drawOval(x, y, 2, 2);
g.setColor(clr);
}
}
}
}
I think that you have to wide boundaries. [-200,100], where you should have [-2,1] for Re and [-1,1] for Im.
complex C = new complex(x/SCALE,y/SCALE);
complex C = new complex(x/SCALE,y/SCALE); // math done on unscaled values
Since x and y are ints (and SCALE too), you're doing integer division here.
Try this instead:
complex C = new complex((double)x/SCALE,(double)y/SCALE); // math done on unscaled values
By the way, this is not an error, but add() and multiply() should really be methods of the Complex class, which should be capitalised according to the Java naming convention.

Categories