Trouble with while to make a loop - java

cameraOn();
while (counter == 1){
if(counter == 0){
cameraOn();
counter += 1;
}else{
cameraOff();
counter -= 1;
}
}
The methods are:
private void cameraOff() {
// TODO Auto-generated method stub
parameters.setFlashMode(Parameters.FLASH_MODE_OFF);
camera.setParameters(parameters);
camera.release();
camera = null;
}
private void cameraOn() {
// TODO Auto-generated method stub
camera = Camera.open();
parameters = camera.getParameters();
parameters.setFlashMode(Parameters.FLASH_MODE_TORCH);
camera.setParameters(parameters);
}
and I have a button who have to break the loop and finish the activity:
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
if (camera == null){
finish();
}else{
parameters.setFlashMode(Parameters.FLASH_MODE_OFF);
camera.setParameters(parameters);
camera.release();
camera = null;
finish();
}
I'm a beginner and I don't understand how does the loop work, I tought with the counter I could do it, but it didn't work.
What I'm trying is to make the camera flash blink every second in a loop until I will press the button. please help me. Thanks

if (counter == 0) will never be true as your loop will exit in that case.

As others have said, entering a loop only when counter == 0 means it will never enter the inner loop requiring counter == 1, and never enter cameraOn().
Try this:
Clear out your onClick method and replace it with:
#Override public void onClick(View v) {
cameraOff();
/* or 'toggle();' if you prefer, see below */
}
(Since it appears to do exactly the same things.)
Comment out / delete that whole nested loop, and be sure to call cameraOn() or toggle() somewhere to get things started.
For setting up the toggle, you can add a static Boolean isFlashActive; (or otherwise detect the flash state, I haven't used that api yet)
..and add a function:
private toggle(){
if ( isFlashActive ) {
cameraOff();
} else {
cameraOn();
}
/* delay? */
}
For the toggle delay, you have a couple options:
First, you can call toggle() from another thread via a Runnable or one of the android options like AsyncTask while adding a wait() into the toggle function to provide the delay;
Second is my personal favorite, which is to setup an intent receiver then use setRepeating() with a PendingIntent.

The following part of your code will never be executed because you only enter the while block if counter == 1.
if(counter == 0){
cameraOn();
counter += 1;
So if you ever entered your while block while (counter == 1), you will always end up calling cameraOff() method. In other words your if statement will never be true and the else statement will be the one to be always executed.

Related

Don't see why this loop does not get reached

Because of many boolean checks i am a little confused, let me introduce me to my next code.
} else {
//check whether the player starts again. the first time we lose the player
//will definitely get into this loop
if(!startAgain){
// we only do this to set a timer, we don't want to start a new game so we set this
// to false
newgame = false;
startAgain = true;
deadTime = System.nanoTime();
}
deadTimepassed = (System.nanoTime() - deadTime)/1000000;
if((deadTimepassed < 2000) && (newgame = false)){
newGame();
}
}
}
This else statement can be seen as the first time a player gets hit by an enemy missile. To make an explosion-animation. I need te screen to freeze for 2 seconds and then start the game over again. I don't see why the second if statement is never reached. Here are my ontouch methods and my new game method:
#Override
public boolean onTouchEvent(MotionEvent event) {
//What happens when the player touches the screen!
if (event.getAction() == MotionEvent.ACTION_DOWN) {
// Boolean check for when player is playing, if he isn't the chopper does nothing.
// we see that the chopper only hangs still if all these booleans are true!
if ((!player.isPlaying()) && (newgame = true) && (startAgain = true)) {
player.setPlaying(true);
} if(player.isPlaying()) {
player.setUp(true);
startAgain = false;
}
return true;
}
if (event.getAction() == MotionEvent.ACTION_UP) {
player.setUp(false);
return true;
}
return super.onTouchEvent(event);
}
public void newGame(){
newgame = true;
missles.clear();
if(player.getScore()>best) {
best = player.getScore();
SharedPreferences.Editor editor = saveBest.edit();
editor.putInt("new best",best);
editor.commit();
}
player.resetScore();
player.setY(HEIGHT/2);
}
As one can see, the new game just resets the players position, the only thing i want to do is just freeze the screen for 2 seconds before that happens, this is supposed to happen in the second if statement but it never get reached...
Any suggestions?
ps: deadTimepassed is introduced as 'private long' just beneath the public class method.
For freeze your Thread (so, the program will be freeze, also your screen) during 2 seconds you can use Thread.sleep() function:
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
You have to put it inside a try-catch block because it can gives to you an InterruptedException.
I expect it will be helpful for you!

