Computer Turn, Wait and delay in Android 2.2 - android

I am making a Poker game in Android, I have made some TextViews and ImageViews to show on the cards of player and computer and the Community cards..
Now the problem is that when a player takes its turn after that it calls a method of call_computer and all the implementation of the computer executes but there is no delay between the player and computer turn.
So a player takes its turn and just after that a card is displayed. What I want is after the player turn, the computer should wait for a while and then it would display a text:
"Computer Selects Check/Fold/Raise"
and then according to the action selected the card should be displayed....
I have called a call_computer function just after the player's turn and action performed.. and I put that method in a new thread and put a sleep of 5 sec, but still no success...

You could use a call to postDelayed(Runnable, int):
long DELAY_IN_MSEC = 1000; // 1s
postDelayed(new Runnable() {
#Override
public void run() {
// call_computer();
}
}, DELAY_IN_MSEC);

Related

TBMP not getting game updates unless it is player's turn

I am trying to include TBMP into my Mahjong game and this issue has been stuck with me for a few months now, and I am no closer to resolving it.
I have four players in a game and the game progressing counterclockwise. So imagine you have four players at a table:
Player 3
---------------------------
Player 4 | | Player 2
---------------------------
Player 1
Now Player 1 takes a turn, the data is pushed via JSON into the game data, and Player 2 gets notified that it is his turn. Player 3 and 4 also get a notification that a match update has occurred, but when they query the game data, it returns the stale game information, unless it becomes their turn, then they get the accurate and current game data.
I would like all players to be updated after every turn, rather than getting all the updates in one go when it becomes their turn.
I register an update listener as follows:
mTurnBasedMultiplayerClient.registerTurnBasedMatchUpdateCallback(mMatchUpdateCallback);
I have a function that processes the update as follows:
private TurnBasedMatchUpdateCallback mMatchUpdateCallback = new TurnBasedMatchUpdateCallback() {
#Override
public void onTurnBasedMatchReceived(#NonNull TurnBasedMatch turnBasedMatch) {
int turnStatus = turnBasedMatch.getTurnStatus();
// OK, it's active. Check on turn status.
switch (turnStatus) {
case TurnBasedMatch.MATCH_TURN_STATUS_MY_TURN:
MainActivity.mTurnData =
MahjongTurn.unpersist(turnBasedMatch.getData());
setLocalGameValues();
state = GameState.Playing;
return;
case TurnBasedMatch.MATCH_TURN_STATUS_THEIR_TURN:
MainActivity.mTurnData =
MahjongTurn.unpersist(turnBasedMatch.getData());
setLocalGameValues();
state = GameState.MultiWait;
return;
}
}
#Override
public void onTurnBasedMatchRemoved(#NonNull String matchId) {
game.showToast("A match was removed.");
state = GameState.MultiWait;
return;
}
};
Anyway, the listener is registered correctly and I can see that my listener gets called, but the call to turnBasedMatch.getData() only returns the correct game data when it is also the player's turn.
So Player 4 gets the updates from Player 1, Player 2 and Player 3 only when it becomes his turn. He gets notified that there is an update to the match, but has no way of knowing what the current game data looks like.
Is this the way it is meant to work? Am I doing something wrong?
One workaround for this is to store all the turns inside the message data. This way, I can treat the game data like a Message Queue and replay everything up to the current turn. This is not ideal, but it works.

Timer anti cheat technique

