I would like to be able to detect collision from a class which uses thread in my activity.When collision is detected, new activity should be started.In my case, new activity is started only when collision is detected and I touch the screen.I want it to immediately start new activity without me having to touch it.I think the problem is in update() method(in activity class).I'm calling it in the wrong place.Any suggestions?
Thread class
private boolean Collision;
Thread t=null;
Pravougaonik pr;
SurfaceHolder holder;
boolean isRunning=false;
SnakeParts sp;
ZmijicaCrtanje zc;
public ZmijicaSV(Context context) {
super(context);
holder=getHolder();
pr=new Pravougaonik(context);
sp=new SnakeParts();
zc=new ZmijicaCrtanje();
Collision=false;
}
public void run()
{
Paint p=new Paint();
p.setColor(Color.BLUE);
p.setStyle(Paint.Style.FILL);
while(isRunning)
{
if(!holder.getSurface().isValid()) {
continue;
}
Canvas c=holder.lockCanvas();
c.drawColor(Color.BLACK);
sp.Draw(c);
pr.onDraw(c);
sp.update();
drawText(c);
holder.unlockCanvasAndPost(c);
try {
t.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void resume()
{
isRunning=true;
t=new Thread(this);
t.start();
}
public void pause()
{
isRunning=false;
while(true)
{
try {
t.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
break;
}
t=null;
}
public void drawText(Canvas canvas)
{
Paint paint=new Paint();
paint.setColor(Color.WHITE);
paint.setTextSize(50);
paint.setTypeface(Typeface.create(Typeface.DEFAULT,Typeface.BOLD));
canvas.drawText("Score:"+zc.getScore(),getWidth()-230,getHeight()-25,paint);
}
public boolean checkCollision()
{
if((sp.getHeadX()<-1)||(sp.getHeadX()>getWidth())||(sp.getHeadY()>getHeight())||(sp.getHeadY()<-1))
Collision=true;
return Collision;
}
}
Activity class
ZmijicaSV zmija;
private static int score=0;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
zmija=new ZmijicaSV(this);
zmija.setOnTouchListener(this);
setContentView(zmija);
}
#Override
protected void onPause() {
super.onPause();
zmija.pause();
}
#Override
protected void onResume() {
super.onResume();
zmija.resume();
}
#Override
public boolean onTouch(View v, MotionEvent event) {
boolean up=zmija.sp.isUp();
boolean right=zmija.sp.isRight();
boolean down=zmija.sp.isDown();
boolean left=zmija.sp.isLeft();
switch(event.getAction()) {
case MotionEvent.ACTION_DOWN:
if(up) {
zmija.sp.setUp(false);
zmija.sp.setRight(true);
update();
break;
}
if(right) {
zmija.sp.setRight(false);
zmija.sp.setDown(true);
update();
break;
}
if(down) {
zmija.sp.setDown(false);
zmija.sp.setLeft(true);
update();
break;
}
if(left) {
zmija.sp.setLeft(false);
zmija.sp.setUp(true);
update();
break;
}
}
return true;
}
public void update()
{
score++;
if(zmija.checkCollision())
startActivity(new Intent(ZmijicaCrtanje.this, GameOver.class));
}
public int getScore()
{
return score;
}
}
Related
I want to scroll RecyclerView with 2 or 3 item/sec when setOnLongClickListener on image view. I searched a lot and tried a countdown timer and handler to scroll RecyclerView by specific time. but without any success. any IDEA how to achieve this.
I tried this :
private Runnable runnable = new Runnable() {
#Override
public void run() {
if (minutesCurrentPosition >= 0 && minutesCurrentPosition < minutesArray.length) {
minutesCurrentPosition++;
if (minutesCurrentPosition == minutesArray.length) {
minutesCurrentPosition--;
}
if (minutesCurrentPosition < minutesArray.length) {
rvMinutes.scrollToPosition(minutesCurrentPosition);
}
}
}
};
ivMinutesUp.setOnLongClickListener(new View.OnLongClickListener() {
#Override
public boolean onLongClick(View v) {
handler.postDelayed(runnable,500);
return false;
}
});
ivMinutesUp.setOnLongClickListener(new View.OnLongClickListener() {
#Override
public boolean onLongClick(View v) {
handler.postDelayed(runnable,500);
return false;
}
});
ivMinutesUp.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View pView, MotionEvent pEvent) {
// We're only interested in when the button is released.
if (pEvent.getAction() == MotionEvent.ACTION_DOWN) {
// handler.postDelayed(runnable,300);
}
switch (pEvent.getAction()) {
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
handler.removeCallbacks(runnable);
break;
}
pView.onTouchEvent(pEvent);
return false;
}
});
I used this:
private void hoursGoUpFast() {
isButtonReleased = false;
if (thread != null) {
thread.interrupt();
thread = null;
}
thread = new Thread(new Runnable() {
#Override
public void run() {
for (int i = 0; i < hoursArray.length; i++) {
if (isButtonReleased) {
break;
} else {
try {
Thread.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
}
nextHour();
}
}
}
});
thread.start();
}
private void hoursGoDownFast() {
isButtonReleased = false;
if (thread != null) {
thread.interrupt();
thread = null;
}
thread = new Thread(new Runnable() {
#Override
public void run() {
for (int i = 0; i < hoursArray.length; i++) {
if (isButtonReleased) {
break;
} else {
try {
Thread.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
}
previousHour();
}
}
}
});
thread.start();
}
on click :
// hours long click
ivHoursUp.setOnLongClickListener(new View.OnLongClickListener() {
#Override
public boolean onLongClick(View v) {
hoursGoUpFast();
// handler.postDelayed(runnable, 500);
return false;
}
});
ivHoursDown.setOnLongClickListener(new View.OnLongClickListener() {
#Override
public boolean onLongClick(View v) {
hoursGoDownFast();
// handler.postDelayed(runnable, 500);
return false;
}
});
in my app i want to offer the user a option to set an animation as live wallpaper using WallpaeprService, also my app include a Radio player (playing in the backgroud) if app is open so you can navigate in other apps while music is playing.
my problem :
if live wallpaper is working and user try to close the app by (Swipe to exit / Recent Task),the music keeps playing although app is closed.
i tried to stop music like this ,but doesn't work :
public class MainActivity extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener {
#SuppressLint({"CommitPrefEdits", "Assert"})
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
startService(new Intent(this, KillNotificationService.class));
trackSelector = new DefaultTrackSelector();
loadControl = new DefaultLoadControl();
exoPlayer = ExoPlayerFactory.newSimpleInstance(new DefaultRenderersFactory(getApplicationContext()), trackSelector, loadControl);
MusicButton.setVisibility(View.INVISIBLE);
MusicButton.setOnCheckedChangeListener(new OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (Build.VERSION.SDK_INT > 15) {
if (started && MusicButton.isChecked()) {
started = false;
exoPlayer.setPlayWhenReady(false);
MusicButton.setChecked(true);
releaseAudioFocusForMyApp(MainActivity.this);
} else {
boolean gotFocus = requestAudioFocusForMyApp(MainActivity.this);
if (gotFocus) {
started = true;
exoPlayer.setPlayWhenReady(true);
MusicButton.setChecked(false);
}
}
} else {
if (started && MusicButton.isChecked()) {
started = false;
mediaPlayer.pause();
MusicButton.setChecked(true);
releaseAudioFocusForMyApp(MainActivity.this);
} else {
boolean gotFocus = requestAudioFocusForMyApp(MainActivity.this);
if (gotFocus) {
started = true;
mediaPlayer.start();
MusicButton.setChecked(false);
}
}
}
}
});
private void playRadio(String url) {
Uri audioUri = Uri.parse(url);
DefaultHttpDataSourceFactory dataSourceFactory = new DefaultHttpDataSourceFactory("ExoPlayerDemo");
ExtractorsFactory extractor = new DefaultExtractorsFactory();
MediaSource audioSource = new ExtractorMediaSource.Factory(dataSourceFactory).setExtractorsFactory(extractor).createMediaSource(audioUri);
exoPlayer.prepare(audioSource);
prepared = true;
exoPlayer.setPlayWhenReady(true);
exoPlayer.addListener(new Player.EventListener() {
#Override
public void onTimelineChanged(Timeline timeline, #Nullable Object manifest, int reason) {
}
#Override
public void onTracksChanged(TrackGroupArray trackGroups, TrackSelectionArray trackSelections) {
}
#Override
public void onLoadingChanged(boolean isLoading) {
}
#Override
public void onPlayerStateChanged(boolean playWhenReady, int playbackState) {
if (isPreparing && playbackState == ExoPlayer.STATE_READY) {
MusicButton.setVisibility(View.VISIBLE);
MusicButton.setChecked(true);
isPreparing = false;
isReady = true;
}
}
#Override
public void onRepeatModeChanged(int repeatMode) {
}
#Override
public void onShuffleModeEnabledChanged(boolean shuffleModeEnabled) {
}
#Override
public void onPlayerError(ExoPlaybackException error) {
}
#Override
public void onPositionDiscontinuity(int reason) {
}
#Override
public void onPlaybackParametersChanged(PlaybackParameters playbackParameters) {
}
#Override
public void onSeekProcessed() {
}
});
}
#Override
protected void onResume() {
super.onResume();
try {
MApplication.sBus.register(this);
} catch (Exception e) {
e.printStackTrace();
}
}
#Override
protected void onStop() {
super.onStop();
}
#Override
protected void onDestroy() {
super.onDestroy();
try {
MApplication.sBus.unregister(this);
} catch (Exception e) {
e.printStackTrace();
}
MApplication.sBus.post(PlaybackEvent.PAUSE);
}
#Override
protected void onStart() {
super.onStart();
}
#Subscribe
public void handlePlaybackEvent(PlaybackEvent event) {
switch (event) {
case PAUSE:
if (Build.VERSION.SDK_INT > 15) {
if (exoPlayer.getPlayWhenReady()) {
exoPlayer.setPlayWhenReady(false);
MusicButton.setChecked(true);
}
} else {
if (mediaPlayer.isPlaying()) {
mediaPlayer.pause();
MusicButton.setChecked(true);
}
}
break;
case PLAY:
if (Build.VERSION.SDK_INT > 15) {
if (!exoPlayer.getPlayWhenReady()) {
exoPlayer.setPlayWhenReady(true);
MusicButton.setChecked(false);
}
} else {
if (!mediaPlayer.isPlaying()) {
mediaPlayer.start();
MusicButton.setChecked(false);
}
}
break;
}
}
#Override
public void onPause() {
super.onPause();
}
}
}
problem solved by checking if live wallpaper are running in the backgroud or not:
#Override
protected void onDestroy() {
super.onDestroy();
try {
WallpaperManager wpm = WallpaperManager.getInstance(this);
WallpaperInfo info = wpm.getWallpaperInfo();
if (info != null && info.getPackageName().equals(this.getPackageName())) {
/*stop music*/
} else {
Log.d(TAG, "We're not running");
}
} catch (Exception e) {
e.printStackTrace();
}
}
I am following a tutorial I found at http://www.androidauthority.com/android-game-java-785331/
I just wanted a basic tutorial to get me started making games on android.
Here is the MainActivity.java
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
this.requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(new GameView(this));
}
}
Here is the Class Android Studio is claiming as abstract:
public class MainThread extends Thread {
private SurfaceHolder surfaceHolder;
private GameView gameView;
private boolean running;
public static Canvas canvas;
public MainThread(SurfaceHolder surfaceHolder, GameView gameView) {
super();
this.surfaceHolder = surfaceHolder;
this.gameView = gameView;
}
#Override
public void run() {
while (running) {
canvas = null;
try {
canvas = this.surfaceHolder.lockCanvas();
synchronized(surfaceHolder) {
this.gameView.update();
this.gameView.draw(canvas);
}
} catch (Exception e) {} finally {
if (canvas != null) {
try {
surfaceHolder.unlockCanvasAndPost(canvas);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
public void setRunning(boolean isRunning) {
running = isRunning;
}
}
And Here is the class that is attempting to instantiate the "abstract" class:
public class GameView extends SurfaceView implements SurfaceHolder.Callback {
public MainThread thread;
public GameView(Context context) {
super(context);
getHolder().addCallback(this);
thread = new MainThread(getHolder(), this);
setFocusable(true);
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
thread.setRunning(true);
thread.start();
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
boolean retry = true;
while (retry) {
try {
thread.setRunning(false);
thread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
retry = false;
}
}
public void update() {
}
}
I copied and pasted all the code from the tutorial. The only thing I can think of is the super class? or if there was a button I accidentally clicked when creating the class that made it abstract? I'm not sure what's wrong but I can't continue with the tutorial with errors. If anyone can see what's wrong or can maybe recommend another Android Studio Game tutorial I would very much appreciate it.
It's a problem with the naming. I had the exact same problem and merely changing it to 'GameThread' solved the problem
I'm making a game for android and i'm running into some problems with my thread when I exit my game and restart it again. I'm trying to interrupt the thread in the onPause function in MainActivity and resuming the thread in the start function in gamepanel with notify. It sometime works but it's not really pausing the game.
What is the proper way to implement the activity lifecycle while pausing a thread? Especially a game thread where game update functions shouldn't be called while the user is away.
public class MainActivity extends Activity {
private GamePanel gamepanel;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
//removes title
requestWindowFeature(Window.FEATURE_NO_TITLE);
//full screen
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
gamepanel = new GamePanel(this);
setContentView(gamepanel);
SoundHandler.setContext(this);
}
#Override
protected void onPause() {
super.onPause();
gamepanel.getThread().interrupt();
}
#Override
protected void onStop() {
super.onStop();
}
#Override
protected void onRestart() {
super.onRestart();
}
#Override
protected void onResume() {
super.onResume();
}
#Override
protected void onDestroy() {
super.onDestroy();
boolean retry = true;
while (retry) {
try {
gamepanel.getThread().setRunning(false);
gamepanel.getThread().join();
} catch (InterruptedException e) {
e.printStackTrace();
}
retry = false;
}
}
}
Gamepanel that extends surfaceView:
#Override
public void surfaceDestroyed (SurfaceHolder holder){}
/**create surface.
*
* #param holder
*/
#Override
public void surfaceCreated (SurfaceHolder holder){
//we can safely start the game loop
System.out.println("CREATING SURFACE");
loadingscreen = false;
start();
}
public void start() {
if(!mGameIsRunning) {
thread.start();
thread.setRunning(true);
mGameIsRunning = true;
} else {
thread.onResume();
}
}
Thread class
public class MainThread extends Thread {
private SurfaceHolder surfaceHolder;
private GamePanel gamePanel;
public boolean running = false;
public static Canvas canvas;
private long startTime;
private long fps = 1/30;
public MainThread(SurfaceHolder surfaceHolder, GamePanel gamePanel) {
super();
this.surfaceHolder = surfaceHolder;
this.gamePanel = gamePanel;
startTime = System.nanoTime();
}
#Override
public void run()
{
while(running) {
if((System.nanoTime() - startTime) / 1000000000> fps) {
canvas = null;
//try locking the canvas for pixel editing
try {
canvas = surfaceHolder.lockCanvas();
synchronized (surfaceHolder) {
this.gamePanel.update();
this.gamePanel.draw(canvas);
this.gamePanel.checkSpeed();
}
} catch (Exception e) {
} finally {
if (canvas != null) {
try {
surfaceHolder.unlockCanvasAndPost(canvas);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
gamePanel.surfaceDestroyed(surfaceHolder);
}
public void onResume(){
synchronized(this){
this.notify();
}
}
public void setRunning(boolean b)
{
running=b;
}
public boolean getRunning(){
return running;
}
}
There is no memory barrier around boolean running you can synchronize or use private volatile boolean running;. Then you need to call setRunning(false) somewhere to stop it, which you do not seem to do. These reasons are probably why your thread isn't quitting.
But I don't believe it makes any sense to render the game in a separate thread anyway. If you can't update & render super fast anyway, (e.g. 1/60th second or better) then moving it to a thread isn't going to help.
For some reason, whenever I increase "score" in 1st class(in OnTouch method) it won't update in my 2nd class when I call drawText method.The score, however, increases when I touch the screen, but calling zc.getScore() method in 2nd class stil shows 100.
ZmijicaSV zmija;
private int score=100;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
zmija=new ZmijicaSV(this);
zmija.setOnTouchListener(this);
setContentView(zmija);
}
#Override
protected void onPause() {
super.onPause();
zmija.pause();
}
#Override
protected void onResume() {
super.onResume();
zmija.resume();
}
#Override
public boolean onTouch(View v, MotionEvent event) {
boolean up=zmija.sp.isUp();
boolean right=zmija.sp.isRight();
boolean down=zmija.sp.isDown();
boolean left=zmija.sp.isLeft();
switch(event.getAction()) {
case MotionEvent.ACTION_DOWN:
if(up) {
zmija.sp.setUp(false);
zmija.sp.setRight(true);
update();
break;
}
if(right) {
zmija.sp.setRight(false);
zmija.sp.setDown(true);
update();
break;
}
if(down) {
zmija.sp.setDown(false);
zmija.sp.setLeft(true);
update();
break;
}
if(left) {
zmija.sp.setLeft(false);
zmija.sp.setUp(true);
update();
break;
}
}
return true;
}
public void update()
{
score++;
}
public int getScore()
{
return score;
}
.
Thread t=null;
Pravougaonik pr;
SurfaceHolder holder;
boolean isRunning=false;
SnakeParts sp;
ZmijicaCrtanje zc;
public ZmijicaSV(Context context) {
super(context);
holder=getHolder();
pr=new Pravougaonik(context);
sp=new SnakeParts();
zc=new ZmijicaCrtanje();
}
public void run()
{
Paint p=new Paint();
p.setColor(Color.BLUE);
p.setStyle(Paint.Style.FILL);
while(isRunning)
{
if(!holder.getSurface().isValid()) {
continue;
}
Canvas c=holder.lockCanvas();
c.drawColor(Color.BLACK);
sp.Draw(c);
pr.onDraw(c);
sp.update();
drawText(c);
holder.unlockCanvasAndPost(c);
try {
t.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void resume()
{
isRunning=true;
t=new Thread(this);
t.start();
}
public void pause()
{
isRunning=false;
while(true)
{
try {
t.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
break;
}
t=null;
}
public void drawText(Canvas canvas)
{
Paint paint=new Paint();
paint.setColor(Color.YELLOW);
paint.setTextSize(200);
canvas.drawText("Score:"+zc.getScore(),100,getHeight()-200,paint);
}
I can't know for sure, because you haven't included the name of the first class, but im quite sure the problem is that you are creating a new instance of the first class (probabaly ZmijicaCrtanje()) in your second class. This instance of ZmijicaCrtanje will be unaltered by the clicks registered in the first instance of ZmijicaCrtanje.
Two possible ways to fix this error are:
Make score a static variable.
Pass an instance of ZmijicaCrtanje to the constructor of the second class, ZmijicaSV, and set it equal to the global variable zc.
Good luck!