Recursive image painter - java

I am trying to make a recursive function that serves as a paint bucket that fills a certain area. This one paints a square where the user clicks:
public void drawSquare(int x, int y, Color paintColor) {
int paintColorRGB = clearAlphaChannel(paintColor.getRGB());
image.setRGB(x - 1, y - 1, paintColorRGB);
image.setRGB(x + 0, y - 1, paintColorRGB);
image.setRGB(x + 1, y - 1, paintColorRGB);
image.setRGB(x - 1, y + 0, paintColorRGB);
image.setRGB(x + 0, y + 0, paintColorRGB);
image.setRGB(x + 1, y + 0, paintColorRGB);
image.setRGB(x - 1, y + 1, paintColorRGB);
image.setRGB(x + 0, y + 1, paintColorRGB);
image.setRGB(x + 1, y + 1, paintColorRGB);
}
The recursive function is called here:
public void transformImage(int x, int y, Color paintColor) {
int paintColorRGB = clearAlphaChannel(paintColor.getRGB());
transformPoint(x, y, getPixelColor(x, y), paintColorRGB);
}
getPixelColor calculates the average colour on a 3x3 pixel square, the treshold is defined by the user in this case, treshold = 4:
private int getPixelColor(int x, int y) {
int pixelColor = clearAlphaChannel(image.getRGB(x, y));
int i= 9;
int cor0 = clearAlphaChannel(image.getRGB(x,y));
int cor1 = clearAlphaChannel(image.getRGB(x+1,y));
int cor2 = clearAlphaChannel(image.getRGB(x,y+1));
int cor3 = clearAlphaChannel(image.getRGB(x-1,y));
int cor4 = clearAlphaChannel(image.getRGB(x,y-1));
int cor5 = clearAlphaChannel(image.getRGB(x+1,y+1));
int cor6 = clearAlphaChannel(image.getRGB(x-1,y-1));
int cor7 = clearAlphaChannel(image.getRGB(x+1,y-1));
int cor8 = clearAlphaChannel(image.getRGB(x-1,y+1));
if(cor0<threshold){
i = i-1;
cor0 = 0;
}
if(cor1<threshold){
i = i-1;
cor1 = 0;
}
if(cor2<threshold){
i = i-1;
cor2 = 0;
}
if(cor3<threshold){
i = i-1;
cor3 = 0;
}
if(cor4<threshold){
i = i-1;
cor4 = 0;
}
if(cor5<threshold){
i = i-1;
cor5 = 0;
}
if(cor6<threshold){
i = i-1;
cor6 = 0;
}
if(cor7<threshold){
i = i-1;
cor7 = 0;
}
if(cor8<threshold){
i = i-1;
cor8 = 0;
}
pixelColor= (cor1+cor2+cor3+cor4+cor5+cor6+cor7+cor8+cor0)/i;
System.out.println(pixelColor);
return pixelColor;
}
This recursive function should paint the area inside the black, but it's giving me a stack overflow:
private void transformPoint(int x, int y, int refColorRGB, int paintColorRGB) {
int pixelRGB = clearAlphaChannel(image.getRGB(x, y));
if(refColorRGB!=pixelRGB){
return; }
// Image width: 0 to imageWidth -1
// Image height: 0 to imageHeight -1
// Threshold defined in GUI: threshold
transformPoint(x+1, y, refColorRGB, paintColorRGB);//1
transformPoint(x, y-1, refColorRGB, paintColorRGB);//2
transformPoint(x, y+1, refColorRGB, paintColorRGB);//3
transformPoint(x-1, y, refColorRGB, paintColorRGB);//4
drawSquare(x, y, new Color(paintColorRGB));
}
Right now only calling the first transformPoint works, but when I try adding the others it doesn't work.
butterfly

Related

Processing. Particle sytem - how to make particles come in one by one

