Draw equilateral triangles using a nested for loop? [closed] - java

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 4 years ago.
Improve this question
I am trying to figure out how to use a nested for loop to produce this pattern below:
Thus far, I have
public class Triangle {
public static final int SIZE = 600;
public static final int INITIAL_X = 300;
public static final int INITIAL_Y = 50;
public static final int SIDE = 100;
/**
*
*
* #param args command line arguments
*/
public static void main(String[] args) {
Scanner console = new Scanner(System.in);
DrawingPanel panel = new DrawingPanel(SIZE, SIZE);
panel.setBackground(Color.WHITE);
System.out.print("Enter number of rows (1-5): " );
int row = console.nextInt();
if(row < 1) {
row = 1;
} else if(row > 5) {
row = 5;
}
System.out.print("Specify red value (0-255): ");
int red = console.nextInt();
if(red < 0) {
red = 0;
} else if(red > 255) {
red = 255;
System.out.print("Specify green value (0-255): ");
int green = console.nextInt();
if(green < 0) {
green = 0;
} else if(green > 255) {
green = 255;
}
System.out.print("Specify blue value (0-255): ");
int blue = console.nextInt();
if(blue < 0) {
blue = 0;
} else if(blue > 255) {
blue = 255;
}
Graphics g = panel.getGraphics(); //Initializes graphics panel.
g.setColor(new Color(red, green, blue));
for (int i = 1; i <= row; i++) {
for (int x = 1; x <= row; x++) {
int lx = sx - SIDE/2;
int rx = sx + SIDE/2;
int ly = (int) (sy + SIDE*Math.sqrt(3)/2);
int ry = ly;
System.out.println("\n*CLOSE the Drawing Panel to exit the program*");
}
/**
* Draws an equilateral triangle with topmost point at (x, y) with the
* given side length and color.
*
* #param g
* #param color
* #param x
* #param y
* #param sideLength
*/
public static void drawTriangle(Graphics g, int sx, int sy, int rows) {
g.drawLine(sx, sy, lx, ly);
g.drawLine(sx, sy, rx, ry);
g.drawLine(lx, ly, rx, ry);
}
This code is definitely not finished. I only want to use the java.awt.* and java.util.* packages to solve this. My trouble is mainly with creating a nested for loop in the main method, but I believe I have a grasp on the scanner part of this assignment. I have used the equilateral triangle formulas below that are derived from the Pythagorean theorem. Each row is supposed to have that many triangles (for instance, the 5th row is supposed to have 5 triangles). The triangles are contiguous and the lower left/right points of each triangle form the uppermost points of the triangles in the row below. The (x, y) coordinates of the topmost point of the triangle in the first row must be (300, 50). Please let me know if anyone can help.

A recursive approach sounds easier than iterative so it could look like this:
private void drawTree(double x, double y, int depth, int maxDepth, Graphics graphics, double sideLength) {
if (depth >= maxDepth) {
return;
}
double leftX = x - sideLength / 2;
double leftY = y + Math.sqrt(sideLength * 3) / 2;
double rightX = x + sideLength / 2;
double rightY = leftY;
//draw line from (x,y) -> (leftX, leftY)
graphics.drawLine(x, y, leftX, leftY);
//draw line from (x,y) -> (rightX, rightY)
graphics.drawLine(x, y, rightX, rightY);
//draw line from (leftX, leftY) -> (rightX, rightY)
graphics.drawLine(leftX, leftX, rightX, rightY);
drawTree(leftX, leftY, depth + 1, maxDepth, graphics, sideLength);
drawTree(rightX, rightY, depth + 1, maxDepth, graphics, sideLength);
}

Related

Calculating 'color distance' between 2 points in a 3-dimensional space

I have a homework task where I have to write a class responsible for contour detection. It is essentially an image processing operation, using the definition of euclidean distance between 2 points in the 3-dimensional space. Formula given to us to use is:
Math.sqrt(Math.pow(pix1.red - pix2.red,2) + Math.pow(pix1.green- pix2.green,2) + Math.pow(pix1.blue- pix2.blue,2));
We need to consider each entry of the two dimensional array storing the colors of the pixels of an image, and if some pixel, pix, the color distance between p and any of its neighbors is more than 70, change the color of the pixel to black, else change it to white.
We are given a seperate class as well responsible for choosing an image, and selecting an output, for which method operationContouring is applied to. Java syntax and convention is very new to me having started with python. Conceptually, I'm struggling to understand what the difference between pix1 and pix2 is, and how to define them. This is my code so far.
Given:
import java.awt.Color;
/* Interface for ensuring all image operations invoked in same manner */
public interface operationImage {
public Color[][] operationDo(Color[][] imageArray);
}
My code:
import java.awt.Color;
public class operationContouring implements operationImage {
public Color[][] operationDo(Color[][] imageArray) {
int numberOfRows = imageArray.length;
int numberOfColumns = imageArray[0].length;
Color[][] results = new Color[numberOfRows][numberOfColumns];
for (int i = 0; i < numberOfRows; i++)
for (int j = 0; j < numberOfColumns; j++) {
int red = imageArray[i][j].getRed();
int green = imageArray[i][j].getGreen();
int blue = imageArray[i][j].getBlue();
double DistanceColor = Math.sqrt(Math.pow(pix1.red - pix2.red,2) + Math.pow(pix1.green- pix2.green,2) + Math.pow(pix1.blue- pix2.blue,2));
int LIMIT = 70;
if (DistanceColor> LIMIT ) {
results[i][j] = new Color((red=0), (green=0), (blue=0));
}
else {
results[i][j] = new Color((red=255), (green=255), (blue=255));
}
}
return results;
}
}
This is a solution I wrote that uses BufferedImages. I tested it and it should work. Try changing it such that it uses your data format (Color[][]) and it should work for you too. Note that "pix1" is nothing more than a description of the color of some pixel, and "pix2" is the description of the color of the pixel you are comparing it to (determining whether the color distance > 70).
public static boolean tooDifferent(Color c1, Color c2) {
return Math.sqrt(Math.pow(c1.getRed() - c2.getRed(),2) + Math.pow(c1.getGreen()- c2.getGreen(),2) + Math.pow(c1.getBlue()- c2.getBlue(),2)) > 70;
}
public static Color getColor(int x, int y, BufferedImage img) {
return new Color(img.getRGB(x, y));
}
public static BufferedImage operationDo(BufferedImage img) {
int numberOfRows = img.getHeight();
int numberOfColumns = img.getWidth();
BufferedImage results = new BufferedImage(numberOfColumns, numberOfRows, BufferedImage.TYPE_INT_ARGB);
for (int y = 0; y < numberOfRows; y++) {
for (int x = 0; x < numberOfColumns; x++) {
Color color = new Color(img.getRGB(x, y));
boolean aboveExists = y > 0;
boolean belowExists = y < numberOfRows - 1;
boolean leftExists = x > 0;
boolean rightExists = x < numberOfColumns - 1;
if ((aboveExists && tooDifferent(color, getColor(x, y - 1, img))) ||
(belowExists && tooDifferent(color, getColor(x, y + 1, img))) ||
(leftExists && tooDifferent(color, getColor(x - 1, y, img))) ||
(rightExists && tooDifferent(color, getColor(x + 1, y, img)))) {
results.setRGB(x, y, Color.black.getRGB());
} else {
results.setRGB(x, y, Color.white.getRGB());
}
}
}
return results;
}

Creating a PPM Image to be Written to a File Java

so I am working on a program in java which creates the a rectangular image (see link below) as a ppm image that would be further written into a ppm file. Creating and writing the image to the file I get. However, I am having difficulty creating the image dynamically such that it works for any width and height specified. From my understanding, a p3 ppm file simply follows the following format for a 4x4 image.
P3
4 4
15
0 0 0 0 0 0 0 0 0 15 0 15
0 0 0 0 15 7 0 0 0 0 0 0
0 0 0 0 0 0 0 15 7 0 0 0
15 0 15 0 0 0 0 0 0 0 0 0
Where the first three numbers are the headings and the rest is simply the rgb values of each pixel. But I am having trouble figuring out how I can create the above matrix for the image below and for any dimensions specified as it does not include solid colors in a straight line?
Image to be created:
I figured I could create an arraylist which holds an array of rgb values such that each index in the list is one rgb set followed by the next rgb set to the right. However, I am quite confused on what the rgb values would be. Here is what I have:
public static void createImage(int width, int height){
pic = new ArrayList();
int[] rgb = new int[3];
for(int i = 0; i <= width; i++){
for(int j = 0; i <= height; j++){
rgb[0] = 255-j; //random values as im not sure what they should be or how to calculate them
rgb[1] = 0+j;
rgb[1] = 0+j;
pic.add(rgb);
}
}
}
Thanks in advance.
EDITED::Updated code
I have managed to fix most of the issues, however, the image generated does not match the one posted above. With this code. I get the following image:
package ppm;
import java.awt.Color;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
public class PPM {
private BufferedImage img;
private static final String imageDir = "Image/rect.ppm";
private final static String filename = "assignment1_q1.ppm";
private static byte bytes[]=null; // bytes which make up binary PPM image
private static double doubles[] = null;
private static int height = 0;
private static int width = 0;
private static ArrayList pic;
private static String matrix="";
/**
* #param args the command line arguments
*/
public static void main(String[] args) throws IOException {
createImage(200, 200);
writeImage(filename);
}
public static void createImage(int width, int height){
pic = new ArrayList();
int[] rgb = new int[3];
matrix +="P3\n" + width + "\n" + height + "\n255\n";
for(int i = 0; i <= height; i++){
for(int j = 0; j <= width; j++){
Color c = getColor(width, height, j, i);
//System.out.println(c);
if(c==Color.red){
rgb[0] = (int) (255*factor(width, height, j, i));
rgb[1] = 0;
rgb[2] = 0;
}else if(c==Color.green){
rgb[0] = 0;
rgb[1] = (int) (255*factor(width, height, j, i));
rgb[2] = 0;
}else if(c==Color.blue){
rgb[0] = 0;
rgb[1] = 0;
rgb[2] = (int) (255*factor(width, height, j, i));
}else if(c== Color.white){
rgb[0] = (int) (255*factor(width, height, j, i));
rgb[1] = (int) (255*factor(width, height, j, i));
rgb[2] = (int) (255*factor(width, height, j, i));
}
matrix += ""+ rgb[0] + " " + rgb[1] + " " + rgb[2] + " " ;
//System.out.println(""+ rgb[0] + " " + rgb[1] + " " + rgb[2] + " ");
//pic.add(rgb);
}
matrix += "\n";
}
}
public static Color getColor(int width, int height, int a, int b){
double d1 = ((double) width / height) * a;
double d2 = (((double) -width / height) * a + height);
if(d1 > b && d2 > b) return Color.green;
if(d1 > b && d2 < b) return Color.blue;
if(d1 < b && d2 > b) return Color.red;
return Color.white;
}
public static double factor(int width, int height, int a, int b){
double factorX = (double) Math.min(a, width - a) / width * 2;
double factorY = (double) Math.min(b, height - b) / height * 2;
//System.out.println(Math.min(factorX, factorY));
return Math.min(factorX, factorY);
}
public static void writeImage(String fn) throws FileNotFoundException, IOException {
//if (pic != null) {
FileOutputStream fos = new FileOutputStream(fn);
fos.write(new String(matrix).getBytes());
//fos.write(data.length);
//System.out.println(data.length);
fos.close();
// }
}
}
You can use Linear functions to model the diagonals in the picture. Keep in mind though that in the coordinates (0, 0) lie in the top-left corner of the image!
Say you want to create an image with the dimensions width and height, the diagonal from the top-left to bottom-right would cross the points (0, 0) and (width, height):
y = ax + t
0 = a * 0 + t => t = 0
height = a * width + 0 => a = height / width
d1(x) = (height / width) * x
Now we can calculate the function for the second diagonal. This diagonal goes through the points (0, height) and (width, 0), so:
y = ax + t
height = a * 0 + t => t = height
0 = a * width + height => a = -(height/width)
d2(x) = -(height/width) * x + height
From this we can determine whether a certain point in the image lies below or above a diagonal. As an example for the point (a, b):
if d1(a) > b: (a, b) lies above the first diagonal (left-top to right-bottom), thus it must be either blue or green. Otherwise it must be either red or white
if d2(a) > b: (a, b) lies above the second diagonal, thus it must be either red or green. Otherwise it must be white or blue
By applying both relationships it's easy to determine to which of the four colors a certain point belongs:
Color getColor(int width, int height, int a, int b){
double d1 = ((double) height / width) * a;
double d2 = ((double) -height / width) * a + height;
if(d1 > b && d2 > b) return greenColor;
if(d1 > b && d2 < b) return blueColor;
if(d1 < b && d2 > b) return redColor;
return whiteColor;
}
Now there's one last thing that we need to take into account: the image darkens towards it's borders.
A darker version of a color can be created by multiplying each channel with a factor. The lower the factor the darker the resulting the color. For the sake of simplicity I'll assume the change in brightness is linear from the center of the image.
Since the brightness changes along two axis independently, we need to model this by calculating the change alongside both axis and using the maximum.
The brightness change as a function of the distance of the center can be modeled using the distance to the closer border of the image in relation to the distance to the center (only on one axis):
deltaX = min(a, width - a) / (width / 2)
deltaY = min(b, height - b) / (height / 2)
So we can get the factor to multiply each color-channel by this way:
double factor(int width, int height, int a, int b){
double factorX = (double) Math.min(a, width - a) / width * 2;
double factorY = (double) Math.min(b, height - b) / height * 2;
return Math.min(factorX, factorY);
}

Draw large bitmaps in Android

I don't know whether or not this question was answered. At least I didn't find an answer.
So here is a thing: I'm making some space-themed 2D game on android, and I'm testing it on emulator with screen size = 2560x1600. In this game there is a field where space ship is flying. And of course it (a field) must have a beautiful background with high resolution. My background image's resolution is 4500x4500. I want to make my image move in opposite direction relative to camera movement, so thats why I can't use small static image. At the time only a part of this image is visible:
When I tried to draw it I got fps = 1-2 (of course it is low because of the image size):
canvas.drawBitmap(getBigImage(), -x, -y, null);
/* getBigImage() method does nothing but returning
a Bitmap object (no calculation or decoding is performing in there) */
I tried to cut out the needed image from the big one but fps was still low:
Bitmap b = Bitmap.createBitmap(getBigImage(), x, y, sw, sh);
canvas.drawBitmap(b, 0, 0, null);
How can I draw this big bitmap with high fps?
Try
drawBitmap(Bitmap bitmap, Rect src, Rect dst, Paint paint)
which takes a rectangle of pixels from the source image to display in a rectangle on the Canvas. I found this to be faster back when I did a scrolling game.
I was thinking a lot and came up with an idea to divide input bitmap to small chunks and save them to an array. So now to draw that bitmap all I have to do is to draw visible chunks.
Picture:
Big black rectangle means input bitmap, green rectangle means viewport, red rectangle means visible chunks that are drawn
I've wrote an object that does that all (I didn't check it for bugs yet :/). I've tested it and it draws 3000x3000 bitmap with ~45 fps. I'm considering this way as very effective. The object itself may need to be developed more but I think this functionality is enough for my needs. Hope it'll help someone :)
P.S. https://stackoverflow.com/a/25953122/6121671 - used this for inspiration :)
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
public final class DividedBitmap {
private final Bitmap[][] mArray; // array where chunks is stored
private final int mWidth; // original (full) width of source image
private final int mHeight; // original (full) height of source image
private final int mChunkWidth; // default width of a chunk
private final int mChunkHeight; // default height of a chunk
/* Init */
public DividedBitmap(Bitmap src) {
this(new Options(src, 100, 100));
}
public DividedBitmap(Options options) {
mArray = divideBitmap(options);
mWidth = options.source.getWidth();
mHeight = options.source.getHeight();
mChunkWidth = options.chunkWidth;
mChunkHeight = options.chunkHeight;
}
/* Getters */
public int getWidth() {
return mWidth;
}
public int getHeight() {
return mHeight;
}
public Bitmap getChunk(int x, int y) {
if (mArray.length < x && x > 0 && mArray[x].length < y && y > 0) {
return mArray[x][y];
}
return null;
}
/* Methods */
/**
* x, y are viewport coords on the image itself;
* w, h are viewport's width and height.
*/
public void draw(Canvas canvas, int x, int y, int w, int h, Paint paint) {
if (x >= getWidth() || y >= getHeight() || x + w <= 0 || y + h <= 0)
return;
int i1 = x / mChunkWidth; // i1 and j1 are indices of visible chunk that is
int j1 = y / mChunkHeight; // on the top-left corner of the screen
int i2 = (x + w) / mChunkWidth; // i2 and j2 are indices of visible chunk that is
int j2 = (y + h) / mChunkHeight; // on the right-bottom corner of the screen
i2 = i2 >= mArray.length ? mArray.length - 1 : i2;
j2 = j2 >= mArray[i2].length ? mArray[i2].length - 1 : j2;
int offsetX = x - i1 * mChunkWidth;
int offsetY = y - j1 * mChunkHeight;
for (int i = i1; i <= i2; i++) {
for (int j = j1; j <= j2; j++) {
canvas.drawBitmap(
mArray[i][j],
(i - i1) * mChunkWidth - offsetX,
(j - j1) * mChunkHeight - offsetY,
paint
);
}
}
}
/* Static */
public static Bitmap[][] divideBitmap(Bitmap bitmap) {
return divideBitmap(new Options(bitmap, 100, 100));
}
public static Bitmap[][] divideBitmap(Options options) {
Bitmap[][] arr = new Bitmap[options.xCount][options.yCount];
for (int x = 0; x < options.xCount; ++x) {
for (int y = 0; y < options.yCount; ++y) {
int w = Math.min(options.chunkWidth, options.source.getWidth() - (x * options.chunkWidth));
int h = Math.min(options.chunkHeight, options.source.getHeight() - (y * options.chunkHeight));
arr[x][y] = Bitmap.createBitmap(options.source, x * options.chunkWidth, y * options.chunkHeight, w, h);
}
}
return arr;
}
public static final class Options {
final int chunkWidth;
final int chunkHeight;
final int xCount;
final int yCount;
final Bitmap source;
public Options(Bitmap src, int chunkW, int chunkH) {
chunkWidth = chunkW;
chunkHeight = chunkH;
xCount = ((src.getWidth() - 1) / chunkW) + 1;
yCount = ((src.getHeight() - 1) / chunkH) + 1;
source = src;
}
public Options(int xc, int yc, Bitmap src) {
xCount = xc;
yCount = yc;
chunkWidth = src.getWidth() / xCount;
chunkHeight = src.getHeight() / yCount;
source = src;
}
}
}

How do I divide a picture into 4 sections and change each section?

In the body of the Picture class create a new public method named "specialEffect" that has return type void and takes no parameters.
The method should contain four loops that each iterate over the pixels of an image in such a way that each loop iterates through 1/4 of the total number of pixels and performs a different effect as follows:
The first loop is to apply an effect that removes the both the blue and green component from each pixel leaving the red component unchanged.
The next loop continuing from where the last left off is to remove the blue and red component from each pixel leaving the green component unchanged.
The next loop continuing from where the last left off it to remove the green and red component from each pixel leaving the blue component unchanged.
The final loop continuing from where the last off is to convert each pixel to greyscale.
How would I go about doing that? I only know how to divide it in half and change the top part.. not sure how to go about doing sections.
Thanks!
The code below produces this picture:
private static BufferedImage specialEffect(BufferedImage in) {
BufferedImage out = new BufferedImage(in.getWidth(), in.getHeight(),
BufferedImage.TYPE_INT_ARGB);
for (int x = 0; x < out.getWidth() / 2; x++) {
for (int y = 0; y < out.getHeight() / 2; y++) {
Color c = new Color(in.getRGB(x, y));
out.setRGB(x, y, new Color(c.getRed(), 0, 0).getRGB());
}
}
for (int x = out.getWidth() / 2; x < out.getWidth(); x++) {
for (int y = 0; y < out.getHeight() / 2; y++) {
Color c = new Color(in.getRGB(x, y));
out.setRGB(x, y, new Color(0, c.getGreen(), 0).getRGB());
}
}
for (int x = 0; x < out.getWidth() / 2; x++) {
for (int y = out.getHeight() / 2; y < out.getHeight(); y++) {
Color c = new Color(in.getRGB(x, y));
out.setRGB(x, y, new Color(0, 0, c.getBlue()).getRGB());
}
}
for (int x = out.getWidth() / 2; x < out.getWidth(); x++) {
for (int y = out.getHeight() / 2; y < out.getHeight(); y++) {
Color c = new Color(in.getRGB(x, y));
int m = Math.max(c.getRed(),Math.max(c.getGreen(),c.getBlue()));
out.setRGB(x, y, new Color(m, m, m).getRGB());
}
}
return out;
}
public static void main(String[] args) throws IOException {
JFrame frame = new JFrame("Test");
frame.add(new JComponent() {
BufferedImage image = specialEffect(ImageIO.read(new URL("http://upload.wikimedia.org/wikipedia/en/2/24/Lenna.png")));
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(image, 0, 0, this);
}
});
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(400, 400);
frame.setVisible(true);
}
I am assuming that your Picture class has the following methods:
int getNumberOfPixels()
float getRValueOfNthPixel(int n)
float getGValueOfNthPixel(int n)
float getBValueOfNthPixel(int n)
void setRValueOfNthPixel(int n, float r)
void setGValueOfNthPixel(int n, float g)
void setBValueOfNthPixel(int n, float b)
If the number of pixels is always a multiple of 4, then one possible implementation of "specialEffect" method would be:
public void specialEffect() {
int n = getNumberOfPixels();
int limit1 = 1 * n / 4;
int limit2 = 2 * n / 4;
int limit3 = 3 * n / 4;
int limit4 = 4 * n / 4;
/*
* The first loop is to apply an effect that removes the both the blue
* and green component from each pixel leaving the red component
* unchanged.
*/
for (int i = 0; i < limit1; i++) {
setBValueOfNthPixel(i, 0);
setGValueOfNthPixel(i, 0);
}
/*
* The next loop continuing from where the last left off is to remove
* the blue and red component from each pixel leaving the green
* component unchanged.
*/
for (int i = limit1; i < limit2; i++) {
setBValueOfNthPixel(i, 0);
setRValueOfNthPixel(i, 0);
}
/*
* The next loop continuing from where the last left off it to remove
* the green and red component from each pixel leaving the blue
* component unchanged.
*/
for (int i = limit2; i < limit3; i++) {
setGValueOfNthPixel(i, 0);
setRValueOfNthPixel(i, 0);
}
/*
* The final loop continuing from where the last off is to convert each
* pixel to greyscale.
*/
for (int i = limit3; i < limit4; i++) {
float grayValue = (getRValueOfNthPixel(i)
+ getGValueOfNthPixel(i)
+ getBValueOfNthPixel(i)) / 3;
setRValueOfNthPixel(i, grayValue);
setGValueOfNthPixel(i, grayValue);
setBValueOfNthPixel(i, grayValue);
}
}

resize required to view images in java applet

I'm working with java images for the first time and having a problem viewing them when the applet loads. If I resize the window they display fine. I feel like this is a common first-timer error. Has anyone else encountered this? Any idea what the fix could be? What I believe to be the pertinent parts of the code are listed below. Thanks for any and all help with this...
import java.applet.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import javax.swing.*;
import java.util.*;
public class example extends JApplet implements Runnable
{
boolean updating;
Thread thread;
private int width, height;
Table aTable; //used to create and store values
private AudioClip[] sounds = new AudioClip[4]; //array to hold audio clips
private int counter = 0; //counter for audio clip array
private Image GameImage;
private Graphics GameGraphics;
public example() //set up applet gui
{
this.resize(new Dimension(600, 500));
//setup table
aTable = new Table(50, 50, 50, 50, 16, 16, getImage("images/FLY.gif", Color.white),
getImage("images/FlySwatter.gif", Color.white)); //Table must be square or flyswatter wont move straight
//add cordTxtFlds to bottom of screen
//this.add(cordTxtFlds, BorderLayout.SOUTH);
super.resize(800, 600);
repaint();
}
public void init()
{
width = getSize().width;
height = getSize().height;
GameImage = createImage(width, height);
GameGraphics = GameImage.getGraphics();
// Automatic in some systems, not in others
GameGraphics.setColor(Color.black);
repaint();
validate();
//show the greeting
ImageIcon icon = new ImageIcon("images/FLY.gif",
"a fly");
repaint();
validate();
}
/** Description of paint(Graphics g)
*
* Function draws table and sets the table color
* #param g graphics object used to draw table
* #return void
*/
public void paint(Graphics g)
{
GameGraphics.clearRect(0, 0, getWidth(), getHeight());
aTable.draw(GameGraphics);
g.drawImage(GameImage, 0, 0, this);
}
public void update(Graphics g)
{
paint(g);
validate();
}
public void start()
{
thread = new Thread(this);
thread.start();
}
public void stop()
{
updating = false;
}
public void run()
{
while(updating)
{
aTable.update();
}
}
//returns a transparent image.
//color is made transparent
private Image getImage(String imgPath, final Color color)
{
Image img = Toolkit.getDefaultToolkit().getImage(imgPath);
ImageFilter filter = new RGBImageFilter() {
// the color we are looking for... Alpha bits are set to opaque
public int markerRGB = color.getRGB() | 0xFFFFFF;
public final int filterRGB(int x, int y, int rgb) {
if ( ( rgb | 0xFF000000 ) == markerRGB ) {
// Mark the alpha bits as zero - transparent
return 0x00FFFFFF & rgb;
}
else {
// nothing to do
return rgb;
}
}
};
ImageProducer ip = new FilteredImageSource(img.getSource(), filter);
img = Toolkit.getDefaultToolkit().createImage(ip);
return img;
}
}
and the class which handles the drawing (in drawValues())
import java.awt.*;
import java.util.Random;
public class Table extends Panel
{
private char[][]values = new char[10][10]; //probably better to use array of integer values(0 or 1)
private Point[]coordLoc;// = new Point[100]; //stores the x & y coordinates of points on the grid
private boolean[]itemMarker; //stores the truth value of wether or not an item
// is located at the coresponding point in cordLoc array
private int [][]coords;// = new int [100][2];
Image itemImg; // stores the item image
private int Rows; // stores number of rows
private int Columns; // stores number of columns
private int BoxWidth ; // stores the width of a box
private int BoxHeight; // stores the height of a box
public Point Pos = new Point(); // creates a new point to draw from
private int tableHeight; // stores the height of the table
private int tableWidth; // stores the width of the table
private int numOfGridLocs;
/** Description of public Table( x, y, width, height, col, rows, X, O)
*
* Constructor function
* #param x contains an x-coordinate of the table
* #param y contains a y-coordinate of the table
* #param width contains the width of a box in the table
* #param height contains the height of a box in the table
* #param col contains the number of columns in the table
* #param rows contains the number of rows in the table
* #param itemImg contains the "target" image ie: ant, fly, ... unicorn
* #return none
*/
public Table(int x, int y, int width, int height, int col, int rows, Image itemImg, Image swatterImg)
{
/*set values*/
numOfGridLocs = (col - 1) * (rows - 1);
//initialize arrays
coordLoc = new Point[numOfGridLocs];
for(int i = 0; i < numOfGridLocs; i++)
coordLoc[i] = new Point();
Rows = rows;
Columns = col;
BoxWidth = width;
BoxHeight = height;
Pos.x = x;
Pos.y = y;
this.itemImg = itemImg;
tableHeight = Rows*BoxHeight;
tableWidth = Columns*BoxWidth;
itemMarker = new boolean[numOfGridLocs];
coords = new int [numOfGridLocs][2];
this.setValues();
mapGrid();
}
/** Description of draw(Graphics g)
*
* Function draws the lines used in the table
* #param g object used to draw the table
* #return none
*/
public void draw(Graphics g)
{
Graphics2D g2=(Graphics2D)g;
//draw flyswatter
drawValues(g2); //draw values
//draw vertical table lines
for (int i = 0 ; i <= Columns ; i++)
{
//make center line thicker
if(i == Rows/2)
g2.setStroke(new BasicStroke(2));
else
g2.setStroke(new BasicStroke(1));
g2.drawLine(i*BoxWidth + Pos.x, Pos.y, i*BoxWidth + Pos.x, tableHeight+Pos.y);
}
//draw horizontal table line
for(int i = 0 ; i <= Rows ; i++)
{
//make center line thicker
if(i == Rows/2)
g2.setStroke(new BasicStroke(2));
else
g2.setStroke(new BasicStroke(1));
g2.drawLine(Pos.x, i*BoxHeight + Pos.y, tableWidth+Pos.x, i*BoxHeight + Pos.y);
}
drawLables(g);
}
/** Description of drawLables(Graphics g)
*
* Function draws the Lables of the Table
* #param g object used to draw the table
* #return none
*/
private void drawLables(Graphics g)
{
String Lable;
Graphics2D g2 = (Graphics2D)g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
Font font = new Font("Serif", Font.PLAIN, 10);
g2.setFont(font);
int xLabel = this.Columns/2 * -1;
int yLabel = this.Rows/2;
//draw Row lables
for (int i = 0 ; i <= Rows ; i++)
{
Lable = "" + yLabel;
g2.drawString(Lable, Pos.x - 25, Pos.y + BoxHeight*i);
yLabel--;
}
//draw Column lables
for (int i = 0 ; i <= Columns ; i++)
{
Lable = "" + xLabel;
g2.drawString(Lable, Pos.x + BoxWidth*i - 5, Pos.y - 20 );
xLabel++;
}
}
/** Description of randomChangeFunc()
*
* Function randomly determines which table value to change
* #param none
* #return void
*/
public int getX(int XCordinate)
{
int x = XCordinate+Columns/2;
if(x < 0) x *= -1; //x must be positive
x *= BoxWidth;
x += Pos.x;
return x-BoxWidth/2;
}
//returns Position of Y-cordinate
public int getY(int YCordinate)
{
int y = YCordinate -Rows/2;
if (y < 0) y *= -1; //y must be positive
y *= BoxHeight;
y += Pos.y;
return y-BoxHeight/2;
}
/** Description of getValue( col, row )
*
* Function draws the lines used in the table
* #param col contains a column coordinate
* #param row contains a row coordinate
* #return returns table coordinates
*/
public char getValue(int col, int row)
{
return values[row][col];
}
/** Description of isDrawable( x, y )
*
* Function returns true if (x,y) is a point in the table
* #param x contains a table column
* #param y contains a table row
* #return boolean if (x,y) is a point in the table
*/
public boolean isDrawable(int x, int y)
{
if((this.getRow(y)!=-1)||(this.getColumn(x)!=-1))
return true;
else
return false;
}
private void drawValues(Graphics g)
{
for(int i = 0; i < numOfGridLocs; i++)
if(itemMarker[i])
g.drawImage(itemImg,coordLoc[i].x+1, coordLoc[i].y+1, BoxWidth-1, BoxHeight-1, null);
g.setColor(Color.black); // set color of table to black
}
//sets the randomized boolean values in itemMarker array
private void setValues()
{
double probOfItem = .25;
for(int count = 0; count < numOfGridLocs; count++){
itemMarker[count] = randomBool(probOfItem);
if(itemMarker[count])
System.out.println("true");
else
System.out.println("false");
}
}
//returns random boolean value, p is prob of 'true'
private boolean randomBool(double p)
{
return (Math.random() < p);
}
public int getColumn(int x)
{
x += (BoxWidth/2); //aTable.getX/Y returns in the middle of squares not at upper left point
int offsetx=0;
for (int i = 0 ; i < Columns*2 ; i++)
{
offsetx = i*BoxWidth;
if((x>=Pos.x+offsetx)&& (x<Pos.x+offsetx+BoxWidth))
return i-Columns;
}
return -100;
}
public int getRow(int y)
{
int offsety=0;
y += (BoxHeight/2); //aTable.getX/Y returns in the middle of squares not at upper left point
for (int i = 0 ; i < Rows*2 ; i++) {
offsety = i * BoxHeight;
if((y >= (offsety+Pos.y))&& (y < (offsety+BoxHeight+Pos.y)))
{
return ((i)*-1)+Rows;
}
}
return -100;
}
public boolean isValidGuess(int x, int y)
{
if ((x > Columns/2) || (x < Columns/2*-1) || (y > Rows/2) || (y < Rows/2*-1))
return false;
return true;
}
/** Description of randomChangeFunc()
*
* Function randomly determines which table value to change
* #param none
* #return void
*/
public void randomChangeFunc()
{
//get random row and column
Random rand=new Random();
int randRow = rand.nextInt(Rows); // gets and holds a random column
int randCol = rand.nextInt(Columns); // gets and holds a random column
System.out.println("randRow = " + randRow + " randCol = " + randCol);
if(values[randRow][randCol] == 'X')
values[randRow][randCol] = 'O';
else if(values[randRow][randCol] == 'O')
values[randRow][randCol] = 'X';
else
System.out.println("ERROR SWAPPING SQUARE VALUE"); // error message
}
private void mapGrid() //set values for coordLoc array
{
//set counter variables
int count = 0;
int index = 0;
//loop through all points, assigning them to the coordLoc array
for (int r=0; r < Rows-1; r++)
for (int c=0; c < Columns-1; c++) {
//the width/height / 2 places the points on grid line intersections, not the boxes they create
coordLoc[count].x = Pos.x + (BoxWidth) * c + (BoxWidth/2); // record x-point
coordLoc[count].y = Pos.y + (BoxHeight) * r + (BoxHeight/2); // record y-point
System.out.println(coordLoc[count].getX() + ", " + coordLoc[count].getY());
count++;
} //end inner for
//set positive x coord values for coords array
int y_axisBeginingIndex = (Rows - 2)/2;
for(int greaterIndex = 0; greaterIndex < ((Rows) / 2); greaterIndex++){
for(int minorIndex = 0; minorIndex < (Rows - 1); minorIndex++){
index = y_axisBeginingIndex + greaterIndex + ((Rows - 1) * minorIndex);
coords[index][0] = greaterIndex;
}
}
//set negative x coord values for coords array
for(int greaterIndex = -1; greaterIndex > (0-((Rows) / 2)); greaterIndex--){
for(int minorIndex = 0; minorIndex < (Rows - 1); minorIndex++){
index = y_axisBeginingIndex + greaterIndex + ((Rows - 1) * minorIndex);
coords[index][0] = greaterIndex;
}
}
//set positive y values for coords array
int x_axisBeginingIndex = (Rows - 1) * ((Rows / 2) - 1);
for(int greaterIndex = 0; greaterIndex < ((Rows) / 2); greaterIndex++){
for(int minorIndex = 0; minorIndex < (Rows - 1); minorIndex++){
index = x_axisBeginingIndex + minorIndex;
coords[index][1] = greaterIndex;
}
x_axisBeginingIndex -= (Rows - 1);
}
//set negative y values for coords array
x_axisBeginingIndex = (Rows - 1) * ((Rows / 2) - 1) + (Rows - 1);
for(int greaterIndex = -1; greaterIndex > (0-((Rows) / 2)); greaterIndex--){
for(int minorIndex = 0; minorIndex < (Rows - 1); minorIndex++){
index = x_axisBeginingIndex + minorIndex;
coords[index][1] = greaterIndex;
}
x_axisBeginingIndex += (Rows - 1);
}
//print out the x and y coords
for(int i = 0; i < numOfGridLocs; i++){
System.out.println("[" + i + "] -> x = " + coords[i][0] + " y = " + coords[i][1]);
}
}
public boolean thereIsAnItemAt(int index){
return itemMarker[index];
}
public boolean bugsLeft(){
boolean thereAreBugsLeft = false;
for(int i = 0; i < numOfGridLocs; i++)
if(itemMarker[i])
thereAreBugsLeft = true;
return thereAreBugsLeft;
}
void update()
{
this.repaint();
}
}
Been stumped on this for weeks. Thanks again...
What I believe to be the pertinent
parts of the code are listed below.
By definition when you have a problem you don't know what part of the code is (or isn't) relevant. That is why you need to post a SSCCE that demonstrates the problem so we can see what you are doing.
The fact that is work "after" a resize means the problem is not with the painting. The problem could be that the images aren't loaded in which case you should be using:
drawImage(...., this);
The "this" instead of "null" notifies the panel to repaint the image when the image gets fully loaded.
Or maybe, you added the panel to the frame after the frame was visible and forgot to use
panel.revalidate().
By resizing the frame you force a revalidation.
The point is we are guessing. So save us time and post a SSCCE next time.
Sorry still too much code.
You need to read the article on Painting in AWT and Swing. Your code is a mixture of both.
Basically, as you where told in your last posting custom painting is done by overriding the paintComponent(...) method of JPanel. So you do the custom painting and then add the JPanel to the JApplet. I gave you a link to the Swing tutorial in your last posting and it also contains a section on how to write an Applet.
You should be extending JPanel, not Panel.
Also, you should NOT be overriding the paint() and upated() method of JApplet, this is old AWT code and should NOT be used with Swing.
Read the article and fix the problems first.
The answer is changing the draw() method in the class that extends JPanel to paintComponent() and switching the last parameter in the call to drawImage() to 'this' instead of 'null'. Worked instantly and perfectly!

Categories