Firing a projectile in mouse direction in java - java

I'm trying to fire a projectile in the mouse direction but i am having trouble.
The angles are wrong, and by that I mean it will only go up left or in the top-left corner.
This is my Gun class for which I fire the Bullet.
package assets;
import Reaper.Game;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
public class Gun
{
public ArrayList<Bullet> bullets;
protected double angle;
Mouse mouse = new Mouse();
private BufferedImage image;
private int centerX = Game.WIDTH / 2;
private int centerY = Game.HEIGHT;
public Gun()
{
bullets = new ArrayList<Bullet>();
image = null;
try
{
image = ImageIO.read(new File("assets/gun.png"));
}
catch (IOException e)
{
e.printStackTrace();
}
}
public BufferedImage loadImage()
{
return image;
}
public int getImageWidth()
{
return image.getWidth(null);
}
public int getImageHeight()
{
return image.getHeight(null);
}
public void rotate(Graphics g)
{
angle = Math.atan2(centerY - mouse.getMouseY(), centerX - mouse.getMouseX()) - Math.PI / 2;
((Graphics2D) g).rotate(angle, centerX, centerY);
g.drawImage(image, Game.WIDTH / 2 - image.getWidth() / 2,
900 - image.getHeight(), image.getWidth(), image.getHeight(),
null);
}
public Image getImage()
{
return image;
}
public void update()
{
shoot();
for (int i = 0; i < bullets.size(); i++)
{
Bullet b = bullets.get(i);
b.update();
}
}
public void shoot()
{
if (mouse.mouseB == 1)
{
double dx = mouse.getMouseX() - Game.WIDTH / 2;
double dy = mouse.getMouseY() - Game.HEIGHT / 2;
double dir = Math.atan2(dy, dx);
bullets.add(new Bullet(Game.WIDTH / 2, Game.HEIGHT / 2, dir));
mouse.mouseB = -1;
}
}
public void render(Graphics g)
{
for (int i = 0; i < bullets.size(); i++)
{
bullets.get(i).render(g);
}
rotate(g);
}
}
This is my Bullet class:
package assets;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
public class Bullet
{
private double dx, dy;
private int x, y;
private double dir;
private BufferedImage image;
public Bullet(int x, int y, double angle)
{
this.x = x;
this.y = y;
this.dir = angle;
image = null;
try
{
image = ImageIO.read(new File("assets/bolt.png"));
}
catch (IOException e)
{
e.printStackTrace();
}
dx = Math.cos(dir);
dy = Math.sin(dir);
}
public void update()
{
x += dx;
y += dy;
System.out.println("dx : " + dx + " " + dy);
}
public void render(Graphics g)
{
g.drawImage(image, x, y, image.getWidth(), image.getHeight(), null);
}
public BufferedImage getImage()
{
return image;
}
}
And this is the main Game class:
package Reaper;
import Reaper.graphics.Screen;
import assets.Gun;
import assets.Mouse;
import gameState.MenuState;
import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferStrategy;
public class Game extends Canvas implements Runnable
{
private static final long serialVersionUID = 1L;
public static int WIDTH = 900;
public static int HEIGHT = 900;
public static int scale = 3;
public int frames = 0;
public int updates = 0;
private boolean running = false;
private Thread thread;
private JFrame frame;
#SuppressWarnings("unused")
private Screen screen;
private Gun gun;
private MenuState mns;
private Mouse mouse;
public Game()
{
Dimension size = new Dimension(WIDTH, HEIGHT);
setPreferredSize(size);
screen = new Screen(WIDTH, HEIGHT);
frame = new JFrame();
gun = new Gun();
mns = new MenuState();
mouse = new Mouse();
addMouseListener(mouse);
addMouseMotionListener(mouse);
}
public static void main(String[] args)
{
Game game = new Game();
game.frame.setResizable(false);
game.frame.add(game);
game.frame.pack();
game.frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
game.frame.setVisible(true);
game.frame.setLocationRelativeTo(null);
game.strat();
}
public void strat()
{
running = true;
thread = new Thread(this, "Reaper");
thread.start();
}
public void stop()
{
running = false;
try
{
thread.join();
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
public void run()
{
long timer = System.currentTimeMillis();
long lastTime = System.nanoTime();
double ns = 1000000000.0 / 60;
double delta = 0;
while (running)
{
long now = System.nanoTime();
delta += (now - lastTime) / ns;
lastTime = now;
while (delta >= 1)
{
update();
updates++;
delta--;
}
render();
frames++;
if (System.currentTimeMillis() - timer > 1000)
{
timer = System.currentTimeMillis();
frame.setTitle("Reaper! " + " | " + updates + " ups , " + frames + " fps");
updates = 0;
frames = 0;
}
}
stop();
}
public void update()
{
if (mns.play)
{
gun.update();
}
}
public void render()
{
BufferStrategy bs = getBufferStrategy();
if (bs == null)
{
createBufferStrategy(3);
return;
}
Graphics g = bs.getDrawGraphics();
g.fillRect(0, 0, WIDTH, HEIGHT);
if (mns.menu)
{
mns.draw(g);
}
if (mns.play)
{
g.clearRect(0, 0, WIDTH, HEIGHT);
g.drawImage(mns.getImage(), 0, 0, mns.getImageWidth(), mns.getImageHeight(), this);
gun.render(g);
}
if (mns.rules)
{
g.clearRect(0, 0, WIDTH, HEIGHT);
}
bs.show();
}
}
I know it's very badly coded, and I will try to fix it as much as I can, but I am really stuck on this. Searched around the web, tried some of the solutions but it wont work. I guess I'm doing it wrong by putting methods in wrong places and calling them, I guess.

I know it's very badly coded, and I will try to fix it as much as I can, ...
Next time, consider first cleaning up the mess and then asking the question.
(Are the variables storing the values returned by getMouseX() and getMouseY() really static?)
However, the main reason for the actual problem are the x and y values in the Bullet class:
class Bullet
{
private double dx, dy;
private int x, y;
....
public void update()
{
x += dx;
y += dy;
System.out.println("dx : " + dx + " " + dy);
}
...
}
They are declared as int values. Imagine what happens in the update method, for example, when x=0 and dx = 0.75: It will compute 0+0.75 = 0.75, truncate this to be an int value, and the result will be 0.
Thus, the x and y values will never change, unless the dx and dy values are >= 1.0, respectively.
Just changing the type of x and y to double will solve this. You'll have to add casts in the render method accordingly:
g.drawImage(image, (int)x, (int)y, ...);
But you should really clean this up.

Related

Game in java: rotating selected object

I'm developing a Java game just for study purposes.
I want the player to select the object. The selected object can move, but the others (non-selected objects) must not move.
Game.java:
import javax.swing.JFrame;
public class Game {
public static void main(String[] args) {
JFrame frame = new JFrame("Kibe");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setContentPane(new GamePanel());
frame.pack();
frame.setVisible(true);
}
}
GamePanel.java:
import javax.swing.JPanel;
import java.awt.*;
import java.awt.image.*;
import java.awt.event.*;
import java.util.*;
public class GamePanel extends JPanel implements Runnable, KeyListener {
// fields
public static final int WIDTH = 640, HEIGHT = 480;
private Thread thread;
private boolean running;
private int FPS = 30;
private double averageFPS;
private BufferedImage image;
private Graphics2D g;
public ArrayList<Circle> circles;
private int selectedCircle;
// constructor
public GamePanel(){
super();
setPreferredSize(new Dimension(WIDTH, HEIGHT));
setFocusable(true);
requestFocus();
}
// functions
public void addNotify(){
super.addNotify();
if(thread == null){
thread = new Thread(this);
thread.start();
}
addKeyListener(this);
}
public void run(){
running = true;
image = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);
g = (Graphics2D) image.getGraphics();
circles = new ArrayList<Circle>();
long startTime;
gameUpdate();
gameRender();
gameDraw();
long URDTimeMillis;
long waitTime;
long totalTime = 0;
int frameCount = 0;
int maxFrameCount = 30;
long targetTime = 1000 / FPS;
while(running){ // the game loop
startTime = System.nanoTime();
gameUpdate();
gameRender();
gameDraw();
URDTimeMillis = (System.nanoTime() - startTime) / 1000000;
waitTime = targetTime - URDTimeMillis;
try{
Thread.sleep(waitTime);
}catch(Exception e){
e.printStackTrace();
}
frameCount++;
if(frameCount == maxFrameCount){
averageFPS = 1000.0 / ((totalTime / frameCount) / 1000000);
frameCount = 0;
totalTime = 0;
}
}
}
private void gameUpdate(){
circles.get(selectedCircle).update();
}
private void gameRender(){
g.setColor(Color.BLACK);
g.fillRect(0, 0, WIDTH, HEIGHT);
for(int i = 0; i < circles.size(); i++){
circles.get(i).draw(g);
}
}
private void gameDraw(){
Graphics g2 = this.getGraphics();
g2.drawImage(image, 0, 0, null);
g2.dispose();
}
// key functions
public void keyTyped(KeyEvent e){
int keyCode = e.getKeyCode();
}
public void keyPressed(KeyEvent e){
int keyCode = e.getKeyCode();
if(keyCode == KeyEvent.VK_SPACE){
circles.add(new Circle());
}
else if(keyCode == KeyEvent.VK_Z){
selectedCircle = (selectedCircle + 1) % circles.size();
}
}
public void keyReleased(KeyEvent e){
int keyCode = e.getKeyCode();
}
}
Circle.java:
import java.awt.*;
public class Circle {
// fields
private double x;
private double y;
private int speed;
private int dx;
private int dy;
private int r;
private boolean up;
private boolean down;
private boolean left;
private boolean right;
private Color color;
// constructor
public Circle(){
x = Math.random() * GamePanel.WIDTH / 2 + GamePanel.HEIGHT / 4;
y = -r;
speed = 5;
dx = 0;
dy = 0;
r = 5;
color = Color.WHITE;
}
// functions
public void setUp(boolean b) { up = b; }
public void setDown(boolean b) { down = b; }
public void setLeft(boolean b) { left = b; }
public void setRight(boolean b ) { right = b; }
public void update(){
if(up)
dy = -speed;
else
dy = 0;
if(down)
dy = speed;
if(left)
dx = -speed;
else
dx = 0;
if(right)
dx = speed;
color = Color.RED;
}
public void draw(Graphics2D g){
g.setColor(Color.WHITE);
g.fillOval((int) x - r, (int) y - r, 2 * r, 2 * r);
}
}
The error when I try to run:
Exception in thread "Thread-2" java.lang.IndexOutOfBoundsException: Index: 0, Si
ze: 0
at java.util.ArrayList.rangeCheck(Unknown Source)
at java.util.ArrayList.get(Unknown Source)
at GamePanel.gameUpdate(GamePanel.java:102)
at GamePanel.run(GamePanel.java:51)
at java.lang.Thread.run(Unknown Source)
The error message is clear:
IndexOutOfBoundsException: Index: 0, Size: 0
You're trying to get the 0th item out of an ArrayList whose size is 0, meaning there is no 0th item (first item).
This line:
private void gameUpdate(){
circles.get(selectedCircle).update(); // here ****
}
This is happening at game start before the circles ArrayList holds any Circle objects.
One solution is to do a validity check before trying to extract something that doesn't exist, e.g.,
private void gameUpdate() {
if (selectedCircle < circles.size()) {
circles.get(selectedCircle).update();
}
}
Of course this won't prevent the other problems that you will soon encounter with this code including
negative Thread.sleep times
Drawing with a Graphics object obtained by calling getGraphics() on a Swing component
Making Swing calls directly from a background thread

How do I rotate objects/images independently in Java?

I am trying to have a series of rectangles rotating about their respective centres and moving to the right, but since the plane contains all the rectangles, all the rectangles rotate in unison about the centre of the latest added rectangle instead of independently around their respective centres. Here are the codes:
The main program:
import java.awt.Graphics2D;
import java.util.ArrayList;
public class Rectangles {
public static final int SCREEN_WIDTH = 400;
public static final int SCREEN_HEIGHT = 400;
public static void main(String[] args) throws Exception {
Rectangles game = new Rectangles();
game.play();
}
public void play() {
board.setupAndDisplay();
}
public Rectangles() {
board = new Board(SCREEN_WIDTH, SCREEN_HEIGHT, this);
rectangle_2 = new Rectangle_2();
rectangles = new ArrayList<Rectangle_2>();
}
public void drawRectangles(Graphics2D g, float elapsedTime) {
ticks++;
if (ticks % 4000 == 0) {
Rectangle_2 rectangle = new Rectangle_2();
rectangles.add(rectangle);
}
rotateRectangles(g);
drawRectangles(g);
moveRectangles(elapsedTime);
for (int i = 0; i < rectangles.size(); i++) {
Rectangle_2 rectangle = rectangles.get(i);
if (rectangle.getX() < -75) {
rectangles.remove(i);
i--;
}
}
}
public void drawRectangles(Graphics2D g) {
for (Rectangle_2 rectangle: rectangles) {
rectangle.drawRectangle(g);
}
}
public void rotateRectangles(Graphics2D g) {
for (Rectangle_2 rectangle: rectangles) {
rectangle.rotateRectangle(g);
}
}
public void moveRectangles(float elapsedTime) {
for (Rectangle_2 rectangle: rectangles) {
rectangle.move(10 * elapsedTime);
}
}
private Board board;
private Rectangle_2 rectangle_2;
private int ticks = 0;
private ArrayList<Rectangle_2> rectangles;
}
The rectangle class:
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
public class Rectangle_2 {
public Rectangle_2() {
x = 0;
y = 200;
rectangle = new Rectangle((int) x, (int) y, 25, 25);
}
public void drawRectangle(Graphics2D g) {
g.setColor(Color.red);
g.draw(rectangle);
}
public void rotateRectangle(Graphics g) {
Graphics2D g2 = (Graphics2D) g;
angle += 0.001;
g2.rotate(angle, rectangle.getX() + rectangle.getWidth() / 2, rectangle.getY() + rectangle.getHeight() / 2);
g2.setColor(Color.red);
}
public void move(float elapsedTime) {
x = x + elapsedTime;
rectangle.setLocation((int) x, (int) y);
}
public boolean collides(Rectangle r) {
return r.intersects(rectangle);
}
#Override
public String toString() {
return "Pipe [x = " + x + ", y = " + y + ", rectangle = " + rectangle + "]";
}
public Rectangle getRectangle() {
return rectangle;
}
public double getX() {
return x;
}
private double x;
private double y;
private double angle = 0;
private Rectangle rectangle;
}
The board class where the animation takes place:
import java.awt.*;
import javax.swing.*;
public class Board extends JPanel {
private static final long serialVersionUID = 1L;
public Board(int width_, int height_, Rectangles simulator_) {
width = width_;
height = height_;
game = simulator_;
lastTime = -1L;
}
public void setupAndDisplay() {
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(new JScrollPane(this));
f.setSize(width, height);
f.setLocation(200, 200);
f.setVisible(true);
this.setFocusable(true);
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
boolean first = (lastTime == -1L);
long elapsedTime = System.nanoTime() - lastTime;
lastTime = System.nanoTime();
g.setColor(Color.white);
g.fillRect(0, 0, width, height);
g.setColor(Color.white);
game.drawRectangles((Graphics2D) g, (first ? 0.0f : (float) elapsedTime / 1e9f));
repaint();
}
private int width;
private int height;
private long lastTime;
private Rectangles game;
}
Please note the rectangle takes a couple of seconds to appear because of the delay implemented. Thank you :).
The Graphics context is a shared resource, that is, during a single paint cycle, all the components get the same Graphics context. Any changes you make to the Graphics context are also maintained (or compound in the case of same transformations). So this means, each time you call Graphics#rotate, you are actually compounding any of the previous rotations which might have been executed on it.
You need to change you code in two ways...
You need a independent update cycle, independent of the paint cycle
Create a local copy of the Graphics context BEFORE you apply any transformations
For example...
Rectangles becomes the main driver/engine. It's responsible for managing the entities and updating them each cycle. Normally, I'd use some kind of interface that described the functionality that other case might be able to use, but you get the idea
public class Rectangles {
public static void main(String[] args) throws Exception {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
Rectangles game = new Rectangles();
game.play();
}
});
}
public void play() {
Board board = new Board(this);
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(board);
f.pack();
f.setLocation(200, 200);
f.setVisible(true);
Timer timer = new Timer(40, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
updateRectangles();
board.repaint();
lastTime = System.nanoTime();
}
});
timer.start();
}
public Rectangles() {
rectangle_2 = new Rectangle_2();
rectangles = new ArrayList<Rectangle_2>();
}
protected void updateRectangles() {
boolean first = (lastTime == -1L);
double elapsedTime = System.nanoTime() - lastTime;
elapsedTime = (first ? 0.0f : (float) elapsedTime / 1e9f);
ticks++;
if (ticks <= 1 || ticks % 100 == 0) {
Rectangle_2 rectangle = new Rectangle_2();
rectangles.add(rectangle);
}
rotateRectangles();
moveRectangles(elapsedTime);
for (int i = 0; i < rectangles.size(); i++) {
Rectangle_2 rectangle = rectangles.get(i);
if (rectangle.getX() < -75) {
rectangles.remove(i);
i--;
}
}
}
public void drawRectangles(Graphics2D g) {
for (Rectangle_2 rectangle : rectangles) {
rectangle.drawRectangle(g);
}
}
protected void rotateRectangles() {
for (Rectangle_2 rectangle : rectangles) {
rectangle.rotateRectangle();
}
}
protected void moveRectangles(double elapsedTime) {
for (Rectangle_2 rectangle : rectangles) {
rectangle.move(10 * elapsedTime);
}
}
private long lastTime = -1L;
private Rectangle_2 rectangle_2;
private int ticks = 0;
private ArrayList<Rectangle_2> rectangles;
}
Board becomes nothing more then a surface onto which the entities can be rendered
public class Board extends JPanel {
public Board(Rectangles engine) {
game = engine;
}
#Override
public Dimension getPreferredSize() {
return new Dimension(400, 400);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
game.drawRectangles((Graphics2D) g);
}
private Rectangles game;
}
And Rectangle_2 is a simple container of information which knows how to paint itself when given the chance. You will note the movement and rotation methods just update the state, they do nothing else.
drawRectangle first creates a copy of the supplied Graphics2D context, before it applies it's changes and renders the rectangle, when done, it calls dispose to dispose of the copy
public class Rectangle_2 {
public Rectangle_2() {
x = 0;
y = 200;
rectangle = new Rectangle((int) x, (int) y, 25, 25);
}
public void drawRectangle(Graphics2D g) {
Graphics2D g2 = (Graphics2D) g.create();
g2.rotate(angle, rectangle.getX() + rectangle.getWidth() / 2, rectangle.getY() + rectangle.getHeight() / 2);
g2.setColor(Color.red);
g2.draw(rectangle);
g2.dispose();
}
public void rotateRectangle() {
angle += 0.001;
}
public void move(double elapsedTime) {
x = x + elapsedTime;
rectangle.setLocation((int) x, (int) y);
}
public boolean collides(Rectangle r) {
return r.intersects(rectangle);
}
#Override
public String toString() {
return "Pipe [x = " + x + ", y = " + y + ", rectangle = " + rectangle + "]";
}
public Rectangle getRectangle() {
return rectangle;
}
public double getX() {
return x;
}
private double x;
private double y;
private double angle = 0;
private Rectangle rectangle;
}

