How do I make the enemies of my game follow my character? - java

So I'm making a game where the enemies follow the player and the player kills them. How do I make the enemies' ImageViews follow the player.
I have tried some if sentences but I actually have no idea. I also searched everywhere but I only find other people doing it with Swing and I get really confused with a lot of things. I use Javafx btw.
public class Main extends Application{
private static final int HEIGHT = 720;
private static final int WIDTH = 1280;
Scene scene;
BorderPane root, htpLayout;
VBox buttons, paragraphs, images;
Button startButton, htpButton, htpReturnButton, leaderboardButton, exitButton;
Text gameName, paragraph1, paragraph2, paragraph3;
Pane gameLayout;
ImageView background;
Game game = new Game();
Player player = new Player();
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage window) throws Exception {
root = new BorderPane();
background = new ImageView("stick mob slayer background.png");
background.fitWidthProperty().bind(window.widthProperty());
background.fitHeightProperty().bind(window.heightProperty());
root.getChildren().add(background);
htpLayout = new BorderPane();
buttons = new VBox(15);
scene = new Scene(root, WIDTH, HEIGHT);
scene.getStylesheets().add("mobslayer/style.css");
gameName = new Text("Mob Slayer Unlimited");
gameName.setFont(Font.font("Complex", 50));
gameName.setFill(Color.WHITE);
root.setAlignment(gameName, Pos.CENTER_LEFT);
root.setTop(gameName);
startButton = new Button("Start Game");
startButton.setOnAction(e -> window.setScene(game.getScene()));
htpButton = new Button("How To Play");
htpButton.setOnAction(e -> scene.setRoot(htpLayout));
leaderboardButton = new Button("Leaderboard");
exitButton = new Button("Exit");
exitButton.setOnAction(e -> Platform.exit());
buttons.getChildren().addAll(startButton, htpButton, leaderboardButton, exitButton);
root.setCenter(buttons);
buttons.setAlignment(Pos.CENTER);
paragraphs = new VBox(30);
paragraph1 = new Text("Objektive\nNär spelet börjar kommer huvudkaraktären möta monster.\n"
+ "Ju längre in i spelet du kommer, ju fler och svårare monster dyker upp.\n"
+ "Ditt mål är att överleva så länge som möjligt.");
paragraph1.setFont(Font.font("Dubai", 13));
paragraph1.setFill(Color.BLACK);
paragraph2 = new Text("Movement\nAlla monster dras imot dig, så du måste akta dig.\n"
+ "Detta gör du med hjälp av piltangenterna.");
paragraph2.setFont(Font.font("Dubai", 13));
paragraph2.setFill(Color.BLACK);
paragraph3 = new Text("Special Effects\nDu kan också attackera tillbaka med en lätt attack(c)\n"
+ "eller med en specialattack(space) som dödar alla monster på skärmen.\n"
+ "Du kan dasha(x) för att röra dig snabbare åt ett håll.");
paragraph3.setFont(Font.font("Dubai", 13));
paragraph3.setFill(Color.BLACK);
paragraphs.getChildren().addAll(paragraph1, paragraph2, paragraph3);
htpReturnButton = new Button("Return");
htpReturnButton.setOnAction(e->scene.setRoot(root));
htpLayout.setBottom(htpReturnButton);
htpLayout.setAlignment(htpReturnButton,Pos.TOP_CENTER);
images = new VBox(30);
// Image image1 = new Image(new FileInputStream("resources\\cod zombies.jpg"));
// final ImageView image11 = new ImageView(image1);
// image11.setFitHeight(100);
// image11.setFitWidth(100);
// image11.setPreserveRatio(true);
//
// Image image2 = new Image(new FileInputStream("resources\\arrowkeys.png")) ;
// final ImageView image22 = new ImageView(image2);
// image22.setFitHeight(100);
// image22.setFitWidth(100);
// image22.setPreserveRatio(true);
//
// Image image3 = new Image(new FileInputStream("resources\\keys.png")) ;
// final ImageView image33 = new ImageView(image3);
// image33.setFitHeight(100);
// image33.setFitWidth(100);
// image33.setPreserveRatio(true);
//
// images.getChildren().addAll(image11, image22, image33);
//
paragraphs.setAlignment(Pos.TOP_LEFT);
htpLayout.setLeft(paragraphs);
htpLayout.setRight(images);
window.setTitle("Mob Slayer Unlimited");
window.setScene(scene);
window.setResizable(false);
window.show();
}
}
public class Game {
private static final int HEIGHT = 720;
private static final int WIDTH = 1280;
private Scene scene;
Pane root;
Text health, stamina, wave, kills;
int waveCounter = 1, killCounter = 0;
Button restartButton, pauseButton;
Line limitUp;
Player player = new Player();
Enemies enemy = new Enemies();
public Game() {
health = new Text(50, 30, "HP: " + player.getHealth());
health.setFont(Font.font("BankGothic Lt BT", 30));
health.setFill(Color.WHITE);
stamina = new Text(50, 80, "STAMINA: " + player.getStamina());
stamina.setFont(Font.font("BankGothic Lt BT", 30));
stamina.setFill(Color.WHITE);
wave = new Text(1050, 30, "WAVE: " + waveCounter);
wave.setFont(Font.font("BankGothic Lt BT", 30));
wave.setFill(Color.WHITE);
kills = new Text(1050, 80, "KILLS: " + killCounter);
kills.setFont(Font.font("BankGothic Lt BT", 30));
kills.setFill(Color.WHITE);
restartButton = new Button("RESTART");
restartButton.setFont(Font.font("BankGothic Lt BT", 30));
restartButton.setOnAction(e -> restart());
restartButton.setLayoutX(350);
restartButton.setLayoutY(20);
pauseButton = new Button("PAUSE");
pauseButton.setFont(Font.font("BankGothic Lt BT", 30));
pauseButton.setOnAction(e -> restart());
pauseButton.setLayoutX(650);
pauseButton.setLayoutY(20);
limitUp = new Line(0, 100, 1280, 100);
limitUp.setStroke(Color.WHITE);
root = new Pane(player.getSlayer(), limitUp, player.getSlayerHitbox(), health, stamina, wave, kills, restartButton, pauseButton, enemy.getEnemy());
root.setStyle("-fx-background-color: black");
enemy.enemyMovement();
movePlayerTo(WIDTH / 2, HEIGHT / 2);
scene = new Scene(root, WIDTH, HEIGHT);
scene.setOnKeyPressed(new EventHandler<KeyEvent>() {
#Override
public void handle(KeyEvent event) {
switch (event.getCode()) {
case W: player.goUp = true; break;
case S: player.goDown = true; break;
case A: player.goLeft = true; break;
case D: player.goRight = true; break;
case K: player.running = true; break;
}
}
});
scene.setOnKeyReleased(new EventHandler<KeyEvent>() {
#Override
public void handle(KeyEvent event) {
switch (event.getCode()) {
case W: player.goUp = false; break;
case S: player.goDown = false; break;
case A: player.goLeft = false; break;
case D: player.goRight = false; break;
case K: player.running = false; break;
}
}
});
AnimationTimer timer = new AnimationTimer() {
#Override
public void handle(long now) {
int dx = 0, dy = 0;
if (player.goUp) dy -= 2;
if (player.goDown) dy += 2;
if (player.goRight) dx += 2;
if (player.goLeft) dx -= 2;
if (player.running) { dx *= 2; dy *= 2; }
enemy.enemyMovement();
movePlayerBy(dx, dy);
}
};
timer.start();
}
public Scene getScene() {
return scene;
}
// I took this methods for movement from Github
public void movePlayerBy(int dx, int dy) {
if (dx == 0 && dy == 0) return;
final double cx = player.getSlayer().getBoundsInLocal().getWidth() / 2;
final double cy = player.getSlayer().getBoundsInLocal().getHeight() / 2;
double x = cx + player.getSlayer().getLayoutX() + dx;
double y = cy + player.getSlayer().getLayoutY() + dy;
movePlayerTo(x, y);
}
public void movePlayerTo(double x, double y) {
final double cx = player.getSlayer().getBoundsInLocal().getWidth() / 2;
final double cy = player.getSlayer().getBoundsInLocal().getHeight() / 2;
if (x - cx >= 0 &&
x + cx <= WIDTH &&
y - cy >= 0 &&
y + cy <= HEIGHT) {
player.getSlayer().relocate(x - cx, y - cy);
player.getSlayerHitbox().relocate(x - cx + 37, y - cy + 35);
}
}
public class Player {
private int health;
private int damage;
private int stamina;
private Image slayerImage;
private ImageView slayer;
private Rectangle slayerHitbox;
boolean running, goUp, goDown, goRight, goLeft;
public Player () {
health = 5;
damage = 1;
stamina = 5;
slayerImage = new Image("stick mob slayer.png", 100, 100, true, true);
slayer = new ImageView(slayerImage);
slayerHitbox = new Rectangle(10, 50);
}
public int getDamage() {
return damage;
}
public void setDamage(int damage) {
this.damage = damage;
}
public int getHealth() {
return health;
}
public void setHealth(int health) {
this.health = health;
}
public int getStamina() {
return stamina;
}
public void setStamina(int stamina) {
this.stamina = stamina;
}
public ImageView getSlayer() {
return slayer;
}
public Rectangle getSlayerHitbox() {
slayerHitbox.setFill(Color.TRANSPARENT);
return slayerHitbox;
}
}
public class Enemies {
private int health;
private int speed;
private Image enemyImage;
private ImageView enemy;
private Rectangle enemyHitbox;
Player player = new Player();
public Enemies () {
health = 1;
speed = 1;
enemyImage = new Image("stick enemy.png", 100, 100, true, true);
enemy = new ImageView(enemyImage);
enemyHitbox = new Rectangle(10, 50);
}
public int getHealth() {
return health;
}
public void setHealth(int health) {
this.health = health;
}
public int getSpeed() {
return speed;
}
public void setSpeed(int speed) {
this.speed = speed;
}
public ImageView getEnemy () {
return enemy;
}
public Rectangle getEnemyHitbox() {
enemyHitbox.setFill(Color.YELLOW);
return enemyHitbox;
}
}
This is everything I have done so far. I would appreciate any help. If possible I would like to know how to make the enemies appear from random spots of the borders of the screen as well. Thanks in advance.

you should try first something more simple like implementing A* path search algo or some grid with some units on it before trying todo a game and having such questions

Related

Java - Game is lagging

I am coding a little Asteroids game, but it seems to be lagging a little bit. I am using a swing.Timer in order to update my JFrame and display the graphics. I have two questions,
the first one being:
"Could the timer be the reason for the lags?" and the second one being:
"Is using a Timer the optimal way to handle game programming in Java, or is it not?"
When browsing the net, it seemed like everyone is using a Timer in order to handle animations, but I can't help but feel that it is a suboptimal way of doing this. Can someone pls explain this to me? Thank you in advance :)
Here is the code of my Timer, if it helps. First the Base class:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import javax.swing.*;
public class Base implements ActionListener {
// Attributes
protected static int cd = 3; // Length of Countdown in seconds
private int nrOfAsteroids = 10; // Amount of Asteroids spawned
protected static int fps = 60; // Frames-per-second
// Various variables and constants
protected static BufferedImage image;
protected static int height;
protected static int width;
protected static boolean colorMode = false;
// Variables needed for Key-register
protected static boolean isWpressed = false;
private boolean isQpressed = false;
private boolean isEpressed = false;
private boolean isSpacePressed = false;
private boolean stop = false; // TODO remove after game is finished
// Various complex-objects
private static Base b = new Base();
private Asteroid[] a = new Asteroid[nrOfAsteroids];
private JFrame frame;
private JButton start;
private JButton colorButton;
private JLabel dummy;
private JLabel gameLabel;
protected static JLabel screen = new JLabel();
private ImageIcon icon;
private Timer t;
private static Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
public static void main(String[] args) {
height = (int) (screenSize.height * 0.9);
width = (int) (screenSize.width * 0.9);
image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
screen.setSize(width, height);
b.frameSetup();
} // end main
private void frameSetup() {
// Frame Setup
frame = new JFrame("yaaasssss hemorrhoids");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().setBackground(Color.BLACK);
frame.setBounds((int) (screenSize.width * 0.05), (int) (screenSize.height * 0.03), width, height);
frame.setLayout(new GridBagLayout());
// creating a "color" button
colorButton = new JButton("CLASSIC");
GridBagConstraints cb = new GridBagConstraints();
cb.weightx = 1;
cb.weighty = 1;
cb.gridx = 2;
cb.gridy = 0;
cb.anchor = GridBagConstraints.FIRST_LINE_END;
cb.insets = new Insets(10, 0, 0, 10);
colorButton.setPreferredSize(new Dimension(100, 30));
frame.add(colorButton, cb);
// creating a "ASTEROIDS" Label
gameLabel = new JLabel("ASSTEROIDS");
GridBagConstraints gl = new GridBagConstraints();
gl.weightx = 1;
gl.weighty = 1;
gl.gridwidth = 3;
gl.gridx = 0;
gl.gridy = 1;
gl.anchor = GridBagConstraints.CENTER;
gl.fill = GridBagConstraints.BOTH;
gameLabel.setPreferredSize(new Dimension(100, 30));
gameLabel.setFont(gameLabel.getFont().deriveFont(60.0f));
gameLabel.setForeground(Color.WHITE);
gameLabel.setHorizontalAlignment(SwingConstants.CENTER);
frame.add(gameLabel, gl);
// Dummy Component
dummy = new JLabel();
GridBagConstraints dc = new GridBagConstraints();
dummy.setPreferredSize(new Dimension(100, 30));
dc.weightx = 1;
dc.weighty = 1;
dc.gridx = 0;
dc.gridy = 0;
frame.add(dummy, dc);
// creating a "start" button
start = new JButton("START");
GridBagConstraints sb = new GridBagConstraints();
sb.weightx = 1;
sb.weighty = 1;
sb.gridx = 1;
sb.gridy = 2;
sb.anchor = GridBagConstraints.PAGE_START;
sb.insets = new Insets(15, 0, 0, 0);
start.setPreferredSize(new Dimension(100, 30));
frame.add(start, sb);
// Implementing a function to the buttons
start.addActionListener(this);
colorButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if (colorButton.getText() == "CLASSIC") {
colorMode = true;
colorButton.setText("LSD-TRIP");
} else {
colorMode = false;
colorButton.setText("CLASSIC");
}
}
});
// Show Results
frame.setVisible(true);
}
private void addImage() {
// Implementing the Image
icon = new ImageIcon(image);
screen.setIcon(icon);
frame.add(screen);
}
protected void setWindowSize() {
width = frame.getBounds().width;
height = frame.getBounds().height;
screen.setSize(width, height);
}
#Override
public void actionPerformed(ActionEvent ae) {
// Cleaning the screen
frame.remove(start);
frame.remove(gameLabel);
frame.remove(colorButton);
frame.remove(dummy);
// Checking if Window has been resized, and acting according to it
setWindowSize();
// Creating the image
for (int i = 0; i < nrOfAsteroids; ++i) {
a[i] = new Asteroid();
}
gameStart();
}
private void gameStart() {
t = new Timer(1000/fps, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
clearScreen();
for (int i = 0; i < nrOfAsteroids; ++i) {
a[i].drawAsteroid();
}
// Managing Controlls
if (isWpressed) {}
if (isQpressed) { }
if (isEpressed) { }
if (isSpacePressed) { }
if (stop) { }
// Updating the screen
b.addImage();
}
});
t.setInitialDelay(0);
actions();
t.start();
}
private void actions() {
// Defining all the constants for more order when handling the actions
final int focus = JComponent.WHEN_IN_FOCUSED_WINDOW;
String move = "Movement started";
String noMove = "Movement stopped";
String shoot = "Shooting started";
String noShoot = "Shooting stopped";
String turnLeft = "Rotation left started";
String noTurnLeft = "Rotation left stopped";
String turnRight = "Rotation right started";
String noTurnRight = "Rotation right stopped";
String stopIt = "stop"; // TODO remove when game is finished
// Getting the input and trigger an ActionMap
screen.getInputMap(focus).put(KeyStroke.getKeyStroke("W"), move);
screen.getInputMap(focus).put(KeyStroke.getKeyStroke("released W"), noMove);
screen.getInputMap(focus).put(KeyStroke.getKeyStroke("SPACE"), shoot);
screen.getInputMap(focus).put(KeyStroke.getKeyStroke("released SPACE"), noShoot);
screen.getInputMap(focus).put(KeyStroke.getKeyStroke("Q"), turnLeft);
screen.getInputMap(focus).put(KeyStroke.getKeyStroke("released Q"), noTurnLeft);
screen.getInputMap(focus).put(KeyStroke.getKeyStroke("E"), turnRight);
screen.getInputMap(focus).put(KeyStroke.getKeyStroke("released E"), noTurnRight);
screen.getInputMap(focus).put(KeyStroke.getKeyStroke("S"), stopIt);
// Triggered ActionMaps perform an Action
screen.getActionMap().put(move, new AbstractAction() {
private static final long serialVersionUID = 1L;
#Override
public void actionPerformed(ActionEvent e) {
isWpressed = true;
} });
screen.getActionMap().put(noMove, new AbstractAction() {
private static final long serialVersionUID = 1L;
#Override
public void actionPerformed(ActionEvent e) {
isWpressed = false;
} });
screen.getActionMap().put(shoot, new AbstractAction() {
private static final long serialVersionUID = 1L;
#Override
public void actionPerformed(ActionEvent e) {
isSpacePressed = true;
} });
screen.getActionMap().put(noShoot, new AbstractAction() {
private static final long serialVersionUID = 1L;
#Override
public void actionPerformed(ActionEvent e) {
isSpacePressed = false;
} });
screen.getActionMap().put(turnLeft, new AbstractAction() {
private static final long serialVersionUID = 1L;
#Override
public void actionPerformed(ActionEvent e) {
isQpressed = true;
} });
screen.getActionMap().put(noTurnLeft, new AbstractAction() {
private static final long serialVersionUID = 1L;
#Override
public void actionPerformed(ActionEvent e) {
isQpressed = false;
} });
screen.getActionMap().put(turnRight, new AbstractAction() {
private static final long serialVersionUID = 1L;
#Override
public void actionPerformed(ActionEvent e) {
isEpressed = true;
} });
screen.getActionMap().put(noTurnRight, new AbstractAction() {
private static final long serialVersionUID = 1L;
#Override
public void actionPerformed(ActionEvent e) {
isEpressed = false;
} });
screen.getActionMap().put(stopIt, new AbstractAction() {
private static final long serialVersionUID = 1L;
#Override
public void actionPerformed(ActionEvent e) {
stop = true;
} });
} // end actions()
private void clearScreen() {
Graphics2D pen = image.createGraphics();
pen.clearRect(0, 0, Base.width, Base.height);
}
} // end class
Now the Asteroid class:
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Polygon;
public class Asteroid {
// Attributes
private int amountOfCornerPoints = 12;
private int size = 50;
private int rotationSpeed = 2;
private int movementSpeed = 3;
// Fields needed to construct the Asteroid
private Polygon asteroidShape;
private int xCenter = (int) (Math.random() * Base.width);
private int yCenter = (int) (Math.random() * Base.height);
private int[] y = new int[amountOfCornerPoints];
private int[] x = new int[amountOfCornerPoints];
private int[] random = new int[amountOfCornerPoints];
private int rmax = 20; //Das Maximum für r
private int rmin = -rmax; //Das Minimum für r
// Field needed to transport the Asteroid
private boolean transporting = false;
// Field needed to rotate the Asteroid
private int cornerAddition = 0;
// Fields needed to detect Collision
// Fields needed to determine the direction of the Asteroid
private int direction = (int) Math.round((Math.random()*7));
private int xMove = 0;
private int yMove = 0;
// Fields for determining the color of the Asteroid
private Color col;
private int red = 255;
private int green = 255;
private int blue = 255;
public Asteroid() {
// Activating colorMode
if (Base.colorMode == true) {
do {
red = (int) Math.round((Math.random()*127));
green = (int) Math.round((Math.random()*127));
blue = (int) Math.round((Math.random()*127));
} while (red < 64 && green < 64 && blue < 64); }
col = new Color(red, green, blue);
// Zufallszahlen Generator
for (int i = 0; i < random.length; ++i) {
random[i] = (int) (Math.random()*rmax + rmin); }
asteroidShape = new Polygon();
whichDirection();
}
protected void drawAsteroid() {
move();
rotate();
int degreeHolder;
int degrees;
for (int i = 0; i < amountOfCornerPoints; ++i) {
degreeHolder = i*(360/amountOfCornerPoints) + cornerAddition;
if (degreeHolder >= 360) {
degrees = degreeHolder - 360;
} else {
degrees = degreeHolder;
}
x[i] = getXvalue(size + random[i])[degrees];
y[i] = getYvalue(size + random[i])[degrees];
}
asteroidShape.invalidate();
asteroidShape = new Polygon(x, y, amountOfCornerPoints);
Graphics2D pen = Base.image.createGraphics();
pen.setColor(col);
pen.draw(asteroidShape);
pen.dispose();
}
private void rotate() {
cornerAddition += rotationSpeed;
if (cornerAddition >= 360)
cornerAddition = cornerAddition - 360;
}
private void move() {
detectTransport();
xCenter += xMove;
yCenter += yMove;
}
private void detectTransport() {
boolean transportImmunity = false;
if (xCenter <= -size || xCenter >= Base.width + size) {
if (transportImmunity == false)
transporting = !transporting;
transportImmunity = true;
transport();
}
if (yCenter <= -size || yCenter >= Base.height + size) {
if (transportImmunity == false)
transporting = !transporting;
transportImmunity = true;
transport();
}
}
private void transport() {
while (transporting) {
xCenter -= xMove;
yCenter -= yMove;
detectTransport();
}
}
private void whichDirection() {
switch (direction) {
case 0: // Gerade Oben
xMove = 0;
yMove = -movementSpeed;
break;
case 1: // Diagonal Oben-rechts
xMove = movementSpeed;
yMove = -movementSpeed;
break;
case 2: // Gerade rechts
xMove = movementSpeed;
yMove = 0;
break;
case 3: // Diagonal Unten-rechts
xMove = movementSpeed;
yMove = movementSpeed;
break;
case 4: // Gerade Unten
xMove = 0;
yMove = movementSpeed;
break;
case 5: // Diagonal Unten-links
xMove = -movementSpeed;
yMove = movementSpeed;
break;
case 6: // Gerade links
xMove = -movementSpeed;
yMove = 0;
break;
case 7: // Diagonal Oben-links
xMove = -movementSpeed;
yMove = -movementSpeed;
break;
}
} // end WhichDirection
private int[] getXvalue(int radius) {
int[] xPoint = new int[360];
for (int i = 0; i < 360; ++i) {
double xplus = Math.cos(Math.toRadians(i+1)) * radius;
xPoint[i] = (int) Math.round(xCenter + xplus); }
return xPoint;
}
private int[] getYvalue(int radius) {
int[] yPoint = new int[360];
for (int i = 0; i < 360; ++i) {
double yPlus = Math.sin(Math.toRadians(i+1)) * radius;
yPoint[i] = (int) Math.round(yCenter - yPlus); }
return yPoint;
}
}
PS.: My computer is most likely not the cause, since it can run a lot bigger games with at least 100fps
Edit: None of the other methods, as for example the rotate() method, is causing the lag, as I have already tried the entire code with only the most essential methods and the result was the same.
Edit2: Maybe its worth noting, that the lag actually is only barely noticeable. However, for a game as small as an Asteroids is, there really shouldn't be any lag, especially if it only runs on 60 fps.
Edit3: MRE is added
I would suggest an/fps-limiting approach instead because the lag that can happen in the game gets amplified by the strict time intervals of the Timer class. After you set the frame to be visible add the following code(or something like it):
long time = System.nanoTime();
while(!gameOver) {
long nTime = System.nanoTime();
float diff = (nTime - time) * 0.000000001f;
if(diff > 1.0f / fps) {
time = nTime;
// do rendering here and multiply any speeds or accelerations by diff
}
}