Let's say I'm developing a game and there exists such thing as respawn. The user may respawn after 15 minutes. Is there any common practice to avoid time cheating? I mean, nothing can stop user from changing system time and set it to future. I know, partially this can be resolved by using server side, but nothing can stop user from disabling the network at all.
PS. the game is cross platform so the solution is interesting for both antroid and iOS. PS2. I know a couple of games that have the solution.
For something like this you could simply start your own timer completely separate from the system time. If you start a 15 minute countdown when a player dies they won't be able to modify your internal timer. I'm not as familiar with iOS dev (NSTimer looks like a possibility) but I know in Android it's as easy as:
// create 30 second internal countdown timer
new CountDownTimer(30000, 3000) {
public void onTick(long millisUntilFinished) {
// store time remaining in database every 3 seconds in case user exits the game
dbHelper.updateDeathTimer(millisUntilFinished);
}
public void onFinish() {
// player respawns now
}
}.start();
To combat the issue of players closing the game I would suggest you also set up your internal timer to cache its' current state in the database at a regular interval, say every 30 seconds or so if you were going to stick with a 15 minute timer.
Below is some psuedocode for what it might look like when a player exits the game while they are dead and our respawn timer was still in progress.
// When game resumes check database and begin updated death timer if necessary
onGameResume() {
if(dbHelper.isUserDead()) {
// resume respawn timer
new CountDownTimer(dbHelper.getRespawnTime(), 15000) {
public void onTick(long millisUntilFinished) {
// store time remaining in database every 15 seconds in case user exits the game
dbHelper.updateDeathTimer(millisUntilFinished);
}
public void onFinish() {
// player respawns now
}
}.start();
}
}
You can store the time of the event (spawn in your case), and then run a timeIntervalSinceReferenceDate against it and see if it exceeds your limit (15 minutes).
The risk on the iOS side is that the app goes to the background and the timers stop.
It's not actually the answer, but just an idea.
What if we use tickCount? Each operating system has this property.
For instance, android.os.SystemClock.elapsedRealtime() in Android and
[NSProcessInfo processInfo].systemUptime in iOS
They should give required values.

How do I call/schedule a function after an action is completed?

I am working on a multiplayer domino game where a device acts as a host and makes the decisions for the rest of the players. So far, it works great when everyone has a good connection, but once you introduce some latency, all things go to heck. One problem I'm having is that I need to move some sprites around on command. When everyone has played, the host device will send a message out that tells the remote players who won the hand. After that message is sent, the winner can make the next move.
I move the dominoes to the right using:
void HelloWorld::onChatReceived(AppWarp::chat chatevent)
{
if (chatprefix.compare("_determinewinner_")==0)
{
//chatstring in this case is the playerID who won the hand
MultiPlayerdetermineTrickWinner(atoi(chatstring.c_str()));
}
}
void HelloWorld::MultiPlayerdetermineTrickWinner(int winningplayer)
{
...
for (int i = 0; i <marray_table->count(); ++i)
{
Domino *marray_table_tile = (Domino *)(marray_table->objectAtIndex(i));
CCMoveTo *translate = CCMoveTo::create(0.1f,ccp(pos_x,pos_y));
CCRotateBy *rotleft=CCRotateBy::create(0.1f, 90*int_rotate);
marray_table_tile->runAction(CCSequence::create(translate,rotleft,NULL));
}
...
}
When the players selects a tile, I call
CCMoveTo *translate = CCMoveTo::create(0.1f,ccp(pos_x,pos_y));
selectedtile->runAction(CCSequence::create(translate,NULL));
marray_table->addObject(selectedtile);
The problem I have is, that there are times when the latency is so bad, that the runaction never completes and the tiles don't actually make it to their final position. For instance, if the host player won the hand and makes their move before the other players received the "determinewinner" message. So short of having all the players tell the host when it can move on, how do I schedule a function to occur only after all actions have been completed?

Detecting buffering error (or timeout) Android MediaPlayer - Use a Timer for timeout?

