Combine elements from ArrayLists - java

I know that some answers have been provided for similar questions, but none of them seemed to be suitable for my issue. I'm making a program to generate images for Granny Squares, or squares that have different color rings on the inside.
The user is able to select how many rings there are, and therefore the number of colors necessary will change. Therefore, I cannot use nested for loops to go through each color as the number of for loops would have to change. Is there a way I can create combinations for these colors?
For example, if I used the colors White, Blue, and Green, the following combinations would be White, White, White; White, White, Blue; White, White, Green; White, Blue, White; etc. So is there a way to accomplish this without nested for loops?

Here is an algorithm that achieves this using recursion.
public static void combine(List<Character> colors, List<Character> combination) {
if (combination.size() == colors.size()) {
System.out.println(combination);
} else {
for (char color : colors) {
combination.add(color);
combine(colors, combination);
combination.remove(combination.size() - 1);
}
}
}
public static void main(String[] args) {
List<Character> colors = new ArrayList<>();
colors.add('W');
colors.add('B');
colors.add('G');
combine(colors, new LinkedList<Character>());
}
colors is the original list of colors (W, B, G)
combinations is a list that is continually modified throughout the recursion to hold the current combination.
Here is what happens to combination until it first hits the base case
[W] // add W, call recursively
[W, W] // add W, call recursively
[W, W, W] // add W, call recursively
The base case is now met, and it prints [W, W, W]. It then removes the last color we put in the list, W, and adds the next color in colors to combination, which gives [W, W, B]. The base case is met again so it prints it out.
It continues to do this until all combinations have been printed.

Related

Java game 2D overlapping shadows with Swing