How do I make multiple balls drop from the top?

public class MovingBagView extends View {
private Bitmap bag[] = new Bitmap[2];
private int bagX;
private int bagY = 1000;
private int bagSpeed;
private Boolean touch = false;
private int canvasWidth, canvasHeight;
private int yellowX = 500, yellowY, yellowSpeed = -16;
private Paint yellowPaint = new Paint();
private int score;
private Bitmap backgroundImage;
private Paint scorePaint = new Paint();
private Bitmap life[] = new Bitmap[2];
public MovingBagView(Context context) {
super(context);
bag[0] = BitmapFactory.decodeResource(getResources(), R.drawable.bag1);
bag[1] = BitmapFactory.decodeResource(getResources(), R.drawable.bag2);
backgroundImage = BitmapFactory.decodeResource(getResources(), R.drawable.background);
yellowPaint.setColor(Color.YELLOW);
yellowPaint.setAntiAlias(false);
scorePaint.setColor(Color.BLACK);
scorePaint.setTextSize(40);
scorePaint.setTypeface(Typeface.DEFAULT_BOLD);
scorePaint.setAntiAlias(true);
life[0] = BitmapFactory.decodeResource(getResources(), R.drawable.heart);
life[1] = BitmapFactory.decodeResource(getResources(), R.drawable.heart_grey);
bagX = 10;
score = 0;
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvasWidth = canvas.getWidth();
canvasHeight = canvas.getHeight();
canvas.drawBitmap(backgroundImage, 0, 0, null);
int minBagX = bag[0].getWidth();
int maxBagX = canvasWidth - bag[0].getWidth() * 2;
bagX = bagX + bagSpeed;
if (bagX < minBagX) {
bagX = minBagX;
}
if (bagX >= maxBagX) {
bagX = maxBagX;
}
bagSpeed = bagSpeed + 2;
if (touch) {
canvas.drawBitmap(bag[1], bagX, bagY, null);
}
else {
canvas.drawBitmap(bag[0], bagX, bagY, null);
}
yellowY = yellowY - yellowSpeed;
if (hitBallChecker(yellowX, yellowY)) {
score = score + 10;
yellowY = -100;
}
if (yellowY < 0) {
yellowY = canvasHeight + 21;
yellowX = (int)Math.floor(Math.random() * (maxBagX - minBagX)) + maxBagX;
}
canvas.drawCircle(yellowX, yellowY, 15, yellowPaint);
canvas.drawText("Score : " + score, 20, 60, scorePaint);
canvas.drawBitmap(life[0], 500, 10, null);
canvas.drawBitmap(life[0], 570, 10, null);
canvas.drawBitmap(life[0], 640, 10, null);
}
public boolean hitBallChecker(int x, int y) {
if (bagY < y && y < (bagY + bag[0].getHeight()) && bagX < x && x < (bagX + bag[0].getWidth())) {
return true;
}
return false;
}
#Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
touch = true;
bagSpeed = -22;
}
return true;
}
}
I've figured out how to make the balls drop from the top of the screen. The code is supposed to make multiple yellow balls drop from the top of the screen, but only one yellow ball drops. Random yellow balls are supposed to drop from the top, and they drop from different positions. You can see the preview of it below:
To implement this, you should consider creating a custom object Ball
public class Ball{
public int x;
public int y;
public int speed;
public Ball(int x, int y, int speed){
this.x = x;
this.y = y;
this.speed = speed;
}
}
Then you can add multiple Balls in an ArrayList and in the draw() you iterate through every Ball in the array and do what you've been doing to one Ball with each.
for(int i = 0; i < balls.length(); i++){
Ball ball = balls.get(i);
ball.y -= ball.speed;
// check for collisions
// draw ball
}

