Delayed drawing of lines on JavaFX canvas - user-interface

I ran into a problem when trying to draw 2 lines on a JavaFX canvas. I'm trying to draw the first line and after 1 seconds the second one, but for example when I use Thread.sleep(1000) between the lines of code that draw the lines the program waits 1 second and then draws the lines simultaneously.
//AN EXAMPLE
GraphicsContext gc = canvas.getGraphicsContext2D();
drawLine(gc,50,50,120,120);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
drawLine(gc,120,120,150,30);
drawLine is the function that I use to draw on the canvas
void drawLine(GraphicsContext gc, double x1, double y1, double x2, double y2){
Affine prije = gc.getTransform();
double dx = x2 - x1, dy = y2 - y1;
double angle = Math.atan2(dy, dx);
int len = (int) Math.sqrt(dx * dx + dy * dy);
Transform transform = Transform.translate(x1, y1);
transform = transform.createConcatenation(Transform.rotate(Math.toDegrees(angle), 0, 0));
gc.setTransform(new Affine(transform));
gc.strokeLine(0, 0, len, 0);
gc.setTransform(prije);
}

One way is to use PauseTransition
.
import javafx.animation.PauseTransition;
import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.layout.HBox;
import javafx.scene.transform.Affine;
import javafx.scene.transform.Transform;
import javafx.stage.Stage;
import javafx.util.Duration;
public class TestingGround extends Application
{
HBox root = new HBox();
public static void main(String[] args)
{
launch(args);
}
#Override
public void start(Stage primaryStage)
{
primaryStage.setTitle("Drawing Operations Test");
Group root = new Group();
Canvas canvas = new Canvas(300, 250);
GraphicsContext gc = canvas.getGraphicsContext2D();
drawLine(gc, 50, 50, 120, 120);
PauseTransition wait = new PauseTransition(Duration.seconds(1));
wait.setOnFinished((e) -> {
drawLine(gc, 120, 120, 150, 30);
});
wait.play();
root.getChildren().add(canvas);
primaryStage.setScene(new Scene(root));
primaryStage.show();
}
void drawLine(GraphicsContext gc, double x1, double y1, double x2, double y2)
{
Affine prije = gc.getTransform();
double dx = x2 - x1, dy = y2 - y1;
double angle = Math.atan2(dy, dx);
int len = (int) Math.sqrt(dx * dx + dy * dy);
Transform transform = Transform.translate(x1, y1);
transform = transform.createConcatenation(Transform.rotate(Math.toDegrees(angle), 0, 0));
gc.setTransform(new Affine(transform));
gc.strokeLine(0, 0, len, 0);
gc.setTransform(prije);
}
}
Another route you can take is use Timeline.
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.scene.Scene;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.layout.HBox;
import javafx.scene.transform.Affine;
import javafx.scene.transform.Transform;
import javafx.stage.Stage;
import javafx.util.Duration;
public class TestingGround extends Application
{
HBox root = new HBox();
public static void main(String[] args)
{
launch(args);
}
#Override
public void start(Stage primaryStage)
{
List<List<Integer>> lineCoors = new ArrayList();
List<Integer> lineCoors1 = new ArrayList(Arrays.asList(50, 50, 150, 50));
List<Integer> lineCoors2 = new ArrayList(Arrays.asList(150, 50, 150, 200));
List<Integer> lineCoors3 = new ArrayList(Arrays.asList(150, 200, 50, 200));
List<Integer> lineCoors4 = new ArrayList(Arrays.asList(50, 200, 50, 50));
lineCoors.add(lineCoors1);
lineCoors.add(lineCoors2);
lineCoors.add(lineCoors3);
lineCoors.add(lineCoors4);
Canvas canvas = new Canvas(300, 250);
GraphicsContext gc = canvas.getGraphicsContext2D();
AtomicInteger counter = new AtomicInteger();
Timeline timeleine = new Timeline(new KeyFrame(Duration.seconds(1), (ActionEvent event) -> {
List<Integer> tempCoors = lineCoors.get(counter.getAndIncrement());
drawLine(gc, tempCoors.get(0), tempCoors.get(1), tempCoors.get(2), tempCoors.get(3));
}));
timeleine.setCycleCount(lineCoors.size());
timeleine.play();
primaryStage.setTitle("Drawing Operations Test");
root.getChildren().add(canvas);
primaryStage.setScene(new Scene(root));
primaryStage.show();
}
void drawLine(GraphicsContext gc, double x1, double y1, double x2, double y2)
{
Affine prije = gc.getTransform();
double dx = x2 - x1, dy = y2 - y1;
double angle = Math.atan2(dy, dx);
int len = (int) Math.sqrt(dx * dx + dy * dy);
Transform transform = Transform.translate(x1, y1);
transform = transform.createConcatenation(Transform.rotate(Math.toDegrees(angle), 0, 0));
gc.setTransform(new Affine(transform));
gc.strokeLine(0, 0, len, 0);
gc.setTransform(prije);
}
}

