I am creating a brick breaker game for school using ArrayLists, abstraction, and polymorphism. I have created an abstract class DrawableBrick that includes a draw method. I have already successfully created the other subclasses that fill my ArrayList and the game works beautifully, but I need to create a new subclass called ShavedBrick that is a polygon that can be easily added to my ArrayList.
I am a little stuck as to how to create the parameterized constructor for this class and to set the class data to the arguments passed in by the user. Here is what I have so far. It needs to be an octagon.
import java.awt.*;
import java.util.*;
public class ShavedBrick extends DrawableBrick {
//data
private int [] xArray = new int [8];
private int [] yArray = new int [8];
private int numberOfSides;
//private Color color;
//constructor
public ShavedBrick(int[] x {}, int [] y {}, int numberOfPoints)
{
Random ranGen = new Random();
xArray[0] = x;
yArray[0] = y;
this.numberOfSides = numberOfPoints;
//this.width = width;
//this.height = height;
this.color = new Color(0,(ranGen.nextInt(156)+100),0);
}
//draw - tells the ShavedBrick to draw itself, using the Graphics object received
public void draw(Graphics g)
{
Color prevColor = g.getColor(); //save previous color associated with g
g.setColor(this.color);
g.fillPolygon(xArray, yArray, numberOfSides);
g.setColor(prevColor); //restore previous color
}
Here is an example of creating the object in the ArrayList
//some constants created in the main data
private final int WALLWIDTH = 5; //Walls' width
private final int BRICKSTARTX = WALLWIDTH;
private final int BRICKSTARTY = 100 + WALLWIDTH;
private final int BRICKWIDTH = 150;
private final int BRICKHEIGHT = 75;
//Fill the ArrayList with random DrawableBricks
for (int i = 0; i<10; i++){
Random random = new Random();
int randomBrick = random.nextInt(3);
if (randomBrick == 0){
myBricks.add(i, new RedBrick((BRICKSTARTX + i*BRICKWIDTH),(BRICKSTARTY + BRICKHEIGHT),BRICKWIDTH,BRICKHEIGHT));
myBricks.add(i, new RedBrick((BRICKSTARTX + i*BRICKWIDTH),((BRICKSTARTY+75) + BRICKHEIGHT),BRICKWIDTH,BRICKHEIGHT));
}
else if (randomBrick == 1) {
myBricks.add(i, new BlueBrick((BRICKSTARTX + i*BRICKWIDTH),(BRICKSTARTY + BRICKHEIGHT),BRICKWIDTH, BRICKHEIGHT));
myBricks.add(i, new BlueBrick((BRICKSTARTX + i*BRICKWIDTH),((BRICKSTARTY+75) + BRICKHEIGHT),BRICKWIDTH,BRICKHEIGHT));
}
//else if (randomBrick == 3){
//myBricks.add(new ShavedBrick(0,0,2,6));
//}
else if (randomBrick == 2){
for (int i = 0; i<8; i++){
xValues[] array = new xArray[8];
myBricks.add(new ShavedBrick(int [i] x {BRICKSTARTX,});
}
}
}
i would suggest something like this...
public ShavedBrick(int[] x, int[] y, int numberOfPoints)
{
Random ranGen = new Random();
for(int i = 0; i < 8; i ++) {
xArray[i] = x[i];
yArray[i] = y[i];
}
this.numberOfSides = numberOfPoints;
this.color = new Color(0,(ranGen.nextInt(156)+100),0);
}
Basically, remove the braces ({ }) from the constructor signature. And add each of the 8 elements in the input arrays to the private arrays of the class using a for loop. You could point the private arrays of the class directly to the input arrays, but i would personally avoid that and simply copy the values to a newly created pair of arrays.
You could also use the Array.copyOf(int[], int) http://docs.oracle.com/javase/6/docs/api/java/util/Arrays.html#copyOf(int[], int) as well.
In your client code just run a loop to compute your co-ordinates and then pass those co-ordinates along to the constructor like this ...
int[] xArray = new int[8];
int[] yArray = new int[8];
for (int i = 0; i < 8; i ++) {
xArray[i] = //some value for the x co-ordinate of the ith point
yArray[i] = //some value for the y co-ordinate of the ith point
}
ShavedBrick b = new ShavedBrick(xArray, yArray, 8);
myBricks.add(b); //finally add the new shaved brick
You can directly assign the argument arrays as follows:
public ShavedBrick(int[] xArray, int[] yArray, int numberOfPoints)
this.xArray = xArray;
this.yArray = yArray;
//...
int[] x {} actually creates a new empty array which of course is not a valid parameter declaration. Parameter declaration should look as int[] xArray.
I'm not sure what your problem is, but if you have an octagon then you don't need a numberOfPoints argument:
public ShavedBrick(int[] x, int [] y)
{
Random ranGen = new Random();
this.numberOfSides = 8; //it's always 8
xArray = Arrays.copyOf(x,numberOfSides); //note, this method will pad array with zeros if x.length is less than 8
yArray = Arrays.copyOf(y,numberOfSides);
this.color = new Color(0,(ranGen.nextInt(156)+100),0);
}
Related
I'm trying to initialize a bi-dimensional array of an object that I've created that has a some parameters (x,y,width,height) but doesn't work... The object is just a g.fillOval and when I do the initializing only prints the last object of the array.
Ovals = new Oval[4][4];
for (int y = 0; y < 4; y++) {
for (int x = 0; x < 4; x++) {
Ovals[x][y] = new Oval(x*100, y, 30,30);
}
}
...
for (int y = 0; y < 4; y++) {
for (int x = 0; x < 4; x++) {
Ovals[x][y].paint(g);
}
}
The Oval class:
package objectes;
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Graphics;
import java.util.Random;
public class Oval extends Canvas{
private static Random random;
private static int r1 = 0;
private static int r2 = 0;
private static int x = 0;
private static int y = 0;
private static int randomN = 5;
public static int color; //0 = red(#FF5C5C), 1 = blue(#4097ED), 2 = green(#65EB8F), 3 = yellow(#F5F267), 4 = orange(#FFAD42)
public Oval(int x, int y, int r1, int r2) {
//Constructor
this.x = x;
this.y = y;
this.r1 = r1;
this.r2 = r2;
random = new Random();
randomN = random.nextInt();
if (randomN < 0 ) {
randomN = randomN*-1;
}
randomN = randomN % 5;
}
public void paint(Graphics g) {
switch (randomN) {
case 0:
g.setColor(Color.decode("#ff5C5C"));
break;
case 1:
g.setColor(Color.decode("#4097ed"));
break;
case 2:
g.setColor(Color.decode("#65eb8f"));
break;
case 3:
g.setColor(Color.decode("#f5f267"));
break;
case 4:
g.setColor(Color.decode("#ffad42"));
break;
}
g.fillOval(x, y, r1, r2);
}
}
All of your classes variables are static
private static int r1 = 0;
private static int r2 = 0;
private static int x = 0;
private static int y = 0;
This means they are associated with the class Oval.. not a single instance of Oval.
Because there is only one copy of each variable, every time you make a new Oval you will overwrite the last value set. When you finally go to draw the Ovals, all of them will be drawn in the exact same spot!
Make them instance variables instead:
private int r1 = 0;
private int r2 = 0;
private int x = 0;
private int y = 0;
The placedShapeInfo() gives me almost the correct result except it gives me wrong coordinates for Shapes at (?,?) like in the following test case:
It seems Im doing smth wrong while reading this line in placedShapeInfo():
"("+coords.get(i)+"," + coords.get(i+1)+")"
Each time a shape passed to placeShapeAt(int row, int col, Shape shape) I add its row and col into the Arraylist coords.
Could smb help me out with this?
import java.util.*;
public class CreateSpace implements Space{
private int height;
private int width;
//private int placedAtRow = 0;
//private int placedAtCol = 0;
private String layout;
private char[][] space;
private Shape originalShape;
private ArrayList<CreateShape> shapes = new ArrayList<>();
private ArrayList<Integer> coords = new ArrayList<>();
Set<Character> shapesCount;
public CreateSpace(int height, int width, char[][] space, String layout)
{
this.height = height;
this.width = width;
this.space = space;
this.layout = layout;
}
public void placeShapeAt(int row, int col, Shape shape)
{
int row1 = row;
int col1 = col;
int sHeight = shape.getHeight();
int sWidth = shape.getWidth();
char [][] spaceWithShapes = space;
if(shapeFitsAt(row, col, shape))
{
for(int r = 0; r < sHeight; r++)
{
for(int c = 0; c < sWidth; c++)
{
if(spaceWithShapes[r+row][c+col] == '.' && shape.isFilledAt(r, c))// && shape.isFilledAt(r,c) == true) //|| (((CreateShape)shape).getShape()[r][c] == '.'))
{
spaceWithShapes[r+row][c+col] = shape.getDisplayChar();
}
}
}
shapes.add((CreateShape)shape);
coords.add((Integer)row1);
coords.add((Integer)col1);
//shapes.add((Integer)row1);
Collections.sort(shapes);
setSpace(spaceWithShapes);
}
else
throw new FitItException("The shape does not fit!");
}
public String placedShapeInfo()
{
Collections.sort(shapes);
int shapesTotal = placedShapeCount();
String desc = shapesTotal + " shapes placed";
String getShapeInfo = "";
for(int i = 0; i < shapes.size(); i++)
//for(int j = 0; j < coords.size(); j++)
{
getShapeInfo +="Shape at " + "("+coords.get(i)+"," + coords.get(i+1)+")" + "\n" + shapes.get(i).toString() + "\n";
System.out.println();
}
return desc + "\n" +
getShapeInfo;
Your coords is a list of integers. So you add two shapes at (1,2) and (3,4). So coords is now (1,2,3,4).
Then you iterate through your list of shapes and for each shape get coords.get(i) and coords.get(i+1). Are you seeing the problem yet?
For your first shape, i=0 and you get coords 0 and 1, which gives you (1,2).
For your second shape, i=1 and you get coords 1 and 2, which gives you (2,3).
You're not using i consistently. Maybe each shape should know its own coordinates and you should ask it for its x and y instead of storing them in an external data structure. That's one way of dealing with it, and that's the sort of thing OO programming is good at.
I've created a function to generate a 2-dimension array of Perlin Noise data, starting with a base noise array of random values between 0 and 1.
The base white noise array looks like this:
From there, I use the smoothNoise() function to interpolate values to create good looking image (which I don't have because it doesn't work)
The smooth noise function is called once every octave. The images of what data the smooth noise function returns is as follows (octaves lowest to highest)
After all the smoothing is done the image outputted turns black. I would upload an image but it is just black so there is no need.
My Code is:
import java.util.Random;
public class Noise2D {
int width;
int height;
public Noise2D(int width, int height){
this.width = width;
this.height = height;
}
public double[][] generateWhiteNoise(int width,int height){
Random r = new Random(0);
double[][] whiteNoise = new double[width][height];
for(int i = 0; i<whiteNoise.length; i++){
for(int j = 0; j<whiteNoise[0].length;j++){
double rNum = r.nextDouble()%1;
whiteNoise[i][j] = (double)rNum;
}
}
ImageWriter.writeImage(whiteNoise, "WhiteNoise");
return whiteNoise;
}
public double interpolate(double x0, double x1, double alpha){
return x0 * (1 - alpha) + alpha * x1;
}
public double[][] generateSmoothNoise(double[][] baseNoise, int octave){
int width = baseNoise.length;
int height = baseNoise[0].length;
double[][] smoothNoise = new double[width][height];
int period = 1<< octave; //2^i
double frequency = 1.0/period;
for(int x = 0; x<width; x++){
int x0 = (x/period)*period; //7/3 = 2 *3 = 6
int x1 = (x0+period)%width;
double hBlend = (x-x0)*frequency;
for(int y = 0; y<height; y++){
int y0 = (y/period)*period;
int y1 = (y0 + period)%height;
double vBlend = (y - y0)*frequency;
double top = interpolate(baseNoise[x0][y0],baseNoise[x1][y1],hBlend);
double bottom = interpolate(baseNoise[x0][y1],baseNoise[x1][y0],hBlend);
smoothNoise[x][y] = interpolate(top,bottom,vBlend);
}
}
ImageWriter.writeImage(smoothNoise,"Smooth"+Integer.toString(octave));
return smoothNoise;
}
public double[][] generatePerlinNoise(double baseNoise[][], int octaves){
int width = baseNoise.length;
int height = baseNoise[0].length;
double persistence = 0.5;
double[][][] smoothNoise = new double[octaves][][];
for(int i = 0; i<octaves; i++){
smoothNoise[i] = generateSmoothNoise(baseNoise,i);
}
double[][] perlinNoise = new double[width][height];
double amplitude = 1;
double totalAmplitude = 0;
for(int octave = octaves-1; octave>=0; octave--){
amplitude*=persistence;
totalAmplitude+=amplitude;
for(int x = 0; x<width;x++){
for(int y = 0; y<height; y++){
perlinNoise[x][y] = smoothNoise[octave][x][y] * amplitude;
}
}
}
ImageWriter.writeImage(perlinNoise,"files");
for(int i = 0; i<width; i++){
for(int j = 0; j<height; j++){
perlinNoise[i][j] /= totalAmplitude;
}
}
return perlinNoise;
}
}
The Class is defined and methods are called by:
Perlin p = new Perlin(256,256);
writeImage(p.smoothNoise(p.makeNoise(256,256), 1, 16), "Perlin");
1 is frequency, 16 is octave count
Where the data is written in the function writeImage(2d array, "name") using the following code (I don't think there is a problem with this part but I'll post it anyway):
public static void writeImage(double[][] data,String name){
BufferedImage img = new BufferedImage(data.length,data[0].length,BufferedImage.TYPE_INT_RGB);
for(int y = 0; y<data.length; y++){
for(int x = 0; x<data[y].length; x++){
if(data[y][x]>1){
data[y][x] = 1;
}
if(data[y][x]<0){
data[y][x] = 0;
}
Color c = new Color((float)data[y][x],(float)data[y][x],(float)data[y][x]);
img.setRGB(x,y,c.getRGB());
}
}
try{
File file = new File(name+".png");
file.createNewFile();
ImageIO.write(img,"png",file);
}catch(IOException e){
e.printStackTrace();
}
}
public static void writeExistingImage(BufferedImage img){
try{
File file = new File("noise2.png");
file.createNewFile();
ImageIO.write(img,"png",file);
}catch(IOException e){
e.printStackTrace();
}
}
To conclude, I believe the problem lies within the smoothNoise method, although I could quite possibly be wrong because my knowledge of Perlin Noise is not extensive. If the problem does not lie here, I assume it lies in the generatePerlinNoise() method. Any help would be greatly appreciated. I will be so happy with any suggestion, I have been trying to solve this problem for an extremely long time.
To clarify:
My problem is that the generatePerlinNoise method returns a set of data(2d) array that makes a black image (rather than a cool noise image)
I also think that the smooth noise images are not supposed to look like they are split up into squares
public static void sample(BufferedImage image) {
int width = image.getWidth();
int height = image.getHeight();
int value[][] = new int[width][height];
int valueR[][] = new int[width][height];
int valueG[][] = new int[width][height];
int valueB[][] = new int[width][height];
for (int j = 0; j < height; j++) {
for (int i = 0; i < width; i++) {
int pixel = image.getRGB(i, j);
value[i][j] = pixel;
Color c = new Color(pixel);
valueR[i][j]= c.getRed();
valueG[i][j] = c.getGreen();
valueB[i][j] = c.getBlue();
System.out.println("Red value = "+valueR[i][j]);
System.out.println("Green value ="+valueG[i][j]);
System.out.println("Blue value"+valueB[i][j]);
}
}
}
The above code is to store RGB values and pixel color values of an image in an array separately.
public static BigInteger modPow(BigInteger a1, BigInteger e, BigInteger n) {
BigInteger r = 1;
for (int i = e.bitLength() - 1; i >= 0; i--) {
r = (r.multiply(r)).mod(n);
if (e.testBit(i)) {
r = (r.multiply(a1)).mod(n);
}
}
System.out.println("C value = " + r);
int lng = 3;
BigInteger bi = BigInteger.valueOf(lng);
BigInteger a = r.divide(bi);
BigInteger b = r.mod(bi);
System.out.println("pixel position a = " + a);
System.out.println("modulus value b = " + b);
return r;
}
In the above code am finding pixel position where i need to embed the secret bit.so i need to go to that specific pixel to embed the message.But in the previous code am storing pixel color in array value[][].i need to search through the array value[][] to get the pixel position which i got in last code.
Note: a1 is the position of current bit of information file to embed
{e,n} is public key
My question is how to find the pixel positions?
To find the position of a pixel is a simple concept with a complex execution. I've written some code here that takes a BufferedImage and searches through it for a pixel of a specific color.
import java.awt.Color;
import java.awt.image.BufferedImage;
import java.io.File;
import javax.imageio.ImageIO;
import java.io.IOException;
public class pixelSearch {
public static void main(String[] args) {
//I don't know where you're getting your image but i'll get one from file
File image = new File("image.bmp");
try {
BufferedImage imageToSearch = ImageIO.read(image);
Color colorToFind = new Color(255,255,255); //define color to search for with RGB vals 255,255,255
//for more information on constructing colors look here: http://docs.oracle.com/javase/7/docs/api/java/awt/Color.html
int[] pixelCoordinates = pSearch( colorToFind, imageToSearch ); //search for the pixel
System.out.println("Found pixel at (" + pixelCoordinates[0] + "," + pixelCoordinates[1] + ")."); //display coordinates
} catch (IOException e) {
System.out.println(e.toString());
}
}
private static int[] pSearch ( Color c, BufferedImage pic ){
int cVal = c.getRGB(); //get integer value of color we are trying to find
int x1 = 0;
int y1 = 0;
int x2 = pic.getWidth();
int y2 = pic.getHeight();
int[] XArray = new int[x2-x1+1]; //create an array to hold all X coordinates in image
int iterator = 0;
while (iterator <= x2) {
XArray[iterator] = x1 + iterator;
iterator++;
}
int [] YArray = new int[y2-y1+1]; //create an array to hold all Y coordinates in image
iterator = 0;
while (iterator <= y2) {
YArray[iterator] = y1 + iterator;
iterator++;
}
//next we iterate throug all the possible coordinates to check each pixel
for (int yVal : YArray) {
for (int xVal : XArray) {
int color = pic.getRGB(xVal, yVal); //get the color of pixel at coords (xVal, yVal)
if (color == cVal) { //if the color is equal to the one we inputted to the function
int[] cPos = {xVal, yVal}; //store the coordinates
return cPos; //return the coordinates
}
}
}
int[] returnVal = {-1,-1}; //if we didn't find it return -1, -1
return returnVal;
}
}
I have everything else correct, but for some reason this is giving me problems. I want to implement a method called populate(). i want to be called in the constructor. I want it to the method to create a random number of objects of each type of object. This is my code.
my error is "*strong text*constructor yellowish in class yellowish cannot be a apllied to given types. required: int found: not argument reason: actual and form argument list differ in length.
public class FishWorld extends World
{
/**
* Constructor for objects of class FishWorld.
*
*/
public FishWorld()
{
super(600, 400, 1);
populate();
populate2();
populate3();
}
public void populate()
{
int randX;
int randY;
for(int i = 0; i < 5; i++)
{
YellowFish yf = new YellowFish();
randX = Greenfoot.getRandomNumber ( getWidth() );
randY = Greenfoot.getRandomNumber( getHeight() );
addObject(yf, randX, randY);
}
}
public void populate2()
{
int randX;
int randY;
for(int i = 0; i < 5; i++)
{
GreenFish gf = new GreenFish();
randX = Greenfoot.getRandomNumber ( getWidth() );
randY = Greenfoot.getRandomNumber( getHeight() );
addObject(yf, randX, randY);
}
}
public void populate3()
{
int randX;
int randY;
for(int i = 0; i < 5; i++)
{
StripeFish sf = new StripeFish();
randX = Greenfoot.getRandomNumber ( getWidth() );
randY = Greenfoot.getRandomNumber( getHeight() );
addObject(yf, randX, randY);
}
}
}
It seems you don't have empty parameter constructor in class YellowFish. You might want to add:
public YellowFish() {
// ... your code here
}
in the YellowFish class.