Java(Android) stuck in while loop

when I run my app it will continuously be stuck in a while loop. It should leave the while loop when a button is pressed, however even after pressing a button it continues to loop.
View.OnClickListener listener11 = new View.OnClickListener() {
#Override
public void onClick(View view) {
temp1 = button[0];
temp3 = button[0].getBackground();
state++;
}
};
while(state == 0) {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
button[0].setOnClickListener(listener11);
}
variable:
state is an int temp1 is a button temp3 is a Drawable
the delay is there because I actually have 20 buttons and I have the setOnClickListeners for all the buttons inside that while loop so I think it causes it to crash without the delay. Another question would be is it possible to have the setOnClickListeners outside the while loop but still be able to check for button clicks inside the loop?
The problem is you are pressing the button while the thread is in a sleeping state causing the event to not be triggered and therefor the state to never change.
You should remove the while loop and just set all the listeners in a for loop:
for(int i = 0; i< button.length; i++) {
button[0].setTag(i);
button[0].setOnClickListener(listener11);
}
And then change your listener to be something like:
private boolean firstClick = true;
View.OnClickListener listener11 = new View.OnClickListener() {
#Override
public void onClick(View view) {
if(firstClick) {
firstClick = false;
temp1 = button[(int)view.getTag()];
} else {
temp2 = button[(int)view.getTag()];
}
}
};
I'm not sure exactly what the code is supposed to be doing because I have no idea of the context, but I think think you could remove the while loop altogether:
// initialize the listener
View.OnClickListener listener11 = new View.OnClickListener() {
#Override
public void onClick(View view) {
// add code that runs when button is clicked here
}
};
// now that we have the listener all set up we add it to the button, at which point it just keeps listening for you, no need to put the thread to sleep
button[0].setOnClickListener(listener11);
UPDATE:
So because you want to see if the second value matches the first value you could use a helper method:
private String firstValue = "";
public boolean isMatch(String mostRecentValue) {
boolean match = false;
if (firstValue.isEmpty()) {
firstValue = mostRecentValue;
} else {
match = firstValue.equals(mostRecentValue);
firstValue = "";
}
return match;
}
This method takes a value and if it is the first click the value is saved, if it is the second click it compares it with the first click and then resets the method. A boolean is returned false for no match, and true for a match. Call this method from within the onClick() method and pass in the buttons value. I've used String as an example value but you could use any object type.
I think you might be misunderstanding what setOnClickListener is doing. It's not handling the click, it is setting up the click handler. The line button[0].setOnClickListener(listener11); would be part of your activity initialisation and then not called again.
The reason you get stuck is because the main thread is busy in the while loop and isn't given an opportunity to process click events. Click events are handled on the main thread but only when it's not already busy doing something. In this case, it's forever busy in the while loop. For example, if the main thread was processing a method that would take 10 seconds to complete and you tap on a button 3 seconds into it, the button press wouldn't be handled for another 7 seconds. At which point, the previously set listener11 would be executed.
What you seem to be trying to achieve is already handled by the Looper. You need to be thinking in terms of event handling. So in other words, all your logic needs to go in listener11 or something similar.

Delete body box2d

