i'm trying to write a program with Java what generates images by coloring individual pixels with RGB by adding up the value of every RGB-channel by one until it reaches 255 and then adds one on the next RGB channel.
Here an example:
RED is set to 0
GREEN is set to 0
BLUE is set to 0
RED gets added up by one (RED ++)on the first pixel until it reaches 255.
After RED reaches 255 RED gets set to 0 and GREEN gets added up by one (GREEN ++).
The RED channel gets added up again like in step 1 until 255 and then step 2 follows again.
If GREEN is 255 the same method is used for BLUE means that one gets added to BLUE while GREEN and RED will be set to 0 again. Then step 1 again.
After all channels in the first Pixel are 255 the second pixel gets one up on its RED channel. Then it should begin by step 1 again until the second Pixel has a value of 255 on RED, what will set RED back to 0 and GREEN gets one up on the second pixel and so on and so on....
I'm sorry for my bad english and for my limited Java-knowledge.
This is my whole code so far(Stuff in comments is either not important in the project no more, not ready to use or i don't understand how to use it xD):
import javax.swing.JFrame;
//import javax.swing.JLabel;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.image.BufferedImage;
//import java.awt.image.BufferedImage;
public class Quadrat
{
public static void main (String[] args)
{ int x = 100;
int y = 0;
int z = 0;
int Max = 255;
int height = 500;
int width = 500;
if (x < Max){
x ++;
} else {
x = 0;
y ++;
}
if (y > Max){
y = 0;
z ++;
}
if (z > Max){
z = 0;
}
JFrame Bild = new JFrame("Bildergenerator");
Bild.setSize(width,height);
Bild.setVisible(true);
Color Kartoffel = new Color(x, y, z, 255);
BufferedImage Test = new BufferedImage(300, 200,
BufferedImage.TYPE_INT_ARGB);
Graphics graphics = Test.getGraphics();
graphics.setColor(Kartoffel);
graphics.fillRect(100, 100, 100, 100);
graphics.dispose();
Test.setRGB(1, 1, Kartoffel.getRGB());
}
/*System.out.println(x);
System.out.println(y);
System.out.println(z);*/
//img.setRGB(x,y,z);
/* JFrame Test = new JFrame("Jframe1");
JLabel Label = new JLabel("");
Test.add(Label);
Test.setSize(xx,yy);
Test.setVisible(true);
Test.setLocation(x/2-(xx/2), y/2-(yy/2));*/
/* JFrame Hyaeaeae = new JFrame("BurrScurrSWAG");
Hyaeaeae.setSize(1000,1000);
Hyaeaeae.setVisible(true);
Hyaeaeae.getContentPane().setBackground( Color.RED);*/
}
I'll hope you can help me in any way and if so i'm very thankful!
Thank you for your Attention!
Have a nice day! c:
You need to create the timer for this as your code is just changing on the first iteration on startup after this nothing is changed so a timer to make sure increments keep on applied on variables
package javatestapp;
import java.awt.Color;
import java.util.Timer;
import java.util.TimerTask;
import javax.swing.JFrame;
public class JavaTestApp extends TimerTask
{
static int x = 100;
static int y = 0;
static int z = 0;
static int Max = 255;
static int height = 500;
static int width = 500;
static JFrame frame;
public static void main(String[] args)
{
InitFrame();
}
public static void incrementValues()
{
if (x < Max)
{
x ++;
}
else
{
x = 0;
y ++;
}
if (y > Max)
{
y = 0;
z ++;
}
if (z > Max)
{
x = 0;
y = 0;
z = 0;
}
}
public static void genImage()
{
Color color = new Color(x,y,z,255);
frame.getContentPane().setBackground(color);
}
public static void InitFrame()
{
frame = new JFrame("Bildergenerator");
frame.setSize(width,height);
frame.setVisible(true);
Timer timer = new Timer(true);
TimerTask timerTask = new JavaTestApp();
timer.scheduleAtFixedRate(timerTask, 0, 10);
}
#Override
public void run()
{
incrementValues();
genImage();
}
}
Related
What I have here is a Buffer image called blackWhite which is completely either black or white. What I am trying to do here is that I take a 2d array of pixel coordinates (in this case, tog) and find out whether it is black or white, assign it to be 0 of black and 1 if not, then save it back to the 3rd column of the 2d array. While it does not through any error, it is not giving me the right colors and saying all of it is white when I know it is not. I have used DDA to pick the coordinates of each pixel between 2 click points for this case and that's what is in the array tog here. Even when I pick just black-to-black pixels, it still says all is white.
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
public class W3_Img_Process_Class_Only extends JPanel {
//--------------variables
int[][] tog; int step;
String inTitle="L1";
int imageCount=0;
int[] x= new int[2], y= new int[2];
int[] black= new int[2]; //-------------if black is 0, then the pixel is black
int clr; int flag=0;
private BufferedImage master;
private BufferedImage blackWhite;
public W3_Img_Process_Class_Only() {
//----------------------try/catch for (pure black || pure white)
try {
master = ImageIO.read(new File(Image_Path));
blackWhite = new BufferedImage(master.getWidth(), master.getHeight(), BufferedImage.TYPE_BYTE_BINARY);
Graphics2D g2d = blackWhite.createGraphics();
g2d.drawImage(master, 0, 0, this);
g2d.dispose();
}catch (IOException ex) {ex.printStackTrace();}
//--------------------------1st and 2nd click point data and color
this.addMouseListener(new MouseListener() {
int[] isFristEmpty;
#Override
public void mouseClicked(MouseEvent e1) {
int[] temp =new int[3]; //external container so i can get 1st and 2nd separately
temp[0] = (int) e1.getX();
temp[1] = (int) e1.getY();
clr = blackWhite.getRGB(temp[0], temp[1]);
temp[2] = (clr & 0x00ff0000) >> 16;//--------------------bit map to find if red is there or not.
//-------------------------------------------------------since its pure b/w, if red 0, its white.
if(isFristEmpty==null) {
isFristEmpty=temp;
x[0] = temp[0]; y[0] = temp[1]; black[0]=temp[2];//------1st click
}else {
x[1] = temp[0]; y[1] = temp[1]; black[1]=temp[2];//-----2nd click
isFristEmpty=null; //so the 3rd click is considered 1st click again
flag=1;
}
if (flag==1) {
System.out.print("X1: "+x[0]+" & "+"Y1: "+y[0]+" "+"(225 if white): "+black[0]+"\t");
System.out.println("X2: "+x[1]+" & "+"Y2: "+y[1]+" "+"(225 if white): "+black[1]);
counter();
}
}
#Override public void mousePressed(MouseEvent e) {}
#Override public void mouseReleased(MouseEvent e) {}
#Override public void mouseEntered(MouseEvent e) {}
#Override public void mouseExited(MouseEvent e) {}
});
}
//--------------------------------------------DDA block
private void counter() {
int dark;
if(flag!=1) return;//-------------------to only go to counter method after it takes that 2nd click
int dx = (x[1] - x[0]);
int dy = (y[1] - y[0]);//---------makes it applicable for both inclinations (we do not have math.abs implies-> -ve goes as -ve)
step = Math.abs(dx) > Math.abs(dy) ? Math.abs(dx) : Math.abs(dy);
System.out.println("Steps: "+step);
float Xinc = dx / (float) step;//----slope change with respect to x axis
float Yinc = dy / (float) step;//----slope change with respect to y axis
tog= new int[step][3];
tog[0][0]=x[0]; tog[0][1]=y[0];
tog[0][2]= (black[0]!=0) ? 1 : 0;//------------Tertiary operator where condition is true, then while is true
//---------------------------------------------------------------send value of x1 and y1 to listOfCoordinates
float xt=x[0],yt=y[0]; int i=0, j=1;
//-------------to get all the coordinates between the 2 points1111
System.out.println(tog[0][0]+" "+tog[0][1]+" "+tog[0][2]);
while (j<step){
if(i==2) i=0;
xt += Xinc;
yt += Yinc;
tog[j][i] = (int)xt;
tog[j][i+1] = (int)yt;
j++;
}
for (i = 0; i < step; i++) {
for (j = 0; j<= 1; j++) {
System.out.print(tog[i][j]+" ");
}//****************issue zone here till...
clr = blackWhite.getRGB(tog[i][j-1], tog[i][j]);
dark = clr & 0x000000ff;//----for blue but if it is 255, its white
System.out.print(dark);
tog[i][2]= (dark!=0) ? 1 : 0;
//System.out.print(tog[i][2]);
System.out.println();
}
//********issue zone till here..
}
//------------image size and such stuff. don't touch it
#Override
public Dimension getPreferredSize() {
Dimension size = super.getPreferredSize();
if (master != null) {
size = new Dimension(master.getWidth(), master.getHeight());
}
return size;
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (master != null) {
int x = (getWidth() - (master.getWidth())) / 2;
int y = (getHeight() - master.getHeight()) / 2;
g.drawImage(blackWhite, x, y, this);
}
}
}
It's the well and fully functional code of it all. Hope it's good enough to be helpful.
The pixel is white if it gives 255 and 0 if black, if u r looking into already substituted to 1 and 0 part then it's 1 for white. it is supposed to give the value of pixel but it gives all white and that's the issue. the x1 y1 and x2 y2 are the coordinates of 1st and 2nd click. the list u get as output is the list of coordinates of pixels between those points and its color (1 of white adn 0 of black)
Apparently, the problem was with the loop where instead of:
for (i = 0; i < step; i++) {
for (j = 0; j<= 1; j++) {
System.out.print(tog[i][j]+" ");
}
}
I should have just used a single loop and reset the value of the y coordinate at the start of the loop again as follows:
for (i = 1; i < step; i++) {
j=0;
clr = blackWhite.getRGB(tog[i][j], tog[i][j+1]);
System.out.print(tog[i][j]+" "+tog[i][j+1]+" ");
}
works as intended.
I am attempting to draw the US flag using java. I have pretty much done all this coding using lots of variables. It should be at least displaying the stripes, blue box, and the stars(ovals in this case). However, when I run the code through the compiler, and run it, all it displayes is a white background with a red stripe on the top. Could I please receive some help to see where my error is? I have tried everything.
Here is the code:
import javax.swing.JFrame;
import javax.swing.JPanel;
import java.awt.Graphics;
import java.awt.Color;
public class UsFlag extends JPanel {
int w = getWidth();
int h = getHeight();
int numberStripes = 13;
int numStarCol = 8;
int numStarRow = 6;
int stripeHeight = h/numberStripes;
int boxWidth = (int)(w*0.4);
int boxHeight = 7 * stripeHeight;
int starWidth = boxWidth/numStarCol;
int starHeight = boxHeight/numStarRow;
/*public UsFlag() {
//ask user to enter number of stripes, star columns, and star rows
}*/
#Override
public void paintComponent(Graphics g) {
int w = getWidth();
int h = getHeight();
//Background
g.setColor(Color.RED);
g.fillRect(0, 0, w, h);
//Stripes
g.setColor(Color.WHITE);
for (int i = 0; i < numberStripes; i += 1) {
g.fillRect(0,stripeHeight, w, stripeHeight);
stripeHeight = stripeHeight + 45;
}
//Blue Rect
g.setColor(Color.BLUE);
g.fillRect(0, 0, boxWidth, boxHeight);
//stars
int y = 0;
int x = 0;
for (int j = 0; j < numStarRow; j++){
for (int i = 0; i < numStarCol; i++){
g.setColor(Color.WHITE);
g.fillOval(5, 5, starWidth, starHeight);
x += starWidth;
}
y += starHeight;
x = 0;
}
}
public static void main(String[] args) {
JFrame window = new JFrame();
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setSize(400, 400);
window.setContentPane(new UsFlag());
window.setVisible(true);
}
}
The first two parameters for the fillRect() method and the fillOval() method are considered coordinates (x & y) for the object you want to paint. This means that for x you need to place a integer pixel value as to where you want the Left edge of the object is to Start being painting from along the horizontal plain, and for y you need to place a integer pixel value as to where you want the Top edge of the object is to Start being painting from along the vertical plain. For fillRect() for example:
g.fillRect(20, 20, 100, 30);
The other two parameters are for the Width (w) and Height (h) in pixels of the object to paint. Use the the variable i from your for loop (y = i + 30; for example) to draw objects below one another. Read this for more information.
I have a Java Swing assignment with the following objectives:
When the program starts, it draws 20 unfilled circles, with radius and location of each determined at random.
If the perimeter line of a circle does NOT intersect any other circle, draw the outline of the circle in RED. If it does intersect at least one other circle, draw it in BLACK.
Add a JButton that, each time it is pressed, creates a new set of circles as described above.
I've completed objectives #1 and #3 above, but I'm stumped on objective #2.
Before I present the code, let me give my understanding of the math behind it. There are two ways a circle can NOT intersect another circle:
The circles are too far apart to share a perimeter point, i.e. the distance between their centers is greater than the sum of their radii (d > r1 + r2). Example.
One circle is completely inside another circle, and their perimeters do not touch, i.e. the distance between their centers is less than the difference between their radii (d < |r1 - r2|). Example.
What I've got so far:
To compare circles, they must be specified before they are drawn, so I used a for-loop to store 20 values in arrays for the center coordinates (int[] x, int[] y) and the radius (double[] radius).
Next, I used nested for-loops to iterate through the array and compare two circles, except when a circle is compared with itself (index j = index k). If the circles intersect, g.setColor(Color.RED). If not, g.setColor(Color.BLACK).
When I execute my code, the circles without any overlap are properly colored red. However, some of the overlapping circles are colored red as well. I assume that they were non-overlapping at the time they were drawn, but were intersected thereafter. How do I fix the code to account for this discrepancy in time? (Problem area located near the bottom, in IntersectingCircles class)
import java.awt.BorderLayout;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JPanel;
import javax.swing.JFrame;
import javax.swing.JButton;
public class ButtonFrame extends JFrame
{
private final JButton resetButton = new JButton("Reset");
public ButtonFrame()
{
super("Drawing Random Circles");
setLayout(new BorderLayout());
IntersectingCircles intersectingCircles = new IntersectingCircles();
this.add(intersectingCircles, BorderLayout.CENTER);
this.add(resetButton, BorderLayout.SOUTH);
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
this.setSize(1400, 1400);
ButtonHandler handler = new ButtonHandler();
resetButton.addActionListener(handler);
}
private class ButtonHandler implements ActionListener
{
#Override
public void actionPerformed(ActionEvent event)
{
reset();
}
}
public static void main(String[] args)
{
ButtonFrame buttonFrame = new ButtonFrame();
buttonFrame.setVisible(true);
}
public void reset()
{
ButtonFrame buttonFrame = new ButtonFrame();
buttonFrame.setVisible(true);
}
}
class IntersectingCircles extends JPanel
{
private static final JButton resetButton = new JButton("Reset Circles");
private static final JFrame frame = new JFrame("Intersecting Circles");
#Override
public void paintComponent(Graphics g)
{
super.paintComponent(g);
this.setBackground(Color.WHITE);
int[] x = new int[20];
int[] y = new int[20];
int[] diameter = new int[20];
double[] radius = new double[20];
for (int i = 0; i < 20; i++)
{
int xCoord = (int)(Math.random() * 600);
int yCoord = (int)(Math.random() * 600);
int circleSize = (int)(Math.random() * 550);
x[i] = xCoord;
y[i] = yCoord;
diameter[i] = circleSize;
radius[i] = circleSize / 2.0;
}
for (int j = 0; j < 20; j++)
{
for (int k = 0; k < 20; k++)
{
if (k != j)
{
if (((Math.sqrt((x[k] - x[j]) * (x[k] - x[j]) + (y[k] - y[j])
* (y[k] - y[j]))) > (radius[j] + radius[k])) ||
((Math.sqrt((x[k] - x[j]) * (x[k] - x[j]) + (y[k] - y[j])
* (y[k] - y[j]))) < (Math.abs(radius[j] - radius[k]))))
g.setColor(Color.RED);
else
g.setColor(Color.BLACK);
g.drawOval(x[j], y[j], diameter[j], diameter[j]);
}
else
continue;
}
}
}
}
You have logic mistake in if statement inside the cycle - you can set black color then revert to red for some other pair circle. Possible solution draft:
for (int j = 0; j < 20; j++)
{
g.setColor(Color.RED); //set non-intersect state
for (int k = j + 1; k < 20; k++) //avoid excessive work
{
if (intersect test)
{
g.setColor(Color.BLACK);
break; //can stop here
};
g.drawOval(x[j], y[j], diameter[j], diameter[j]);
}
}
I have created a time lapse to show the density on a highway over the course of a day. The data is held in a double[][] array data, where data.length is 2880 (each index represents a 30-second interval) and data[0].length is about 450 (representing a cubic interpolation across the highway section's length).
My code for the time lapse is as follows:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.ObjectInputStream;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.Timer;
public class TimeLapse extends JPanel {
static double[][] data;
int index = 0;
double max;
double lineWidth;
Timer timer;
final JProgressBar progressBar = new JProgressBar(0, 2879);
BufferedImage[] images;
Color colors[][];
public static void main(String[] args) {
data=getData(); //arbitrary method to get interpolated data
new TimeLapse(data, 90);
}
public TimeLapse(double[][] data1, double max) {
data = data1;
this.max = max;
JFrame frame = new JFrame("Timelapse");
frame.setPreferredSize(new Dimension(800, 600));
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new GridBagLayout());
GridBagConstraints c = new GridBagConstraints();
c.fill = GridBagConstraints.BOTH;
c.anchor = GridBagConstraints.NORTH;
c.gridwidth = 1;
c.gridx = 0;
c.gridheight = 1;
c.weightx = 1;
c.weighty = .01;
c.gridy = 0;
frame.add(progressBar, c);
c.anchor = GridBagConstraints.SOUTH;
c.gridy = 1;
c.gridheight = 9;
c.weighty = 1;
frame.add(this, c);
frame.pack();
getColorArray();
frame.setVisible(true);
int dataLength;
dataLength = data.length;
// Make the animation 5 seconds long
int delay = (int) (5000d / dataLength);
timer = new Timer(delay, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
updateIndex();
repaint();
Toolkit.getDefaultToolkit().sync();
}
});
timer.start();
}
private void getColorArray() {
double cutOff = max / 2;
colors = new Color[data.length][data[0].length];
for (int index = 0; index < data.length; index++) {
for (double x = 0; x < data[0].length; x++) {
colors[index][(int) x] =
getColor(data[index][(int) x], cutOff);
}
}
}
private void updateIndex() {
index = index < data.length - 1 ? index + 1 : 0;
progressBar.setValue(2879 * index / data.length);
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
int panelHeight = getHeight();
lineWidth = ((double) getWidth()) / ((double) (data[0].length));
// guaranteed counter, as doing it in timer's ActionListener could overlap with rendering
for (double x = 0; x < data[0].length; x++) {
g2.setColor(colors[index][(int) x]);
double rectHeight = panelHeight * data[index][(int) x] / max;
g2.fillRect((int) (x * lineWidth),
(int) (panelHeight - rectHeight),
(int) (lineWidth + 1), (int) rectHeight + 1);
}
g2.dispose();
}
private Color getColor(double value, double cutOff) {
int hueR, hueG, hueB = 0;
if (value < cutOff) {
hueG = 255;
hueR = (int) (255 * value / (cutOff));
} else if (max != cutOff) {
hueR = 255;
hueG = (int) (255 - (255 * (value - cutOff) / (max - cutOff)));
} else {
hueR = 255;
hueG = 0;
}
hueR = (hueR < 0) ? 0 : ((hueR > 255) ? 255 : hueR);
hueG = (hueG < 0) ? 0 : ((hueG > 255) ? 255 : hueG);
hueB = (hueB < 0) ? 0 : ((hueB > 255) ? 255 : hueB);
return new Color(hueR, hueG, hueB);
}
}
The animation functions smoothly, but it typically takes a great deal longer than the five seconds I set it to, which I chalk up to the constant coloring and generation of hundreds of lines in the panel.
To verify that I was correct and it was indeed much slower than it should be, I used the Google Chrome widget that appears when you Google "stopwatch" to time it. Doing this I found that when I ran the stopwatch the animation sped up greatly, as well as whenever I moved my mouse over certain elements (hyperlinks, the tabs at the top, and seemingly anything else that gives a visual response to the mouse hovering). This only happens when I move the mouse or am running the stopwatch; keeping the mouse still does not speed it up, and it appears to only have this behavior while hovering over Chrome (i.e. any other application is fine). Can anyone explain this odd behavior?
EDIT: It also happens while reloading a tab, but not after it's done reloading.
EDIT 2: I now know for certain that the timer is speeding up. I created a small class with a timer that prints every millisecond an increasing index:
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.Timer;
public class TimerTest {
static int index = 0;
public static void main(String[] args) {
Timer t = new Timer(1, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
System.out.println(index++);
}
});
t.start();
while (true) {
}
}
}
This has exactly the same behavior as the time lapse class, speeding up greatly when moving the mouse over Chrome's elements. I believe the reason is that, in this case, println is a slow method and executes slower than the timer updates. Again, can someone explain why Chrome specifically speeds up a backed-up timer?
A painting method is for painting only.
You should not be changing properties of your class in the painting method.
That is you can not control when Swing determines a component needs to be repainted. So there may be some system call that is causing the component to be repainted and therefore changing your properties more frequently than you think.
For example you should not be updating your "index" variable or the progress bar value. Instead your Timer should invoke a method to changes these properties and then that method should invoke repaint on the panel.
This only happens when I move the mouse
Maybe you have tooltips on the panel which would cause it to be repainted.
This is easy to test, just add a System.out.println(...) statement to the paintComponent() method to see if it displays more frequently than the 5 seconds of your Timer.
There is something in the following code that I am unable to understand. After digging through google for a while, I decided it would be better to ask someone.
I am following a game programming tutorial on youtube, and I feel I understand (to some degree) everything I have written, except for some lines which concern the rendering part of the program.
package com.thomas.game;
import java.awt.Canvas;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.image.BufferStrategy;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferInt;
import javax.swing.JFrame;
import com.thomas.game.graphics.Screen;
import com.thomas.game.input.Keyboard;
public class Game extends Canvas implements Runnable {
private static final int WIDTH = 300;
private static final int HEIGHT = (WIDTH / 16) * 9;
private static final int SCALE = 3;
private static final String TITLE = "Game";
private JFrame frame;
private Thread thread;
private Screen screen;
private BufferedImage image;
private Keyboard key;
private int[] pixels;
private boolean running = false;
private int x = 0, y = 0;
public Game() {
setPreferredSize(new Dimension(WIDTH * SCALE, HEIGHT * SCALE));
screen = new Screen(WIDTH, HEIGHT);
frame = new JFrame();
initializeFrame();
image = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);
pixels = ((DataBufferInt)image.getRaster().getDataBuffer()).getData();
this is what I don't understand. I get the image raster, from which I get the databuffer. I typecast that databuffer into a (DatabufferInt), which allows me to retrieve an int[] through the getData() method. After this is done, pixel.length has a value of 48600, and every index contains the int value 0. Operating with this int[] makes the program render like it is supposed to. However, if I don't typecast and retrieve the int[] in the above manner, and instead say pixels = new int[48600], i end up with a black screen.
I guess what I want to know is: what is the difference between these two int[], or rather, what makes the first one work? How does it work?
key = new Keyboard();
addKeyListener(key);
setFocusable(true);
}
public void run() {
long lastTime = System.nanoTime();
double nsPerTick = 1E9/60;
double delta = 0;
long now;
int ticks = 0;
int frames = 0;
long timer = System.currentTimeMillis();
while(running) {
now = System.nanoTime();
delta += (now - lastTime) / nsPerTick;
lastTime = now;
while(delta >= 1) {
tick();
ticks++;
delta--;
}
render();
frames++;
if(System.currentTimeMillis() - timer >= 1000) {
timer += 1000;
frame.setTitle(TITLE + " | ups: " + ticks + " fps: " + frames);
ticks = 0;
frames = 0;
}
}
}
private void render() {
BufferStrategy bs = getBufferStrategy(); // retrieves the bufferstrategy from the current component (the instance of Game that calls this method)
if(bs == null) {
createBufferStrategy(3);
return;
}
screen.clear();
screen.render(x, y);
getPixels();
Graphics g = bs.getDrawGraphics(); // retrieves a graphics object from the next in line buffer in the bufferstrategy, this graphics object draws to that buffer
g.drawImage(image, 0, 0, getWidth(), getHeight(), null); // draws the bufferedimage to the available buffer
g.dispose();
bs.show(); // orders the next in line buffer (which the graphics object g is tied to) to show its contents on the canvas
}
private void tick() {
key.update();
if(key.up)
y--;
if(key.down)
y++;
if(key.left)
x--;
if(key.right)
x++;
}
public void initializeFrame() {
frame.setTitle(TITLE);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setResizable(false);
frame.add(this);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public synchronized void start() {
running = true;
thread = new Thread(this);
thread.start();
}
public synchronized void stop() {
running = false;
try {
thread.join();
} catch(InterruptedException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
Game game = new Game();
game.start();
}
public void getPixels() {
for(int i = 0; i < pixels.length; i++)
pixels[i] = screen.pixels[i];
}
}
It seems like the bufferedimage gets values from the pixels array. But I don't understand how these two communicate, or how they are connected. I haven't explicitly told the bufferedimage to get its pixels from the pixels array, so how does it know?
I will also attach the Screen class, which is responsible for updating the pixels array.
package com.thomas.game.graphics;
import java.util.Random;
public class Screen {
private int width, height;
public int[] pixels;
private final int MAP_SIZE = 64;
private final int MAP_SIZE_MASK = MAP_SIZE - 1;
private int[] tiles;
private int tileIndex;
private int xx, yy;
private Random r;
public Screen(int w, int h) {
width = w;
height = h;
pixels = new int[width * height];
tiles = new int[MAP_SIZE * MAP_SIZE];
r = new Random(0xffffff);
for(int i = 0; i < tiles.length; i++) {
tiles[i] = r.nextInt();
}
tiles[0] = 0;
}
public void clear() {
for(int i = 0; i < pixels.length; i++)
pixels[i] = 0;
}
public void render(int xOffset, int yOffset) {
for(int y = 0; y < height; y++) {
yy = y + yOffset;
for(int x = 0; x < width; x++) {
xx = x + xOffset;
tileIndex = (yy >> 4 & MAP_SIZE_MASK) * MAP_SIZE + (xx >> 4 & MAP_SIZE_MASK);
pixels[y * width + x] = tiles[tileIndex];
}
}
}
}
I really hope someone can explain this to me, it would be greatly appreciated. The program is working like it is supposed to, but I don't feel comfortable continuing on the tutorial until I grasp this.
Basic types like short, int, long etc are not Objects.
However, int[] is an array. Arrays are objects in java. Java manipulates objects by reference, not value.
In this line you are not creating a new object. You are storing a reference to the object int[] in your variable pixels. Anything you change in pixels, gets changed inside of the int[] object in image:
pixels = ((DataBufferInt)image.getRaster().getDataBuffer()).getData();
I've created an example, try running this code:
public class Data {
private int[] values = {25,14};
public int[] getValues() {
return values;
}
public static void main(String[] args) {
Data d = new Data();
System.out.println(d.getValues()[0]);
int[] values = d.getValues();
values[0] = 15;
System.out.println(d.getValues()[0]);
}
}
Output:
25
15
Note that you have this code...
pixels = ((DataBufferInt)image.getRaster().getDataBuffer()).getData();
while it should be like this...
pixels = ((DataBufferInt)img.getRaster().getDataBuffer()).getData();
Change image to img.
Hope it works!