I have written code to drive a Differential Drive Robot through a fixed path, chosen by me. I am trying to get the code to run either from the command line:
java StartRobot
or being able to run the application an an Applet within a browser. My code is below:
import java.awt.*;
import javax.swing.*;
import java.util.ArrayList;
import java.util.List;
class DifferentialDriveRobot {
public static void main(String[] args) {
new DifferentialDriveRobot();
}
public DifferentialDriveRobot() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
createAndShowGUI();
}
});
}
public void createAndShowGUI() {
JFrame frame = new JFrame("Differential Drive Robot");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
Robots robots = new Robots();
frame.add(robots);
frame.setSize(400,400);
frame.setVisible(true);
new Thread(new Drive(robots)).start();
}
public static int random(int maxRange) {
return (int) Math.round((Math.random() * maxRange));
}
public class Robots extends JPanel {
private List<Bot> robots;
public Robots() {
robots = new ArrayList<Bot>(1);
robots.add(new Bot(Color.red));
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
for(Bot robot : robots) {
robot.paint(g2d);
}
g2d.dispose();
}
public List<Bot> getRobots() {
return robots;
}
}
public class Drive implements Runnable {
private Robots parent;
public Drive(Robots parent) {
this.parent = parent;
}
#Override
public void run() {
int width = getParent().getWidth();
int height = getParent().getHeight();
for(Bot robot : getParent().getRobots()) {
int x = 5;
int y = 5;
int diameter = robot.getDiameter();
if(x + diameter > width) {
x = width - diameter;
}
if(y + diameter > height) {
y = height - diameter;
}
robot.setX(x);
robot.setY(y);
}
while(getParent().isVisible()) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
getParent().repaint();
}
});
for(Bot robot : getParent().getRobots()) {
move(robot);
}
try {
Thread.sleep(100);
} catch(InterruptedException ex) {}
}
}
public Robots getParent() {
return parent;
}
public void move(Bot robot) {
int diameter = robot.getDiameter();
double v1 = robot.getV1();
double v2 = robot.getV2();
double x = robot.getX();
double y = robot.getY();
double theta = robot.getTheta();
double dx, dy, dtheta;
int time = robot.getTime();
dx = 0.5*(Math.cos(Math.toRadians(theta)))*(v1+v2);
dy = 0.5*(Math.sin(Math.toRadians(theta)))*(v1+v2);
dtheta = (-1)*(0.5*(v2-v1));
if((x + dx < 0 || x + diameter + dx > getParent().getWidth()) || (y + dy < 0 || y + diameter + dy > getParent().getHeight())) {
v1 = 0;
v2 = 0;
} else {
if(time == 50) {
v2 = 0;
} else if(time > 50 && time < 300 && theta == 89.5) {
v1 = v2 = 1;
} else if(time > 300 && time < 450) {
v1 = 1;
v2 = 3;
}
if(time > 400 && theta == -89.0 && time < 500) {
v1 = 5;
v2 = 5;
}
if(time > 500 && time < 550) {
v1 = v2 = 0;
} else if(time > 550 && time < 600) {
v1 = v2 = -2;
} else if(time > 600) {
v1 = v2 = 0;
}
}
x = x + dx;
y = y + dy;
theta = theta + dtheta;
time = time + 1;
robot.setTheta(theta);
robot.setV1(v1);
robot.setV2(v2);
robot.setX(x);
robot.setY(y);
robot.setTime(time);
}
}
public class Bot {
private Color color;
private double x, y;
private int diameter;
private double v1, v2;
private double theta;
private int time;
public Bot(Color color) {
setColor(color);
v1 = 1;
v2 = 1;
diameter = 30;
theta = 0;
time = 0;
}
public int getTime() {
return time;
}
public void setTime(int time) {
this.time = time;
}
public int getDiameter() {
return diameter;
}
public void setColor(Color color) {
this.color = color;
}
public void setX(double x) {
this.x = x;
}
public void setY(double y) {
this.y = y;
}
public void setTheta(double theta) {
this.theta = theta;
}
public Color getColor() {
return color;
}
public double getX() {
return x;
}
public double getY() {
return y;
}
public double getV1() {
return v1;
}
public double getV2() {
return v2;
}
public double getTheta() {
return theta;
}
public void setV1(double v1) {
this.v1 = v1;
}
public void setV2(double v2) {
this.v2 = v2;
}
protected void paint(Graphics2D g2d) {
double x = getX();
double y = getY();
double v1 = getV1();
double v2 = getV2();
g2d.rotate(Math.toRadians(theta),x,y);
g2d.setColor(getColor());
g2d.fillRect((int)x, (int)y, getDiameter(), getDiameter());
g2d.setColor(Color.black);
g2d.fillOval((int)x+9,(int)y-5,15,15);
g2d.fillOval((int)x+9,(int)y+20,15,15);
}
}
}
In the past I have been able to accomplish this by adding the following into my .java file:
public class StartRobot extends JApplet {
public void init() {
EventQueue.invokeLater(new Runnable() {
public void run() {
DifferentialDriveRobot panel = new DifferentialDriveRobot();
getContentPane.add(panel);
}
});
}
public static void main(String[] args) {
//Schedule a job for the event-dispatching thread:
//creating and showing this application's GUI.
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
DifferentialDriveRobot panel = new DifferentialDriveRobot();
panel.createAndShowGUI();
}
});
}
}
However, this throws an error while compiling. I think this is due to the fact that my main class DifferentialDriveRobot does not extend JPanel, instead it is a subclass where I accomplish this. Is there a quick fix to this?
The class DifferentialDriveRobot is a non-component class that cannot be added to an applet. It is a class that causes a JFrame to be created and adds your Robot panel class. This will cause a JFrame to appear if you run the applet in a browser, which is usually not desirable.
You could define the class Robot as your applet:
public class Robot extends JApplet {
public void init() {
...
}
then add the applet to your main method:
public static void main(String[] args) {
JFrame frame = new JFrame("Applet Demo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(500, 400);
JApplet applet = new Robot();
applet.init();
applet.start();
frame.add(applet);
frame.setVisible(true);
}
If you want the applet to run as an application, a good alternative is to convert it completely an JFrame-based application and deploy it using Java Web Start.
Related
I am working on a donkey kong type game and like I said I want the player to only jump if he is on the floor.
I made a sort of a gravity mechanic and I check collision so he don't go through a floor and I came up with an idea that your can jump only when you are colliding. But here comes the main problem that I don't know how to tell that information to a method in another class.
Hope it makes some sense, I am a beginner and don't know if I described the problem well.
I tried to separate my code but it makes more problems
Here's a class with a player:
import java.awt.*;
import java.awt.event.KeyEvent;
public class Mario extends Rectangle {
int rychlost = 5;
int xZrychleni;
int gravitace= 5;
int yZrychleni;
int vyskok = 20;
Mario(int x, int y, int SIRKA_MARIA,int VYSKA_MARIA){
super(x, y, SIRKA_MARIA, VYSKA_MARIA);
}
public void nakresli(Graphics g) {
g.setColor(Color.white);
g.fillRect(x, y, width, height);
}
public void keyPressed(KeyEvent e) {
if(e.getKeyCode()==KeyEvent.VK_A) {
nastavSmerX(-rychlost);
}
if(e.getKeyCode()== KeyEvent.VK_D) {
nastavSmerX(rychlost);
}
if(e.getKeyCode()==KeyEvent.VK_SPACE){
nastavSmerY(vyskok);
}
}
public void keyReleased(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_A) {
nastavSmerX(0);
}
if (e.getKeyCode() == KeyEvent.VK_D) {
nastavSmerX(0);
}
if(e.getKeyCode()==KeyEvent.VK_SPACE){
nastavSmerY(0);
}
}
public void nastavSmerX ( int SmerX){
xZrychleni = SmerX;
}
public void nastavSmerY ( int SmerY){
yZrychleni = SmerY;
}
public void move () {
x = x + xZrychleni;
y = y + gravitace;
y = y - yZrychleni;
}
}
Here is a panel class where I check collisions:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class HerniPanel extends JPanel implements Runnable{
static final int HERNI_SIRKA = 1200;
static final int HERNI_VYSKA = 700;
static final Dimension SCREEN_SIZE = new Dimension(HERNI_SIRKA, HERNI_VYSKA);
static final int SIRKA_PLOSINY = 1000;
static final int VYSKA_PLOSINY = 35;
static final int SIRKA_ZEBRIKU = 25;
static final int VYSKA_ZEBRIKU = 180;
static final int MARIO_VELIKOST_XY = 50;
Thread gameThread;
Image image;
Graphics graphics;
Plosina plosina0;
Plosina plosina1;
Plosina plosina2;
Plosina plosina3;
Mario mario;
Zebrik zebrik1;
Zebrik zebrik2;
Zebrik zebrik3;
HerniPanel(){
novaPlosina();
novyMario();
novyZebrik();
this.setFocusable(true);
this.addKeyListener(new AL());
this.setPreferredSize(SCREEN_SIZE);
gameThread = new Thread(this);
gameThread.start();
}
public void novaPlosina() {
plosina0 = new Plosina(0, (HERNI_VYSKA - VYSKA_PLOSINY), HERNI_SIRKA, VYSKA_PLOSINY, 1);
plosina1 = new Plosina((HERNI_SIRKA - SIRKA_PLOSINY),(HERNI_VYSKA - VYSKA_PLOSINY - 180), SIRKA_PLOSINY, VYSKA_PLOSINY, 2 );
plosina2 = new Plosina(0, (HERNI_VYSKA - VYSKA_PLOSINY - 360), SIRKA_PLOSINY, VYSKA_PLOSINY,3 );
plosina3 = new Plosina((HERNI_SIRKA - SIRKA_PLOSINY), (HERNI_VYSKA - VYSKA_PLOSINY - 540), HERNI_SIRKA, VYSKA_PLOSINY,4);
}
public void novyMario(){
mario= new Mario(1000, (HERNI_VYSKA - VYSKA_PLOSINY - MARIO_VELIKOST_XY), MARIO_VELIKOST_XY , MARIO_VELIKOST_XY );
}
public void novyZebrik(){
zebrik1 = new Zebrik(250, (HERNI_VYSKA-VYSKA_PLOSINY-VYSKA_ZEBRIKU),SIRKA_ZEBRIKU,VYSKA_ZEBRIKU);
zebrik2 = new Zebrik(800, (HERNI_VYSKA-VYSKA_PLOSINY-VYSKA_ZEBRIKU-180),SIRKA_ZEBRIKU,VYSKA_ZEBRIKU);
zebrik3 = new Zebrik(300, (HERNI_VYSKA-360-VYSKA_PLOSINY-VYSKA_ZEBRIKU),SIRKA_ZEBRIKU,VYSKA_ZEBRIKU);
}
public void paint(Graphics g) {
image = createImage(getWidth(),getHeight());
graphics = image.getGraphics();
nakresli(graphics);
g.drawImage(image,0,0,this);
}
public void nakresli(Graphics g) {
plosina0.nakresli(g);
plosina1.nakresli(g);
plosina2.nakresli(g);
plosina3.nakresli(g);
mario.nakresli(g);
zebrik1.nakresli(g);
zebrik2.nakresli(g);
zebrik3.nakresli(g);
Toolkit.getDefaultToolkit().sync();
}
public void move() {
mario.move();
}
public void zkontrolujKolizi() {
if(mario.x<=0)
mario.x=0;
if(mario.x >= (HERNI_SIRKA-MARIO_VELIKOST_XY))
mario.x = HERNI_SIRKA-MARIO_VELIKOST_XY;
if (mario.y >= (HERNI_VYSKA-VYSKA_PLOSINY - MARIO_VELIKOST_XY)) {
mario.y = (HERNI_VYSKA - VYSKA_PLOSINY - MARIO_VELIKOST_XY);
}
if(mario.intersects(plosina1)){
mario.y = (HERNI_VYSKA-VYSKA_PLOSINY-MARIO_VELIKOST_XY-180);
}
if(mario.intersects(plosina2)){
mario.y = (HERNI_VYSKA-VYSKA_PLOSINY-MARIO_VELIKOST_XY-360);
}
if(mario.intersects(plosina3)){
mario.y = (HERNI_VYSKA-VYSKA_PLOSINY-MARIO_VELIKOST_XY-540);
}
}
public void run() {
//game loop
long lastTime = System.nanoTime();
double amountOfTicks =60.0;
double ns = 1000000000 / amountOfTicks;
double delta = 0;
while(true) {
long now = System.nanoTime();
delta += (now -lastTime)/ns;
lastTime = now;
if(delta >=1) {
move();
zkontrolujKolizi();
repaint();
delta--;
}
}
}
public class AL extends KeyAdapter{
public void keyPressed(KeyEvent e) {
mario.keyPressed(e);
}
public void keyReleased(KeyEvent e) {
mario.keyReleased(e);
}
}
}
So here is the code after taking the tips into account.
The map is kept being repainted, the keylistener has changed but there still seems to be a problem.
The problem again is, the little square in the upper left corner will not move, which is the desired outcome.
package schoolgamev2;
import java.awt.BorderLayout;
import java.awt.Graphics;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Spel {
public static void main(String[] args) {
Speelveld map = new Speelveld();
map.Speelveld();
map.GenerateMap();
}
}
class Speelveld extends JPanel {
final int rijen = 16;
final int kolommen = 16;
Speler speler = new Speler();
Loopgebied loopgebied = new Loopgebied();
Blokken blok = new Blokken();
int[][] coordinaten = new int[rijen][kolommen];
public void Speelveld() {
JFrame frame = new JFrame();
frame.setSize(500, 500);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(this);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
setFocusable(true);
addKeyListener(new KeyListener(this));
}
//genereer map
public void GenerateMap() {
Random random = new Random();
int x;
int y;
for (y = 0; y < rijen; y++) { //scan langs y
for (x = 0; x < kolommen; x++) { //scan langs x
//selecteert type blok voor coordinaten x y
coordinaten[x][y] = random.nextInt(4);
//debugprint
}
//debugprint
}
coordinaten[0][0] = 4; //speler begint altijd links boven
coordinaten[15][15] = 5; //finish is altijd rechts onder
}
public int[][] getCoordinaten() {
return coordinaten;
}
public Speler getSpeler2() {
return speler;
}
public int getSpelerX() {
return speler.getX();
}
public int getSpelerY() {
return speler.getY();
}
public void setSpelerX(int x) {
speler.setX(x);
}
public void setSpelerY(int y) {
speler.setY(y);
}
//#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
int x;
int y;
for (y = 0; y < rijen; y++) { //scan langs y
System.out.println("");
for (x = 0; x < kolommen; x++) { //scan langs x
blok.setX(x);
blok.setY(y);
blok.setType(coordinaten[x][y]);
System.out.print(coordinaten[x][y] + " ");
switch (blok.getType()) {
case 0:
loopgebied.teken(g);
break;
case 4:
speler.teken(g);
/*case 5:
eindveld.teken(g);
break;*/
default:
break;
}
}
}
}
}
class Speler extends Blokken {
Blokken blok = new Blokken();
public void teken(Graphics g) {
g.drawRect(blok.getX(), blok.getY(), 10, 10);
}
}
class Loopgebied extends Blokken {
Blokken blok = new Blokken();
public void teken(Graphics g) {
g.drawRect(blok.getX() * size, blok.getY() * size, size, size);
}
}
class Blokken {
private static int x;
private static int y;
private static int type;
public int size = 16;
//setters voor x y en type
public void setX(int xIn) {
x = xIn;
}
public void setY(int yIn) {
y = yIn;
}
public void setType(int typeIn) {
type = typeIn;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
public int getType() {
return type;
}
}
class KeyListener extends KeyAdapter {
private static final int SCALE = 3;
private Speelveld speelveld;
public KeyListener(Speelveld speelveld) {
this.speelveld = speelveld;
}
#Override
public void keyPressed(KeyEvent e) {
int key = e.getKeyCode();
int deltaX = 0;
int deltaY = 0;
if (key == KeyEvent.VK_LEFT) {
deltaX = -1 * SCALE;
deltaY = 0;
} else if (key == KeyEvent.VK_UP) {
deltaX = 0;
deltaY = -1 * SCALE;
} else if (key == KeyEvent.VK_RIGHT) {
deltaX = 1 * SCALE;
deltaY = 0;
} else if (key == KeyEvent.VK_DOWN) {
deltaX = 0;
deltaY = 1 * SCALE;
} else {
return;
}
int x = speelveld.getSpelerX() + deltaX;
int y = speelveld.getSpelerY() + deltaY;
speelveld.setSpelerX(x);
speelveld.setSpelerY(y);
speelveld.repaint();
}
}
As mentioned in comments, you got your player, the Speler class, that extends JPanel and is wired to use a KeyListener, but note that it is not being used as a JPanel, and so the KeyListener is non-functioning, because they only work when they have been added to a visible component that has focus.
Suggestions:
Again as per comments, make Speler a non-GUI logical class. Meaning don't have it extend JPanel or any other Swing component, and certainly don't add a KeyListener to it.
Instead give it code for the player's behavior and for having the player draw itself, and that's it. What I'm suggesting is that you try to separate part of your "Model" here the player from the "View" here the Swing GUI.
Have one JPanel and only one that does drawing. Have it override paintComponent (don't forget to call the super's paintComponent within it), and have it draw each logical component by calling the logical component's draw method (public void verf(Graphics2D g2)? or public void teken(Graphics2D g2)?) within its paintComponent method.
As a general rule, you also don't want your GUI component classes, the JPanel here, directly implementing listener interfaces, such as the KeyListener, but will want to keep them separate.
Either make this drawing JPanel focusable, give it focus and add the KeyListener, a separate class, to it.
Or better, use Key Bindings as per the tutorial: Key Bindings
For example the simple [MCVE] below doesn't use a Swing Timer or change velocities, but rather it uses a KeyListener to change position of the Speler2 object using only one drawing JPanel and a KeyListener. If I were making this more robust and larger, I would use the Swing Timer, would use Key Bindings, and would change the velocities using the key bindings.
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.image.BufferedImage;
import javax.swing.*;
public class Spel2 {
private static final int VELD_WIDTH = 500;
private static void createAndShowGui() {
Speelveld2 speelveld2 = new Speelveld2(VELD_WIDTH, VELD_WIDTH);
JFrame frame = new JFrame("Spel2");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(speelveld2);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
speelveld2.requestFocusInWindow();
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGui());
}
}
class MyKeyListener extends KeyAdapter {
private static final int SCALE = 3;
private Speelveld2 speelveld2;
public MyKeyListener(Speelveld2 speelveld2) {
this.speelveld2 = speelveld2;
}
#Override
public void keyPressed(KeyEvent e) {
int key = e.getKeyCode();
int deltaX = 0;
int deltaY = 0;
if (key == KeyEvent.VK_LEFT) {
deltaX = -1 * SCALE;
deltaY = 0;
} else if (key == KeyEvent.VK_UP) {
deltaX = 0;
deltaY = -1 * SCALE;
} else if (key == KeyEvent.VK_RIGHT) {
deltaX = 1 * SCALE;
deltaY = 0;
} else if (key == KeyEvent.VK_DOWN) {
deltaX = 0;
deltaY = 1 * SCALE;
} else {
return;
}
int x = speelveld2.getSpelerX() + deltaX;
int y = speelveld2.getSpelerY() + deltaY;
speelveld2.setSpelerX(x);
speelveld2.setSpelerY(y);
speelveld2.repaint();
}
}
#SuppressWarnings("serial")
class Speelveld2 extends JPanel {
private int prefW;
private int prefH;
private Speler2 speler2 = new Speler2();
public Speelveld2(int prefW, int prefH) {
this.prefW = prefW;
this.prefH = prefH;
setFocusable(true);
addKeyListener(new MyKeyListener(this));
}
public Speler2 getSpeler2() {
return speler2;
}
public int getSpelerX() {
return speler2.getX();
}
public int getSpelerY() {
return speler2.getY();
}
public void setSpelerX(int x) {
speler2.setX(x);
}
public void setSpelerY(int y) {
speler2.setY(y);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
speler2.teken(g2);
}
#Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet()) {
return super.getPreferredSize();
}
return new Dimension(prefW, prefH);
}
}
class Speler2 extends Blokken2 {
private static final int RECT_W = 10;
public Speler2() {
super(BlokkenType.SPELER);
}
#Override
public void teken(Graphics2D g2) {
int x = getX();
int y = getY();
g2.drawRect(x, y, RECT_W, RECT_W);
}
}
class Blokken2 {
private int x;
private int y;
private int velx = 0;
private int vely = 0;
private BlokkenType type;
private BufferedImage img;
public Blokken2(BlokkenType type) {
this.type = type;
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
public int getVelx() {
return velx;
}
public void setVelx(int velx) {
this.velx = velx;
}
public int getVely() {
return vely;
}
public void setVely(int vely) {
this.vely = vely;
}
public BlokkenType getType() {
return type;
}
public void setType(BlokkenType type) {
this.type = type;
}
public void setImg(BufferedImage img) {
this.img = img;
}
public BufferedImage getImg() {
return img;
}
public void teken(Graphics2D g2) {
if (img != null) {
g2.drawImage(img, x, y, null);
}
}
}
enum BlokkenType {
LOOPGEBIED, BARRICADE, MUUR, SLEUTEN, SPELER, EINDVELD
}
Edit: your latest code has an error here:
class Speler extends Blokken {
Blokken blok = new Blokken();
public void teken(Graphics g) {
g.drawRect(blok.getX(), blok.getY(), 10, 10);
}
}
Regarding your edit:
Now when you create a Speler instance, you create TWO Blokken instances, one which is the Speler instance since it extends Blokken and the other which is contained by the Speler instance since it also has a Blokken field.
You update the x/y state of the first one, but you draw with the second one, and that's why no motion is being displayed. The solution is obvious: use one or the other but not both. Either have Speler extend Blokken or have it contain a Blokken instance but don't do both.
I have made a game in Eclipse neon with the language Java, but I was wondering how I can make the game so that if the user presses r he or she could go back to the first screen where it says press spacebar to start. here are my 3 files of code if you need it to figure out the solution.
//This is the game file (main)
import processing.core.PApplet;
public class Game extends PApplet{
public static void main(String[] args) {
// TODO Auto-generated method stub
PApplet.main("Game");
}
James james1;
Wall wall1;
Wall wall2;
Wall wall3;
public void settings() {
size(500, 700);
}
public void setup() {
frameRate(40);
james1 = new James(this, 250, 650, 50);
wall1 = new Wall(this, 0);
wall2 = new Wall(this, 250);
wall3 = new Wall(this, -250);
}
public void draw() {
if(key == ' ') {
clear();
background(0, 255, 255);
boolean loser = wall1.col(james1.getX(), james1.getY()) || wall2.col(james1.getX(), james1.getY()) ||wall3.col(james1.getX(), james1.getY());
james1.show();
move();
if (!loser){
wall1.update();
wall2.update();
wall3.update();
}
else {
reset();
}
wall1.display();
wall2.display();
wall3.display();
}
else {
background(255, 0, 255);
textSize(45);
text("Press Space to Start!", 50, 350);
}
}
public void reset() {
clear();
frameRate(0);
textSize(40);
text("You Lose, R to restart", 25, 550);
}
public void restart() {
}
public void move() {
james1.setX(mouseX);
if (mouseX <= 25) {
james1.setX(25);
}
else if (mouseX >= 475) {
james1.setX(475);
}
}
}
//This is the character file (James)
import processing.core.PApplet;
public class James {
PApplet p;
private float x;
private float y;
private float size;
public James(PApplet np, float nx, float ny, float nsize) {
p = np;
x = nx;
y = ny;
size = nsize;
}
public void show() {
p.fill(255,20,147);
p.ellipse(x, y, size, size);
p.fill(128,128,0);
p.ellipse(x - 10, y - 10, size - 30, size - 30);
p.ellipse(x + 10, y - 10, size -30, size - 30);
}
public float getX() {
return x;
}
public float getY() {
return y;
}
public float getSize() {
return size;
}
public void setX(float gx) {
x = gx;
}
public void setY(float gy) {
y = gy;
}
public void setSize(float gSize) {
size = gSize;
}
}
//This is obstacle class file (walls)
import processing.core.PApplet;
public class Wall {
PApplet p;
private float x;
private float y;
private float w;
private float xw;
private float yw;
private float h;
private float wh;
private float xspeed;
private float yspeed;
public Wall (PApplet np, float ny) {
p = np;
x = 0;
y = ny;
wh = 0;
xw = p.random(0, 450);
yw = p.random(0, 450);
w = p.random(0, 450);
h = 30;
yspeed = 10;
}
public void display() {
p.rect(0, y, w, h);
p.rect(w + 100, y, 500-(w+100), h);
}
public void update() {
if(y > p.height) {
y = 0;
w = p.random(0,450);
xw = p.random(0, 450);
yw = p.random(0, 450);
}
y = yspeed + y;
}
public float getX() {
return x;
}
public float getY() {
return y;
}
public float getW() {
return w;
}
public float getXW() {
return xw;
}
public float getYW() {
return yw;
}
public float getWH() {
return wh;
}
public float getH() {
return h;
}
public float getxSpeed() {
return xspeed;
}
public float getySpeed() {
return yspeed;
}
public void setX(float gx) {
x = gx;
}
public void setYW(float gyw) {
yw = gyw;
}
public void setW(float gw) {
w = gw;
}
public void setY(float gy) {
y = gy;
}
public void setH(float gh) {
h = gh;
}
public void setxSpeed(float gxSpeed) {
xspeed = gxSpeed;
}
public void setySpeed(float gySpeed) {
yspeed = gySpeed;
}
public boolean col(float ballX, float ballY) {
if (y + h >= ballY - 25 && y <= ballY + 25 ) {
if(ballX - 25 <= w || ballX+25 >= w+100) {
return true;
}
}
return false;
}
}
Hope that wasn't too long for just one goal ;)
Copy everything from method setup to method restart and then call restart from method setup.
You get something like this:
public void setup()
{
restart();
}
public void restart()
{
frameRate(40);
james1 = new James(this, 250, 650, 50);
wall1 = new Wall(this, 0);
wall2 = new Wall(this, 250);
wall3 = new Wall(this, -250);
}
Now just call restart whenever you want the game to restart. In your example: when the user presses the 'r' button.
In games, it really is a good idea to have a Map class that handles these kind of things.
You can just basically copy setup and paste it with a new method name, or even use that same method to make it so when pressed "r", it just calls that method back again. But just for it to be cleaner and much more readable. you can do this.
public void setup() {
if(key.r) { //of course this key.r will have to be created as a KeyListener.
restart();
}
}
public void restart() {
frameRate(40);
james1 = new James(this, 250, 650, 50);
wall1 = new Wall(this, 0);
wall2 = new Wall(this, 250);
wall3 = new Wall(this, -250);
}
You can either create a new class for the KeyInput or do it in the same class, but it should be a little like this:
public boolean[] keys = new boolean[120];
public boolean r;
public void keyPressed(KeyEvent e) {
int key = e.getKeyCode();
f3 = (key == KeyEvent.VK_F3);
}
public void keyReleased(KeyEvent e) {
keys[e.getKeyCode()] = false;
}
public void keyTyped(KeyEvent e) {
keys[e.getKeyCode()] = false;
}
}
Have a nice day!
:D
I am having trouble using setter methods from the main class with a JFrame "position". The active parts of the JFrame(triangles called "turtles" moving about) are leaving the JFrame and my current method of changing the coordinates when this happens is not working. Any help would be greatly appreciated, as I have been stuck for days.
The method wrapPosition is designed to change the coordinate if they're off the "screen" which is (800x600)pixels. This check is in the loop so a turtle never goes off the screen.
here is the Main Class:
import javax.swing.*;
import java.awt.*;
import java.util.ArrayList;
class Lab7b
{
public static void main(String [ ] args)
{
int deltaTime = 50;
JFrame frame = new JFrame();
Canvas canvas = new Canvas();
frame.setTitle("Welcome to turtle land!");
frame.setSize(800, 600);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
frame.add(canvas);
ArrayList<DynamicTurtle> turtles = new ArrayList<DynamicTurtle>(); //An ArrayList containing Turtle elemenets
turtles.add(new RandomTurtleA(turtleCanvas, 400, 300));
turtles.add(new RandomTurtleA(turtleCanvas, 400, 300));
turtles.add(new RandomTurtleA(turtleCanvas, 400, 300));
while(true)
{
for (int i = 0; i < turtles.size(); i++)
{
(turtles.get(i)).unDrawTurtle();
hello.setText("X: " + (turtles.get(i)).getPositionX() + " Y: " + (turtles.get(i)).getPositionY()); //print to JFRAME
System.out.println("X: " + (turtles.get(i)).getPositionX() + " Y: " + (turtles.get(i)).getPositionY()); //print to CMD
(turtles.get(i)).wrapPosition((turtles.get(i)).getPositionX(), (turtles.get(i)).getPositionY()); //this is the wrapPosition method that does not work
}
for (int i = 0; i < turtles.size(); i++)
{
(turtles.get(i)).update(1000);
}
for (int i = 0; i < turtles.size(); i++)
{
(turtles.get(i)).drawTurtle();
}
Utils.pause(deltaTime/2);
}
}
}
the Turtle class with the troublesome wrapPosition method:
class Turtle
{
protected Canvas canvas; // private field reference to a canvas private
private CartesianCoordinate myLocation, oldLocation;
private boolean penDown = true;
private double Angle, maxX, maxY, x, y;
public double d, e, first, second;
public Turtle(Canvas canvas, CartesianCoordinate initLocation)
{
this.canvas = canvas;
this.myLocation = new CartesianCoordinate(0,0);
Angle = 0;
penDown = true;
myLocation = initLocation.copy();
}
public void wrapPosition(double x, double y)
{
this.x = maxX;
this.y = maxY;
if(maxX < 0)
{
this.setPositionX(800);
}
if(maxX > 800)
{
this.setPositionX(0);
}
if(maxY < 0)
{
this.setPositionY(600);
}
if(maxY > 600)
{
this.setPositionY(0);
}
}
public double getPositionX()
{
double getPosX;
getPosX = myLocation.getX();
return getPosX;
}
public double getPositionY()
{
double getPosY;
getPosY = myLocation.getY();
return getPosY;
}
public void setPositionX(double x)
{
myLocation.setX(x);
}
public void setPositionY( double y)
{
myLocation.setY(y);
}
}
Also, if it is any help the coordinate class:
class CartesianCoordinate
{
private double xPosition, yPosition, setterX, setterY;
public CartesianCoordinate(double x, double y)
{
this.xPosition = x;
this.yPosition = y;
}
public double getX()
{
return this.xPosition;
}
public double getY()
{
return this.yPosition;
}
public void setX(double setterX)
{
this.setterX = xPosition;
}
public void setY(double setterY)
{
this.setterY = yPosition;
}
}
Any Help would be greatly appreciated. Thank you in advance.
The "setters" in class CartesianCoordinate do virtually nothing because they just assign to member variables which are not read.
public void setX(double setterX)
{
this.setterX = xPosition;
}
public void setY(double setterY)
{
this.setterY = yPosition;
}
Try these instead to have coordinates to be read be updated:
public void setX(double setterX)
{
this.xPosition= setterX;
}
public void setY(double setterY)
{
this.yPosition= setterY;
}
I am having a problem getting my application to draw a Ball when i click on the frame.
I thought my code was correct, and I don't get any errors, but it still doesn't work.
I feel the problem is with the MouseListener implementation and that the application is not handling the MouseEvent properly.
import java.awt.*;
import java.awt.geom.*;
import javax.swing.*;
import java.awt.event.*;
import java.util.*;
public class BouncingBallApp extends JFrame
{
public static void main(String[] args)
{
Container container;
BouncingBallApp bouncingBalls = new BouncingBallApp();
bouncingBalls.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
container = new Container();
BouncingBallPanel BBP = new BouncingBallPanel();
container.add(BBP);
bouncingBalls.addMouseListener(BBP);
//addMouseListener;
bouncingBalls.setBackground( Color.WHITE );
bouncingBalls.setSize(400,300);
bouncingBalls.setVisible( true );
}//end of main method
}//end of BouncingBallApp
class BouncingBallPanel extends JPanel implements MouseListener, Runnable
{
private Ball[] ballArray = new Ball[20];
private int ballCount = 0;
public void run()
{
for(int i = 0; i<ballArray.length; i++){
if(ballArray[i] != null){
ballArray[i].move();}}
repaint();
//delay(1);
}
public void mouseClicked(MouseEvent e)
{
ballArray[ballCount] = new Ball();
ballCount++;
if(ballCount == 1)
(new Thread(new BouncingBallPanel())).start();
}
//empty interface methods
public void mouseExited(MouseEvent e){}
public void mouseReleased(MouseEvent e){}
public void mouseEntered(MouseEvent e){}
public void mousePressed(MouseEvent e){}
public void paintComponent(Graphics g)
{
super.paintComponent( g );
Graphics2D g2d = (Graphics2D) g;
for(int i = 0; i<ballArray.length; i++)
{
if(ballArray[i] != null){
g2d.setColor(ballArray[i].getColor());
g2d.fill(new Ellipse2D.Double(ballArray[i].getX(),ballArray[i].getY(),ballArray
[i].getDiameter(),ballArray[i].getDiameter()));}
}//end of for loop
}
}//end of BouncingBallPanel
class Ball
{
private double x;
private double y;
private double deltaX;
private double deltaY;
private double diameter;
private Color color;
Random random = new Random();
public Ball()
{
x = random.nextInt(400);
y = random.nextInt(300);
deltaX = 2;
deltaY = 2;
diameter = 10;
color = new Color(random.nextInt(256),random.nextInt(256),random.nextInt(256));
}//end of constructor
public double getX(){
return x;}
public double getY(){
return y;}
public double getDiameter(){
return diameter;}
public Color getColor(){
return color;}
public void move()
{
x += deltaX;
y += deltaY;
if (x < 0) {
x = 0;
deltaX = -deltaX;}
else if (x > 400) {
x = 400;
deltaX = -deltaX;}
if (y < 0) {
y = 0;
deltaY = -deltaY;}
else if (y > 300) {
y = 300;
deltaY = -deltaY;}
}//end of method move
}//end of ball
3 Things
No size for container
You are not adding container
No loop to update graphics
The code below is working
import java.awt.*;
import java.awt.geom.*;
import javax.swing.*;
import java.awt.event.*;
import java.util.*;
public class BouncingBallApp extends JFrame {
public static void main(String[] args) {
// Container container;
BouncingBallApp bouncingBalls = new BouncingBallApp();
bouncingBalls.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// container = new Container();
BouncingBallPanel BBP = new BouncingBallPanel();
// container.add(BBP);
bouncingBalls.addMouseListener(BBP);
// addMouseListener;
bouncingBalls.setBackground(Color.WHITE);
bouncingBalls.setSize(400, 300);
BBP.setSize(400, 300);
BBP.setLayout(null);
bouncingBalls.setContentPane(BBP);
/*
* JTextField jtf = new JTextField(); BBP.add(jtf); jtf.setSize(100,
* 20);
*/
bouncingBalls.setVisible(true);
}// end of main method
}// end of BouncingBallApp
class BouncingBallPanel extends JPanel implements MouseListener {
private Ball[] ballArray = new Ball[20];
private int ballCount = 0;
public void mouseClicked(MouseEvent e) {
ballArray[ballCount] = new Ball();
ballCount++;
if (ballCount == 1) {
final Runnable updateGraphics = new Runnable() {
public void run() {
for (int i = 0; i < ballArray.length; i++) {
if (ballArray[i] != null) {
ballArray[i].move();
}
}
repaint();
}
};
Runnable animation = new Runnable() {
public void run() {
while (true) {
try {
EventQueue.invokeLater(updateGraphics);
Thread.sleep(100);
} catch (InterruptedException e) {
return;
}
}
}
};
new Thread(animation).start();
}
}
// empty interface methods
public void mouseExited(MouseEvent e) {
}
public void mouseReleased(MouseEvent e) {
}
public void mouseEntered(MouseEvent e) {
}
public void mousePressed(MouseEvent e) {
}
public void paintComponent(Graphics g) {
// super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
for (int i = 0; i < ballArray.length; i++) { if (ballArray[i] !=
null) { System.out.println(" ball " + i + " , " +
ballArray[i].getColor() + " , " + ballArray[i].getX() + " , " +
ballArray[i].getY() + " , " + ballArray[i].getDiameter());
g2d.setColor(ballArray[i].getColor());
g2d.fillRect((int)ballArray[i].getX(), (int)ballArray[i].getY(),
(int)ballArray[i].getDiameter(), (int)ballArray[i].getDiameter()); }
}// end of for loop
}
}// end of BouncingBallPanel
class Ball {
private double x;
private double y;
private double deltaX;
private double deltaY;
private double diameter;
private Color color;
Random random = new Random();
public Ball() {
x = random.nextInt(400);
y = random.nextInt(300);
deltaX = 2;
deltaY = 2;
diameter = 10;
color = new Color(random.nextInt(256), random.nextInt(256), random.nextInt(256));
}// end of constructor
public double getX() {
return x;
}
public double getY() {
return y;
}
public double getDiameter() {
return diameter;
}
public Color getColor() {
return color;
}
public void move() {
x += deltaX;
y += deltaY;
if (x < 0) {
x = 0;
deltaX = -deltaX;
}
else if (x > 400) {
x = 400;
deltaX = -deltaX;
}
if (y < 0) {
y = 0;
deltaY = -deltaY;
}
else if (y > 300) {
y = 300;
deltaY = -deltaY;
}
}// end of method move
}// end of ball