I'm trying to draw 2048 boxes onto a screen with a width and a height. (I am making this in Java)
I have the following variables:
width = 1024
height = 768
population = 2048
Based on these variables, how can I draw a grid with x amount of columns and y amount of rows allowing the whole layout to perfectly fit the desired width and height?
For example:
I have a width and height of 4 x 4 and a total population of 4, I therefore would have 2 columns and 2 rows.
Example 2:
I want to reproduce the exact same thing in the screenshot above, but I do not know how many rows and columns I need to loop through as well as the size of each square.
All I know is the total width/height of the window, along with the total number of boxes I want to draw.
The best thing you can do to answer questions like this for yourself is to get out a piece of paper and a pencil, and draw out a bunch of examples. Label the width and height of the window, as well as the position and width and height of each individual box. Keep drawing examples until you notice a pattern.
Stack Overflow isn't really designed for general "how do I do this" type questions. It's for specific "I tried X, expected Y, but got Z instead" type questions. You need to break your problem down into smaller pieces and take those pieces on one at a time. That being said, I can try to help in a general sense.
First, you need to figure out how many rows and columns your grid should have. There isn't just a single correct way to go from a population to a row and column count. In fact, it might not even be possible- how would you split up a population of 3? There are also multiple solutions: if your population count is 20, then you could have a grid that's 1x20, 2x10, 4x5, 5x4, 10x2, or 20x1. I recommend you treat this as a separate problem and post a separate question about that.
But once you have the row and column count, you can use some basic math to figure out the position and size of each box. Again, drawing out some examples would help, but the basics would look like this:
float cellWidth = width/columns;
float cellHeight = height/rows;
for (int row = 0; row < rows; row++) {
for (int column = 0; column < columns; column++) {
float cellX = cellWidth*column;
float cellY = cellHeight*row;
rect(cellX, cellY, cellWidth, cellHeight);
}
}
Note that I got this code from this tutorial, but you'll find examples all over the internet if you do some googling. If you still can't get it working, please post a MCVE showing exactly what you tried, and we'll go from there. Good luck.
If the boxes need to be rectangular, there are multiple possible solutions. eg. for area 12, box can be of 12x1, 1x12, 4x3, 3x4, 6x2, 2x6, etc.. let alone the floating values.
If square boxes are OK:
area = available_width * available_height
area_per_box = area / no_of_boxes
length = sqrt(area_per_box)
fill grid with this obtained length as width and height of small boxes.
Another approach would be to fill the grid as you like and scale the grid to your desired dimension.
Related
I am trying to program a visualisation for the Mandelbrot set in java, and there are a couple of things that I am struggling with to program. I realize that questions around this topic have been asked a lot and there is a lot of documentation online but a lot of things seem very complicated and I am relatively new to programming.
The first issue
The first issue I have is to do with zooming in on the fractal. My goal is to make an "infinite" zoom on the fractal (of course not infinite, as far as a regular computer allows it regarding calculation time and precision). The approach I am currently going for is the following on a timer:
Draw the set using some number of iterations on the range (-2, 2) on the real axis and (2, 2) on the imaginary axis.
Change those ranges to zoom in.
Redraw that section of the set with the number of iterations.
It's the second step that I struggle with. This is my current code:
for (int Py = beginY; Py < endY; Py++) {
for (int Px = beginX; Px < endX; Px++) {
double x0 = map(Px, 0, height,-2, 2);
double y0 = map(Py, 0, width, -2, 2);
Px and Py are the coordinates of the pixels in the image. The image is 1000x1000. The map funtion takes a number, in this case Px or Py, with a range of (0, 1000) and devides it evenly over the range (-2, 2), so it returns the corresponding value in that range.
I think that in order to zoom in, I'll have to change the -2 and 2 values by some way in the timer, but whatever I try, it doesn't seem to work. The zoom always ends up slowing down after a while or it will end up zooming in on a part of the set that is in the set, so not the borders. I tried multiplying them by some scale factor every timer tick, but that doesn't really produce the result I was looking for.
Now I have two questions about this issue.
Is this the right approach to visualizing the set and zooming in(draw, change range, redraw)?
If it is, how do I zoom in properly on an area that is interesting and that will keep zooming in properly even after running for a minute?
The second issue
Of course when visualizing something, you need to get some actual visual thing. In this case I want to color the set in a way similar to what you see here: (https://upload.wikimedia.org/wikipedia/commons/f/fc/Mandel_zoom_08_satellite_antenna.jpg).
My guess is that you have use the amount of iterations a pixel went through to before breaking out of the loop to give it some color value. However, I only really know how to do this with a black and white color scheme. I tried making a color array that holds the same amount of different gray colors as the amount of max iterations, starting from black and ending in white. Here is my code:
Color[] colors = new Color[maxIterations + 2];
for (int i = 0; i < colors.length; i++) {
colors[i] = new Color((int)map(i, 0, maxIterations + 2, 0, 255),
(int)map(i, 0, maxIterations + 2, 0, 255),
(int)map(i, 0, maxIterations + 2, 0, 255));
}
I then just filled in the amount of iterations in the array and assigned that color to the pixel. I have two questions about this:
Will this also work as we zoom into the fractal in the previously described manner?
How can I add my own color scheme in this, like in the picture? I've read some things about "linear interpolation" but I don't really understand what it is and in what way it can help me.
It sounds like you've made a good start.
Re the first issue: I believe there are ways to automatically choose an "interesting" portion of the set to zoom in on, but I don't know what they are. And I'm quite sure it involves more than just applying some linear function to your current bounding rectangle, which is what it sounds like you're doing.
So you could try to find out what these methods are (might get mathematically complicated), but if you're new to programming, you'll probably find it easier to let the user choose where to zoom. This is also more fun in the beginning, since you can run your program repeatedly and explore a new part of the set each time.
A simple way to do this is to let the user draw a rectangle over the image, and use your map function to convert the pixel coordinates of the drawn rectangle to the new real and imaginary coordinates of your zoom area.
You could also combine both approaches: once you've found somewhere you find interesting by manually selecting the zoom area, you can set this as your "final destination", and have the code gradually and smoothly zoom into it, to create a nice movie.
It will always get gradually slower though, as you start using ever more precise coordinates, until you reach the limits of precision with double and it becomes a pixellated mess. From there, if you want to zoom further, you'll have to look into arbitrary-precision arithmetic with BigDecimal - and it will continue to get slower and slower.
Re the second issue: starting off by calculating a value of numIterations / maxIterations (i.e. between 0 and 1) for each pixel is the right idea (I think this is basically what you're doing).
From there, there are all sorts of ways to convert this value to a colour, it's time to get creative!
A simple one is to have an array of a few very different colours. E.g. if you had white (0.0), red (0.25), green (0.5), blue (0.75), black (1.0), then if your calculated number was exactly one of the ones listed, you'd use the corresponding colour. If it's somewhere between, you blend the colours, e.g. for 0.3 you'd take:
((0.5-0.3)*red + (0.3-0.25)*green) / (0.5 - 0.25)
= 0.8*red + 0.2*green
Taking a weighted average of two colours is something I'll leave as an exercise ;)
(hint: take separate averages of the r, g, and b values. Playing with the alpha values could maybe also work).
Another one, if you want to get more mathsy, is to take an equation for a spiral and use it to calculate a point on a plane in HSB colour space (you can keep the brightness at some fixed value, say 1). In fact, any curve in 2D or 3D which you know how to write as an equation of one real variable can be used this way to give you smoothly changing colours, if you interpret the coordinates as points in some colour space.
Hope that's enough to keep you going! Let me know if it's not clear.
Basically, I have a 3D hexagonal tile map (think something like a simplified Civ 5 map). It is optimized to use a single large mesh to reduce draw calls and easily allow for some cool Civ 5 features (terrain continuity and uv texture bleeding).
I want to support wraparound maps in my game, and so was brainstorming ideas on how to best do this.
For example, if the main camera is approaching the far east of the map, then I can simply perform the translation to the far west by doing:
if(camera.x >= MAP_WIDTH)
camera.translate(0, 0, y);
However, by doing this, there will be a brief timespan in which the player will see the "end" of the board before the translation. I want to eliminate this.
The first idea I had to solve this problem was to basically just modify the above code as follows:
if((camera.x + camera.viewportWidth >= MAP_WIDTH)
camera.translate(0, 0, y);
However, this has the side effect of a "jump" during the translation that feels unnatural.
My final solution, and the subject of the question:
I have three cameras, my main camera, one to the far east, and one to the far west. I basically want to "combine" the matrices of these cameras to render the map outside of its actual bounds.
Basically, if the camera is a certain distance from the world bounds, I want to draw the scene from the other side of the world in the following location. So, for example, this is the pseudo code of what I want to do:
int MAP_WIDTH = 25;
float viewportSize = 10f;
float mainCamX = 24f;
float mainCamY = 15f;
Matrix4 cbnd = camera.combined;
if(camX >= MAP_WIDTH)
camX = 0;
else if(camX < 0)
camX = MAP_WIDTH - camX;
if(camX + viewportSize >= MAP_WIDTH)
cbnd = combineMatrices(mainCam.combined, westCam.combined);
modelBatch.setProjectionMatrix(cbnd);
modelBatch.begin();
//Draw map model
//Draw unit models.
modelBatch.end();
modelBatch.setProjectionMatrix(mainCam.combined);
But I am unsure of how to appropriately combine matrices, and am new to the concept of matrices in general.
Can somebody give me a hand in combining these matrices?
Sounds too complicated. Here is my idea:
I.e. you can display 10x10 fields on screen
you have map 100x100 fields
just increase your map to 110x110 and in that extra space repeat your first (zero-est rows and columns)
that way you can scroll smoothly and when camera reaches i.e. most right position you have on map just return it to 0 X position. Same goes for vertical movement.
So, idea is to have double most left part of map in width of screen width and most top part of map in size of screen height at rigth/bottom of the map respectively.
I am trying to get equal space between my buttons across the screen for any screen size (width). I am using Libgdx tables inside a stage. I think my logic is on the right track but it is not returning anything close to what I want.. most of the buttons are off the screen. (I have 5 buttons total)
int width = Gdx.graphics.getWidth();
int spacing = width / 5;
System.out.println(width);
System.out.println(spacing);
//BOTTOM TABLE
tableBottom = new Table(skin);
stage.addActor(tableBottom);
tableBottom.setBounds(0,0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
tableBottom.setFillParent(true);
tableBottom.columnDefaults(1).width(spacing);
tableBottom.add(inventoryButton).size(144,160).center();
tableBottom.add(assignButton).size(148,180).center();
tableBottom.add(shopButton).size(130,152).center();
tableBottom.add(collectButton).size(182,198).center();
tableBottom.add(fightButton).size(162,178).center();
As Requested Images:
This is what the code above is doing! and it is not accurate it does different based on every screen size.
This is what I WANT it to look like. On every Sized screen equal spacing and take up the whole bottom.. obviously a bigger screen they will be not as close together but that is fine! thanks been struggling with this.
To get equal spacing in horizontal direction change
tableBottom.add(inventoryButton).size(144,160).center();
tableBottom.add(assignButton).size(148,180).center();
tableBottom.add(shopButton).size(130,152).center();
tableBottom.add(collectButton).size(182,198).center();
tableBottom.add(fightButton).size(162,178).center();
to
tableBottom.add(inventoryButton).size(144,160).expandX();
tableBottom.add(assignButton).size(148,180).expandX();
tableBottom.add(shopButton).size(130,152).expandX();
tableBottom.add(collectButton).size(182,198).expandX();
tableBottom.add(fightButton).size(162,178).expandX();
I am due to start work on a 2D platform game in Java using Java2D, and am trying to devise a way to create a world. I have been reading up about this for the last few hours now, and as far as I can tell, a relatively effective way is to have a text file with a "matrix" of values in it, which is read in by the program in order to create the map (stored in a 2D array).
Now, my plan is to have multiple JComponents that display ImageIcons for the various textures in the world; the JComponent object would depend on the character in the given array index.
Is there anything I may have overlooked?
Will this schematic work with a background image, i.e. when there is a character that represents a blank space, will part of the background be shown?
Apologies if this seems like a lazy question, I can assure you it is not out of laziness. I am merely trying to plan this out before hacking code together.
Unless you have compelling reason to, having a different component for each tile is probably not a good way to go. Look into a Canvas and displaying loaded images at different offsets in it.
Example:
480x640 Canvas
128x16 image file(contains 8 16x16 tile images)
So your file has a bunch of numbers(characters etc.), we'll say 0-7 for the 8 tiles in the image. The file has 30x40 numbers, laid out in a grid the same as the canvas. So
1 2 1 3 4 8 2...
...
And to display the code ends up something like(not tested, based on docs)
Graphics g = //initialize graphics;
Image yourTileImage = //load your image;
for (int xpos = 0; xpos < maxX; xpos++)
for (int ypos = 0; ; ypos < maxY; ypos++)
int number = //get number from map file
g.drawImage(Image yourTileImage,
xpos * 16, ypos * 16, xpos * 16 + 15, ypos * 16 + 15,
number*16, 0, number+15, 15,
ImageObserver observer)
Which basically maps the number to your tile image, then puts that tile image into the right spot in the canvas(x,y) coordinates * size of tile.
There are a number of good 2d graphics engines available for Java. You would be better off using one of those rather than trying to re-invent the wheel. (Quite apart from anything else they will make use of the GPU.
You should easily find one that does what you need.
I have a screen with a RitchTextField added, which has a custom font applied. I want to find the total number of lines that the RitchTextField can hold to avoid vertical scrolling.
I tried to do this by getting the height of the RichTextField then dividing it by the the height of the font, the problem however is using rtfField.getHeight() always returns the current height of field, and using the screens getHeight() returns the screen size not taking other fields into consideration.
For example:
Screen Size using getHeight() = 360.
Font Size using: this.rtfField.getFont().getHeight() = 25
Total Lines ~ 12
However doing a manual count the screen only comfortably displays 8 lines.
Not sure if this is what you're looking for, but I think you want the current height of the field divided by the font height:
int lines = this.rtfField.getHeight() / this.rtfField.getFont().getHeight();