Could anyone tell me why this is returning the error
'AL lib: (EE) alc_cleanup: 1 device not closed'
//mouseJoint collision callback
private QueryCallback queryCallback = new QueryCallback() {
#Override
public boolean reportFixture(Fixture fixture) {
if(fixture.getBody() == chest){
//add to remove list
bodiesToRemove.add(chest);
}
if (fixture.testPoint(tmp.x, tmp.y)){
reportFixture = fixture.getBody();
}
if (!fixture.testPoint(tmp.x, tmp.y))
return false;
//assigning bodyB to fixture
jointDef.bodyB = fixture.getBody();
jointDef.target.set(fixture.getBody().getWorldCenter());
//jointDef.target.set(tmp.x, tmp.y);// initial target point coincide with body anchor
joint = (MouseJoint) world.createJoint(jointDef);// creating the join the physics world
return false;
}
};
//main rendering loop
public void render(float delta) {
// TODO Auto-generated method stub
//code clears the screen with the given RGB colour (black)
Gdx.gl.glClearColor( 0f, 0f, 0f, 1f );
Gdx.gl.glClear( GL20.GL_COLOR_BUFFER_BIT );
stage.setCamera(camera);
stage.act(Gdx.graphics.getDeltaTime());
camera.position.x= chest.getPosition().x;
camera.update();
stage.draw();
world.step(1 / 60f, 8, 3);
renderer.render(world, camera.combined);
/////////////////////////////////////////////////////////////////
// this is the code that is causing the error when I try to delete a body
if(bodiesToRemove != null){
for(int i = 0; i <bodiesToRemove.size; i++){
Body b = bodiesToRemove.get(i);
if(b != null){
world.destroyBody(b);
b.setUserData(null);
b = null;
}
bodiesToRemove.clear();
}
}
////////////////////////////////////////////////////////////
}
////////////////////////////////////////////////////////////////////////////
I've changed this and it work's(pasted below), if anyone would like to explain the right way to do this or if this is the correct way that would be helpful.
I just added a boolean to prevent it from destroying the joint
// ////////////////// TOUCH EVENT ///////////////////////////////
//Called when a finger was lifted or a mouse button was released.
#Override
public boolean touchUp(int screenX, int screenY, int pointer, int button) {
//If no mouseJoint do nothing
System.out.println("touch" + (screenY*0.01f));
System.out.println("touch" + (screenX*0.01f));
if (joint == null)
return false;
//When user is not touching Screen destroy the
//mouseJoint/set to null
if(ran == false){
world.destroyJoint(joint);
joint = null;}
ran = false;
return true;
}
////////////////////////////////
/////////////////////////////////
if(!world.isLocked() && world.getBodyCount() > 0 ){
for(int i = 0; i <bodiesToRemove.size; i++){
Body b = bodiesToRemove.get(i);
if(b == null){
bodiesToRemove.removeIndex(i);
continue;
}
world.destroyBody(b);
ran = true;
bodiesToRemove.removeIndex(i);
}
}else{
bodiesToRemove.clear();
}
////////////////////////////////////////////////////////////
Box2D throws some odd errors, this is not one of them.
I assume you are using LibGDX, basically what is happening is a crash due to Box2D (I also assume it pops up saying "java or whatever has stopped responding"), this error you are seeing is thrown when the app exits while OpenAL is closing streams and cleaning up resources. Don't worry about that too much.
Ensure you are checking of the world is locked before destroying bodies, it usually throws an error and prints a clear message telling you this, depending on the way you are removing bodies.
if(!world.isLocked())
// do clean up code here
You don't need to clean up the variable inside local scope, or clear the userdata inside the body as the body as it will no longer exist in reference (unless you have it stored somewhere else).
So the proper code would be something like this:
if(!world.isLocked()){
for(int i = bodiesToRemove.size - 1; i--){
Body b = bodiesToRemove.get(i);
if(b == null){
bodiesToRemove.removeAt(i);
continue;
}
world.destroyBody(b);
bodiesToRemove.removeAt(i);
}
}
You are also clearing a list during iteration, not a good idea.
EDIT
The only other thing I can think of that is causing this problem is trying to delete a body that is not actually in the worlds body list.
Try the following:
// Ensure world is not locked AND that there is even bodies in the world
if(!world.isLocked() && world.getBodyCount() > 0){
for(int i = bodiesToRemove.size - 1; i--){
Body b = bodiesToRemove.get(i);
if(b == null){
bodiesToRemove.removeAt(i);
continue;
}
world.destroyBody(b);
bodiesToRemove.removeAt(i);
}
}else{
// There is no bodies in the world, so the bodies in our list are just
// random memory hogs, leave them for the GC by clearing the list
bodiesToRemove.clear();
}
EDIT
As stated by the OP, the problem lies with this block of code:
private QueryCallback queryCallback = new QueryCallback() {
#Override
public boolean reportFixture(Fixture fixture) {
if(fixture.getBody() == chest){
//add to remove list
bodiesToRemove.add(chest);
}
if (fixture.testPoint(tmp.x, tmp.y)){
reportFixture = fixture.getBody();
}
if (!fixture.testPoint(tmp.x, tmp.y))
return false;
//assigning bodyB to fixture
jointDef.bodyB = fixture.getBody();
jointDef.target.set(fixture.getBody().getWorldCenter());
//jointDef.target.set(tmp.x, tmp.y);
joint = (MouseJoint) world.createJoint(jointDef);
return false;
}
};
More specifically, this line:
joint = (MouseJoint) world.createJoint(jointDef);
The query callback is triggered during a world step. In Box2D, you can not create or destroy bodies, fixtures, and joints during the world step.
You have to create it outside this method, the simplest way to do it is via a flag. Set a flag to true and store the instance of the fixture somewhere and handle it outside in the game loop using said flag and fixture.

