2D visibility with java grapics (Fog of War) - java

I am making a 2d game and i want to make 2d visibility. So my idea is to make the map and then mask it with another black (for example) polygon so that the player can see through the black polygon the map. So my idea is to draw some kind of a hole(polygon) trough the black polygon in order to see the map which is below the black polygon. I have already made the visibility but i have no idea how to make the mask.
This is what the program looks so far http://prntscr.com/7y36ev
but the problem is that if there are any objects in the dark they would still be rendered and the player could see them. I can shoot a ray and see if they are in line of sight but it would be a bit buggy because the rays will be shot in the center of the objects and if for example only their shoulder is showing up the object will not be rendered. Can somebody help ?
Edit - for anyone who wants to do the same
I made it with Path2D. First I make the outside polygon with Path2D, then make the inside polygon(the hole) and append the hole to the outside polygon. This is sample code:
public void paintComponent(Graphics g){
Graphics2D g2d = (Graphics2D) g;
g2d.setColor(Color.red);
Path2D.Double poly = new Path2D.Double();
Path2D.Double hole = new Path2D.Double();
hole.moveTo(40,40);
hole.lineTo(40,60);
hole.lineTo(60,60);
hole.lineTo(60,40);
hole.lineTo(40,40);
poly.moveTo(80,2);
poly.lineTo(80,80);
poly.lineTo(2,80);
poly.lineTo(2,2);
poly.lineTo(80,2);
poly.append(hole, true);
g2d.fill(poly);
}

Hi so far I understood your problem, you are intend to let each pixel of the map to be visible when the mask has a black pixel on the same position?
If I'm right then:
Get the BufferedImage of the Map and the BufferedImage of the Mask and using two for loops, check if Mask has black-Pixel at Position (X,Y) if so then add pixel of Map to a new BufferedImage to position (X,Y) otherwise add a black Pixel to the resulting BufferedImage at position (X,Y).
Edit:
Little bit Pseudo Code
BufferedImage mapBI = .... // the map as BufferedImage
BufferedImage maskBI = .... // the mask as BufferedImage
BufferedImage resultBI = ... // new BufferedImage with same size as mask
for (i=0; i< maskBI.width; i++){
for(j=0; j< maskBI.height; j++){
if (maskBI.pixelAt(i,j) == blackPixel){
resultBI.setPixel(i,j,mapBI.pixelAt(i,j));
}else{
resultBI.setPixel(i,j,blackPixel);
}
}
}
I hope you understand what I mean.

Related

Will using a matrix transformation affect copying pixel by pixel from pixels[]? If so, How? (in Processing / Java)

I am using Processing and am copying the pixels[] array pixel by pixel in a for loop to a PGraphics object.
I am interested in using pushMatrix() and popMatrix() along with some transformations, but I cannot find any info on how the translate(), rotate(), and scale() functions affect how the pixels[] array is organized.
Also, in the info I could find, it says to push the matrix, then draw, and then pop the matrix back to its original state. I am curious if copying pixels pixel by pixel would count as drawing. I know that image() is affected, but what else? Where can I find a list? What are all the types of drawing and editing of pixels that the matrix transformations affect?
Thanks
If you want to render an image into a PGraphics instance, there's no need to manually access the pixels[] array, pixel by pixel.
Notice that PGraphics provides image() which can take prior transformations (translation/rotation/scale) into account.
Here's a basic example:
PImage testImage;
PGraphics buffer;
void setup(){
size(400,400);
testImage = createImage(100,100,RGB);
//make some noise
for(int i = 0; i < testImage.pixels.length; i++){
testImage.pixels[i] = color(random(255),random(255),random(255));
}
testImage.updatePixels();
//setup PGraphics
buffer = createGraphics(width,height);
buffer.beginDraw();
//apply localised transformations
buffer.pushMatrix();
buffer.translate(width / 2, height / 2);
buffer.rotate(radians(45));
buffer.scale(1.5);
//render transformed image
buffer.image(testImage,0,0);
buffer.popMatrix();
//draw the image with no transformations
buffer.image(testImage,0,0);
buffer.endDraw();
}
void draw(){
image(buffer,0,0);
}

How to move the location of the graphic in JPanel

