Java Applet repaint from another class - java

I am learning Java game development and I am having an issue understanding why the "Robot" is not moving.
I know the issue is with the repaint but I can not figure it out.
please help
Thank
Game Class
public class GameMain extends Applet implements KeyListener {
private Image image, character;
private Graphics gpx;
private Droid droid;
private URL base;
private static Background bg1, bg2;
#Override
public void init() {
setSize(800, 480);
setBackground(Color.BLACK);
setFocusable(true);
addKeyListener(this);
Frame frame = (Frame) this.getParent().getParent();
frame.setTitle("My First Game");
droid = new Droid();
base = getDocumentBase();
character = getImage(base, "data/char.png");
}
#Override
public void start() {
GameThread thread = new GameThread();
thread.start();
System.out.println("Thread Started");
}
#Override
public void stop() {
}
#Override
public void destroy() {
}
#Override
public void update(Graphics g) {
if(image == null){
image = createImage(this.getWidth(), this.getHeight());
gpx = image.getGraphics();
}
gpx.setColor(getBackground());
gpx.fillRect(0, 0, getWidth(), getHeight());
gpx.setColor(getForeground());
paint(gpx);
g.drawImage(image, 0, 0, this);
}
#Override
public void paint(Graphics g) {
g.drawImage(character, droid.getPositionX() - 61, droid.getPositionY()- 63, this);
}
#Override
public void keyPressed(KeyEvent key) {
switch(key.getKeyCode() ){
case KeyEvent.VK_UP:
break;
case KeyEvent.VK_DOWN:
break;
case KeyEvent.VK_LEFT:
droid.moveLeft();
break;
case KeyEvent.VK_RIGHT:
droid.moveRight();
break;
case KeyEvent.VK_SPACE:
droid.jump();
break;
}
}
#Override
public void keyReleased(KeyEvent key) {
switch(key.getKeyCode() ){
case KeyEvent.VK_UP:
break;
case KeyEvent.VK_DOWN:
break;
case KeyEvent.VK_LEFT:
droid.stop();
break;
case KeyEvent.VK_RIGHT:
droid.stop();
break;
case KeyEvent.VK_SPACE:
break;
}
}
#Override
public void keyTyped(KeyEvent key) {
// TODO Auto-generated method stub
}
}
Thread Class
public class GameThread extends Thread {
GameMain game;
Droid droid;
private static Background bg1, bg2;
public GameThread(){
bg1 = new Background(0,0);
bg2 = new Background(2160, 0);
}
#Override
public void run() {
game = new GameMain();
droid = new Droid();
//Game while loop
while(true){
droid.update();
game.repaint();
//bg1.update();
//bg2.update();
try {
Thread.sleep(17);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
Droid Class
public class Droid {
private int positionX = 100;
private int positionY = 382;
private int speedX = 0;
private int speedY = 1;
private boolean jump = false;
public void update(){
//Update X Position
if(speedX < 0){
positionX += speedX;
}else if(speedX == 0){
System.out.println("Do not scroll the background.");
}else{
if(positionX <= 150){
positionX += speedX;
}else{
System.out.println("Scroll Background Here");
}
}
//Update Y Position
if(positionY + speedY >= 382){
positionY = 382;
}else{
positionY += speedY;
}
//update Jump
if(jump == true){
speedY += 1;
if(positionY + speedY >= 382){
positionY = 382;
speedY = 0;
jump = false;
}
}
}
public void moveRight(){
speedX = 6;
System.out.println(speedX);
}
public void moveLeft(){
speedX = -6;
System.out.println(speedX);
}
public void stop(){
speedX = 0;
}
public void jump(){
if(jump == false){
speedY = -15;
jump = true;
}
}
public void setPositionX(int positionX){
this.positionX = positionX;
}
public int getPositionX(){
return positionX;
}
public void setPositionY(int positionY){
this.positionY = positionY;
}
public int getPositionY(){
return positionY;
}
public void setSpeedX(int speedX){
this.speedX = speedX;
}
public int getSpeedX(){
return speedX;
}
public void setSpeedY(int speedY){
this.speedY = speedY;
}
public int getSpeedY(){
return speedY;
}
}

The problem is, the droid you're updating isn't the droid you're painting...in fact, the GameMain you're repainting isn't the one that is one the screen...
public class GameMain extends Applet implements KeyListener {
//...
private Droid droid;
//...
#Override
public void init() {
//...
droid = new Droid();
//...
}
#Override
public void paint(Graphics g) {
g.drawImage(character, droid.getPositionX() - 61, droid.getPositionY()- 63, this);
}
And then in you GameThread;
public class GameThread extends Thread {
GameMain game;
Droid droid;
//...
#Override
public void run() {
// Created a new GameMain
game = new GameMain();
// Created a new Droid...
droid = new Droid();
//Game while loop
while (true) {
droid.update();
game.repaint();
//...
You create new instances of GameMain and Droid, these have no connection what so ever to the screen.
Instead, you should be passing a reference of GameMain to the GameThread and GameThread should be telling GameMain to update the game state...
For example...
Add the method updateGameState
public class GameMain extends Applet implements KeyListener {
//...
public void updateGameState() {
droid.update();
repaint();
}
//...
Then in GameMain's start method, pass a reference of GameMain to GameThread...
GameThread thread = new GameThread(this);
thread.start();
Then in GameMain, store the reference you are passed and remove any reference to Droid
public class GameThread extends Thread {
//...
private GameMain gameMain;
public GameThread(GameMain gameMain) {
this.gameMain = gameMain;
//...
Then in GameTread#run, call gameMain.updateGameState();...
public void run() {
while (true) {
gameMain.updateGameState();
try {
Thread.sleep(17);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
As a side note...
Applet is outdated, you should be using JApplet
I'd be very careful using this.getParent().getParent(), you may not like the results if you deployed this in a browser..
And when you start using JApplet, move you game rendering to something like JPanel, overriding it's paintComponent method, this will give you automatic double buffering and use the Key binding API over KeyListener. It's more easily, programmatically, updatable and doesn't suffer from the same focus related issues as KeyListener

Related

adding keylistener returns null pointer exception

I am learning to program 2d games in java for quite a while. In my lastest game I have tried to create a private class that will handle the key events from within the Player class, I did it like this:
package game;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
public class Player {
final private int MOVEMENTSPEED = 4;
final private int BOOST = 8;
final private EventHandler HANDLER = new EventHandler();
private int x, y;
private int speedX, speedY;
public Player(int x, int y){
this.x = x;
this.y = y;
}
public void update(){
x += speedX;
y += speedY;
}
public int getSpeedX() {
return speedX;
}
public int getSpeedY() {
return speedY;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
public EventHandler getHandler(){
return HANDLER;
}
private class EventHandler implements KeyListener{
#Override
public void keyPressed(KeyEvent e) {
switch(e.getKeyCode()){
case KeyEvent.VK_W: speedY = -MOVEMENTSPEED;
break;
case KeyEvent.VK_S: speedY = MOVEMENTSPEED;
break;
case KeyEvent.VK_A: speedX = -MOVEMENTSPEED;
break;
case KeyEvent.VK_D: speedX = MOVEMENTSPEED;
break;
}
}
#Override
public void keyReleased(KeyEvent e) {
switch(e.getKeyCode()){
case KeyEvent.VK_W: speedY = 0;
case KeyEvent.VK_S:
break;
case KeyEvent.VK_A: speedX = 0;
case KeyEvent.VK_D:
break;
}
}
#Override
public void keyTyped(KeyEvent e) {
// TODO Auto-generated method stub
}
}
and here is where i try to add the eventHandler class to the class that deals with the game loop, painting and such:
public class FrameWork extends Applet implements Runnable {
private URL base;
private Graphics second;
private Image image;
public static Player p;
#Override
public void start() {
p = new Player(400, 400);
Thread thread = new Thread(this);
thread.start();
}
#Override
public void init() {
setSize(1000, 600);
setFocusable(true);
Frame frame = (Frame) this.getParent().getParent();
frame.setTitle("Assassin");
frame.setResizable(false);
**this.addKeyListener(p.getHandler());**
}
I have already worked with keylistener but did it either without the an extra class (implementing the methods within the same class of the game loop) or by creating a completely differnent class and using its instance.
Anyway I tried to do it differently because it seemed more comfortable but it always returns the error java.lang.NullPointerException and I don't understand why.
Thanks for help
The lifecycle of an Applet starts with init and later start is called.
You initialize the player in start which is called after init, therefore p in init is null.
Create the player in the init method.
See Applet lifecycle: what's the practical difference between init() & start(), and destroy() & stop()?
Try making these changes:
Make your Player variable non-static.
Initialize this variable in the init() method rather than the start() method.
public Player p; //changed this to be an instance variable (non-static)
#Override
public void start() {
//moved initialization of player to init() method
Thread thread = new Thread(this);
thread.start();
}
#Override
public void init() {
setSize(1000, 600);
setFocusable(true);
Frame frame = (Frame) this.getParent().getParent();
frame.setTitle("Assassin");
frame.setResizable(false);
p = new Player(400, 400); //initialize Player here
this.addKeyListener(p.getHandler());
}

Make this cube's movement smoother?

I've been working the movement of this cube, however, its movement is pretty ugly and sudden, so is there anyway that I could make it "smooth" and "clean"?
Here is my code:
import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
public class Main extends JPanel implements KeyListener
{
Environment environment = new Environment ();
Cube cube = new Cube ();
JFrame frame = new JFrame ();
int cubeX = cube.cube.x;
int cubeY = cube.cube.y;
// Paint method used to repaint the cube's location
public void paint (Graphics g)
{
Graphics2D g2d = (Graphics2D) g;
g2d.setRenderingHint (RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
environment.createBox (g2d);
cube.createCube (g2d);
}
// Getting pressed keys to move cube
#Override
public void keyPressed (KeyEvent e)
{
if (e.getKeyCode () == KeyEvent.VK_UP)
{
try
{
cube.isCubeMoving = true;
cube.moveCube ();
Thread.sleep (10);
frame.repaint ();
}
catch (InterruptedException ie)
{
ie.printStackTrace ();
}
}
else if (e.getKeyCode () == KeyEvent.VK_DOWN)
{
cube.cube.y = cube.cube.y + 100;
if (cube.cube.y > 620)
{
cube.cube.y = 620;
}
try
{
Thread.sleep (10);
frame.repaint ();
}
catch (InterruptedException e1)
{
e1.printStackTrace ();
}
}
}
#Override
public void keyReleased (KeyEvent arg0)
{
}
#Override
public void keyTyped (KeyEvent arg0)
{
}
// Main method
public static void main (String[] args) throws InterruptedException
{
Main m = new Main ();
m.frame.add (m);
m.frame.addKeyListener (m);
m.frame.setSize (700, 1000);
m.frame.setVisible (true);
m.frame.setTitle ("The Cube");
m.frame.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
m.frame.setResizable (true);
m.frame.setLocationRelativeTo (null);
m.frame.setBackground (new Color (240, 84, 84));
while (true)
{
m.frame.repaint ();
Thread.sleep (3);
}
}
}
Here's the Cube class:
import java.awt.*;
public class Cube extends Thread
{
public int x = 200;
public int y = 620;
public boolean isCubeMoving = true;
int whereCubeStops = 440;
Runnable r = new Runnable ()
{
public void run ()
{
while (isCubeMoving == true)
{
cube.setLocation (x, y -= 10);
System.out.println (y);
if (y == whereCubeStops)
{
try
{
isCubeMoving = false;
cube.setLocation (x, y = 620);
Thread.sleep (100);
}
catch (InterruptedException e)
{
e.printStackTrace ();
}
}
try
{
Thread.sleep (10);
}
catch (InterruptedException e)
{
e.printStackTrace ();
}
}
}
};
Rectangle cube = new Rectangle (x, y, 80, 80);
public void createCube (Graphics2D g2d)
{
g2d.setColor (new Color (148, 235, 148));
g2d.fill (cube);
}
public void moveCube ()
{
new Thread (r).start ();
}
}
Thanks very much for all your help!
:)
Well, for this, we have to write a proper game loop. Let's start one by one:
Here's my GameFrame:
import javax.swing.*;
import java.awt.*;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
public abstract class GameFrame extends JFrame
{
private GamePanel gamePanel;
public GameFrame (String gameTitle, GamePanel gamePanel)
{
super (gameTitle);
this.gamePanel = gamePanel;
setDefaultCloseOperation (WindowConstants.EXIT_ON_CLOSE);
addWindowListener (new FrameListener ());
getContentPane ().setLayout (new GridBagLayout ());
getContentPane ().add (gamePanel);
pack ();
setLocationRelativeTo (null);
setResizable (false);
setVisible (true);
}
public class FrameListener extends WindowAdapter
{
public void windowActivated (WindowEvent event)
{
gamePanel.setWindowPaused (false);
}
public void windowDeactivated (WindowEvent event)
{
gamePanel.setWindowPaused (true);
}
public void windowDeiconified (WindowEvent event)
{
gamePanel.setWindowPaused (false);
}
public void windowIconified (WindowEvent event)
{
gamePanel.setWindowPaused (true);
}
public void windowClosing (WindowEvent event)
{
gamePanel.stopGame ();
}
}
}
Its an abstract class, and all it does is put a GamePanel in it, and make itself visible when initialised.
Here's my GamePanel which implements a game loop:
import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
public abstract class GamePanel extends JPanel implements Runnable
{
private int panelWidth;
private int panelHeight;
private Thread animator;
private volatile boolean running = false;
private volatile boolean isUserPaused = false;
private volatile boolean isWindowPaused = false;
private Graphics2D dbg;
private Image dbImage = null;
private static final int NO_DELAYS_PER_YIELD = 16;
private static final int MAX_FRAME_SKIPS = 5;
private Color backgroundColor;
private long period;
public GamePanel (int width, int height, long fps, Color backgroundColor)
{
this.panelWidth = width;
this.panelHeight = height;
this.backgroundColor = backgroundColor;
this.period = 1000000L * (long) 1000.0 / fps;
setBackground (backgroundColor);
setPreferredSize (new Dimension (panelWidth, panelHeight));
setFocusable (true);
requestFocus ();
readyForPause ();
addKeyListener (new KeyAdapter ()
{
public void keyPressed (KeyEvent e)
{
consumeKeyPressed (e.getKeyCode ());
}
});
}
protected abstract void consumeKeyPressed (int keyCode);
protected abstract void renderGame (Graphics2D graphics);
protected abstract void updateGame ();
#Override
public void addNotify ()
{
super.addNotify ();
startGame ();
}
protected void startGame ()
{
if (animator == null || ! running)
{
animator = new Thread (this);
animator.start ();
}
}
protected void stopGame ()
{
running = false;
}
private void readyForPause ()
{
addKeyListener (new KeyAdapter ()
{
public void keyPressed (KeyEvent e)
{
int keyCode = e.getKeyCode ();
if ((keyCode == KeyEvent.VK_ESCAPE) || (keyCode == KeyEvent.VK_Q)
|| (keyCode == KeyEvent.VK_END) || (keyCode == KeyEvent.VK_P)
|| ((keyCode == KeyEvent.VK_C) && e.isControlDown ()))
{
setUserPaused (! isUserPaused);
}
}
});
}
public void run ()
{
long beforeTime, afterTime, timeDiff, sleepTime;
long overSleepTime = 0L;
int noDelays = 0;
long excess = 0L;
beforeTime = System.nanoTime ();
running = true;
while (running)
{
requestFocus ();
gameUpdate ();
gameRender ();
paintScreen ();
afterTime = System.nanoTime ();
timeDiff = afterTime - beforeTime;
sleepTime = (period - timeDiff) - overSleepTime;
if (sleepTime > 0)
{
try
{
Thread.sleep (sleepTime / 1000000L);
}
catch (InterruptedException ignored)
{
}
overSleepTime = (System.nanoTime () - afterTime - sleepTime);
}
else
{
excess -= sleepTime;
overSleepTime = 0L;
if (++ noDelays >= NO_DELAYS_PER_YIELD)
{
Thread.yield ();
noDelays = 0;
}
}
beforeTime = System.nanoTime ();
int skips = 0;
while ((excess > period) && (skips < MAX_FRAME_SKIPS))
{
excess -= period;
gameUpdate ();
skips++;
}
}
System.exit (0);
}
private void gameUpdate ()
{
if (! isUserPaused && ! isWindowPaused)
{
updateGame ();
}
}
private void gameRender ()
{
if (dbImage == null)
{
dbImage = createImage (panelWidth, panelHeight);
if (dbImage == null)
{
System.out.println ("Image is null.");
return;
}
else
{
dbg = (Graphics2D) dbImage.getGraphics ();
}
}
dbg.setColor (backgroundColor);
dbg.fillRect (0, 0, panelWidth, panelHeight);
renderGame (dbg);
}
private void paintScreen ()
{
Graphics2D g;
try
{
g = (Graphics2D) this.getGraphics ();
if ((g != null) && (dbImage != null))
{
g.drawImage (dbImage, 0, 0, null);
}
Toolkit.getDefaultToolkit ().sync ();
if (g != null)
{
g.dispose ();
}
}
catch (Exception e)
{
System.out.println ("Graphics context error : " + e);
}
}
public void setWindowPaused (boolean isPaused)
{
isWindowPaused = isPaused;
}
public void setUserPaused (boolean isPaused)
{
isUserPaused = isPaused;
}
}
This again is an abstract class. Its abstract for reusability purpose. You need not know the exact implementation of my game loop. You can create your own custom game panel that inherits from it, and implement the abstract methods of it, and everything will be good to go.
Lets create a Box now:
import java.awt.*;
public class Box extends Rectangle
{
private Color color;
private Direction currentDirection = Direction.None;
private int speed;
public Box (int size, int speed, Color color)
{
super (size, size);
this.speed = speed;
this.color = color;
}
public void update ()
{
switch (currentDirection)
{
case None:
break;
case North:
y -= speed;
break;
case South:
y += speed;
break;
case East:
x += speed;
break;
case West:
x -= speed;
break;
}
}
public void draw (Graphics2D graphics)
{
graphics.setColor (color);
graphics.fill (this);
}
public void setDirection (Direction direction)
{
currentDirection = direction;
}
}
Nothing out of the ordinary here. Its a Rectangle shape, which has update method to update its state based on the Direction it has and a draw method that renders it on screen using the graphics object as context.
The Direction enum used in Box looks as follows:
public enum Direction
{
None,
North,
South,
East,
West
}
So now its time to create our own custom BoxPanel that will inherit from GamePanel. Here's how it looks like:
import java.awt.*;
import java.awt.event.KeyEvent;
public class BoxPanel extends GamePanel
{
private Box box;
public BoxPanel ()
{
super (800, 600, 60, Color.lightGray);
box = new Box (80, 5, Color.darkGray);
}
#Override
protected void consumeKeyPressed (int keyCode)
{
switch (keyCode)
{
case KeyEvent.VK_W:
box.setDirection (Direction.North);
break;
case KeyEvent.VK_S:
box.setDirection (Direction.South);
break;
case KeyEvent.VK_D:
box.setDirection (Direction.East);
break;
case KeyEvent.VK_A:
box.setDirection (Direction.West);
break;
case KeyEvent.VK_SPACE:
box.setDirection (Direction.None);
break;
}
}
#Override
protected void renderGame (Graphics2D graphics)
{
box.draw (graphics);
}
#Override
protected void updateGame ()
{
box.update ();
}
}
It basically creates a box and implements the abstract methods of the GamePanel where all it does is update the box and render the box using appropriate methods present.
The consumeKeyPressed is all about handling key presses, where all I do is set the direction of the box appropriately.
And so finally comes my BoxFrame which wraps everything together into a runnable demonstration:
public class BoxFrame extends GameFrame
{
public BoxFrame ()
{
super ("Box Demo", new BoxPanel ());
}
public static void main (String[] args)
{
new BoxFrame ();
}
}
That's it!
You can use GameFrame and GamePanel in your own projects too. Abstraction really pays off. Doesn't it?
You need not worry if you don't understand part of the game loop or anything. By repeated reading of the code, you'll eventually understand it.
This is a runnable demonstration that shows how you can create smooth movements. I'd suggest you also look into interpolation for creating smooth movements.
You can tweak the FPS value while creating the BoxPanel to vary the smooth factor of the game.
Run the code, read it, re-read it, understand it. Then write it yourself as practice.
FYI, my game loop uses a concept called Double Buffering for rendering the objects smoothly on screen.
You can create other objects too that have update and draw method, and can put their calls in the updateGame and renderGame method of your custom panel, and those objects will appropriately be rendered as well.

Game in Java is not displaying

Hello everyone I am trying to make a game where the user plays as some kind of character, and trys to collect coins while avoiding monsters that spawn. My program compiles with no error, but nothing is showing up when I run the applet. This could be because of the order of extension I have everything in but I am not sure. Any help would be greatly appreciated (this is for a final school project for my intro to Java class). Here is the code, I know it is long but it all pertains to the question at hand:
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import java.util.*;
public class Sprite extends JApplet
{
Image image;
int x, y;
boolean isVisible;
public Sprite()
{
isVisible = false;
image = null;
}
public Sprite(Image i)
{
isVisible = true;
image = i;
x = 10;
y = 10;
}
public void setImage(Image img)
{
image = img;
isVisible = true;
}
public void setLocation(int _x, int _y)
{
x = _x;
y = _y;
}
public Rectangle getDimensions()
{
return new Rectangle(x, y, image.getWidth(null), image.getHeight(null));
}
public boolean intersects(Sprite s)
{
return getDimensions().intersects(s.getDimensions());
}
public void setVisible(boolean vis)
{
isVisible = vis;
}
public void paintComponent(Graphics g)
{
if(isVisible)
{
g.drawImage(image, x, y, null);
}
}
}
class Coins extends Sprite
{
int amount;
public Coins(int amt)
{
amount = amt;
}
public int getAmount()
{
return amount;
}
public void setAmount(int amt)
{
amount = amt;
}
}
class AnimateSprite extends Sprite
{
int speed = 5;
int directionX = 1, directionY = 1;
int healthPoints = 100;
final boolean DEAD = false;
final boolean ALIVE = true;
public void moveUp()
{
y -= speed;
}
public void moveDown()
{
y += speed;
}
public void moveLeft()
{
x -= speed;
}
public void moveRight()
{
x += speed;
}
public int getHealthPoints()
{
return healthPoints;
}
public void setHealthPoints(int hp)
{
healthPoints = hp;
}
public boolean hit(int amt)
{
healthPoints -= amt;
if(healthPoints < 0)
return DEAD;
else
return ALIVE;
}
}
class Game extends AnimateSprite implements Runnable, KeyListener
{
AnimateSprite user;
AnimateSprite monster, troll;
Coins ten, twenty;
Thread thread;
Random r;
public void init()
{
r = new Random();
user = new AnimateSprite();
user.setImage(getImage(getCodeBase(), "player.gif"));
monster = new AnimateSprite();
monster.setImage(getImage(getCodeBase(), "monster.gif"));
troll = new AnimateSprite();
troll.setImage(getImage(getCodeBase(), "monster.gif"));
troll.setLocation(350, 350);
setupCoins();
setFocusable(true);
addKeyListener(this);
thread = new Thread(this);
thread.start();
}
public void setupCoins()
{
ten = new Coins(10);
twenty = new Coins(20);
ten.setLocation(400, 350);
twenty.setLocation(450, 50);
ten.setImage(getImage(getCodeBase(), "coins.gif"));
twenty.setImage(getImage(getCodeBase(), "coins.gif"));
}
public void keyPressed(KeyEvent ke) //Event handling
{
int key = ke.getKeyCode();
if(key == KeyEvent.VK_UP)
user.moveUp();
else if(key == KeyEvent.VK_DOWN)
user.moveDown();
else if(key == KeyEvent.VK_LEFT)
user.moveLeft();
else if(key == KeyEvent.VK_RIGHT)
user.moveRight();
}
public void keyReleased(KeyEvent ke) {}
public void keyTyped(KeyEvent ke) {}
public void update(Graphics g) {paint(g);}
public void paint(Graphics g)
{
g.clearRect(0, 0, this.getWidth(), this.getHeight());
ten.paintComponent(g);
twenty.paintComponent(g);
monster.setLocation(r.nextInt(10) - 5 + monster.x, r.nextInt(10 - 5 + monster.y));
monster.paintComponent(g);
user.paintComponent(g);
if(user.intersects(monster))
{
g.setFont(new Font("Serif", Font.BOLD, 26));
g.drawString("YOU HAVE DIED, YOU LOSE!", 20, 100); //Prints this when you lose
thread.interrupt(); //Stopping the thread if you die
}
}
public void run()
{
try //Try catch
{
while(true) //Only does this while when the boolean is true
{
repaint();
Thread.sleep(10); //Thread sleeps
}
} catch(Exception e) {} //Exception handling
}
}
Your order of inheritance seems odd, but its not whats causing the problem. Take a look at this website: http://www.dreamincode.net/forums/topic/28410-application-to-japplet-and-reverse/
Java Applets need to have init(), start(), stop(), and destroy(). You will need to put these methods in your Sprite class for the Applet to function.

Changing image immediately

I am currently trying to learn a little bit about programming games.
I got myself a player class extending a sprite class i wrote by myself.
Now i want to know, how i can change the image of my player object in the middle of the running game. imagine a spaceship, when pressing the right arrow key it should be a different image, inclined to the right.
now i am trying to do this:
when a button is pressed (e.g. space) setImage(the new image)
But now, when i call this method my image just disappears and the new one won't appear?
Any ideas?
My code of the Main class:
public class Game extends JPanel implements Runnable{
private static final long serialVersionUID = 1L;
public boolean isRunning;
public static final int WIDTH = 320;
public static final int HEIGHT = 240;
public static final int SCALE = 2;
private Player player;
public Game() {
addKeyListener(new TAdapter());
setFocusable(true);
requestFocus();
start();
}
public void start() {
isRunning = true;
new Thread(this).start();
}
public void stop() {
isRunning = false;
}
public void run() {
init();
while(isRunning) {
update();
repaint();
try {
Thread.sleep(5);
} catch (Exception e) {
e.printStackTrace();
}
}
}
public void init() {
player = new Player("/ship_blue", WIDTH - 32/2, 400);
}
public void update() {
player.update();
}
public void paint(Graphics g) {
super.paint(g);
Graphics2D g2d = (Graphics2D)g;
drawPlayer(g2d);
}
public void drawPlayer(Graphics2D g2d) {
if(player.isVisible)g2d.drawImage(player.getImage(),(int) player.getX(), (int) player.getY(), null);
}
public static void main(String[] args) {
Game gameComponent = new Game();
Dimension size = new Dimension(WIDTH*SCALE, HEIGHT*SCALE);
JFrame frame = new JFrame("Invaders");
frame.setVisible(true);
frame.setSize(size);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setResizable(false);
frame.add(gameComponent);
}
public class TAdapter extends KeyAdapter{
public void keyPressed(KeyEvent e) {
player.keyPressed(e);
}
public void keyReleased(KeyEvent e) {
player.keyReleased(e);
}
}
}
That's the main class, now the player class in which i am trying to change the image in the onPress() method:
public class Player extends Sprite{
private double glideSpeed = .125;
private int fixY;
private int xDirection = 0;
private int yDirection = 1;
public Player(String source, int x, int y) {
this.x = x;
this.y = y;
ImageIcon ii = new ImageIcon(this.getClass().getResource(source));
setImage(ii.getImage());
setTileSize(ii.getIconWidth());
setSpeed(0.2);
fixY = y;
}
public void update() {
x += xDirection * 1.4;
glide(10);
}
public void keyPressed(KeyEvent e) {
int key = e.getKeyCode();
if(key == KeyEvent.VK_RIGHT) {
xDirection = 1;
}
if(key == KeyEvent.VK_LEFT) {
xDirection = -1;
}
if(key == KeyEvent.VK_SPACE) {
ImageIcon ii2 = new ImageIcon("/player_blue_negativ");
setImage(ii2.getImage()); //<-----Here I am trying to change the image
}
}
public void keyReleased(KeyEvent e) {
int key = e.getKeyCode();
if(key == KeyEvent.VK_RIGHT || key == KeyEvent.VK_LEFT) {
xDirection = 0;
}
}
public void glide(int span) {
y += yDirection * glideSpeed;
if(y - fixY > span || fixY - y > span) {
yDirection = -yDirection;
}
}
}
And to complete everything here's my sprite class:
public class Sprite {
protected double x;
protected double y;
protected int tileSize;
protected double speed;
protected Image img;
protected boolean isVisible;
public Sprite() {
isVisible = true;
}
public double getSpeed() {
return speed;
}
public double getX() {
return x;
}
public double getY() {
return y;
}
public int getTileSize() {
return tileSize;
}
public Image getImage() {
return img;
}
public boolean getVisible() {
return isVisible;
}
public void setSpeed(double speed) {
this.speed = speed;
}
public void setX(double x) {
this.x = x;
}
public void setY(double y) {
this.y = y;
}
public void setTileSize(int tileSize) {
this.tileSize = tileSize;
}
public void setImage(Image img) {
this.img = img;
}
public void die() {
isVisible = false;
}
}
if(key == KeyEvent.VK_SPACE) {
ImageIcon ii2 = new ImageIcon("/player_blue_negativ");
There is the basic problem. All images should be loaded and cached prior to an event happening. When the event occurs, use the cached image and the GUI should render immediately.
As mentioned by #camickr, the use of an ImageIcon also subtly slips from an URL to a String (presumed to represent a
File path). Stick with the URL obtained from getResource(..).
On ImageObserver.
If an ImageObserver is used to paint the image, the observer will be informed of updates to images that are asynchronously loaded. All components (e.g. JPanel) implement ImageObserver, so..
g2d.drawImage(player.getImage(),(int) player.getX(), (int) player.getY(), null);
Should be:
g2d.drawImage(player.getImage(),(int) player.getX(), (int) player.getY(), this);
Free the EDT!
class Game extends JPanel implements Runnable ..
Thread.sleep(5);
Don't block the EDT (Event Dispatch Thread) - the GUI will 'freeze' when that happens.
Also don't attempt to update the GUI from anything other than the EDT.
Instead of calling Thread.sleep(n) in a Runnable, implement a Swing Timer for repeating tasks or a SwingWorker for long running tasks. See Concurrency in Swing for more details.
Use paintComponent(Graphics) for Swing components!
public void paint(Graphics g) {
Should be:
#Override
public void paintComponent(Graphics g) {
When you load the initial image you use the following without a problem:
ImageIcon ii = new ImageIcon(this.getClass().getResource(source));
When you change the image you use:
ImageIcon ii2 = new ImageIcon("/player_blue_negativ");
I'm guessing you don't find the image, probably because you don't need the "/". But why not use the same method that you know works?

Varying results with simplistic Java applet game [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions concerning problems with code you've written must describe the specific problem — and include valid code to reproduce it — in the question itself. See SSCCE.org for guidance.
Closed 9 years ago.
Improve this question
I was following a tutorial on some basic game design for Java when I ran across an unusual issue. When I run an applet that simply moves an image based character on the screen, it will not let me use the methods to change position of the image. It raises a NullPointerException in located at my robot.update() method which handles the movement of the image. The odd part is that if I choose the "Restart" option from the drop down list in the Applet frame, it works as normal. Any ideas?
Main Class
package Game;
import java.applet.Applet;
import java.awt.Color;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.net.URL;
public class First extends Applet implements Runnable, KeyListener {
private Robot robot;
private Image image, character;
private Graphics second;
private URL base;
#Override
public void init() {
setSize(800,480);
setBackground(Color.BLACK);
setFocusable(true);
Frame frame = (Frame) this.getParent().getParent();
frame.setTitle("First Game");
addKeyListener(this);
try {
base = getDocumentBase();
} catch (Exception e) {
e.printStackTrace();
System.out.println("Image not accessible");
}
character = getImage(base, "data/character.png");
// TODO Auto-generated method stub
super.init();
}
#Override
public void start() {
Thread thread = new Thread(this);
thread.start();
robot = new Robot();
// TODO Auto-generated method stub
super.start();
}
#Override
public void stop() {
// TODO Auto-generated method stub
super.stop();
}
#Override
public void destroy() {
// TODO Auto-generated method stub
super.destroy();
}
#Override
public void run() {
// TODO Auto-generated method stub
while (true) {
robot.update();
repaint();
try {
Thread.sleep(17);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void update(Graphics g) {
if (image == null) {
image = createImage(this.getWidth(), this.getHeight());
second = image.getGraphics();
}
second.setColor(getBackground());
second.fillRect(0, 0, getWidth(), getHeight());
second.setColor(getForeground());
paint(second);
g.drawImage(image, 0, 0, this);
}
#Override
public void paint(Graphics g) {
// TODO Auto-generated method stub
g.drawImage(character, robot.getCenterX() - 61,
robot.getCenterY() - 63, this);
super.paint(g);
}
#Override
public void keyTyped(KeyEvent e) {
// TODO Auto-generated method stub
}
#Override
public void keyPressed(KeyEvent e) {
switch (e.getKeyCode()) {
case KeyEvent.VK_UP:
System.out.println("Move UP");
break;
case KeyEvent.VK_DOWN:
System.out.println("Move DOWN");
break;
case KeyEvent.VK_LEFT:
robot.moveLeft();
break;
case KeyEvent.VK_RIGHT:
robot.moveRight();
break;
case KeyEvent.VK_SPACE:
robot.jump();
break;
}
// TODO Auto-generated method stub
}
#Override
public void keyReleased(KeyEvent e) {
switch (e.getKeyCode()) {
case KeyEvent.VK_UP:
System.out.println("Stop UP");
break;
case KeyEvent.VK_DOWN:
System.out.println("Stop DOWN");
break;
case KeyEvent.VK_LEFT:
robot.stop();
break;
case KeyEvent.VK_RIGHT:
robot.stop();
break;
case KeyEvent.VK_SPACE:
robot.stop();
break;
// TODO Auto-generated method stub
}
}
}
Robot Class
package Game;
public class Robot {
private int centerX = 100;
private int centerY = 382;
private boolean jumped = false;
private int speedX = 0;
private int speedY = 1;
public void update() {
if (speedX < 0) {
centerX += speedX;
} else if (speedX == 0){
System.out.println("Do not scroll the background");
} else {
if (centerX <= 300) {
centerX += speedX;
} else {
System.out.println("Scroll background here");
}
}
if (centerY + speedY >= 382) {
centerY = 382;
}else{
centerY += speedY;
}
// Handles Jumping
if (jumped == true) {
speedY += 1;
if (centerY + speedY >= 382) {
centerY = 382;
speedY = 0;
jumped = false;
}
}
// Prevents going beyond X coordinate of 0
if (centerX + speedX <= 60) {
centerX = 61;
}
}
public int getCenterX() {
return centerX;
}
public void setCenterX(int centerX) {
this.centerX = centerX;
}
public int getCenterY() {
return centerY;
}
public void setCenterY(int centerY) {
this.centerY = centerY;
}
public boolean isJumped() {
return jumped;
}
public void setJumped(boolean jumped) {
this.jumped = jumped;
}
public int getSpeedX() {
return speedX;
}
public void setSpeedX(int speedX) {
this.speedX = speedX;
}
public int getSpeedY() {
return speedY;
}
public void setSpeedY(int speedY) {
this.speedY = speedY;
}
public void moveRight() {
speedX = 6;
}
public void moveLeft() {
speedX = -6;
}
public void stop() {
speedX = 0;
}
public void jump() {
if (jumped == false) {
speedY = -15;
jumped = true;
}
}
}
This is the error message I am gettings
Exception in thread "Thread-3" java.lang.NullPointerException
at Game.First.run(First.java:65)
at java.lang.Thread.run(Thread.java:722)
You should initialize robot object first not after running the thread, try:
robot = new Robot();
Thread thread = new Thread(this);
thread.start();
As when you start the thread's execution it may start with null robot.
when you again reload it works as by then it is initialized.

Categories

Resources