Loop in a JApplet animation Java

import java.awt.Graphics;
import javax.swing.JApplet;
import javax.swing.JPanel;
public class Circle extends JPanel {
int x = 75;
int y = 100;
int diameter = 50;
public void setAnimationY(int y) {
this.y = y;
}
public int getAnimationY() {
return y;
}
public int getDiameter() {
return diameter;
}
public void setDiameter(int startDiameter) {
diameter = startDiameter;
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawOval(x, y, diameter, diameter);
}
}
import java.awt.BorderLayout;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JApplet;
import javax.swing.JPanel;
import javax.swing.Timer;
public class BouncingBall extends JApplet {
private int speed = 5;
private Timer timer;
private Circle draw;
#Override
public void init() {
super.init();
setLayout(new BorderLayout());
draw = new Circle();
add(draw);
timer = new Timer(30, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
int y = draw.getAnimationY();
int diameter = draw.getDiameter();
int roof = getHeight();
y += speed;
if (y < 0) {
y = 0;
speed *= -1;
} else if (y + diameter > roof) {
y = roof - diameter;
speed *= -1;
}
draw.setAnimationY(y);
repaint();
}
});
}
#Override
public void start() {
super.start();
timer.start();
}
#Override
public void stop() {
timer.stop();
super.stop();
}
}
I am trying to create a JApplet that contains a ball that is bouncing up and down. So far I have been able to get the ball to go up and down but now I am trying to make the ball more "life-like" so I want the height of the ball to decrease each time the ball bounces until eventually it stops.
I have attempted to do a while loop using the roof variable that I created for the getHeight() method but for some reason when I tried to use it either the ball didn't move at all or the loop had no affect on the ball.
I have also tried a for loop but I ran into the same problem that I got into with the while loop. I believe the problem is that I am not placing this for loop in the correct spot for it to work correctly.
thanks in advance.
Little modifications to your code that can give you some trails:
#Override
public void actionPerformed(ActionEvent e) {
int y = draw.getAnimationY();
int diameter = draw.getDiameter();
int roof = getHeight();
y += speed;
//
// Reduce the ball size at the bottom of the screen
//
if(y + diameter > roof) {
if(diameter > minDiameter) {
diameter -= (roof - y);
} else {
diameter = minDiameter;
}
} else if (diameter < maxDiameter) {
diameter++;
}
draw.setDiameter(diameter);
if (y < 0) {
y = 0;
speed *= -1;
} else if (y + diameter > roof) {
y = roof - diameter;
speed *= -1;
}
// Simulates a little gravity
speed += 0.5;
draw.setAnimationY(y);
repaint();
}
For more realism, the best way would to find an equation that is function of the ball position and a coefficient of hardness for the ball and would give you the ball size.
Well let use continue with #MadProgrammer's solution from your other related question:
In your class of DrawPane we can easily define the height, getAnimationHeight() and setAnimationHeight(int) to control the height decrease as soon as it touches the ground. Please remember that in java left-top co-ordinate is (0, 0) and right-bottom co-ordinate is (getWidth(), getHeight()). Suppose that it starts from height = 0(top). Then it will start from y = height(top) and eventually move to the getHeight()(bottom) of your container. We will increase the height(top y) using setAnimationHeight() by adding an amount(say 30) to current height(which getAnimationHeight() will return) .
So, this little tweak made to #MadeProgrammer's solution in your other question will be the following demo.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.Timer;
public class Circle extends JApplet {
private int delta = 8;
private Timer timer;
private DrawPane drawPane;
#Override
public void init() {
super.init();
setLayout(new BorderLayout());
drawPane = new DrawPane();
add(drawPane);
timer = new Timer(100, new ActionListener() {
int frameCount = 0;
#Override
public void actionPerformed(ActionEvent e) {
int y = drawPane.getAnimationY();
int diameter = drawPane.getDiameter();
y += delta;
if (y < drawPane.getAnimationHeight()) {
y = drawPane.getAnimationHeight();
delta *= -1;
} else if (y + diameter > getHeight()) {
y = getHeight()- diameter;
delta *= -1;
int animationHeight = drawPane.getAnimationHeight();
animationHeight = animationHeight + (getHeight() - diameter - animationHeight)/2;
drawPane.setAnimationHeight(animationHeight);
if(animationHeight + diameter + 2 >= getHeight())
{
System.out.println("true");
drawPane.setAnimationY(getHeight() - diameter);
repaint();
timer.stop();
return;
}
}
drawPane.setAnimationY(y);
repaint();
}
});
}
#Override
public void start() {
super.start();
timer.start();
}
#Override
public void stop() {
timer.stop();
super.stop();
}
public class DrawPane extends JPanel {
int x = 100;
int y = 0;
int diameter = 50;
int height = 0;
public void setAnimationX(int x) {
this.x = x;
}
public void setAnimationY(int y) {
this.y = y;
}
public void setAnimationHeight(int h)
{
height = h;
}
public int getAnimationHeight()
{
return height;
}
public int getAnimationX() {
return x;
}
public int getAnimationY() {
return y;
}
public int getDiameter() {
return diameter;
}
public void setDiameter(int startDiameter) {
diameter = startDiameter;
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawOval(x, y, diameter, diameter);
}
}
}
NOTE: As soon as it touches the bottom finally, you should stop the Timer to get rid of the flickering of the ball. This task is left as an exercise for you.

