I've written Conway's Game Of Life in Java and I want to display it in a browser. I wanted to learn some Canvas, so what is the preferred way to draw a 2D grid and filling each cell in with a color? Thanks.
This will make a grid. It's useful I think for being able to position or determine the coordinates of an element or something, and several other possible handy use cases as well.
var grid = function() {
for (var i = 0; i < canvasWidth || i < canvasHeight; i += 100) { // 100 represents the width in pixels between each line of the grid
// draw horizontal lines
ctx.moveTo(i, 0);
ctx.lineTo(i, canvasHeight);
// draw vertical lines
ctx.moveTo(0, i);
ctx.lineTo(canvasWidth, i);
}
ctx.save();
ctx.strokeStyle = 'hsla(200, 0%, 20%, 0.8)';
ctx.stroke();
ctx.restore();
};
// Call the function
grid()
Hope this helps, and is what you're trying to do too. :)
edit: If you are looking to fill each grid square with a different color, then this function will not work, or could at least be used in combination with another function which creates and fills the squares in a similar way to the function above but cutting the width and height off based on the dimensions of the canvas width and height.
Related
What is the most painless way to create an N x N grid in a JavaFX application?
The only requirements I'm looking for is that the size of the grid will always take up the same amount of space, so more squares = smaller squares. I can set colors for the squares, and I can hover over each square individually and be able to show some for each square.
I won't know 'N' until the program runs and parses through some data to figure out how many total squares I need which is when I calculate the smallest NxN grid I can use.
From what I can tell my options are:
GridPane - Using the column constraints and row constraints to generate size and possibly add properties for hovering?
TableView - A lot more options for being able to give each cell data to show when hovered over but still difficult to just add rows and columns to start with.
Rectangles - Just generate and draw each rectangle while calculating the x and y coordinates for each square. This will make it easy to do the colors and hovering but I can't see how resizing would work but I'm ok with having a specific size for my application. I'll also have to calculate the best size to make each square to fill up the grids area.
I'm not necessarily looking for someone to code a solution, but if someone has dealt with this and knows a good way I'd like to hear about it.
Don't stray away from the original ideas. Why are you looking for "painless" ways when all the methods you've given are all viable? Here's one using your rectangles. The GridMaker.SCREEN_SIZE refers to the size of the screen you must have.
public static Pane makeGrid(int n){
double width = GridMaker.SCREEN_SIZE/n;
Pane p = new Pane();
Rectangle [][] rec = new Rectangle [n][n];
for(int i=0; i<n; i++){
for(int j=0; j<n; j++){
rec[i][j] = new Rectangle();
rec[i][j].setX(i * width);
rec[i][j].setY(j * width);
rec[i][j].setWidth(width);
rec[i][j].setHeight(width);
rec[i][j].setFill(null);
rec[i][j].setStroke(Color.BLACK);
p.getChildren().add(rec[i][j]);
}
}
return p;
}
Then simply add the mouse listener to the pane if you wish to make it change color.
p.setOnMouseClicked(new EventHandler <MouseEvent> (){
#Override
public void handle(MouseEvent me){
double posX = me.getX();
double posY = me.getY();
int colX = (int)(posX / width);
int colY = (int) (posY / width);
rec[colX][colY].setFill(Color.RED);
}
});
-- Edit
1)
2) For Hover, what kind of hover effects are you looking for? You can add Hover effects onto each rectangles, if you want me to show you how, I can definitely code it for you.
I would like to know if anybody can help me with a better method of drawing a Tile map for my android game.
Currently, I use a for loop to draw the required Bitmaps to the screen but when doing this for the amount of tiles I need to render at once (enough to cover the screen and a bit more), when the map scrolls, you can notice the map become jolty with its movement, because of the for loop having to loop through all the tiles. The tiles are drawn simular to this:
for(int i = 0; i < 170; i++) {
canvas.drawBitmap(bitmap, x + i * bitmap.getWidth(), y, null);
}
The method I am currently using uses a few bitmaps to save memory, and draws them in different locations.
A different method i can think of to draw the map would be to create a larger Bitmap from the tiles and move the position of that larger bitmap to create movement. The problem with this is that is does require lots of memory and gets out of memory errors.
So, i need to try and find out a method of drawing multiple tiles preferably without the use of a for-loop (I believe the for-loop is causing the jolty, un-smooth movement of the map).
For more details just ask, thanks.
The for loop is the correct way to draw it, your problem is probably the amount of data you are trying to draw in one frame and/or the number of pixels you are trying to push through the system.
If you want good performance on Android your best bet will be to use the graphics hardware it provides. There are various game frameworks available that will make that easier for you and give you much better performance than you will get otherwise.
If not then you will need to break up the drawing and still run the same effective logic but spread out so you draw a few tiles per frame.
is it really required to draw ALL tiles at once?
if it is possible for you, maybe you can determine the 'visible view port' and then just draw those tiles, which need to be drawn?!?
int width = getWidth()/Tiles.width; // do it once before any rendering
// thats the amount of tiles per line
int height = getHeight()/Tiles.height; // do it once before any rendering
// thats the amount of tiles per row
Point pos = ...; // you should know the position of your 'figure' within the map
// could as well be the scroll position
//now draw only those tile from the 'viewport':
for (int dy = 0; dy < width; dy++){
for (int dx = 0; dy < height; dy++){
int xOnMap = pos.x + x;
int yOnMap = pos.y + dy;
int index = yOnMap*height+yOnMap; //index in list
canvas.drawBitmap(bitmap,
x * bitmap.getWidth(), y * bitMap.getHeight(), null);
}
}
so you just have to draw some tile and that would always be the same amount...
i must confess i wrote that code onstackoverflow so there is a chance i did a syntax terror ^^
Situation: I have a canvas on an Android game, I have some objects (I will keep it as simple as possible):World(where are storaged all Laser and Block objects), Block and Laser. I can draw all this objects in the canvas.
I would like to 'hide' them behind a black 'background', and then draw a blurry 'transparent' circle, so all objects are hidden behind the black background, except the objects behing the circle.
I have thought about it, but I can't think of an approach to do this.
Images:
This is my actual situation:
This is the expected:
Do something like this:
public void drawBitmapsInCanvas(Canvas c){
c.drawBitmap(block, new Rect(/*coordinates here*/), new Rect(/*More coordinates*/),null);
c.drawBitmap(block2, new Rect(/*coordinates here*/), new Rect(/*More coordinates*/),null);
c.drawBitmap(laser, new Rect(/*coordinates here*/), new Rect(/*More coordinates*/),null);
c.drawColor(Color.BLACK);//this hides everything under your black background.
c.drawBitmap(circle, new Rect(/*coordinates here*/), new Rect(/*More coordinates*/),null);
}
If you want transparency:
Paint paint =new Paint();
paint.setARGB(120,0,0,0); //for the "120" parameter, 0 is completely transparent, 255 is completely opaque.
paint.setAntiAlias(true);
c.drawBitmap(bmp,Rect r,Rect rr, paint);
or if you are trying to change the opacity of individual pixels, the approach is a bit more complicated (I have not tested the code, but you get the gist of it):
public static final Bitmap getNewBitmap(Bitmap bmp, int circleCenterX,
int circleCenterY,int circleRadius){
//CIRCLE COORDINATES ARE THE DISTANCE IN RESPECT OF (0,0) of the bitmap
//, not (0,0) of the canvas itself. The circleRadius is the circle's radius.
Bitmap temp=bmp.copy(Bitmap.Config.ARGB_8888, true);
int[]pixels = new int[temp.getWidth()*temp.getHeight()];
temp.getPixels(pixels,0 ,temp.getWidth(),0,0,temp.getWidth(), temp.getHeight());
int counter=0;
for(int i=0;i<pixels.length;i++){
int alpha=Color.alpha(pixels[i]);
if(alpha!=0&&!((Math.pow(counter/temp.getWidth()-circleCenterY,2.0)+
Math.pow(counter%temp.getWidth()-circleCenterX,2.0))<Math.pow(circleRadius,2.0))){
//if the pixel itself is not completely transparent and the pixel is NOT within range of the circle,
//set the Alpha value of the pixel to 0.
pixels[i]=Color.argb(0,Color.red(pixels[i]),Color.green(pixels[i]),Color.blue(pixels[i]));
}
counter++;
}
temp.setPixels(pixels,0, temp.getWidth(),0,0,temp.getWidth(),temp.getHeight());
return temp;
}
and then draw temp.
I'm not completely sure what you are trying to ask, so you may have to modify as necessary.
If you try the second answer of qwertyuiop5040, you will get a ver low - perfomance when you try to apply it to a large image. Let's say a 1000*800 pixels image. Then you will have a loop:
for (int i = 0 ; i < 1000*800; i++)
You could create an image that's a black rectangle with a transparent hole in it. The hole would be the circle that you can see through, and the image would be rendered over the spot you want to be visible. Then, you can draw four black rectangles around the image to cover the rest of the screen.
I'm having a little problem with figuring something out (Obviously).
I'm creating a 2D Top-down mmorpg, and in this game I wish the player to move around a tiled map similar to the way the game Pokemon worked, if anyone has ever played it.
If you have not, picture this: I need to load various areas, constructing them from tiles which contain an image and a location (x, y) and objects (players, items) but the player can only see a portion of it at a time, namely a 20 by 15 tile-wide area, which can be 100s of tiles tall/wide. I want the "camera" to follow the player, keeping him in the center, unless the player reaches the edge of the loaded area.
I don't need code necessarily, just a design plan. I have no idea how to go about this kind of thing.
I was thinking of possibly splitting up the entire loaded area into 10x10 tile pieces, called "Blocks" and loading them, but I'm still not sure how to load pieces off screen and only show them when the player is in range.
The picture should describe it:
Any ideas?
My solution:
The way I solved this problem was through the wonderful world of JScrollPanes and JPanels.
I added a 3x3 block of JPanels inside of a JScrollPane, added a couple scrolling and "goto" methods for centering/moving the JScrollPane around, and voila, I had my camera.
While the answer I chose was a little more generic to people wanting to do 2d camera stuff, the way I did it actually helped me visualize what I was doing a little better since I actually had a physical "Camera" (JScrollPane) to move around my "World" (3x3 Grid of JPanels)
Just thought I would post this here in case anyone was googling for an answer and this came up. :)
For a 2D game, it's quite easy to figure out which tiles fall within a view rectangle, if the tiles are rectangular. Basically, picture a "viewport" rectangle inside the larger world rectangle. By dividing the view offsets by the tile sizes you can easily determine the starting tile, and then just render the tiles in that fit inside the view.
First off, you're working in three coordinate systems: view, world, and map. The view coordinates are essentially mouse offsets from the upper left corner of the view. World coordinates are pixels distances from the upper left corner of tile 0, 0. I'm assuming your world starts in the upper left corner. And map cooridnates are x, y indices into the map array.
You'll need to convert between these in order to do "fancy" things like scrolling, figuring out which tile is under the mouse, and drawing world objects at the correct coordinates in the view. So, you'll need some functions to convert between these systems:
// I haven't touched Java in years, but JavaScript should be easy enough to convey the point
var TileWidth = 40,
TileHeight = 40;
function View() {
this.viewOrigin = [0, 0]; // scroll offset
this.viewSize = [600, 400];
this.map = null;
this.worldSize = [0, 0];
}
View.prototype.viewToWorld = function(v, w) {
w[0] = v[0] + this.viewOrigin[0];
w[1] = v[1] + this.viewOrigin[1];
};
View.prototype.worldToMap = function(w, m) {
m[0] = Math.floor(w[0] / TileWidth);
m[1] = Math.floor(w[1] / TileHeight);
}
View.prototype.mapToWorld = function(m, w) {
w[0] = m[0] * TileWidth;
w[1] = m[1] * TileHeight;
};
View.prototype.worldToView = function(w, v) {
v[0] = w[0] - this.viewOrigin[0];
v[1] = w[1] - this.viewOrigin[1];
}
Armed with these functions we can now render the visible portion of the map...
View.prototype.draw = function() {
var mapStartPos = [0, 0],
worldStartPos = [0, 0],
viewStartPos = [0, 0];
mx, my, // map coordinates of current tile
vx, vy; // view coordinates of current tile
this.worldToMap(this.viewOrigin, mapStartPos); // which tile is closest to the view origin?
this.mapToWorld(mapStartPos, worldStartPos); // round world position to tile corner...
this.worldToView(worldStartPos, viewStartPos); // ... and then convert to view coordinates. this allows per-pixel scrolling
mx = mapStartPos[0];
my = mapStartPos[y];
for (vy = viewStartPos[1]; vy < this.viewSize[1]; vy += TileHeight) {
for (vx = viewStartPos[0]; vx < this.viewSize[0]; vy += TileWidth) {
var tile = this.map.get(mx++, my);
this.drawTile(tile, vx, vy);
}
mx = mapStartPos[0];
my++;
vy += TileHeight;
}
};
That should work. I didn't have time to put together a working demo webpage, but I hope you get the idea.
By changing viewOrigin you can scroll around. To get the world, and map coordinates under the mouse, use the viewToWorld and worldToMap functions.
If you're planning on an isometric view i.e. Diablo, then things get considerably trickier.
Good luck!
The way I would do such a thing is to keep a variable called cameraPosition or something. Then, in the draw method of all objects, use cameraPosition to offset the locations of everything.
For example: A rock is at [100,50], while the camera is at [75,75]. This means the rock should be drawn at [25,-25] (the result of [100,50] - [75,75]).
You might have to tweak this a bit to make it work (for example maybe you have to compensate for window size). Note that you should also do a bit of culling - if something wants to be drawn at [2460,-830], you probably don't want to bother drawing it.
One approach is along the lines of double buffering ( Java Double Buffering ) and blitting ( http://download.oracle.com/javase/tutorial/extra/fullscreen/doublebuf.html ). There is even a design pattern associated with it ( http://www.javalobby.org/forums/thread.jspa?threadID=16867&tstart=0 ).
Ok, I am implementing a flowchart editor in Java. My goal is to provide a possibility to display grid lines on a drawing surface. I partially made it to work:
public void paintComponent(Graphics g)
{
super.paintComponent(g);
Graphics2D g2 = (Graphics2D)g;
// Scrolling
g2.transform(transformation);
// Step one: draw grid
if(showGrid)
{
// Horizontal grid lines
for(int i = -1; i < getSize().getWidth(); i += 50)
{
g2.drawLine(i, 0, i, (int)getSize().getHeight());
}
// Vertical grid lines
for(int i = -1; i < getSize().getHeight(); i += 50)
{
g2.drawLine(0, i, (int)getSize().getWidth(), i);
}
}
// Step two: draw symbols
// ...
}
The results are like this:
But, if I scroll the diagram down or up, I get this:
As seen, diagram is scrolled, but not the grid. I also tried putting Step one code before g2.transform(transformation) line, but after that, if I scroll, grid lines are not moving.
So, the question is: is there a way to draw grid lines and avoid mentioned behavior? The goal is to scroll grid along with other elements on diagram.
List item
The grid is being scrolled, but the lines do not extend to the new bounds.
The grid is scrolled along with the objects. That's why there's empty space at the bottom of the second diagram. The top of the grid has been scrolled off the top of the panel. The bottom of the grid has been scrolled above the bottom of the panel. The grid lines have moved.
The only problem I see is that the grid lines should always extend to the extents of the visible area. To do this, you need to reverse the transformation for the getWidth and getHeight and then draw the grid lines on all of the multiples of 50 between those values.
Paint the entire diagram and put it into a JScrollPane instead of transforming scroll actions yourself.