I'am new new to JavaFX, and I got a problem. I'm trying to move Nodes with UP,DOWN,LEFT,RIGHT, if I just move my "Player" node, it's work perfectly, but I wanna make a game like sokoban, so my Player node can move "Crate" node, the problem is if I press the RIGHT next to the Crate, it swap the places, but not working correctly here is the moving method :
private void lepes(int i, int j, int target_i, int target_j){
int ai, aj;
int bi, bj;
ai = i;
aj = j;
bi = target_i;
bj = target_j;
MyNode nodeA = playfield[ai][aj];
nodeA.toFront();
MyNode nodeB = playfield[bi][bj];
nodeB.toFront();
playfield[ai][aj] = nodeB;
playfield[bi][bj] = nodeA;
Path pathA = new Path();
pathA.getElements().add (new MoveTo ( nodeA.getTranslateX() + nodeA.getBoundsInParent().getWidth() / 2.0, nodeA.getTranslateY() + nodeA.getBoundsInParent().getHeight() / 2.0));
pathA.getElements().add (new LineTo( nodeB.getTranslateX() + nodeB.getBoundsInParent().getWidth() / 2.0, nodeB.getTranslateY() + nodeB.getBoundsInParent().getHeight() / 2.0));
PathTransition pathTransitionA = new PathTransition();
pathTransitionA.setDuration(Duration.millis(1));
pathTransitionA.setNode( nodeA);
pathTransitionA.setPath(pathA);
pathTransitionA.play();
Path pathB = new Path();
pathB.getElements().add (new MoveTo ( nodeB.getTranslateX() + nodeB.getBoundsInParent().getWidth() / 2.0, nodeB.getTranslateY() + nodeB.getBoundsInParent().getHeight() / 2.0));
pathB.getElements().add (new LineTo( nodeA.getTranslateX() + nodeA.getBoundsInParent().getWidth() / 2.0, nodeA.getTranslateY() + nodeA.getBoundsInParent().getHeight() / 2.0));
PathTransition pathTransitionB = new PathTransition();
pathTransitionB.setDuration(Duration.millis(1));
pathTransitionB.setNode( nodeB);
pathTransitionB.setPath(pathB);
pathTransitionB.play();
pathTransitionA.setOnFinished( new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
if( (pathTransitionB.getStatus() == Status.RUNNING))
return;
}
});
pathTransitionB.setOnFinished( new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
if( (pathTransitionA.getStatus() == Status.RUNNING))
return;
}
});
}
and here is the eventHandler
scene.setOnKeyPressed(new EventHandler<KeyEvent>() {
#Override
public void handle(KeyEvent event) {
if (event.getCode()==KeyCode.RIGHT) {
if(jatekosX < 8 && playfield[jatekosX+1][jatekosY].getHisNumber() == 2){
lepes(jatekosX, jatekosY, jatekosX+1, jatekosY);
jatekosX++;
lepesek++;
}
else if(jatekosX < 8 && playfield[jatekosX+1][jatekosY].getHisNumber() == 1 ){
lepes(jatekosX+1, jatekosY, jatekosX+2, jatekosY);
lepes(jatekosX, jatekosY, jatekosX+1, jatekosY);
jatekosX++;
lepesek++;
}
System.out.println("Jobbra");
System.out.println("X: " + jatekosX + "Y: " + jatekosY + " lépés: " + lepesek + "\n");
}
}
});
Here is the picture next to crate node, https://postimg.org/image/7qkqxnxs5/
And here is after a Right step, https://postimg.org/image/t1ib1xfwl/
I Don't know what causes this.
Related
I would like to draw an arrow in a JavaFX application, that rotates around an object that is bound to it (2 group objects that are connected with an arrow). To compute the correct angle I tried to compute it by substracting the two coordinates (end and start xy coordinates from the groups). But my arrow head will not move. Any ideas what I am doing wrong?
// controller code:
PlaceIcon startIconGroup = new PlaceIcon();
startIconGroup.setLayoutX(100);
startIconGroup.setLayoutY(120);
startIconGroup.addEventHandler(MouseEvent.MOUSE_CLICKED, onClickEventHandler); // for dragging
startIconGroup.addEventHandler(MouseEvent.MOUSE_DRAGGED, onDragEventHandler);
startIconGroup.addEventHandler(MouseEvent.MOUSE_PRESSED, onPressEventHandler);
workplace.getChildren().add(startIconGroup); // workplace is the pane were the nodes are shown
PlaceIcon endIconGroup = new PlaceIcon();
endIconGroup.setLayoutX(100);
endIconGroup.setLayoutY(120);
endIconGroup.addEventHandler(MouseEvent.MOUSE_CLICKED, onClickEventHandler);
endIconGroup.addEventHandler(MouseEvent.MOUSE_DRAGGED, onDragEventHandler);
endIconGroup.addEventHandler(MouseEvent.MOUSE_PRESSED, onPressEventHandler);
endIconGroup.getChildren().add(startIconGroup);
RelationIcon relationIcon = new RelationIcon();
relationIcon.setStartNode(startNode);
relationIcon.setEndNode(endNode);
...
EventHandler<MouseEvent> onDragEventHandler = new EventHandler<MouseEvent>() {
/**
* This method is used to compute the new position of an node. Therefore, the
* position in pixels (x/yLayout) is incremented by coordinate change of mouse
* movement.
*/
#Override
public void handle(MouseEvent event) {
Group clickedElement = (Group) event.getSource();
// Node node = clickedElement.getChildren().get(0);
double offsetX = event.getSceneX() - mousePosition.get().getX();
double offsetY = event.getSceneY() - mousePosition.get().getY();
clickedElement.setLayoutX(clickedElement.getLayoutX() + offsetX);
clickedElement.setLayoutY(clickedElement.getLayoutY() + offsetY);
mousePosition.set(new Point2D(event.getSceneX(), event.getSceneY()));
eventlog.setText("Move "+ clickedElement + " to x=" + clickedElement.getLayoutX() + " y="
+ clickedElement.getLayoutY());
}
};
And here is the PlaceIconClass
public class RelationIcon extends Group {
Line line;
Polygon arrowHead;
Group startNode;
Group endNode;
public RelationIcon() {
//draw arrow line
line = new Line();
// draw arrow head
arrowHead = new Polygon();
arrowHead.getPoints().addAll(new Double[]{
-10.0, -20.0,
10.0, -20.0,
0.0, 0.0});
// merge into a group
this.getChildren().addAll(line, arrowHead);
}
public Group getStartNode() {
return startNode;
}
public void setStartNode(Group startNode) {
this.startNode = startNode;
line.startXProperty().bind(this.startNode.layoutXProperty());
line.startYProperty().bind(this.startNode.layoutYProperty());
}
public Group getEndNode() {
return endNode;
}
public void setEndNode(Group endNode) {
this.endNode = endNode;
line.endXProperty().bind(this.endNode.layoutXProperty());
line.endYProperty().bind(this.endNode.layoutYProperty());
arrowHead.layoutXProperty().bind(this.endNode.layoutXProperty());
arrowHead.layoutYProperty().bind(this.endNode.layoutYProperty());
arrowHead.rotateProperty().bind(this.endNode.layoutXProperty()); // THIS WORKS
arrowHead.rotateProperty().bind(Bindings.createDoubleBinding(() -> {
double x = line.endXProperty().getValue() - line.startXProperty().getValue();
double y = line.endYProperty().getValue() - line.startYProperty().getValue();
System.out.println(x+" "+y);
double a = Math.atan2(x, y);
return Math.toDegrees(a);
})); // THIS WORKS NOT
}
Thank you for your help!
I have writen a program in Processing to implement the Bentley-Ottmann algorithm for the line segment intersection problem.
The program returns a set of points but it does not find all the intersections. Can anyone tell me please what have I done wrong?
An ArrayList holds the active line segments that intersect the sweep line.
For each endpoint I store its x position and the Line2D it belongs to, at an TreeMap(Double, List(Line2D)) structure.
I am holding a List of Lines2D (TreeMap(Double, List(Line2D) ) because if I find an intersection I report its x position and the two lines that intersect.
I think I followed all the steps required by the algorithm. I've studied from the "Computational Geometry - Algorithms and Applications", and also a pdf named "Computing intersections in a set of line segments: the Bentley-Ottmann algorithm" from Michiel Smid.
Although, I am not taking into account the restrictions about the vertical lines, intersection with three segments etc. most of the times the requirements are met but still the results are not the expected ones.
This is an example
This is my code
import java.util.*;
import java.awt.*;
import java.awt.geom.*;
import java.util.List;
import java.util.concurrent.TimeUnit;
Algorithm algorithm = new Algorithm();
List<Line2D> initialList = new ArrayList<Line2D>();
List<Double> xStructure = new ArrayList<Double>();
Set<Point2D> intersections = new HashSet<Point2D>();
void setup() {
size(640, 480);
initialList = algorithm.createListOfRandomLines(5);
long start = System.currentTimeMillis();
intersections = algorithm.runBentleyOttmann(initialList);
long stop = System.currentTimeMillis() - start;
System.out.println(String.format("Execution Time: %f sec", (float)TimeUnit.MILLISECONDS.toSeconds(stop)));
}
void draw() {
background(255);
strokeWeight(1);
stroke(0);
for(Line2D l : initialList)
line((float)l.getX1(), (float)l.getY1(), (float)l.getX2(), (float)l.getY2());
strokeWeight(5);
stroke(255,0,0);
for(Point2D p : intersections)
point((float)p.getX(), (float)p.getY());
}
class Algorithm {
TreeMap<Double, List<Line2D>> xStructure;
Double slPosition;
List<Line2D> slStatus; // Y-structure
Set<Point2D> intersectionPoints;
public Algorithm() {
intersectionPoints = new HashSet<Point2D>();
slPosition = Double.MIN_VALUE;
slStatus = new ArrayList<Line2D>();
xStructure = new TreeMap<Double, List<Line2D>>();
}
public Set<Point2D> runBentleyOttmann(List<Line2D> list) {
//System.out.println("DEBUG INFO: runBentleyOttmann got input a list of " + list.size() + " line segments.");
xStructure = createMapOfSortedEndpointsAndCorespondingLineSegment(list);
//System.out.println("DEBUG INFO: runBentleyOttmann x-structure now contains the " + xStructure.size() + " endpoints.");
//System.out.println("DEBUG INTO: runBentleyOttmann sweep line is at position " + slPosition);
//System.out.println("DEBUG INFO: runBentleyOttmann begins while loop");
while (!xStructure.isEmpty()) {
Map.Entry<Double, List<Line2D>> entry = xStructure.pollFirstEntry();
Double min = entry.getKey();
slPosition = min;
List<Line2D> lines = entry.getValue();
//System.out.println("-----DEBUG INFO: runBentleyOttmann let min be the minimum element of x-structure " + min);
//System.out.println("-----DEBUG INFO: runBentleyOttmann delete min from the x-structure");
//System.out.println("-----DEBUG INFO: runBentleyOttmann checks endpoint type");
if (checkEndpointType(lines) == EndpointType.LEFT) {
//System.out.println("----------DEBUG INFO: Endpoint Type LEFT");
handleLeftEndpoint(lines);
}
else if (checkEndpointType(lines) == EndpointType.RIGHT) {
//System.out.println("----------DEBUG INFO: Endpoint Type RIGHT");
handleRightEndpoint(lines);
}
else if (checkEndpointType(lines) == EndpointType.INTERSECTION) {
//System.out.println("----------DEBUG INFO: Endpoint Type INTERSECTION");
handleIntersectionEndpoint(lines);
}
}
//System.out.println("DEBUG INFO: runBentleyOttmann ends while loop");
return intersectionPoints;
}
public void handleIntersectionEndpoint(List<Line2D> lines) {
Line2D l1 = slStatus.get(slStatus.indexOf(lines.get(0)));
Line2D l2 = slStatus.get(slStatus.indexOf(lines.get(1)));
if (slStatus.indexOf(l1) > slStatus.indexOf(l2)) {
Line2D ltemp = slStatus.get(slStatus.indexOf(lines.get(0)));
l1 = l2;
l2 = ltemp;
}
Line2D prev;
Line2D next;
if (slStatus.indexOf(l1) > 0) {
prev = getAboveLine(l1);
if (prev != null)
if (l2.intersectsLine(prev)) {
Point2D ip = findIntersectionPoint(l2, prev);
if (ip.getX() > slPosition) {
intersectionPoints.add(findIntersectionPoint(l2, prev));
List<Line2D> tempList = new ArrayList<Line2D>();
tempList.add(l2);
tempList.add(prev);
xStructure.put(ip.getX(), tempList);
}
}
}
if (slStatus.indexOf(l2) < slStatus.size()-1) {
next = getBelowLine(l2);
if (next != null)
if (l1.intersectsLine(next)) {
Point2D ip = findIntersectionPoint(l1, next);
if (ip.getX() > slPosition) {
intersectionPoints.add(findIntersectionPoint(l1, next));
List<Line2D> tempList = new ArrayList<Line2D>();
tempList.add(l1);
tempList.add(next);
xStructure.put(ip.getX(), tempList);
}
}
}
System.out.println(slStatus.indexOf(l1) + " " + slStatus.indexOf(l2));
}
public void handleLeftEndpoint(List<Line2D> lines) {
//System.out.println("HANDLE LEFT ENDPOINT started");
slStatus.add(lines.get(0));
//System.out.println("Line [X1=" + lines.get(0).getX1() + ", Y1=" + lines.get(0).getY1() + ", X2=" + lines.get(0).getX2() + ", Y2=" + lines.get(0).getY2() + "] added to Y-Structure.");
Collections.sort(slStatus, new YComparator());
//System.out.println("Y-Structure is sorted by Y endpoint");
Line2D above = getAboveLine(lines.get(0));
if (above != null)
if (lines.get(0).intersectsLine(above)) {
Point2D ip = findIntersectionPoint(lines.get(0), above);
if (ip.getX() > slPosition) {
intersectionPoints.add(findIntersectionPoint(lines.get(0), above));
List<Line2D> tempList = new ArrayList<Line2D>();
tempList.add(lines.get(0));
tempList.add(above);
xStructure.put(ip.getX(), tempList);
}
}
Line2D below = getBelowLine(lines.get(0));
if (below != null)
if (lines.get(0).intersectsLine(below)) {
Point2D ip = findIntersectionPoint(lines.get(0), below);
if (ip.getX() > slPosition) {
intersectionPoints.add(findIntersectionPoint(lines.get(0), below));
List<Line2D> tempList = new ArrayList<Line2D>();
tempList.add(lines.get(0));
tempList.add(below);
xStructure.put(ip.getX(), tempList);
}
}
//System.out.println("HANDLE LEFT ENDPOINT finished");
}
public void handleRightEndpoint(List<Line2D> lines) {
//System.out.println("HANDLE RIGHT ENDPOINT started");
Line2D above = getAboveLine(lines.get(0));
Line2D below = getBelowLine(lines.get(0));
if (above != null && below != null)
if (above.intersectsLine(below)){
Point2D ip = findIntersectionPoint(lines.get(0), below);
if (ip.getX() > slPosition)
intersectionPoints.add(findIntersectionPoint(lines.get(0), below));
}
slStatus.remove(lines.get(0));
//System.out.println("Line [X1=" + lines.get(0).getX1() + ", Y1=" + lines.get(0).getY1() + ", X2=" + lines.get(0).getX2() + ", Y2=" + lines.get(0).getY2() + "] deleted from Y-Structure.");
}
public Line2D getAboveLine(Line2D line) {
if (slStatus.indexOf(line) > 0) {
Line2D a = slStatus.get(slStatus.indexOf(line)-1);
//System.out.println("getAboveLine returns line [X1=" + a.getX1() + ", Y1=" + a.getY1() + ", X2=" + a.getX2() + ", Y2=" + a.getY2() + "]");
return a;
}
//System.out.println("getAboveLine returns no line");
return null;
}
public Line2D getBelowLine(Line2D line) {
if (slStatus.indexOf(line) < slStatus.size()-1) {
Line2D b = slStatus.get(slStatus.indexOf(line)+1);
//System.out.println("getBelowLine returns line [X1=" + b.getX1() + ", Y1=" + b.getY1() + ", X2=" + b.getX2() + ", Y2=" + b.getY2() + "]");
//System.out.println("getAboveLine returns no line");
return b;
}
return null;
}
public EndpointType checkEndpointType(List<Line2D> lines) {
if (lines.size() == 2)
return EndpointType.INTERSECTION;
if (slStatus.contains(lines.get(0)))
return EndpointType.RIGHT;
if (!slStatus.contains(lines.get(0)))
return EndpointType.LEFT;
return null;
}
public List<Line2D> sortEndpointsByXCoordinate(List<Line2D> inputList) {
List<Line2D> returnList = new ArrayList(inputList);
Collections.sort(returnList, new XComparator());
return returnList;
}
public TreeMap<Double, List<Line2D>> createMapOfSortedEndpointsAndCorespondingLineSegment(List<Line2D> inputList) {
TreeMap returnTreeMap = new TreeMap<Double, Line2D>();
for (Line2D l : inputList) {
List<Line2D> tempList = new ArrayList<Line2D>();
tempList.add(l);
returnTreeMap.put(l.getX1(), tempList);
returnTreeMap.put(l.getX2(), tempList);
}
return returnTreeMap;
}
public List<Double> createListOfSortedEndpoints(List<Line2D> inputList) {
List<Double> returnList = new ArrayList<Double>();
for (Line2D l : inputList) {
returnList.add(l.getBounds().getX());
returnList.add(l.getBounds().getY());
}
Collections.sort(returnList);
//System.out.println("DEBUG INFO: createListOfSortedEndpoints returns " + returnList.size() + " endpoints");
return returnList;
}
public List<Line2D> createListOfRandomLines(int size) {
Set<Line2D> hashset = new HashSet<Line2D>();
Random random = new Random();
while (hashset.size() != size) {
Line2D line = new Line2D.Double();
line.setLine(random.nextInt(width-1)+1, random.nextInt(height-1)+1, random.nextInt(width-1)+1, random.nextInt(height-1)+1);
hashset.add(line);
}
List<Line2D> returnList = new ArrayList(hashset);
return returnList;
}
public Point2D findIntersectionPoint(Line2D l1, Line2D l2) {
Double p0_x = l1.getX1();
Double p0_y = l1.getY1();
Double p1_x = l1.getX2();
Double p1_y = l1.getY2();
Double p2_x = l2.getX1();
Double p2_y = l2.getY1();
Double p3_x = l2.getX2();
Double p3_y = l2.getY2();
Double s1_x = p1_x - p0_x;
Double s1_y = p1_y - p0_y;
Double s2_x = p3_x - p2_x;
Double s2_y = p3_y - p2_y;
Double s, t;
s = (-s1_y * (p0_x - p2_x) + s1_x * (p0_y - p2_y)) / (-s2_x * s1_y + s1_x * s2_y);
t = ( s2_x * (p0_y - p2_y) - s2_y * (p0_x - p2_x)) / (-s2_x * s1_y + s1_x * s2_y);
Double i_x, i_y;
i_x = p0_x + (t * s1_x);
i_y = p0_y + (t * s1_y);
Point2D p = new Point2D.Double(i_x, i_y);
return p;
}
}
class XComparator implements Comparator<Line2D>{
public int compare(Line2D l1, Line2D l2){
return new Double(l1.getBounds().getX()).compareTo(l2.getBounds().getX());
}
}
class YComparator implements Comparator<Line2D>{
public int compare(Line2D l1, Line2D l2){
return new Double(l1.getBounds().getY()).compareTo(l2.getBounds().getY());
}
}
enum EndpointType {
LEFT, RIGHT, INTERSECTION
};
I would recommend considering the following Java implementation: https://github.com/stanislav-antonov/bentley-ottmann
It's clean and minimalistic enough, but still handles all the major edge cases.
I am working on a knight's tour problem with basic gui,i want to take user input in the two text fields which make up the (x,y) from user and then in one text box i print if solution is posiible and in the other i write the path adopted by the knight.My algorithm works fine and i have problem in gui.i have given a few default values to (x,y) for that i get correct output .But when i change the value of (x,y) in the textfield,no change occurs.this is the main file ,there is another event handler file,which is below it.Your help will be sincerely appreciated.I am working on processing 2.2.1.This is how the output screen looks like
Main file/project.pde
// Need G4P library
import g4p_controls.*;
Maxim maxim;
AudioPlayer player;
int x=-1;
int y=-1;
String solution="";
PImage img;
int count=0;
public void setup(){
size(480, 320, JAVA2D);
maxim=new Maxim(this);
player=maxim.loadFile("song.wav");
player.setLooping(true);
img=loadImage("chess.jpg");
createGUI();
customGUI();
// Place your setup code here
}
int t[]=new int[25];
boolean visited[][]=new boolean[5][5];
int check[][]=new int[5][5];
boolean b;
int counter=-1;
boolean move(int x,int y , int m){
boolean result=false;
if (x<0 || x>=5 || y<0 || y>=5 || visited[x][y]==true)
{
return false;
}
visited[x][y]=true;
if (m==24)
{
visited[x][y]=true;
return true;
}
else
{
String xstring=String.valueOf(x);
String ystring=String.valueOf(y);
solution=solution+xstring+","+ystring+" ";
print (x);
print(",");
print(y);
check[x][y]=counter+1;
if (move(x+2,y+1,m+1) || move(x+2,y-1,m+1)
|| move(x-2,y+1,m+1) || move(x-2,y-1,m+1)
|| move(x+1,y+1,m+1) || move(x+1,y-1,m+1)
|| move(x-1,y+1,m+1) || move(x-1,y-1,m+1)){
print (x);
print(",");
print(y);
//check[x][y]=1;
return true;
}
return false;
}
}
public void draw(){
counter=counter+1;
background(0,128,128);
image(img,0,0,480,320);
player.play();
textarea2.setText(solution);
String txt1 = textfield1.getText();
x = Integer.parseInt(txt1);
String txt2 = textfield2.getText();
y= Integer.parseInt(txt2);
print(solution);
if(x>=0 && y>=0)
{
b=move(x,y,0);
if(b==false)
{
textarea1.setText("Solution is not possible,enter other coordinates");
}
if(b==true)
{
textarea1.setText("Congratulations solution is possible");
}
}
if(count%8==0)
{
delay(1000);
println(counter);
}
}
void keyPressed()
{
if (key==13)
{
solution="";
print(solution);
textarea2.setText(solution);
String txt1 = textfield1.getText();
x = Integer.parseInt(txt1);
String txt2 = textfield2.getText();
y= Integer.parseInt(txt2);
}
if(x>=0 && y>=0)
{
b=move(x,y,0);
if(b==false)
{
textarea1.setText("Solution is not possible,enter other coordinates");
}
if(b==true)
{
textarea1.setText("Congratulations solution is possible");
}
}
}
// Use this method to add additional statements
// to customise the GUI controls
public void customGUI(){
}
this is the event handlers file
/* =========================================================
* ==== WARNING ===
* =========================================================
* The code in this tab has been generated from the GUI form
* designer and care should be taken when editing this file.
* Only add/edit code inside the event handlers i.e. only
* use lines between the matching comment tags. e.g.
void myBtnEvents(GButton button) { //_CODE_:button1:12356:
// It is safe to enter your event code here
} //_CODE_:button1:12356:
* Do not rename this tab!
* =========================================================
*/
public void tf1(GTextField source, GEvent event) { //_CODE_:textfield1:418637:
println("textfield1 - GTextField >> GEvent." + event + " # " + millis());
} //_CODE_:textfield1:418637:
public void tf2(GTextField source, GEvent event) { //_CODE_:textfield2:859413:
println("textfield2 - GTextField >> GEvent." + event + " # " + millis());
} //_CODE_:textfield2:859413:
public void ta1(GTextArea source, GEvent event) { //_CODE_:textarea1:252891:
println("textarea1 - GTextArea >> GEvent." + event + " # " + millis());
} //_CODE_:textarea1:252891:
public void ta2(GTextArea source, GEvent event) { //_CODE_:textarea2:483845:
println("textarea2 - GTextArea >> GEvent." + event + " # " + millis());
} //_CODE_:textarea2:483845:
public void slider1_change1(GSlider source, GEvent event) { //_CODE_:slider1:280049:
println("slider1 - GSlider >> GEvent." + event + " # " + millis());
} //_CODE_:slider1:280049:
public void slider2_change1(GSlider source, GEvent event) { //_CODE_:slider2:362722:
println("slider2 - GSlider >> GEvent." + event + " # " + millis());
} //_CODE_:slider2:362722:
// Create all the GUI controls.
// autogenerated do not edit
public void createGUI(){
G4P.messagesEnabled(false);
G4P.setGlobalColorScheme(GCScheme.BLUE_SCHEME);
G4P.setCursor(ARROW);
if(frame != null)
frame.setTitle("Sketch Window");
textfield1 = new GTextField(this, 210, 32, 160, 30, G4P.SCROLLBARS_NONE);
textfield1.setText("1");
textfield1.setPromptText("Enter x-Cordinate");
textfield1.setOpaque(true);
textfield1.addEventHandler(this, "tf1");
textfield2 = new GTextField(this, 204, 96, 160, 30, G4P.SCROLLBARS_NONE);
textfield2.setText("1");
textfield2.setPromptText("Enter y Cordinate");
textfield2.setLocalColorScheme(GCScheme.PURPLE_SCHEME);
textfield2.setOpaque(true);
textfield2.addEventHandler(this, "tf2");
textarea1 = new GTextArea(this, 53, 196, 160, 80, G4P.SCROLLBARS_NONE);
textarea1.setLocalColorScheme(GCScheme.GREEN_SCHEME);
textarea1.setOpaque(true);
textarea1.addEventHandler(this, "ta1");
textarea2 = new GTextArea(this, 288, 192, 160, 80, G4P.SCROLLBARS_NONE);
textarea2.setLocalColorScheme(GCScheme.YELLOW_SCHEME);
textarea2.setOpaque(true);
textarea2.addEventHandler(this, "ta2");
slider1 = new GSlider(this, 96, 276, 264, 40, 10.0);
slider1.setLimits(0.5, 0.0, 1.0);
slider1.setNumberFormat(G4P.DECIMAL, 2);
slider1.setOpaque(false);
slider1.addEventHandler(this, "slider1_change1");
slider2 = new GSlider(this, 348, 240, 100, 36, 10.0);
slider2.setLimits(0.5, 0.0, 1.0);
slider2.setNumberFormat(G4P.DECIMAL, 2);
slider2.setOpaque(false);
slider2.addEventHandler(this, "slider2_change1");
}
// Variable declarations
// autogenerated do not edit
GTextField textfield1;
GTextField textfield2;
GTextArea textarea1;
GTextArea textarea2;
GSlider slider1;
GSlider slider2;
There are some problems with above constructions.
You do recursive move() method inside draw() method. But in Processing draw() is called many times in each second by animation thread.
Common desing for such cases is:
you should have variables that hold application state (logical state)
what your draw() method draws depends only on state
state may be modified by animation thread or by any other thread
I suggest changing your code a little:
First - state variables:
// 1 - display status, wait to enter values
// 2 - check if x and y are correct
// 3 - solve problem
int state=1;
boolean solutionExists=false;
public void setup() {
...
}
next draw() method:
void draw() {
counter=counter+1;
background(0,128,128);
String coords = "(" + x + "," + y + ")";
if (state == 1) {
if(solutionExists) {
textarea1.setText("Congratulations solution is possible " + coords);
} else {
textarea1.setText("Solution is not possible,enter other coordinates " +coords);
}
return;
}
if (state == 2) {
readXY();
return;
}
if (state == 3) {
println("find solution for: " + coords);
solutionExists = move(x,y,0);
state = 1;
return;
}
}
public void readXY() {
try {
x = Integer.parseInt(textfield1.getText().trim());
y = Integer.parseInt(textfield2.getText().trim());
state = 3;
} catch(Exception e) {
state = 1;
}
}
and finally textfields handlers:
public void tf1(GTextField source, GEvent event) {
if (event.getType().equals("LOST_FOCUS")) {
state=2;
}
}
public void tf2(GTextField source, GEvent event) {
if (event.getType().equals("LOST_FOCUS")) {
state=2;
}
}
As you can see:
if state==1 - draw() only updates message
if state==2 - draw() checks if x and y are valid, if valid -> change state to 3
if state==3 - draw() performs recursive algo, update solutionExists variable, change state to 1
Anytime when your textfield1 or textfield2 loose focus, it changes state to 2.
draw() is driven only by application state.
application state is modified by other events.
For best results, recursive algo should be performat in another thread, not in animation thread.
One fine note: when you edit textfield it may contains string such as "" (empty) or " 3" (leading space) or " 3 " etc - such text cannot be parsed with Integer.parseInt - you need to trim such text and be sure that NumberFormatException is not thrown - see readXY() method.
I am trying to develop a hex editor in which the panel for editor is provided with key listeners and the input through keyboard is converted into corresponding input. The problem however is regarding the saving the coverted input.only one key stroke value is converted at a time as for now. I would like to use this converted input() in a string as a bunch and use it for other purposes. I tried to save converted text in a byte array but it is returning the first value I typed irrespective of what the input afterwards is.
package gui.hex;
import javax.swing.*;
import cryptool.Test;
import java.awt.*;
import java.awt.event.*;
import java.nio.charset.Charset;
import java.nio.charset.CharsetEncoder;
public class JHexEditorASCII extends JComponent implements MouseListener,
KeyListener {
private static final long serialVersionUID = 5636121664420538046L;
private JHexEditor he;
private static CharsetEncoder encoder = Charset.forName("UTF-8")
.newEncoder();
public static String modifiedText;
public static byte temp[];
public static byte[] getTemp() {
return temp;
}
public void setTemp(byte[] temp) {
this.temp = temp;
}
protected JHexEditorASCII(JHexEditor he) {
this.he = he;
addMouseListener(this);
addKeyListener(this);
addFocusListener(he);
}
public Dimension getPreferredSize() {
debug("getPreferredSize()");
return getMinimumSize();
}
public Dimension getMinimumSize() {
debug("getMinimumSize()");
Dimension d = new Dimension();
FontMetrics fn = getFontMetrics(JHexEditor.font);
int h = fn.getHeight();
int nl = he.getLines();
d.setSize((fn.stringWidth(" ") + 1) * (16) + (he.border * 2) + 1, h
* nl + (he.border * 2) + 1);
return d;
}
public void paint(Graphics g) {
debug("paint(" + g + ")");
debug("cursor=" + he.cursor + " buff.length=" + he.buff.length);
Dimension d = getMinimumSize();
// sets the color to the background.
g.setColor(Color.orange);
g.fillRect(0, 0, d.width, d.height);
g.setColor(Color.black);
g.setFont(JHexEditor.font);
// ascii data
int ini = he.getInitial() * 16;
int fin = ini + (he.getLines() * 16);
if (fin > he.buff.length)
fin = he.buff.length;
int x = 0;
int y = 0;
for (int n = ini; n < fin; n++) {
if (n == he.cursor) {
// sets color for the focus cursor it used to be in blue color.
g.setColor(Color.red);
if (hasFocus())
he.background(g, x, y, 1);
else
he.table(g, x, y, 1);
if (hasFocus())
g.setColor(Color.white);
else
g.setColor(Color.black);
} else {
g.setColor(Color.black);
}
// builds a character object
String s;
if (encoder.isLegalReplacement(new byte[] { he.buff[n] }))
s = "" + new Character((char) he.buff[n]);
else
s = ".";
// compares the input supplied
// if ((he.buff[n] < 20) || (he.buff[n] > 126))
// converts the input entered into string
// s = ".";
// displaying of the text goes here.
// displays the input
System.out.println("the typed in string is:" + s);
temp = s.getBytes();
setTemp(temp);
setModifiedText(s);
he.printString(g, s, (x++), y);
if (x == 16) {
x = 0;
y++;
}
}
}
private void debug(String s) {
if (he.DEBUG)
System.out.println("JHexEditorASCII ==> " + s);
}
public void dispaly(Graphics g) {
int x = 0;
int y = 0;
he.printString(g, Test.getK(), (x++), y);
if (x == 16) {
x = 0;
y++;
}
}
// calculate the position of the mouse
public int calculateMousePosition(int x, int y) {
FontMetrics fn = getFontMetrics(JHexEditor.font);
x = x / (fn.stringWidth(" ") + 1);
y = y / fn.getHeight();
debug("x=" + x + " ,y=" + y);
return x + ((y + he.getInitial()) * 16);
}
// mouselistener
public void mouseClicked(MouseEvent e) {
if (e.getClickCount() == 2) {
// double clicked
he.setNewTextListener.actionPerformed(new ActionEvent(this, 0,
"NEWASCII"));
}
debug("mouseClicked(" + e + ")");
he.cursor = calculateMousePosition(e.getX(), e.getY());
this.requestFocus();
he.repaint();
}
public void mousePressed(MouseEvent e) {
}
public void mouseReleased(MouseEvent e) {
}
public void mouseEntered(MouseEvent e) {
}
public void mouseExited(MouseEvent e) {
}
// KeyListener
public void keyTyped(KeyEvent e) {
debug("keyTyped(" + e + ")");
// only add content, if buffer is large enough
if (he.buff.length > he.cursor) {
he.buff[he.cursor] = (byte) e.getKeyChar();
if (he.cursor != (he.buff.length - 1))
he.cursor++;
// change this
// System.out.println( he.buff.toString());
he.repaint();
}
}
public void keyPressed(KeyEvent e) {
debug("keyPressed(" + e + ")");
he.keyPressed(e);
}
public void keyReleased(KeyEvent e) {
debug("keyReleased(" + e + ")");
}
public boolean isFocusTraversable() {
return true;
}
public static String getModifiedText() {
return modifiedText;
}
public void setModifiedText(String modifiedText) {
this.modifiedText = modifiedText;
}
}
develop a hex editor (encoder.isLegalReplacement...)
use JTextField with DocumentFilter, or easiest could be JFormatterTextField instead of paint chars by using paint() to JComponent
use paintComponent (instead of paint()) for Swing JComponents
add DocumentListener to the JTextField with DocumentFilter or JFormatterTextField
interesting way could be to built / prepare / create a ArrayList of hex () and to use AutoComplete JTextField
i'm posting a simple game code, written in java. It took my hours today to write this but now i'm stuck! The problem is, in the second level of this game (after failure or success) i can't see the red tiles. It works only the first time.
games logic:
it starts up with a 3x3 matrix and rebound the dimension of this matrix in case of success (testing the ability of memory, memorising the coordinates of red tiles in 1200 ms). So we show the red tiles first, than we check the estimations. If there became a wrong try, failure!. If it is a bigger matrix than 3x3, it gets smaller.
the code is a little bit long but just one class, so it is so easy yo execute it. If you have time i would be appreciate.
So there it goes:
package skeleton;
public class Memory extends JFrame implements ActionListener {
private static final long serialVersionUID = 5963518754230629235L;
private static int minDimX = 3, minDimY = 3;
private static int maxDimX = 15, maxDimY = 15;
private static int counter = 13;
private static int memoriseTime = 1200; // milliseconds
private static int memGridWidthX = 60;
private static int memGridWidthY = 60;
private JPanel centerPanel;
private JButton memTile;
private Random generator;
private int memGridDimX, memGridDimY, coef, numberOfMemTilesToGuess;
int[][] memTileCoordinates;
int[] randomNums;
Border grayBorder = LineBorder.createGrayLineBorder();
public Memory(int xDim, int yDim) {
waitALittleBit(1300);
memGridDimX = xDim;
memGridDimY = yDim;
coef = 3;
numberOfMemTilesToGuess = memGridDimX*memGridDimY / coef;
centerPanel = new JPanel();
centerPanel.setLayout(new GridLayout(memGridDimY, memGridDimX, 0, 0));
add(centerPanel, BorderLayout.CENTER);
System.out.println("int[" + memGridDimX + "][" + memGridDimY + "] array is created ");
randomNums = new int[numberOfMemTilesToGuess];
for (int i = 0 ; i < numberOfMemTilesToGuess ; i ++) {
System.out.println("> we are in for the "+ (i+1) +". time!");
int randomNum;
boolean randomNumberAlreadySelected = false;
do {
randomNum = calculateARandomNumber(memGridDimX * memGridDimY);
if (i != 0) { //for the first time, we don't need to compare any numbers
randomNumberAlreadySelected = isThisRandomNumberExistInAlreadyFoundRandomNumbersArray(randomNum, randomNums, i);
if (randomNumberAlreadySelected)
System.out.println("######## RECALCULATING RANDOM NUMBER !! ##########");
else
System.out.println("They are not equal, go on!");
}
} while (randomNumberAlreadySelected);
randomNums[i] = (Integer)randomNum;
}
//show the memory tiles
setMemTiles(randomNums, true);
waitALittleBit(memoriseTime);
//hide the memory tiles
setMemTiles(randomNums, false);
}
private int calculateARandomNumber(int limit) {
generator = new Random();
System.out.println("* Calculating random number which is smaller than " + memGridDimX * memGridDimY);
int randomNum = generator.nextInt() % (memGridDimX * memGridDimY);
System.out.println("- Calculated random number: " + randomNum);
if (randomNum < 0) {
System.out.println(".. it is negative, so we add: " + memGridDimX * memGridDimY);
randomNum += memGridDimX * memGridDimY;
}
System.out.println(".. and we add 1 to have a grid array between 1 and 12");
randomNum += 1;
System.out.println(".. and our new random number is: " + randomNum);
return randomNum;
}
private boolean isThisRandomNumberExistInAlreadyFoundRandomNumbersArray(int number, int[] numberArr, int numberArrSize) {
for (int j = 0 ; j < numberArrSize ; j ++) {
System.out.println("# Comparing random number: " + number + " and " + (j+1) + ". random number selected earlier: " + numberArr[j]);
if (number == numberArr[j])
return true;
}
return false;
}
private void setMemTiles(int[] randomNums, boolean showMemTiles) {
centerPanel.removeAll();
memTileCoordinates = new int[randomNums.length][2];
for (int i = 1 ; i <= memGridDimY ; i ++) {
for (int j = 1 ; j <= memGridDimX ; j ++) {
int rnX = -1;
int rnY = -1;
boolean isMemTile = false;
for (int k = 0 ; k < randomNums.length ; k ++) {
int rn = randomNums[k];
if (rn % memGridDimX == 0) {
rnY = rn / memGridDimX;
rnX = memGridDimX;
} else {
rnY = rn / memGridDimX + 1;
rnX = rn % memGridDimX;
}
if (i == 1 && j == 1 && !showMemTiles) { //do it once
System.out.println("********* ************");
System.out.println("Random label number: " + rn + " and it's position in the grid: " + rnX + "," + rnY);
memTileCoordinates[k][0] = rnX;
memTileCoordinates[k][1] = rnY;
System.out.println("> Memory Tiles coordinates: " + memTileCoordinates[k][0] + "," + memTileCoordinates[k][1]);
System.out.println("> Memory Tiles length: " + memTileCoordinates.length);
System.out.println("********* ************");
}
if (rnX == j && rnY == i)
isMemTile = true;
}
memTile = new JButton();
if (isMemTile) {
update(getGraphics());
if (showMemTiles) {
memTile.setBackground(Color.red);
System.out.println("%%%% PAINTING MEM TILES IN RED %%%%");
} else
memTile.setBackground(Color.white);
update(getGraphics());
} else
memTile.setBackground(Color.white);
if (!showMemTiles) // we listen actions after the memory tiles disappears
memTile.addActionListener(this);
centerPanel.add(memTile);
update(getGraphics());
}
}
setJPanelSettings();
}
private void setJPanelSettings() {
setSize(memGridDimX * memGridWidthX, memGridDimY * memGridWidthY);
setTitle("Memory :: " + memGridDimX + "x" + memGridDimY);
setResizable(false);
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
setVisible(true);
}
private void waitALittleBit(long waitingMillisSeconds) {
long t0 = System.currentTimeMillis();
long t1 ;
do {
t1 = System.currentTimeMillis();
} while (t1 - t0 < waitingMillisSeconds);
}
public static void main(String[] args) {
new Memory(minDimX,minDimY);
}
#Override
public void actionPerformed(ActionEvent e) {
System.out.println(">>> An action came >>>");
JButton memTile = (JButton) e.getSource();
Dimension size = memTile.getSize();
int chosenMemTileDimX = memTile.getX();
int chosenMemTileDimY = memTile.getY();
int chosenMemTilePosX = chosenMemTileDimX / size.width + 1; // we add 1 becausee we present our tile numbers as 1:1, 1:2, ... ( instead of 0:0,0:1, ... )
int chosenMemTilePosY = chosenMemTileDimY / size.height + 1;
System.out.println("Chosen Tile's x dimension: " + chosenMemTileDimX + " ans y dimension: " + chosenMemTileDimY);
System.out.println("Chosen Tile's width: " + size.width + " and height: " + size.height);
System.out.println("Chosen Tile's coordinates: " + chosenMemTilePosX + ", " + chosenMemTilePosY);
boolean tileIsMemTile = false;
System.out.println("Memory Tiles Coordinates: ");
for (int i = 0 ; i < memTileCoordinates.length ; i ++) {
int memTileDimX = memTileCoordinates[i][0];
int memTileDimY = memTileCoordinates[i][1];
System.out.println("x: " + memTileDimX + ", y: " + memTileDimY);
if (chosenMemTilePosX == memTileDimX && chosenMemTilePosY == memTileDimY)
tileIsMemTile = true;
}
if (tileIsMemTile) {
System.out.println("!!! Right Tile !!!");
memTile.setBackground(Color.red);
numberOfMemTilesToGuess -= 1;
System.out.println("It rest " + numberOfMemTilesToGuess + " tiles to guess");
} else {
System.out.println("!!! Wrong Tile !!!");
Icon falseTileIcon;
try {
falseTileIcon = new ImageIcon(getClass().getResource("wrong.png"));
if (falseTileIcon.getIconHeight() > 0)
memTile.setIcon(falseTileIcon);
} catch (Exception e1) {
memTile.setBackground(Color.black);
}
update(getGraphics()); // good trick!!
waitALittleBit(1000);
//TODO !!! FAILED IN LEVEL MESSAGE !!!
dispose();
if (memGridDimX == minDimX && ( memGridDimY == minDimY || memGridDimY == minDimY + 1))
new Memory(minDimX, minDimY);
else if (memGridDimX == memGridDimY)
new Memory(memGridDimX - 1, memGridDimY);
else
new Memory(memGridDimX, memGridDimY -1);
}
System.out.println(">>> Action processed >>>");
if (numberOfMemTilesToGuess == 0) {
System.out.println("\n END OF THE LEVEL");
System.out.println("Congratulations, you guessed all the tiles without error !! \n");
dispose();
//TODO !!!! SHOW INTERLEVEL INFORMATION !!!!
if (memGridDimX != maxDimX && memGridDimY != maxDimY) {
if (memGridDimX == memGridDimY)
new Memory(memGridDimX, memGridDimY + 1);
else
new Memory(memGridDimX + 1, memGridDimY);
} else
System.out.println("You have a really good memory my friend!");
}
}}
I used update(getGraphics()); many times, it was just for a test...
Thanks in advance.
You where told in your last posting to NOT use the update() method.
do
{
t1 = System.currentTimeMillis();
}
while (t1 - t0 < waitingMillisSeconds);
Also, never use a tight loop like that. Its just as bad as using Thread.sleep(...);
You where given suggestions in your last posting!
I think you can use LWJGL, which is a java game library.
https://www.lwjgl.org
Some of the issues may be due to the thread on which the various bit of code run. The first time through you are running on the "Main" thread, and to be completely correct calls to update the AWT/Swing GUI should be done using the "Event Dispatcher Thread".
The actionPerformed method is called from the "Event Dispatcher Thread" and so then the second time you call into the constructor for Memory you are in this thread.
Also, aside from the fact you have implemented a delay with a spin-loop, which is not efficient; you should not delay the "Event Dispatcher Thread".
See this short overview: http://www.javamex.com/tutorials/threads/swing_ui.shtml