I'm having a bit of trouble developing my first Java game using images instead of vector graphics. Currently I'm experimenting with moving an Image on a key press with the AffineTransform object. Only it won't move. What am I doing wrong?
I haven't tried using threads yet, but I am not sure how to do this. If you think it would help, please include it in your answer.
Here is my code:
import java.awt.*;
import java.net.*;
import java.awt.event.*;
import java.awt.geom.*;
import java.applet.*;
public class DisplayImage extends Applet implements KeyListener{
AffineTransform identity = new AffineTransform();
boolean left = false;
boolean right = false;
public URL getURL(String filename)
{
URL url = null;
try
{
url = this.getClass().getResource(filename);
}
catch(Exception e){e.printStackTrace();}
return url;
}
private Image image;
public void init()
{
image = getImage(getURL("spaceship.png"));
addKeyListener(this);
}
public void update(Graphics g){paint(g);}
public void paint(Graphics g)
{
AffineTransform trans = new AffineTransform();
trans.setTransform(identity);
Graphics2D g2d = (Graphics2D)g;
g2d.setColor(Color.BLACK);
g2d.fillRect(0,0,getSize().width,getSize().height);
if(left==true)
{
trans.translate(-10,0);
left = false;
repaint();
}
if(right==true)
{
trans.translate(10,0);
right = false;
repaint();
}
g2d.drawImage(image,0,0,this);
}
public void keyPressed(KeyEvent e)
{
int keycode = e.getKeyCode();
switch(keycode)
{
case KeyEvent.VK_RIGHT:
right = true;
repaint();
case KeyEvent.VK_LEFT:
left = true;
repaint();
}
}
public void keyTyped(KeyEvent e){}
public void keyReleased(KeyEvent e){}
}
Can someone please comment or answer? I feel a "tumbleweed" badge heading my way.
Overall, the approach you're learning from your book is far from ideal for games but I touched up the code anyway.
import java.awt.*;
import java.net.*;
import java.awt.event.*;
import java.awt.geom.*;
import java.applet.*;
public class DisplayImage extends Applet implements KeyListener{
int coordX=0;//ship x axis position
int coordY=0;//ship y axis position
/*
0-------------------------x
0|
|
|
|
|
|
y
*/
public URL getURL(String filename)
{
URL url = null;
try
{
url = this.getClass().getResource(filename);
}
catch(Exception e){e.printStackTrace();}
return url;
}
private Image image;
public void init()
{
image = getImage(getURL("spaceship.png"));
addKeyListener(this);
}
public void update(){repaint();}//let update control the calls to repaint
public void paint(Graphics g)
{
Graphics2D g2d = (Graphics2D)g;
g2d.setColor(Color.BLACK);
g2d.fillRect(0,0,getSize().width,getSize().height);
g2d.drawImage(image,coordX,coordY,this);//paint the spaceship to the updated coordinates
}
public void keyPressed(KeyEvent e)
{
int keycode = e.getKeyCode();
//37=left arrow. 39=right arrow. 38=up & 40=down
if(keycode==37){coordX-=1;}else if(keycode==39){coordX+=1;}
if(keycode==38){coordY-=1;}else if(keycode==40){coordY+=1;}
update();//request repaint when logic has updated
}
public void keyTyped(KeyEvent e){}
public void keyReleased(KeyEvent e){}
}
Cheers
EDIT::
This is the basic concept you want to work on.
private void mainGameLoop(){
while(pause==false){
updateLogic();//process movement, detect collisions etc
renderGraphics();//draw a new frame
try{Thread.sleep(25);}catch(InterruptedException e){e.printStackTrace();}//sleep the thread to control the frame rate. (there are more efficient ways to sleep a thread but this is the most simplistic)
}
}
Related
I am new to Java and I am trying to make a simple game for fun.
I first tried to put repaint into paintComponent(), it worked until I tried to add some background.
Does anyone know how to let my player move with or without 'repaint'?
Screen class
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
class Frame extends JFrame implements KeyListener
{
Map map;
public static void main(String[] args)
{
Frame frame = new Frame();
frame.addKeyListener(new Frame());
frame.setVisible(true);
}
public Frame()
{
setInit();
}
private void setInit()
{
map = new Map();
add(map);
setSize(800, 800);//frame size 300 width and 300 height
setTitle("Eerste Game");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo(null);
setResizable(false);
setLayout(new GridLayout(1,1,0,0));
setFocusable(true);
setVisible(true);
}
public void keyPressed(KeyEvent e) {
int keyCode = e.getKeyCode();
map.movePlayer(keyCode);
}
public void keyReleased(KeyEvent e)
{
}
public void keyTyped(KeyEvent e)
{
}
}
Map class
import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
class Map extends JPanel
{
Player player;
BufferedImage map;
public Map() {
player = new Player();
try{map = ImageIO.read(new File("img/map.png"));}catch (Exception e){};
}
public void movePlayer(int keyPressed)
{
player.move(keyPressed);
revalidate();
repaint();
}
#Override
public void paintComponent(Graphics g)
{
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.drawImage(player.img,player.getX(),player.getY(), null);
}
}
Player class
import java.awt.event.KeyEvent;
import java.awt.image.BufferedImage;
import java.io.File;
import javax.imageio.ImageIO;
class Player
{
BufferedImage img = null;
private int x = 100;
private int y = 100;
public Player()
{
try{img = ImageIO.read(new File("img/bob.png"));}catch (Exception e){}
}
public int getX()
{
return x;
}
public int getY()
{
return y;
}
public void move(int keyPressed)
{
if(keyPressed == KeyEvent.VK_W) {
// handle up
y = y - 5;
}
if (keyPressed == KeyEvent.VK_A) {
// handle links
x = x - 5;
}
if (keyPressed == KeyEvent.VK_S) {
// handle onder
y = y + 5;
}
if (keyPressed == KeyEvent.VK_D ) {
// handle right
x = x + 5;
}
}
}
You're unnecessarily creating a new Frame object as the KeyListener, and so the KeyListener events all go to a different Frame instance, not the one being shown. Change
frame.addKeyListener(new Frame());
to:
frame.addKeyListener(frame);
So that now the KeyListener drives the true displayed Frame instance of interest.
Other issues, this is not good:
catch (Exception e){}
Always catch specific exceptions and almost always, you should handle them. At least do something like this:
catch (IOException e) {
e.printStacktrace();
}
You do:
frame.addKeyListener(new Frame());
Which creates a new frame instead of adding the current frame as the Listener.
So you change it tO
frame.addKeyListener(frame);
My program has 3 java files, namely Frame, Dude(which contains the character) and Board(which implements the actionListener). My program is not throwing any error and the images(background and character) are rendering good. But the character is not moving forward.
import javax.swing.*;
public class Frame {
public static void main(String[] args){
JFrame frame= new JFrame("2D Game");
frame.add(new Board());
frame.setVisible(true);
frame.setSize(1200, 600);
}
}
import java.awt.*;
import java.awt.event.KeyEvent;
import javax.swing.*;
public class Dude {
int x, dx, y;
Image still;
public Dude(){
ImageIcon i = new ImageIcon("/home/amitabh/Pictures/man1.jpg");
still= i.getImage();
x=10;
y=172;
}
public void move(){
x=x+dx;
}
public int getX(){
return x;
}
public int getY(){
return y;
}
public Image getImage(){
return still;
}
public void keyPressed(KeyEvent e){
int key= e.getKeyCode();
if(key== KeyEvent.VK_LEFT);
dx= -1;
if(key== KeyEvent.VK_RIGHT);
dx= 1;
}
public void keyReleased(KeyEvent e){
int key= e.getKeyCode();
if(key==KeyEvent.VK_LEFT);
dx=0;
if(key==KeyEvent.VK_RIGHT);
dx=0;
}
}
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class Board extends JPanel implements ActionListener{
Image img;
Timer time;
Dude p;
public Board(){
p= new Dude();
addKeyListener(new AL());
setFocusable(true);
ImageIcon i= new ImageIcon("/home/amitabh/Pictures/game1.png");
img= i.getImage();
time= new Timer(5,this);
time.start();
}
#Override
public void actionPerformed(ActionEvent e) {
p.move();
repaint();
}
public void paint(Graphics g){
super.paint(g);
Graphics2D g2d= (Graphics2D)g;
g2d.drawImage(img, 0,0, null);
g2d.drawImage(p.getImage(), p.getX(), p.getY(), null);
}
public class AL extends KeyAdapter{
public void keyReleased(KeyEvent e){
p.keyReleased(e);
}
public void KeyPressed(KeyEvent e){
p.keyPressed(e);
}
}
}
Start by talking a very close look at:
if (key == KeyEvent.VK_LEFT);
Does that look funny to you?
if (key == KeyEvent.VK_LEFT); // <--- What's the ; doing here?
Change it to be more like...
if (key == KeyEvent.VK_LEFT) {
dx = 0;
}
And, yes, this is why you're encouraged to use { ... }
Next, take a closer look at...
public void KeyPressed(KeyEvent e) {
See anything wrong there? Why does it start with an uppercase K, that's not the correct method signature
Change to something more like...
#Override
public void keyReleased(KeyEvent e) {
p.keyReleased(e);
}
#Override
public void keyPressed(KeyEvent e) {
p.keyPressed(e);
}
Yes, this is why you're encouraged to use #Override ;)
And finally change your paint method to paintComponent
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
You are encouraged to override paintComponent when performing custom painting, it tends to cause less issues
I'd also encorage you to have a look at the Key Bindings API and favour it over KeyListener as it provides better control of the focus level required to trigger the key events
I'd also encourage your to override getPreferredSize of the Board and return your preferred size from there, rather then setting the frame's size. The frame size includes the frame's decorations, so you content is smaller then the frame size
I've been attempting some sprite animation in with Java and redrawing it, however I can't seem to get my sprite to redraw properly on the Canvas. At first the Problem was that the Previous frames were still there in the back ground of the Canvas when I re-drew it so in order to fix that I added a call to .clearRect(); However while adding the call to that function did fix that problem it caused me to start loosing frames like crazy. I've searched and tried a few things but could find a solution and as near as I can figure .clearRect() is on occasion getting executed after .drawImage(). the Code for my canvas is as Fallows:
package rpg;
import java.awt.Canvas;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
public class Sprite extends Canvas{
/**
*
*/
private BufferedImage img;
private static final long serialVersionUID = 1L;
public Sprite(int width, int height, BufferedImage img){
this.img = img;
setSize(width, height);
}
#Override
public void paint(Graphics g)
{
Graphics2D g2d = (Graphics2D) g;
g2d.clearRect(0, 0, this.getWidth(), this.getHeight());
g2d.drawImage(img, 0, 0, null);
g2d.dispose();
}
#Override
public void update(Graphics g) {
paint(g);
}
public void changeSprite(BufferedImage img)
{
this.img = img;
repaint();
}
}
Note: I'm Working with a Transparent background and would like to keep it transparent.
At first the Problem was that the Previous frames were still there in the back ground of the Canvas when I re-drew it so in order to fix that I added a call to .clearRect();
Don't use clearRect(). Instead you should use fillRect(...) to paint the background color of the component.
The following is from the API of the clearRect() method:
Beginning with Java 1.1, the background color of offscreen images may be system dependent. Applications should use setColor followed by fillRect to ensure that an offscreen image is cleared to a specific color.
However, you don't even need to do that. When you override a painting method you need to invoke super.thePaintingMethod(...). In this case you are attempting to override the paint() method so the first statement should be:
super.paint(g);
Then the default painting code of the component will paint the background for you.
Also, this is not Swing painting code. This is AWT code. You really should tag your question properly. We don't know if you are actually trying to do painting using Swing techniques or whether you found old AWT painting code and assume it is the same in Swing.
I'm working with a transparent background
Umm... And why are you trying to use AWT? You still haven't qualified your question. Since you haven't removed the "Swing" tag, I assume you are using Swing.
Using Swing the code would be:
JLabel sprite = new JLabel( new ImageIon(...) );
That's it. One line of code. No need for a custom class.
To change the image you would then just use:
sprite.setIcon( new ImageIcon(...) );
Probably this little example code helps you...
import javax.swing.JFrame;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.image.BufferedImage;
import java.io.*;
import javax.imageio.ImageIO;
import javax.swing.JPanel;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.awt.EventQueue;
class Player {
public float health;
public float yvel;
public float xvel;
public float x;
public float y;
public BufferedImage image;
public void work(Graphics g, int[] keys) {
g.drawImage(image,(int)x,(int)y,null);
if (keys[0]==1) { //Is the UP-Key pressed
yvel=yvel-1;
}
if (keys[1]==1) { //Is the DOWN-Key pressed
yvel=yvel+1;
}
if (keys[2]==1) { //Is the LEFT-Key pressed
xvel=xvel-1;
}
if (keys[3]==1) { //Is the RIGHT-Key pressed
xvel=xvel+1;
}
x=x+xvel;
y=y+yvel;
xvel=xvel-(xvel/4); //One fourth gets lost
yvel=yvel-(yvel/4); //One fourth gets lost
}
public Player(BufferedImage imagew,float xw, float yw, float healthw) {
x=xw;
y=yw;
image=imagew;
health=healthw;
}
}
public class Game extends JFrame implements KeyListener {
public BufferedImage playerimage;
public Player player;
public int[] keys=new int[4];
public void keyTyped(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_UP) {
keys[0]=1;
}
if (e.getKeyCode() == KeyEvent.VK_DOWN) {
keys[1]=1;
}
if (e.getKeyCode() == KeyEvent.VK_LEFT) {
keys[2]=1;
}
if (e.getKeyCode() == KeyEvent.VK_RIGHT) {
keys[3]=1;
}
}
public void keyReleased(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_UP) {
keys[0]=0;
}
if (e.getKeyCode() == KeyEvent.VK_DOWN) {
keys[1]=0;
}
if (e.getKeyCode() == KeyEvent.VK_LEFT) {
keys[2]=0;
}
if (e.getKeyCode() == KeyEvent.VK_RIGHT) {
keys[3]=0;
}
}
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_UP) {
keys[0]=1;
}
if (e.getKeyCode() == KeyEvent.VK_DOWN) {
keys[1]=1;
}
if (e.getKeyCode() == KeyEvent.VK_LEFT) {
keys[2]=1;
}
if (e.getKeyCode() == KeyEvent.VK_RIGHT) {
keys[3]=1;
}
if (e.getKeyCode() == KeyEvent.VK_SPACE) {
keys[4]=1;
}
}
public Game(){
super("Game");
try {
playerimage = ImageIO.read(getClass().getClassLoader().getResource("player.gif")); //Player Image
} catch(IOException bug) {
System.out.println(bug);
}
player=new Player(playerimage,100,100,100);
addKeyListener(this);
setTitle("Game");
setContentPane(new Pane());
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(800, 600);
setResizable(false);
setVisible(true);
long start = System.currentTimeMillis();
while (true){
long now = System.currentTimeMillis();
if (now-start > 40) {
System.out.println("FPS : "+Long.toString(1000/(now-start)));
start=now;
framec++;
if (framec==250) {
System.gc();
}
validate();
repaint();
}
}
}
class Pane extends JPanel{
public Pane() {
}
public void paintComponent(Graphics g){
player.work(g,keys);
}
}
public static void main(String args[]){
new Game();
}
}
It draws a controllable player with velocity...
Background should be transparent...
I'm trying to modify this program so that it draws an image of a castle and I am able to scale this image using the up and down arrow keys. I can't manage to get the keylistener to work, the program runs but it isn't responding to key presses. Any help will be appreciated, thanks.
import java.awt.*;
import java.awt.geom.*;
import java.util.*;
import javax.swing.*;
import java.net.*;
import java.awt.event.*;
public class DrawImage extends JFrame implements KeyListener {
int scale = 1;
private Image image;
enter code here
public static void main(String[] args) {
new DrawImage();
}
public DrawImage() {
super("DrawImage");
setSize(600,600);
setVisible(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Toolkit tk = Toolkit.getDefaultToolkit();
image = tk.getImage(getURL("castle.png"));
addKeyListener(this);
}
private URL getURL(String filename) {
URL url = null;
try {
url = this.getClass().getResource(filename);
}
catch (Exception e) { }
return url;
}
public void paint(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
AffineTransform trans = new AffineTransform();
trans.scale(scale, scale);
System.out.println("scale: " + scale);
g2d.setColor(Color.BLACK);
g2d.fillRect(0, 0, getSize().width, getSize().height);
g2d.setTransform(trans);
g2d.drawImage(image, 0, 40, this);
addKeyListener(this);
}
public void keyReleased(KeyEvent e) { }
public void keyTyped(KeyEvent e) { }
public void keyPressed(KeyEvent e) {
int key = e.getKeyCode();
if (key == KeyEvent.VK_UP) {
scale++;
}
if (key == KeyEvent.VK_DOWN) {
scale--;
}
}
}
I can't manage to get the keylistener to work, the program runs but it isn't responding to key presses.
Yours is a very common problem that is asked here frequently, and almost always the problem is due to lack of focus -- that the component being listened to does not have the current focus, and focus is essential for a KeyListener to work.
The short answer is to give the component that is being listened to the focus.
The longer better answer is to not use KeyListeners and instead to use Key Bindings for such a project.
Edit
Other problems:
In your code above, you're adding the KeyListener to a JFrame, and this shouldn't be done, even if you had good reason to use KeyListeners.
You're also drawing directly in the JFrame which in my opinion is an even bigger problem, since you risk unwanted side effects.
You're adding a listener inside of the paint method, an even bigger problem. The paint method should not be overridden (in general), and if you did have to override it, should never be used for program logic, for adding or removing listeners, or for doing any non-painting activities. It should be for painting and painting only.
Instead you should draw directly in a JPanel or JComponent.
Instead you should do the drawing in a paintComponent(Graphics g) override in your painting JPanel or JComponent.
Just as described above, this method should be for painting and painting only and should be as fast as possible.
You should call the super.paintComponent(g) inside of your paintComponent(Graphics g) override.
Again the drawing component should listen for key strokes using Key Bindings (tutorial here). The tutorial will explain why this distinction (KeyListener vs. Key Bindings) is important.
Edit 2
You never want to ignore exceptions as your code shows here since this is the programming equivalent of driving blind:
try {
url = this.getClass().getResource(filename);
} catch (Exception e) {
}
Hopefully this is not how your production code looks, that you only ignored the exceptions in your posted code for the sake of brevity, but understand for many of us seeing this is like hearing nails on a chalk-board.
Edit 3
More on KeyListeners vs. Key Bindings: Assuming that you got your code to work with a KeyListener, then assume that you added any other focusable components to your GUI and they somehow got the focus via user interaction, then your KeyBindings will no longer work. If you had done this correctly with Key Bindings, this would not be an issue.
Edit 4
You really want your scale field to be a double, not an int. And you really don't want to increment and decrement it, but rather you want to multiply it and divide it by some multiplier constant, say 1.2 as an example. You will also want to call repaint() whenever you change your scale.
Edit 5
Please check out two sample programs, the first, called DrawImagePanelKeyListener.java, uses a KeyListener, while the second, called DrawImagePanelKeyBindings, uses Key Bindings. They both should compile, run, and function as expected: when you press the up or down arrow keys, the displayed image shrinks and grows. The difference in their behavior though can be seen when the JButton both have is pressed. Press the button and see what happens to your key response. When the component that has a KeyListener loses focus, its KeyListener will stop working, but the same is not true for the component that uses Key Bindings.
A kludge that could get around this problem could be to prevent all other components from getting the focus, but that is not practical or desired with most GUI's.
DrawImagePanelKeyListener.java
import java.awt.*;
import javax.imageio.ImageIO;
import javax.swing.*;
import java.io.IOException;
import java.net.*;
import java.awt.event.*;
#SuppressWarnings("serial")
public class DrawImagePanelKeyListener extends JPanel implements KeyListener {
public static final String IMAGE_PATH = "https://duke.kenai.com/"
+ "nyanya/.Midsize/NyaNya.jpg.png";
private static final double MULTIPLIER = 1.2;
double scale = 1.0;
private Image image;
private Dimension initialSize = new Dimension(0, 0);
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
DrawImagePanelKeyListener drawImage = new DrawImagePanelKeyListener();
drawImage.add(new JButton("Foo"));
JFrame frame = new JFrame("Draw Image");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(drawImage);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public DrawImagePanelKeyListener() {
setFocusable(true);
requestFocusInWindow();
URL imgURL;
try {
imgURL = new URL(IMAGE_PATH);
image = ImageIO.read(imgURL);
initialSize = new Dimension(image.getWidth(this),
image.getHeight(this));
addKeyListener(this);
setVisible(true);
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
#Override
public Dimension getPreferredSize() {
return initialSize;
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.BLACK);
g.fillRect(0, 0, getSize().width, getSize().height);
Graphics2D g2d = (Graphics2D) g.create();
g2d.scale(scale, scale);
g2d.drawImage(image, 0, 0, this);
}
public void keyReleased(KeyEvent e) {
}
public void keyTyped(KeyEvent e) {
}
public void keyPressed(KeyEvent e) {
int key = e.getKeyCode();
if (key == KeyEvent.VK_UP) {
scale *= MULTIPLIER;
}
if (key == KeyEvent.VK_DOWN) {
scale /= MULTIPLIER;
}
repaint();
}
}
DrawImagePanelKeyBindings.java
import java.awt.*;
import javax.imageio.ImageIO;
import javax.swing.*;
import java.io.IOException;
import java.net.*;
import java.awt.event.*;
#SuppressWarnings("serial")
public class DrawImagePanelKeyBindings extends JPanel {
public static final String IMAGE_PATH = "https://duke.kenai.com/"
+ "nyanya/.Midsize/NyaNya.jpg.png";
private static final double MULTIPLIER = 1.2;
double scale = 1.0;
private Image image;
private Dimension initialSize = new Dimension(0, 0);
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
DrawImagePanelKeyBindings drawImage = new DrawImagePanelKeyBindings();
drawImage.add(new JButton("Foo"));
JFrame frame = new JFrame("Draw Image");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(drawImage);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public DrawImagePanelKeyBindings() {
setBindings();
URL imgURL;
try {
imgURL = new URL(IMAGE_PATH);
image = ImageIO.read(imgURL);
initialSize = new Dimension(image.getWidth(this),
image.getHeight(this));
setVisible(true);
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
private void setBindings() {
int condition = WHEN_IN_FOCUSED_WINDOW;
InputMap inputMap = getInputMap(condition);
ActionMap actionMap = getActionMap();
final KeyStroke[] keyStrokes = {
KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0),
KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0)
};
for (final KeyStroke keyStroke : keyStrokes) {
inputMap.put(keyStroke, keyStroke.toString());
actionMap.put(keyStroke.toString(), new AbstractAction() {
#Override
public void actionPerformed(ActionEvent evt) {
myKeyPressed(keyStroke.getKeyCode());
}
});
}
}
#Override
public Dimension getPreferredSize() {
return initialSize;
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.BLACK);
g.fillRect(0, 0, getSize().width, getSize().height);
Graphics2D g2d = (Graphics2D) g.create();
g2d.scale(scale, scale);
g2d.drawImage(image, 0, 0, this);
}
public void myKeyPressed(int key) {
if (key == KeyEvent.VK_UP) {
scale *= MULTIPLIER;
}
if (key == KeyEvent.VK_DOWN) {
scale /= MULTIPLIER;
}
repaint();
}
}
A simple question with a perhaps not so simple solution. My code is supposed to show a triangle on a black background that can be moved around onscreen. Only nothing displays, just a white area that can't be right-clicked on. It does not work in either the appletviewer or an HTML document, and shows no syntax errors. What is wrong with my code?
import java.awt.*;
import java.applet.*;
import java.awt.geom.*;
import java.awt.image.BufferedImage;
import java.awt.event.*;
public class Shipmovementtest extends Applet implements Runnable,KeyListener{
Graphics2D g2d;
Ship ship1 = new Ship();
BufferedImage backbuffer;
AffineTransform identity = new AffineTransform();
Shape ship1shape;
Thread gameloop;
public void start()
{
gameloop = new Thread(this);
gameloop.start();
}
public void run()
{
Thread t = Thread.currentThread();
while(gameloop==t)
{
try
{
Thread.sleep(20);
}
catch(InterruptedException e)
{
e.printStackTrace();
}
repaint();
}
}
public void stop()
{
gameloop = null;
}
public void init()
{
ship1shape = ship1.getShape();
backbuffer = new BufferedImage(640,480,BufferedImage.TYPE_INT_RGB);
g2d = backbuffer.createGraphics();
addKeyListener(this);
setFocusable(true);
requestFocusInWindow();
}
public void update(Graphics g)
{
g2d.setTransform(identity);
g2d.setPaint(Color.BLACK);
g2d.fillRect(0,0,getSize().width,getSize().height);
drawShip();
paint(g);
}
public void keyTyped(KeyEvent e){}
public void keyPressed(KeyEvent e)
{
int ke = e.getKeyCode();
switch(ke)
{
case KeyEvent.VK_LEFT:
ship1.setFaceAngle(ship1.getFaceAngle()-5);
break;
case KeyEvent.VK_RIGHT:
ship1.setFaceAngle(ship1.getFaceAngle()+5);
break;
case KeyEvent.VK_UP:
ship1.incX(-ship1.calcAngleMoveX(ship1.getFaceAngle())*ship1.velocity);
ship1.incY(-ship1.calcAngleMoveY(ship1.getFaceAngle())*ship1.velocity);
break;
case KeyEvent.VK_DOWN:
ship1.incX(ship1.calcAngleMoveX(ship1.getFaceAngle())*ship1.velocity);
ship1.incY(ship1.calcAngleMoveY(ship1.getFaceAngle())*ship1.velocity);
break;
}
}
public void paint(Graphics g)
{
g2d.drawImage(backbuffer,0,0,this);
}
public void keyReleased(KeyEvent e){}
public void drawShip()
{
g2d.setTransform(identity);
g2d.translate(ship1.getX(),ship1.getY());
g2d.rotate(Math.toRadians(ship1.getFaceAngle()));
g2d.setColor(ship1.getColor());
g2d.fill(ship1.getShape());
}
}
In the end of paint you need to actually draw the buffer to the real graphics g. Currently you are only painting in the buffer.
So correct code would be
public void paint(Graphics g)
{
g.drawImage(backbuffer,0,0,this);
}