Why doesn't libgdx button work every time?

I made a button, witch stops the game. The is a menu, where you can continue the game. But if the cam moves with the player, the button doesn't work any more. You can see it, but if you click on it nothing happens. If you come back to the "start position" of the cam, the button works again. But the InputProcessor is always the stage with the button.
public class PlayState extends State {
//Objects
private final GameStateManager gameStateManager;
private final State me;
private EntityManager entityManager;
private Player player;
private Texture background;
private Texture filter;
private BitmapFont font;
private Sound click, boost;
private Drug drug;
private Border border;
private House house;
//Constants
public static final int FIELD_SIZE_HEIGHT = 1000;
public static final int FIELD_SIZE_WIDTH = 500;
//Variables
private int collectedDrugs;
private boolean pause, renderLost;
private boolean boostSound;
//Button pause
private Stage stage;
private ImageButton button;
private Drawable drawable;
private Texture textureBtn;
public PlayState(GameStateManager gsm) {
super(gsm);
gameStateManager = gsm;
me = this;
entityManager = new EntityManager();
player = new Player(this, 100, 100);
border = new Border();
background = new Texture("bggame.png");
filter = new Texture("filter.png");
cam.setToOrtho(false, MinniMafia.WIDTH, MinniMafia.HEIGHT);
click = Gdx.audio.newSound(Gdx.files.internal("Click.mp3"));
boost = Gdx.audio.newSound(Gdx.files.internal("boost.mp3"));
drug = new Drug();
house = new House();
collectedDrugs = 0;
font = new BitmapFont();
entityManager.addEntity(player);
entityManager.addEntity(drug);
entityManager.addEntity(border);
entityManager.addEntity(house);
pause = false;
renderLost = false;
boostSound = false;
stage = new Stage();
textureBtn = new Texture("pausebtn.png");
drawable = new TextureRegionDrawable(new TextureRegion(textureBtn));
button = new ImageButton(drawable);
button.setPosition(cam.position.x + cam.viewportWidth/2 - 50, cam.position.y + cam.viewportHeight/2 - 50);
button.addListener(new ClickListener() {
#Override
public void clicked(InputEvent event, float x, float y) {
gameStateManager.set(new PauseState(gameStateManager, me));
}
});
stage.addActor(button);
Gdx.input.setInputProcessor(button.getStage());
}
#Override
protected void handleInput() {
if (Gdx.input.justTouched()) {
click.play(0.2f);
}
if (Gdx.input.isTouched()) {
player.setStop(true);
boostSound = false;
} else {
if (!boostSound) {
boost.play(0.2f);
boostSound = true;
}
player.setStop(false);
}
}
#Override
public void update(float dt) {
Gdx.input.setInputProcessor(stage);
if(Gdx.input.getInputProcessor() == stage){
System.out.println("All working");
}else{
System.out.println("Error");
}
if (!pause) {
handleInput();
entityManager.updateEntities(dt);
setCam();
button.setPosition(cam.position.x + cam.viewportWidth/2 - 60, cam.position.y + cam.viewportHeight/2 - 60);
if (drug.collides(player.getBounds())) {
entityManager.disposeEntity(drug);
player.setGotDrug(true);
}
if (border.collides(player.getBounds()) && !border.isOpen()) {
pause = true;
renderLost = true;
}
if (house.collides(player.getBounds()) && player.isGotDrug()) {
player.setGotDrug(false);
collectedDrugs++;
drug = new Drug();
entityManager.addEntity(drug);
}
} else if (renderLost = true) {
if (Gdx.input.isTouched()) {
gsm.set(new MenuState(gsm));
dispose();
}
}
}
#Override
public void render(SpriteBatch sb) {
sb.setProjectionMatrix(cam.combined);
sb.begin();
sb.draw(background, 0, 0);
entityManager.renderEntities(sb);
button.draw(sb, 10f);
font.draw(sb, "" + collectedDrugs, cam.position.x - cam.viewportWidth / 2 + 10, cam.position.y - cam.viewportHeight / 2 + 20);
if (renderLost) {
sb.draw(filter, cam.position.x - cam.viewportWidth / 2, cam.position.y - cam.viewportHeight / 2);
font.draw(sb, "LOST! SCORE:" + collectedDrugs, cam.position.x - 50, cam.position.y);
}
sb.end();
}
#Override
public void dispose() {
background.dispose();
entityManager.disposeAll();
click.dispose();
}
private void setCam() {
float camViewportHalfX = cam.viewportWidth * .5f;
float camViewportHalfY = cam.viewportHeight * .5f;
cam.position.x = player.getPosition().x;
cam.position.y = player.getPosition().y;
cam.position.x = MathUtils.clamp(cam.position.x, camViewportHalfX, FIELD_SIZE_WIDTH - camViewportHalfX);
cam.position.y = MathUtils.clamp(cam.position.y, camViewportHalfY, FIELD_SIZE_HEIGHT - camViewportHalfY);
cam.update();
}
public Drug getDrug() {
return drug;
}
public House getHouse() {
return house;
}
}
I really don't know where the problem is. Could you help me please?

