This question already has answers here:
Lambda this reference in java
(2 answers)
How can a Java lambda-expression reference itself?
(4 answers)
Closed 3 years ago.
I'm trying to add an event handler to a canvas which removes itself when a condition is fulfilled.
I tried doing this, but I'm getting an error which says the variable may have not been initialized.
EventHandler<MouseEvent> canvasHandler = e -> {
double x = e.getX();
double y = e.getY();
boolean last = false;
if (Math.abs(x - lastX) < 20f) x = lastX;
if (Math.abs(y - lastY) < 20f) y = lastY;
if (points.size() > 2) {
if (Math.abs(x - points.get(0).getKey()) < 20f && Math.abs(y - points.get(0).getValue()) < 20f) {
x = points.get(0).getKey();
y = points.get(0).getValue();
last = true;
}
}
points.add(new Pair<Double, Double>(x, y));
lastX = x;
lastY = y;
gc.lineTo(x, y);
if (!last)
gc.strokeOval(x - 5f, y - 5f, 10f, 10f);
else
canvas.removeEventHandler(MouseEvent.MOUSE_CLICKED, canvasHandler);
gc.stroke();
};
canvas.addEventHandler(MouseEvent.MOUSE_CLICKED, canvasHandler);
If you use an anonymous class instead of a lambda you can reference the EventHandler with this from inside the handle method:
EventHandler<MouseEvent> canvasHandler = new EventHandler<>() {
#Override public void handle(MouseEvent event) {
// handle event...
if (/* condition */) {
canvas.removeEventHandler(MouseEvent.MOUSE_CLICKED, this);
});
canvas.addEventHandler(MouseEvent.MOUSE_CLICKED, canvasHandler);
Related
I am making a custom 'gun' plugin for a minecraft server. My problem is that when attempting to detect where a projectile has landed, the locational difference between the projectile and the player being hit is too large to be detected by my headshot method. The only reason I am using a projectile trace for 'isHeadshot' is due to debugging trials.
This is my shoot method
public void shootGun(Player p) {
if (getFirearmAction().isDelayed(p))
return;
double shiftYaw = (p.getLocation().getYaw() + 180) * (Math.PI/180);
Vector shiftVec = new Vector(Math.cos(shiftYaw), 0.0D, Math.sin(shiftYaw)); //TODO: add bullet_spread
for (int i = 0; i < projectileInfo.getAmount(); i++) {
Projectile proj = (Projectile)p.getWorld().spawn(p.getEyeLocation().toVector().add(shiftVec.multiply(0.2D)).toLocation(p.getWorld()), getProjectileInfo().getProjectileClass());
proj.setVelocity(UtilMethods.getBulletVelocity(p).multiply(projectileInfo.getSpeed()));
proj.setShooter(p);
}
projectileInfo.playShootGunSound(p);
getFirearmAction().performAction(p);
}
This is the listener for a 'hit'
#EventHandler
public void onEntDamage(EntityDamageByEntityEvent event) {
if (event.getDamager() instanceof Projectile) {
Projectile p = (Projectile)event.getDamager();
if (p.getShooter() instanceof Player) {
Player player = (Player)p.getShooter();
Gun gun = UtilMethods.getGun(player);
if (gun != null) {
int damage = gun.getProjectileInfo().getDamage();
if (event.getEntity() instanceof Player) {
Player ent = (Player)event.getEntity();
if (UtilMethods.isHeadShot(ent, p))
damage *= 2;
}
event.setDamage(damage);
}
}
}
}
And finally, this is [isHeadshot, isInCuboid, and bulletVelocity] methods. The first two are substitute methods for trying to figure out a failed headshot detection... The getBulletVelocity method sets the correct velocity and direction of the projectile. (In this case I am working with Snowball.class)
public static boolean isHeadShot(Player victim, Projectile projectile) {
Location locA = new Location(victim.getWorld(), victim.getEyeLocation().getX() -0.5, victim.getEyeLocation().getY() - 0.5, victim.getEyeLocation().getZ() - 0.5);
Location locB = new Location(victim.getWorld(), victim.getEyeLocation().getX() +0.5, victim.getEyeLocation().getY() + 0.5, victim.getEyeLocation().getZ() + 0.5);
for (double i = 0; i < 256; i+=0.8D) {
System.out.println(projectile.getLocation() + " | " + victim.getLocation());
projectile.getLocation().add(projectile.getVelocity().normalize().multiply(i));
if (isInCuboid(locA, locB, projectile.getLocation())) {
System.out.println(i);
return true;
}
}
return false;
}
public static boolean isInCuboid(Location min, Location max, Location varying) {
double[] locs = new double[2];
locs[0] = min.getX();
locs[1] = max.getX();
Arrays.sort(locs);
if (varying.getX() > locs[1] || varying.getX() < locs[0])
return false;
locs[0] = min.getY();
locs[1] = max.getY();
Arrays.sort(locs);
if (varying.getY() > locs[1] || varying.getY() < locs[0])
return false;
locs[0] = min.getZ();
locs[1] = max.getZ();
Arrays.sort(locs);
if (varying.getZ() > locs[1] || varying.getZ() < locs[0])
return false;
return true;
}
public static Vector getBulletVelocity(Player shooter) {
double yaw = Math.toRadians((-shooter.getLocation().getYaw() - 90.0f));
double pitch = Math.toRadians(-shooter.getLocation().getPitch());
double x = Math.cos(pitch) * Math.cos(yaw);
double y = Math.sin(pitch);
double z = -Math.sin(yaw) * Math.cos(pitch);
Vector dirVec = new Vector(x, y, z).normalize();
return dirVec;
}
I would like some help since it seems that when the bullet causes damage, the bullet is already through the player's hitbox and can not be detected as a headshot anylonger. Any advice?
This is the locational difference. First location is projectile, second location is victim. However, for there to be a hit, the bullet must pass through the player at one point..
[08:53:22] [Server thread/INFO]: Location{world=CraftWorld{name=San_Andreas},x=2501.8249706725665,y=73.62000000476837,z=1681.0750064188326,pitch=0.0,yaw=0.0} | Location{world=CraftWorld{name=San_Andreas},x=2508.7144181513295,y=72.0,z=1671.9424013003206,pitch=0.3,yaw=-8.100003}
Listen for the ProjectileHitEvent and check if the projectile's y-coord is within a certain distance of the y-coord of the hit player's eye location (the x and z coords are irrelevant for determining a headshot on a player).
can someone help me?
I made a grid for my board. When I'm trying to get Point position of the square in the board, console returns only (0,0).
This is my point code:
public struct Point
{
public int X {get; set;}
public int Y {get; set;}
public Point(int x, int y){
this.X = x;
this.Y = y;
}
}
This is script where every square get a point in the grid when instantiated:
public Point GridPosition { get; set; }
public void Setup(Point gridPos, Vector3 worldPos)
{
this.GridPosition = gridPos;
transform.position = worldPos;
}
private void OnMouseDown(){
Debug.Log (GridPosition.X + ", "+ GridPosition.Y );
}
And this is my main script with Dictionary part:
public static Dictionary<Point,Grid> Tiles { get; set; }
void Start()
{
CreateLevel ();
}
void CreateLevel()
{
Tiles = new Dictionary<Point,Grid> ();
}
private void PlaceTilesColliders(Vector3 tileStart, float tileOffset){
for (int y = 0; y < 8; y++)
{
for (int x = 0; x < 8; x++)
{
TileCollider.GetComponent<Grid> ().Setup (new Point (x, y), new Vector3 (tileStart.x + (tileOffset * x), tileStart.y - (tileOffset * y), 0));
Tiles.Add (new Point (x, y), Instantiate(TileCollider).GetComponent<Grid>());
}
}
}
So, console return every time (0,0), don't matter which square was clicked.
Can someone explain me how to get true point position of the square in the grid?
Try Instantiate first, then configure the resulting new Grid and add to the dictionary.
for (int y = 0; y < 8; y++)
{
for (int x = 0; x < 8; x++)
{
GameObject newGrid = Instantiate(TileCollider);
newGrid.GetComponent<Grid>().Setup(new Point (x, y), new Vector3 (tileStart.x + (tileOffset * x), tileStart.y - (tileOffset * y), 0));
Tiles.Add(new Point (x, y), newGrid.GetComponent<Grid>());
}
}
I would recommend, though, that you pay attention to parenting, as right now the instantiated objects have no parent.
avariant is essentially correct with their answer, but I'd like to point out what your code is actually doing and why you're getting the values you're getting.
Lets look at this loop:
for (int y = 0; y < 8; y++) {
for (int x = 0; x < 8; x++) {
TileCollider.GetComponent<Grid> ().Setup (new Point (x, y), new Vector3 (tileStart.x + (tileOffset * x), tileStart.y - (tileOffset * y), 0));
Tiles.Add (new Point (x, y), Instantiate(TileCollider).GetComponent<Grid>());
}
}
We loop over Y and X (this is fine) and then we call TileCollider.GetComponent<Grid> (). Wait, hold on, TileCollider? What is this? This can't be one of our files in the scene, we haven't used our X and Y coordinates to go fetch a GameObject from the scene to get this reference...
That means anything we do to it has no effect on our tiles in the game world! And because the reference isn't updated, we continuously update it's values to the new X and Y positions, overwriting what we'd already done and having no effect on anything.
Oops.
And this is why avariant says that you need to call Instantiate and create a new tile, then get the component from that GameObject and call Setup() on it.
Im having trouble finding a null pointer exception in some lejos code, which is for the EV3 lego robot.
Below is the class state and constructor:
public class Mapper {
private LineMap CurrentMap;
private Line[] lines;
private boolean[] userDrawn;
private Rectangle boundary = new Rectangle(0, 0, 594, 891);
private int counter;
/**
* Initializes an empty map with just a boundary
*
* #author Ben
*/
public Mapper(){
counter = 0;
lines = new Line[counter];
userDrawn = new boolean[counter];
CurrentMap = new LineMap(lines,boundary);
}
And the function causing me grief
public void addLine(float x1, float y1, float x2, float y2, boolean isUserDrawn){
counter++;
Line[] oldLines = lines;
boolean[] oldUserDrawn = userDrawn;
lines = new Line[counter];
userDrawn = new boolean[counter];
for(int i = 0; i < counter - 1; i++){
lines[i] = oldLines[i];
userDrawn[i] = oldUserDrawn[i];
}
lines[counter-1] = new Line(x1,y1,x2,y2);
if(isUserDrawn == true){
userDrawn[counter - 1] = true;
}
else{
userDrawn[counter - 1] = false;
}
CurrentMap = new LineMap(lines,boundary);
}
Any ideas for what might be a source of a null pointer exception:
Dont worry, problem not in this code. And has been solved.
I have created wafermap chart. I want to make chips(die) in wafer selectable on mouse click and insert labels as well lines from one chip to another. Anyone expert in jfree chart?
wafermap chart
Here are the basic pieces for a tooltip listener for wafer maps, which is a form of selecting the die. Add the following to WaferMapPlot:
public String findChipAtPoint(double x, double y, Rectangle2D plotArea){
double[] xValues = this.getChipXValues(plotArea, dataset.getMaxChipX()
+ 2, dataset.getChipSpace());
double startX = xValues[1];
double chipWidth = xValues[0];
int ychips = this.dataset.getMaxChipY()+ 2;
double[] yValues = this.getChipYValues(plotArea, ychips,
dataset.getChipSpace());
double startY = yValues[1];
double chipHeight = yValues[0];
double chipSpace = dataset.getChipSpace();
int chipX = (int)Math.floor((x - startX + chipWidth + chipSpace) /
(chipWidth + chipSpace));
int chipY = (int)Math.floor((y - startY + chipHeight + chipSpace) /
(chipHeight + chipSpace));
chipX = chipX - dataset.getXOffset() - 1;
chipY = ychips - chipY - dataset.getYOffset() - 1;
StringBuilder sb = new StringBuilder("(");
Number value = dataset.getChipValue(chipX, chipY);
if (value instanceof Double)
value = value.intValue();
sb.append(chipX).append(",").append(chipY).append(") ").append(
(value == null) ? "" : value.toString());
return sb.toString();
}
Then make a subclass of ChartPanel that will be the listener:
public class WaferMapChartPanel extends ChartPanel {
WaferMapPlot waferPlot = null;
WaferMapDataset dataSet = null;
public WaferMapChartPanel(JFreeChart chart){
super(chart);
waferPlot = (WaferMapPlot)chart.getPlot();
if (waferPlot != null)
dataSet = waferPlot.getDataset();
}
/**
* Returns a string for the tooltip.
* #param e the mouse event.
* #return A tool tip or <code>null</code> if no tooltip is available.
*/
#Override
public String getToolTipText(MouseEvent e) {
if (waferPlot != null){
Object source = e.getSource();
if (source instanceof WaferMapChartPanel){
WaferMapChartPanel chartSource= (WaferMapChartPanel)e.getSource();
Rectangle2D plotArea = chartSource.getChartRenderingInfo().getPlotInfo().getPlotArea();
Insets insets = this.getInsets();
double x = (e.getX() - insets.left) / this.getScaleX();
double y = (e.getY() - insets.top) / this.getScaleY();
return waferPlot.findChipAtPoint(x, y, plotArea);
}
}
return "";
}
}
This creates a tooltip of the die's x,y and bin or whatever value you are using instead of bin.
I have a problem with zooming using javaFX and zooming. The items are wrapped in a group which is then scaled by the ZoomUtil. One node is animated to show the weird effect resulting: The Rectangles should stay within their original place and not constantly move around the frame.
I have no idea what causes this behaviour and tried many different transform settings and such but were not successful.
public class Test extends Application {
#Override
public void start(Stage primaryStage) {
List<Rectangle> rectangles = new ArrayList<>(5);
Color color = new Color(random(), random(), random(), 1);
Rectangle r = new Rectangle(200, 140,color);
r.relocate(-500,-500);
rectangles.add(r);
r = new Rectangle(200,140,color);
r.relocate(500, -500);
rectangles.add(r);
r = new Rectangle(200,140,color);
r.relocate(500, 500);
rectangles.add(r);
r = new Rectangle(200,140,color);
r.relocate(0, 0);
rectangles.add(r);
r = new Rectangle(200,140,color);
r.relocate(-500, 500);
rectangles.add(r);
Timeline timeline = new Timeline();
Node circle = r;
timeline.getKeyFrames().addAll(
new KeyFrame(Duration.seconds(10), // set start position at 0
new KeyValue(circle.translateXProperty(), random() * 8000),
new KeyValue(circle.translateYProperty(), random() * 6000)
),
new KeyFrame(new Duration(80000), // set end position at 40s
new KeyValue(circle.translateXProperty(), random() * 8000),
new KeyValue(circle.translateYProperty(), random() * 6000)
)
);
Group group = new Group();
group.setManaged(false);
group.getChildren().addAll(rectangles);
StackPane pane = new StackPane();
pane.setPrefWidth(500);
pane.setPrefHeight(500);
Scene scene = new Scene(pane);
pane.getChildren().add(group);
pane.setOnScroll(event -> ZoomUtil.zoom(group, event));
primaryStage.setScene(scene);
primaryStage.setWidth(500);
primaryStage.setHeight(500);
primaryStage.show();
timeline.play();
}
}
.
public class ZoomUtil {
/** Allow to zoom/scale any node with pivot at scene (x,y) coordinates.
*
* #param node
* #param x
* #param y
*/
public static void zoom(Node node, double factor, double x, double y) {
double oldScale = node.getScaleX();
double scale = oldScale * factor;
if (scale < 0.05) scale = 0.05;
if (scale > 50) scale = 50;
node.setScaleX(scale);
node.setScaleY(scale);
double f = (scale / oldScale) - 1;
/* Move view by translational difference */
Bounds bounds = node.localToScene(node.getBoundsInLocal());
double dx = (x - (bounds.getWidth() / 2 + bounds.getMinX()));
double dy = (y - (bounds.getHeight() / 2 + bounds.getMinY()));
node.setTranslateX(node.getTranslateX() - f * dx);
node.setTranslateY(node.getTranslateY() - f * dy);
}
public static void zoom(Node node, ScrollEvent event) {
zoom(node, Math.pow(1.002, event.getDeltaY()), event.getSceneX(), event.getSceneY());
}
public static void zoom(Node node, ZoomEvent event) {
zoom(node, event.getZoomFactor(), event.getSceneX(), event.getSceneY());
}
}