So for a school project, I have to create a game with a program called 'Processing'.
I am creating a main menu with the switch statement. For that I want to use the buttons 'Start', 'Help', and 'exit'.i would like to use those buttons to change the variables of the switch statement. Therefore I'm using "mousePressed". The problem is that which button I'm pressing, is giving me the same result as the 'exit' button. Could somebody give me tips on how I can structure my menu better or even make my button work? I am using a library on Processing called 'ControlP5' to make my buttons.
here is my code so far:
int mode; // 1: intro screen, 2: game , 3: game over
final int INTRO = 1;
final int PLAY = 2;
final int GAMEOVER = 3;
//==============================================================
void setup(){
size(1920,1080);
mode = 1;
}
//========================================================
void draw(){
if(mode == 1){
introScreen();
}
else if (mode == 2){
gameItself();
}
else if (mode == 3){
gameOver();
}
else println("mode error");{
}
}
void introScreen(){
mode = 1;
static int Page = 0;
import controlP5.*;
ControlP5 cp5;
cp5= new ControlP5(this);
switch(Page){
case 0: // main menu
cp5.addButton("Start").setValue(0).setPosition(1420,250).setSize(400,100);
cp5.addButton("Exit").setValue(0).setPosition(1420,650).setSize(400,100);
cp5.addButton("Help").setValue(0).setPosition(1420,450).setSize(400,100);
break;
case 1: //help menu
cp5.addButton("Back").setValue(0).setPosition(1420,450).setSize(400,100);
break;
}
public void Start(){
if(mousePressed){
mode = 2; // switching to the game itself
}
println("Start");
}
public void Exit(){
if(mousePressed){
exit(); }
println("Exit");
}
public void Help(){
Page = 1;
println("Help");
}
public void Back(){
if(mousePressed){
Page = 0;
}
println("Back");
}
void gameItself(){
// game and stuff
}
void gameOver(){
//gameover
}
Take a look at how the mousePressed event works. You may use this information useful.
To achieve your goal as to change the Page variable by clicking buttons, there are multiple options. First, I'll go with the easier one, the one which doesn't need an import but just check for coordinates. Then I'll do the same thing, but with controlP5.
1. Just checking where the clicks lands
I'll go with the most basic one: detecting the "click" and checking if it's coordinates are inside a button.
First, we'll add the mouseClicked() method. This method is called every time a mouse button is pressed.
// I'm typing this out of IDE si there may be some quirks to fix in the code
void mouseClicked() {
switch(Page) {
case 0:
if (mouseX > 1420 && mouseX < 1420+400 && mouseY > 250 && mouseY < 250+100) {
// You're in the main menu and Start was clicked
}
if (mouseX > 1420 && mouseX < 1420+400 && mouseY > 650 && mouseY < 650+100) {
// You're in the main menu and Exit was clicked
}
if (mouseX > 1420 && mouseX < 1420+400 && mouseY > 450 && mouseY < 450+100) {
// You're in the main menu and Help was clicked
}
// You should use 'else if' instead of 3 different if, but I coded it like that so it would be easier to see the small differences between the coordinates
case 1:
if (mouseX > 1420 && mouseX < 1420+400 && mouseY > 450 && mouseY < 450+100) {
// You're un the help menu and Back was clicked
}
}
}
As you can see, I just used the coordinates and size of your buttons to check if the click was located inside one. That's kind of ninja-ing my way out of this issue. I don't know how far into programming you are, or else I would recommand to build a class to handle user inputs, but this way is easy to manage for small exercises like homework.
2. Designing controlP5 buttons
I'm not a ControlP5 expert, so we'll keep close to the basics.
I'll be blunt, the code you provided is ripe with problems, and it's not so many lines, so instead of pointing where it goes wrong I'll give you some skeleton code which will work and on which you can build some understanding. I'll give you the tools and then you can make your project work.
When you design your buttons, if you design them all in the same object, they'll share some properties. For an example, all your buttons will be visible or invisible at the same time. You don't need to redraw them all the time, because they already handle this, so you need to manage them with another method.
You should design your buttons as global objects (as you did), and add them to the ControlP5 object which makes the most sense. You can have one button per object if you want, or many if they are linked together, for an example all the "menu" buttons which appears at the same time could be owned by the same object. Design your buttons in the setup() method if you design them only one time for the whole program. Of course, if this was more than an homework, you may want to avoid the buttons being globals, but it'll be much easier to keep them in memory for a short project.
The "name" of the button is also the name of the method that it'll try to call if you click on it. Two buttons cannot share the same "name". Buttons can have a set value which will be sent to the method that they call.
You don't need to use Processing's mouse events for the buttons to work. They are self-contained: they have their own events, like being clicked on or detecting when the mouse is over them. Here's the documentation for the full list of the methods included in the ControlP5 buttons.
You don't need to manage the buttons in the draw() loop. They manage themselves.
Here's some skeleton code to demonstrate what I just said. You can copy and paste it in a new Processing project and run it to see what's going on.
ControlP5 cp5;
ControlP5 flipVisibilityButton;
int Page = 0;
void setup() {
size(1920, 800);
textAlign(CENTER, CENTER);
textSize(60);
fill(255);
cp5 = new ControlP5(this); // this is ONE object, which will own buttons.
cp5.addButton("MenuButton0") // this is the name of the button, but also the name of the method it will call
.setValue(0) // this value will be sent to the method it calls
.setPosition(1420, 250)
.setSize(400, 100);
cp5.addButton("MenuButton1")
.setValue(1)
.setPosition(1420, 450)
.setSize(400, 100);
cp5.addButton("MenuButton2")
.setValue(2)
.setPosition(1420, 650)
.setSize(400, 100);
flipVisibilityButton = new ControlP5(this); // this is a different object which own it's own controls (a button in this case)
flipVisibilityButton.addButton("flipVisibility")
.setValue(2)
.setPosition(200, height/2)
.setSize(200, 100);
}
void draw() {
// No button management to see here
background(0);
// showing which button has been pressed while also keeping watch to see if the mouse is over one of the cp5 buttons
text(Page + "\n" + cp5.isMouseOver(), width/2, height/2);
}
void MenuButton0(int value) {
ChangePage(value);
}
void MenuButton1(int value) {
ChangePage(value);
}
void MenuButton2(int value) {
ChangePage(value);
}
void ChangePage(int value) {
Page = value;
}
void flipVisibility(int value) {
// When the buttons are invisible, they are also unclickable
cp5.setVisible(!cp5.isVisible());
}
You should be able to expand on this example to do your project, but if you have difficulties don't hesitate to comment here and ask further questions. Have fun!
Related
I'm working on a breakout game for an assignment and for part 2 of it I need to include code that stops the bat from being moved out of the boundaries. I'm pretty sure that I need to use an if statements but I don't know what exactly I should put inside the brackets for else (something that will enable the bat to move). I
This is the code in particular I'm talking about.
if (dist < 0)
{
}
else
{} // move
if ((dist + 150)> 600)
{
}
else
{} // move
(Part 2 is in the ModelBreakout class).
There are lots of classes and just so many different parts of the code that are to do with the movement of the bat and I don't know what to use for this part, I would appreciate a hint of what I need to do!
Edit: I removed all of the classes because people were complaining. If you would like to view the classes go to this page and scroll down to the title Mini project: The BreakOut game.
Thanks for any help. I'm not looking for anyone to do my work for me, I would just like some guidance, I've worked out that I need to do an if statement, I'm just not sure of what I need to put inside it.
TL;DR.
I recently created a similar game. Here's how I implemented it.
Racket Class
protected static final float MIN_X = 10;
protected static final float MAX_X = 590;
public void moveLeft()
{
if (x > MIN_X)
{
x -= 5;
}
}
public void moveRight()
{
if (x < MAX_X)
{
x += 5;
}
}
Player extends Racket
public void process(int key)
{
if (key == KeyEvent.VK_KP_LEFT || key == KeyEvent.VK_LEFT)
{
moveLeft();
}
else if (key == KeyEvent.VK_KP_RIGHT || key == KeyEvent.VK_RIGHT)
{
moveRight();
}
}
Edit: This is not the complete classes. It's just some items lifted from them. There's a key listener added to the game which passes the key to Player.process().
Edit 2: Updated my code. Your width is set to 600 so the boundaries can be 10 and 590. This should work for you
Looking at the classes there are built in methods for each object on the screen, so you could do something like this:
If( Bat.GetX() < 0 ) {
Bat.moveX( *INSERT THE X HERE* )
}
And you also could do a the same thing for the max width. Also if you do a simple fix like this make sure to change the refresh rate of the screen, otherwise you will see the bat Jumping to the new position.
I am making a chess game and need to figure out how to move the pieces. I have my pieces stored in an array squaresGrid[][] and I want to use the method moveTo to move the pieces. Currently this method simply marks a piece selected but I need it to take a second mouse click to choose the square to move the selected piece to but am not sure how best to do this.
public void actionPerformed(ActionEvent e)
{
for(int x = 0; x < 8; x++)
{
for(int y = 0; y < 8; y++)
{
if(e.getSource() == squaresGrid[x][y])
{
moveTo(e, squaresGrid[x][y]);
}
}
}
}
public void moveTo(ActionEvent e, JButton clicked)
{
clicked.setIcon(selected);
}
You don't do a "second actionPerformed". What you do is keep around state, and when a click happens, look at the state, and decide what the action should be.
For example, keep around a field called currentlySelected, pointing to the currently selected square (containing its coordinates, for example).
In the actionPerformed, when you receive a click, you look at currentlySelected.
If it is null, it means you are supposed to select the clicked square and put it in currentlySelected.
If it is not null, and the current click is in the same square, the user probably wants to de-select it. De-select and clear (put null) in currentlySelected.
If it is not null and not the same square, it means that you have to check if the move is legal. If it is legal, you can do the move, and clear currentlySelected. If it is not legal, you do what you think is the proper thing to do: perhaps de-select the original place and select the new one. Or just de-select and tell the user the move is not legal. Or keep it selected.
Remember to always clear your currentlySelected in the appropriate situations.
You don't need a second ActionListener or actionPerformed method, but rather you need a state-ful ActionListener, one that knows whether the button push represents the first push or the 2nd. A boolean variable could be all that is required for this. Another option is to use a variable to represent the first pushed location, set it equal to null initially and then set it equal to the position on the first push. On the 2nd push check if it is null or non-null and if non-null, the button push represents the 2nd push. Then set it back to null.
For example
public void actionPerformed(ActionEvent e) {
for(int x = 0; x < 8; x++) {
for(int y = 0; y < 8; y++) {
if(e.getSource() == squaresGrid[x][y]) {
if (gridLocation == null) {
// class to hold x and y location
gridLocation = new GridLocation(x, y);
} else {
// use gridLocation here
int firstX = gridLocation.getX();
int firstY = gridLocation.getY();
moveTo(e, x, y, firstX, firstY);
gridLocation = null;
}
}
}
}
}
Hi I'm new to stackoverflow so bear with me if I make mistakes.
I'm making this Java Simon Says Game for a class project. It works by a random number generator for each sequence#. I show the sequence through doClick() but remove the actionlisteners beforehand and add it afterwards.
The problem is the buttons won't unpress or unarm until all other buttons have been pressed. I've tried using thread.sleep to put a delay between each if...else statements yet it only stays pressed for longer. I've tried updating the gui through repaint(), revalidate(), updateUI() within the try... catch of the thread.sleep but that didn't work either.
I've realized this issue is mainly cosmetic because when I tried implementing setPressed or setArmed it said it wasn't being pressed but it looked pressed.
Here is the code snippet in it's most simplest form without thread.sleep or my previous attempts in comments.
public void sequence2() //This is where the issue happens. The buttons won't unpress until every button has been pressed.
{
level.setText(" Level 2"); //Level indicator
Green.removeActionListener(Listener);
Red.removeActionListener(Listener);
Yellow.removeActionListener(Listener);
Blue.removeActionListener(Listener);
if(sequence1 == 1)
{
Green.doClick(300); //Programmatically clicks the button
}
else if(sequence1 == 2)
{
Red.doClick(300);
}
else if(sequence1 == 3)
{
Yellow.doClick(300);
}
else if(sequence1 == 4)
{
Blue.doClick(300);
}
if(sequence2 == 1)
{
Green.doClick(300);
}
else if(sequence2 == 2)
{
Red.doClick(300);
}
else if(sequence2 == 3)
{
Yellow.doClick(300);
}
else if(sequence2 == 4)
{
Blue.doClick(300);
}
Green.addActionListener(Listener);
Red.addActionListener(Listener);
Yellow.addActionListener(Listener);
Blue.addActionListener(Listener);
}
I'm very new to java so I'm not skilled in multithreading or working on the Event Dispatch Thread for that manner. But if that's the only solution I'll need some more help with that.
I have the full code in a zip file with previous attempts commented out if that will help.
https://drive.google.com/file/d/0Bxg4WleC9jD2VFhoZmZBNjV6Vkk/view?usp=sharing
Invoking doClick() may be an awkward choice for this, as it uses a Timer internally. Instead, use a JToggleButton, which will allow you to control each button's appearance based on its selected state using setSelected(). A complete example is shown in the game Buttons. In the ActionListener of your Swing Timer, select the current button, play its note and increment the sequence index. When all notes have been played, unselect all the buttons.
Addendum: Can you show how you implement the timer?
In outline, given a suitable list of toggle buttons:
private static final int MAX = 4;
List<JToggleButton> buttons = new ArrayList<JToggleButton>(MAX);
private int i;
The timer's listener might look like this:
#Override
public void actionPerformed(ActionEvent e) {
Object src = e.getSource();
JToggleButton b = buttons.get(i);
if (i > MAX) { // reset i and all the buttons
for (JToggleButton b : buttons) {
b.setSelected(false);
}
timer.stop();
i = 0;
} else {
b.setSelected(true);
// play tone i
i++;
}
}
A toggle button's item listener should update the button's appearance as indicated by its state:
#Override
public void itemStateChanged(ItemEvent e) {
JToggleButton b = (JToggleButton) e.getItem();
if (b.isSelected()) {
// change icon, color etc.
} else {
// restore icon, color etc.
}
}
How to effectively switch states?Whenever I press the replay button, the two states shows alternatively (win & play). I believe that was an infinite loop but Eclipse does not print any errors.
When I tried this, it results to null.Thus, ending the game.
Could this be the answer? But I don't understand his Update(). What to put exactly there?will that overwrite the update of the state class?
Here is my code:
stateID(2) is the Wins.java
PlayGround.java
public static boolean bouncy = true;
public void update(GameContainer gc, StateBasedGame sbg, int delta) throws SlickException{
//if the user is successful, show winner state
if(!bouncy){
sbg.enterState(2);
}
//moves the image randomly in the screen
new Timer(10,new ActionListener(){
public void actionPerformed(ActionEvent e)
{
posX = (r.nextInt(TestProject4.appGC.getWidth()-75));
posY = (r.nextInt(TestProject4.appGC.getHeight()-75));
}
}).start();
}
public void mousePressed(int button,int x,int y){
//if the user pressed the mouse button And
//if the user's coordinates is inside the hit area(rect)
if((button == 0) && (rect.contains(x, y))){
Toolkit.getDefaultToolkit().beep();
bouncy = false;
}
}
Wins.java
#Override
public void update(GameContainer gc, StateBasedGame sbg, int delta)throws SlickException {
//replay game
if(backToGame == true){
sbg.enterState(state);
}
}
public void mousePressed(int button,int x,int y){
//if the user clicks the replay button
if(button == 0){
if((x>160 && x<260)&&(y>280 && y<320)){
if(Mouse.isButtonDown(0)){
backToGame = true;
state = 1;
}
}
//exit button
if((x>=360 && x<460)&&(y>280 && y<320)){
if(Mouse.isButtonDown(0)){
System.exit(0);
}
}
}
}
I think you switch between both states again and again because both GameState objects are still in the same "state" (variables have still the same values) when you switch back.
Try:
if(!bouncy){
bouncy = true; // next time we are in this game state it will not trigger immediately
sbg.enterState(2);
}
if(backToGame == true){
backToGame = false; // same here
sbg.enterState(state);
}
Previous answer:
Please check your if statement:
if((x>160 && x<180)||(y>280 && y<320)){
You are checking whether the mouse is between some x coordinates OR some y coordinates.
I think you want to check whether the mouse is between some x AND some y coordinates:
if((x>160 && x<180)&&(y>280 && y<320)){
Your code has two methods mousePressed() one in PlayGround.java and the other in Wins.java.
The application is clearly using the Playground.java Code.
Adding the button detection code into the PlayGround.java may solve the problem.
Other wise explicitly calling the mousePressed() method in Wins from PlayGround.java
may work as well.
Adding comments help.
It can show your train of thought for a project, Helps others to try and see what you are doing.
In fleshing out a complex method I comment excessively at first, weeding out obvious comments through iterations of debugging and code review.
I also helps when others are viewing your code.
Remember There are no stupid comments, only stupid people.
How do I know if the mouse if out of the window I made and from which side it exited. I'm making a classic pong game and when I move my mouse out too fast, the 'thing' stays some pixels in. I'd like it to move to the edge of the window where it exited.
private class MouseMotion extends MouseAdapter{
public void mouseMoved(MouseEvent e) {
super.mouseMoved(e);
int x = e.getX();
p1.move(x);
}
}
and the move function
public void move(int x) {
if (x < 0 ) {
this.x = 0;
}else if(x+width > Main.screenSize.width - 1){
this.x = Main.screenSize.width - width - 1;
} else {
this.x = x;
}
}
I just need to know a way to know if the mouse is out of the window.
Check for MouseListener.mouseExited(MouseEvent).
You might want to take a look this:
Point mouse = MouseInfo.getPointerInfo().getLocation();
This tells you were the pointer is on the screen. No matter if your application has the focus or not. No matter if the pointer in on top of your window or not.
You can use MouseExited() and then get the coordinate from the event generated, using event.getPoint().
Try putting this somewhere where it will get run and getting rid of the MouseMotion class. 'c' is the JComponent that p1 is getting drawn to, I don't know what you called that object in your code. 'running' is some boolean that is set to true. When this code is run, p1 will move according to the mouse until 'running' is set to false.
new Thread(()->{
while(running) {
p1.move(MouseInfo.getPointerInfo().getLocation().getX()-c.getLocationOnScreen());
}
}).start();