I am trying to make my particle system generate particles one by one, rather than all at the same time. My code currently will generate all 100 particles instantly.
I have not tried much as I am new to coding.
I have a setup where I call and updated my particle class, and a class that has all my parameters of the particle system.
int num = 100;
Particle[] p = new Particle[num];
void setup() {
size(1080, 720);
colorMode(HSB);
for (int i = 0; i < num; i ++) {
p[i] = new Particle(new PVector(random(width), random(height)), 100, 150);
}
stroke(255);
}
void draw() {
background(0);
for (int i = 0; i < num; i ++) {
p[i].update(p, i);
}
}
class Particle {
PVector pos;
PVector vel;
float r, mr;
float spd = 0.1;
float max = 2;
Particle(PVector pos, float r, float mr) {
this.pos = pos;
this.r = r;
this.mr = mr;
vel = new PVector(random(-1, 1), random(-1, 1));
}
void update(Particle[] p, int i) {
float h = map(mouseX, 0, width, 0, 255);
pos.add(vel);
if (pos.x < -10) pos.x = width;
if (pos.x > width + 10) pos.x = 0;
if (pos.y < -10) pos.y = height;
if (pos.y > height + 10) pos.y = 0;
vel.x = constrain(vel.x + random(-spd, spd), -max, max);
vel.y = constrain(vel.y + random(-spd, spd), -max, max);
for (int j = i + 1; j < p.length; j ++) {
float ang = atan2(pos.y - p[j].pos.y, pos.x - p[j].pos.x);
float dist = pos.dist(p[j].pos);
if (dist < r) {
stroke(h, 255, map(dist, 0, r, 255, 0));
strokeWeight(map(dist, 0, r, 3, 0));
line(pos.x, pos.y, p[j].pos.x, p[j].pos.y);
float force = map(dist, 0, r, 4, 0);
vel.x += force * cos(ang);
vel.y += force * sin(ang);
}
}
float ang = atan2(pos.y - mouseY, pos.x - mouseX);
float dist = pos.dist(new PVector(mouseX, mouseY));
if (dist < r) {
stroke(0, 0, map(dist, 0, r, 255, 0));
strokeWeight(map(dist, 0, r, 3, 0));
line(pos.x, pos.y, mouseX, mouseY);
float force = map(dist, 0, r, 30, 0);
vel.x += force * cos(ang);
vel.y += force * sin(ang);
}
noStroke();
fill(h, 255, 255);
ellipse(pos.x, pos.y, 5, 5);
}
}
Create an ArrayList of particles, but don't add any particle in setup():
ArrayList<Particle> paticles = new ArrayList<Particle>();
void setup() {
size(400, 400);
colorMode(HSB);
stroke(255);
}
Consecutively add the particles in draw(). The function millis() is used to get the time since the program was started:
void draw() {
int num = 100;
int interval = 100; // 0.5 seconds
int time = millis(); // milliseconds since starting the program
if (paticles.size() < num && paticles.size()*interval+5000 < time) {
paticles.add(new Particle(new PVector(random(width), random(height)), 100, 150));
}
background(0);
for (int i = 0; i < paticles.size(); i ++) {
Particle p = paticles.get(i);
p.update(paticles, i);
}
}
Note, the class Particle has to be adapted, because it has to operate with the ArrayList of variable length rather than the array with fixed length:
class Particle {
PVector pos;
PVector vel;
float r, mr;
float spd = 0.1;
float max = 2;
Particle(PVector pos, float r, float mr) {
this.pos = pos;
this.r = r;
this.mr = mr;
vel = new PVector(random(-1, 1), random(-1, 1));
}
void update(ArrayList<Particle> paticles, int i) {
float h = map(mouseX, 0, width, 0, 255);
pos.add(vel);
if (pos.x < -10) pos.x = width;
if (pos.x > width + 10) pos.x = 0;
if (pos.y < -10) pos.y = height;
if (pos.y > height + 10) pos.y = 0;
vel.x = constrain(vel.x + random(-spd, spd), -max, max);
vel.y = constrain(vel.y + random(-spd, spd), -max, max);
for (int j = i + 1; j < paticles.size(); j ++) {
Particle pj = paticles.get(j);
float ang = atan2(pos.y - pj.pos.y, pos.x - pj.pos.x);
float dist = pos.dist(pj.pos);
if (dist < r) {
stroke(h, 255, map(dist, 0, r, 255, 0));
strokeWeight(map(dist, 0, r, 3, 0));
line(pos.x, pos.y, pj.pos.x, pj.pos.y);
float force = map(dist, 0, r, 4, 0);
vel.x += force * cos(ang);
vel.y += force * sin(ang);
}
}
float ang = atan2(pos.y - mouseY, pos.x - mouseX);
float dist = pos.dist(new PVector(mouseX, mouseY));
if (dist < r) {
stroke(0, 0, map(dist, 0, r, 255, 0));
strokeWeight(map(dist, 0, r, 3, 0));
line(pos.x, pos.y, mouseX, mouseY);
float force = map(dist, 0, r, 30, 0);
vel.x += force * cos(ang);
vel.y += force * sin(ang);
}
noStroke();
fill(h, 255, 255);
ellipse(pos.x, pos.y, 5, 5);
}
}

