I am practising on a simple Android Game where a round button is randomly placed on the screen when the user taps on it..
it works fine but i want to speedify the process of placing the button so that the game gets harder for user...
here is the Code I'm using -
public class GameWindow extends Activity implements View.OnClickListener {
static int score;
private Timer t;
private int TimeCounter = 29;
private boolean canMove = true;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setVolumeControlStream(AudioManager.STREAM_MUSIC);
////Remove title screen for activty.
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_game_window);
moveButton();
endonTimeOver();
}
public void endonTimeOver(){
////Activity timer for 60 seconds.
final TextView timer = (TextView) findViewById(R.id.seconds);
t = new Timer();
t.scheduleAtFixedRate(new TimerTask() {
////Set string to timer.
#Override
public void run() {
// TODO Auto-generated method stub
runOnUiThread(new Runnable() {
public void run() {
timer.setText(String.valueOf(TimeCounter)); // you can set it to a textView to show it to the user to see the time passing while he is writing.
TimeCounter = TimeCounter - 1;
}
});
}
}, 1000, 1000); // 1000 means start from 1 sec, and the second 1000 is do the loop each 1 sec.
new Timer().schedule(new TimerTask(){
public void run() {
GameWindow.this.runOnUiThread(new Runnable() {
public void run() {
startActivity(new Intent(GameWindow.this, Finished.class));
}
});
}
}, 30000);
}
////Move button.
private void moveButton()
{
if(!canMove){ return; }
runOnUiThread(
new Runnable()
{
#Override
public void run()
{
Display display = getWindowManager().getDefaultDisplay();
Point size = new Point();
display.getSize(size);
int width = size.x;
int height = size.y;
Button button = (Button)findViewById(R.id.button);
Random r = new Random();
int startX = width/2;
int startY = height/2;
if(score==0){
button.setX(startX);
button.setY(startY);
}
else {
int x = r.nextInt(width - 210);
int y = r.nextInt(height - 200);
button.setX(x);
button.setY(y);
}
}
}
);
}
////Display score
public void displayScore(int score) {
TextView scoreView = (TextView) findViewById(R.id.score);
scoreView.setText(String.valueOf(score));
}
#Override
public void onClick(View v) {
MediaPlayer mp = MediaPlayer.create(this, R.raw.buttonsound);
mp.setOnCompletionListener(new OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mp) {
// TODO Auto-generated method stub
mp.release();
}
});
mp.start();
score = score + 1;
displayScore(score);
switch (v.getId()) {
case (R.id.button): {
moveButton();
}
}
}
public static int getScore(){
return score;
}}
Use global variables for values that don't change:
findViewById is slow
Creating new Random every time is not necessary
getting the window parameter every time is not necessary either
You seem to be starting a new thread and telling it to runonui , this might be slowing you down , try this :
private void moveButton()
{
if(!canMove){ return; }
Display display = getWindowManager().getDefaultDisplay();
Point size = new Point();
display.getSize(size);
int width = size.x;
int height = size.y;
Button button = (Button)findViewById(R.id.button);
Random r = new Random();
int startX = width/2;
int startY = height/2;
if(score==0){
button.setX(startX);
button.setY(startY);
}
else {
int x = r.nextInt(width - 210);
int y = r.nextInt(height - 200);
button.setX(x);
button.setY(y);
}
}
the computation itself doesn't seem to heavy so no need for another thread , you can do it on the main thread , if you're calling from oncreate that means you're already on main thread , this might give you the answer if i understood the question , try it
Related
I am having problems with detecting clapping sounds using TarsosDSP. PitchDetectioHandler somehow works but when it comes to using PercussionOnsetDetector, it does not detect anything.
Am I doing anything wrong here?
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//Checks Permission
checkPermission(Manifest.permission.RECORD_AUDIO,REQUEST_RECORD_AUDIO_PERMISSION);
pitchText = (TextView) findViewById(R.id.pitch);
noteText = (TextView) findViewById(R.id.note);
/*PitchDetectionHandler pdh = new PitchDetectionHandler() {
#Override
public void handlePitch(PitchDetectionResult res, AudioEvent e){
final float pitchInHz = res.getPitch();
runOnUiThread(new Runnable() {
#Override
public void run() {
processPitch(pitchInHz);
}
});
}
};
AudioProcessor pitchProcessor = new PitchProcessor(PitchProcessor.PitchEstimationAlgorithm.FFT_YIN, 22050, 1024, pdh);
dispatcher.addAudioProcessor(pitchProcessor);
Thread audioThread = new Thread(dispatcher, "Audio Thread");
audioThread.start(); */
AudioDispatcher dispatcher = AudioDispatcherFactory.fromDefaultMicrophone(22050,1024,0);
double threshold = 8;
double sensitivity = 20;
PercussionOnsetDetector mPercussionDetector = new PercussionOnsetDetector(22050, 1024,
new OnsetHandler() {
#Override
public void handleOnset(double time, double salience) {
runOnUiThread(new Runnable() {
#Override
public void run() {
System.out.println("YAAAYYY");
}
});
}
}, sensitivity, threshold);
dispatcher.addAudioProcessor(mPercussionDetector);
new Thread(dispatcher,"Audio Dispatcher").start();
}
The following code detects the clap with Tarsos DSP:
final AudioDispatcher fromDefaultMicrophone = AudioDispatcherFactory.fromDefaultMicrophone(22050, 1024, 0);
double threshold = 6; // lower it a bit
double sensitivity = 20;
PercussionOnsetDetector mPercussionDetector = new PercussionOnsetDetector(22050, 1024,
new OnsetHandler() {
#Override
public void handleOnset(double time, double salience) {
Log.d(TAG, "Clap detected!");
startAlarm();
}
}, sensitivity, threshold);
fromDefaultMicrophone.addAudioProcessor(mPercussionDetector);
new Thread(fromDefaultMicrophone,"Audio Dispatcher").start();
I have this swapAnimation method which basically swaps two views. I call this method inside a loop and pass different views on the swapAnimation method each time. But the problem is the animation happens only once. I want it to repeat n number of times.
void swapAnimation(View v1,View v2){
if(isAnimating)return;
isAnimating = true;
float x1,y1,x2,y2;
x1 =getRelativeX(v1);
x2 = getRelativeX(v2);
y1 = getRelativeY(v1);
y2 = getRelativeY(v2);
float x_displacement = (x2-x1);
float y_displacement = (y2-y1);
v1.animate().xBy(x_displacement).yBy(y_displacement);
v2.animate().xBy(-x_displacement).yBy(-y_displacement);
v1.animate().setDuration(500);
v2.animate().setDuration(500);
long duration = v1.animate().getDuration();
new CountDownTimer(duration+10,duration+10){
#Override
public void onTick(long millisUntilFinished) {
}
#Override
public void onFinish() {
isAnimating = false;
}
}.start();
}
public static void arrange(LinearLayout container, Context context){
MainActivity activity = (MainActivity) context;
for(int i=0;i<container.getChildCount();i++){
BarView v1 = (BarView) container.getChildAt(i);
for(int j=i;j<container.getChildCount();j++){
BarView v2 = (BarView) container.getChildAt(j);
if(v1.getWeight() > v2.getWeight()){
Log.d(TAG, "bubbleSort: "+v1.getWeight()+">"+v2.getWeight());
activity.swapAnimation(v1,v2);
}
}
}
}
Try this
animation.setRepeatCount(Animation.INFINITE);
This question already has answers here:
Android "Only the original thread that created a view hierarchy can touch its views."
(33 answers)
Closed 6 years ago.
I want to change the image dynamically with its link in a thread.
public class MainActivity extends AppCompatActivity {
public static final Integer[] images =
{
R.drawable.vr_final_icon,
R.drawable.playnew
};
public static final String[] Links =
{
"http://stackoverflow.com/questions/541487/implements-runnable-vs-extends-thread",
"http://www.facebook.com",
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
new Thread(new Runnable()
{
#Override
public void run()
{
try
{
Random r = new Random();
int Low = 0;
int High = images.length;
final int Result = r.nextInt(High - Low) + Low;
INCP(Result);
Thread.sleep(6000);
run();
}
catch (Exception e)
{
e.printStackTrace();
}
}
public void INCP(final int incp)
{
Drawable res = getResources().getDrawable(images[incp]);
ImageView INCPimage = (ImageView) findViewById(R.id.INCP);
INCPimage.setImageDrawable(res);
INCPimage.setOnClickListener(new View.OnClickListener() {
public void onClick(View v)
{
Intent intent = new Intent();
intent.setAction(Intent.ACTION_VIEW);
intent.addCategory(Intent.CATEGORY_BROWSABLE);
intent.setData(Uri.parse(Links[incp]));
startActivity(intent);
}
});
}
}).start();
}
}
But it gives me error that
Only the original thread that created a view hierarchy can touch its views.
How can i solve it !
I want image to change dynamically with its link on run time.
Only main thread can touch views. Change code like this;
Random r = new Random();
int Low = 0;
int High = images.length;
final int Result = r.nextInt(High - Low) + Low;
runOnUiThread(new Runnable() {
#Override
public void run() {
INCP(Result);
}
});
Thread.sleep(6000);
run();
I have a game where image Views changes on a timer. When a button is clicked (stop) the update is called to update score and spins. I need to stop when the whammy(); is called and run a frame animation then start the timer back when the animation has ended. I have tried to call sleep(2500); but it cause the everything to wait the 2.5 seconds and the frame animation then runs with the image view timer. That just won't work for what I need. Below is the section of code I need help with:
public void onClick(View v) {
if (v.getId() == R.id.btstop) {
final Button bstop = (Button) findViewById(R.id.btstop);
bstop.setEnabled(false);
updateState();
}
}
/**
* set random view. get random 1 point from class utils and display to 1
* position random
*/
public void setRandomView() {
int item = new Random().nextInt(18);
current = Utils.getAPoint();
int img = current.getImg();
int score = current.getScore();
int spin = current.getSpin();
iv[item].setImageResource(img);
dataPoint.get(item).setImg(img);
dataPoint.get(item).setScore(score);
dataPoint.get(item).setSpin(spin);
ivcenter.setImageResource(img);
}
/**
* display Name,score & spin to screen
*/
public void setPoint() {
tvspin.setText(spins + "\n" + name);
tvpoint.setText(point + "");
}
/**
* Start Thread Sets the speed of the game board Enable STOP button to true
*
* #param time
*/
public void start(int time) {
countDownTimer = new CountDownTimer(time, 300) {
#Override
public void onTick(long millisUntilFinished) {
// call to set random view
setRandomView();
}
#Override
public void onFinish() {
// TODO Auto-generated method stub
}
}.start();
}
/**
* stop timer thread
*/
public void stop() {
try {
countDownTimer.cancel();
} catch (Exception e) {
// TODO: handle exception
} finally {
}
}
/**
* update state game and check what tile is in the center
*/
public void updateState() { // get score,spin current point
int scoreCurrent = current.getScore();
int spinCurrent = current.getSpin();
spins--;// Take one from spins
// if score = 2, that mean to double score
if (scoreCurrent == 2) {
point = point * 2;
playmp3(R.raw.correct);
}
// if score = 0, that means tile is a whammy
if (scoreCurrent == 0) {
playmp3(R.raw.buzz);
whammy();// I need to put everything else on hold here and animation here
point = 0;// sets the score to 0
whammy++; // Add a whammy to the whammy count
// Display the whammy that was added
for (int i = 0; i < whammy; i++) {
popup[i].setVisibility(View.VISIBLE);
}
// sleep(2500);
if (whammy == 4) {
stop();
stopmp3();
callFinish();
}
}
// else ,score = score current + point.getscore
else {
playmp3(R.raw.correct);
point = point + scoreCurrent;
}
// spins--;// Take one from spint
// if spin > 0, that mean is add a spin
if (spinCurrent > 0) {
spins = spins + spinCurrent;
}
setPoint(); // display spin,score and name to screen
sleep(2000); // Adds a delay so that the whammy pop up can be seen
// if spint >0 start new data random
if (spins > 0) {
stop();
final Button bstop = (Button) findViewById(R.id.btstop);
bstop.setEnabled(true);
start(10000 * 60 * 60 * 24);
} else {
// stop all
stop();
stopmp3();
// if spin < 2, that round <2 move to spin activity
if (round < 2) {
Intent it = new Intent(getBaseContext(), SpinActivity.class);
startActivity(it);
finish();
}
// else move to high score activity
else {
callFinish();
}
}
}
private void whammy() {
// set up the whammy act animation
final ImageView act = (ImageView) findViewById(R.id.whammyact);
act.setBackgroundResource(R.drawable.tnt_animation);
actAnim = (AnimationDrawable) act.getBackground();
actAnim.setVisible(true, true);
}
OK Here are the changes that were made to make the animation run and finish before the game timer gets started back...
IF THERE ARE QUESTION OR ANYONE NEED HELP FEEL FREE TO ASK.
if (scoreCurrent == 0) {
countDownTimer.cancel();
countDownTimer = null;
// Use Timer to set visibility to GONE after the animation finishes.
TimerTask timerTask = new TimerTask(){
#Override
public void run() {
PressActivity.this.runOnUiThread(new Runnable(){
public void run() {
resumeLogicAfterPress();
}
});}};
Timer timer = new Timer();
timer.schedule(timerTask, getWhammyAnimationTotalDuration(actAnim));
} else {
resumeLogicAfterPress();
}
}
public void resumeLogicAfterPress() {
// Display the whammy that was added
for (int i = 0; i < whammy; i++) {
popup[i].setVisibility(View.VISIBLE);
}
sleep(2500); //Adds a delay so that the whammy pop up can be seen
//Start the background music
playmp3(mpPress, R.raw.press);
// if whammy = 4. stop all and move to high score
if (whammy == 4) {
stop();
stopmp3();
callFinish();
}
// if spint >0 start new data random
if (spint > 0) {
stop();
final Button bstop = (Button) findViewById(R.id.btstop);
bstop.setEnabled(true);
start(10000 * 60 * 60 * 24);
} else {
// stop all
stop();
stopmp3();
// if spin < 2, that round <2 move to spin activity
if (spin < 2) {
Intent it = new Intent(getBaseContext(), SpinActivity.class);
startActivity(it);
finish();
}
// esle move to high score activity
else {
callFinish();
}
}
}
private void whammy() {
// set up the whammy act animation
final ImageView act = (ImageView) findViewById(R.id.whammyact);
act.setBackgroundResource(R.drawable.tnt_animation);
actAnim = (AnimationDrawable) act.getBackground();
actAnim.setVisible(true, true);
}
I'm newbie in java. So the program should take the user entered text and if there is "a" it gonna play a-sound, if there is "b" it gonna play b-sound.And it must play this sounds one by one even if there are multiple "a" or "b". Here is my code:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Button bStart = (Button) findViewById(R.id.bStart);
final EditText etStart = (EditText) findViewById(R.id.etStart);
final EditText etFinish = (EditText) findViewById(R.id.etFinish);
final char[] arr = etStart.getText().toString().toCharArray();
final MediaPlayer as = MediaPlayer.create(R2d2Activity.this, R.raw.as);
final MediaPlayer bs = MediaPlayer.create(R2d2Activity.this, R.raw.bs);
final SoundPool sp;
final int a;
final int b;
final int t;
sp = new SoundPool(2, AudioManager.STREAM_MUSIC, 0);
a = sp.load(this, R.raw.as, 1);
b = sp.load(this, R.raw.bs, 1);
final String value = etStart.getText().toString();
final Thread timer = new Thread(new Runnable() {
#Override
public void run() {
try {
Thread.sleep(1300);
// Do some stuff
} catch (Exception e) {
e.getLocalizedMessage();
}
}
});
bStart.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
int n = 0;
String value;
String first;
value = etStart.getText().toString();
// TODO Auto-generated method stub
//actual code
for (int i=0; i<value.length(); i++){
first = etStart.getText().toString().substring(i, i+1);
if(first.contentEquals("a")){
as.start();
as.setOnCompletionListener(new OnCompletionListener(){
public void onCompletion(MediaPlayer arg0) {
//when finished
}
});
}else{
}
if(first.contentEquals("b")){
bs.start();
}else{
}
}
}
});
The problem is that it starts playing audio files all at one time. I tried to add some OnCompletionListener, but I don't know what to do with it. Help me please.
What you can do is
//define a variable to be used as index.
int audioindex = 0;
//Extract the files id into an array
int[] audioFileIds=new int[]{R.raw.as,R.raw.bs};
Then in your MediaPlayer onCompletionListener put something like following.
then in your OnCompletionListener.
mp.setOnCompletionListener(new OnCompletionListener(){
// #Override
public void onCompletion(MediaPlayer player) {
// File has ended, play the next one.
FunctionPlayFile(audioFileIds[audioindex]);
audioindex+=1; //increment the index to get the next audiofile
}
});