当用户按下后退按钮时,游戏音乐不会在我的 android 游戏中停止
Game music doesnt stop in my android game when user press back button
在我的 android 游戏中,当用户按下后退按钮时音乐不会停止,即使用户关闭游戏音乐仍在播放。
这是我的主要 class 游戏。 MediaPlayer mp1 用于播放音乐。
public class GameView extends SurfaceView{
Bitmap bmp,pause;
Bitmap background,kinfe,note1,appleimg,note2;
Bitmap run1;
Bitmap run2;
Bitmap run3;
Bitmap coin;
Bitmap exit;
private SurfaceHolder holder;
private int x = 0,y=0,z=0,delay=0,getx,gety,sound=1;
int show=0,sx,sy;
int cspeed=0,kspeed=0,gameover=0;
int score=0,health=100,reset=0;
int pausecount=0,volume,power=0,applerun=0,shieldrun=0;
@SuppressWarnings("deprecation")
@SuppressLint("NewApi")
public GameView(Context context)
{
super(context);
gameLoopThread = new GameLoop(this);
holder = getHolder();
holder.addCallback(new SurfaceHolder.Callback() {
@SuppressWarnings("deprecation")
@Override
public void surfaceDestroyed(SurfaceHolder holder)
{
//for stoping the game
gameLoopThread.setRunning(false);
gameLoopThread.getThreadGroup().interrupt();
}
@SuppressLint("WrongCall")
@Override
public void surfaceCreated(SurfaceHolder holder)
{
//for starting the game
gameLoopThread.setRunning(true);
gameLoopThread.start();
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format,int width, int height)
{
}
});
//getting the screen size
// Display display = getWindowManager().getDefaultDisplay();
// sx = display.getWidth();
// sy = display.getHeight();;
Display display = getWindowManager().getDefaultDisplay();
Point size = new Point();
display.getSize(size);
sx = size.x;
sy = size.y;
cspeed=sx/2;
kspeed=sx/2;
applerun=(3*sx/4);
shieldrun=sx/8;
background = BitmapFactory.decodeResource(getResources(), R.drawable.cold);
run1=BitmapFactory.decodeResource(getResources(), R.drawable.run1);
run2=BitmapFactory.decodeResource(getResources(), R.drawable.run2);
run3=BitmapFactory.decodeResource(getResources(), R.drawable.run3);
coin=BitmapFactory.decodeResource(getResources(), R.drawable.coin);
exit=BitmapFactory.decodeResource(getResources(), R.drawable.exit);
kinfe=BitmapFactory.decodeResource(getResources(), R.drawable.kinfe);
note1=BitmapFactory.decodeResource(getResources(), R.drawable.note1);
pause=BitmapFactory.decodeResource(getResources(), R.drawable.pause);
appleimg=BitmapFactory.decodeResource(getResources(), R.drawable.power);
note2=BitmapFactory.decodeResource(getResources(), R.drawable.note2);
exit=Bitmap.createScaledBitmap(exit, 25,25, true);
pause=Bitmap.createScaledBitmap(pause, 25,25, true);
appleimg=Bitmap.createScaledBitmap(appleimg, 25,25, true);
note2=Bitmap.createScaledBitmap(note2, sx,sy, true);
run1=Bitmap.createScaledBitmap(run1, sx/9,sy/7, true);
run2=Bitmap.createScaledBitmap(run2, sx/9,sy/7, true);
run3=Bitmap.createScaledBitmap(run3, sx/9,sy/7, true);
coin=Bitmap.createScaledBitmap(coin, sx/16,sy/24, true);
background=Bitmap.createScaledBitmap(background, 2*sx,sy, true);
//health dec
note1=Bitmap.createScaledBitmap(note1, sx,sy, true);
mp1=MediaPlayer.create(Game.this,R.raw.game);
jump=MediaPlayer.create(Game.this,R.raw.jump);
takecoin=MediaPlayer.create(Game.this,R.raw.cointake);
}
// on touch method
@Override
public boolean onTouchEvent(MotionEvent event) {
if(event.getAction()==MotionEvent.ACTION_DOWN)
{
show=1;
getx=(int) event.getX();
gety=(int) event.getY();
//exit
if(getx<25&&gety<25)
{
//high score
SharedPreferences pref = getApplicationContext().getSharedPreferences("higher", MODE_PRIVATE);
Editor editor = pref.edit();
editor.putInt("score", score);
editor.commit();
System.exit(0);
}
// restart game
if(getx>91&&gety<25)
{
if(health<=0)
{
gameLoopThread.setPause(0);
health=100;
score=0;
}
}
//pause game
if((getx>(sx-25)&&gety<25&&pausecount==0))
{
gameLoopThread.setPause(1);
mp1.stop();
pausecount=1;
}
else if(getx>(sx-25)&&gety<25&&pausecount==1)
{
gameLoopThread.setPause(0);
mp1.start();
pausecount=0;
}
}
return true;
}
@SuppressLint("WrongCall")
@Override
protected void onDraw(Canvas canvas)
{
//volume
SharedPreferences pref = getApplicationContext().getSharedPreferences("higher", MODE_PRIVATE);
Editor editor = pref.edit();
volume=pref.getInt("vloume", 0);
if(volume==0)
{
sound=0;
}
canvas.drawColor(Color.BLACK);
//background moving
z=z-10;
if(z==-sx)
{
z=0;
canvas.drawBitmap(background, z, 0, null);
}
else
{
canvas.drawBitmap(background, z, 0, null);
}
//running player
x+=5;
if(x==20)
{
x=5;
}
if(show==0)
{
if(x%2==0)
{
canvas.drawBitmap(run3, sx/16, 15*sy/18, null);
}
else
{
canvas.drawBitmap(run1, sx/16, 15*sy/18, null);
}
//kinfe hit
if(kspeed==20)
{
kspeed=sx;
health-=25;
canvas.drawBitmap(note1, 0, 0, null);
}
//power take
if(applerun==30)
{
applerun=3*sx;
health+=25;
canvas.drawBitmap(note2, 0, 0, null);
}
}
//power
applerun=applerun-10;
canvas.drawBitmap(appleimg, applerun, 15*sy/18, null);
if(applerun<0)
{
applerun=3*sx/4;
}
//kinfe
kspeed=kspeed-20;
canvas.drawBitmap(kinfe, kspeed, 15*sy/18, null);
if(kspeed<0)
{
kspeed=sx;
}
// for jump
if(show==1)
{
if(sound==1)
{
jump.start();
}
canvas.drawBitmap(run2, sx/16, 4*sy/7, null);
//score
if(cspeed<=sx/8&&cspeed>=sx/16)
{
if(sound==1)
{
takecoin.start();
}
cspeed=sx/2;
score+=10;
}
// jump-hold
delay+=1;
if(delay==3)
{
show=0;
delay=0;
}
}
//for coins
cspeed=cspeed-5;
if(cspeed==-sx/2)
{
cspeed=sx/2;
canvas.drawBitmap(coin, cspeed, 3*sy/4, null);
}
else
{
canvas.drawBitmap(coin, cspeed, 3*sy/4, null);
}
//score
Paint paint = new Paint();
paint.setColor(Color.BLUE);
paint.setAntiAlias(true);
paint.setFakeBoldText(true);
paint.setTextSize(25);
paint.setTextAlign(Align.LEFT);
canvas.drawText("Score :"+score, 3*sx/4, 20, paint);
//exit
canvas.drawBitmap(exit, 0, 0, null);
if(sound==1)
{
mp1.start();
mp1.setLooping(true);
}
else
{
mp1.stop();
}
//health
Paint myPaint = new Paint();
myPaint.setColor(Color.RED);
myPaint.setStrokeWidth(10);
myPaint.setAntiAlias(true);
myPaint.setFakeBoldText(true);
paint.setTextSize(25);
canvas.drawText("Health :"+health, 0, (sy/8)-5, myPaint);
canvas.drawRect(0, sy/8, health, sy/8+10, myPaint);
//game over
if(health<=0)
{
gameover=1;
mp1.stop();
sound=0;
//high score
editor.putInt("score", score);
editor.commit();
myPaint.setColor(Color.BLACK);
myPaint.setFakeBoldText(true);
canvas.drawText("GAME OVER", sx/2, sy/2, myPaint);
canvas.drawText("YOUR SCORE : "+score, sx/2, sy/4, myPaint);
canvas.drawText("RESTART", 91, 25, myPaint);
gameLoopThread.setPause(1);
canvas.drawBitmap(background, sx, sy, null);
}
// restart
if(reset==1)
{
gameLoopThread.setPause(0);
health=100;
score=0;
mp1.start();
}
canvas.drawBitmap(pause, (sx-25), 0, null);
}
}
这是游戏的循环class。
public class GameLoop extends Thread {
private GameView view;
static final long FPS = 10;
private boolean running = false;
boolean isPaused;
public GameLoop(GameView view) {
this.view = view;
}
public void setRunning(boolean run) {
running = run;
}
public void setPause(int i)
{
synchronized (view.getHolder())
{
if(i==0)
{
isPaused=false;
}
if(i==1)
{
isPaused = true;
}
}
}
@SuppressLint("WrongCall")
@Override
public void run() {
long ticksPS = 100;
long startTime = 0;
long sleepTime;
while (running) {
//pause and resume
if (isPaused)
{
try
{
this.sleep(50);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
else
{
Canvas c = null;
startTime = System.currentTimeMillis();
try {
c = view.getHolder().lockCanvas();
synchronized (view.getHolder())
{
view.onDraw(c);
}
}
finally
{
if (c != null)
{
view.getHolder().unlockCanvasAndPost(c);
}
}
}
sleepTime = ticksPS-(System.currentTimeMillis() - startTime);
try {
if (sleepTime > 0)
sleep(sleepTime);
else
sleep(10);
}
catch (Exception e) {}
}
}}
您需要手动停止音乐,您可以在onStop()
或onDestroy()
中调用mp1.stop()
,或在onBackPressed()
.
中使用
或尝试使用:
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
mp1.stop();
return super.onKeyDown(keyCode, event);
}
子类化 SurfaceView
和覆盖 SurfaceView.onDraw()
,很少有意义。
如果您将代码构造为具有 SurfaceView 的 Activity,事情会进行得更顺利,因为您需要处理 onPause()
和 onResume()
,并处理表面状态回调。如果您希望应用程序在关闭和返回、使用电源按钮关闭和打开设备等时正常工作,则需要提供标准的 Android 生命周期方法。
重写的 onDraw()
方法在 SurfaceView 的 View 部分而不是 Surface 上绘制,因此除非您想要覆盖,否则它没有意义。您可能不会注意到一个问题,因为只有当某些东西使视图无效时,它才会被视图层次结构调用。您需要做的就是将 onDraw()
更改为 doDraw()
并删除 @Override
,以便仅在您显式调用它时才调用它。 (如果您 想要覆盖 onDraw()
,那么您可能应该使用 custom view,而不是 SurfaceView。)
This article explains the interaction between the Activity and SurfaceView lifecycles. Grafika 提供了几个 SurfaceView 代码示例。例如,"multi-surface test" 提供了一个 Activity 使用 Canvas 渲染到 SurfaceView(实际上,不止一个)的示例。
我得到了解决方案,因为我将我的 class GameView extends SurfaceView 放在另一个 class Game extends Activity 中,使我能够使用 onBackPressed() 方法。
@Override
public void onBackPressed()
{
mp1.stop();
Intent i=new Intent(this,MainActivity.class);
startActivity(i);
}
感谢大家为解决我的问题所做的最大努力。
在我的 android 游戏中,当用户按下后退按钮时音乐不会停止,即使用户关闭游戏音乐仍在播放。 这是我的主要 class 游戏。 MediaPlayer mp1 用于播放音乐。
public class GameView extends SurfaceView{
Bitmap bmp,pause;
Bitmap background,kinfe,note1,appleimg,note2;
Bitmap run1;
Bitmap run2;
Bitmap run3;
Bitmap coin;
Bitmap exit;
private SurfaceHolder holder;
private int x = 0,y=0,z=0,delay=0,getx,gety,sound=1;
int show=0,sx,sy;
int cspeed=0,kspeed=0,gameover=0;
int score=0,health=100,reset=0;
int pausecount=0,volume,power=0,applerun=0,shieldrun=0;
@SuppressWarnings("deprecation")
@SuppressLint("NewApi")
public GameView(Context context)
{
super(context);
gameLoopThread = new GameLoop(this);
holder = getHolder();
holder.addCallback(new SurfaceHolder.Callback() {
@SuppressWarnings("deprecation")
@Override
public void surfaceDestroyed(SurfaceHolder holder)
{
//for stoping the game
gameLoopThread.setRunning(false);
gameLoopThread.getThreadGroup().interrupt();
}
@SuppressLint("WrongCall")
@Override
public void surfaceCreated(SurfaceHolder holder)
{
//for starting the game
gameLoopThread.setRunning(true);
gameLoopThread.start();
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format,int width, int height)
{
}
});
//getting the screen size
// Display display = getWindowManager().getDefaultDisplay();
// sx = display.getWidth();
// sy = display.getHeight();;
Display display = getWindowManager().getDefaultDisplay();
Point size = new Point();
display.getSize(size);
sx = size.x;
sy = size.y;
cspeed=sx/2;
kspeed=sx/2;
applerun=(3*sx/4);
shieldrun=sx/8;
background = BitmapFactory.decodeResource(getResources(), R.drawable.cold);
run1=BitmapFactory.decodeResource(getResources(), R.drawable.run1);
run2=BitmapFactory.decodeResource(getResources(), R.drawable.run2);
run3=BitmapFactory.decodeResource(getResources(), R.drawable.run3);
coin=BitmapFactory.decodeResource(getResources(), R.drawable.coin);
exit=BitmapFactory.decodeResource(getResources(), R.drawable.exit);
kinfe=BitmapFactory.decodeResource(getResources(), R.drawable.kinfe);
note1=BitmapFactory.decodeResource(getResources(), R.drawable.note1);
pause=BitmapFactory.decodeResource(getResources(), R.drawable.pause);
appleimg=BitmapFactory.decodeResource(getResources(), R.drawable.power);
note2=BitmapFactory.decodeResource(getResources(), R.drawable.note2);
exit=Bitmap.createScaledBitmap(exit, 25,25, true);
pause=Bitmap.createScaledBitmap(pause, 25,25, true);
appleimg=Bitmap.createScaledBitmap(appleimg, 25,25, true);
note2=Bitmap.createScaledBitmap(note2, sx,sy, true);
run1=Bitmap.createScaledBitmap(run1, sx/9,sy/7, true);
run2=Bitmap.createScaledBitmap(run2, sx/9,sy/7, true);
run3=Bitmap.createScaledBitmap(run3, sx/9,sy/7, true);
coin=Bitmap.createScaledBitmap(coin, sx/16,sy/24, true);
background=Bitmap.createScaledBitmap(background, 2*sx,sy, true);
//health dec
note1=Bitmap.createScaledBitmap(note1, sx,sy, true);
mp1=MediaPlayer.create(Game.this,R.raw.game);
jump=MediaPlayer.create(Game.this,R.raw.jump);
takecoin=MediaPlayer.create(Game.this,R.raw.cointake);
}
// on touch method
@Override
public boolean onTouchEvent(MotionEvent event) {
if(event.getAction()==MotionEvent.ACTION_DOWN)
{
show=1;
getx=(int) event.getX();
gety=(int) event.getY();
//exit
if(getx<25&&gety<25)
{
//high score
SharedPreferences pref = getApplicationContext().getSharedPreferences("higher", MODE_PRIVATE);
Editor editor = pref.edit();
editor.putInt("score", score);
editor.commit();
System.exit(0);
}
// restart game
if(getx>91&&gety<25)
{
if(health<=0)
{
gameLoopThread.setPause(0);
health=100;
score=0;
}
}
//pause game
if((getx>(sx-25)&&gety<25&&pausecount==0))
{
gameLoopThread.setPause(1);
mp1.stop();
pausecount=1;
}
else if(getx>(sx-25)&&gety<25&&pausecount==1)
{
gameLoopThread.setPause(0);
mp1.start();
pausecount=0;
}
}
return true;
}
@SuppressLint("WrongCall")
@Override
protected void onDraw(Canvas canvas)
{
//volume
SharedPreferences pref = getApplicationContext().getSharedPreferences("higher", MODE_PRIVATE);
Editor editor = pref.edit();
volume=pref.getInt("vloume", 0);
if(volume==0)
{
sound=0;
}
canvas.drawColor(Color.BLACK);
//background moving
z=z-10;
if(z==-sx)
{
z=0;
canvas.drawBitmap(background, z, 0, null);
}
else
{
canvas.drawBitmap(background, z, 0, null);
}
//running player
x+=5;
if(x==20)
{
x=5;
}
if(show==0)
{
if(x%2==0)
{
canvas.drawBitmap(run3, sx/16, 15*sy/18, null);
}
else
{
canvas.drawBitmap(run1, sx/16, 15*sy/18, null);
}
//kinfe hit
if(kspeed==20)
{
kspeed=sx;
health-=25;
canvas.drawBitmap(note1, 0, 0, null);
}
//power take
if(applerun==30)
{
applerun=3*sx;
health+=25;
canvas.drawBitmap(note2, 0, 0, null);
}
}
//power
applerun=applerun-10;
canvas.drawBitmap(appleimg, applerun, 15*sy/18, null);
if(applerun<0)
{
applerun=3*sx/4;
}
//kinfe
kspeed=kspeed-20;
canvas.drawBitmap(kinfe, kspeed, 15*sy/18, null);
if(kspeed<0)
{
kspeed=sx;
}
// for jump
if(show==1)
{
if(sound==1)
{
jump.start();
}
canvas.drawBitmap(run2, sx/16, 4*sy/7, null);
//score
if(cspeed<=sx/8&&cspeed>=sx/16)
{
if(sound==1)
{
takecoin.start();
}
cspeed=sx/2;
score+=10;
}
// jump-hold
delay+=1;
if(delay==3)
{
show=0;
delay=0;
}
}
//for coins
cspeed=cspeed-5;
if(cspeed==-sx/2)
{
cspeed=sx/2;
canvas.drawBitmap(coin, cspeed, 3*sy/4, null);
}
else
{
canvas.drawBitmap(coin, cspeed, 3*sy/4, null);
}
//score
Paint paint = new Paint();
paint.setColor(Color.BLUE);
paint.setAntiAlias(true);
paint.setFakeBoldText(true);
paint.setTextSize(25);
paint.setTextAlign(Align.LEFT);
canvas.drawText("Score :"+score, 3*sx/4, 20, paint);
//exit
canvas.drawBitmap(exit, 0, 0, null);
if(sound==1)
{
mp1.start();
mp1.setLooping(true);
}
else
{
mp1.stop();
}
//health
Paint myPaint = new Paint();
myPaint.setColor(Color.RED);
myPaint.setStrokeWidth(10);
myPaint.setAntiAlias(true);
myPaint.setFakeBoldText(true);
paint.setTextSize(25);
canvas.drawText("Health :"+health, 0, (sy/8)-5, myPaint);
canvas.drawRect(0, sy/8, health, sy/8+10, myPaint);
//game over
if(health<=0)
{
gameover=1;
mp1.stop();
sound=0;
//high score
editor.putInt("score", score);
editor.commit();
myPaint.setColor(Color.BLACK);
myPaint.setFakeBoldText(true);
canvas.drawText("GAME OVER", sx/2, sy/2, myPaint);
canvas.drawText("YOUR SCORE : "+score, sx/2, sy/4, myPaint);
canvas.drawText("RESTART", 91, 25, myPaint);
gameLoopThread.setPause(1);
canvas.drawBitmap(background, sx, sy, null);
}
// restart
if(reset==1)
{
gameLoopThread.setPause(0);
health=100;
score=0;
mp1.start();
}
canvas.drawBitmap(pause, (sx-25), 0, null);
}
}
这是游戏的循环class。
public class GameLoop extends Thread {
private GameView view;
static final long FPS = 10;
private boolean running = false;
boolean isPaused;
public GameLoop(GameView view) {
this.view = view;
}
public void setRunning(boolean run) {
running = run;
}
public void setPause(int i)
{
synchronized (view.getHolder())
{
if(i==0)
{
isPaused=false;
}
if(i==1)
{
isPaused = true;
}
}
}
@SuppressLint("WrongCall")
@Override
public void run() {
long ticksPS = 100;
long startTime = 0;
long sleepTime;
while (running) {
//pause and resume
if (isPaused)
{
try
{
this.sleep(50);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
else
{
Canvas c = null;
startTime = System.currentTimeMillis();
try {
c = view.getHolder().lockCanvas();
synchronized (view.getHolder())
{
view.onDraw(c);
}
}
finally
{
if (c != null)
{
view.getHolder().unlockCanvasAndPost(c);
}
}
}
sleepTime = ticksPS-(System.currentTimeMillis() - startTime);
try {
if (sleepTime > 0)
sleep(sleepTime);
else
sleep(10);
}
catch (Exception e) {}
}
}}
您需要手动停止音乐,您可以在onStop()
或onDestroy()
中调用mp1.stop()
,或在onBackPressed()
.
或尝试使用:
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
mp1.stop();
return super.onKeyDown(keyCode, event);
}
子类化 SurfaceView
和覆盖 SurfaceView.onDraw()
,很少有意义。
如果您将代码构造为具有 SurfaceView 的 Activity,事情会进行得更顺利,因为您需要处理 onPause()
和 onResume()
,并处理表面状态回调。如果您希望应用程序在关闭和返回、使用电源按钮关闭和打开设备等时正常工作,则需要提供标准的 Android 生命周期方法。
重写的 onDraw()
方法在 SurfaceView 的 View 部分而不是 Surface 上绘制,因此除非您想要覆盖,否则它没有意义。您可能不会注意到一个问题,因为只有当某些东西使视图无效时,它才会被视图层次结构调用。您需要做的就是将 onDraw()
更改为 doDraw()
并删除 @Override
,以便仅在您显式调用它时才调用它。 (如果您 想要覆盖 onDraw()
,那么您可能应该使用 custom view,而不是 SurfaceView。)
This article explains the interaction between the Activity and SurfaceView lifecycles. Grafika 提供了几个 SurfaceView 代码示例。例如,"multi-surface test" 提供了一个 Activity 使用 Canvas 渲染到 SurfaceView(实际上,不止一个)的示例。
我得到了解决方案,因为我将我的 class GameView extends SurfaceView 放在另一个 class Game extends Activity 中,使我能够使用 onBackPressed() 方法。
@Override
public void onBackPressed()
{
mp1.stop();
Intent i=new Intent(this,MainActivity.class);
startActivity(i);
}
感谢大家为解决我的问题所做的最大努力。