Related

How can i stop an element when it get the bounds of the screen in JavaFX?

I need to create an animation where there is a ball in the screen. I need to stop the ball one it gets the bound of the screen.
I've tried to use this solution:
boolean collision =
bullet.getBoundsInParent().getMaxX()>=View.getInstance().getXLimit() ||
bullet.getBoundsInLocal().getMaxY()>=View.getInstance().getYLimit();
In order to detect the collision, but it works only for a time! I've tried to relocate the ball by using the "relocate()" method, but when i class "getBoundsInParent().getMaxX()" it return the same value of the screen limit, and i can't restart the animation.
How can I solve the problem?
Since you did not provide any relevant code, I will use the example from here.
Replace
deltaX *= -1; and deltaY *= -1;
with
deltaX = 0;deltaY = 0;
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Bounds;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.stage.Stage;
import javafx.util.Duration;
public class GamePractice extends Application
{
public static Circle circle;
public static Pane canvas;
#Override
public void start(final Stage primaryStage)
{
canvas = new Pane();
final Scene scene = new Scene(canvas, 800, 600);
primaryStage.setTitle("Game");
primaryStage.setScene(scene);
primaryStage.show();
circle = new Circle(15, Color.BLUE);
circle.relocate(100, 100);
canvas.getChildren().addAll(circle);
final Timeline loop = new Timeline(new KeyFrame(Duration.millis(10), new EventHandler<ActionEvent>()
{
double deltaX = 3;
double deltaY = 3;
#Override
public void handle(final ActionEvent t)
{
circle.setLayoutX(circle.getLayoutX() + deltaX);
circle.setLayoutY(circle.getLayoutY() + deltaY);
final Bounds bounds = canvas.getBoundsInLocal();
final boolean atRightBorder = circle.getLayoutX() >= (bounds.getMaxX() - circle.getRadius());
final boolean atLeftBorder = circle.getLayoutX() <= (bounds.getMinX() + circle.getRadius());
final boolean atBottomBorder = circle.getLayoutY() >= (bounds.getMaxY() - circle.getRadius());
final boolean atTopBorder = circle.getLayoutY() <= (bounds.getMinY() + circle.getRadius());
if (atRightBorder || atLeftBorder) {
deltaX = 0;
deltaY = 0;
}
if (atBottomBorder || atTopBorder) {
deltaY = 0;
deltaX = 0;
}
}
}));
loop.setCycleCount(Timeline.INDEFINITE);
loop.play();
}
public static void main(final String[] args)
{
launch(args);
}
}

javafx: How to add an appropriate listener to an ensemble demo?