nullpointerexception arrray = array.clone not working?

Down in the second class named paintthis, in the constructor i declare that array = array.clone, and it says that there is nothing in the array? I declare the array in LineGraph and then put the array into the peramiters, which there is a constructor of the second class names painthis with the arguments int[] array.
package javatestframming;
import java.awt.geom.*;
import javax.swing.*;
import java.awt.*;
import java.util.*;
public class LineGraph extends JFrame{
public LineGraph(){
super("Line Graph");
int[] array = {1, 2, 3, 4, 5, 7, 8, 9};
setSize(400, 400);
setDefaultCloseOperation(EXIT_ON_CLOSE);
paintthis gpane = new paintthis(array);
add(gpane);
setVisible(true);
}
public static void main(String[] args){
LineGraph lg = new LineGraph();
}
}
class paintthis extends JPanel{
int[] xpoints;
paintthis(int[] array){
xpoints = array.clone;
}
int max = arrayGetMaxInt(xpoints);
int min = arrayGetMinInt(xpoints);
int divisable = findDivisableWholeNumber(max, min);
Font f = new Font("Arial", Font.BOLD, 14);
FontMetrics fm = getFontMetrics(f);
public void paintComponent(Graphics g){
Graphics2D g2d = (Graphics2D) g;
super.paintComponents(g);
int graphHeight = 200;
int graphWidth = 200;
int graphX = 10;
int graphY = 10;
float borderThickness = 5.0f;
//set graph background and border
g2d.setColor(Color.white);
g2d.fillRect(graphX, graphY, graphWidth, graphHeight);
g2d.setColor(Color.GRAY);
BasicStroke bs = new BasicStroke(borderThickness, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND);
g2d.setStroke(bs);
g2d.drawLine(graphX - (int)borderThickness, graphY, graphX + graphWidth, graphY);
g2d.drawLine(graphX - (int)borderThickness, graphY + graphHeight, graphX + graphWidth, graphY + graphHeight);
g2d.drawLine(graphX - (int)borderThickness, graphY, graphX - (int)borderThickness, graphY + graphHeight);
g2d.drawLine(graphX + graphWidth, graphY, graphX + graphWidth, graphY + graphHeight);
int trueGraphWidth = graphWidth - drawYAxis(g2d, graphWidth, graphHeight, max, min, divisable, graphY, graphX);
int trueGraphHeight = graphHeight - drawXAxis(g2d, graphY + graphHeight - fm.getHeight(), graphX, graphWidth, (int)borderThickness);
System.out.println(trueGraphWidth + " " + graphWidth);
drawPoints(g2d, trueGraphWidth, trueGraphHeight, (graphWidth - trueGraphWidth) + (int)borderThickness + graphX, (graphHeight - trueGraphHeight) + (int)borderThickness + graphY);
}
public int drawYAxis(Graphics2D g, int graphWidth, int graphHeight, int max, int min, int counts, int beginingpoint, int overx){
graphHeight -= fm.getHeight();
int averageSpaceInBetween = ((graphHeight-fm.getHeight())/((max - min)/counts)); //- ((fm.getHeight()/(graphHeight/fm.getHeight())));
int space = 0;
Stack<Integer> stackAxisNumbers = new Stack<Integer>();
g.setFont(f);
for (int x = 0; x <= (max - min); x+=counts){
stackAxisNumbers.add(x + min);
}
for (int x = 0; x <= (max - min); x+= counts){
g.drawString("$" + Integer.toString(stackAxisNumbers.pop()), overx, space + beginingpoint + fm.getHeight());
space += averageSpaceInBetween;
}
space = 0;
return fm.stringWidth("$" + Integer.toString(max));
}
public int drawXAxis(Graphics2D g, int beginingpoint, int overx, int graphWidth, int borderThickness){
g.drawLine(overx - borderThickness, beginingpoint, overx + graphWidth, beginingpoint);
return beginingpoint - fm.getHeight();
}
public void drawPoints(Graphics2D g, int graphWidth,int graphHeight, int startX, int startY){
g.setColor(Color.blue);
int xSpace = (int) graphWidth/xpoints.length;
g.drawLine(startX, startY, xSpace + startX, xpoints[0]);
}
public int arrayGetMaxInt(int[] array){
int max = 0;
for (int x: array){
if (x > max){
max = x;
}
}
return max;
}
public int arrayGetMinInt(int[] array){
int min = max;
for (int x: array){
if (x < min){
min = x;
}
}
return min;
}
public int power(int base, int exp){
int num = base;
for (int x = 1; x < exp; x++){
num = num * base;
}
if (exp == 0){
num = 1;
}
return num;
}
public int findDivisableWholeNumber(int max, int min){
boolean passed = false;
int range = max - min;
int divis = 1;
int multiplier = 1;
out:
for (int x = 5; x > 0; x--){
if (range >= power(10, x)){
multiplier = x;
break;
}
}
out:
for (int x = 10 * multiplier; x <= 10 * multiplier && x > 0; x--){
if(range%((int)(range/x)) == 0){
divis = x;
passed = true;
break;
}
}
if (passed == false){
out:
for (int x = 11 * multiplier; x <= (int)(range / 2); x++){
if(range%((int)(range/x)) == 0){
divis = x;
passed = true;
break;
}
}
}
if (passed == false){
System.out.println("ERROR -- NoWholeDiviableNumbersException");
System.exit(0);
}
return divis;
}
}
Exception is:
Exception in thread "main" java.lang.NullPointerException
at javatestframming.paintthis.arrayGetMaxInt(LineGraph.java:97)
at javatestframming.paintthis.<init>(LineGraph.java:31)
at javatestframming.LineGraph.<init>(LineGraph.java:15)
at javatestframming.LineGraph.main(LineGraph.java:22)
C:\Users\Morgan Higginbotham\AppData\Local\NetBeans\Cache\8.1\executor- snippets\run.xml:53: Java returned: 1
BUILD FAILED (total time: 1 second)
When you create an object using paintthis gpane = new paintthis(array); It will initialize class level variables first
int max = arrayGetMaxInt(xpoints);
then body of constructor is called. In this case xpoints is still not initialized, so you are getting NullPointerException
You can try some thing like this
class paintthis extends JPanel{
int[] xpoints;
int max;
int min;
int divisable;
public paintthis(int[] array){
xpoints = array.clone();
max = arrayGetMaxInt(xpoints);
min = arrayGetMinInt(xpoints);
divisable = findDivisableWholeNumber(max, min);
}

Java - A* algorithm walks into unwalkable tiles

I'm writing automation scripts for a popular game, and part of it requires a pathfinder to walk extended distances.
I wrote this A* pathfinder to achieve this, but there are a few problems with it:
Sometimes, the pathfinder will go into unwalkable tiles which will eventually lead to it going to the top corners of the map and then out of bounds
The pathfinder will also get lost and go a long way away from the desired position and then back, leaving a path of 10000+ nodes even though there's only a distance of about 100 tiles sometimes
Here is my AStar.java:
package Webwalker;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.osbot.rs07.api.map.Position;
import org.osbot.rs07.script.Script;
import Pickpocketer.PickpocketScript;
public class AStar {
List<Position> open, closed;
List<PathTile> holdingList;
Position s, e, current;
int horizontalCost, diagonalCost, index;
Script scr;
public AStar(Script script) {
open = new ArrayList<Position>();
closed = new ArrayList<Position>();
holdingList = new ArrayList<PathTile>();
horizontalCost = 10;
index = 0;
diagonalCost = 14;
scr = script;
}
public List<Position> findPath(Position start, Position end) {
s = current = start;
closed.add(s);
holdingList.add(new PathTile(start, 0, 0, null));
e = end;
while (!nextToEnd()) {
//scr.log("Finding next node");
PathTile[] nodes = getAdjacent(current);
PathTile node = getLeastCost(nodes);
current = node.p;
if (!node.walkable) {
scr.log("Node " + node.p + " - f " + node.f);
}
closed.add(current);
open.remove(current);
Position mapP = PickpocketScript.map.getMapPos(current);
int x = mapP.getX();
int y = mapP.getY();
PickpocketScript.map.drawPixel(x, y, node.walkable);
//holdingList.add(node);
//scr.log(current);
index++;
}
/*scr.log("Cleaning nodes!");
List<Position> actualPath = new ArrayList<Position>();
for (PathTile pt : holdingList) {
if (pt == null || pt.parent == null) continue;
if (pt.parent.p.equals(start)) {
actualPath.add(pt.parent.p);
break;
}
if (pt.p.equals(start)) break;
actualPath.add(pt.parent.p);
Position mapP = PickpocketScript.map.getMapPos(pt.parent.p);
int x = mapP.getX();
int y = mapP.getY();
PickpocketScript.map.drawPixel(x, y, pt.parent.walkable);
}*/
scr.log("Finished finding " + closed.size() + " nodes");
//Collections.reverse(actualPath);
return closed;
}
public boolean nextToEnd() {
int mh = ManhattenValue(current);
return (mh < 21);
//return false;
}
public int[] distance(Position a, Position b) {
int x = Math.abs(a.getX() - b.getX());
int y = Math.abs(a.getY() - b.getY());
return new int[] { x, y };
}
public PathTile getLeastCost(PathTile[] nodes) {
int lowestIndex = 0;
int lowestF = Integer.MAX_VALUE;
for (int i = 0; i < nodes.length; i++) {
//if (!nodes[i].walkable) scr.log("Node " + nodes[i].p + " - f " + nodes[i].f +" getleastcost");
if (nodes[i] != null && nodes[i].walkable && nodes[i].f < lowestF && !closed.contains(nodes[i].p)) {
lowestF = nodes[i].f;
lowestIndex = i;
}
}
//scr.log(lowestIndex);
return nodes[lowestIndex];
}
public PathTile[] getAdjacent(Position p) {
PathTile[] nodes = new PathTile[8];
int x = p.getX();
int y = p.getY();
PathTile old = null;
if (holdingList.size() > 0) old = holdingList.get(holdingList.size() - 1);
Position newNode = new Position(x - 1, y - 1, p.getZ()); //top left
if (!open.contains(newNode)) open.add(newNode);
int h = OctileValue(newNode);
int g = diagonalCost;
nodes[0] = new PathTile(newNode, g, h, old);
//nodes[0] = nodes[2] = nodes[4] = nodes[5] = nodes[7] = null;
newNode = new Position(x, y - 1, p.getZ()); //top centre
if (!open.contains(newNode)) open.add(newNode);
h = OctileValue(newNode);
g = horizontalCost;
nodes[1] = new PathTile(newNode, g, h, old);
newNode = new Position(x + 1, y - 1, p.getZ()); //top right
if (!open.contains(newNode)) open.add(newNode);
h = OctileValue(newNode);
g = diagonalCost;
nodes[2] = new PathTile(newNode, g, h, old);
newNode = new Position(x - 1, y, p.getZ()); //centre left
if (!open.contains(newNode)) open.add(newNode);
h = OctileValue(newNode);
g = horizontalCost;
nodes[3] = new PathTile(newNode, g, h, old);
/* Centre centre would be "p", so we skip it (we are not moving back to p) */
newNode = new Position(x + 1, y, p.getZ()); //centre right
if (!open.contains(newNode)) open.add(newNode);
h = OctileValue(newNode);
g = horizontalCost;
nodes[4] = new PathTile(newNode, g, h, old);
newNode = new Position(x - 1, y + 1, p.getZ()); //bottom left
if (!open.contains(newNode)) open.add(newNode);
h = OctileValue(newNode);
g = diagonalCost;
nodes[5] = new PathTile(newNode, g, h, old);
newNode = new Position(x, y + 1, p.getZ()); //bottom centre
if (!open.contains(newNode)) open.add(newNode);
h = OctileValue(newNode);
g = horizontalCost;
nodes[6] = new PathTile(newNode, g, h, old);
newNode = new Position(x + 1, y + 1, p.getZ()); //bottom right
if (!open.contains(newNode)) open.add(newNode);
h = OctileValue(newNode);
g = diagonalCost;
nodes[7] = new PathTile(newNode, g, h, old);
/*PathTile[] temp = nodes.clone();
for (int i = 0; i < nodes.length; i++) {
if (!temp[i].walkable) {
nodes[i] = null;
}
}*/
return nodes;
}
public int OctileValue(Position start) { //This is our "H" value
int x = start.getX();
int y = start.getY();
int horizontal = Math.abs(x - e.getX());
int vertical = Math.abs(y - e.getY());
//return Math.max(horizontal, vertical) * horizontalCost; //bad algorithm lol
//return (horizontal + vertical) * horizontalCost; //Manhatten
//double tieBreaker = (1.0 + (diagonalCost / ManhattenValue(start)));
if (horizontal == 0 && vertical == 0) return 0;
//int h = horizontalCost * (horizontal + vertical) + (diagonalCost - 2 * horizontalCost) * Math.min(horizontal, vertical);
int h = Math.max(horizontal, vertical) + (diagonalCost - horizontalCost) * Math.min(horizontal, vertical);
//h *= (tieBreaker);
return h; //Octile distance
}
public int ManhattenValue(Position start) {
int x = start.getX();
int y = start.getY();
int horizontal = Math.abs(x - e.getX());
int vertical = Math.abs(y - e.getY());
return (horizontal + vertical) * horizontalCost;
}
}
class PathTile {
public Position p;
public int g, h, f;
public boolean walkable;
public PathTile parent;
public PathTile(Position pos, int G, int H, PathTile par) {
p = pos;
g = G;
h = H;
if (par != null) {
g += par.g;
parent = par;
}
if (h == 0) f = 0;
else f = g + h;
System.out.println(p + " - g " + g + " - h " + h + " - f " + f);
walkable = (PickpocketScript.map.isWalkable(pos));
if (!walkable) {
f = Integer.MAX_VALUE;
}
}
}
I know that these tiles are unwalkable because they have an F value of int.maxvalue (as defined in PathTile class)
A Position in this scenario simply has an int for x,y,z.
I'm not too sure how to fix these problems, as I'm quite new to writing algorithms like this :)
Your findPath() method looks like it's performing a greedy best-first search. Check the line PathTile node = getLeastCost(nodes);... You are selecting the least-cost node from among the neighbors of the current PathTile, not from among the entries in the open set. Instead, use a PriorityQueue sorted by f-value for the open list and get your next node from the head of the open list.
Additional Resources: I recommend you follow Wikipedia's A* Search Algorithm Pseudocode. Also, you may want to check out the introduction to A* at Redblobgames.com.
Final Consideration: When working with pathfinding in a grid graph, it is helpful to use an enum to define the directions. This makes your code more readable and maintainable. Here's an example:
enum Direction{
TOP_LEFT(-1,-1,diagonalCost),
TOP_CENTER(0,-1,horizontalCost),
TOP_RIGHT(1,-1,diagonalCost),
MIDDLE_LEFT(-1,0,horizontalCost),
MIDDLE_RIGHT(1,0,horizontalCost),
BOTTOM_LEFT(-1,1,diagonalCost),
BOTTOM_CENTER(0,1,horizontalCost),
BOTTOM_RIGHT(1,1,diagonalCost);
public final int x;
public final int y;
public final int cost;
Direction(int x, int y, int cost){
this.x = x;
this.y = y;
this.cost = cost;
}
}
Your (uncorrected) getAdjacent method can be simplified to the following:
public PathTile[] getAdjacent(Position p) {
PathTile[] nodes = new PathTile[8];
int x = p.getX();
int y = p.getY();
PathTile old = null;
if (holdingList.size() > 0) old = holdingList.get(holdingList.size() - 1);
for(Direction d: Direction.values()){
newNode = new Position(x+ d.x, y + d.y, p.getZ()); //top centre
if (!open.contains(newNode)) open.add(newNode);
h = OctileValue(newNode);
g = d.cost;
nodes[d.ordinal()] = new PathTile(newNode, g, h, old);
}
return nodes;
}