Android if rectangle contains touch coords then add to array giving weird output

I am building a game that you drag your finger in a sequence from one block to the next.
What I need to happen: when they hover over a block, it adds that block number to an array so I know in which sequence the blocks were touched in. it needs to be dragged from block to block, not clicked (sort of like the android lockscreen app).
What I am doing so far: creating a rectangle for each block using its coordinates and dimensions, then I am checking that if the user's touch is within that rectangle, add that block number to the array.
It seems to be working, but it only works for buttons 1, 2 and 3 (Only 1, 2 and 3 will be added to the array) But if I log the touch to logcat and the buttons dimensions / coordinates, it is picking the thing up, so I don't know why it is not holding the information?
Here is the code:
#Override
public boolean onTouch(View arg0, MotionEvent arg1) {
// TODO Auto-generated method stub
try {
Thread.sleep(50);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
x = (int) arg1.getX();
y = (int) arg1.getY();
if(b1R.contains(x,y)){
arr.add("1");
} else if(b2R.contains(x,y)){
arr.add("2");
} else if(b3R.contains(x,y)){
arr.add("3");
} else if(b4R.contains(x,y)){
arr.add("4");
} else if(b5R.contains(x,y)){
arr.add("5");
} else if(b6R.contains(x,y)){
arr.add("6");
} else if(b7R.contains(x,y)){
arr.add("7");
} else if(b8R.contains(x,y)){
arr.add("8");
} else if(b9R.contains(x,y)){
arr.add("9");
}
if(arr.toString() != null){
Log.d("log", arr.toString());
Log.d("x", ""+x);
Log.d("y", ""+y);
}
return false;
}
#Override
public void onWindowFocusChanged (boolean hasFocus){
super.onWindowFocusChanged(hasFocus);
if(hasFocus){
b1R = new Rect(b1.getLeft(), b1.getTop(), b1.getRight(), b1.getBottom());
b2R = new Rect(b2.getLeft(), b2.getTop(), b2.getRight(), b2.getBottom());
b3R = new Rect(b3.getLeft(), b3.getTop(), b3.getRight(), b3.getBottom());
b4R = new Rect(b4.getLeft(), b4.getTop(), b4.getRight(), b4.getBottom());
b5R = new Rect(b5.getLeft(), b5.getTop(), b5.getRight(), b5.getBottom());
b6R = new Rect(b6.getLeft(), b6.getTop(), b6.getRight(), b6.getBottom());
b7R = new Rect(b7.getLeft(), b7.getTop(), b7.getRight(), b7.getBottom());
b8R = new Rect(b8.getLeft(), b8.getTop(), b8.getRight(), b8.getBottom());
b9R = new Rect(b9.getLeft(), b9.getTop(), b9.getRight(), b9.getBottom());
}
}
this is what is being printed to logcat:
[1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,1,1,1,3,3,3,1,1,3,3,3]
and no other buttons?
Please help!
Thanks in advance!
What is B1r? Should you be updating this at some point to account for a new set of locations? You're using Else If statements, which means that as long as
if(b1R.contains(x,y)){
Evaluates to true, none of your other checks will execute.
I would ensure that you don't have b1r's bounds set to the entire screen, or some other incorrect (or possibly "correct" but damaging value).
It's hard to really debug this without more code however.

Limit number of checked checkboxes in Android

I have a problem with my application. I just want to set a limit of 2 checked checkboxes but I don't know how.
I have 4 checkboxes and a button. When the button is pressed, if there are only 2 checked checkboxes do something, if are 3 or more do something else. Here is my code:
button.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
if(chk1.isChecked()){
counter++;}
else{
counter--;
}
if(chk2.isChecked())
{ counter++;}
else{
counter--;
}
if(chk3.isChecked())
{ counter++; }
else{
counter--;
}
if(chk4.isChecked())
{ counter++; }
else{
counter--;
}
if ( (chk1.isChecked() || chk2.isChecked() || chk3.isChecked() || chk4.isChecked()) && counter >2 ) {
Toast.makeText(StartingPoint.this, "boo", Toast.LENGTH_LONG).show();
}
else {
Toast.makeText(StartingPoint.this, "no boo", Toast.LENGTH_LONG).show();
}
}
});
If I understand you correctly, you nearly got it already.
Declare your counter
Forget about the decrements, only use increments
Use a 1st if/then statement to check how many checkboxes have been checked (the value of counter)
Use a nested if/then statement to apply logic based on the specific checkboxes
Edit - here's a simplified example.
/*
* This will check the number of CheckBoxes checked when your
* button is pressed, and perform some logic consequently.
*
* ALTERNATIVE (not shown here):
* If you wish to disable the button based on how many CheckBoxes
* are checked, you should add an OnClickListener for each CheckBox
* (I'm over-simplifying here on purpose).
* Each CheckBox click would increase the counter if checked,
* decrease it if not.
* Each listener would decide whether or not to enable the button
* after computing the counter's value.
*/
Button myButton = null; // TODO initialize properly
// TODO initialize all CheckBoxes properly
final CheckBox cb0 = null;
final CheckBox cb1 = null;
final CheckBox cb2 = null;
// ... and so forth ...
// Initializing the anonymous listener class attached to the Button
myButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// initializing the counter each click
int counter = 0;
// incrementing the counter for each CheckBox checked
if (cb0.isChecked()) counter++;
if (cb1.isChecked()) counter++;
if (cb2.isChecked()) counter++;
// ... and so forth ...
// Verifying number of CheckBoxes checked...
// ...up to 2 CheckBoxes checked
if (counter < 3) {
// TODO logic depending on which CheckBox(es)
}
// ...more than 2 CheckBoxes checked
else {
// TODO logic depending on which CheckBox(es) or anything else
}
}
});

Categories

Resources