I'm new to javafx and browsed through the demos provided by oracle, especially I found this:
package ensemble.samples.graphics2d.images.imageoperator;
import javafx.application.Application;
import javafx.beans.InvalidationListener;
import javafx.beans.Observable;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.image.PixelWriter;
import javafx.scene.image.WritableImage;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
public class ImageOperationApp extends Application {
private SimpleDoubleProperty gridSize = new SimpleDoubleProperty(3.0);
private SimpleDoubleProperty hueFactor = new SimpleDoubleProperty(12.0);
private SimpleDoubleProperty hueOffset = new SimpleDoubleProperty(240.0);
private static void renderImage(WritableImage img, double gridSize, double hueFactor, double hueOffset) {
PixelWriter pw = img.getPixelWriter();
double w = img.getWidth();
double h = img.getHeight();
double xRatio = 0.0;
double yRatio = 0.0;
double hue = 0.0;
for (int y = 0; y < h; y++) {
for (int x = 0; x < w; x++) {
xRatio = x/w;
yRatio = y/h;
hue = Math.sin(yRatio*(gridSize*Math.PI))*Math.sin(xRatio*(gridSize*Math.PI))*Math.tan(hueFactor/20.0)*360.0 + hueOffset;
Color c = Color.hsb(hue, 1.0, 1.0);
pw.setColor(x, y, c);
}
}
}
public Parent createContent() {
StackPane root = new StackPane();
final WritableImage img = new WritableImage(200, 200);
gridSize.addListener((Observable observable) -> {
renderImage(img, gridSize.doubleValue(), hueFactor.doubleValue(), hueOffset.doubleValue());
});
hueFactor.addListener((Observable observable) -> {
renderImage(img, gridSize.doubleValue(), hueFactor.doubleValue(), hueOffset.doubleValue());
});
hueOffset.addListener((Observable observable) -> {
renderImage(img, gridSize.doubleValue(), hueFactor.doubleValue(), hueOffset.doubleValue());
});
renderImage(img, 3.0, 12.0, 240.0);
ImageView view = new ImageView(img);
root.getChildren().add(view);
return root;
}
#Override public void start(Stage primaryStage) throws Exception {
primaryStage.setScene(new Scene(createContent()));
primaryStage.show();
}
/** Java main for when running without JavaFX launcher
* #param args command line arguments
*/
public static void main(String[] args) { launch(args); }
}
1. This is selfcontained and runable.
2. In opposite to the container application for the demos, "ensemle.jar", which provides a "playground" with some sliders for the three SimpleDoubleProperties, here are no sliders cf. the screenshot of ensemble .
3. In order to get an idea how the event-handling with FX works (and to enjoy this nice application) I would like to add appropriate keylisteners to imitate the sliders.
I have no idea where to add the listeners and where to process the events fired by the keyboard, but guess, that there are missing only some lines of code.
Edit: I would be happy if I had a hint, where (and how) to insert a keylistener, so that typing "Y" would give me a "HelloWorld" in the console. I'm confident to do the rest myself.
Adjust your start method like this and you will get a message whenever you press the Y-key.
#Override public void start(Stage primaryStage) throws Exception {
Scene scene = new Scene(createContent());
scene.setOnKeyPressed(new EventHandler<KeyEvent>() {
#Override
public void handle(KeyEvent event) {
if(event.getCode()== KeyCode.Y){
System.out.println("got a Y");
}
}
});
primaryStage.setScene(scene);
primaryStage.show();
}
If you want to do sth else, I would suggest to look into all the setOn...-methods applicable for scene in the javadocs.

Javafx : How can I produce an animation with 3D path?