I am currently developing a 2D Java game using Swing as my primary drawing component. Every object has a shadow (BufferedImage) but every shadow overlaps other shadows. Is it possible to only have the shadows not overlap each other? Because I still want the shadows to draw over the player if the object is beneath it, and not if the object is above of the player. Here is a picture for clarity:
I have looked at alpha compositing, I guess I need Source Out? I also thought of having all the shadows (with no transparency) draw on one layer and then draw it with transparency but then it won't draw over the player and other objects like before.
I have a Draw object which is a JPanel and overrides the paintComponent method. Within this method I draw the floor of the current room and then I iterate over the list of objects that belongs to the current room and call each objects' draw method to draw everything.
The object draw method:
public void draw(Graphics g) {
if (visible && checkInScreen()) {
// The required drawing location
int drawLocationX = getX() - globalCameraX;
int drawLocationY = getY() - globalCameraY;
if (shadow) {
g.drawImage(shadowImages.get(imageIndex),
drawLocationX + shadowOffset.x + (getImageWidth()/2),
drawLocationY + shadowOffset.y, null);
}
g.drawImage(images.get(imageIndex), drawLocationX, drawLocationY, null);
//Collisionbox
if (SHOW_COLLISION_BOXES){
g.setColor(Color.WHITE);
g.drawRect(drawLocationX + getCollBoxX(), drawLocationY + getCollBoxY(), getCollBoxW() - getCollBoxX(), getCollBoxH() - getCollBoxY());
}
}
}
My apologies if this question has already been asked but I couldn't find something similar like this.
What I would do to solve this is to have a shadow-layer bitmap. By which I mean:
have your shadow textures saved as a 2D array of boolean values (representing the position of a shadow pixel).
What you can do with this is to then logically or the shadow maps together to create a single layer, which can be layered behind the tree textures to create the shadows.
You may want to change the booleans to floats to represent the colour/intensity of the shadow, then have a larger calculation to merge the shadows together.
The below ShadowMap class is used to store the data for each shadow:
class ShadowMap {
public int xPos, yPos;
public boolean[][] array;
public ShadowMap(int xPos, int yPos, boolean[][] array) {
this.xPos = xPos;
this.yPos = yPos;
this.array = array;
}
}
The ShadowLayer class creates a 2D array for the entire screen, containing if a shadow is present for each pixel:
class ShadowLayer {
public static boolean[][] array = new boolean[SCREEN_WIDTH][SCREEN_HEIGHT];
public static makeNew(ShadowMap[] shadows) {
for (int x = 0; x < SCREEN_WIDTH; x++) {
for (int y = 0; y < SCREEN_HEIGHT; y++) {
array[x][y] = false;
}
}
for (ShadowMap map : shadows) {
for (int i = 0; i < SCREEN_WIDTH; i++) {
for (int j = 0; j < SCREEN_HEIGHT; j++) {
// Logical or such that the pixel at (x, y) has a shadow
// if any shadow map also has a shadow at pixel (x, y)
array[i + map.xPos][j + map.yPos] |= map.array[i][j];
}
}
}
}
}
Using this ShadowLayer class, you just need to darken each pixel on the screen if the ShadowMap has a shadow on the same pixel:
public static Color ajustPixelForShadows(int x, int y, Color pixel) {
return ShadowMap.array[x][y] ? pixel.darken() : pixel;
}
I admit I'm not familiar with Swing so I'm not sure it is possible with that specific interface but the below solution could be used in a variety of 2D graphics engines.
You'll need an off-screen "shadow layer" to draw to that matches the screen dimensions. Initialize the shadow layer to being pure white.
For each object you draw from back to front (y-sorting), do the following, in order, with the shadow layer:
Draw the object's shadow shape in a single solid dark grey color to the shadow layer
Draw the object itself to the shadow layer as a pure white sprite (i.e. all non-transparent pixels in the object's bitmap are white)
Of course, also draw the object itself to the screen.
Then, once all objects have been drawn to both the screen and the shadow layer, draw the shadow layer to the screen using multiply blending. The multiply blend guarantees shadows will darken whatever they are drawn over (unlike alpha blend which, with very light shadows, could potentially actually lighten the colors they are drawn over). It will also make the pure white portions of the layer do nothing, which is what you want.
The above steps mean that after each object draws a shadow, it erases any shadows that would be underneath it in the final scene when it draws itself in white to the shadow layer. Therefore it won't cast a shadow on itself, and objects won't cast shadows over other objects that are technically in front of them.
Objects will still cast shadows onto other objects that are behind them as you wanted, since any parts of the shadow that haven't been erased by an overlapping object will still apply (or if they are erased, will be potentially re-drawn by a later object). And, since you are drawing the shadows as a single non-translucent color to the shadow layer, multiple shadows overlapping won't affect each other either, which was of course the main point.
You could modify this technique depending on what you have available. For example, instead of white you could use a fully transparent shadow layer initially and an "erase" blend mode [(src * 0) + (dst * (1 - srcAlpha))] to draw the objects that erase shadows underneath them. You could then use alpha instead of multiply blend if you prefer for drawing the shadow layer to the screen.

Even distribution of colours

It's a pretty basic question however I can't understand it very well I'm afraid.
What I'm trying to do is spawn squares a certain colour out of 3 colours. each colour has it's own number value (-1, 0, 1) what I will then do is add that to a 2D array making a grid of squares.
For blue, it's a 1/4 chance. For red it's a 1/4 chance. For white it's a 1/2 chance.
I understand how to use Java's Random class, however I'm not quite sure how to implement what I'm looking for.
Could someone point me in the right direction?
Create a (1D) array the size of the number of squares, put the proportionate number of each colour into the array, random sort it (Collections.shuffle), and then pop them all off and into your 2D array.
Could someone point me in the right direction?
Create a square 2D array of int's: int[][] matrix = new int[SIZE][SIZE]
Fill it using random numbers from 0 to 3
CORRESPONDENCES (for example)
0-1 yellow
2 blue
3 red
Iterate over the 2D array and in each iteration:
draw a rectangle
increase y value (position) in each inner iteration and x in outer
assign color depending the value of the array.
HOW? Executing something like this method each iteration
//this will draw a square of size 50 at position x,y colored
public void paint(Graphics g, int color){
switch (color) {
case 2:
g.setColor(Color.blue);
break;
case 3:
g.setColor(Color.red);
break;
default:
g.setColor(Color.yellow);
break;
}
g.drawRect(x,y,50,50);
}
That's it, I think you have enough to achieve your goal.

how to calculate image gradient

My instructor gave us the pseudocode:
grad = abs(im(x+1,y)-im(x-1,y)) + abs(im(x,y+1)-im(x,y-1))
to calculate the gradient of an image for an edge detector we are making. I thought that the way this pseudocode would look like is:
int grad = Math.abs(img.getRGB(i+1,j)-img.getRGB(i-1,j)) +
Math.abs(img.getRGB(i,j+1)-img.getRGB(i,j-1));
he said this code would only get the R value of a color. I'm having trouble understanding this. Could someone help me understand how to use this formula to get an entire color gradient? (this formula would go in a nested for loop and apply to every pixel)
Your instructor means that you need to get the Red for each pixel. You can either fiddle with the bits that are returned from getRGB(x, y) to get just the red, or you can put the RGB value into a Color and extract it that way.
public int getRed(BufferedImage image, int x, int y)
{
// Color color = new Color(image.getRGB(x, y), true); if you care about alpha
Color color = new Color(image.getRGB(x, y));
return color.getRed();
}
This will give you a value between [0, 255]. If you want a value between [0, 1], then you need to divide by 255.0.
Bit shifting would be a faster solution, but this is the easier solution and it is likely fast enough. For reference, red would be bits [16, 23].

setting colours for various shapes with java

I have made a bunch of triangles that are inside one another, I'm trying to set the color so that each triangle is a random color..How can I do this? I tried
g2.setColor(new Color(COLOUR,COLOUR,COLOUR));
and
COLOUR=(int)(Math.random()*256)
then I filled the triangle but then all the triangles end up being the same color....
for ( int i=0 ; i<triangle.size() ; i++) {
Triangle tri
tri=triangle.get(i);
g2.setColor(new Color(COLOR,COLOR,COLOR));
tri.draw(g2);
}
The triangle does create what i want it too, nested triangles, just cant get it colored correctly.
You will need to randomize the color before you draw each triangle. If you want colors other than gray, you'll also need to initialize each component of the color (red, green, and blue) separately.
int redColor,greenColor,blueColor;
for ( int i=0 ; i<triangle.size() ; i++) {
Triangle tri;
tri=triangle.get(i);
redColor=(int)(Math.random()*255);
greenColor=(int)(Math.random()*255);
blueColor=(int)(Math.random()*255);
g2.setColor(new Color(redColor,greenColor,blueColor));
tri.draw(g2);
}
Hopefully this helps illustrate what the problem is.
you need to set new color each time you want to draw a triangle as follows:
g2d.setColor(aColor);
g2d.drawPolygon(); // triangle
g2d.setColor(bColor);
g2d.drawPolygon(); // triangle

What is the meaning of four parameters of cvScalar constructor in javacv?

Please can some one explain the meaning of the four parameters of the cvScalar(double d, double d1, double d2, double d3) method in javacv?
How can I represent black color in cvScalar ?
The cvScalar is simply a convenient container for 1, 2, 3 or 4 floating point values.
The meaning of the data in such tuples is left to the user of the cvScalar.
For example they can be used to hold, say, Points in the plane (2-tuple), Rectangles (4-tuple), RGB colors (3-tuple), Points in a 3-D world (3-tuple) etc. The cvScalar is systematically implemented as a 4-tuple, with the unused values set to 0.
To answer the question about the RGB color black:
cvScalar cBlack = new cvScalar(0, 0, 0, 0);
// BEWARE: the params for the cvScalar constructor are not in RGB order
// it is: new cvScalar(blue, green, red, unused)
// note how the 4th scalar is unused.
Alternatively you can use the CV_RGB() convenience method as in:
CvScalar cBlack = CV_RGB(0, 0, 0);
// here the CV_RGB() arguments are in Red, Green, Blue order.
Edit: because the example above was for the color black, whereby all color components have the same value, it failed to make evident that the order of the RGB components as stored within the CvScalar is reverse from the conventional order Red, Green, Blue.
The CV_RGB() convenience method's parameters are in the conventional RGB order, but the storage in the cvScalar is in Blue, Green, Red order.
In other words, the definition of CV_RGB is as follow:
public static CvScalar CV_RGB(double r, double g, double b) {
return cvScalar(b, g, r, 0);
}
Or said otherwise yet, cvScalar(0, 1, 130, 0) is equivalent to CV_RGB(130, 1, 0), i.e. the color red, with a minute touch of green.
In addition to CV_RGB(), when using cvScalars for the purpose of color values, it may be convenient to use cvScalar.Red(), cvScalar.Blue(), cvScalar.Green() methods to extract the individual components without having to worry where these are stored. The class also include a few static instances for each of the common colors: cvScalar.GRAY, cvScalar.YELLOW, cvScalar.BLUE etc.
cvScalar is a generic array of 4 doubles. the data type is often used to represent pixel values, e.g.:
CvScalar blue = CV_RGB(64, 64, 255);
the remaining doubles are set to 0 in the constructors that take fewer than 4 values.
cvGet2D is another function that returns a pixel value in the form of a CvScalar
The easiest way to read individual pixels is with the cvGet2D() function
CvScalar cvGet2D(const CvArr*, int row, int col);
This function takes three parameters: a pointer to a data container (CVArr*) and array indices for row and column location. The data container can be an IplImage structure. The topmost row of pixels is row=0, and the bottommost is row=height-1.
The cvGet2D() function returns a C structure, CvScalar, defined as
typedef struct CvScalar
{
double val[4];
}
CvScalar;
The pixel values for each channel are in val[i]. For grayscale images, val[0] contains pixel >brightness. The other three values are set to 0. For a three-channel, BGR image, blue=val[0], >green=val[1], and red=val[2].
http://www.cognotics.com/opencv/servo_2007_series/part_1/page_4.html

Categories