Variable stops being set after "if" statement is added [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 9 years ago.
Improve this question
I have a input class. When up is pressed it sets player.hasJumped = true; and when hasJumped is true, it changes dy to -3 in the player class. The problem is, that hasJumped is being set to true, but the variable is not changing. I can't really figure out why this is happening. This is a short sample of my code, I can provide more if needed.
InputHandler.java
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
public class InputHandler implements KeyListener{
Player player = new Player();
private boolean[] keys = new boolean[120];
public boolean up;
public void tick(){
up = keys[KeyEvent.VK_UP] || keys[KeyEvent.VK_W];
if(player.jumpReady){
if(up){
player.inAir = true;
System.out.println("JUMPED " + player.inAir);
}
}
}
public void keyPressed(KeyEvent e) {
keys[e.getKeyCode()] = true;
}
public void keyReleased(KeyEvent e) {
keys[e.getKeyCode()] = false;
}
Player.java
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
public class Player {
int x;
int y;
int dx;
public long xElapsed = 0;
public int dy;
int width = 50;
int height = 75;
public int hangTime = 0;
int maxHangTime = 100;
int nextX = 1000;
public int playerSpeed = 7;
public int coinsCollected = 0;
public boolean isMoving = true;
public boolean hasJumped = false;
public boolean jumpReady = true;
public boolean hasCollided = false;
public boolean inAir = false;
private BufferedImage moving1 = null;
private String path1 = "res/player_moving_1.png";
public Player(){
try {
moving1 = ImageIO.read(new File(path1));
}catch (IOException e) {
e.printStackTrace();
System.err.println("Could not load image " + moving1 + " at path" + path1);
}
x = 150;
y = 250;
}
public void render(Graphics g){
Graphics2D g2d = (Graphics2D) g;
g2d.drawImage(moving1, x, y, null);
}
public void move(){
x = x + dx;
y = y + dy;
xElapsed++;
if(xElapsed == nextX){
upSpeed();
nextX += 1000;
}
if(inAir){
System.out.println("test");
dy = -3;
}
}
public void paint(Graphics g){
g.setColor(Color.RED);
g.fillRect(x, y, width, height);
}
public void upSpeed(){
playerSpeed++;
}
public int getX(){
return x;
}
public int getY(){
return y;
}
public long getXElapsed(){
return xElapsed;
}
public double getSpeed(){
return playerSpeed;
}
public int getNextX(){
return nextX;
}
public int getCoinsCollected(){
return coinsCollected;
}
public Rectangle bounds(){
return (new Rectangle(x, y, width, height));
}
}
Game.java
private static final long serialVersionUID = 1L;
public static final int WIDTH = 350;
public static final int HEIGHT = WIDTH / 16 * 9;
public static final int SCALE = 2;
private Thread thread;
private JFrame frame;
private InputHandler input;
private boolean running = false;
private Screen screen;
private BufferedImage image = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);
private int[] pixels = ((DataBufferInt)image.getRaster().getDataBuffer()).getData();
Player player = new Player();
public Game() {
Dimension size = new Dimension(WIDTH * SCALE, HEIGHT * SCALE);
setPreferredSize(size);
screen = new Screen(WIDTH, HEIGHT);
frame = new JFrame();
input = new InputHandler();
addKeyListener(input);
setFocusable(true);
}
public void run() {
long lastTime = System.nanoTime();
long timer = System.currentTimeMillis();
final double ns = 1000000000.0 / 60.0;
double delta = 0;
int frames = 0;
int ticks = 0;
while(running){
long now = System.nanoTime();
delta += (now - lastTime) / ns;
lastTime = now;
while(delta >= 1){
tick();
ticks++;
delta--;
}
render();
frames++;
if(System.currentTimeMillis() - timer > 1000){
timer += 1000;
System.out.println(ticks + " tps, " + frames + " fps");
ticks = 0;
frames = 0;
}
}
stop();
}
public void tick(){
input.tick();
player.move();
collision();
obstacleHole.move();
obstacleWolf.move();
coin.move();
}
Within Game.java pass the object player as argument within the constructor of InputHandler as follows:
public Game() {
Dimension size = new Dimension(WIDTH * SCALE, HEIGHT * SCALE);
setPreferredSize(size);
screen = new Screen(WIDTH, HEIGHT);
frame = new JFrame();
input = new InputHandler(player);//pass player object as argument
addKeyListener(input);
setFocusable(true);
}
And change the InputHandler class as follows:
public class InputHandler implements KeyListener{
Player player ; //Don't initialize it.
//Create a parametric constructor
public InputHandler(Player player)
{
this.player = player;
}
//...And then proceed with other stuffs
}

[Java]Double buffering failing to double buffer

Well, as the title says, I am having trouble with double buffering. I read this Java Ebook and it doesn't give you code for what they are teaching you - at least not completely. So I have to do a lot of guess work.
Objective : Bouncing ball in an applet.
It's not working in the way that the ball is still flashing. Aka double buffering is failing to work.
I use three classes, ball class, double buffering class, and MainApplet class. MainApplet extends double buffering, and ball class extends MainApplet
import java.applet.Applet;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Rectangle;
#SuppressWarnings("serial")
public class MainApplet extends DoubleBuffering implements Runnable {
public Ball ball;
public Graphics g;
private Thread ticker;
public boolean running = false;
public void init() {
setSize(100,100);
ball = new Ball(getWidth() / 5f, getHeight() / 4f, 1.5f,
2.3f, 12, Color.red);
moveBall();
}
public void run() {
while(running) {
try {
Rectangle bou = new Rectangle(getWidth(), getHeight());
ball.move(bou);
ball.update(getGraphics());
Thread.sleep(1000 / 15);
} catch (InterruptedException e) {
System.out.println(e.getMessage());
}
repaint();
}
}
public void moveBall() {
start();
}
public synchronized void start() {
running = true;
ticker = new Thread(this);
ticker.setPriority(Thread.MIN_PRIORITY + 1);
ticker.start();
}
public synchronized void stop() {
running = false;
ticker.stop();
}
}
import java.applet.Applet;
import java.awt.Graphics;
import java.awt.Image;
public class DoubleBuffering extends Applet
{
Image offScreenBuffer;
#SuppressWarnings("deprecation")
public void update(Graphics g)
{
System.out.println("We are buffing");
Graphics gr;
if (offScreenBuffer==null ||
(! (offScreenBuffer.getWidth(this) == this.size().width
&& offScreenBuffer.getHeight(this) == this.size().height)))
{
offScreenBuffer = this.createImage(size().width, size().height);
}
gr = offScreenBuffer.getGraphics();
System.out.println("Something else");
paint(gr);
g.drawImage(offScreenBuffer, 0, 0, this);
}
}
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Rectangle;
public class Ball extends MainApplet{
int size;
private Color color;
public float x, y, dx, dy;
public Ball ball;
public int width, height;
public Image offscreenImage;
public Graphics offscr;
private MainApplet ma;
Ball (float x, float y, float dx, float dy, int size,
Color color) {
this.x = x;
this.y = y;
this.dy = dx;
this.dy = dy;
this.color = color;
this.size = size;
}
public void draw (Graphics g) {
g.setColor(this.color);
g.fillOval((int) x, (int) y, size, size);
}
public void update(Graphics g) {
g.clearRect(0, 0, getWidth(), getHeight());
draw(g);
}
public void move(Rectangle bounds) {
// Add velocity values dx/dy to position to
// ball s new position
x += dx;
y += dy;
// Check for collision with left edge
if (x < bounds.x && dx < 0) {
dx = -dx;
x -= 2 * (x - bounds.x);
}
// Check for collision with right edge
else if (x + size > bounds.x + bounds.width &&
dx > 0) {
dx = -dx;
x -= 2 * ((x + size) - (bounds.x + bounds.width));
}
// Checks for collision with top edge
else if (y < bounds.y && dy < 0) {
dy = -dy;
y -= 2 * (y - bounds.y);
}
// Checks for collision with bottom edge
else if (y + size > bounds.y + bounds.height && dy >0) {
dy = -dy;
y -= 2 * ((y + size) - (bounds.y + bounds.width));
}
}
}
Note: I'm not too sure how this code will come out >.< it looks as if it's being choppy with the 'code:' function.
Anyways, don't hate too hard on my conventions, I'm still rather new. Tips and answers would be appreciated. Thanks.
Instead of calling Thread.Sleep() try using the swing Timer like this.
private Timer t;
public void moveBall() {
t = new Timer(1000/15, new ActionListener() {
public void actionPerformed(ActionEvent e) {
Rectangle bou = new Rectangle(getWidth(), getHeight());
ball.move(bou);
ball.update(getGraphics());
repaint();
}
});
t.start();
}
public void destroy() {
if(t!=null) t.stop();
super.destroy();
}
that should help at least a little bit.
I'm assuming the class DoubleBuffering is some tutorial class. I'm guessing it derives from Applet and not JApplet. If you use JApplet you will get double buffering by default.

Categories