I'm new to JavaFX, and I encountered a problem when trying to deal with animation.
I know class PathTransition provides methods to move a node between two points along an arbitrary curve by class Path; but it seems that all the classes that are related to PathTransition, like Path and MoveTo and CubicCurveTo and including itself, can only work in the xy plane. What if I want to move a node in the yz plane or xz plane? I just can't find any information about it on the internet. Any advice would be appreciated.
As shown in Animation Basics, Animations, you can compose multiple kinds of Transition, including PathTransition, in a SequentialTransition or ParallelTransition. The approach is especially convenient when the equation of motion can be expressed in parametric form. Motion along a helix, shown below, uses a ParallelTransition to combine a PathTransition along a Circle with a Timeline along a line.
animation = new ParallelTransition(
createTransition(circle, arrow),
createTimeline(size / 2));
import javafx.animation.Animation;
import javafx.animation.Interpolator;
import javafx.animation.KeyFrame;
import javafx.animation.KeyValue;
import javafx.animation.ParallelTransition;
import javafx.animation.PathTransition;
import javafx.animation.PathTransition.OrientationType;
import javafx.animation.Timeline;
import javafx.animation.Transition;
import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.PerspectiveCamera;
import javafx.scene.Scene;
import javafx.scene.effect.Bloom;
import javafx.scene.input.MouseEvent;
import javafx.scene.input.ScrollEvent;
import javafx.scene.paint.Color;
import javafx.scene.paint.PhongMaterial;
import javafx.scene.shape.Box;
import javafx.scene.shape.Circle;
import javafx.scene.shape.Polygon;
import javafx.scene.shape.Shape;
import javafx.scene.shape.StrokeLineCap;
import javafx.scene.transform.Rotate;
import javafx.stage.Stage;
import javafx.util.Duration;
/**
* #see http://stackoverflow.com/a/37370840/230513
*/
public class Helix extends Application {
private static final double SIZE = 300;
private final Content content = Content.create(SIZE);
public void play() {
content.animation.play();
}
private static final class Content {
private static final Duration DURATION = Duration.seconds(4);
private static final Color COLOR = Color.AQUA;
private static final double WIDTH = 3;
private final Group group = new Group();
private final Rotate rx = new Rotate(0, Rotate.X_AXIS);
private final Rotate ry = new Rotate(0, Rotate.Y_AXIS);
private final Rotate rz = new Rotate(0, Rotate.Z_AXIS);
private final Box xAxis;
private final Box yAxis;
private final Box zAxis;
private final Shape circle;
private final Shape arrow;
private final Animation animation;
private static Content create(double size) {
Content c = new Content(size);
c.group.getChildren().addAll(c.arrow, c.circle,
c.xAxis, c.yAxis, c.zAxis);
c.group.getTransforms().addAll(c.rz, c.ry, c.rx);
c.group.setTranslateX(-size / 2);
c.group.setTranslateY(-size / 2);
c.group.setTranslateZ(size / 2);
c.rx.setAngle(35);
c.ry.setAngle(-45);
return c;
}
private Content(double size) {
xAxis = createBox(size, WIDTH, WIDTH);
yAxis = createBox(WIDTH, size, WIDTH);
zAxis = createBox(WIDTH, WIDTH, size);
circle = createCircle(size);
arrow = createShape();
animation = new ParallelTransition(
createTransition(circle, arrow),
createTimeline(size / 2));
}
private Circle createCircle(double size) {
Circle c = new Circle(size / 4);
c.setFill(Color.TRANSPARENT);
c.setStroke(COLOR);
return c;
}
private Box createBox(double w, double h, double d) {
Box b = new Box(w, h, d);
b.setMaterial(new PhongMaterial(COLOR));
return b;
}
private Shape createShape() {
Shape s = new Polygon(0, 0, -10, -10, 10, 0, -10, 10);
s.setStrokeWidth(WIDTH);
s.setStrokeLineCap(StrokeLineCap.ROUND);
s.setStroke(COLOR);
s.setEffect(new Bloom());
return s;
}
private Transition createTransition(Shape path, Shape node) {
PathTransition t = new PathTransition(DURATION, path, node);
t.setOrientation(OrientationType.ORTHOGONAL_TO_TANGENT);
t.setCycleCount(Timeline.INDEFINITE);
t.setInterpolator(Interpolator.LINEAR);
return t;
}
private Timeline createTimeline(double size) {
Timeline t = new Timeline();
t.setCycleCount(Timeline.INDEFINITE);
t.setAutoReverse(true);
KeyValue keyX = new KeyValue(group.translateXProperty(), size);
KeyValue keyY = new KeyValue(group.translateYProperty(), size);
KeyValue keyZ = new KeyValue(group.translateZProperty(), -size);
KeyFrame keyFrame = new KeyFrame(DURATION.divide(2), keyX, keyY, keyZ);
t.getKeyFrames().add(keyFrame);
return t;
}
}
#Override
public void start(Stage primaryStage) throws Exception {
primaryStage.setTitle("JavaFX 3D");
Scene scene = new Scene(content.group, SIZE * 2, SIZE * 2, true);
primaryStage.setScene(scene);
scene.setFill(Color.BLACK);
scene.setOnMouseMoved((final MouseEvent e) -> {
content.rx.setAngle(e.getSceneY() * 360 / scene.getHeight());
content.ry.setAngle(e.getSceneX() * 360 / scene.getWidth());
});
PerspectiveCamera camera = new PerspectiveCamera(true);
camera.setFarClip(SIZE * 6);
camera.setTranslateZ(-3 * SIZE);
scene.setCamera(camera);
scene.setOnScroll((final ScrollEvent e) -> {
camera.setTranslateZ(camera.getTranslateZ() + e.getDeltaY());
});
primaryStage.show();
play();
}
public static void main(String[] args) {
launch(args);
}
}
In this related example, the yellow shapes follow a Timeline animation comprised of rotations of the cube's orthogonal axes, while also following a PathTransition along the edges of a cube's face.
cube.setOnMouseMoved(new EventHandler<MouseEvent>() {
#Override
public void handle(final MouseEvent e) {
animation = new Timeline();
animation.getKeyFrames().addAll(
new KeyFrame(new Duration(2000),
new KeyValue(cube.rx.angleProperty(), e.getY()),
new KeyValue(cube.ry.angleProperty(), -e.getX()),
new KeyValue(cube.rz.angleProperty(), e.getY())
));
animation.play();
}
});
…
pathBackFaceTransition = new PathTransition();
pathBackFaceTransition.setPath(rectangleBackFace);
…
pathFrontFaceTransition = new PathTransition();
pathFrontFaceTransition.setPath(rectangleFrontFace);
…
public void play() {
pathBackFaceTransition.play();
pathFrontFaceTransition.play();
}
Finally, you can simulate motion along the x, y and z axes by using a KeyValue that targets the scale and translate properties. Referring again to Animation Basics, the following change to TimelineEvents creates the illusion of a 3-D shape moving to and fro.
//create a keyValue with factory: scaling the circle 2times
KeyValue keyValueX = new KeyValue(stack.scaleXProperty(), 2);
KeyValue keyValueY = new KeyValue(stack.scaleYProperty(), 2);
KeyValue keyTransX = new KeyValue(stack.translateXProperty(), 100);
KeyValue keyTransY = new KeyValue(stack.translateYProperty(), 100);
//create a keyFrame, the keyValue is reached at time 2s
Duration duration = Duration.millis(2000);
//one can add a specific action when the keyframe is reached
EventHandler<ActionEvent> onFinished = new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent t) {
//reset counter
i = 0;
}
};
KeyFrame keyFrame = new KeyFrame(duration, onFinished,
keyValueX, keyValueY, keyTransX, keyTransY);