So I'm creating a game using Javax.swing library for my uni coursework.
I have created a window and I have successfully written code to procedurally generate a game map.
However, I am unable to change the focus of the map. What I mean is that the map is always stuck in one corner of the screen. (IE: Location is set to 0,0, hence the Graphics g (the map) is put in that location going outwards.)
I would like to be able to move the "camera" so that different areas of the map can be viewed by the player.
Bellow I have pasted my method that draws the map onto the screen. Could anyone tell me what I could do to have the camera move at runtime. AKA: to shift the map left or right.
I thought of having a Graphics object that will hold the map, and then I'd only draw a subImage of that Graphics object, but considering how the map will be redrawn every frame (For animation purposes) that just means that I'll have even more graphics to redraw.
The map is 6,400 * 6,400 Pixels
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
try {
for(int x = 0; x < OverworldMap.MAP_X_SIZE; x++){
for(int y = 0; y < OverworldMap.MAP_Y_SIZE; y++){
for(int layer = 0; layer < OverworldMap.MAP_LAYER_SIZE; layer++) {
g.drawImage(OverworldMap.getTileAt(x, y, layer).getSprite(), x * SPRITE_SIZE, y * SPRITE_SIZE, null);
}
}
}
} catch (Exception e) {
LauncherClass.printErrorLog(e);
}
}
The best / easiest way to solve this is to put a JScrollPane around your JPanel, and make the JPanel the size of your image. You don't need to worry about only repainting the right part of your image - Java is pretty smart about only drawing the parts that are on screen. Note that you can show or hide the ScrollBars, but if you hide them you need to add logic to activate scrolling through some other mechanism
You cannot store a Graphics object and use it later. It is only valid for the duration of the paint method to which it is passed.
You can, however, simply offset your painting:
Image sprite = OverworldMap.getTileAt(x, y, layer).getSprite();
g.drawImage(sprite, x * SPRITE_SIZE - playerX, y * SPRITE_SIZE - playerY, this);
(Notice that the last argument to drawImage should be this.)

Drawing a gradient in Libgdx

