I am completely new to java and I have one problem I am trying to resolve. I am using ACM Library for my purpose. My goal is the following:
Move Label 1
Move Label 2
Compare label 1's and label 2's position (when the text hits and its on each other) "Using 'if' statement"
Once on top, stop it by using break statement.
Restart the cycle.
If someone could help me out by explaining how this can be implemented. That would be awesome. I am trying to learn. Thank you!
import acm.graphics.GLabel;
import acm.program.CommandLineProgram;
import acm.program.GraphicsProgram;
public class Main extends GraphicsProgram {
public void run( )
{
int label1_xy = 50;
int label2_xy = 200;
GLabel label1 = new GLabel("Hello World.");
add(label1, label1_xy,label1_xy);
GLabel label2 = new GLabel("Goodbye World.");
add(label2, label2_xy,label2_xy);
while (true)
{
label1.move(10,10);
pause(500);
label2.move(-10,-10);
break;
}
}
}
Move Label 1
Move Label 2
You have done these two.
Compare label 1's and label 2's position (when the text hits and its on each other) "Using 'if' statement"
Once on top, stop it by using break statement.
You can compare the position of those two labels by trying to retrieve the "bound" of the object. example :
label1.move(10,10);
pause(500);
if (label1.getBounds().getX() == label2.getBounds().getX()
&& label1.getBounds().getY() == label2.getBounds().getY()) {
break;
} else {
label2.move(-10,-10);
}
Restart the cycle
You can restart this by putting another while block for the run() code or maybe just call the run() (beware of the StackOverflowError here).
Related
I'm working on a game in java, based on the Atari game adventure. I got the basic KeyListener part working fine, but then I added another if statement, using another class, to test if if the player was going to hit a wall, and stopping movement if that was the case. The method I used also used if statements, and when I ran the code, it had MAJOR lag. I tried a while loop first, but that made it lag even worse. Anyway to make this not lag so much? It doesn't seem that complex a program to run, and I still have to add yet another if statement to make be able to move into another room, so I have to do something to massively cut down on the lag.
Here is the class:
class Player extends JPanel implements KeyListener{
private char c = 'e';
int x = 400;
int y = 400;
int mapX = 0;
int mapY = 0;
public Player() {
this.setPreferredSize(new Dimension(800, 500));
addKeyListener(this);
}
public void addNotify() {
super.addNotify();
requestFocus();
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
Environment Layout = new Environment();
Layout.drawRoom(mapX,mapY,g);
g.fillRect(x , y , 20, 20);
}
public void keyPressed(KeyEvent e) { }
public void keyReleased(KeyEvent e) { }
public void keyTyped(KeyEvent e) {
c = e.getKeyChar();
repaint();
Environment Layout = new Environment();
if(Layout.isWall(x,y,c)){}
else{
if (c == 'a'){
x = x - 3;
}
else if (c == 'w'){
y = y - 3;
}
else if (c == 's'){
y = y + 3;
}
else if (c == 'd'){
x = x + 3;
}
}
}
public static void main(String[] s) throws IOException{
JFrame f = new JFrame();
f.getContentPane().add(new Player());
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.pack();
f.setVisible(true);
}
}
The draw room method I used in this was just to put the background of the room into place.
Here is the isWall method from the Environment class:
public boolean isWall(int moveX, int moveY, char let){
BufferedImage room = null;
try {
room = ImageIO.read(new File(xNum + "," + yNum + ".png"));
}
catch (IOException e) {
}
int[][] walls = convertImage(room);
boolean blocked = false;
if(let == 'w') {
if(walls[moveY-8][moveX] == -3584){blocked = true;}
}
else if(let == 's') {
if(walls[moveY+20][moveX] == -3584){blocked = true;}
}
else if(let == 'a') {
if(walls[moveY][moveX-5] == -3584){blocked = true;}
}
else if(let == 'd') {
if(walls[moveY][moveX+20] == -3584){blocked = true;}
}
return blocked;
}
the convertImage method just converts the image of the room into an int array, for the value of the colors. -3584 is the color of the walls. It's possible this is what's lagging it, but this seemed like the best way for each room to have the walls done automatically.
I also tried a timer, but either I did that wrong, or it just didn't help.
I can give more of my code if that's needed, but help with this would be much appreciated. I'm relatively new to this kind of stuff, so it's likely I'm missing something big. Thanks.
The lag here is almost certainly not from the if statements. Those are really fast. I think the bigger issue is in isWall. Notice that any time you want to check for whether a wall is present, you
Open a file,
read the file contents,
convert the file contents from an image to a grid of pixels, and
read exactly one pixel.
Reading files from disk is extremely slow compared to looking at values in memory. For example, a regular magnetic hard drive works at around 7200 RPM, so the seek time is measured in milliseconds. On the other hand, your processor can do about a billion operations per second, so other operations take nanoseconds. That means that a disk read is roughly a million times slower than other operations, which is almost certainly where you're getting the lag from!
To fix this, consider rewriting your isWall code so that you only read the file and do the conversion once and, having done that, then just look up the part of the image you need. This converts doing tons of (glacially slow) file reads to one single (slow but inevitable) file read followed by tons of fast memory reads.
You appear to be moving your walls further than you are moving your player.
Is it possible that your player object is getting stuck in a wall there by producing "blocked = true" continuously?
Your character gets +- 3 in every direction, however your walls seem inconsistent and range from 8 up to 20 down to 5 left to 20 right.
This is an extension to #templatetypedef's answer.
Instead of loading the image files upon calling the isWall method, you might want to consider caching all of the walls on game start.
So I am thinking;
have a HashMap data structure keyed by <String, Integer>. Where String is your coordinates. E.g. coordinate string = "100,238"
parse all the .png image files in the directories and store the coordinates as key and the value can just be any dummy value like 1 or 2.
Then when isWall() is invoked. Given the X and Y coordinate, build the coordinate string as mentioned in point 1 and check if the key exists. If it does then we know it is a piece of wall else not.
This should drastically reduce the I/O disk contention.
In future, if you would like to extend the solution to incorporate APIs like isTreasureChest() or isMonster(). It can be extended by building a immutable class call "Room" or "Tile" to represent the object. Then modify the HashMap to take in <String, Room>.
I'm making a guess the number program and I'm having trouble with my loop. When I run the program and input a number into the textfield and hit enter it freezes. I figured out that this might be happening because of an infinite loop. Feel free to correct me if I'm wrong. Basically when I enter a number into the textfield and press enter it suppose to change a label and change background color but this doesn't happen and I think its because my loop runs until win becomes true and when I type in my number it keeps running that number instead of outputting the correct label and letting me input a different number into the textfield. P.S: I know the newGame button does not work yet
import java.util.*;
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
public class GuessingGame implements ActionListener
{
JFrame guessFrame;
JPanel guessPanel;
JTextField guessText;
JButton newGame;
JLabel rangeLbl, enterGuessLbl, winLbl;
Random rand = new Random();
int numToGuess = rand.nextInt(1000)+1;
int numOfTries = 0;
int guess;
public GuessingGame()
{
// Create the frame and container.
guessFrame = new JFrame("Guess the Number");
guessPanel = new JPanel();
guessPanel.setLayout(new GridLayout(5,0));
// Add the widgets.
addWidgets();
// Add the panel to the frame.
guessFrame.getContentPane().add(guessPanel, BorderLayout.CENTER);
// Exit when the window is closed.
guessFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// Show the converter.
guessFrame.pack();
guessFrame.setVisible(true);
}
// Create and add the widgets for converter.
private void addWidgets()
{
// Create widgets.
guessText = new JTextField();
guessText.setHorizontalAlignment(JTextField.CENTER);
rangeLbl = new JLabel("I have a number between 1 and 1000. Can you guess my number?", SwingConstants.LEFT);
enterGuessLbl = new JLabel("Please enter your guess", SwingConstants.LEFT);
winLbl = new JLabel(" ", SwingConstants.CENTER);
newGame = new JButton("New Game");
// Listen to events from Convert textfield.
guessText.addActionListener(this);
// Add widgets to container.
guessPanel.add(rangeLbl);
guessPanel.add(enterGuessLbl);
guessPanel.add(guessText);
guessPanel.add(winLbl);
guessPanel.add(newGame);
}
// Implementation of ActionListener interface.
public void actionPerformed(ActionEvent event)
{
boolean win = false;
guess = Integer.parseInt(guessText.getText());
if ( guess == numToGuess)
{
win = true;
}
else if ( guess < numToGuess)
{
winLbl.setText("Too Low");
guessPanel.setBackground(Color.red);
guess = Integer.parseInt(guessText.getText());
}
else if ( guess > numToGuess)
{
winLbl.setText("Too High");
guessPanel.setBackground(Color.blue);
guess = Integer.parseInt(guessText.getText());
}
winLbl.setText("Correct!");
guessPanel.setBackground(Color.green);
}
public static void main(String[] args)
{
GuessingGame game = new GuessingGame();
}
}
Your while-loop is inappropriate here, because you are in a actionPerformed() Method. This method is most likely to be called on a gui action (e.g. button kicked).
It should do one action corresponding to your needs and then terminate, since this method is invoked within the EDT. Your gui will not perform any updates until this method is finished.
Thus nothing will change (e.g. your win status) until the user makes some additional action, which he can't because your gui is frozen.
You don't update the value of guess. You'll need to read guess at the end of your loop, or at least in those cases that guess and numToGuess don't have the same value.
In the current case: if the values are not equal the first iteration, it will never become.
add
guess = Integer.parseInt(guessText.getText());
as last statement to each else if block
EDIT: a better way, as Marcinek points out, would be to remove the while loop, but since I don't know your requirements, I won't go as far as to claim it's the correct sollution.
Your loop keep runing because this condition if ( guess == numToGuess) never verfied
boolean win = false;
while (win == false){
if ( guess == numToGuess){
win = true;
}
.......
}
and
win still false, and while loop go a head runing.
while (win == false)
{
.....}
I am wondering how can you keep this iteration in memory.
I forgot to say that player one can choose any of the five button
I was just using button 1 as a example for player 1.
this is where my problem is cause I can't figure out a way to keep this chosen button which can be any to stay disable(false) after player 2 as chosen is button.
It works if I don't disable all button after player 1 chose is, but the other 4 are enable and if player 1 press one of those button when its player 2 turns everything is mess up.
that's what I'm trying to fix. Help please.
I have 5 button for player 1 and 5 button for player 2.
Let's say button 1 is press for player 1, after its press all the other button is deactivated for player 1 and the others are activated for player 2
When player 2 press it chooses is button, all other of his is deactivated
Here is the tricky part, after player 2 press his button, player 1 button reactivate minus button 1 which was already chosen. This means only 2,3,4 and 5 are activated.
and so on. This must alternate until all 5 button was chosen.
I just can't seem to find, its the tricky part that I can't figure out.
Can anyone help me solve this or any suggestion.
Thanks.
here is the code
//The 2 first for loop are for just showing the 10 buttons
for(int i=0;i<5;i++)
{
x=100*i;
jbChoixJun[i]=new JButton(String.valueOf("Choisir"));
jbChoixJun[i].setBounds(x+30,160,80,30);
add(jbChoixJun[i]);
jbChoixJun[i].addActionListener(this);
jbChoixJun[i].setEnabled(false);
}
for(int i=0;i<5;i++)
{
x=100*i;
jbChoixJdeux[i]=new JButton(String.valueOf("Choisir"));
jbChoixJdeux[i].setBounds(x+30,390,80,30);
add(jbChoixJdeux[i]);
jbChoixJdeux[i].addActionListener(this);
jbChoixJdeux[i].setEnabled(false);
}
//The next 2 for loop, when the player its the button it becomes false and
// stay false until the end, this works ok
for(i=0;i<5;i++)
{
if(source==jbChoixJun[i])
{
mainJoueur1.getCarte(compteurI1);
jbChoixJun[i].setEnabled(false);
compteur1=1;
compteurI1=i;
comparaison1=true;
System.out.println("compteur des images");
System.out.println("compteurI1="+compteurI1);
comparaisonBataille1=true;
}
//This turn all button off after the player chose is
if(jbChoixJun[compteurI1].isEnabled()==false)
jbChoixJun[i].setEnabled(false);
}
for(int i=0;i<5;i++)
{
if(source==jbChoixJdeux[i])
{
mainJoueur2.getCarte(compteurI2);
jbChoixJdeux[i].setEnabled(false);
compteur2=1;
compteurI2=i;
comparaison2=true;
comparaisonBataille2=true;
jbChoixJun[compteurI1].setEnabled(false);
}
if(jbChoixJdeux[compteurI1].isEnabled()==false)
jbChoixJdeux[i].setEnabled(false);
if(i==compteurI1)
continue;
else
jbChoixJun[i].setEnabled(true);
The problem, is that the first button chosen by player comes active and only the second one that becomes disable.
Can of hard to explain
Hope you guys can help me
As asked by the OP here is how you can extend JButton and use it according to your needs by adding new properties, this gives you more flexibility
public class ExtendedJButton extends JButton{
private static final long serialVersionUID = 1L;
/**
* We use this boolean for some case and set it to true or false according to out need
*/
private boolean someCheck;
//Add more propterties according to your need and create conditions to enable and disable them accordingly
public boolean isSomeCheck() {
return someCheck;
}
public void setSomeCheck(boolean someCheck) {
this.someCheck = someCheck;
}
public static void main(String[] args) {
JFrame frameForExample = new JFrame();
ExtendedJButton button = new ExtendedJButton();
frameForExample.add(button);
//Now you can access properties of JButton class as well as new properties of your extended class
button.setEnabled(false);
////.........
//An example case
if(button.isSomeCheck()){
//Do what you want to
//if you want to disable the button when this case is true do it,
}
}
This is not an answer but more a guidance on how you can proceed.
Not to sure about why this code is not working as intended and hoping you could help me figure it out. I am working on a tictactoe game from a series of tutorials that use jbuttons. What i have is a method in my main class that "checksforwin" each time a button is clicked. Using print statements i found that my method does run each time a button is clicked however the getText().equals("_") conditions do not operate properly.
This code is part of my tictactoe.java and all works properly. this event is copied 9 times for each button.
public void button1ActionPerformed(ActionEvent e) {
if(button1.getText().equals("")){
if(Main.playerTurn==true){
button1.setText("X");
Main.checkforwin();
Main.playerTurn = false;
}else{
button1.setText("O");
Main.checkforwin();
Main.playerTurn = true;
}
}
}
This code is part of my main.java which houses the checkforwin method. The check for win chunk of code is repeated multiple times for each possible win in tictactoe for both the player 1 and computer(player2).
public class Main {
public static boolean playerTurn = true;
public static boolean playerWon = false;
public static boolean computerWon = false;
public static tictactoe board = new tictactoe();
public static void checkforwin(){
System.out.println("testing1");
//horizontal row 1
if(board.button1.getText().equals("X")){
System.out.println("testing2");
if(board.button2.getText().equals("X")){
if(board.button3.getText().equals("X")){
playerWon = true;
computerWon = false;
System.out.println("Player 1 won");
}
}
}
}
The method will output testing1 every time a button is clicked, however it will never print inside the conditions.
Any help or advice would be greatly appreciated thanks!
My guess is its not picking up the button text change - after the button text change (button1.setText("X");) etc - you need to add it to the panel again, so panel.add(button1); or whatever they're stored on
I was taking a quick look at your coding and not entirely sure, but "maybe" you should try using AND operator in your conditional IF statement? For example:
if(board.button1.getText().equals("X") && board.button2.getText().equals("X") && board.button3.getText().equals("X")){
playerWon = true;
computerWon = false;
System.out.println("Player 1 won");
}
You could use these types of conditional statements to say either player/computer has won, providing the horizontal or vertical buttons equal X or O.
There is probably a more efficient way though to do it though, but this is the first thought that occurred to me so you could try it out!
I hope it helps!
I'm having trouble with a contentPane. Here's the code in question:
public void graph() {
JFrame frame = new JFrame("Graph");
Graph[] graphs = new Graph[timeSlices];
int k = 0;
for (TreeMap<MyPoint, BigDecimal> prevU : prevUs) {
graphs[k] = new Graph(prevU);
k++;
}
// The KeyList handles switching between graphs.
frame.addKeyListener(new KeyList(frame.getContentPane(), graphs));
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(810, 500);
frame.setVisible(true);
}
private class KeyList extends KeyAdapter {
private Container contentPane;
private Graph[] graphs;
private int index;
public KeyList(Container contentPane, Graph[] graphs) {
this.contentPane = contentPane;
this.graphs = graphs;
this.index = 0;
this.contentPane.add(this.graphs[0]);
}
public void keyPressed(KeyEvent e) {
// Go back a time step
if (e.getKeyCode() == KeyEvent.VK_LEFT && index > 0) {
contentPane.remove(graphs[index]);
contentPane.add(graphs[--index]);
contentPane.validate();
System.out.println(index);
}
// Go forward a time step
else if (e.getKeyCode() == KeyEvent.VK_RIGHT && index < timeSlices - 1) {
contentPane.remove(graphs[index]);
contentPane.add(graphs[++index]);
contentPane.validate();
System.out.println(index);
}
// Exit if Esc is hit
else if (e.getKeyCode() == KeyEvent.VK_ESCAPE)
System.exit(0);
}
}
Graph is just a Component, easy peasy. When I hit the right arrow, I want to replace the currently displayed Graph with the next one in the array, and when I hit the left arrow, I want to replace the Graph with the previous one in the array.
The weird thing is that when I hit right, it works just fine. However, when I hit left, the Graph doesn't change. The index changes, thus I know the code is being reached, but the GUI doesn't change.
Now get ready for this. When I comment out the right key's validate line, the left one will work about half the time. What is going on there? Here's the rest of the code if you want to run and see for your self (just one file) : http://pastebin.com/qWxWrypK. The starting paramemters I'm currently using are T=1, dt=.01, L=1, h=.05.
I was looking into it, I thought it might be because the contentPane of a JFrame is really a JPanel, but that line of thinking didn't get anywhere...
Thanks for any help
Edit:
So I'm still working with it. Here's another weird thing. If I set the index in the KeyList class to timeSlices-1 (basically getting the last Graph in graphs array), and I hit left, it works! But, now the right doesn't! Something weird has to be going on with the array or something because the index changes just fine. Hmm.
Edit:
Something's going on with the array. For some reason, the Graph can only be used once. Perhaps it's being destroyed on removal? Or something like that...
Instead of trying to remove/add panels to a container use a CardLayout which was designed for this purpose.
Also, don't use KeyListeners. Instead you should be using Key Bindings. Then you simply bind the next/previous keys to the next/previous methods of the card layout.