fading in and fading out of an circle in javafx canvas

I would like to fade in and fadeout a circle in a javafx canvas.
I can move a circle from one part of the screen to another but i just can't seem to get this object to fade in and out.
Below is the code i used for moving a circle from one part of the screen to the other
public class AnimatedCircleOnCanvas extends Application {
public static final double W = 200; // canvas dimensions.
public static final double H = 200;
public static final double D = 20; // diameter.
#Override public void start(Stage stage) {
DoubleProperty x = new SimpleDoubleProperty();
DoubleProperty y = new SimpleDoubleProperty();
Timeline timeline = new Timeline(
new KeyFrame(Duration.seconds(0),
new KeyValue(x, 0),
new KeyValue(y, 0)
),
new KeyFrame(Duration.seconds(3),
new KeyValue(x, W - D),
new KeyValue(y, H - D)
)
);
timeline.setAutoReverse(true);
timeline.setCycleCount(Timeline.INDEFINITE);
final Canvas canvas = new Canvas(W, H);
AnimationTimer timer = new AnimationTimer() {
#Override
public void handle(long now) {
GraphicsContext gc = canvas.getGraphicsContext2D();
gc.setFill(Color.CORNSILK);
gc.fillRect(0, 0, W, H);
gc.setFill(Color.FORESTGREEN);
gc.fillOval(
x.doubleValue(),
y.doubleValue(),
D,
D
);
}
};
stage.setScene(
new Scene(
new Group(
canvas
)
)
);
stage.show();
timer.start();
timeline.play();
}
public static void main(String[] args) { launch(args); }
}
Your help is greatly appreciated
Animate a DoubleProperty for the opacity in values ranging from 1 to 0 in exactly the same way as you animated the properties for x and y, and then use Color.deriveColor(...) to set the color based on the changing property:
import javafx.animation.AnimationTimer;
import javafx.animation.KeyFrame;
import javafx.animation.KeyValue;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.beans.property.DoubleProperty;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
import javafx.util.Duration;
public class FadeCircleOnCanvas extends Application {
public static final double W = 200; // canvas dimensions.
public static final double H = 200;
public static final double D = 20; // diameter.
#Override public void start(Stage stage) {
DoubleProperty opacity = new SimpleDoubleProperty();
Timeline timeline = new Timeline(
new KeyFrame(Duration.seconds(0),
new KeyValue(opacity, 1)
),
new KeyFrame(Duration.seconds(3),
new KeyValue(opacity, 0)
)
);
timeline.setAutoReverse(true);
timeline.setCycleCount(Timeline.INDEFINITE);
final Canvas canvas = new Canvas(W, H);
AnimationTimer timer = new AnimationTimer() {
#Override
public void handle(long now) {
GraphicsContext gc = canvas.getGraphicsContext2D();
gc.setFill(Color.CORNSILK);
gc.fillRect(0, 0, W, H);
gc.setFill(Color.FORESTGREEN.deriveColor(0, 1, 1, opacity.get()));
gc.fillOval(
W/2,
H/2,
D,
D
);
}
};
stage.setScene(
new Scene(
new Group(
canvas
)
)
);
stage.show();
timer.start();
timeline.play();
}
public static void main(String[] args) { launch(args); }
}
In general, I prefer not to use a Canvas for this, and just to use Shape instances placed in a Pane. Then you can directly change the pre-defined properties of the Shape, or in many cases use specific pre-defined animations (TranslateTransition or FadeTransition for example).
Here's the same example using this technique:
import javafx.animation.FadeTransition;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.stage.Stage;
import javafx.util.Duration;
public class FadeCircleOnCanvas extends Application {
public static final double W = 200; // canvas dimensions.
public static final double H = 200;
public static final double D = 20; // diameter.
#Override public void start(Stage stage) {
Circle circle = new Circle(W/2, H/2, D, Color.FORESTGREEN);
FadeTransition fade = new FadeTransition(Duration.seconds(3), circle);
fade.setFromValue(1);
fade.setToValue(0);
fade.setAutoReverse(true);
fade.setCycleCount(Timeline.INDEFINITE);
Pane pane = new Pane(circle);
stage.setScene(
new Scene(
pane, W, H, Color.CORNSILK
)
);
stage.show();
fade.play();
}
public static void main(String[] args) { launch(args); }
}