How to keep generating rectangles and update them AnimationTimer?

The following code draws an intersection and adds a car, the car keeps moving until the end of its lane (since the light is red). I added the car in an ArrayList in order to keep generating cars and update them (to move). If I do cars.add(new Car()); inside the animation timer, it does not work. The car code generates a car at a random side (N,S,E,W) and with a random size. My question is, what can I write to let the code keep generating cars in an arraylist and updating them?
Simulator:
import java.util.ArrayList;
import javafx.animation.AnimationTimer;
import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.stage.Stage;
public class Simulator extends Application {
ArrayList<Car> cars;
TrafficLight[] trafficLights;
TrafficLight northTrafficLight, westTrafficLight, eastTrafficLight, southTrafficLight;
Group root;
Canvas canvas;
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage primaryStage) {
primaryStage.setTitle("Simulator");
root = new Group();
cars = new ArrayList<Car>();
cars.add(new Car());
canvas = new Canvas(800, 800);
trafficLights = new TrafficLight[4];
// TrafficLights
trafficLights[0] = new TrafficLight(185, 135, 100, 200, true, "N");
trafficLights[1] = new TrafficLight(135, 565, 200, 100, true, "W");
trafficLights[2] = new TrafficLight(565, 185, 200, 100, false, "E");
trafficLights[3] = new TrafficLight(565, 565, 100, 200, false, "S");
GraphicsContext gc = canvas.getGraphicsContext2D();
drawShapes(gc);
update();
root.getChildren().add(canvas);
Scene scene = new Scene(root, 800, 800);
primaryStage.setScene(scene);
primaryStage.show();
}
private void drawShapes(GraphicsContext gc) {
// Draw Intersection
gc.setLineWidth(10.0);
gc.strokeLine(250, 0, 250, 250);
gc.strokeLine(0, 250, 250, 250);
gc.strokeLine(550, 0, 550, 250);
gc.strokeLine(550, 250, 800, 250);
gc.strokeLine(250, 550, 250, 800);
gc.strokeLine(250, 550, 0, 550);
gc.strokeLine(550, 550, 550, 800);
gc.strokeLine(550, 550, 800, 550);
// Draw Cars
for (int i = 0; i < cars.size(); i++) {
root.getChildren().add(cars.get(i).drawCar());
}
// Draw Traffic light
for (int i = 0; i < trafficLights.length; i++) {
root.getChildren().add(trafficLights[i].drawTL());
root.getChildren().add(trafficLights[i].drawRedCircle());
root.getChildren().add(trafficLights[i].drawGreenCircle());
}
}
private void update() {
AnimationTimer timer = new AnimationTimer() {
#Override
public void handle(long arg0) {
// TODO Auto-generated method stub
for (int i = 0; i < cars.size(); i++) {
String side = cars.get(i).getSide();
if (side == "N") {
if (cars.get(i).getYPosition() > 224) {
cars.get(i).stopCar();
} else {
// car = new Car(trafficLights[0]);
cars.get(i).incrementYPosition();
cars.get(i).drawCar();
}
} else if (side == "S") {
if (cars.get(i).getYPosition() < 550) {
cars.get(i).stopCar();
} else {
// car = new Car(trafficLights[0]);
cars.get(i).decrementYPosition();
cars.get(i).drawCar();
// System.out.println(car.getYPosition());
}
} else if (side == "W") {
if (cars.get(i).getXPosition() > 224) {
cars.get(i).stopCar();
} else {
// car = new Car(trafficLights[0]);
cars.get(i).incrementXPosition();
cars.get(i).drawCar();
}
} else {
if (cars.get(i).getXPosition() < 555) {
cars.get(i).stopCar();
} else {
// car = new Car(trafficLights[0]);
cars.get(i).decrementXPosition();
cars.get(i).drawCar();
// System.out.println(car.getXPosition());
}
}
}
System.out.println(cars.size());
}
};
timer.start();
}
}
Car:
import java.util.concurrent.ThreadLocalRandom;
import javafx.scene.shape.Rectangle;
public class Car {
int size;
int xposition;
int yposition;
int position;
TrafficLight TrfcLight;
String side;
Rectangle car;
public Car() {
car = new Rectangle();
size = ThreadLocalRandom.current().nextInt(25, 75 + 1);
position = ThreadLocalRandom.current().nextInt(0, 3 + 1);
switch(position) {
case 0: side = "N";
break;
case 1: side = "S";
break;
case 2: side = "W";
break;
case 3: side = "E";
break;
default: side = "N";
break;
}
if(side =="N") {
xposition = ThreadLocalRandom.current().nextInt(250-size, 550 -size + 1);
yposition = 0;
}else if(side =="S"){
xposition = ThreadLocalRandom.current().nextInt(250-size, 550 -size + 1);
yposition = 800-size/2;
}else if(side == "W") {
xposition = 0;
yposition = ThreadLocalRandom.current().nextInt(250-size, 550 -size + 1);
}else {
xposition = 800-size/2;
yposition = ThreadLocalRandom.current().nextInt(250-size, 550 -size + 1);
}
}
public Rectangle drawCar() {
car.setX(xposition);
car.setY(yposition);
car.setWidth(size/2);
car.setHeight(size/2);
return car;
}
public void stopCar() {
car.setX(xposition);
car.setY(yposition);
}
public int getXPosition() {
return xposition;
}
public int getYPosition() {
return yposition;
}
public int getSize() {
return size;
}
public String getSide() {
return side;
}
public void incrementXPosition() {
xposition+=2;
}
public void incrementYPosition() {
yposition+=2;
}
public void decrementXPosition() {
xposition-=2;
}
public void decrementYPosition() {
yposition-=2;
}
}
TrafficLight:
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.scene.shape.Rectangle;
public class TrafficLight {
int x, y, width, height;
Rectangle trafficLight;
Circle red, green;
Color color;
boolean solution;
String side;
public TrafficLight() {
trafficLight = new Rectangle();
red = new Circle();
green = new Circle();
}
public TrafficLight(int x, int y, int width, int height, boolean solution, String side) {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
this.solution = solution;
this.side = side;
trafficLight = new Rectangle();
red = new Circle();
green = new Circle();
}
public Rectangle drawTL() {
trafficLight.setX(x);
trafficLight.setY(y);
trafficLight.setWidth(width/2);
trafficLight.setHeight(height/2);
trafficLight.setFill(Color.TRANSPARENT);
trafficLight.setStroke(Color.BLACK);
trafficLight.setStrokeWidth(5);
return trafficLight;
}
public Circle drawRedCircle() {
if(width < height) {
red.setCenterX(trafficLight.getX()+(trafficLight.getHeight()/4));
red.setCenterY(trafficLight.getY()+(trafficLight.getHeight()/4));
red.setRadius(trafficLight.getHeight()/7);
if(solution) {
red.setFill(Color.TRANSPARENT);
red.setStroke(Color.BLACK);
red.setStrokeWidth(2);
side = "N";
color = Color.TRANSPARENT;
}else {
red.setFill(Color.RED);
red.setStroke(Color.BLACK);
red.setStrokeWidth(2);
side ="S";
color = Color.RED;
}
}else{
red.setCenterX(trafficLight.getX()+(trafficLight.getHeight()/2));
red.setCenterY(trafficLight.getY()+(trafficLight.getHeight()/2));
red.setRadius(trafficLight.getWidth()/7);
if(solution) {
red.setFill(Color.TRANSPARENT);
red.setStroke(Color.BLACK);
red.setStrokeWidth(2);
side = "W";
color = Color.TRANSPARENT;
}else {
red.setFill(Color.RED);
red.setStroke(Color.BLACK);
red.setStrokeWidth(2);
side = "E";
color = Color.RED;
}
}
return red;
}
public Circle drawGreenCircle() {
if(width < height) {
green.setCenterX(red.getCenterX());
green.setCenterY(red.getCenterY()+50);
green.setRadius(trafficLight.getHeight()/7);
if(solution) {
green.setFill(Color.RED);
green.setStroke(Color.BLACK);
green.setStrokeWidth(2);
color = Color.RED;
}else {
green.setFill(Color.TRANSPARENT);
green.setStroke(Color.BLACK);
green.setStrokeWidth(2);
color = Color.TRANSPARENT;
}
}else {
green.setCenterX(red.getCenterX()+50);
green.setCenterY(red.getCenterY());
green.setRadius(trafficLight.getWidth()/7);
if(solution) {
green.setFill(Color.RED);
green.setStroke(Color.BLACK);
green.setStrokeWidth(2);
color = Color.RED;
}else {
green.setFill(Color.TRANSPARENT);
green.setStroke(Color.BLACK);
green.setStrokeWidth(2);
color = Color.TRANSPARENT;
}
}
return green;
}
public String getSide() {
return side;
}
public Color getColor() {
return color;
}
}
To add cars dynamically to your array list, you can place the below code at the end of your start() method. The below code adds a new car (for 10 times) every 3 seconds. I verified with your demo and it is working.
Timeline tl = new Timeline(new KeyFrame(Duration.millis(3000), ae -> {
Car car=new Car();
cars.add(car);
root.getChildren().add(car.drawCar());
}));
tl.setCycleCount(10);
tl.play();

