I am writing a video game in Java (a horrible idea, yes I know). But I have run into a massive roadblock. I have written code that accesses a text document to output a 'dungeon' through the use of 1s and 0s. This is read into an multidimensional Array [imageArray] which then places my "wall' images. This works like a charm. What I am now trying to do is create a second array that can be accessed outside of the try/catch brackets.
My problem is I have tried several different ways of accessing a secondary array, and I just need help.
Much appreciated.
This is the Code.
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.Random;
import java.io.*;
import java.util.Scanner;
public class main extends JPanel implements KeyListener, ActionListener
{
Timer t = new Timer(8, this);
int xCoord, yCoord;
int x=1;
int y=1;
int d,v;
private Image image1, image2, image3, image4;
boolean pressed;
Random ran = new Random();
int cubeDimension = 40;
int set = cubeDimension + 2;
public main(){
xCoord = 0;
yCoord = 0;
t.start();
addKeyListener(this);
setFocusable(true);
setFocusTraversalKeysEnabled(false);
}
public void paintComponent(Graphics g)
{
super.paintComponent(g);
g.setColor(Color.black);
g.fillRect(0,0, 1000,1000);
g.setColor(Color.white);
for(int i = 0; i < 795; i += set){
for(int e = 0; e < 595; e += set){
g.fillRect(i, e, cubeDimension, cubeDimension);
}
}
//random code (ran.nextInt(9)+1)
//ImageIcon m1 = new ImageIcon("monster1.jpg");
//image2=m1.getImage();
ImageIcon w = new ImageIcon("wall.jpg");
image3 = w.getImage();
ImageIcon j = new ImageIcon("Hero.jpg");
image1 = j.getImage();
try{
Scanner file = new Scanner(new File("room.dat"));
int cnt = file.nextInt();
int cnt2 =file.nextInt();
int[][] imageArray = new int[cnt][cnt2];
for(int i=0;i<cnt;i++)
{
yCoord=i;
for(int c=0;c<cnt2;c++)
{
xCoord=c;
int n = file.nextInt();
imageArray[i][c] = n;
mapArray[xCoord][yCoord]=n;
if (n==1)
{
g.drawImage(image3,c*set,i*set,null);
}
if (n==2)
{
g.drawImage(image1,c*set*x+5,i*set*y,null);
}
}
}
}
catch(FileNotFoundException e){
System.out.println("Error");
}
}
//border code
public void keyReleased(KeyEvent e)
{
int code = e.getKeyCode();
if(code==KeyEvent.VK_NUMPAD8)
if(y>=0)
up();
if(code==KeyEvent.VK_NUMPAD7)
if(y>=0&&x>=0)
upleft();
if(code==KeyEvent.VK_NUMPAD2)
if(y<=14)
down();
if(code==KeyEvent.VK_NUMPAD1)
if(y<=14&&x>0)
downleft();
if(code==KeyEvent.VK_NUMPAD6)
if(x<=19)
right();
if(code==KeyEvent.VK_NUMPAD3)
if(x<=19&&y<=14)
downright();
if(code==KeyEvent.VK_NUMPAD4)
if(x>=0)
left();
if(code==KeyEvent.VK_NUMPAD9)
if(x<=19&&y>0)
upright();
}
public void actionPerformed(ActionEvent e){
repaint();
}
public void up(){ y= y-1 ;}
public void upleft(){y= y-1;x= x-1;}
public void down(){ y= y+1;}
public void downleft(){ y= y+1; x= x-1;}
public void left(){ x = x-1;}
public void upright(){x = x+1;y= y-1;}
public void right(){ x = x+1;}
public void downright(){y= y+1;x = x+1;}
public void keyTyped(KeyEvent e){}
public void keyPressed(KeyEvent e){}
}
My problem is accessing a secondary array outside of the try/catch brackets.
Move imageArray before try block.
int[][] imageArray = null;
try{
Scanner file = new Scanner(new File("room.dat"));
int cnt = file.nextInt();
int cnt2 =file.nextInt();
imageArray = new int[cnt][cnt2];
...
}catch(FileNotFoundException e){
System.out.println("Error");
}
Related
So my university uses the book Java programming from problem analysis to program design by DS Malik(ISBN: 978-1-111-53053-2) and in one of the examples I copied the code word for word. It runs but doesn't work the way its supposed too. What you're supposed to do is be able to click and drag circles that populate the screen in an applet. If anyone is interested in the programming example its 12-10. I have provided the code from eclipse. Any and all help is appreciated.
import javax.swing.*;
import java.awt.event.*;
import java.applet.*;
import java.awt.*;
public class FreeDrawApplet extends JApplet implements MouseMotionListener
{
//instance variables
ColorCircle[] myGraph;
final int NUM_CIRCLES = 7;
final int WIDTH = 400;
final int HEIGHT = 400;
public class ColorCircle
{
private int x;
private int y;
public void setx(int iNewX)
{
x = iNewX;
}
public void sety(int iNewY)
{
x = iNewY;
}
public void paint (Graphics g)
{
g.fillOval(x-10, y-10, 20, 20);
}
public boolean selected(int iXcoord, int iYcoord)
{
if ((iXcoord >= x-10) && (iXcoord <= x+10) && (iYcoord >= y-10) && (iYcoord <= y+10))
return true;
else
return false;
}
}//end of public class circle
public void init ()
{
addMouseMotionListener(this);
myGraph = new ColorCircle[NUM_CIRCLES];
for(int i = 0; i < NUM_CIRCLES; i++)
{
ColorCircle myVertex = new ColorCircle();
myVertex.setx((int)(Math.random() * (WIDTH-50)));
myVertex.sety((int)(Math.random() * (HEIGHT-100)));
myGraph[i] = myVertex;
}
JOptionPane.showMessageDialog(null, "Try to drag any one of the colored circles ", "Information", JOptionPane.PLAIN_MESSAGE);
}//end of method
public void paint(Graphics g)
{
Color[] myColor = {Color.black, Color.red, Color.blue, Color.green, Color.cyan, Color.orange, Color.yellow};
if(NUM_CIRCLES > 0)
for(int i =0; i < NUM_CIRCLES; i++)
{
g.setColor(myColor[i]);
myGraph[i].paint(g);
}
}//end of paint method
public void mouseDragged(MouseEvent event)
{
int iX = event.getX();
int iY = event.getY();
for(int i = 0; i < NUM_CIRCLES; i++)
{
if(myGraph[i].selected(iX, iY))
{
myGraph[i].setx(iX);
myGraph[i].sety(iY);
break;
}
}
repaint();
}
public void mouseMoved(MouseEvent p1)
{
}
}
I am writing a code of game bean machine(Galton box), its mechanism that one ball fall and move randomly until it get to one of the slots (randomly) and then another ball comes doing the same thing and so on, the problem is that all balls fall at the same time which something I do not want, I want each ball to fall when the current one finishes its travel..can anyone helps me ! Thanks..
here is the code:
import java.awt.*;
import java.awt.event.*;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Random;
import java.util.Scanner;
import java.lang.Iterable;
import javax.swing.*;
public class BallPanel extends JPanel {
int x=1, y=1;
Collection <Ball> ball;
public static void main(String [] args){
// create the list
SwingUtilities.invokeLater(new Runnable() {
public void run() {
JFrame frame= new JFrame("Bean game");
frame.add(new BallPanel());
frame.setSize(300,500);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
});
}
public BallPanel() {
JPanel panel = new JPanel();
ball=new ArrayList<>();
for(int i=1;i<=4;i++){
ball.add(new Ball(x,y));
x++;
y++;
}
Timer timer = new Timer(400, new ActionListener()
{
public void actionPerformed(ActionEvent e) {
for (Ball b: ball) {
b.move();repaint();
}
}
});
timer.start();
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
int raduis=10;
int i=0;
int width=(getWidth()/8);
int space=(getWidth()-8*30)/2;
g.setColor(Color.BLACK);
for(i=0;i<=8;i++){
g.drawLine(space+(30*i),getHeight()-5*(raduis) ,space+(30*i) ,getHeight() );
if(i!=0 && i!=8)
g.fillOval(space+(30*i)-5, getHeight()-5*(raduis)-5, 10, 10);
if(i==0){
g.drawLine(space,getHeight()-5*(raduis) , space+((8)*15)-(raduis/2)-15 , getHeight()-15-(5*raduis)-(30*(8-2))-raduis/2);
g.drawLine(space+((8)*15)-(raduis/2)-15 , getHeight()-15-(5*raduis)-(30*(8-2))-raduis/2 , space+((8)*15)-(raduis/2)-15 , getHeight()/2-8*8);//vertical line
}
if(i==8){
g.drawLine(space+(30*i), getHeight()-5*(raduis), space+((8)*15)+(raduis/2)+15, getHeight()-15-(5*raduis)-(30*(8-2))-raduis/2);
g.drawLine(space+((8)*15)+(raduis/2)+15 , getHeight()-15-(5*raduis)-(30*(8-2))-raduis/2 , space+((8)*15)+(raduis/2)+15 , getHeight()/2-8*8);//vertical line
}
}
int o=1;
for(i=1;i<=8-2;i++){
int k=2;
for(int j=i;j<=8-2;j++){
g.fillOval(space+((i+k)*15)-raduis/2, getHeight()-(5*raduis)-(30*o)-raduis/2, raduis, raduis);
k=k+2;
}o++;
}
for (Ball b : ball) {
b.draw(g);
}
}
public class Ball {
Random rand=new Random();
private int n;
private int raduis = 10;
private int moveRaduis=12;
private int L = 0;
private int R = 0;
private int D = 0;
int x, y;
public Ball(int x, int y){
this.x=x;
this.y=y;
}
public void draw(Graphics g) {
g.setColor(Color.RED);
g.fillOval(getWidth()/2 -raduis/2 + R + L, 0 + D , moveRaduis, moveRaduis);
}
public void move() {
n=1+rand.nextInt(100);
if(n<=51){
D+=15;
if(D<=(getHeight()-15-(5*raduis)-(30*(8-2))-raduis/2))
L=0;
else if(D>getHeight()-15-(5*raduis)-(30*(8-2))-raduis/2 && D<getHeight()-5*(raduis))
{
D+=15;
L-=15;
}
else if(D>=getHeight()-5*(raduis))
{
if(D==31*15)D-=15;
D=D;
}
}
else if (n>=51 && n<=100){
D+=15;
if(D<=getHeight()-15-(5*raduis)-(30*(8-2))-raduis/2)
R=0;
else if(D>getHeight()-15-(5*raduis)-(30*(8-2))-raduis/2 && D<getHeight()-5*(raduis))
{
D+=15;
R+=15;
}
else if(D>=getHeight()-5*(raduis)){
if(D==31*15)D-=15;
D=D;
}
}
}
}
}
So, your movement code moves all the balls on each iteration, what you need to do is have an "active" ball, for example...
private Ball activeBall;
Timer timer = new Timer(400, new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (activeBall != null && activeBall.hasCompleted()) {
activeBall = null;
}
if (activeBall == null && ball.size() > 0) {
activeBall = ball.remove(0);
}
if (activeBall != null) {
activeBall.move();
repaint();
}
}
});
You'll need to add in some kind of check to determine the ball has completed it's run though
basically i have been following a Java tutorial to make a basic maze game where i generate a random maze which is saved to a file then i print it out using Jpanel however i keep getting this error when i compile.
Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
at maze.Map.getMap(Map.java:43)
at maze.Board.paint(Board.java:40)
However i am not sure why, i believe it is something to do with my Y integer but if i set it to 0 it causes my program to print out wrong(just prints the same column instead of changing rows).
I need the Y value in Map.java:43 to increase like my x value does however it provides me with the Exception error.
Code:
Map Class
package maze;
import java.awt.Image;
import java.io.File;
import java.util.*;
import javax.swing.ImageIcon;
public class Map {
private Scanner m;
private Image wall, ground;
//number of columns
private String Map[] = new String[20];
public Map() {
//sets ground to a texture
ImageIcon img = new ImageIcon("C:\\MazeGraphics\\ground.png");
ground = img.getImage();
//sets wall texture
img = new ImageIcon("C:\\MazeGraphics\\wall.png");
wall = img.getImage();
openFile();
readFile();
closeFile();
}
public Image getGround() {
// gives grass texture for screen
return ground;
}
public Image getWall() {
// gives wall texture for screen
return wall;
}
public String getMap(int x, int y) {
//compares string to find graphic to use
String index= Map[y].substring(x, x+1);
return index;
}
public void openFile() {
try {
m = new Scanner(new File("C:\\MazeGraphics\\Maze.txt"));
} catch (Exception e) {
System.out.println("Error Loading Map");
}
}
public void readFile() {
for(int i = 0; i < 20; i++)
{
while(m.hasNext()){
Map[i] = m.next();
}
}
}
public void closeFile() {
m.close();
}
}
Board Class:
package maze;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class Board extends JPanel implements ActionListener {
private Timer timer;
private Map m;
private Player p;
public Board()
{
MazeGeneration maz=new MazeGeneration();
//runs Map class
m = new Map();
p = new Player();
//listens for key presses
addKeyListener(new Al());
//knows to add key listener to the frame
setFocusable(true);
timer = new Timer(25, this);
timer.start();
}
public void actionPerformed(ActionEvent e) {
repaint();
}
public void paint(Graphics g) {
super.paint(g);
//paints the board row by row
for (int y = 0; y < 20; y++)
{
for (int x = 0; x < 20; x++)
{
//places graphic depending on the letter.
if (m.getMap(x, y).equals("g"))
{
g.drawImage(m.getGround(), y * 32, x * 32, null);
}
if (m.getMap(x, y).equals("w"))
{
g.drawImage(m.getWall(), y * 32,x * 32, null);
}
}
}
g.drawImage(p.getPlayer(), p.gettileX() * 32, p.gettileY() * 32, null);
}
public class Al extends KeyAdapter {
//moving the player
public void keyPressed(KeyEvent e, char maz[][], int r, int c) {
int keycode = e.getKeyCode();
if (keycode == KeyEvent.VK_W) {
//if not a wall can move
if (!m.getMap(p.gettileX(), p.gettileY() - 1).equals("w")) {
p.move(0, -1);
}
}
if (keycode == KeyEvent.VK_S) {
if (!m.getMap(p.gettileX(), p.gettileY() + 1).equals("w")) {
p.move(0, 1);
}
}
if (keycode == KeyEvent.VK_A) {
if (!m.getMap(p.gettileX() - 1, p.gettileY()).equals("w")) {
p.move(-1, 0);
}
}
if (keycode == KeyEvent.VK_D) {
if (!m.getMap(p.gettileX() + 1, p.gettileY() ).equals("w")) {
p.move(1, 0);
}
}
}
}
}
The issue is in this code: In your readFile() method, your issue arises during reading your file:
for(int i = 0; i < 20; i++)
{
while(m.hasNext()){
Map[i] = m.next();
}
}
You are assigning the value only to the 0'th index. To explain, for the first for loop, the index i is at zero. The inner loop "iterates" through the Scanner m until there is no element next. Therefore, Map[0] contains the last element on the file.
Your solution is as follows:
int i = 0;
while (m.hasNext()) {
Map[i++] = m.next();
}
I hope this helps.
I would like to make a graphical representation of the audio signal.
I have a problem with entering data array to the method paint (Graphics g).
Data entered in the method setData(int intValue) works fine.
But if I want to print a data array in the method paint() I have zero values.
Why?
import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JPanel;
public class MyPlotter extends JPanel{
int width = 320;
int height = 130;
int frameSize;
int[] data;
public MyPlotter(int fSize){
setSize(width,height);
setPreferredSize(this.getSize());
this.frameSize = fSize;
data = new int[fSize+1];
}
public void setData(int[] intValue){
data = intValue;
// this works fine:
for (int i=0; i<440; i++)
System.out.println("setData "+data[i]);
repaint();
}
public void paint (Graphics g){
// some code:
// g.drawLine(...)
// g.setColor(...)
// etc...
for (int i = 0; i< frameSize-1;i++)
{
//ZERO values:
System.out.println("paint() "+(data[i]));
// g.drawline(...);
}
}
}
Edit:
Array Data is entered from MyPanel.class
import javax.swing.JPanel;
public class MyPanel extends JPanel {
private MyPlotter plotter;
public MyPanel(){
setSize(320,210);
plotter = new MyPlotter(440);
add(this.plotter,0);
}
public void setData(int[] data){
plotter.setData(data);
}
}
data = intValue;
Here you are psssing reference of intValue to data. If you change data intValue array also get changed.
Try this :
data = System.arraycopy( intValue, 0, data, 0, intValue.length);
Instead of :
data = intValue;
I think that possibly the "repaint()" method you called modifies the original array "intValue"
The assignment you have made data = intValue; only makes "data[]" a reference of your original array so as repaint is called seems like the data is reset or the reference is lost.If you want to copy the array you can do any of the following if a & b are two arrays:
b = Arrays.copyOf(a, a.length);
0r
b = new int[a.length];
System.arraycopy(a, 0, b, 0, b.length);
or
b = (int[]) a.clone();
or
int b[] = new int[a.length];
for (int i = 0; i < a.length; i++) {
b[i] = a[i];
}
Your code is OK. The problem is in the main method. Ensure you have added only one plotter to the panel.
public static void main(String[]args){
int[] mass = new int[]{1,2,3,4,5,6,7,8,9,10};
JFrame frame = new JFrame();
MyPanel mp = new MyPanel();
frame.add(mp);
frame.setSize(300, 300);
mp.setData(mass);
frame.setVisible(true);
}
Works well.
I'm sorry to answer my own post, but I changed the program completely.
I do not know if I can remove the code from the first post. So I put in a new post.
I changed a application but still have a problem with entering the array to another method.
Copy arrays by "Arrays.copyOf b = (a, a.length)" and changing the array as static does not fix a problem.
I can't enter array from setSignal() to getSignal() in OscilloscopeController class.
OscilloscopeController.java
import java.util.Arrays;
import java.util.Random;
public class OscilloscopeController {
private static int frameSize = (int) (44100 / 100F);
private int idx, numFramesToSkip = 10;
private static int[] toDraw = new int[frameSize];
private static int[] data = new int[frameSize];
public OscilloscopeController() {
for (int i = 0; i < frameSize; i++) {
toDraw[i] = 0;
data[i] = 0;
}
}
public void setSignal(int in) {
// Because the Model layer is off, I generate a test signal
Random randomGenerator = new Random();
int j = 0;
for (int i = 0; i < 44100; i++) {
int randomInt = randomGenerator.nextInt(32675 * 2) - (32675);
if (i % 4 == 0) {
j = randomInt;
}
in = j;
}
if (idx++ > frameSize * numFramesToSkip)
{
idx = 0;
}
else
{
if (idx < frameSize) {
data[idx] = in;
}
if (idx == frameSize)
{
// HERE IS PROBLEM. I'D LIKE THIS toDraw in getSignal()
toDraw = Arrays.copyOf(data, data.length);
}
}
}
public int[] getSignal() {
// IF UNCOMMENT BELOW WORKS FINE, OTHERWISE ZERO VALUES
/*
Random randomGenerator = new Random();
int j=0;
for (int i = 0; i < 440; i++) {
int randomInt = randomGenerator.nextInt(32675*2)-(32675);
if (i%4==0) j = randomInt;
toDraw[i]=j;
}
*/
for (int i = 0; i < frameSize; i++)
System.out.println("Controller.getSignal() = "+ toDraw[i]);
return toDraw;
}
}
MainPanel contains main method:
import java.awt.*;
import javax.swing.*;
public class MainPanel extends JPanel {
public static void main(String args[]) throws Exception {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new MainPanel());
frame.pack();
frame.setVisible(true);
}
});
}
private final OscilloscopeView oscView = new OscilloscopeView();
private final OscilloscopeController oscController = new OscilloscopeController();
public MainPanel() {
setPreferredSize(new Dimension(400, 200));
// a lot of other components here
oscView.setData(oscController.getSignal());
add(oscView);
}
}
OscilloscopeView.java
import javax.swing.JFrame;
import javax.swing.JPanel;
public class OscilloscopeView extends JPanel {
private OscPlotter plotter = new OscPlotter(441);;
public OscilloscopeView()
{
setSize(320,210);
add(this.plotter);
}
public void setData(int[] data){
plotter.setData(data);
}
}
OscPlotter.java
import java.awt.Color;
import java.awt.Graphics;
import java.util.Arrays;
import javax.swing.JPanel;
public class OscPlotter extends JPanel{
private int width = 320;
private int height = 130;
private float widthC;
private float heightC;
private int sampleSize;
private int frameSize;
private int[] toDraw;
private float x,prevX;
public OscPlotter(int fSize){
setSize(width,height);
setPreferredSize(this.getSize());
this.frameSize = fSize;
this.toDraw = new int[441];
sampleSize = 1;
}
public void setData(int[] data){
toDraw = Arrays.copyOf(data, data.length);
repaint();
}
#Override
public void paintComponent(Graphics g){
widthC = ((float)width/frameSize);
sampleSize = (16 == 16 ? 65536 : 256);
heightC = (((float)height-15)/sampleSize);
g.setColor(Color.black);
g.fillRect(0,0,width,height);
g.setColor(Color.gray);
for (int i = 1; i<height;i+=height/8)
g.drawLine(0,i,width,i);
for (int i = 1; i<width;i+=width/8)
g.drawLine(i,0,i,height);
g.setColor(Color.lightGray);
g.drawLine(0,(int)(height/2),width,(int)((height/2)));
g.setColor(Color.green);
x = 0;
for (int i = 0; i< frameSize-1;i++)
{
prevX = x;
x +=widthC;
// draw the read waveform data
g.drawLine ((int)prevX,(int)((height/2+toDraw[i]*heightC)),(int)x,(int)((height/2+toDraw[i+1]*heightC)));
}
}
}
I am having a problem with a game that I am trying to make in Java. I am trying to attach a MouseListener to my canvas, however, when I click on the canvas, nothing happens. I think I may be attaching the MouseListener to the wrong thing, but I don't know what to attach it to. I have tried attaching it to the JFrame and the canvas. Here is my code:
import java.awt.*;
import java.awt.event.*;
import java.util.ArrayList;
import java.io.*;
import javax.imageio.ImageIO;
import javax.swing.*;
import java.util.Random;
public class Gravity extends Canvas {
public static final int screenw = 1024;
public static final int screenh = 768;
public static Random gen = new Random();
public static Boolean started = false;
public static int[] starx = new int[100];
public static int[] stary = new int[100];
public static Color[] starc = new Color[100];
public static JFrame frame;
public static Gravity canvas;
public static Image buffer;
public static Graphics bg;
public static int[] xh = new int[1000];
public static int[] yh = new int[1000];
public static int i = 0;
public static Image title;
public static ArrayList<Integer> ptx = new ArrayList<Integer>();
public static ArrayList<Integer> pty = new ArrayList<Integer>();
double x = 100;
double y = 100;
public Gravity(){
}
public void paint (Graphics g) {
frame.addMouseListener(new MouseListener(){
public void mouseClicked(MouseEvent e){
started = true;
System.out.println("Mouse was clicked");
}
public void mouseEntered(MouseEvent arg0) {}
public void mouseExited(MouseEvent arg0) {}
public void mousePressed(MouseEvent arg0) {}
public void mouseReleased(MouseEvent arg0) {}
});
buffer = createImage(screenw, screenh);
bg = buffer.getGraphics();
int w = getWidth();
int h = getHeight();
double px = getWidth()/2;
double py = getHeight()/2;
bg.setColor(Color.BLACK);
bg.fillRect(0, 0, w, h); //black background
for (int j=0; j < 100; j++){ //make stars
starx[j] = gen.nextInt(w);
stary[j] = gen.nextInt(h);
starc[j] = new Color(gen.nextInt(100)+156, gen.nextInt(100)+156, gen.nextInt(100)+156);
bg.setColor(starc[j]);
bg.drawLine(starx[j], stary[j], starx[j]+2, stary[j]+2);
bg.drawLine(starx[j], stary[j]+2, starx[j]+2, stary[j]);
}
try {
title = ImageIO.read(new ByteArrayInputStream(Base64.decode(""))); //I have omitted the Base64 code for the image for my title screen
} catch (IOException e) {
e.printStackTrace();
}
bg.drawImage(title, 100, 100, null);
g.drawImage(buffer, 0, 0, null);
while (!started){
try {
Thread.sleep(50);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
}
double xvel = -15;
double yvel = 10;
for (int j=0; j < 100; j++){ //store stars
starx[j] = gen.nextInt(w);
stary[j] = gen.nextInt(h);
starc[j] = new Color(gen.nextInt(100)+156, gen.nextInt(100)+156, gen.nextInt(100)+156);
}
Image test = createImage(200,200);
Graphics testg = test.getGraphics();
testg.drawLine(50,50,150,150);
while(true){
g.drawImage(buffer, 0,0, null);
try {
Thread.sleep(33);
} catch (Exception e) {
e.printStackTrace();
}
bg.setColor(Color.BLACK);
bg.fillRect(0, 0, w, h); //black background
for (int j=0; j < 100; j++){ //draw stars
bg.setColor(starc[j]);
bg.drawLine(starx[j], stary[j], starx[j]+2, stary[j]+2);
bg.drawLine(starx[j], stary[j]+2, starx[j]+2, stary[j]);
}
bg.setColor(Color.BLUE);
if (i > 0){
for (int z=0; z < i-1; z++){
bg.drawLine(ptx.get(z), pty.get(z), ptx.get(z+1), pty.get(z+1));
}
}
bg.setColor(Color.CYAN);
bg.fillOval((int)px, (int)py, 25, 25); //planet
bg.setColor(Color.RED);
bg.fillRect((int)(x-5),(int)(y-5),10,10); //ship
double fg = (5*50000)/(Math.pow(dist(x,y,px,py),2));
double m = (y-py)/(x-px);
double ms = Math.sqrt(Math.abs(m));
if (m < 0) ms = -ms;
double xchg = fg;
double ychg = fg*ms;
if (x > px){
xchg = -xchg;
ychg = -ychg;
}
xvel += xchg;
yvel += ychg;
x += xvel;
y += yvel;
ptx.add((int)x);
pty.add((int)y);
i++;
}
}
public static void main(String[] args){
canvas = new Gravity();
frame = new JFrame();
frame.setSize(screenw, screenh);
frame.setResizable(false);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(canvas);
frame.setVisible(true);
}
public static double dist(double x1, double y1, double x2, double y2){
double x = x2-x1;
double y = y2-y1;
return Math.sqrt((x*x)+(y*y));
}
}
General tips, in point form:
Don't mix AWT (e.g. Canvas) with Swing (e.g. JFrame) components. Instead of the Canvas, use a JPanel and override paintComponent(Graphics) rather than paint(Graphics).
Don't call Thread.sleep(n) on the EDT. Instead use a Swing based Timer to call repaint()
Don't perform long running operations on the paint method, especially starting an infinite loop! Even the creation of the buffer image should only be done in the case the screen size changes. (left as 'TODO' - BNI)
Add the MouseListener once in the constructor or an init() method rather than every time paint is called.
Highly recommend all of Nate's numbered list of notes.
Try this code, and compare it carefully to the original to see the changes.
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Dimension;
import java.awt.event.*;
import java.util.ArrayList;
import java.io.*;
import javax.imageio.ImageIO;
import javax.swing.*;
import java.util.Random;
public class Gravity extends JPanel {
public static final int screenw = 800;
public static final int screenh = 600;
public static Random gen = new Random();
public static int[] starx = new int[100];
public static int[] stary = new int[100];
public static Color[] starc = new Color[100];
public static Image buffer;
public static Graphics bg;
public static int[] xh = new int[1000];
public static int[] yh = new int[1000];
public static int i = 0;
public static ArrayList<Integer> ptx = new ArrayList<Integer>();
public static ArrayList<Integer> pty = new ArrayList<Integer>();
double x = 100;
double y = 100;
Timer timer;
public Gravity(){
// set thre PREFERRED size!
setPreferredSize(new Dimension(screenw, screenh));
addMouseListener(new MouseListener(){
public void mouseClicked(MouseEvent e){
System.out.println("Mouse was clicked");
timer.start();
}
public void mouseEntered(MouseEvent arg0) {}
public void mouseExited(MouseEvent arg0) {}
public void mousePressed(MouseEvent arg0) {}
public void mouseReleased(MouseEvent arg0) {}
});
ActionListener animation = new ActionListener() {
#Override
public void actionPerformed(ActionEvent ae) {
repaint();
}
};
timer = new Timer(50, animation);
}
#Override
public void paintComponent(Graphics g) {
buffer = createImage(screenw, screenh);
bg = buffer.getGraphics();
int w = getWidth();
int h = getHeight();
double px = getWidth()/2;
double py = getHeight()/2;
bg.setColor(Color.BLACK);
bg.fillRect(0, 0, w, h); //black background
for (int j=0; j < 100; j++){ //make stars
starx[j] = gen.nextInt(w);
stary[j] = gen.nextInt(h);
starc[j] = new Color(gen.nextInt(100)+156, gen.nextInt(100)+156, gen.nextInt(100)+156);
bg.setColor(starc[j]);
bg.drawLine(starx[j], stary[j], starx[j]+2, stary[j]+2);
bg.drawLine(starx[j], stary[j]+2, starx[j]+2, stary[j]);
}
g.drawImage(buffer, 0, 0, null);
double xvel = -15;
double yvel = 10;
for (int j=0; j < 100; j++){ //store stars
starx[j] = gen.nextInt(w);
stary[j] = gen.nextInt(h);
starc[j] = new Color(gen.nextInt(100)+156, gen.nextInt(100)+156, gen.nextInt(100)+156);
}
Image test = createImage(200,200);
Graphics testg = test.getGraphics();
testg.drawLine(50,50,150,150);
g.drawImage(buffer, 0,0, null);
try {
Thread.sleep(33);
} catch (Exception e) {
e.printStackTrace();
}
bg.setColor(Color.BLACK);
bg.fillRect(0, 0, w, h); //black background
for (int j=0; j < 100; j++){ //draw stars
bg.setColor(starc[j]);
bg.drawLine(starx[j], stary[j], starx[j]+2, stary[j]+2);
bg.drawLine(starx[j], stary[j]+2, starx[j]+2, stary[j]);
}
bg.setColor(Color.BLUE);
if (i > 0){
for (int z=0; z < i-1; z++){
bg.drawLine(ptx.get(z), pty.get(z), ptx.get(z+1), pty.get(z+1));
}
}
bg.setColor(Color.CYAN);
bg.fillOval((int)px, (int)py, 25, 25); //planet
bg.setColor(Color.RED);
bg.fillRect((int)(x-5),(int)(y-5),10,10); //ship
double fg = (5*50000)/(Math.pow(dist(x,y,px,py),2));
double m = (y-py)/(x-px);
double ms = Math.sqrt(Math.abs(m));
if (m < 0) ms = -ms;
double xchg = fg;
double ychg = fg*ms;
if (x > px){
xchg = -xchg;
ychg = -ychg;
}
xvel += xchg;
yvel += ychg;
x += xvel;
y += yvel;
ptx.add((int)x);
pty.add((int)y);
i++;
}
public static void main(String[] args){
SwingUtilities.invokeLater(new Runnable() {
public void run() {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new Gravity());
frame.setResizable(false);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
});
}
public static double dist(double x1, double y1, double x2, double y2){
double x = x2-x1;
double y = y2-y1;
return Math.sqrt((x*x)+(y*y));
}
}
Use a JComponent instead of a Canvas. You'll want to add the mouse listener to that object. You'll also need to set up the mouse listener in the constructor, not the paint() method.
Edit: You're doing to much in the paint() method as #AndrewThompson pointed out.
public Gravity() {
addMouseListener(new MouseListener() {
#Override
public void mouseClicked(MouseEvent e) {
System.out.println("Mouse was clicked");
}
#Override
public void mouseEntered(MouseEvent arg0) {
}
#Override
public void mouseExited(MouseEvent arg0) {
}
#Override
public void mousePressed(MouseEvent arg0) {
}
#Override
public void mouseReleased(MouseEvent arg0) {
}
});
}
#Override
public void paint(Graphics g) {
buffer = createImage(screenw, screenh);
bg = buffer.getGraphics();
...
bg.setColor(Color.BLACK);
bg.fillRect(0, 0, w, h); // black background
for (int j = 0; j < 100; j++) { // make stars
...
}
bg.drawImage(title, 100, 100, null);
g.drawImage(buffer, 0, 0, null);
double xvel = -15;
double yvel = 10;
for (int j = 0; j < 100; j++) { // store stars
...
}
Image test = createImage(200, 200);
Graphics testg = test.getGraphics();
testg.drawLine(50, 50, 150, 150);
g.drawImage(buffer, 0, 0, null);
bg.setColor(Color.BLACK);
bg.fillRect(0, 0, w, h); // black background
for (int j = 0; j < 100; j++) { // draw stars
...
}
bg.setColor(Color.BLUE);
if (i > 0) {
for (int z = 0; z < i - 1; z++) {
bg.drawLine(ptx.get(z), pty.get(z), ptx.get(z + 1), pty.get(z + 1));
}
}
bg.setColor(Color.CYAN);
bg.fillOval((int) px, (int) py, 25, 25); // planet
bg.setColor(Color.RED);
bg.fillRect((int) (x - 5), (int) (y - 5), 10, 10); // ship
....
ptx.add((int) x);
pty.add((int) y);
}
public static void main(String[] args) {
...
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
...
}
Notes about your code:
Avoid making fields public static. 99.9% of the time this is not necessary, and usually leads to trouble later.
The painting code seems to be unnecessarily using buffers--the test Image is not used at all currently!
I removed the while(true) loop, but noticed you're drawing an image, modifying the image, and then drawing the image again. You can probably do this in one go.
You should be able to avoid using an Image buffer altogether since you're creating a new one each time paint() is called, and clearing it at the beginning. Just draw your graphics directly to g.
Avoid doing I/O from within the paint() method. Load your images during construction or in a background thread.
Your paint() method is tying up the Thread that handles the mouse click event, due to the while (!started) loop that never exits. started is never true because the MouseListener's mouseClicked() is never called because the paint() method is waiting for started to be true! If you remove that loop, the while (true) loop will have a similar effect. Any mouse events that happen while paint() is running will be queued until paint() returns.