Problems with moving in a 2d game using the Slick library

For some reason you just keep moving left and I can't figure out why. The keyboard input reading isn't the problem because moving in any other direction works perfectly. Ignore the isClipped() method as I'm not done with it yet. Thanks for the help.
main class
package Genisis;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import org.lwjgl.input.Mouse;
import org.newdawn.slick.*;
import org.newdawn.slick.state.*;
import org.newdawn.slick.tiled.TiledMap;
public class Play extends BasicGameState
{
int mouseX;
int mouseY;
Level testLevel;
boolean[][] blocked;
MainCharacter mc;
public Play(int state)
{
}
public void init(GameContainer gc, StateBasedGame sbg) throws SlickException
{
gc.setMouseCursor("res/sprites/Cursor.png", 0, 0);
try {
testLevel = new Level(0, 0, "res/maps/testmap.tmx");
} catch (FileNotFoundException e) {
System.out.println("Failed to load map.");
e.printStackTrace();
}
mouseX = Mouse.getX();
mouseY = gc.getHeight() - Mouse.getY();
mc = new MainCharacter(50, 50, new Image("res/sprites/mcg.png"));
}
public void render(GameContainer gc, StateBasedGame sbg, Graphics g) throws
SlickException
{
testLevel.render(mc.x, mc.y);
mc.render(mouseX, mouseY);
}
public void update(GameContainer gc, StateBasedGame sbg, int delta) throws
SlickException
{
mc.move(gc, testLevel);
mc.render(gc.getWidth()/2, gc.getHeight()/2);
testLevel.render(mc.x, mc.y);
}
public int getID()
{
return 1;
}
public void spawnMC(float spwnMCX, float spwnMCY)
{
testLevel.render(spwnMCX, spwnMCY);
testLevel.render(spwnMCX, spwnMCY);
}
public void spawnOC()
{
//todo
}
}
Player class
package Genisis;
import org.newdawn.slick.GameContainer;
import org.newdawn.slick.Image;
import org.newdawn.slick.Input;
import org.newdawn.slick.SlickException;
public class MainCharacter extends Player
{
public MainCharacter(float newX, float newY, Image newSprite) throws SlickException
{
sprite = newSprite;
x = newX;
y = newY;
}
public void move(GameContainer gc, Level map)
{
Input in = gc.getInput();
if(in.isKeyDown(Input.KEY_W))
if(map.isClipped(x, y + 1))
y += 1;
if(in.isKeyDown(Input.KEY_D))
if(map.isClipped(x + 1, y))
x -= 1;
if(in.isKeyDown(Input.KEY_S))
if(map.isClipped(x, y - 1))
y -= 1;
if(in.isKeyDown(Input.KEY_A));
if(map.isClipped(x - 1, y))
x += 1;
}
public void render(float mX, float mY)
{
float xDist = mX - (500 + (sprite.getWidth() / 2));
float yDist = mY - (250 + (sprite.getHeight() / 2));
double angleToTurn = Math.toDegrees(Math.atan2(yDist, xDist));
sprite.setRotation((float)angleToTurn);
sprite.draw(500, 250);
}
}
level class
package Genisis;
import org.newdawn.slick.Image;
import org.newdawn.slick.SlickException;
import org.newdawn.slick.SpriteSheet;
import org.newdawn.slick.tiled.TiledMap;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.util.Scanner;
public class Level
{
//height of background (in tiles)
public int height;
//width of background (in tiles)
public int width;
public boolean[][] clipped;
public TiledMap map;
public Level(int newHeight, int newWidth, String path) throws
FileNotFoundException, SlickException
{
map = new TiledMap(path);
clipped = new boolean[map.getHeight()][map.getWidth()];
for(int i = 0; i < map.getHeight(); i++)
for(int j = 0; i < map.getWidth(); i++)
{
if("true".equals(map.getTileProperty(map.getTileId(i, j,
0), "blocked", "false")))
clipped[i][j] = false;
}
}
//render map
public void render(float mcX, float mcY)
{
map.render((int)(mcX), (int)(mcY));
}
//return height of level (in pixels)
public int getHeight()
{
return map.getHeight();
}
//return width of level (in pixels)
public int getWidth()
{
return map.getWidth();
}
public boolean isClipped(float charX, float charY)
{
//return clipped[(int)(charX / 50)][(int)(charY / 50)];
return true;
}
}
Found the problem. There is an extra semicolon (it's always a semicolon -_-) after the if statement for moving left.
if(in.isKeyDown(Input.KEY_A));
if(map.isClipped(x - 1, y))
x += 1;

Resources