387 lines
14 KiB
Java
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();
|
|
}
|
|
}
|
|
}
|