Ok I have this code
#Override
public void render() {
// do not update game world when paused
if (!paused) {
// Update game world by the time that has passed
// since last render frame
worldController.update(Gdx.graphics.getDeltaTime());
}
// Sets the clear screen color to: Cornflower Blue
Gdx.gl.glClearColor(0x64/255.0f, 0x95/255.0f, 0xed/255.0f,
0xff/255.0f);
// Clears the screen
Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
// Render game world to screen
worldRenderer.render();
}
And it draws a light blue background onto the screen. I am attempting to create a gradient that goes from a dark blue at the top, to a light blue towards the bottom. Is there a simple way to do this? I'm new to Libgdx, and OpenGL so i'm trying to learn from a book but I can't seem to find the answer to this one. I've heard of drawing a big square and having the vertices different colors, but I'm unsure of how to do this.
In libGDX, the ShapeRenderer object contains a drawRect() method that takes arguments for its position and size as well as four colors. Those colors are converted to a 4-corners gradient. If you want a vertical gradient, just make the top corners one color and the bottom corners another color. Something like this:
shapeRenderer.filledRect(x, y, width, height, lightBlue, lightBlue, darkBlue, darkBlue);
From the API for ShapeRenderer:
The 4 color parameters specify the color for the bottom left, bottom right, top right and top left corner of the rectangle, allowing you to create gradients.
It seems ShapeRenderer.filledRect method has been removed in late libGDX versions. Now the way to do this is as follows:
shapeRenderer.set(ShapeRenderer.ShapeType.Filled);
shapeRenderer.rect(
x,
y,
width,
height,
Color.DARK_GRAY,
Color.DARK_GRAY,
Color.LIGHT_GRAY,
Color.LIGHT_GRAY
);
The parameters for rect method work in the same way as those in filledRect used to do, like in Kevin Workman answer.
There are some further details worth bearing in mind before comitting to ShapeRenderer. I for one will be sticking with stretching and tinting Texture.
private Color topCol = new Color(0xd0000000);
private Color btmCol = new Color(0xd0000000);
#Override
public void render(float delta) {
...
batch.end(); //Must end your "regular" batch first.
myRect.setColor(Color.YELLOW); // Must be called, I don't see yellow, but nice to know.
myRect.begin(ShapeRenderer.ShapeType.Filled); //Everyone else was saying call `set`.
//Exception informed me I needed `begin`. Adding `set` after was a NOP.
myRect.rect(
10, 400,
//WORLD_H - 300, // WORLD_H assumed 1920. But ShapeRenderer uses actual pixels.
420,
300,
btmCol, btmCol, topCol, topCol
);
myRect.end();
I was hoping to change transparency dynamically as player health declines. The btmCol and topCol had no effect on transparency, hence I'll stick to Textures. Translating pixel space is no biggie, but this is much more than the proferred single or double line above.

Android game developing - dynamic bounds definition

I am currently developing a game for android using libgdx library .
Lets say we have a lizard, now the user creates paths by sliding fingers on the screen, on which the lizard can walk on.
The question is , how do restrict the lizard to walk on only where the finger touched the screen( on the path - between the bounds).
public class Block {
static final float SIZE = 1f;
Vector2 position = new Vector2();
Rectangle bounds = new Rectangle();
public Block(Vector2 pos) {
this.position = pos;
this.bounds.width = SIZE;
this.bounds.height = SIZE;
}
}
In this example we can see a block, the bounds of the block is a rectangle on which the lizard can walk on.
how do I make some similar bounds only using a circle?
Here is what i got so far:
I have created a doubled layer bitmap that overlap each other. When the user touches the screen , he erases the first bitmap reveling the second bitmap underneath the first one ( only the part where the user touched get removed).
here is the function that erases the first bitmap.
public void onDraw(Canvas canvas){
super.onDraw(canvas);
canvas.drawColor(Color.TRANSPARENT);
canvas.drawBitmap(bgr, 0, 0, null);
c2.drawCircle(X, Y, 40, pTouch);
Paint new_paint = new Paint(/*Paint.ANTI_ALIAS_FLAG*/);
new_paint.setXfermode(new PorterDuffXfermode(Mode.SRC_ATOP));
//new_paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
canvas.drawBitmap(overlay, 0, 0, new_paint);
}
Notice#
the bitmap is removed using a circle shape.
It would be great if i could add to the circle that's removing the bitmap, a property of bound, on which the lizard can walk on.
Any ideas?
u should update the cordinates of bounds as per the lizard position
bounds.x=position.x;
bounds.y=position.y;
So that your bounds follow the lizard
Also instead of using recatangle for bounds try to use
sprite.getBoundingRectangle()
this method gives u the exact rectangular bounds of the image so no need to maintain bounds.
Provided you use AtlasSprite or Sprite for your image.
I shared my game Bomberman early. You can find code you needed in GameScreen class
p.s. also you can find different interesting samples of LibGDX usage here

Drawing a dot grid

I'm new to graphics programming. I'm trying to create a program that allows you to draw directed graphs. For a start I have managed to draw a set of rectangles (representing the nodes) and have made pan and zoom capabilities by overriding the paint method in Java.
This all seems to work reasonably well while there aren't too many nodes. My problem is when it comes to trying to draw a dot grid. I used a simple bit of test code at first that overlayed a dot grid using two nested for loops:
int iPanX = (int) panX;
int iPanY = (int) panY;
int a = this.figure.getWidth() - iPanX;
int b = this.figure.getHeight() - (int) iPanY;
for (int i = -iPanX; i < a; i += 10) {
for (int j = -iPanY; j < b; j += 10) {
g.drawLine(i, j, i, j);
}
}
This allows me to pan the grid but not zoom. However, the performance when panning is terrible! I've done a lot of searching but I feel that I must be missing something obvious because I can't find anything on the subject.
Any help or pointers would be greatly appreciated.
--Stephen
Use a BufferedImage for the dot grid. Initialize it once and later only paint the image instead of drawing the grid over and over.
private init(){
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
Graphics g = image.getGraphics();
// then draw your grid into g
}
public void paint(Graphics g) {
g.drawImage(image, 0, 0, null);
// then draw the graphs
}
And zooming is easily achieved using this:
g.drawImage(image, 0, 0, null); // so you paint the grid at a 1:1 resolution
Graphics2D g2 = (Graphics2D) g;
g2.scale(zoom, zoom);
// then draw the rest into g2 instead of g
Drawing into the zoomed Graphics will lead to proportionally larger line width, etc.
I think re-drawing all your dots every time the mouse moves is going to give you performance problems. Perhaps you should look into taking a snapshot of the view as a bitmap and panning that around, redrawing the view 'properly' when the user releases the mouse button?

Categories

Resources