Subversion Repositories QTron

Rev

Blame | Compare with Previous | Last modification | View Log | RSS feed

#include <QtCore/QCryptographicHash>
#include <QtCore/QStringList>

#include <QtNetwork/QHostAddress>

#include "client.hpp"

#include <iostream>

using namespace std;

Client::Client(int sd) :
    QThread()
{
    connected = true;
   
    socket = new QTcpSocket(this);
    socket->setSocketDescriptor(sd);
   
    peerAddress = socket->peerAddress().toString();
   
    colourRed = -1;
    colourGreen = -1;
    colourBlue = -1;
   
    playing = false;
   
    playedGo = false;
}

Client::~Client()
{
    cout << ":: Deleted Connection: " << peerAddress.toStdString() << endl;
   
    if (connected)
    {
        socket->disconnectFromHost();
    }
   
    delete socket;
}

bool Client::isConnected()
{
    return connected;
}

void Client::run()
{
    cout << ":: Running Thread" << endl;
    doGo();
}

bool Client::doGo()
{
    playedGo = false;
    bool p = false;
   
    checkDisconnected();
   
    if (connected)
    {
        if (playing && !crashed)
        {
            int start = time(0);
            updatePos();
            crashed = hasCollided(clients);
           
            sendText("G");
            if (socket->waitForReadyRead(2000))
            {
                p = checkReadyRead();
                if (!playedGo)
                {
                    socket->disconnectFromHost();
                }
            }
            else
            {
                p = true;
                socket->disconnectFromHost();
            }
                       
            int finish = time(0);
            int delta = finish - start;
           
            cout << ":: " << name.toStdString() << ": " << delta << endl;
           
           
        }
        else
        {
            while (socket->canReadLine())
            {
                checkReadyRead();
            }
           
            checkPlayable();
           
            p = true;
        }
    }
   
    playedGo = p;
   
    return true;
}

void Client::checkDisconnected()
{
    if (socket->state() == QAbstractSocket::UnconnectedState)
    {
        connected = false;
    }
    else
    {
        if (socket->waitForDisconnected(10))
        {
            connected = false;
        }
    }
}

bool Client::checkReadyRead()
{
    bool playedGo = false;

    if (socket->canReadLine())
    {
        QByteArray data = socket->readLine();
        QString line = data.trimmed();
       
        cout << ":: " << name.toStdString() << ": " << line.toStdString() << endl;
       
        if (line == "DISCONNECT")
        {
            socket->disconnectFromHost();
        }
        else if (line.startsWith("NAME "))
        {
            name = line.remove(0, 5);
        }
        else if (line.startsWith("CHAT "))
        {
            QString text = line.remove(0, 5);
            emit chat(name, text);
            playedGo = true;
        }
        else if (line.startsWith("COLOUR "))
        {
            QStringList list = line.split(" ");
            if (list.count() == 4)
            {
                colourRed = list[1].toInt();
                colourGreen = list[2].toInt();
                colourBlue = list[3].toInt();
            }
        }
        else if (line == "N")
        {
            playedGo = true;
        }
        else if (line == "L")
        {
            angle -= 90;
            playedGo = true;
        }
        else if (line == "R")
        {
            angle -= 90;
            playedGo = true;
        }
        else if (line == "A")
        {
            //if (speed < 2.0)
            //{
            //    speed += 0.1;
            //}
            playedGo = true;
        }
        else if (line == "D")
        {
            //if (speed > 0.2)
            //{
            //    speed -= 0.1;
            //}
            playedGo = true;
        }
    }
   
    return playedGo;
}

void Client::checkPlayable()
{
    if (!name.isEmpty())
    {
        if (colourRed != -1)
        {
            if (colourGreen != -1)
            {
                if (colourBlue != -1)
                {
                    playing = true;
                }
            }
        }
    }
}

void Client::updatePos()
{
    if (angle >= 360)
    {
        angle -= 360;
    }
    if (angle <= -90)
    {
        angle += 360;
    }
   
    if (angle == 0)
    {
        y -= speed;
    }
    else if (angle == 180)
    {
        y += speed;
    }
    else if (angle == 90)
    {
        x += speed;
    }
    else if (angle == 270)
    {
        x -= speed;
    }
   
    linePoints.append(QPoint(x, y));
}

void Client::reset()
{
    x = rand() % 800;
    y = rand() % 600;
   
    int a = rand() % 4;
    angle = a * 90;
   
    speed = 1.0;
   
    linePoints.clear();
    linePoints.append(QPoint(x, y));
   
    crashed = false;
   
    sendText("RESET");
}

bool Client::hasCollided(QList<Client *> clients)
{
    int i = linePoints.count() - 1;
    if(linePoints[i-1].x() < 0 || linePoints[i-1].x() > 800 || linePoints[i-1].y() < 0 || linePoints[i-1].y() > 600)
        return true;
    if(linePoints[i].x() < 0 || linePoints[i].x() > 800 || linePoints[i].y() < 0 || linePoints[i].y() > 600)
        return true;
    int j;

    foreach (Client *bike, clients)
    {
        for(j = 0; j < bike->linePoints.count() - 2; j++)
        {
            if(!(bike->linePoints[j].x() == bike->linePoints[j+1].x() && linePoints[i].x() == linePoints[i-1].x()) && !(bike->linePoints[j].y() == bike->linePoints[j+1].y() && linePoints[i].y() == linePoints[i-1].y()))
            {

                // If not parallel
                if(bike->linePoints[j].x() == bike->linePoints[j+1].x())
                {
                    // x equal

                    if (((linePoints[i-1].x() > bike->linePoints[j].x()) && (linePoints[i].x() < bike->linePoints[j].x())) || ((linePoints[i-1].x() < bike->linePoints[j].x()) && (linePoints[i].x() > bike->linePoints[j].x())))
                    {
                        if((sign(linePoints[i-1].y() - bike->linePoints[j].y()) != sign(linePoints[i-1].y() - bike->linePoints[j+1].y())))
                            return true;
                    }
                }
                else if(bike->linePoints[j].y() == bike->linePoints[j+1].y())
                {

                    if (((linePoints[i-1].y() > bike->linePoints[j].y()) && (linePoints[i].y() < bike->linePoints[j].y())) || ((linePoints[i-1].y() < bike->linePoints[j].y()) && (linePoints[i].y() > bike->linePoints[j].y())))
                    {
                        if((sign(linePoints[i-1].x() - bike->linePoints[j].x()) != sign(linePoints[i-1].x() - bike->linePoints[j+1].x())))
                            return true;
                    }
                }
            }
        }
    }
    return false;
}

void Client::sendText(QByteArray text)
{
    if (connected)
    {
        write(text);
        write("\n");
    }
}

void Client::write(QByteArray text)
{
    if (connected)
    {
        socket->write(text);
        socket->flush();
    }
}

int sign(float x)
{
    if (x > 0)
    {
        return 1;
    }
   
    if (x < 0)
    {
        return -1;
    }
   
    return 0;
}