So I am trying to make a pinball game made as a applet load into a JFrame. The applet loads into it no problem but when i run it flickers and glitch out. Thanks in advance!
Jframe class:
import javax.swing.*;
import java.awt.*;
import java.applet.*;
public class PinBallGUI extends JFrame
{
public static void main(String[] args)
{
JFrame frame = new JFrame("Pinball");
frame.setVisible(true);
frame.setSize(600,700);
int height = 700;
int width = 600;
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
PinBallGame temp = new PinBallGame();
frame.add(temp);
temp.init(width,height);
temp.start();
temp.run();
}
}
Applet class:
import java.awt.*;
import javax.swing.*;
import java.applet.*;
import java.util.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
public class PinBallGame extends Applet implements Runnable
{
Thread runner;
private Image Buffer;
private Graphics gBuffer;
int width,height;
PinBallBall B1;
PinBallPaddle P1,P2;
PinBallRectangle R1,R2,R3,R4;
PinBallRectangle[] rArray;
boolean leftKey;
boolean rightKey;
boolean downKey;
boolean spaceKey;
int points;
Random gen = new Random();
public void init(int W,int H)
{
width=W;
height=H;
Buffer=createImage(width,height);
gBuffer=Buffer.getGraphics();
B1 = new PinBallBall(-1,width-57,645);
P1 = new PinBallPaddle(180,625,255,640);
P2 = new PinBallPaddle(300,640,375,625);
R1 = new PinBallRectangle(1,width-35,60,15,600);
R2 = new PinBallRectangle(1,width-80,60,15,600);
R3 = new PinBallRectangle(1,0,625,180,40);
R4 = new PinBallRectangle(1,375,625,140,40);
rArray = new PinBallRectangle[5];
for(int i=0; i<rArray.length; i++)
{
rArray[i] = new PinBallRectangle(-1,gen.nextInt(450),gen.nextInt(450),gen.nextInt(60),gen.nextInt(60));
}
int count = 0;
addKeyListener(new MyKeyListener());
points = 0;
}
private class MyKeyListener extends KeyAdapter
{
public void keyPressed(KeyEvent e)
{
switch(e.getKeyCode())
{
case KeyEvent.VK_LEFT:
leftKey = true;
break;
case KeyEvent.VK_RIGHT:
rightKey = true;
break;
case KeyEvent.VK_SPACE:
spaceKey = true;
break;
case KeyEvent.VK_DOWN:
downKey = true;
break;
}
}
public void keyReleased(KeyEvent e)
{
switch(e.getKeyCode())
{
case KeyEvent.VK_LEFT:
leftKey = false;
break;
case KeyEvent.VK_RIGHT:
rightKey = false;
break;
case KeyEvent.VK_SPACE:
spaceKey = false;
break;
case KeyEvent.VK_DOWN:
downKey = false;
break;
}
}
}
public void start()
{
if (runner == null)
{
runner = new Thread (this);
runner.start();
}
}
public void stop()
{
runner = null;
}
public void run()
{
while(true)
{
update(gBuffer);
if(leftKey){P1.moveLeftPaddle();}
if(rightKey){P2.moveRightPaddle();}
if(downKey){B1.launchBall(width,height);}
repaint();
try {runner.sleep(25);}
catch (Exception e) { }
repaint();
gBuffer.setColor(Color.black);
gBuffer.fillRect(0,0,width,height);
if((B1.getX() != width-57)||(B1.getY() != 645))
{
B1.movePinBallBall(width,height);
B1.update();
}
R1.ballCollision(B1);
repaint();
R2.ballCollision(B1);
repaint();
R3.ballCollision(B1);
repaint();
R4.ballCollision(B1);
repaint();
P1.ballCollision(B1);
repaint();
P2.ballCollision(B1);
repaint();
for(int i=0; i<rArray.length; i++)
{
rArray[i].ballCollision(B1);
repaint();
}
for(int i=0; i<rArray.length; i++)
{
rArray[i].paint(gBuffer);
}
update(gBuffer);
B1.paint(gBuffer);
R1.paint(gBuffer);
R2.paint(gBuffer);
R3.paint(gBuffer);
R4.paint(gBuffer);
P1.paint(gBuffer);
P2.paint(gBuffer);
repaint();
update(gBuffer);
}//while(true)
} //run
public void update(Graphics g)
{
paint(g);
}
public void paint(Graphics g)
{
g.drawImage(Buffer,0,0, this);
}
}
I also have 3 other classes that are just for objects (ball, rectangle, paddle).
Thanks again in advance!
You're going to want to either use JFrame and JPanel or Frame and Canvas instead of using a JFrame and an Applet. You can definitely mix and match components, but you'll probably encounter less bugs if you don't.
I generally find flickering to happen when you aren't using double buffering. Fro a JPanel you'll want to enable double buffering and for a Canvas there is a way to implement triple buffering if you really need to, but stick with a JPanel for most cases.
Related
I have written a sample code using KeyListener in Java,
I have created a JPanel, then set its focusable to true, I have created a KeyListener, requested a focus and then added the KeyListener to my panel. But the methods for the keyListener are never called. It seems although I have requested focus, it does not focus.
Can anyone help?
listener = new KeyLis();
this.setFocusable(true);
this.requestFocus();
this.addKeyListener(listener);
class KeyLis implements KeyListener{
#Override
public void keyPressed(KeyEvent e) {
currentver += 5;
switch (e.getKeyCode()) {
case KeyEvent.VK_LEFT : if(horizontalyInBounds()) currentPos-= 5;
break;
case KeyEvent.VK_RIGHT: if(horizontalyInBounds()) currentPos+= 5;
break;
}
repaint();
}
#Override
public void keyReleased(KeyEvent e) {
// TODO Auto-generated method stub
}
#Override
public void keyTyped(KeyEvent e) {
}
}
If any runnable code should be needed:
import java.awt.Color;
import java.awt.Graphics;
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.JLabel;
public class test extends JFrame {
private AreaOfGame areaOfGame;
public test()
{
super("");
setVisible(true);
this.setBackground(Color.darkGray);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.pack();
setLayout(null);
setBounds(200, 10, 400, 700);
areaOfGame = new AreaOfGame();
this.add(areaOfGame);
startGame();
}
public int generateNext()
{
Random r = new Random();
int n = r.nextInt(7);
return n;
}
public void startGame()
{
while(!areaOfGame.GameOver())
{
areaOfGame.startGame(generateNext());
}
}
public static void main(String[] args) {
new MainFrame();
}
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import javax.swing.JPanel;
public class AreaOfGame extends JPanel {
private static final int rightside = 370;
private int bottom;
private int top;
private int currentPos;
private int currentver;
private KeyLis listener;
public AreaOfGame()
{
super();
bottom = 650;
top = 50;
setLayout(null);
setBounds(20, 50, 350, 600);
setVisible(true);
this.setBackground(Color.lightGray);
listener = new KeyLis();
this.setFocusable(true);
if(this.requestFocus(true))
System.out.println("true");;
this.addKeyListener(listener);
currentPos = 150;
currentver=0;
}
public void startGame(int n)
{
while(verticallyInBound()){
System.out.println("anything");
}
}
public boolean verticallyInBound()
{
if(currentPos<= bottom -50)
return true;
return false;
}
public boolean GameOver()
{
if(top>= bottom){
System.out.println("game over");
return true;
}
else return false;
}
public boolean horizontalyInBounds()
{
if(currentPos<=rightside && currentPos>= 20)
return true;
else return false;
}
class KeyLis implements KeyListener{
#Override
public void keyPressed(KeyEvent e) {
System.out.println("called");
currentver += 5;
switch (e.getKeyCode()) {
case KeyEvent.VK_LEFT : if(horizontalyInBounds()) currentPos-= 5; break;
case KeyEvent.VK_RIGHT: if(horizontalyInBounds()) currentPos+= 5; break;
}
repaint();
}
#Override
public void keyReleased(KeyEvent e) {
// TODO Auto-generated method stub
}
#Override
public void keyTyped(KeyEvent e) {
System.out.println("called 3");
}
}
}
I'll bet that you're requesting focus before the JPanel has been rendered (before the top level window has either had pack() or setVisible(true) called), and if so, this won't work. Focus request will only be possibly granted after components have been rendered. Have you checked what your call to requestFocus() has returned? It must return true for your call to have any chance for a success. Also it's better to use requestFocusInWindow() rather than requestFocus().
But more importantly, you shouldn't be using KeyListeners for this but rather key bindings, a higher level concept that Swing itself uses to respond to key presses.
Edit
An example of an SSCCE:
import java.awt.Dimension;
import java.awt.event.*;
import javax.swing.*;
public class TestKeyListener extends JPanel {
private KeyLis listener;
public TestKeyListener() {
add(new JButton("Foo")); // something to draw off focus
listener = new KeyLis();
this.setFocusable(true);
this.requestFocus();
this.addKeyListener(listener);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(300, 200);
}
private class KeyLis extends KeyAdapter {
#Override
public void keyPressed(KeyEvent e) {
switch (e.getKeyCode()) {
case KeyEvent.VK_LEFT:
System.out.println("VK_LEFT pressed");
break;
case KeyEvent.VK_RIGHT:
System.out.println("VK_RIGHT pressed");
break;
}
}
}
private static void createAndShowGui() {
TestKeyListener mainPanel = new TestKeyListener();
JFrame frame = new JFrame("TestKeyListener");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
Edit 2
And the equivalent SSCCE using Key Bindings:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
#SuppressWarnings("serial")
public class TestKeyBindings extends JPanel {
public TestKeyBindings() {
add(new JButton("Foo")); // something to draw off focus
setKeyBindings();
}
private void setKeyBindings() {
ActionMap actionMap = getActionMap();
int condition = JComponent.WHEN_IN_FOCUSED_WINDOW;
InputMap inputMap = getInputMap(condition );
String vkLeft = "VK_LEFT";
String vkRight = "VK_RIGHT";
inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0), vkLeft);
inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0), vkRight);
actionMap.put(vkLeft, new KeyAction(vkLeft));
actionMap.put(vkRight, new KeyAction(vkRight));
}
#Override
public Dimension getPreferredSize() {
return new Dimension(300, 200);
}
private class KeyAction extends AbstractAction {
public KeyAction(String actionCommand) {
putValue(ACTION_COMMAND_KEY, actionCommand);
}
#Override
public void actionPerformed(ActionEvent actionEvt) {
System.out.println(actionEvt.getActionCommand() + " pressed");
}
}
private static void createAndShowGui() {
TestKeyBindings mainPanel = new TestKeyBindings();
JFrame frame = new JFrame("TestKeyListener");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
Edit 3
Regarding your recent SSCCE, your while (true) loops are blocking your Swing event thread and may prevent user interaction or painting from happening. Better to use a Swing Timer rather than while (true). For example:
import java.awt.*;
import java.awt.event.*;
import java.util.Random;
import javax.swing.*;
public class BbbTest extends JFrame {
private AreaOfGame areaOfGame;
public BbbTest() {
super("");
// setVisible(true);
this.setBackground(Color.darkGray);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.pack();
setLayout(null);
setBounds(200, 10, 400, 700);
areaOfGame = new AreaOfGame();
this.add(areaOfGame);
setVisible(true);
startGame();
}
public int generateNext() {
Random r = new Random();
int n = r.nextInt(7);
return n;
}
public void startGame() {
// while (!areaOfGame.GameOver()) {
// areaOfGame.startGame(generateNext());
// }
areaOfGame.startGame(generateNext());
}
public static void main(String[] args) {
new BbbTest();
}
class AreaOfGame extends JPanel {
private static final int rightside = 370;
private int bottom;
private int top;
private int currentPos;
private int currentver;
private KeyLis listener;
public AreaOfGame() {
super();
bottom = 650;
top = 50;
setLayout(null);
setBounds(20, 50, 350, 600);
setVisible(true);
this.setBackground(Color.lightGray);
listener = new KeyLis();
this.setFocusable(true);
if (this.requestFocus(true))
System.out.println("true");
;
this.addKeyListener(listener);
currentPos = 150;
currentver = 0;
}
public void startGame(int n) {
// while (verticallyInBound()) {
// System.out.println("anything");
// }
int timeDelay = 50; // msecs delay
new Timer(timeDelay , new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
System.out.println("anything");
}
}).start();
}
public boolean verticallyInBound() {
if (currentPos <= bottom - 50)
return true;
return false;
}
public boolean GameOver() {
if (top >= bottom) {
System.out.println("game over");
return true;
}
else
return false;
}
public boolean horizontalyInBounds() {
if (currentPos <= rightside && currentPos >= 20)
return true;
else
return false;
}
class KeyLis implements KeyListener {
#Override
public void keyPressed(KeyEvent e) {
System.out.println("called");
currentver += 5;
switch (e.getKeyCode()) {
case KeyEvent.VK_LEFT:
if (horizontalyInBounds())
currentPos -= 5;
break;
case KeyEvent.VK_RIGHT:
if (horizontalyInBounds())
currentPos += 5;
break;
}
repaint();
}
#Override
public void keyReleased(KeyEvent e) {
// TODO Auto-generated method stub
}
#Override
public void keyTyped(KeyEvent e) {
System.out.println("called 3");
}
}
}
}
It's possible to use the "TAB" button to switch between the buttons and the key listener.
I have a program with one button that after I press it, the key listener does not work.
I realized that if you press the "TAB" button, the "Attention" or "focus" of the program returns to the key listener.
maybe this will help: http://docstore.mik.ua/orelly/java-ent/jfc/ch03_08.htm
I have started making slime volleyball. I have run into this problem where the image for the slime character flickers insanely. the image is disappeared just about the same amount of time that it is visible.
I tried removing the super.paint(g); in the paint method and that fixed the problem of flickering, but it created a new problem that wouldn't remove the image from previous locations.
Source Code:
package slimevolleyball.main;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
public class Main extends JFrame {
private static final long serialVersionUID = 1L;
public static int x = 275;
public static int y = 300;
public static boolean right = false;
public static boolean left = false;
public static boolean jump = false;
public static int startjump = 0;
public static int low = 300;
public static double gravity = 0;
public static double time = 0;
public static int startVelocity = 0;
public static double velocity = 0;
public static BufferedImage slime1;
public static BufferedImage slime2;
public static BufferedImage background;
static Rectangle FrameSize;
static JFrame frame = new JFrame();
public Main() {
addKeyListener(new KeyListener() {
public void keyTyped(KeyEvent e) {
}
public void keyReleased(KeyEvent e) {
int keyCode = e.getKeyCode();
switch (keyCode) {
case KeyEvent.VK_UP:
break;
case KeyEvent.VK_DOWN:
break;
case KeyEvent.VK_LEFT:
left = false;
break;
case KeyEvent.VK_RIGHT:
right = false;
}
}
public void keyPressed(KeyEvent e) {
int keyCode = e.getKeyCode();
switch (keyCode) {
case KeyEvent.VK_UP:
if (jump == false) {
jump = true;
startjump = 1;
}
break;
case KeyEvent.VK_DOWN:
break;
case KeyEvent.VK_LEFT:
left = true;
right = false;
break;
case KeyEvent.VK_RIGHT:
right = true;
left = false;
break;
}
}
});
setFocusable(true);
setTitle("Slime VolleyBall");
setSize(600, 400);
setResizable(true);
setVisible(true);
setDefaultCloseOperation(EXIT_ON_CLOSE);
}
public void paint(Graphics g) {
super.paint(g);
g.drawImage(slime1, x, y, null);
}
public static void main(String[] args) throws InterruptedException, IOException {
Main game = new Main();
slime1 = ImageIO.read(new File("red.png"));
while (true) {
MoveSlime1();
Update();
game.repaint();
Thread.sleep(2);
}
}
private static void Update() {
FrameSize = frame.getBounds();
}
private static void MoveSlime1() {
if (right == true && x <= FrameSize.getWidth() / 2) {
x += 1;
} else if (left == true && x >= 0) {
x -= 1;
}
if (jump == true) {
if (startjump == 1) {
low = 300;
gravity = -9.8;
time = 0;
startVelocity = 3;
velocity = 0;
startjump = 0;
} else {
velocity = startVelocity + (gravity * time);
y -= velocity;
time += 0.005;
if (time > 0.01 && y >= low) {
jump = false;
}
}
}
}
}
JFrame is not double buffered, hence the flicker, which is just one of a list of reasons why you should not be extending from JFrame and overriding it's paint method.
Instead, move all your logic over to a class which extends JPanel and then override it's paintComponent method, this way, you'll get double buffering for free.
Also, you should avoid using KeyListeners and favor the Key Bindings API which solves the focus related issues of KeyListener
Also, static is not your friend, you should learn to live without it
I'm having a lot of trouble trying to make my code move a player (Ship) around a screen. I can get the planets to draw on the screen and the the player ship but I can not figure out how to implement the keyListener to at least print out something. Thank you in advance for all the help!
import javax.swing.JFrame;
import javax.swing.JPanel;
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.Toolkit;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
public class MapPanel extends JPanel {
public static final int WIDTH = 25;
public static final int HEIGHT = 20;
int zone = 0;
private int xValue;
private int yValue;
private Color color;
public Planet[][] planetGrid = new Planet[WIDTH][HEIGHT];
static Player currPlayer = new Player("h");
static Universe universe = new Universe(currPlayer);
/**
* Create the panel.
*/
public MapPanel(Universe univ, Player p) {
this.universe = univ;
currPlayer = p;
int i = 0;
this.setSize(new Dimension(450,450));
setVisible( true );
//this.addKeyListener(new KeyController());
KeyController kc = new KeyController();
this.addKeyListener(kc);
repaint();
}
/**
* Draw method to draw the playing field
* #param g Graphics object
* #param tileDimension dimension of the tile
*/
public void draw(Graphics g)
{
universe.draw(g);
// KeyController key = new KeyController();
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
draw(g);
}
public static void main(String[] args)
{
MapPanel mp = new MapPanel(universe, currPlayer);
JFrame f = new JFrame();
f.add(mp);
f.setSize(new Dimension(450,450));
f.setVisible(true);
f.setFocusable(true);
}
private class KeyController implements KeyListener {
public KeyController()
{
System.out.println("ghgh");
setFocusable(true);
// addKeyListener(this);
}
#Override
public void keyPressed(final KeyEvent key) {
System.out.println("fgfgf");
if (currPlayer != null) {
int oldX = currPlayer.getPosition().x;
int oldY = currPlayer.getPosition().y;
switch (key.getKeyCode()) {
case KeyEvent.VK_RIGHT:
currPlayer.setPosition(new Point(oldX+1, oldY)); //move right
System.out.println("RIGHT");
break;
case KeyEvent.VK_LEFT:
currPlayer.setPosition(new Point(oldX-1, oldY)); //move left
break;
case KeyEvent.VK_DOWN:
currPlayer.setPosition(new Point(oldX, oldY+1)); //move down
break;
case KeyEvent.VK_UP:
currPlayer.setPosition(new Point(oldX, oldY-1)); //move up
break;
}
}
repaint();
}
#Override
public void keyReleased(KeyEvent e) {
System.out.println("ggg");
}
#Override
public void keyTyped(KeyEvent e) {
System.out.println("typeeeddd");
}
}
}
A JPanel won't get its keyboard focus automatically, you should call this, in the constructor:
addMouseListener(new MouseAdapter(){
public void mousePressed(MouseEvent evt){
requestFocus();
}
});
You may have to do
MapPanel panel = new MapPanel();
panel.setFocusable(true);
I was having the same problem, and I had to do for all the other components (such as JButton's) the following:
myButton.setFocusable(false);
Worked for me.
I figured out the solution for my previous question which landed me into new problem.
In the following code im moving an image around a JFrame using arrow keys. but every time i press an arrow key the image seems to flicker which is quite noticeable when a key is pressed continuously.
import java.awt.Graphics;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.image.BufferedImage;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
public class TestProgram extends JFrame implements KeyListener {
private BufferedImage TestImage;
private int cordX = 100;
private int cordY = 100;
public TestProgram() {
setTitle("Testing....");
setSize(500, 500);
imageLoader();
setVisible(true);
}
public void imageLoader() {
try {
String testPath = "test.png";
TestImage = ImageIO.read(getClass().getResourceAsStream(testPath));
} catch (IOException ex) {
ex.printStackTrace();
}
addKeyListener(this);
}
#Override
public void paint(Graphics g) {
super.paint(g);
g.drawImage(TestImage, cordX, cordY, this);
}
public static void main(String[] args) {
new TestProgram();
}
public void keyPressed(KeyEvent ke) {
switch (ke.getKeyCode()) {
case KeyEvent.VK_RIGHT: {
cordX+=5;
}
break;
case KeyEvent.VK_LEFT: {
cordX-=5;
}
break;
case KeyEvent.VK_DOWN: {
cordY+=5;
}
break;
case KeyEvent.VK_UP: {
cordY-=3;
}
break;
}
repaint();
}
public void keyTyped(KeyEvent ke) {}
public void keyReleased(KeyEvent ke) {}
}
Is there any solution to avoid that?
EDIT: above is the complete working code. I'm finding it difficult to incorporate doublebuffer in it. can anyone help me in that part?
Non flickering, working Code.
Repaint() doesn't just call the paint() method. A repaint() method actually calls the update() method and the default update() method then calls to the paint() method. So just override the update() method. Also painting as BufferedImage as mentioned above correctly.
This should work now. It worked fine here. I only used a different imagepath.
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.image.BufferedImage;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
public class TestProgram extends JFrame implements KeyListener {
/**
*
*/
private static final long serialVersionUID = 1L;
private Image TestImage;
private BufferedImage bf;
private int cordX = 100;
private int cordY = 100;
public TestProgram() {
setTitle("Testing....");
setSize(500, 500);
imageLoader();
setVisible(true);
}
public void imageLoader() {
try {
String testPath = "test.png";
TestImage = ImageIO.read(getClass().getResourceAsStream(testPath));
} catch (IOException ex) {
ex.printStackTrace();
}
addKeyListener(this);
}
public void update(Graphics g){
paint(g);
}
public void paint(Graphics g){
bf = new BufferedImage( this.getWidth(),this.getHeight(), BufferedImage.TYPE_INT_RGB);
try{
animation(bf.getGraphics());
g.drawImage(bf,0,0,null);
}catch(Exception ex){
}
}
public void animation(Graphics g) {
super.paint(g);
g.drawImage(TestImage, cordX, cordY, this);
}
public static void main(String[] args) {
new TestProgram();
}
public void keyPressed(KeyEvent ke) {
switch (ke.getKeyCode()) {
case KeyEvent.VK_RIGHT: {
cordX += 5;
}
break;
case KeyEvent.VK_LEFT: {
cordX -= 5;
}
break;
case KeyEvent.VK_DOWN: {
cordY += 5;
}
break;
case KeyEvent.VK_UP: {
cordY -= 3;
}
break;
}
repaint();
}
public void keyTyped(KeyEvent ke) {
}
public void keyReleased(KeyEvent ke) {
}
}
You have to use a Buffer to get rid of the flickering.
For images, there is the BufferedImage Buffer:
BufferedImage bf = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_RGB);
Then you draw your image to the screen like this:
g.drawImage(bf, 0, 0, null);
I am trying to learn some more about vectors and rotation in Java by making a simple asteroids game. I have been trying out the Vector2d class, but I feel like I could have done it just using Points and doubles. Is my use of the Vector2d redundant? How would you change my program?
Source:
import java.awt.Color;
import java.awt.Cursor;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Toolkit;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import javax.vecmath.Vector2d;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Asteroids extends JPanel implements Runnable{
BufferedImage img;
boolean up, left, right;
double angle = 0;
int imgw = 0;
int imgh = 0;
int magnitude = 0;
JFrame f;
ArrayList<Projectile> bullets;
Vector2d rocket = new Vector2d();
Vector2d Magnitude = new Vector2d();
AffineTransform at = new AffineTransform();
public Asteroids(JFrame f){
this.f = f;
setSize(900, 800);
try {
img = ImageIO.read(new File("res/rocket.png"));
} catch (IOException e) {}
imgw = img.getWidth();
imgh = img.getHeight();
bullets = new ArrayList<Projectile>();
f.addKeyListener(new KeyAdapter() {
public void keyPressed(KeyEvent evt) {
switch (evt.getKeyCode()) {
case KeyEvent.VK_UP:
up= true;
break;
case KeyEvent.VK_LEFT:
left = true;
right = false;
break;
case KeyEvent.VK_RIGHT:
right = true;
left = false;
break;
}
}
public void keyReleased(KeyEvent evt) {
switch (evt.getKeyCode()) {
case KeyEvent.VK_UP:
up= false;
break;
case KeyEvent.VK_LEFT:
left = false;
break;
case KeyEvent.VK_RIGHT:
right = false;
break;
case KeyEvent.VK_SPACE:
Vector2d dir = new Vector2d(Math.cos(angle-Math.toRadians(90)),Math.sin(angle-Math.toRadians(90)));
bullets.add(new Projectile(dir,rocket));
break;
}
}
});
Thread t = new Thread(this);
t.start();
}
public static void main(String[] Args){
JFrame frame = new JFrame();
BufferedImage cursorImg = new BufferedImage(16, 16, BufferedImage.TYPE_INT_ARGB);
Cursor blankCursor = Toolkit.getDefaultToolkit().createCustomCursor(cursorImg, new Point(0, 0), "blank cursor");
frame.getContentPane().setCursor(blankCursor);
frame.add(new Asteroids(frame));
frame.setVisible(true);
frame.setSize(900,500);
}
public void paintComponent(Graphics g){
super.paintComponent(g);
Graphics2D g2 = (Graphics2D)g;
g2.fillRect(0,0,this.getWidth(),this.getHeight());
g2.drawImage(img,at,this);
g2.setColor(Color.red);
for(Projectile p: bullets){
p.draw(g2);
}
}
public void run(){
rocket = new Vector2d(100, 400);
Magnitude = new Vector2d(Magnitude = new Vector2d(magnitude*Math.cos(angle-Math.toRadians(90)),magnitude*Math.sin(angle-Math.toRadians(90))));
while(true){
if(left){
angle-=Math.toRadians(5);
}
if(right){
angle+=Math.toRadians(5);
}
if(up){
Vector2d m2 = new Vector2d(Math.cos(angle-Math.toRadians(90)),Math.sin(angle-Math.toRadians(90)));
m2.normalize();
m2.x/=5;
m2.y/=5;
Magnitude.add(m2);
}
if(angle>=Math.toRadians(360)){
angle-=Math.toRadians(360);
}else if(angle<=Math.toRadians(-360)){
angle+=Math.toRadians(360);
}
Vector2d rocketN = new Vector2d(rocket);
rocketN.normalize();
rocket.add(Magnitude);
System.out.println(Math.toDegrees(angle));
at.setToTranslation(rocket.x-img.getWidth()/2, rocket.y-img.getHeight()/2);
at.rotate(angle, imgw/2, imgh/2);
Magnitude.x*=0.99;
Magnitude.y*=0.99;
for(Projectile p: bullets){
p.update();
}
repaint();
try {Thread.sleep(25);
} catch (InterruptedException e) {}
}
}
public class Projectile{
int magnitude;
private Vector2d Magnitude, position;
public Projectile(Vector2d dir, Vector2d Position){
this.position = new Vector2d(Position);
magnitude = 10;
Magnitude = new Vector2d(dir);
position.x+=(5*Magnitude.x);
position.y+=(5*Magnitude.y);
Magnitude.x*=magnitude;
Magnitude.y*=magnitude;
}
public void update(){
position.add(Magnitude);
}
public void draw(Graphics2D g2){
g2.drawOval((int)position.x, (int)position.y,4,4);
}
}
}
Currently there is no asteroids to shoot, you can just move around and shoot. Here is the Image I used: http://findicons.com/files/icons/1495/space/32/rocket_ship.png
I think that not (answer to your question)
but most important is there wrong usage of KeyListener, use KeyBindings instead, example for Keys UP, DOWN, LEFT, RIGHT
(I'm not good in Graphics2D) but another issues could be caused by method
public void draw(Graphics2D g2){
check this thread how to move with Graphics2D, especialy answer by #trashgod
I've never heard of KeyBindings, always used the VK_LETTER. Before that, I used getKeyChar. I think they all work fine.