Algorithm for drawing tiles on screen

I have struggled with this problem for several days now, and I just can't solve the problem myself.
I have a Minecraft 2D sort of game. The Blocks are divided into Chunks of 64 * 64 Blocks.
I have this draw function:
#Override
protected void gameDraw(Graphics2D g) {
g.drawImage(Texture.getImage("background"), 0, 0, 800, 600, 0, 0, 800, 600, null);
int pixelXMin = (int) (screenX);
int pixelYMin = (int) (screenY);
int pixelXMax = (int) (canvas.getWidth() + screenX);
int pixelYMax = (int) (canvas.getHeight() + screenY);
int blockXMin = pixelXMin / Block.BLOCK_PIXEL_WIDTH;
int blockYMin = pixelYMin / Block.BLOCK_PIXEL_HEIGHT;
int blockXMax = pixelXMax / Block.BLOCK_PIXEL_WIDTH;
int blockYMax = pixelYMax / Block.BLOCK_PIXEL_HEIGHT;
int diffX = pixelXMin % Block.BLOCK_PIXEL_WIDTH;
int diffY = pixelYMin % Block.BLOCK_PIXEL_HEIGHT;
for (int bx = blockXMin; bx < blockXMax; bx++) {
for (int by = blockYMin; by < blockYMax; by++) {
int chunkNum = bx / Chunk.COLUMNS_IN_CHUNK;
int blockX = bx % Chunk.COLUMNS_IN_CHUNK;
int blockY = by % Chunk.COLUMNS_IN_CHUNK;
Chunk chunk = level.loadChunk(chunkNum);
Block block = chunk.getBlock(blockX, blockY);
if (block == null) { continue; }
BlockData blockData = block.getBlockData();
if (blockData.getType().getTextureName().equals("")) { continue; }
int blockPosX = canvas.getWidth() - (bx * Block.BLOCK_PIXEL_WIDTH + diffX);
int blockPosY = canvas.getHeight() - (by * Block.BLOCK_PIXEL_HEIGHT + diffY);
BufferedImage image = Texture.getImage(blockData.getType().getName());
g.drawImage(image, blockPosX, blockPosY, Block.BLOCK_PIXEL_WIDTH, Block.BLOCK_PIXEL_HEIGHT, null);
}
}
}
Here i tried to calculate the maximum and minimum number of pixels on the screen with the variables screenX and screenY who serve as "camera position". Then I loop through every block that is within these pixels.
The rest is sort of self explanatory.
Now for the problem:
As you can see does the game draw nicely, but when you change the values of screenX and screenY, the "box" of blocks move realtive to the screen, but the blocks stay at the same location.
How can I solve this? Thank you!
Link to dropbox download for .jar file and full sourcecode. gameDraw() is in CubeExplorer.java
https://www.dropbox.com/sh/madienlwmhjt2wh/AADA83aKa00j5UFowhotfmmaa?dl=0
SOLUTION
Here is my solution:
#Override
protected void gameDraw(Graphics2D g) {
g.drawImage(Texture.getImage("background"), 0, 0, 800, 600, 0, 0, 800, 600, null);
int x = (int) (screenX / Block.BLOCK_PIXEL_WIDTH);
int y = (int) (screenY / Block.BLOCK_PIXEL_HEIGHT);
int blockXMin = x;
int blockYMin = y;
int blockXMax = x + canvas.getWidth() / Block.BLOCK_PIXEL_WIDTH + 2;
int blockYMax = y + canvas.getWidth() / Block.BLOCK_PIXEL_WIDTH + 2;
System.out.println(x + "," + y + " " + blockXMax + "," + blockYMax);
for(int blockX = blockXMin; blockX < blockXMax; blockX++) {
for(int blockY = blockYMin; blockY < blockYMax; blockY++) {
int chunkX = blockX / Chunk.COLUMNS_IN_CHUNK;
Chunk chunk = level.loadChunk(chunkX);
int blockChunkPosX = blockX % Chunk.COLUMNS_IN_CHUNK;
int blockChunkPosY = blockY % Chunk.ROWS_IN_CHUNK;
Block block = chunk.getBlock(blockChunkPosX, blockChunkPosY);
if (block == null) { continue; }
BlockData blockData = block.getBlockData();
if (blockData.getType().getTextureName().equals("")) { continue; }
int blockScreenLocX = (int) ((int) + blockX * Block.BLOCK_PIXEL_WIDTH - screenX);
int blockScreenLocY = 600 - (int) ((int) + blockY * Block.BLOCK_PIXEL_HEIGHT - screenY);
BufferedImage image = Texture.getImage(blockData.getType().getName());
g.drawImage(image, blockScreenLocX, blockScreenLocY, Block.BLOCK_PIXEL_WIDTH, Block.BLOCK_PIXEL_HEIGHT, null);
}
}
}

