Java Applet game double buffering broke with switch statement - java

I'm just starting out trying to make games and I did a HelloWorld Applet, then tested my idea for scrolling on it, and eventually it started turning into a "helicopter" style game. Now everything worked fine until I decided to put a bunch of switch statements in to handle states(title screen, running, and game over). The code that was functioning before is unchanged, and my new "intro screen" works fine, but when you switch into the game state the double buffering seems to go out of whack. The game foreground flashes on and off quickly and has triangles cut out of it, and the background hardly renders at all. This is just me exploring basic principles of game coding, so it's not elegant or modular or anything, but it should work...
[EDIT] I know that Applets and AWT in general is probably a bad way to go, but I started it like this and I just want to learn how this works and what I'm doing wrong so I can be satisfied and move on.
package testStuff;
import java.awt.*;
import java.applet.*;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
public class HelloWorld extends Applet implements Runnable{
//game time counter
int count = 0;
//controller object
Controller control;
//accesses images and creates image variables
File wavesource = new File("C:\\sourceimages\\waves.jpg");
File playerSource = new File("C:\\sourceimages\\plane3.png");
Image player = null;
Image waves = null;
//font for score
Font myFont;
//double buffer objects
Graphics bground;
Image bgImage = null;
private int bgx = 0;
//player position
private int xPos=0;
private int yPos=50;
//arrays for tunnel locations
private int[] topTunnel = new int[200];
private int[] botTunnel = new int[200];
//size of tunnel
private int tunnelSize;
//boolean determines direction of tunnel movement
private boolean tunUp;
//state
private int state;
//"constructor"
public void init(){
//set state
state = 0;
//instantiates controller adds it to the applet
control = new Controller();
this.addKeyListener(control);
//instantiates images
try {
waves = ImageIO.read(wavesource);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
player = ImageIO.read(playerSource);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//instantiates arrays and tunnel size
for(int i=0;i<199;i++){
topTunnel[i]=-1;
botTunnel[i]=-1;
}
topTunnel[199]=20;
botTunnel[199]=179;
tunnelSize = botTunnel[199]-topTunnel[199];
tunUp = false;
}
public void paint(Graphics g){
switch(state){
case 0:
g.setColor(Color.black);
myFont = new Font("Courier", Font.BOLD+Font.ITALIC, 12);
g.setFont(myFont);
g.drawString("DON'T CRASH THE PLANE BRO", 10, 100);
myFont = new Font("Courier", Font.PLAIN, 8);
g.setFont(myFont);
g.drawString("Press Spacebar to Play", 40, 150);
break;
case 1:
g.drawImage(player, xPos, yPos, null);
g.setColor(Color.red);
for(int i=0;i<200;i++){
g.fillRect(i, 0, 1, topTunnel[i]);
g.fillRect(i, botTunnel[i], 1, botTunnel[i]);
}
g.setColor(Color.cyan);
myFont = new Font("Helvetica", Font.PLAIN, 12);
setFont(myFont);
if(count<170)
g.drawString("SCORE: " + 0, 0, 12);
else
g.drawString("SCORE: " + (this.count-170), 0, 12);
break;
}
}
public void start(){
Thread thread = new Thread(this);
thread.start();
}
#Override
public void run(){
while(true){
switch(state){
case 0:
//increases count
count++;
//paints
this.repaint();
try {
Thread.sleep(1000/30);
} catch (InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
if(control.spaceDown()){
state = 1;
count = 0;
}
break;
case 1:
//increases count
count++;
//handles scrolling
if(xPos<75){
xPos++;
}
else{
if(bgx>-600){
bgx--;
}
else{
bgx=0;
}
}
//handles input
if(control.spaceDown()==true&&yPos>=0){
yPos--;
}
else if(yPos<180){
yPos++;
}
//repositions tunnel
if(xPos>=75){
for(int i=1;i<200;i++){
topTunnel[i-1]=topTunnel[i];
botTunnel[i-1]=botTunnel[i];
}
}
//defines new tunnel space
if(topTunnel[199]<=0 || !tunUp)
topTunnel[199]++;
if(botTunnel[199]>=200 || tunUp)
topTunnel[199]--;
botTunnel[199] = topTunnel[199]+tunnelSize;
//randomly chooses direction to move tunnel
double randomNum = Math.random();
if(randomNum>.5)
tunUp = true;
else
tunUp = false;
//narrows tunnel
if(count%20 == 0)
tunnelSize--;
//calls update
this.repaint();
//handles framerate
try {
Thread.sleep(1000/30);
} catch (InterruptedException e) {
//TODO Auto-generated catch block
e.printStackTrace();
}
break;
}
}
}
public void update(Graphics g){
//instantiates image and graphics on first tick
if(bgImage == null){
bgImage = createImage(this.getSize().width, this.getSize().height);
bground = bgImage.getGraphics();
}
//create background based on state
switch(state){
case 0:
//flashing colors!
if(count%20<10){
bground.setColor(Color.yellow);
bground.fillRect(0, 0, 200, 200);
}
else{
bground.setColor(Color.orange);
bground.fillRect(0, 0, 200, 200);
}
break;
case 1:
//draws background image(s)
bground.drawImage(waves,bgx,0,this);
if(bgx<-399)
bground.drawImage(waves,bgx+600,0,this);
break;
}
//paint over the background then draw it to screen
paint(bground);
g.drawImage(bgImage, 0, 0, this);
}
}

You need to "clear" the graphics on each frame, otherwise you are painting on what was previously painted...
In the example below, I've filled the graphics context while it's "playing", but left as is when it's paused, you should be able to see the difference...
public class HelloWorld extends Applet implements Runnable {
private int direction = 4;
private int state = 0;
private Image bgImage;
private Graphics bground;
private int count;
private int x = 0;
//"constructor"
public void init() {
addKeyListener(new KeyAdapter() {
#Override
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_SPACE) {
if (state == 0) {
state = 1;
} else if (state == 1) {
state = 0;
}
}
}
});
}
public void paint(Graphics g) {
switch (state) {
case 0:
g.setColor(Color.black);
g.drawString("DON'T CRASH THE PLANE BRO", 10, 100);
g.drawString("Press Spacebar to Play", 40, 150);
break;
case 1:
break;
}
}
public void start() {
Thread thread = new Thread(this);
thread.start();
}
#Override
public void run() {
while (true) {
switch (state) {
case 0:
count++;
this.repaint();
break;
case 1:
x += direction;
if (x < 0) {
x = 0;
direction *= -1;
} else if (x > getWidth()) {
x = getWidth();
direction *= -1;
}
//calls update
this.repaint();
//handles framerate
try {
Thread.sleep(1000 / 30);
} catch (InterruptedException e) {
//TODO Auto-generated catch block
e.printStackTrace();
}
break;
}
}
}
public void update(Graphics g) {
//instantiates image and graphics on first tick
if (bgImage == null) {
bgImage = createImage(this.getSize().width, this.getSize().height);
bground = bgImage.getGraphics();
}
//create background based on state
switch (state) {
case 0:
//flashing colors!
if (count % 20 < 10) {
bground.setColor(Color.yellow);
bground.fillRect(0, 0, 200, 200);
} else {
bground.setColor(Color.orange);
bground.fillRect(0, 0, 200, 200);
}
break;
case 1:
bground.setColor(Color.WHITE);
bground.fillRect(0, 0, getWidth(), getHeight());
bground.setColor(Color.RED);
int y = (getHeight() / 2) - 4;
bground.fillOval(x, y, 8, 8);
break;
}
//paint over the background then draw it to screen
paint(bground);
g.drawImage(bgImage, 0, 0, this);
}
}

