Files
PTS3/app/src/main/java/com/iutlaval/myapplication/Game/GameLogicThread.java
T

387 lines
14 KiB
Java

package com.iutlaval.myapplication.Game;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.util.Log;
import android.view.MotionEvent;
import android.widget.Toast;
import com.iutlaval.myapplication.Game.Cards.Card;
import com.iutlaval.myapplication.Game.Cards.CardRegistery;
import com.iutlaval.myapplication.GameActivity;
import com.iutlaval.myapplication.R;
import com.iutlaval.myapplication.Video.Drawables.DrawableBitmap;
import com.iutlaval.myapplication.Video.Drawables.DrawableCard;
import com.iutlaval.myapplication.Video.Drawables.DrawableSelfRemoving;
import com.iutlaval.myapplication.Video.Drawables.DrawableText;
import com.iutlaval.myapplication.Video.Renderer;
import com.iutlaval.myapplication.exception.UnrecognizedCard;
import java.io.IOException;
import java.io.InterruptedIOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OptionalDataException;
import java.lang.reflect.Constructor;
import java.net.Socket;
import java.net.SocketException;
import java.net.SocketTimeoutException;
public class GameLogicThread extends Thread{
public static final float BUTTON_Y_POS = 45F;
public static final int BUTTON_X_POS = 0;
public static final float BUTTON_X_SIZE = 20F;
public static final float BUTTON_Y_SIZE = 10F;
public static final String BUTTONTURN_DRAWABLE_NAME = "buttonturn";
private Context cont;
private Renderer renderer;
private boolean ready;
private TouchHandler touch;
private GameActivity gameActivity;
private NetworkDeck deck;
private Hand hand;
private Board board;
private boolean isYourTurn;
private boolean cancelled;
private String deckName;
private int mana=0;
private Communication coms;
//ces variable permette la comunication avec le thread android du tactile et le reseau en passant par ce thread
boolean requestDone=true;
DrawableCard requestCard=null;
int requestZone=-1;
boolean requestResult;
public GameLogicThread(GameActivity gameActivity, String deckName, Renderer renderer)
{
this.deckName=deckName;
Log.e("RESOLUTION:",""+GameActivity.screenWidth+"x"+GameActivity.screenHeight);
ready=false;
this.cont = gameActivity;
this.renderer = renderer;
board=new Board();
touch = new TouchHandler(renderer,this,gameActivity);
hand = new Hand();
this.gameActivity=gameActivity;
GameActivity.setGameEngine(this);
isYourTurn=false;
cancelled=false;
}
@Override
public void run() {
//pickDeck();
//loading textures
Bitmap bitmapYourTurn = BitmapFactory.decodeResource(renderer.getResources(),R.drawable.t_pb_your_turn);
Bitmap bitmapEnemyTurn = BitmapFactory.decodeResource(renderer.getResources(),R.drawable.t_pb_enemy_turn);
Bitmap bitmapButtonEnd = BitmapFactory.decodeResource(renderer.getResources(),R.drawable.t_btn_boutonfintour);
Bitmap bitmap= BitmapFactory.decodeResource(cont.getResources(), R.drawable.t_b_board_background);
//adding the background
renderer.addToDraw(new DrawableBitmap(bitmap, 0,0, "background", 100, 100 ));
//drawHandPreview();
//Rectangle pos = new Rectangle(0F,0F,100F,100F);
ready=true;
final String host = "0.tcp.ngrok.io";//192.168.43.251tcp://2.tcp.ngrok.io:
final int port = 13562;
try {
Socket client = new Socket(host, port);
coms= new Communication(client);
} catch (IOException e) {
Log.e("ERROR SERVER DEAD","srv");
//TODO display error and don't crash the game;
System.exit(1);
}
renderer.updateFrame();
//principe de fonctionnement : on attends une comande du server et on l'execute
//si quelquechose se passe alors c'est le server qu'il l'a dit
while(ready && !cancelled)
{
if(!requestDone && requestZone != -1 && requestCard != null)
{
try {//on allonge le delais car sinon on skip l'autorisation serveur
coms.setUnlimitedTimeOut();
} catch (SocketException e) {}
requestResult = onCardPlayed(requestCard,requestZone);
requestZone=-1;
requestCard=null;
Log.e("request","done");
requestDone=true;
}
try {
//on limite le temps du readobject pour eviter les blockaeg
coms.setLimitedTimeOut();
String serveurCmd = coms.recieve();
coms.setUnlimitedTimeOut();
if(!serveurCmd.equals("timeout"))Log.e("command",serveurCmd);
switch (serveurCmd)
{
case Command.GET_DECK:
coms.send(deckName);
String deckstr = coms.recieve();
deck = new NetworkDeck(deckstr,gameActivity.getBaseContext());
Log.e("got deck",deckstr);
break;
case Command.DRAW:
int nbcard = coms.recieveInt();
hand.pickCardFromDeck(deck,nbcard);
Log.e("picked",nbcard+"card");
drawHandPreview();
break;
case Command.YOURTURN:
isYourTurn=true;
renderer.addToDraw(new DrawableSelfRemoving(new DrawableBitmap(bitmapYourTurn,0,0,"yourTurn",100F,50F),1));
renderer.addToDraw(new DrawableBitmap(bitmapButtonEnd, BUTTON_X_POS, BUTTON_Y_POS, BUTTONTURN_DRAWABLE_NAME, BUTTON_X_SIZE, BUTTON_Y_SIZE));
break;
case Command.SETMANA:
renderer.removeToDraw("mana");
mana = coms.recieveInt();
renderer.addToDraw(new DrawableText("Mana : "+mana,90F,90F,"mana",10F,10F,100,800,200));
break;
case Command.ENEMYTURN:
//on update pas vu que l'instruction suivante va le faire
renderer.removeToDrawWithoutUpdate(BUTTONTURN_DRAWABLE_NAME);
renderer.addToDraw(new DrawableSelfRemoving(new DrawableBitmap(bitmapEnemyTurn,0,0,"enemyTurn",100F,50F),1));
break;
case Command.POPUP:
String recivedMessage = coms.recieve();
Toast popupToast = new Toast(gameActivity);
popupToast.setText(recivedMessage);
popupToast.setDuration(Toast.LENGTH_LONG);
popupToast.show();
Log.e("popup",recivedMessage);
break;
case Command.WIN:
//on termine la parite
cancelled = true;
Toast winToast = new Toast(gameActivity);
winToast.setText("bravo ! vous avez gagné");
winToast.setDuration(Toast.LENGTH_LONG);
winToast.show();
renderer.updateFrame();
break;
case Command.LOSE:
//on termine la partie
cancelled=true;
Toast loseToast = new Toast(gameActivity);
loseToast.setText("vous avez perdu!");
loseToast.setDuration(Toast.LENGTH_LONG);
loseToast.show();
break;
case Command.PING:
coms.send(Command.PONG);
break;
case Command.UPDATE:
renderer.updateFrame();
case Command.PUT_ENEMY_CARD:
int cardId = coms.recieveInt();
int zone = coms.recieveInt();
//on instancie la carte recu
Class<? extends Card> c = CardRegistery.get(cardId);
Constructor con = c.getConstructor(String.class, Context.class);
Card cardPlayed = (Card) con.newInstance("enemy"+zone,gameActivity);
cardPlayed.getDrawableCard().setOnBoard(true);
//ajout de la carte au rendu
cardPlayed.getDrawableCard().setCoordinates(((DrawableCard.getCardWith()+1)*zone+DrawableCard.getCardWith()),10F);
renderer.addToDraw(cardPlayed.getDrawableCard());
//ajout la card au terain
board.setEnemyCard(zone,cardPlayed);
break;
case "timeout":
//ceci est une erreur et non une commande elle se doit donc de ne rien faire
break;
default:
Log.e("UNKOWN COMMAND",serveurCmd);
}
}catch (SocketTimeoutException e){}
catch (InterruptedIOException e)
{
if(e.getStackTrace().length != 0)
{
e.printStackTrace();
Log.e("Stopping","dead thread");
}
}catch(IOException e)
{
}
catch (Exception e) {
Log.e("ERROR DURING COMS","SERVER DIED");
e.printStackTrace();
if(e instanceof OptionalDataException)
{
System.out.println(((OptionalDataException)e).eof);
}
break;
}
}
}
/**
* cette methode est UNIQUEMENT a bute de test elle ne sert a rien d'autre ne pas s'en servir
*/
private void drawHandPreview() {
int i = 0;
for(Card c : hand.getHand())
{
renderer.addToDraw(c.getDrawableCard());
renderer.moveToDraw(i* DrawableCard.getCardWith(),90F,c.getDrawableCard().getName());
i++;
}
}
/**
* cette evenement est appelé par le touchHandler et permet d'envoyer au serveur le fait qu'un carte a été jouer
* CE CODE CONTIEN DE l'ACCES RESEAU QUI N'APPARTIEN QU'A CE THREAD IS DOIT RESTER PRIVE
* @param card la carte jouer
* @param zone ou elle a été joué sur le terrain
* @return retourne si la carte a put être jouer
*/
private boolean onCardPlayed(DrawableCard card,int zone)
{
if(isYourTurn)
{
try {
//on veut jouer une carte
coms.send(Command.PUT_CARD);
//on lui dit quelle caret on veut
int cardId = CardRegistery.indexOf(card.getCard());
if (cardId == -1) {
coms.send("CLIENT REGISTRY ERROR");
throw new UnrecognizedCard();
}
coms.send(cardId);
coms.send(zone);
Log.e("waiting","for ok");
if (coms.recieve().equals(Command.OK)) {
board.setCard(zone, card.getCard());
return true;
}
}catch (Exception e)
{
e.printStackTrace();
}
}
return false;
}
protected synchronized boolean setOnCardPlayedRequest(DrawableCard card,int zone)
{
//on ne peut pas avoir 2 requette simultané
if(!requestDone)return false;
this.requestCard=card;
this.requestZone=zone;
requestDone=false;
//on attends la fin de la requette
while(!requestDone) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return requestResult;
}
/**
* cette fonction est appeller a chaque fin de frame
* CETTE FONCTION A UN IMPACT DIRECT SUR LES FPS ELLE SE DOIT D'être OPTIMAL
* TOUT CALCUL REDONDANT CE DOIT D'AVOIR ETE PRE FAIT
*
* TOUT APELLE DE CETTE FONCTION SE DOIT D'ÊTRE PROTEGER PAR isReady()
*
* /!\ renderer.updateFrame(); va forcer le system a redessiner l'afficher qui ensuite reappelera onFrameDoneRendering() ce qui peut causer si le updateFrame() n'est pas proteger
* une utilisation de la batterie massive
*/
//TODO : supprimer cette fonction si on a rien a en faire
public void onFrameDoneRendering()
{
}
/**
* retourne vrai sir le moteur est pret a avoir sont evenemnt onFrameDoneRendering d'appeler
* @return
*/
public boolean isReady() {
return ready;
}
/**
* délegue l'evenement directement au touch Handler
* @param event
*/
public void onTouchEvent(MotionEvent event) {
if(isReady())touch.onTouchEvent(event);
}
public boolean isYourTurn() {
return isYourTurn;
}
public Board getBoard() {
return board;
}
/**
* cette fonction a pour rôle de kill le thread
* vu que Thread.destroy() est déprecier c'est la seul methode possible;
*/
public void terminate() {
ready=false;
try {
if(coms != null)coms.close();
} catch (IOException e) {}
cancelled=true;
interrupt();
}
public void onEndTurnButtonPushed() {
if(isYourTurn)
{
try {
Log.e("TURN","PASSED");
coms.send(Command.PASS_TURN);
} catch (IOException e) {
e.printStackTrace();
}
}else{
Toast t = new Toast(gameActivity);
t.setText("IT'S NOT YOUR TURN BE PATIENT");
t.setDuration(Toast.LENGTH_SHORT);
t.show();
}
}
}