Apparently no exception is thrown so that I can recognize an error while buffering streaming audio content. For example I've disconnected my router and the app will continue to try to buffer the whole time. When I reconnect then it completes buffering and continues even after being disconnected for over a minute!
So the problem is I can't let my user sit there for that long without considering that a problem. What is the proper method to detect a buffering problem with the Android media player?
I'm thinking about using a Timer for a timeout. I'll start probably with 15 seconds (using a proxy I tested a 5kbps connection, which would be a worst case, was able to start playing in 6-10 seconds, so I think 15 seconds would be a reasonable timeout period). Does this sound like a good plan? If so should I create a new Timer with each buffer attempt or should I keep the same Timer throughout the lifetime of the playback service?
So basically I'm asking two questions:
1) What's the proper way to detect if a buffer is having a problem? Is there a listener I'm overlooking? I've tried MediaPlayer.OnErrorListener of course that doesn't fire in my tests. My conclusion is I have to have a timeout to detect a buffering error.
2) If I'm correct on number one, what is the proper way to use a Timer? Create one with each buffer attempt or reuse the same one? EDIT Also should I restart the (or cancel and create a new) Timer onBufferUpdate? With the onBufferUpdate listener I should know that some data is coming back so should maybe reset the timer with that.
From your question, I understand that the primary objective is to detect a situation if your player is stalled due to buffering and take some actions thereof. To handle this situation, I feel that the following 2 listeners may be helpful to identify the same.
MediaPlayer.onBufferingUpdate would provide the timely progress of the buffering. So, if there are 2 callbacks with same percent value, this could be an indication of potential buffering.
There is another listener MediaPlayer.onInfoListener which has some specific events which could be of interest to you. On this listener, if the what is MEDIA_INFO_BUFFERING_START, this would indicate that the player is pausing the playback for buffering i.e. trigger for your logic. Similarly MEDIA_INFO_BUFFERING_END indicates the restart of the playback after filling the buffers.
You Should see this article. The mediaplayer has a ErrorListener to get any error.
http://developer.android.com/reference/android/media/MediaPlayer.OnErrorListener.html
int count=40;//for 40 seconds to wait for buffering after it will finish the activity
//boolean timeoutflag=false;
timeout = new Handler(Looper.getMainLooper()) {
#Override
public void handleMessage(Message msg) {
System.out.println("value of count="+msg.getData().getLong("count"));
if (msg.getData().getBoolean("valid")) {
if (msg.getData().getLong("count") == 0 && !timeoutflag)
{
if (pDialog != null && pDialog.isShowing())
{
try
{
pDialog.dismiss();
}catch(Exception e)
{
e.printStackTrace();
}
}
Toast.makeText(getApplicationContext(),
"Unable To Load This Video", Toast.LENGTH_LONG).show();
finish();
} else {
}
}
}
};
timeout.postDelayed(null, 0);
new Thread(new Runnable() {
#Override
public void run() {
while (count > 0) {
try {
Thread.sleep(1020);
} catch (Exception e) {
}
Message msg = new Message();
Bundle b = new Bundle();
b.putBoolean("valid", true);
b.putLong("count", --count);
msg.setData(b);
timeout.sendMessage(msg);
}
}
}).start();
// set timeoutflag=true; in setOnPreparedListener of video view
For buffering during preparation, you have to set your own timer which calls player.reset() after some interval. This puts the player back into init state.
For buffering after preparation (during play) you have to monitor getPosition(). If it falls behind some maximum, call reset(). This allows you to set an experience threshold for your playback. Handles not only failed connection, but also choppy connection.
Best solution is to not use MediaPlayer. Use a public VLC derivative instead. MP has too many internalized private design limitations requiring horrible workarounds (eg. CANT add codecs). RTFM gives you false hope in this case.
Unless you are doing a very straight laced android app, don't depend on any android api. Some opensource substitutes are better supported, and for good reason.
(really bandeely olly jolly satisfying editorial rant deleted)

Problem synchronizing sound and display

I have an app that plays an mp3 file and I'm trying to update a custom field in synchrony with certain times we have tabulated for the sound playback (kind of like a karaoke effect). I'm using a Handler to schedule these updates. In my custom field class, I define a Runnable that is supposed to run the update at the right time:
private final Runnable mTrigger = new Runnable() {
#Override
public void run() {
int now = mPlayer.getCurrentPosition();
if (mState == STATE_PLAYING && mUpdateAction != null) {
if (mTriggerTime - now > MAX_PREMATURE_TRIGGER) {
// Sound is lagging too much; reschedule this trigger
mHandler.postDelayed(this, mTriggerTime - now);
} else {
// Run the update
mUpdateAction.run();
}
}
}
};
When I call mPlayer.start() I schedule the first update by calling mHandler.postDelayed(mTrigger, timeToFirstUpdate). Each update action decides what the next update will be and schedules it (by calling mHandler.postDelayed(mTrigger, timeToNextUpdate)). The updates times are typically a few hundred milliseconds apart.
The problem is that, while some updates are happening promptly at the scheduled times, others can be delayed by 200 milliseconds or more, which is quite noticeable to the user. I'm not doing anything in my app between these updates other than playing the sound. (No background worker threads; no other display updates.) The delays appear to be random and vary considerably each time through.
I didn't think that the timing for postDelayed would be this imprecise! I don't know if this is an emulator issue or a problem with my approach. Does sound playback screw up the timing of the UI thread loop? Should I move the timing into a background thread (and is it safe to call mPlayer.getCurrentPosition() from a background thread)? Something else?
After much experimenting, it seems like the problem is the emulator. When I ran everything on a speedier workstation, the problem seems to have gone away.

Categories

Resources