I think you should start but adding more braces. I'm a beginner at coding but from what I've been reading, coding lengthy statements without braces on certain statements in your code would result in some errors.
There are a lot of processes going on here and I feel like braces help a
//defines new tunnel space
if(topTunnel[199]<=0 || !tunUp)
topTunnel[199]++;
if(botTunnel[199]>=200 || tunUp)
topTunnel[199]--;
botTunnel[199] = topTunnel[199]+tunnelSize;
//randomly chooses direction to move tunnel
double randomNum = Math.random();
if(randomNum>.5)
tunUp = true;
else
tunUp = false;
//narrows tunnel
if(count%20 == 0)
tunnelSize--;
//calls update
this.repaint();
Correct me if I'm wrong, I just want to learn too!

Related

A* pathfinding game system exit issue

I am making a game where a badGuy AI is trying to chase me while I use arrow keys to move away. In my main I have a try catch block for if the player attempts to exit the screen border. For some reason however when I click on start I get the exception which I have a system print out saying "GAME OVER, you exited the map". Without my reCalcPath method in the badguy class this does not happen so it must be an issue within this method.
For this method I have a map array. This array is a 40x40 boolean array of 20x20 pixels/cells/squares which states true if I have clicked on that cell position if previously false, painting a white square and visa versa. Now I thought, check the cell position of the badGuy, then check all of his neighbouring cells, if the state of that cell is false i.e. no cell is painted (which means there is no wall blocking him in this sense), then check for the distance between him and my player. I use a Euclidean distance approach by treating xPlayer-xbadGuy, yPLayer-xBadGuy as the opposite and adjacent sides of a triangle. Using pythagoras I get the hypotenuse. Do this for each neighbouring cell, the one with the smallest hypotenuse means shortest distance. Now this is not working at all as when its called the game crashes. Ignore the move method as that is irrelevant if recalcpath won't work
Main
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.awt.image.*;
import java.io.*;
public class AStarMaze extends JFrame implements Runnable, MouseListener, MouseMotionListener, KeyListener {
// member data
private boolean isInitialised = false;
private BufferStrategy strategy;
private Graphics offscreenBuffer;
public boolean map[][] = new boolean[40][40];
private boolean isGameRunning = false;
private BadGuy badguy;
private Player player;
private int startI, startJ;
private int endI, endJ;
private String pFilePath, bgFilePath;
// constructor
public AStarMaze () {
//Display the window, centred on the screen
Dimension screensize = java.awt.Toolkit.getDefaultToolkit().getScreenSize();
int x = screensize.width/2 - 400;
int y = screensize.height/2 - 400;
setBounds(x, y, 800, 800);
setVisible(true);
this.setTitle("A* Pathfinding Demo");
bgFilePath = "C:\\Users\\brads\\IdeaProjects\\PathfindingAssignment\\src\\badguy.png";
pFilePath = "C:\\Users\\brads\\IdeaProjects\\PathfindingAssignment\\src\\player.png";
// load raster graphics and instantiate game objects
ImageIcon icon = new ImageIcon(bgFilePath);
Image img = icon.getImage();
badguy = new BadGuy(img);
icon = new ImageIcon(pFilePath);
img = icon.getImage();
player = new Player(img);
// create and start our animation thread
Thread t = new Thread(this);
t.start();
// initialise double-buffering
createBufferStrategy(2);
strategy = getBufferStrategy();
offscreenBuffer = strategy.getDrawGraphics();
// register the Jframe itself to receive mouse and keyboard events
addMouseListener(this);
addMouseMotionListener(this);
addKeyListener(this);
// initialise the map state
for (x=0;x<40;x++) {
for (y=0;y<40;y++) {
map[x][y]=false;
}
}
isInitialised = true;
}
public boolean[][] getMap(){
return map;
}
// thread's entry point
public void run() {
long loops=0;
while ( 1==1 ) {
// 1: sleep for 1/5 sec
try {
Thread.sleep(100);
} catch (InterruptedException e) { }
try {
// 2: animate game objects
if (isGameRunning) {
loops++;
player.move(map); // player moves every frame
if (loops % 3 == 0) // badguy moves once every 3 frames
badguy.reCalcPath(map,player.x,player.y);
// badguy.move(map, player.x, player.y);
}
// 3: force an application repaint
this.repaint();
}
catch(IndexOutOfBoundsException e){
System.out.println("GAME OVER, you exited the map");
System.exit(-1);
}
}
}
private void loadMaze() {
String filename = "C:\\Users\\brads\\IdeaProjects\\PathfindingAssignment\\maze.txt";
String textinput = null;
try {
BufferedReader reader = new BufferedReader(new FileReader(filename));
textinput = reader.readLine();
reader.close();
}
catch (IOException e) { }
if (textinput!=null) {
for (int x=0;x<40;x++) {
for (int y=0;y<40;y++) {
map[x][y] = (textinput.charAt(x*40+y)=='1');
}
}
}
}
private void saveMaze() {
// pack maze into a string
String outputtext="";
for (int x=0;x<40;x++) {
for (int y=0;y<40;y++) {
if (map[x][y])
outputtext+="1";
else
outputtext+="0";
}
}
try {
String filename = "C:\\Users\\brads\\IdeaProjects\\PathfindingAssignment\\maze.txt";
BufferedWriter writer = new BufferedWriter(new FileWriter(filename));
writer.write(outputtext);
writer.close();
}
catch (IOException e) { }
}
// mouse events which must be implemented for MouseListener
public void mousePressed(MouseEvent e) {
if (!isGameRunning) {
// was the click on the 'start button'?
int x = e.getX();
int y = e.getY();
if (x>=15 && x<=85 && y>=40 && y<=70) {
isGameRunning=true;
return;
}
// or the 'load' button?
if (x>=315 && x<=385 && y>=40 && y<=70) {
loadMaze();
return;
}
// or the 'save' button?
if (x>=415 && x<=485 && y>=40 && y<=70) {
saveMaze();
return;
}
}
// determine which cell of the gameState array was clicked on
int x = e.getX()/20;
int y = e.getY()/20;
// toggle the state of the cell
map[x][y] = !map[x][y];
// throw an extra repaint, to get immediate visual feedback
this.repaint();
// store mouse position so that each tiny drag doesn't toggle the cell
// (see mouseDragged method below)
prevx=x;
prevy=y;
}
public void mouseReleased(MouseEvent e) {}
public void mouseEntered(MouseEvent e) {}
public void mouseExited(MouseEvent e) {}
public void mouseClicked(MouseEvent e) {}
//
// mouse events which must be implemented for MouseMotionListener
public void mouseMoved(MouseEvent e) {}
// mouse position on previous mouseDragged event
// must be member variables for lifetime reasons
int prevx=-1, prevy=-1;
public void mouseDragged(MouseEvent e) {
// determine which cell of the gameState array was clicked on
// and make sure it has changed since the last mouseDragged event
int x = e.getX()/20;
int y = e.getY()/20;
if (x!=prevx || y!=prevy) {
// toggle the state of the cell
map[x][y] = !map[x][y];
// throw an extra repaint, to get immediate visual feedback
this.repaint();
// store mouse position so that each tiny drag doesn't toggle the cell
prevx=x;
prevy=y;
}
}
//
// Keyboard events
public void keyPressed(KeyEvent e) {
if (e.getKeyCode()==KeyEvent.VK_LEFT)
player.setXSpeed(-1);
else if (e.getKeyCode()==KeyEvent.VK_RIGHT)
player.setXSpeed(1);
else if (e.getKeyCode()==KeyEvent.VK_UP)
player.setYSpeed(-1);
else if (e.getKeyCode()==KeyEvent.VK_DOWN)
player.setYSpeed(1);
}
public void keyReleased(KeyEvent e) {
if (e.getKeyCode()==KeyEvent.VK_LEFT || e.getKeyCode()==KeyEvent.VK_RIGHT)
player.setXSpeed(0);
else if (e.getKeyCode()==KeyEvent.VK_UP || e.getKeyCode()==KeyEvent.VK_DOWN)
player.setYSpeed(0);
}
public void keyTyped(KeyEvent e) { }
//
// application's paint method
public void paint(Graphics g) {
if (!isInitialised)
return;
g = offscreenBuffer; // draw to offscreen buffer
// clear the canvas with a big black rectangle
g.setColor(Color.BLACK);
g.fillRect(0, 0, 800, 800);
// redraw the map
g.setColor(Color.WHITE);
for (int x=0;x<40;x++) {
for (int y=0;y<40;y++) {
if (map[x][y]) {
g.fillRect(x*20, y*20, 20, 20);
}
}
}
// redraw the player and badguy
// paint the game objects
player.paint(g);
badguy.paint(g);
if (!isGameRunning) {
// game is not running..
// draw a 'start button' as a rectangle with text on top
// also draw 'load' and 'save' buttons
g.setColor(Color.GREEN);
g.fillRect(15, 40, 70, 30);
g.fillRect(315, 40, 70, 30);
g.fillRect(415, 40, 70, 30);
g.setFont(new Font("Times", Font.PLAIN, 24));
g.setColor(Color.BLACK);
g.drawString("Start", 22, 62);
g.drawString("Load", 322, 62);
g.drawString("Save", 422, 62);
}
// flip the buffers
strategy.show();
}
// application entry point
public static void main(String[] args) {
AStarMaze w = new AStarMaze();
}
}
Player Class
import java.awt.Graphics;
import java.awt.Image;
public class Player {
Image myImage;
int x=0,y=0;
int xSpeed=0, ySpeed=0;
public Player( Image i ) {
myImage=i;
x=10;
y=35;
}
public void setXSpeed( int x ) {
xSpeed=x;
}
public void setYSpeed( int y ) {
ySpeed=y;
}
public void move(boolean map[][]) {
int newx=x+xSpeed;
int newy=y+ySpeed;
if (!map[newx][newy]) {
x=newx;
y=newy;
}
}
public void paint(Graphics g) {
g.drawImage(myImage, x*20, y*20, null);
}
}
Bad Guy
import java.awt.Graphics;
import java.awt.Image;
public class BadGuy {
Image myImage;
int x=0,y=0;
int distanceX = 0, distanceY = 0;
boolean hasPath=false;
public BadGuy( Image i ) {
myImage=i;
x = 30;
y = 10;
}
public void reCalcPath(boolean map[][],int targx, int targy) {
// TO DO: calculate A* path to targx,targy, taking account of walls defined in map[][]
int totalDistance = 0;
for (int i = -1; i <= 1; i++) {
for (int j = -1; j <= 1; j++) {
if (!map[(x / 20) + i][(y / 20) + j]) {
if ((((targx - x) ^ 2) + ((targy - y) ^ 2)) <= totalDistance) {
totalDistance = (((targx - x) ^ 2) + ((targy - y) ^ 2));
x = ((x / 20) + i);
y = ((y / 20) + j);
return;
}
}
}
}
System.out.println("Not working");
}
// public void move(boolean map[][],int targx, int targy) {
// if (hasPath) {
// // TO DO: follow A* path, if we have one defined
// }
// else if(map[x / 20][y / 20]) {
// hasPath = false;
// }
// }
public void paint(Graphics g) {
g.drawImage(myImage, x*20, y*20, null);
}
}
Your catch block is triggered by an IndexOutOfBoundsException. One easy way to find more information about your error is to log or output the stack trace. You can do that in your code by adding e.printStackTrace() to your catch block:
catch(IndexOutOfBoundsException e){
System.out.println("GAME OVER, you exited the map");
e.printStackTrace()
System.exit(-1);
}
This should show you the line number that's causing your problem.
Looking at the code in your reCalcPath method, my educated guess is the line causing the problem is this: if (!map[(x / 20) + i][(y / 20) + j]) {. If either (x / 20) + i or (y / 20) + j are less than 0 or greater than your map dimensions, it will throw the IndexOutOfBoundsException that you are seeing. In the case where you start and x=30, y=10, i=-1, and j=-1, that evaluates to map[0][-1].
This is what's known as an edge case. You need to check for the case where your x and y are on the edges of the grid. In that situation the neighboring grid cells are outside of the map and will throw an exception.

How can I export as Runnable JAR file from eclipse?

When I try to export as a Runnable JAR file, I have no options for 'Launch configuration'. Why is this? I am new to programming, can anyone help me?
It's a code for the game Snake. Do I need a main()?
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Point;
import java.awt.Toolkit;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.image.BufferedImage;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.net.URL;
import java.util.LinkedList;
import java.util.Random;
import javax.swing.JOptionPane;
#SuppressWarnings("serial")
public class snakeCanvas extends Canvas implements Runnable, KeyListener
{
private final int BOX_HEIGHT = 15;
private final int BOX_WIDTH = 15;
private final int GRID_HEIGHT = 25;
private final int GRID_WIDTH = 25;
private LinkedList<Point> snake;
private Point fruit;
private int direction = Direction.NO_DIRECTION;
private Thread runThread; //allows us to run in the background
private int score = 0;
private String highScore = "";
private Image menuImage = null;
private boolean isInMenu = true;
public void paint(Graphics g)
{
if (runThread == null)
{
this.setPreferredSize(new Dimension(640, 480));
this.addKeyListener(this);
runThread = new Thread(this);
runThread.start();
}
if (isInMenu)
{
DrawMenu(g);
//draw menu
}
else
{
if (snake == null)
{
snake = new LinkedList<Point>();
GenerateDefaultSnake();
PlaceFruit();
}
if (highScore.equals(""))
{
highScore = this.GetHighScore();
System.out.println(highScore);
}
DrawSnake(g);
DrawFruit(g);
DrawGrid(g);
DrawScore(g);
//draw everything else
}
}
public void DrawMenu(Graphics g)
{
if (this.menuImage == null)
{
try
{
URL imagePath = snakeCanvas.class.getResource("snakeMenu.png");
this.menuImage = Toolkit.getDefaultToolkit().getImage(imagePath);
}
catch (Exception e)
{
e.printStackTrace();
}
}
g.drawImage(menuImage, 0, 0, 640, 480, this);
}
public void update(Graphics g)
{
Graphics offScreenGraphics;
BufferedImage offscreen = null;
Dimension d= this.getSize();
offscreen = new BufferedImage(d.width, d.height, BufferedImage.TYPE_INT_ARGB);
offScreenGraphics = offscreen.getGraphics();
offScreenGraphics.setColor(this.getBackground());
offScreenGraphics.fillRect(0, 0, d.width, d.height);
offScreenGraphics.setColor(this.getForeground());
paint(offScreenGraphics);
g.drawImage(offscreen, 0, 0, this);
}
public void GenerateDefaultSnake()
{
score = 0;
snake.clear();
snake.add(new Point (0,2));
snake.add(new Point(0,1));
snake.add(new Point(0,0));
direction = Direction.NO_DIRECTION;
}
public void Move() //adds a new 'block' at front of snake, deleting the back 'block' to create movement
{
Point head = snake.peekFirst(); //grab the first item with no problems
Point newPoint = head;
switch (direction) {
case Direction.NORTH:
newPoint = new Point(head.x, head.y - 1); //vector of -j
break;
case Direction.SOUTH:
newPoint = new Point(head.x, head.y + 1);
break;
case Direction.WEST:
newPoint = new Point(head.x - 1, head.y);
break;
case Direction.EAST:
newPoint = new Point (head.x + 1, head.y);
break;
}
snake.remove(snake.peekLast()); //delete the last block
if (newPoint.equals(fruit))
{
//the snake hits the fruit
score+=10;
Point addPoint = (Point) newPoint.clone(); //creating the end piece upon eating fruit
switch (direction) {
case Direction.NORTH:
newPoint = new Point(head.x, head.y - 1); //vector of -j
break;
case Direction.SOUTH:
newPoint = new Point(head.x, head.y + 1);
break;
case Direction.WEST:
newPoint = new Point(head.x - 1, head.y);
break;
case Direction.EAST:
newPoint = new Point (head.x + 1, head.y);
break;
}
//the movement upon eating fruit
snake.push(addPoint);
PlaceFruit();
}
else if (newPoint.x < 0 || newPoint.x > (GRID_WIDTH - 1))
{
//snake has gone out of bounds - reset game
CheckScore();
GenerateDefaultSnake();
return;
}
else if (newPoint.y < 0 || newPoint.y > (GRID_HEIGHT - 1))
{
//snake has gone out of bounds - reset game
CheckScore();
GenerateDefaultSnake();
return;
}
else if (snake.contains(newPoint))
{
//running into your tail - reset game
CheckScore();
GenerateDefaultSnake();
return;
}
snake.push(newPoint);
}
public void DrawScore(Graphics g)
{
g.drawString("Score: " + score, 0, BOX_HEIGHT * GRID_HEIGHT + 15);
g.drawString("Highscore:" + highScore, 0, BOX_HEIGHT * GRID_HEIGHT + 30);
}
public void CheckScore()
{
if (highScore.equals(""))
return;
if (score > Integer.parseInt((highScore.split(":")[1])))
{
String name = JOptionPane.showInputDialog("New highscore. Enter your name!");
highScore = name + ":" + score;
File scoreFile = new File("highscore.dat");
if (!scoreFile.exists())
{
try {
scoreFile.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
}
FileWriter writeFile = null;
BufferedWriter writer = null;
try
{
writeFile = new FileWriter(scoreFile);
writer = new BufferedWriter(writeFile);
writer.write(this.highScore);
}
catch (Exception e)
{
}
finally
{
try
{
if (writer != null)
writer.close();
}
catch (Exception e) {}
}
}
}
public void DrawGrid(Graphics g)
{
//drawing the outside rectangle
g.drawRect(0, 0, GRID_WIDTH * BOX_WIDTH, GRID_HEIGHT * BOX_HEIGHT);
//drawing the vertical lines
for (int x = BOX_WIDTH; x < GRID_WIDTH * BOX_WIDTH; x+=BOX_WIDTH)
{
g.drawLine(x, 0, x, BOX_HEIGHT * GRID_HEIGHT);
}
//drawing the horizontal lines
for (int y = BOX_HEIGHT; y < GRID_HEIGHT * BOX_HEIGHT; y+=BOX_HEIGHT)
{
g.drawLine(0, y, GRID_WIDTH * BOX_WIDTH, y);
}
}
public void DrawSnake(Graphics g)
{
g.setColor(Color.ORANGE);
for (Point p : snake)
{
g.fillRect(p.x * BOX_WIDTH, p.y * BOX_HEIGHT, BOX_WIDTH, BOX_HEIGHT);
}
g.setColor(Color.BLACK);
}
public void DrawFruit(Graphics g)
{
g.setColor(Color.RED);
g.fillOval(fruit.x * BOX_WIDTH, fruit.y * BOX_HEIGHT, BOX_WIDTH, BOX_HEIGHT);
g.setColor(Color.BLACK);
}
public void PlaceFruit()
{
Random rand = new Random();
int randomX = rand.nextInt(GRID_WIDTH);
int randomY = rand.nextInt(GRID_HEIGHT);
Point randomPoint = new Point(randomX, randomY);
while (snake.contains(randomPoint)) //If the fruit happens to spawn on the snake, it will change position
{
randomX= rand.nextInt(GRID_WIDTH);
randomY= rand.nextInt(GRID_HEIGHT);
randomPoint = new Point(randomX, randomY);
}
fruit = randomPoint;
}
#Override
public void run() {
while (true)
{
repaint();
//runs indefinitely (CONSTANTLY LOOPS)
if (!isInMenu)
Move();
//Draws grid, snake and fruit
//buffer to slow down the snake
try
{
Thread.currentThread();
Thread.sleep(100);
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
public String GetHighScore()
{
FileReader readFile = null;
BufferedReader reader = null;
try
{
readFile = new FileReader("highscore.dat");
reader = new BufferedReader(readFile);
return reader.readLine();
}
catch (Exception e)
{
return "Nobody:0";
}
finally
{
try{
if (reader != null)
reader.close();
} catch (IOException e){
e.printStackTrace();
}
}
}
#Override
public void keyPressed(KeyEvent e) {
switch (e.getKeyCode())
{
case KeyEvent.VK_UP:
if (direction != Direction.SOUTH)
direction = Direction.NORTH;
break;
case KeyEvent.VK_DOWN:
if (direction != Direction.NORTH)
direction = Direction.SOUTH;
break;
case KeyEvent.VK_RIGHT:
if (direction != Direction.WEST)
direction = Direction.EAST;
break;
case KeyEvent.VK_LEFT:
if (direction != Direction.EAST)
direction = Direction.WEST;
break;
case KeyEvent.VK_ENTER:
if (isInMenu)
{
isInMenu = false;
repaint();
}
break;
case KeyEvent.VK_ESCAPE:
isInMenu = true;
break;
}
}
#Override
public void keyReleased(KeyEvent e) {
}
#Override
public void keyTyped(KeyEvent e) {
// TODO Auto-generated method stub
}
}
Basically, you need a Run configuration that was already used to execute your Java application to have a runnable jar file. This is used to select the correct starting point of the program.
If you have executed your Java application using the Run command (either from the Run menu or the toolbar), a Run configuration was created that executes. However, judging from your question, you have not done so, as you have no entrypoint defined for your application.
For that java uses a static main method with predefined parameters, and any Java class that has such a method can be executed. After you have successfully executed your application, it can be started, and then the created run configuration can be used to export a jar file.

Images not drawn/showing using paintComponent()

I'm in the process of developing a java applet game following a tutorial found here: http://www.kilobolt.com/unit-2-creating-a-game-i.html
I'm using this as a foundation to extend my own app. But here is the problem.
I want to add JButtons to the applet for certain features (start, options etc). But I found them to be flickering when i hover over them and completely hidden if left untouched. I read that it has to do with double buffering and that I should use the paintComponent rather than paint eg
public void paintComponents(Graphics g) {
super.paintComponents(g);
}
That solves the Jbuttons from flickering but then the g.drawimage methods are broke or I don't understand it fully, as the images I'm trying to draw are not showing. I don't know if they are hidden or can't be load or what. If someone could please point to the right direction that would be great.
public class StartingClass extends Applet implements Runnable, KeyListener, ActionListener {
private PlayerChar playerChar;
private Image image, currentSprite, character, characterDown, characterJumped, background;
private Graphics second;
private URL base;
private static Background bg1, bg2;
private JButton start, options;
private boolean running = false;
private int score;
#Override
public void init() {
setSize(800, 480);
setFocusable(true);
addKeyListener(this);
Frame frame = (Frame) this.getParent().getParent();
frame.setTitle("GraviOn-Alpha");
try {
base = getDocumentBase();
}
catch (Exception e) {
// TODO: handle exception
}
// Image Setups
character = getImage(base, "data/character.png");
characterDown = getImage(base, "data/down.png");
characterJumped = getImage(base, "data/jumped.png");
currentSprite = character;
background = getImage(base, "data/background.png");
score = 0;
}
#Override
public void start() {
bg1 = new Background(0, 0);
bg2 = new Background(2160, 0);
playerChar = new PlayerChar();
JPanel myPanel = new JPanel();
start = new JButton("Start");
start.addActionListener(this);
options = new JButton("Change Colour");
options.addActionListener(this);
myPanel.add(start);
myPanel.add(options);
myPanel.setBackground(Color.BLACK);
myPanel.setPreferredSize(new Dimension(100, 75));
this.add(myPanel);
Thread thread = new Thread(this);
thread.start();
}
#Override
public void stop() {
// TODO Auto-generated method stub
}
#Override
public void destroy() {
// TODO Auto-generated method stub
}
#Override
public void run() {
while (true) {
if (running == true) {
playerChar.moveRight();
score += 3;
start.setVisible(false);
options.setVisible(false);
}
else {
}
playerChar.update();
if (playerChar.isJumped()) {
currentSprite = characterJumped;
}
else if (playerChar.isJumped() == false && playerChar.isDucked() == false) {
currentSprite = character;
}
bg1.update();
bg2.update();
repaint();
try {
Thread.sleep(17);
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
}
#Override
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 paintComponents(Graphics g) {
super.paintComponents(g);
g.drawImage(background, bg1.getBgX(), bg1.getBgY(), this);
g.drawImage(background, bg2.getBgX(), bg2.getBgY(), this);
g.drawImage(currentSprite, playerChar.getCenterX() - 61, playerChar.getCenterY() - 63, this);
g.drawString("Score: " + score, 50, 50);
}
#Override
public void keyPressed(KeyEvent e) {
switch (e.getKeyCode()) {
case KeyEvent.VK_UP:
System.out.println("Move up");
break;
case KeyEvent.VK_DOWN:
currentSprite = characterDown;
if (playerChar.isJumped() == false) {
playerChar.setDucked(true);
playerChar.setSpeedX(0);
}
break;
case KeyEvent.VK_LEFT:
// playerChar.moveLeft();
playerChar.setMovingLeft(true);
break;
case KeyEvent.VK_RIGHT:
// playerChar.moveRight();
playerChar.setMovingRight(true);
break;
case KeyEvent.VK_SPACE:
playerChar.jump();
break;
}
}
#Override
public void keyReleased(KeyEvent e) {
switch (e.getKeyCode()) {
case KeyEvent.VK_UP:
System.out.println("Stop moving up");
break;
case KeyEvent.VK_DOWN:
currentSprite = character;
playerChar.setDucked(false);
break;
case KeyEvent.VK_LEFT:
playerChar.stopLeft();
break;
case KeyEvent.VK_RIGHT:
playerChar.stopRight();
break;
case KeyEvent.VK_SPACE:
break;
}
}
#Override
public void keyTyped(KeyEvent e) {
// TODO Auto-generated method stub
}
public static Background getBg1() {
return bg1;
}
public static Background getBg2() {
return bg2;
}
#Override
public void actionPerformed(ActionEvent e) {
if (e.getActionCommand().equals("Start")) {
running = true;
}
if (e.getActionCommand().equals("Change Colour") && character == getImage(base, "data/character.png")) {
character = getImage(base, "data/character2.png");
}
else if (e.getActionCommand().equals("Change Colour") && character == getImage(base, "data/character2.png")) {
character = getImage(base, "data/character.png");
}
repaint();
}
}
This is with trying to utilize the paintComponents method. I would greatly appreciate help.
EDIT: I have changed to using Japplet and used paintComponent in a Jpanel to draw everything and it worked fine, all based on JApplet - super.paint(); causes flicker.
I have changed to using Japplet and used paintComponent in a Jpanel to draw everything and it worked fine.
JPanel myPanel = new JPanel(){
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(background, bg1.getBgX(), bg1.getBgY(), this);
g.drawImage(background, bg2.getBgX(), bg2.getBgY(), this);
g.drawImage(currentSprite, playerChar.getCenterX() - 61, playerChar.getCenterY() - 63, this);
g.drawString("Score: " + score, 50, 50);
}

How to put two different tasks in Threads

I have following code. in this code i have an image which moves from left to right and a button which has an event. but i want to put these both tasks in Threads. so that it can work properly. the problem with this code is that button event does not work until it reaches to the right most point.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
class MyImage extends JFrame implements ActionListener
{
static int xPixel = 20;
Image myImage, offScreenImage;
Graphics offScreenGraphics;
JPanel p = new JPanel();
Button btn = new Button("bun");
JFrame f = new JFrame();
public MyImage()
{
myImage = Toolkit.getDefaultToolkit().getImage("mywineshoplogo.jpg");
setExtendedState(JFrame.MAXIMIZED_BOTH);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
add(p);
p.add(btn);
moveImage();
btn.addActionListener(this);
}
public void update(Graphics g)
{
paint(g);
}
public void paint(Graphics g)
{
int width = getWidth();
int height = getHeight();
if (offScreenImage == null)
{
offScreenImage = createImage(width, height);
offScreenGraphics = offScreenImage.getGraphics();
}
// clear the off screen image
offScreenGraphics.clearRect(0, 0, width + 1, height + 1);
// draw your image off screen
offScreenGraphics.drawImage(myImage, xPixel, 10, this);
// draw your image off screen
// show the off screen image
g.drawImage(offScreenImage, 0, 0, this);
// show the off screen image
}
void moveImage() //left to right move
{
Thread hilo = new Thread() {
public void run() {
try {
for (int i = 0; i < 530; i++)
{
xPixel += 1;
repaint();
// then sleep for a bit for your animation
try
{
Thread.sleep(4);
} /* this will pause for 50 milliseconds */
catch (InterruptedException e)
{
System.err.println("sleep exception");
}
}
} //try
catch (Exception ex) {
// do something...
}
}
};
hilo.start();
}
/* void moveimg() // right to left move
{
for (int i = 529; i > 0; i--)
{
if (i == 1)
{
moveImage();
}
xPixel -= 1;
repaint();
// then sleep for a bit for your animation
try
{
Thread.sleep(40);
} // this will pause for 50 milliseconds
catch (InterruptedException e)
{
System.err.println("sleep exception");
}
}
} */
public void actionPerformed(ActionEvent ae)
{
try
{
if (ae.getSource() == btn)
{
p.setBackground(Color.RED);
}
}
catch (Exception e)
{
System.out.println("error");
}
}
public static void main(String args[])
{
MyImage me = new MyImage();
}
}
Whenever you are about to write Thread.sleep in your GUI code, stop yourself and introduce a task scheduled on Swing's Timer. This is exactly what you need with your code: schedule each update as a separate scheduled task on Timer. Timer is quite simple and straightforward to use, see for example this official Oracle tutorial.

Java Platformer Collision with Platforms

I'm in dire need of help. I've spent 3 hours pulling my hair over the fact that I don't know how to make my collision with one single platform work!
I want the player to be able to jump on the platform and not glitch on it, or fall through it. However, there is also the case that if the player holds up and the left arrow key or right arrow key and comes in contact with the edge of the platform! I really need your help on how I can make the simple aspects of collision with a platform work with my code.
Here is my code:
import java.applet.Applet;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
public class Form1 extends Applet implements Runnable, KeyListener
{
private Image dbImage;
private Graphics dbg;
Thread t1;
int x = 300;
int y = 300;
boolean jumping = false;
double yVel = 0;
double termVel = 10;
int loop_cnt = 0;
int start_cnt = loop_cnt;
boolean falling = false;
boolean left, right, up, down;
double counter2 = 4;
int counter;
int num = 7;
int prevY = y;
int prevX = x;
int d = 0;
Rectangle player;
Rectangle platform;
public void init()
{
setSize(600, 400);
}
public void start()
{
player = new Rectangle();
platform = new Rectangle();
addKeyListener(this);
t1 = new Thread(this);
t1.start();
}
public void stop()
{
}
public void destroy()
{
}
#Override
public void run()
{
while (true)
{
//this code will be used if the player is on a platform and then walks off it by pressing either right or left
if (y <= 300 && !up)
{
y += 10;
}
if (left)
{
prevX = x;
x -= 2;
}
if (right)
{
prevX = x;
x += 2;
}
if (up)
{
counter2 += 0.05;
prevY = y;
y = y + (int) ((Math.sin(counter2) + Math.cos(counter2)) * 5);
if (counter2 >= 7)
{
counter2 = 4;
up = false;
}
}
if (y >= 300)
{
falling = false;
y = 300;
}
repaint();
try
{
t1.sleep(17);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
}
public Rectangle IntersectPlatform()
{
return platform;
}
public void update(Graphics g)
{
dbImage = createImage (this.getSize().width, this.getSize().height);
dbg = dbImage.getGraphics();
// initialize buffer
if (dbImage == null)
{
}
// clear screen in background
dbg.setColor(getBackground());
dbg.fillRect(0, 0, this.getSize().width, this.getSize().height);
// draw elements in background
dbg.setColor(getForeground());
paint(dbg);
// draw image on the screen
g.drawImage(dbImage, 0, 0, this);
}
public void paint(Graphics g)
{
String string = String.valueOf(y);
g.setColor(Color.RED);
g.fillRect(x, y, 40, 100);
player.setBounds(x, y, 40, 100);
g.setColor(Color.BLUE);
platform.setBounds(180, 300, 100, 40);
g.fillRect(180, 300, 100, 40);
g.drawString(string, 100, 100);
}
#Override
public void keyPressed(KeyEvent e)
{
switch (e.getKeyCode())
{
case KeyEvent.VK_RIGHT:
right = true;
break;
case KeyEvent.VK_LEFT:
left = true;
break;
case KeyEvent.VK_UP:
up = true;
break;
case KeyEvent.VK_DOWN:
down = true;
break;
}
}
#Override
public void keyReleased(KeyEvent e)
{
switch (e.getKeyCode())
{
case KeyEvent.VK_RIGHT:
right = false;
break;
case KeyEvent.VK_LEFT:
left = false;
break;
case KeyEvent.VK_UP:
break;
case KeyEvent.VK_DOWN:
down = false;
break;
}
}
#Override
public void keyTyped(KeyEvent arg0)
{
// TODO Auto-generated method stub
}
}

Categories

Resources