How to delete object with a mouse click?

I made a simple FlowChat Editor that creates rectangles and triangles and connects them to each other and shows the way from up to down. I can move this elements on screen too.
I am now trying to create a button to delete the element which I clicked. There is problem that I can delete MyTriangle objects, but I can't delete MyRectangle objects. It deletes but not object which I clicked. I delete from first object to last.
Here is my code:
if (deleteObj) {
if (rectsList.size() != 0) {
for (int i = 0; i < rectsList.size(); i++) {
MyRect rect = (MyRect) rectsList.get(i);
if (e.getX() <= rect.c.x + 50 && e.getX() >= rect.c.x - 50
&& e.getY() <= rect.c.y + 15 && e.getY() >= rect.c.y - 15) {
rectsList.remove(rect);
System.out.println("This is REctangle DELETED\n");
}
}
}
if (triangleList.size() != 0) {
for (int j = 0; j < triangleList.size(); j++) {
MyTriangle trian = (MyTriangle) triangleList.get(j);
if (e.getX() <= trian.c.x + 20 && e.getX() >= trian.c.x - 20
&& e.getY() <= trian.c.y + 20 && e.getY() >= trian.c.y - 20) {
triangleList.remove(trian);
System.out.println("This is Triangle Deleted\n");
}
}
}
Edit Here MyRectangle and MyTriangle classes
public class MyRect extends Ellipse2D.Double {
Point c;
Point in;
Point out;
int posX;
int posY;
int width = 100;
int height = 30;
int count;
public MyRect(Point center, Point input, Point output,int counter) {
c = center;
in = input;
out = output;
count=counter;
}
void drawMe(Graphics g) {
// in.x=c.x+20;
int posX = c.x;
int posY = c.y;
int posInX = in.x;
int posInY = in.y;
int posOutX = out.x;
int posOutY = out.y;
g.setColor(Color.MAGENTA);
g.drawString(" S "+count ,posX-5, posY+5);
g.setColor(Color.black);
g.drawRect(posX-50, posY-15, width, height);
g.setColor(Color.green);
g.drawRect(posInX-3, posInY-9, 6, 6);
g.setColor(Color.blue);
g.drawRect(posOutX-3, posOutY+3, 6, 6);
}
}
public class MyTriangle {
Point c;
Point in ;
Point outYES ;
Point outNO ;
int posX;
int posY;
int count;
public MyTriangle(Point center,Point input,Point outputYES,Point outputNO,int counter) {
c = center;
in = input;
outYES = outputYES;
outNO = outputNO;
count=counter;
}
void drawMe(Graphics g) {
int posX = c.x;
int posY = c.y;
int posInX=in.x;
int posInY=in.y;
int posOutYESX=outYES.x;
int posOutYESY=outYES.y;
int posOutNOX=outNO.x;
int posOutNOY=outNO.y;
int[] xPoints = {posX - 50, posX, posX + 50, posX};
int[] yPoints = {posY, posY - 30, posY, posY + 30};
g.setColor(Color.MAGENTA);
g.drawString(" T "+count,posX-5, posY+5);
g.setColor(Color.black);
g.drawPolygon(xPoints, yPoints, 4);
// draw input
g.setColor(Color.green);
g.drawRect(posInX-3,posInY-9, 6, 6);
g.setColor(Color.blue);
g.drawRect(posOutYESX-9,posOutYESY-3 , 6, 6);
g.setColor(Color.red);
g.drawRect(posOutNOX-3,posOutNOY+3 , 6, 6);
}
}
Edit 2
Here my funcs to add object to list.Is there could be ant mistake?Because I am her ceratıng new object of that calss and I am addıng that object to rectlist or trianglelist..
public void initRect(Point c, Point in, Point out) {
sCounter++;
MyRect myrects = new MyRect(c, in, out, sCounter);
rectsList.add(myrects);
s_And_t_List.add(myrects);
objectCounter.add("S " + sCounter);
selectablePanel.repaint();
}
public void initTriangle(Point c, Point in, Point outYES, Point outNO) {
tCounter++;
MyTriangle mytriangles = new MyTriangle(c, in, outYES, outNO, tCounter);
triangleList.add(mytriangles);
s_And_t_List.add(mytriangles);
objectCounter.add("T " + tCounter);
selectablePanel.repaint();
}
It seems like your logic is wrong. In your Rectangle class why not make a method returning a boolean that tests if a given set of coordinates is contained in your object. For example:
public boolean contains(int x, int y){
if(x_starting_point <= x && x <= x_starting_point+width
&& y_starting_point <= y && y <= y_starting_point+height)
return true;
return false;
}

Categories

Resources