Is there a way to fall an entire canvas, except for a shape. For example, this thread, but in Java's Processing PApplet.
Thank you in advanced.
By the answer in HTML 5 linked, I assume you need something like this:
PGraphics mask, filler;
int x;
void setup(){
size(400,400);
// initial bg color, the white circle...
background(255);
//init both PGraphics
mask = createGraphics(width, height);
filler = createGraphics(width, height);
// draw a circle as a mask
mask.beginDraw();
mask.background(255);
mask.noStroke();
mask.fill(0);
mask.ellipse(width/2, height/2, 200, 200);
mask.endDraw();
}
void draw(){
// a changing bg
x = (x+1)%255;
background(x);
//dinamiaclly draw random rects
filler.beginDraw();
filler.noStroke();
filler.fill(random(255), random(255), random(255));
filler.rect(random(width), random(height), random(5,40), random(5,40));
filler.endDraw();
// get an imge out ofthis...
PImage temp = filler.get();
//mask image
temp.mask(mask);
//dispay it
image(temp, 0, 0);
}
void mousePressed(){
mask.beginDraw();
mask.background(0);
mask.noStroke();
mask.fill(255);
mask.ellipse(width/2, height/2, 200, 200);
mask.endDraw();
}
void mouseReleased(){
mask.beginDraw();
mask.background(255);
mask.noStroke();
mask.fill(0);
mask.ellipse(width/2, height/2, 200, 200);
mask.endDraw();
}
second example
PGraphics mask, front, back;
int x;
void setup(){
size(400,400);
background(0);
//init both PGraphics
mask = createGraphics(width, height);
front = createGraphics(width, height);
back = createGraphics(width, height);
}
void draw(){
float x = random(width);
float y = random(height);
float sx = random(5, 40);
// draw a circle as a mask
mask.beginDraw();
mask.background(255);
mask.noStroke();
mask.fill(100);
mask.ellipse(mouseX, mouseY, 200, 200);
mask.endDraw();
//dinamiaclly draw random colored rects to PG
front.beginDraw();
front.noStroke();
front.fill(random(255), random(255), random(255));
front.rect(x, y, sx, sx);
front.endDraw();
//dinamiaclly draw random gray rects to display
back.beginDraw();
back.stroke(200);
back.fill(0, 100);
back.rect(x, y, sx, sx);
back.endDraw();
// get an imge out ofthis...
PImage temp = front.get();
//mask image
temp.mask(mask);
//dispay it
image(back,0,0);
image(temp, 0, 0);
}
example using Unfold maps
import de.fhpotsdam.unfolding.*;
import de.fhpotsdam.unfolding.geo.*;
import de.fhpotsdam.unfolding.utils.*;
PGraphics mask, red;
color transparent = color(0);
color opaque = color(255);
UnfoldingMap map;
void setup() {
size(800, 600, P2D);
mask = createGraphics(width, height);
red = createGraphics(width, height);
map = new UnfoldingMap(this);
map.zoomAndPanTo(new Location(52.5f, 13.4f), 10);
MapUtils.createDefaultEventDispatcher(this, map);
}
void draw() {
map.draw();
PImage temp = get();
//red
red.beginDraw();
red.tint(200,20,20);
red.image(temp, 0, 0);
red.endDraw();
//mask
mask.beginDraw();
mask.noStroke();
mask.background(opaque);
mask.fill(transparent);
mask.ellipseMode(CENTER);
mask.ellipse(mouseX, mouseY, 200,200);
mask.endDraw();
// without this i'm not getting to call mask in red...
// don't really know why, this is a workaround
PImage redCasted = red.get();
redCasted.mask(mask);
image(redCasted, 0, 0);
}
Your question doesn't specify if you want anything more than what that link shows, so perhaps this answer isn't what you want (but it is what you asked). First, fill the entire screen with whatever color you want, then draw your shape on top of that. Example:
background(0);
fill(255);
ellipse(50,50,50,50);
Related
Hi I've had a problem where I'm unable to put the ellipse onto the map. Instead what happens is that the ellipse loads for a second and then the map continues to load after this. I've added the code below to see if anyone can help?
PImage map;
float zoom = 1;
float posX = 0;
float posY = 0;
void setup() {
size (800, 800, P3D);
loadData();
map = loadImage("uk-admin.jpg");
}
void draw () {
background (0);
translate(posX,posY);
scale(zoom);
image(map, 0,0, width, height);
camera(width/2, height/2, (height/2) / tan(PI*30.0 / 180.0),width/2.0, height/2.0 , 0, 0, 1, 0);
}
Table table;
void loadData() {
table = loadTable("data.csv", "header");
for (int i = 0; i < table.getRowCount(); i++) {
TableRow row = table.getRow(i);
String city = row.getString("City");
int year1991 = row.getInt("1991");
int year2001 = row.getInt("2001");
int year2011 = row.getInt("2011");
float lat = row.getFloat("latitude");
float lon = row.getFloat("longitude");
lat = map(lat, 90.0, -90.0, 0, height);
lon = map(lon, -180.0, 180.0, 0, width);
fill(255);
stroke(10);
ellipse(lon, lat, 30, 30);
}}
You need to call loadData() in the draw() loop. What's happening now is that you're drawing the ellipse for the first frame, then you're drawing the image on top of it every frame after that.
In Processing, the setup() block is run once, then the current state of the canvas is displayed, then the draw() block is run, then the canvas displayed, then draw(), then display, and so on. So when you draw an ellipse (or a bunch of ellipses) in setup(), then draw something over that ellipse in draw(), it only shows the ellipse for the first frame.
When I run this program the green triangles appear all over the place when I click instead I want it to reposition itself to a random place and remove the original green triangle
float x;
void setup()
{
size (800, 600);
background(29, 154, 178);
x=random(width);
frameRate(30);
}
void draw()
{
noStroke();
fill(91, 180, 118 );
triangle(x, 20, 0, height, width, height);
fill(82, 45, 80);
triangle(width/2-200, 120, 0, height, width, height);
fill(82, 45, 60);
triangle(width/2+150, 220, 0, height, width, height);
fill(82, 45, 28);
triangle(width/2-100, 320, 0, height, width, height);
fill(243, 245, 158);
rect(0, 525, 800, 100);
if(mousePressed == true)
{
x=random(width);
}
}
Then add noLoop() in your setup so you're not drawing the same thing 60 times a second, and use mouse click handling instead, with a redraw call so you only draw when there is something new to draw:
float x, y, triangleSideLength;
void setup() {
size(300,300);
noLoop();
triangleSideLength = 30; // or whatever value it needs to be of course
}
void draw() {
x = random(0, width - triangleSideLength);
y = random(0, height - triangleSideLength);
drawTriangleAt(x, y);
}
void drawTriangleAt(float x, float y) {
//...triangle drawing code here...
}
void mouseClicked() {
redraw();
}
Also note that you usually want to constrain your x/y coordinates so that a triangle will always "fit on the screen" instead of getting an x/y coordinate that happens to have x=width and now your triangle is basically 100% out of view.
I am trying to make a program where when you click a check box saying that you want an object to be drawn with a dashed line you can, but when I create a stroke and try to use it my graphics does not acknowledge it. The code is set to double buffer so the image doesn't disappear when you are creating it. I am not sure how to make the objects draw in with the dashed line and would appreciate any help!
Graphics bgg = bg.getGraphics();
if(!jCheckBox1.isSelected()){
bgg.drawImage(fg, jPanel1.getX(), jPanel1.getY()-50, null);
}
else{
Graphics2D g2d = (Graphics2D) bgg;
float[] fa = {10, 10, 10};
BasicStroke bs = new BasicStroke(5, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL, 10, fa, 10);
g2d.setStroke(bs);
g2d.drawImage(fg, jPanel1.getX(), jPanel1.getY()-50, null);
}
In order to draw a rectangle onto your image you will need to use the Graphics.drawRect() method something like this (just off the top of my head with what you've already got):
Graphics bgg = bg.getGraphics();
if(!jCheckBox1.isSelected()){
bgg.drawImage(fg, jPanel1.getX(), jPanel1.getY()-50, null);
}
else{
Graphics2D g2d = (Graphics2D) bgg;
//Draw image into panel...
g2d.drawImage(fg, jPanel1.getX(), jPanel1.getY()-50, null);
//Draw dashed rectagle in center of panel...
int pW = jPanel1.getWidth(); // Get panel Width
int pH = jPanel1.getHeight(); // Get panel Height
float[] fa = {10, 10, 10}; // The dash pattern
// Set Brush thickness (5)
BasicStroke bs = new BasicStroke(5, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL, 10, fa, 10);
g2d.setStroke(bs);
Dimension rectangle = new Dimension(200, 50); // Our desired rectangle dimensions
// Center locations for rectangle...
int x1 = (pW / 2) - (rectangle.width / 2);
int y1 = (pH / 2) - (rectangle.height / 2);
int x2 = rectangle.width;
int y2 = rectangle.height;
g2d.setColor(Color.RED); // Set the dashed shape line color
g2d.drawRect(x1, y1, x2, y2); // Draw the dashed rectangle
// free resourses
bgg.dispose();
g2d.dispose();
jPanel1.revalidate(); // update panel graphics
}
A brush stroke of 5 makes for a pretty heavy dash :)
I'm currently trying to make a game, and I'm still novice with using cameras, and I'm thinking that two OrthographicCameras may be necessary, but I'm not sure if that's the most efficient way, or even how to do so.
Basically, I want this to be the layout for it:
The Main Area is where the main stuff is, which is a Server Interface. The Game Level is where the actual game part is in. I am currently using a ScissorStack to cut the region, but with this demo, results make me question how to do this:
public class TestScissorStackAndCamera extends ApplicationAdapter {
private SpriteBatch batch;
private OrthographicCamera camera;
private Sprite sprite;
private int width, height;
#Override
public void create() {
Gdx.gl.glClearColor(0, 0, 0, 0);
width = Gdx.graphics.getWidth();
height = Gdx.graphics.getHeight();
batch = new SpriteBatch();
camera = new OrthographicCamera(width, height);
camera.position.set(width / 2, height / 2, 0);
camera.update();
createSprite();
}
private void createSprite() {
Pixmap map = new Pixmap(width, height, Format.RGBA8888);
map.setColor(Color.RED);
map.fillRectangle(0, 0, width, height);
map.setColor(Color.BLUE);
map.drawLine(width / 2, 0, width / 2, height);
map.drawLine(0, height / 2, width, height / 2);
Texture texture = new Texture(map);
sprite = new Sprite(texture);
}
#Override
public void render() {
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
batch.setProjectionMatrix(camera.combined); // The Question!
batch.begin();
{
Rectangle scissors = new Rectangle();
Rectangle area = new Rectangle(10, 10, width - 20, height - 20);
ScissorStack.calculateScissors(camera, batch.getTransformMatrix(), area, scissors);
ScissorStack.pushScissors(scissors);
batch.draw(sprite, 0, 0);
batch.flush();
ScissorStack.popScissors();
}
batch.end();
}
public static void main(String[] args) {
LwjglApplicationConfiguration config = new LwjglApplicationConfiguration();
config.title = "ScissorStack & Camera Test";
config.resizable = false;
new LwjglApplication(new TestScissorStackAndCamera(), config);
}
}
Questioning batch.setProjectionMatrix(camera.combined)
I marked a line in the code with a comment, The Question!, which is what is affecting the results. If I don't have it, using the camera.translate(...) method, the image is drawn at (0, 0) but what it does is it moves what part is viewed. If I do have that line, when I use the camera.translate(...) method, the image is drawn respectively to the position of the camera.
In respect to the game that I'm currently developing, it behaves awkwardly without the projectionMatrix not being set, but when I do set it, it messes up the positioning of the rest of the game. I even added some testing features, and it's not rendering inside of the correct ScissorStack
How could I go about setting up two cameras, or what could I do to set up what I'm trying to correctly and efficiently?
With my actual game (not the mock-up) this is what it is doing. It should be rendering inside of the red lines, but it's not:
If you'd like to see my current code for my GameLevel that is handling the ScissorStack and OrthographicCamera:
public GameLevel(int x, int y, int displayWidth, int displayHeight) {
this.x = x; // x = 10
this.y = y; // y = 10
this.displayWidth = displayWidth; // displayWidth = Gdx.graphics.getWidth() - x - 10
this.displayHeight = displayHeight; // displayHeight = Gdx.graphics.getHeight() - y - 120
camera = new OrthographicCamera(Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
camera.position.set(displayWidth / 2, displayHeight / 2, 0);
// FBLAGame.batch.setProjectionMatrix(camera.combined);
camera.update();
init();
}
...
#Override
public void render() {
Rectangle area = new Rectangle(x, y, displayWidth, displayHeight);
Rectangle scissor = new Rectangle();
Matrix4 matrix = FBLAGame.batch.getTransformMatrix();
ScissorStack.calculateScissors(camera, matrix, area, scissor);
ScissorStack.pushScissors(scissor);
renderLevel();
FBLAGame.batch.flush();
ScissorStack.popScissors();
Pixmap map = new Pixmap(Gdx.graphics.getWidth(), Gdx.graphics.getHeight(), Format.RGBA8888);
map.setColor(Color.RED);
map.drawRectangle((int) area.x, (int) area.y, (int) area.width, (int) area.height);
Texture t = new Texture(map);
map.dispose();
FBLAGame.batch.draw(t, 0, 0);
}
So I have a black image that acts as darkness (In my game). I want to show a small portion around the character only. Like so
The red square is the player.
The green bit is the ground in the game (grass).
The black is the shadow/darkness.
What I want to do is cut a Ellipse/hole out of the blank, black image. I want this Ellipse to be centered around the players (The red square) x and y position.
Currently I am using this to get the effect:
for(int x = 0; x < width; x++) {
for(int y = 0; y < height; y++) {
//draw mask
g.setColor(Color.black);
if(!nearPlayer(x, y)) {
g.drawLine(x, y, x, y);
}
}
}
But, this processes extremely slow and laggs the players movement drastically.
Is this possible?
..the Player is the red square. Basically what i want to do is cut a circle out of the blank, black image around the coordinates of the player relative to said black image.
What DYM by 'black image' - exactly? To me that just looks like the BG is painted black, which would make more sense for any solid color. In that case, just create the red thing using an Area, fill it, then for the border set a stroke & the color to black, and draw it. This example shows how.
The relevant part of that short code is..
public void paintDaisyPart(Graphics2D g, Area daisyArea) {
g.setClip(daisyArea);
g.setColor(Color.YELLOW);
g.fillRect(0, 0, 200, 200);
g.setColor(Color.YELLOW.darker());
g.setClip(null);
g.setStroke(new BasicStroke(3));
g.draw(daisyArea);
}
I must be bored. This is an animated SSCCE version of the code that drew the image above. It is typically showing >130 FPS. And that is on a clunky machine for which I told the guy my spec. was 'cheap' & reminded him twice that I don't play (heavy rendering) games.
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.*;
import java.awt.image.BufferedImage;
import javax.swing.*;
public class DaisyDisplay {
DaisyDisplay() {
JPanel gui = new JPanel(new BorderLayout(2,2));
final BufferedImage daisy = new BufferedImage(
200,200,BufferedImage.TYPE_INT_RGB);
final JLabel daisyLabel = new JLabel(new ImageIcon(daisy));
gui.add(daisyLabel,BorderLayout.CENTER);
final Daisy daisyPainter = new Daisy();
daisyPainter.setSize(200);
final JLabel fps = new JLabel("FPS: ");
gui.add(fps,BorderLayout.SOUTH);
ActionListener animator = new ActionListener() {
int counter = 0;
long timeLast = 0;
long timeNow = 0;
public void actionPerformed(ActionEvent ae) {
Graphics2D g = daisy.createGraphics();
g.setColor(Color.GREEN.darker());
g.fillRect(0, 0, 200, 200);
daisyPainter.paint(g);
g.dispose();
daisyLabel.repaint();
counter++;
timeNow = System.currentTimeMillis();
if (timeLast<timeNow-1000) {
fps.setText("FPS: " + counter);
counter = 0;
timeLast = timeNow;
}
}
};
Timer timer = new Timer(1,animator);
timer.start();
JOptionPane.showMessageDialog(null, gui);
timer.stop();
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new DaisyDisplay();
}
});
}
}
class Daisy {
double size = 200;
Point location;
double offset = 0.0;
public void paint(Graphics2D g) {
Area daisyArea = getDaisyShape();
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
offset += .02d;
AffineTransform plain = g.getTransform();
g.setTransform(AffineTransform.getRotateInstance(
offset + (Math.PI*1/8),
100,100));
paintDaisyPart(g,daisyArea);
g.setTransform(AffineTransform.getRotateInstance(
offset + (Math.PI*3/8),
100,100));
paintDaisyPart(g,daisyArea);
g.setTransform(AffineTransform.getRotateInstance(
offset,
100,100));
paintDaisyPart(g,daisyArea);
g.setTransform(AffineTransform.getRotateInstance(
offset + (Math.PI*2/8),
100,100));
paintDaisyPart(g,daisyArea);
g.setTransform(plain);
}
public void setLocation(Point location) {
this.location = location;
}
public void paintDaisyPart(Graphics2D g, Area daisyArea) {
g.setClip(daisyArea);
g.setColor(Color.YELLOW);
g.fillRect(0, 0, 200, 200);
g.setColor(Color.YELLOW.darker());
g.setClip(null);
g.setStroke(new BasicStroke(3));
g.draw(daisyArea);
}
public void setSize(double size) {
this.size = size;
}
public Area getDaisyShape() {
int diameter = (int)size*6/20;
Ellipse2D.Double core = new Ellipse2D.Double(
(size-diameter)/2,(size-diameter)/2,diameter,diameter);
int pad = 10;
int petalWidth = 50;
int petalLength = 75;
Area area = new Area(core);
// left petal
area.add(new Area(new Ellipse2D.Double(
pad,(size-petalWidth)/2,petalLength,petalWidth)));
// right petal
area.add(new Area(new Ellipse2D.Double(
(size-petalLength-pad),(size-petalWidth)/2,petalLength,petalWidth)));
// top petal
area.add(new Area(new Ellipse2D.Double(
(size-petalWidth)/2,pad,petalWidth,petalLength)));
// bottom petal
area.add(new Area(new Ellipse2D.Double(
(size-petalWidth)/2,(size-petalLength-pad),petalWidth,petalLength)));
return area;
}
}