Drawing curve bit by bit

I need to draw a curve, knowing that I receive points every x milliseconds or x seconds, and that the curve is moving to the left by one pixel each time I receive a new point. I'm using the Bezier algorithm to draw the curve from the points I receive, so I need at least three points to start. I would like to know how to proceed to draw the curve bit by bit on an image.
This is what I'm doing right now:
int xPos = 0;
Point2D.Double[] points = new Point2D.Double[listYpos.size()];
for (int i = 0; i < listYpos.size(); i++) {
points[i] = new Point2D.Double(i, listYpos.get(i));
}
if (curveImg == null) {
curveImg = gc.createCompatibleImage(imageWidth, imageHeight, Transparency.BITMASK);
}
if (points.length > 3) {
Graphics2D gImg = (Graphics2D) curveImg.getGraphics();
renderCurve(gImg, Arrays.copyOfRange(points, listYpos.size() - 4, listYpos.size() - 1));
gImg.dispose();
}
AffineTransform at = g.getTransform();
at.scale(-1, 1);
at.translate(-xPos++, listYpos.get(listYpos.size() - 1));
g.drawImage(curveImg, at, null);
This method is called each time a new point is received every x milliseconds or x seconds.
I think that gImg.dispose();
maybe this code can help you with that (from old.forums.sun.com)
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import java.util.ArrayList;
import javax.swing.*;
public class BezierTest {
private class Animator implements ActionListener {
private double distance = 0;
private boolean moveTo = true;
private ArrayList<Point2D> points = new ArrayList<Point2D>();
private double step = -1;
private double steps;
private Timer timer = new Timer(0, this);
#Override
public void actionPerformed(ActionEvent e) {
step++;
if (step <= steps) {
double t = step / steps;
Point2D newPoint = computeBezierPoint(new Point2D.Double(), t, curvePoints);
marks[marks.length - 1].setFrame(newPoint.getX() - 5, newPoint.getY() - 5, 10, 10);
points.add(newPoint);
if (moveTo) {
path.moveTo(newPoint.getX(), newPoint.getY());
moveTo = false;
} else {
path.lineTo(newPoint.getX(), newPoint.getY());
}
lines[3] = new Line2D.Double(computePointOnLine(lines[0], t), computePointOnLine(lines[1], t));
lines[4] = new Line2D.Double(computePointOnLine(lines[1], t), computePointOnLine(lines[2], t));
lines[5] = new Line2D.Double(computePointOnLine(lines[3], t), computePointOnLine(lines[4], t));
// The maximum distance encountered between the results of two calculation methods.
// newPoint from computeBezierPoint() the other via the lines method
distance = Math.max(distance, newPoint.distance(computePointOnLine(lines[5], t)));
demoComponent.repaint();
} else {
timer.stop();
animationButton.setEnabled(true);
if (distance > 0d) {
System.out.println("Maximum difference " + distance);
}
}
}
public void init() {
timer.stop();
animationButton.setEnabled(false);
steps = sliderStep.getValue();
step = -1;
distance = 0;
moveTo = true;
path = new Path2D.Double();
int sleepTime = (int) Math.round(1000d * sliderDuration.getValue() / steps);
timer.setDelay(sleepTime);
timer.setInitialDelay(0);
timer.start();
}
private Point2D computeBezierPoint(Point2D rv, double t,
Point2D... curve) {
if (rv == null) {
rv = new Point2D.Double();
} else {
rv.setLocation(0, 0);
}
int n = curve.length - 1;
double oneMinusT = 1.0 - t;
for (int index = 0; index < curve.length; index++) {
double multiplier = index == 0 || index == n ? 1 : StrictMath.min(n - index, index) * n;
multiplier *= StrictMath.pow(t, index) * StrictMath.pow(oneMinusT, n - index);
rv.setLocation(rv.getX() + multiplier * curve[index].getX(), rv.getY() + multiplier * curve[index].getY());
}
return rv;
}
private Point2D computePointOnLine(Line2D line, double t) {
return new Point2D.Double((line.getX2() - line.getX1()) * t + line.getX1(), (line.getY2() - line.getY1()) * t + line.getY1());
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new BezierTest().createGUI();
}
});
}
private final JButton animationButton = new JButton(new AbstractAction("Start animation") {
private static final long serialVersionUID = 1L;
#Override
public void actionPerformed(ActionEvent e) {
animator.init();
}
});
private final Animator animator = new Animator();
private Point2D[] curvePoints = new Point2D[]{new Point(10, 50), new Point(190, 10), new Point(190, 190), new Point(10, 150)};
private JComponent demoComponent = new JComponent() {
private static final long serialVersionUID = 1L;
{
setPreferredSize(new Dimension(400, 400));
addComponentListener(new ComponentAdapter() {
#Override
public void componentResized(ComponentEvent e) {
int w = getWidth();
int h = getHeight();
recalculateAfterResize(w, h);
}
});
}
#Override
protected void paintComponent(Graphics g) {
if (isVisible()) {
g.setColor(Color.WHITE);
g.fillRect(0, 0, getWidth(), getHeight());
super.paintComponent(g);
paintBezier(g);
}
}
};
private Line2D[] lines = new Line2D[6];
private final Ellipse2D[] marks;
private Path2D path;
private final JSlider sliderDuration = createSlider(1, 20, 2, "Duration in seconds", 9, 1);
private final JSlider sliderStep = createSlider(8, 128, 64, "Animation steps", 16, 1);
private Path2D totalCurve;
{
marks = new Ellipse2D[curvePoints.length + 1];
for (int index = 0; index < marks.length; index++) {
marks[index] = new Ellipse2D.Double();
}
}
private void createGUI() {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(demoComponent, BorderLayout.CENTER);
JToolBar toolBar = new JToolBar();
toolBar.add(animationButton);
toolBar.add(sliderStep);
toolBar.add(sliderDuration);
frame.add(toolBar, BorderLayout.PAGE_START);
frame.pack();
frame.setLocation(150, 150);
frame.setVisible(true);
}
private JSlider createSlider(int min, int max, int value, String title, int major, int minor) {
JSlider slider = new JSlider(min, max, value);
slider.setBorder(BorderFactory.createTitledBorder(title));
slider.setMajorTickSpacing(major);
// slider.setMinorTickSpacing(minor);
slider.setPaintLabels(true);
slider.setPaintTicks(true);
return slider;
}
private void paintBezier(Graphics g) {
Path2D path1 = this.path;
if (path1 != null) {
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
g2.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.setColor(Color.GREEN);
for (Shape mark : marks) {
g2.fill(mark);
}
g2.setStroke(new BasicStroke(2f));
g2.setColor(Color.BLACK);
for (Shape mark : marks) {
g2.draw(mark);
}
g2.setStroke(new BasicStroke(0f));
g2.draw(totalCurve);
g2.setStroke(new BasicStroke(1f));
g2.setColor(Color.RED);
g2.draw(path1);
g2.setStroke(new BasicStroke(.5f));
g2.setColor(Color.BLACK);
for (Line2D line : lines) {
if (line != null) {
g2.draw(line);
}
}
}
}
private void recalculateAfterResize(int w, int h) {
curvePoints = new Point2D[]{new Point2D.Double(10, h / 4.0), new Point2D.Double(w - 10, 10), new Point2D.Double(w - 10, h - 10), new Point2D.Double(10, h - h / 4.0)};
totalCurve = new Path2D.Double();
totalCurve.moveTo(curvePoints[0].getX(), curvePoints[0].getY());
totalCurve.curveTo(curvePoints[1].getX(), curvePoints[1].getY(), curvePoints[2].getX(), curvePoints[2].getY(), curvePoints[3].getX(), curvePoints[3].getY());
for (int index = 0; index < curvePoints.length; index++) {
marks[index].setFrame(curvePoints[index].getX() - 5, curvePoints[index].getY() - 5, 10, 10);
}
marks[marks.length - 1].setFrame(marks[0].getFrame());
for (int index = 0; index < curvePoints.length - 1; index++) {
lines[index] = new Line2D.Double(curvePoints[index], curvePoints[index + 1]);
}
lines[3] = null;
lines[4] = null;
lines[5] = null;
animator.init();
}
}

Categories

Resources