diff options
author | Tomaz Noleto <tomaz.noleto@openbossa.org> | 2011-10-25 17:13:31 +0200 |
---|---|---|
committer | Tomaz Noleto <tomaz.noleto@openbossa.org> | 2011-10-25 17:14:32 +0200 |
commit | 5c722451a2bb6702c628a1b7c1468160fc01734a (patch) | |
tree | bf5487fc0f82a0de0d6b7ed38088538acfc1389a /chicken-wranglers/src | |
parent | d7d612ff07253b1cc1ffa4be489a8d90ec750af6 (diff) |
chicken-wranglers: Initial commit
Signed-off-by: Tomaz Noleto <tomaz.noleto@openbossa.org>
Diffstat (limited to 'chicken-wranglers/src')
112 files changed, 13967 insertions, 0 deletions
diff --git a/chicken-wranglers/src/ai/ai.pri b/chicken-wranglers/src/ai/ai.pri new file mode 100644 index 0000000..8f9dd78 --- /dev/null +++ b/chicken-wranglers/src/ai/ai.pri @@ -0,0 +1,9 @@ +PATH = $$PWD + +HEADERS += \ + $$PATH/matchai.h \ + $$PATH/graph.h + +SOURCES += \ + $$PATH/matchai.cpp \ + $$PATH/graph.cpp diff --git a/chicken-wranglers/src/ai/graph.cpp b/chicken-wranglers/src/ai/graph.cpp new file mode 100644 index 0000000..34c61c8 --- /dev/null +++ b/chicken-wranglers/src/ai/graph.cpp @@ -0,0 +1,129 @@ +/**************************************************************************** +** +** This file is a part of QtChickenWranglers. +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).* +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +** FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +** COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +** BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +** ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +** POSSIBILITY OF SUCH DAMAGE." +** +****************************************************************************/ + + +#include "graph.h" + +Node::Node(QObject *parent) + : QObject(parent), data(Node::Empty), rank(0), + chickenCount(0), pos(0, 0), direction(Node::Stop) +{ + neighbor[Node::Stop] = this; + neighbor[Node::Up] = this; + neighbor[Node::Down] = this; + neighbor[Node::Right] = this; + neighbor[Node::Left] = this; +} + +Global::Direction Node::neighborDirection(Node::Neighbor neighbor) +{ + switch (neighbor) { + case Node::Up: + return Global::DirectionUp; + case Node::Down: + return Global::DirectionDown; + case Node::Right: + return Global::DirectionRight; + case Node::Left: + return Global::DirectionLeft; + default: + return Global::DirectionStop; + } +} + +Node::Neighbor Node::directionNeighbor(Global::Direction direction) +{ + switch (direction) { + case Global::DirectionUp: + return Node::Up; + case Global::DirectionDown: + return Node::Down; + case Global::DirectionRight: + return Node::Right; + case Global::DirectionLeft: + return Node::Left; + default: + return Node::Stop; + } +} + +Graph::Graph(QSize size, QObject *parent) + : QObject(parent), m_size(size) +{ + initMatrix(); +} + +Node *Graph::node(QPoint pos) +{ + if (pos.y() < m_size.height() && pos.x() < m_size.width() + && pos.y() >= 0 && pos.x() >= 0) { + return m_matrix[pos.y()][pos.x()]; + } + + return 0; +} + +void Graph::initMatrix() +{ + if (!m_size.height() || !m_size.width()) + return; + + // FIXME: Better way to alloc the matrix + for (int row = 0; row < m_size.height(); row++) + for (int column = 0; column < m_size.width(); column++) + m_matrix[row][column] = new Node(this); + + for (int row = 0; row < m_size.height(); row++) { + for (int column = 0; column < m_size.width(); column++) { + m_matrix[row][column]->pos = QPoint(column, row); + + if (row > 0) + m_matrix[row][column]->neighbor[Node::Up] = m_matrix[row - 1][column]; + if (column > 0) + m_matrix[row][column]->neighbor[Node::Left] = m_matrix[row][column - 1]; + if (row < m_size.height() - 1) + m_matrix[row][column]->neighbor[Node::Down] = m_matrix[row + 1][column]; + if (column < m_size.width() - 1) + m_matrix[row][column]->neighbor[Node::Right] = m_matrix[row][column + 1]; + } + + } +} diff --git a/chicken-wranglers/src/ai/graph.h b/chicken-wranglers/src/ai/graph.h new file mode 100644 index 0000000..322b79f --- /dev/null +++ b/chicken-wranglers/src/ai/graph.h @@ -0,0 +1,114 @@ +/**************************************************************************** +** +** This file is a part of QtChickenWranglers. +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).* +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +** FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +** COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +** BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +** ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +** POSSIBILITY OF SUCH DAMAGE." +** +****************************************************************************/ + + +#ifndef GRAPH_H +#define GRAPH_H + +#include <QtCore/QList> +#include <QtCore/QObject> +#include <QtCore/QPair> +#include <QtCore/QPoint> +#include <QtCore/QSize> + +#include "global.h" + +class Node : public QObject +{ + Q_OBJECT + +public: + enum Neighbor { + Right, + Left, + Up, + Down, + Stop, + MAX_NEIGHBOR + }; + + enum Data { + Empty, + Chicken, + Player, + Hencoop + }; + + explicit Node(QObject *parent = 0); + + bool isEmpty() { return data == Node::Empty; } + bool isChicken() { return data == Node::Chicken; } + bool isPlayer() { return data == Node::Player; } + bool isHencoop() { return data == Node::Hencoop; } + bool isScape() { return !isPlayer() && !isHencoop(); } + bool isSafe() { return !rank; } + void emitChickenEntered() { emit chickenEntered(chickenCount); } + + static Global::Direction neighborDirection(Node::Neighbor); + static Node::Neighbor directionNeighbor(Global::Direction); + + Node *neighbor[MAX_NEIGHBOR]; + Data data; + int rank; + int chickenCount; + QPoint pos; + Node::Neighbor direction; + +signals: + void chickenEntered(int numChickens); +}; + +class Graph : public QObject +{ + Q_OBJECT + +public: + explicit Graph(QSize size, QObject *parent = 0); + Node *node(QPoint pos); + +private: + void initMatrix(); + + QSize m_size; + Node *m_matrix[20][20]; +}; + +#endif diff --git a/chicken-wranglers/src/ai/matchai.cpp b/chicken-wranglers/src/ai/matchai.cpp new file mode 100644 index 0000000..1870655 --- /dev/null +++ b/chicken-wranglers/src/ai/matchai.cpp @@ -0,0 +1,408 @@ +/**************************************************************************** +** +** This file is a part of QtChickenWranglers. +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).* +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +** FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +** COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +** BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +** ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +** POSSIBILITY OF SUCH DAMAGE." +** +****************************************************************************/ + + +#include "global.h" + +#include "matchai.h" + +MatchAI::MatchAI(QSize matchCanvasSize) +{ + m_graph = new Graph(matchCanvasSize); +} + +MatchAI::~MatchAI() +{ + m_graph->deleteLater(); +} + +bool MatchAI::addChicken(QPoint position) +{ + Node *chickenNode = m_graph->node(position); + + if (!chickenNode || !chickenNode->isEmpty()) + return false; + + chickenNode->data = Node::Chicken; + chickenNode->chickenCount = 1; + + return true; +} + +Node *MatchAI::addPlayer(QPoint position) +{ + Node *playerNode = m_graph->node(position); + + if (!playerNode || !playerNode->isEmpty()) + return 0; + + Node *hencoop = addHencoop(playerNode); + + if (hencoop) { + playerNode->data = Node::Player; + doUnSafe(playerNode); + } + + return hencoop; +} + +bool MatchAI::toggleLaser(QPoint position, Global::LaserDirection direction) +{ + Node *node = m_graph->node(position); + Node *neighbor; + + if (!node) + return false; + + switch (direction) { + + case Global::LaserUp: + neighbor = m_graph->node(position + QPoint(0, -1)); + if (neighbor) { + if (node->neighbor[Node::Up] != neighbor) { + // Turn off laser + node->neighbor[Node::Up] = neighbor; + neighbor->neighbor[Node::Down] = node; + return false; + } else { + // Turn on laser + node->neighbor[Node::Up] = node; + neighbor->neighbor[Node::Down] = neighbor; + return true; + } + } + break; + + case Global::LaserDown: + neighbor = m_graph->node(position + QPoint(0, 1)); + if (neighbor) { + if (node->neighbor[Node::Down] != neighbor) { + // Turn off laser + node->neighbor[Node::Down] = neighbor; + neighbor->neighbor[Node::Up] = node; + return false; + } else { + // Turn on laser + node->neighbor[Node::Down] = node; + neighbor->neighbor[Node::Up] = neighbor; + return true; + } + } + break; + + case Global::LaserRight: + neighbor = m_graph->node(position + QPoint(1, 0)); + if (neighbor) { + if (node->neighbor[Node::Right] != neighbor) { + // Turn off laser + node->neighbor[Node::Right] = neighbor; + neighbor->neighbor[Node::Left] = node; + return false; + } else { + // Turn on laser + node->neighbor[Node::Right] = node; + neighbor->neighbor[Node::Left] = neighbor; + return true; + } + } + break; + + case Global::LaserLeft: + neighbor = m_graph->node(position + QPoint(-1, 0)); + if (neighbor) { + if (node->neighbor[Node::Left] != neighbor) { + // Turn off laser + node->neighbor[Node::Left] = neighbor; + neighbor->neighbor[Node::Right] = node; + return false; + } else { + // Turn on laser + node->neighbor[Node::Left] = node; + neighbor->neighbor[Node::Right] = neighbor; + return true; + } + } + break; + + default: + return false; + } + + return false; +} + +QPair<QPoint, Global::Direction> MatchAI::moveChicken(QPoint position) +{ + Node *chickenNode = m_graph->node(position); + + if (!chickenNode || !chickenNode->isChicken()) + return QPair<QPoint, Global::Direction>(position, Global::DirectionStop); + + QList<QPair<QPoint, Node::Neighbor> > nextPosList; + Node *neighbor; + if (chickenNode->isSafe() && chickenNode->chickenCount == 1) { + nextPosList.append(QPair<QPoint, Node::Neighbor>(position, Node::Stop)); + nextPosList.append(QPair<QPoint, Node::Neighbor>(position, Node::Stop)); + nextPosList.append(QPair<QPoint, Node::Neighbor>(position, Node::Stop)); + nextPosList.append(QPair<QPoint, Node::Neighbor>(position, Node::Stop)); + nextPosList.append(QPair<QPoint, Node::Neighbor>(position, Node::Stop)); + nextPosList.append(QPair<QPoint, Node::Neighbor>(position, Node::Stop)); + nextPosList.append(QPair<QPoint, Node::Neighbor>(position, Node::Stop)); + nextPosList.append(QPair<QPoint, Node::Neighbor>(position, Node::Stop)); + } + + neighbor = chickenNode->neighbor[Node::Up]; + if (!neighbor->isPlayer() && neighbor->isSafe() && chickenNode != neighbor) { + nextPosList.append(QPair<QPoint, Node::Neighbor>(neighbor->pos, Node::Up)); + if (chickenNode->neighbor[Node::Down]->isPlayer()) { + nextPosList.append(QPair<QPoint, Node::Neighbor>(neighbor->pos, Node::Up)); + nextPosList.append(QPair<QPoint, Node::Neighbor>(neighbor->pos, Node::Up)); + nextPosList.append(QPair<QPoint, Node::Neighbor>(neighbor->pos, Node::Up)); + nextPosList.append(QPair<QPoint, Node::Neighbor>(neighbor->pos, Node::Up)); + nextPosList.append(QPair<QPoint, Node::Neighbor>(neighbor->pos, Node::Up)); + nextPosList.append(QPair<QPoint, Node::Neighbor>(neighbor->pos, Node::Up)); + nextPosList.append(QPair<QPoint, Node::Neighbor>(neighbor->pos, Node::Up)); + nextPosList.append(QPair<QPoint, Node::Neighbor>(neighbor->pos, Node::Up)); + } + } + + neighbor = chickenNode->neighbor[Node::Down]; + if (!neighbor->isPlayer() && neighbor->isSafe() && chickenNode != neighbor) { + nextPosList.append(QPair<QPoint, Node::Neighbor>(neighbor->pos, Node::Down)); + if (chickenNode->neighbor[Node::Up]->isPlayer()) { + nextPosList.append(QPair<QPoint, Node::Neighbor>(neighbor->pos, Node::Down)); + nextPosList.append(QPair<QPoint, Node::Neighbor>(neighbor->pos, Node::Down)); + nextPosList.append(QPair<QPoint, Node::Neighbor>(neighbor->pos, Node::Down)); + nextPosList.append(QPair<QPoint, Node::Neighbor>(neighbor->pos, Node::Down)); + nextPosList.append(QPair<QPoint, Node::Neighbor>(neighbor->pos, Node::Down)); + nextPosList.append(QPair<QPoint, Node::Neighbor>(neighbor->pos, Node::Down)); + nextPosList.append(QPair<QPoint, Node::Neighbor>(neighbor->pos, Node::Down)); + nextPosList.append(QPair<QPoint, Node::Neighbor>(neighbor->pos, Node::Down)); + } + } + + neighbor = chickenNode->neighbor[Node::Right]; + if (!neighbor->isPlayer() && neighbor->isSafe() && chickenNode != neighbor) { + nextPosList.append(QPair<QPoint, Node::Neighbor>(neighbor->pos, Node::Right)); + if (chickenNode->neighbor[Node::Left]->isPlayer()) { + nextPosList.append(QPair<QPoint, Node::Neighbor>(neighbor->pos, Node::Right)); + nextPosList.append(QPair<QPoint, Node::Neighbor>(neighbor->pos, Node::Right)); + nextPosList.append(QPair<QPoint, Node::Neighbor>(neighbor->pos, Node::Right)); + nextPosList.append(QPair<QPoint, Node::Neighbor>(neighbor->pos, Node::Right)); + nextPosList.append(QPair<QPoint, Node::Neighbor>(neighbor->pos, Node::Right)); + nextPosList.append(QPair<QPoint, Node::Neighbor>(neighbor->pos, Node::Right)); + nextPosList.append(QPair<QPoint, Node::Neighbor>(neighbor->pos, Node::Right)); + nextPosList.append(QPair<QPoint, Node::Neighbor>(neighbor->pos, Node::Right)); + } + } + + neighbor = chickenNode->neighbor[Node::Left]; + if (!neighbor->isPlayer() && neighbor->isSafe() && chickenNode != neighbor) { + nextPosList.append(QPair<QPoint, Node::Neighbor>(neighbor->pos, Node::Left)); + if (chickenNode->neighbor[Node::Right]->isPlayer()) { + nextPosList.append(QPair<QPoint, Node::Neighbor>(neighbor->pos, Node::Left)); + nextPosList.append(QPair<QPoint, Node::Neighbor>(neighbor->pos, Node::Left)); + nextPosList.append(QPair<QPoint, Node::Neighbor>(neighbor->pos, Node::Left)); + nextPosList.append(QPair<QPoint, Node::Neighbor>(neighbor->pos, Node::Left)); + nextPosList.append(QPair<QPoint, Node::Neighbor>(neighbor->pos, Node::Left)); + nextPosList.append(QPair<QPoint, Node::Neighbor>(neighbor->pos, Node::Left)); + nextPosList.append(QPair<QPoint, Node::Neighbor>(neighbor->pos, Node::Left)); + nextPosList.append(QPair<QPoint, Node::Neighbor>(neighbor->pos, Node::Left)); + } + } + + if (nextPosList.isEmpty()) { + neighbor = chickenNode->neighbor[Node::Up]; + + if (neighbor->isScape() && neighbor->rank < chickenNode->rank && chickenNode != neighbor) + nextPosList.append(QPair<QPoint, Node::Neighbor>(neighbor->pos, Node::Up)); + + neighbor = chickenNode->neighbor[Node::Down]; + if (neighbor->isScape() && neighbor->rank < chickenNode->rank && chickenNode != neighbor) + nextPosList.append(QPair<QPoint, Node::Neighbor>(neighbor->pos, Node::Down)); + + neighbor = chickenNode->neighbor[Node::Right]; + if (neighbor->isScape() && neighbor->rank < chickenNode->rank && chickenNode != neighbor) + nextPosList.append(QPair<QPoint, Node::Neighbor>(neighbor->pos, Node::Right)); + + neighbor = chickenNode->neighbor[Node::Left]; + if (neighbor->isScape() && neighbor->rank < chickenNode->rank && chickenNode != neighbor) + nextPosList.append(QPair<QPoint, Node::Neighbor>(neighbor->pos, Node::Left)); + } + + if (nextPosList.isEmpty()) { + neighbor = chickenNode->neighbor[Node::Up]; + + if (!neighbor->isPlayer() && neighbor->rank < chickenNode->rank && chickenNode != neighbor) + nextPosList.append(QPair<QPoint, Node::Neighbor>(neighbor->pos, Node::Up)); + + neighbor = chickenNode->neighbor[Node::Down]; + if (!neighbor->isPlayer() && neighbor->rank < chickenNode->rank && chickenNode != neighbor) + nextPosList.append(QPair<QPoint, Node::Neighbor>(neighbor->pos, Node::Down)); + + neighbor = chickenNode->neighbor[Node::Right]; + if (!neighbor->isPlayer() && neighbor->rank < chickenNode->rank && chickenNode != neighbor) + nextPosList.append(QPair<QPoint, Node::Neighbor>(neighbor->pos, Node::Right)); + + neighbor = chickenNode->neighbor[Node::Left]; + if (!neighbor->isPlayer() && neighbor->rank < chickenNode->rank && chickenNode != neighbor) + nextPosList.append(QPair<QPoint, Node::Neighbor>(neighbor->pos, Node::Left)); + } + + if (nextPosList.isEmpty()) + return QPair<QPoint, Global::Direction>(position, Global::DirectionStop); + + QPair<QPoint, Node::Neighbor> nextPos = nextPosList.at(qrand() % nextPosList.size()); + neighbor = chickenNode->neighbor[nextPos.second]; + if (neighbor != chickenNode) { + chickenNode->chickenCount -= 1; + if (!chickenNode->chickenCount) + chickenNode->data = Node::Empty; + + neighbor->chickenCount += 1; + + if (neighbor->isHencoop()) + neighbor->emitChickenEntered(); + else + neighbor->data = Node::Chicken; + } + + return QPair<QPoint, Global::Direction>(nextPos.first, + Node::neighborDirection(nextPos.second)); +} + +QPoint MatchAI::movePlayer(QPoint position, Global::Direction direction) +{ + Node *playerNode = m_graph->node(position); + + if (!playerNode || playerNode->data != Node::Player) + return position; + + Node *neighbor = playerNode->neighbor[Node::directionNeighbor(direction)]; + if (neighbor->isEmpty()) { + playerNode->data = Node::Empty; + neighbor->data = Node::Player; + + doSafe(playerNode); + + playerNode->direction = Node::Stop; + neighbor->direction = Node::directionNeighbor(direction); + + doUnSafe(neighbor); + + return neighbor->pos; + } else { + doSafe(playerNode); + playerNode->direction = Node::directionNeighbor(direction); + doUnSafe(playerNode); + } + + return position; +} + +bool MatchAI::isChickenSafe(QPoint position) +{ + Node *chickenNode = m_graph->node(position); + + if (!chickenNode || chickenNode->data != Node::Chicken) + return false; + + return chickenNode->isSafe(); +} + +Node *MatchAI::addHencoop(Node *node) +{ + if (node->neighbor[Node::Right] == node) { + node->rank = 1; + node->neighbor[Node::Right] = new Node(m_graph); + node->neighbor[Node::Right]->data = Node::Hencoop; + node->neighbor[Node::Right]->rank = 4; + node->neighbor[Node::Right]->pos = node->pos + QPoint(1, 0); + return node->neighbor[Node::Right]; + } + + if (node->neighbor[Node::Left] == node) { + node->rank = 1; + node->neighbor[Node::Left] = new Node(m_graph); + node->neighbor[Node::Left]->data = Node::Hencoop; + node->neighbor[Node::Left]->rank = 4; + node->neighbor[Node::Left]->pos = node->pos + QPoint(-1, 0); + return node->neighbor[Node::Left]; + } + + return 0; +} + +void MatchAI::doUnSafe(QPoint position) +{ + Node *playerNode = m_graph->node(position); + + if (!playerNode || !playerNode->isPlayer()) + return; + doUnSafe(playerNode); +} + +void MatchAI::doSafe(QPoint position) +{ + Node *playerNode = m_graph->node(position); + + if (!playerNode || !playerNode->isPlayer()) + return; + doSafe(playerNode); +} + +void MatchAI::doUnSafe(Node *node) +{ + node->neighbor[Node::Up]->rank += 2; + node->neighbor[Node::Down]->rank += 2; + node->neighbor[Node::Right]->rank += 2; + node->neighbor[Node::Left]->rank += 2; + node->neighbor[node->direction]->rank += 4; +} + +void MatchAI::doSafe(Node *node) +{ + node->neighbor[Node::Up]->rank -= 2; + node->neighbor[Node::Down]->rank -= 2; + node->neighbor[Node::Right]->rank -= 2; + node->neighbor[Node::Left]->rank -= 2; + node->neighbor[node->direction]->rank -= 4; +} diff --git a/chicken-wranglers/src/ai/matchai.h b/chicken-wranglers/src/ai/matchai.h new file mode 100644 index 0000000..79832fe --- /dev/null +++ b/chicken-wranglers/src/ai/matchai.h @@ -0,0 +1,78 @@ +/**************************************************************************** +** +** This file is a part of QtChickenWranglers. +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).* +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +** FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +** COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +** BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +** ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +** POSSIBILITY OF SUCH DAMAGE." +** +****************************************************************************/ + + +#ifndef GLOBALAI_H +#define GLOBALAI_H + +#include <QtCore/QPair> +#include <QtCore/QPoint> + +#include "global.h" +#include "graph.h" + +class MatchAI +{ +public: + MatchAI(QSize); + ~MatchAI(); + + bool addChicken(QPoint position); + QPair<QPoint, Global::Direction> moveChicken(QPoint position); + bool isChickenSafe(QPoint position); + + Node *addPlayer(QPoint position); + QPoint movePlayer(QPoint position, Global::Direction direction); + + bool toggleLaser(QPoint position, Global::LaserDirection direction); + + void doUnSafe(QPoint position); + void doSafe(QPoint position); + +private: + Node *addHencoop(Node *node); + void doUnSafe(Node *node); + void doSafe(Node *node); + + Graph *m_graph; +}; + +#endif diff --git a/chicken-wranglers/src/control/control.cpp b/chicken-wranglers/src/control/control.cpp new file mode 100644 index 0000000..3728bc0 --- /dev/null +++ b/chicken-wranglers/src/control/control.cpp @@ -0,0 +1,79 @@ +/**************************************************************************** +** +** This file is a part of QtChickenWranglers. +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).* +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +** FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +** COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +** BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +** ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +** POSSIBILITY OF SUCH DAMAGE." +** +****************************************************************************/ + + +#include "sensormovement.h" + +#include "control.h" + +Control::Control(QObject *parent) + : QObject(parent) +{ + m_sensorMovement = new SensorMovement(this); +} + +void Control::start() +{ + connect(m_sensorMovement, SIGNAL(directionChanged(Global::Direction)), + this, SLOT(onSensorMovementDirectionChanged(Global::Direction))); +} + +void Control::stop() +{ + disconnect(m_sensorMovement, SIGNAL(directionChanged(Global::Direction)), + this, SLOT(onSensorMovementDirectionChanged(Global::Direction))); +} + +void Control::onSensorMovementDirectionChanged(Global::Direction direction) +{ + setDirection(direction); +} + +void Control::setDirection(Global::Direction direction) +{ + if (m_direction == direction) + return; + + m_direction = direction; + + emit directionChanged(m_direction); + emit directionChanged(); +} diff --git a/chicken-wranglers/src/control/control.h b/chicken-wranglers/src/control/control.h new file mode 100644 index 0000000..7f92f00 --- /dev/null +++ b/chicken-wranglers/src/control/control.h @@ -0,0 +1,82 @@ +/**************************************************************************** +** +** This file is a part of QtChickenWranglers. +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).* +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +** FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +** COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +** BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +** ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +** POSSIBILITY OF SUCH DAMAGE." +** +****************************************************************************/ + + +#ifndef CONTROL_H +#define CONTROL_H + +#include <QtCore/QObject> + +#include "global.h" + +class SensorMovement; + +class Control : public QObject +{ + Q_OBJECT + + Q_PROPERTY(QString directionString READ directionString NOTIFY directionChanged) + +public: + Control(QObject *parent = 0); + + Global::Direction direction() const { return m_direction; } + void setDirection(Global::Direction direction); + QString directionString() const { return Global::directionString(m_direction); } + + void start(); + void stop(); + + SensorMovement *sensorMovement() const { return m_sensorMovement; } + +signals: + void directionChanged(Global::Direction direction); + void directionChanged(); + +protected slots: + void onSensorMovementDirectionChanged(Global::Direction direction); + +private: + SensorMovement *m_sensorMovement; + Global::Direction m_direction; +}; + +#endif diff --git a/chicken-wranglers/src/control/control.pri b/chicken-wranglers/src/control/control.pri new file mode 100644 index 0000000..50f950d --- /dev/null +++ b/chicken-wranglers/src/control/control.pri @@ -0,0 +1,16 @@ +maemo5 { + CONFIG += mobility12 +} else { + CONFIG += mobility +} +MOBILITY += sensors + +PATH = $$PWD + +HEADERS += \ + $$PATH/control.h \ + $$PATH/sensormovement.h + +SOURCES += \ + $$PATH/control.cpp \ + $$PATH/sensormovement.cpp diff --git a/chicken-wranglers/src/control/sensormovement.cpp b/chicken-wranglers/src/control/sensormovement.cpp new file mode 100644 index 0000000..4b032a1 --- /dev/null +++ b/chicken-wranglers/src/control/sensormovement.cpp @@ -0,0 +1,192 @@ +/**************************************************************************** +** +** This file is a part of QtChickenWranglers. +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).* +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +** FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +** COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +** BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +** ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +** POSSIBILITY OF SUCH DAMAGE." +** +****************************************************************************/ + + +#include "sensormovement.h" + +SensorMovement::SensorMovement(QObject *parent) + : QObject(parent), m_direction(Global::DirectionStop), m_startX(0), + m_startY(0), m_minimumRotation(0), + m_threshold(0), m_directionTimeout(0), m_enabled(false) +{ + m_sensor.addFilter(this); + m_sensor.start(); + + setEnabled(true); + + timer.setSingleShot(true); + + connect(&timer, SIGNAL(timeout()), this, SLOT(notifyDirectionChanged())); +} + +void SensorMovement::setEnabled(bool enabled) +{ + if (!m_sensor.isActive()) + return; + + m_enabled = enabled; + + emit enabledChanged(); +} + +void SensorMovement::setMinimumRotation(qreal minimumRotation) +{ + m_minimumRotation = minimumRotation; + + emit minimumRotationChanged(); +} + +void SensorMovement::setThreshold(qreal threshold) +{ + m_threshold = threshold; + + emit thresholdChanged(); +} + +void SensorMovement::setDirectionTimeout(int directionTimeout) +{ + m_directionTimeout = directionTimeout; + + emit directionTimeoutChanged(); +} + +void SensorMovement::resetStartPosition() +{ + QAccelerometerReading *reading = m_sensor.reading(); + + if (!reading) + return; + + m_startX = reading->x(); + m_startY = reading->y(); +} + +bool SensorMovement::filter(QAccelerometerReading *reading) +{ + if (!m_enabled) + return true; + + Global::Direction nextDirection; + // XXX: Axis are inverted on N900, thanks to the fact that + // is a landscape device by definition. + if (Global::environment() == Global::Maemo) + nextDirection = calculateDirectionMaemo5(reading->x(), reading->y()); + else + nextDirection = calculateDirection(reading->x(), reading->y()); + + if (nextDirection != m_direction) { + m_direction = nextDirection; + + timer.stop(); + timer.start(m_directionTimeout); + } + + return true; +} + +Global::Direction SensorMovement::calculateDirection(qreal x, qreal y) +{ + m_actualY = y - m_startY; + m_actualX = x - m_startX; + + if (qAbs(m_actualX) > qAbs(m_actualY)) { + if (m_actualX > 0) { + if (m_actualX > m_minimumRotation + m_threshold) + return Global::DirectionDown; + else if (m_actualX < m_minimumRotation - m_threshold && m_actualX > m_threshold) + return Global::DirectionStop; + } else { + if (m_actualX < -m_minimumRotation - m_threshold) + return Global::DirectionUp; + else if (m_actualX > -m_minimumRotation + m_threshold && m_actualX < -m_threshold) + return Global::DirectionStop; + } + } else if (m_actualY > 0) { + if (m_actualY > m_minimumRotation + m_threshold) + return Global::DirectionRight; + else if (m_actualY < m_minimumRotation - m_threshold && m_actualY > m_threshold) + return Global::DirectionStop; + } else { + if (m_actualY < -m_minimumRotation - m_threshold) + return Global::DirectionLeft; + else if (m_actualY > -m_minimumRotation + m_threshold && m_actualY < -m_threshold) + return Global::DirectionStop; + } + + return m_direction; +} + +Global::Direction SensorMovement::calculateDirectionMaemo5(qreal x, qreal y) +{ + m_actualY = y - m_startY; + m_actualX = x - m_startX; + + if (qAbs(m_actualX) > qAbs(m_actualY)) { + if (m_actualX > 0) { + if (m_actualX > m_minimumRotation + m_threshold) + return Global::DirectionLeft; + else if (m_actualX < m_minimumRotation - m_threshold && m_actualX > m_threshold) + return Global::DirectionStop; + } else { + if (m_actualX < -m_minimumRotation - m_threshold) + return Global::DirectionRight; + else if (m_actualX > -m_minimumRotation + m_threshold && m_actualX < -m_threshold) + return Global::DirectionStop; + } + } else if (m_actualY > 0) { + if (m_actualY > m_minimumRotation + m_threshold) + return Global::DirectionDown; + else if (m_actualY < m_minimumRotation - m_threshold && m_actualY > m_threshold) + return Global::DirectionStop; + } else { + if (m_actualY < -m_minimumRotation - m_threshold) + return Global::DirectionUp; + else if (m_actualY > -m_minimumRotation + m_threshold && m_actualY < -m_threshold) + return Global::DirectionStop; + } + + return m_direction; +} + +void SensorMovement::notifyDirectionChanged() +{ + emit directionChanged(m_direction); +} diff --git a/chicken-wranglers/src/control/sensormovement.h b/chicken-wranglers/src/control/sensormovement.h new file mode 100644 index 0000000..d4e4b07 --- /dev/null +++ b/chicken-wranglers/src/control/sensormovement.h @@ -0,0 +1,148 @@ +/**************************************************************************** +** +** This file is a part of QtChickenWranglers. +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).* +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +** FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +** COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +** BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +** ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +** POSSIBILITY OF SUCH DAMAGE." +** +****************************************************************************/ + + +#ifndef SENSORMOVEMENT_H +#define SENSORMOVEMENT_H + +#include "global.h" + +#include <QtCore/QObject> +#include <QtCore/QTimer> +#include <QAccelerometer> + +QTM_USE_NAMESPACE + +class SensorMovement : public QObject, public QAccelerometerFilter +{ + Q_OBJECT + +public: + SensorMovement(QObject *parent = 0); + + Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled NOTIFY enabledChanged) + Q_PROPERTY(qreal minimumRotation READ minimumRotation WRITE setMinimumRotation NOTIFY minimumRotationChanged) + Q_PROPERTY(qreal threshold READ threshold WRITE setThreshold NOTIFY thresholdChanged) + Q_PROPERTY(int directionTimeout READ directionTimeout WRITE setDirectionTimeout NOTIFY directionTimeoutChanged) + + /** + * Defines if sensor is \a enabled, if it will forward direction change signals. + */ + bool isEnabled() const { return m_enabled; } + void setEnabled(bool enabled); + + /** + * Defines a minimum absolute rotation value required to + * detect a direction change in a axis. Note that DirectionStop + * is also considered a direction. + */ + qreal minimumRotation() const { return m_minimumRotation; } + void setMinimumRotation(qreal minimumRotation); + + /** + * Defines an angle interval as [-threshold, threshold], where the device + * rotation is not considered to be at any direction. + * + * For instance, if threshold was set to 5 and device is moving along + * vertical axis, it will not notify any direction change when the the + * rotation sensor value for that axis is between -5 and 5. + */ + qreal threshold() const { return m_threshold; } + void setThreshold(qreal threshold); + + /** + * Defines a time required for the device to stand in a given direction, + * before actually notifying a direction change. + * + * When devices is moved to a direction A and changed to a direction B in + * less than \a timeout miliseconds, it won't emit directionChange signal + * for direction A. + */ + int directionTimeout() const { return m_directionTimeout; } + void setDirectionTimeout(int directionTimeout); + + Global::Direction direction() const { return m_direction; } + +public slots: + /** + * Resets the device's start position. + * + * When this method is called, the current device position is read + * from sensor and all the direction calculations will be based on + * these offsets for both axis (x = 0 + m_startX, y = 0 + m_startY). + */ + void resetStartPosition(); + +signals: + void directionChanged(Global::Direction direction); + void minimumRotationChanged(); + void thresholdChanged(); + void directionTimeoutChanged(); + void enabledChanged(); + +protected: + bool filter(QAccelerometerReading *reading); + +private slots: + void notifyDirectionChanged(); + +private: + Global::Direction calculateDirection(qreal x, qreal y); + Global::Direction calculateDirectionMaemo5(qreal x, qreal y); + + QAccelerometer m_sensor; + + Global::Direction m_direction; + + qreal m_startX; + qreal m_startY; + qreal m_actualX; + qreal m_actualY; + + qreal m_minimumRotation; + qreal m_threshold; + int m_directionTimeout; + bool m_enabled; + + QTimer timer; +}; + +#endif diff --git a/chicken-wranglers/src/controllers/chickencontroller.cpp b/chicken-wranglers/src/controllers/chickencontroller.cpp new file mode 100644 index 0000000..e358ec7 --- /dev/null +++ b/chicken-wranglers/src/controllers/chickencontroller.cpp @@ -0,0 +1,116 @@ +/**************************************************************************** +** +** This file is a part of QtChickenWranglers. +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).* +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +** FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +** COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +** BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +** ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +** POSSIBILITY OF SUCH DAMAGE." +** +****************************************************************************/ + +#include "chickencontroller.h" + +#include "matchai.h" + +#include <QtCore/QTime> + +ChickenController::ChickenController(QObject *parent) + : QObject(parent), m_isSafe(true), m_matchAI(0) +{ + initPosition(); +} + +ChickenController::ChickenController(MatchAI *matchAI, QObject *parent) + : QObject(parent), m_matchAI(matchAI) +{ + initPosition(); +} + +ChickenController::~ChickenController() +{ +} + +void ChickenController::setPosition(const QPoint &position) +{ + if (position == m_position) + return; + + m_position = position; + + emit positionChanged(); +} + +void ChickenController::setDirection(const QString &direction) +{ + if (direction == m_direction) + return; + + m_direction = direction; + + emit directionChanged(); +} + +void ChickenController::setSafe(bool isSafe) +{ + if (m_isSafe == isSafe) + return; + + m_isSafe = isSafe; + + emit isSafeChanged(); +} + +void ChickenController::move() +{ + Q_ASSERT(m_matchAI); + + setSafe(m_matchAI->isChickenSafe(m_position)); + + QPair<QPoint, Global::Direction> nextPos = m_matchAI->moveChicken(m_position); + + setDirection(Global::directionString(nextPos.second)); + setPosition(nextPos.first); +} + +void ChickenController::initPosition() +{ + Q_ASSERT(m_matchAI); + + qsrand(QTime::currentTime().msec()); + do { + m_position = QPoint(qrand() % 10, qrand() % 10); + } while (!m_matchAI->addChicken(m_position)); + + m_direction = Global::directionString(Global::DirectionStop); +} diff --git a/chicken-wranglers/src/controllers/chickencontroller.h b/chicken-wranglers/src/controllers/chickencontroller.h new file mode 100644 index 0000000..a12a393 --- /dev/null +++ b/chicken-wranglers/src/controllers/chickencontroller.h @@ -0,0 +1,89 @@ +/**************************************************************************** +** +** This file is a part of QtChickenWranglers. +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).* +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +** FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +** COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +** BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +** ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +** POSSIBILITY OF SUCH DAMAGE." +** +****************************************************************************/ + +#ifndef CHICKENCONTROLLER_H +#define CHICKENCONTROLLER_H + +#include <QtCore/QObject> +#include <QtCore/QPoint> +#include <QtCore/QString> + +class MatchAI; + +class ChickenController : public QObject +{ + Q_OBJECT + + Q_PROPERTY(QPoint position READ position NOTIFY positionChanged) + Q_PROPERTY(QString direction READ direction NOTIFY directionChanged) + Q_PROPERTY(bool isSafe READ isSafe NOTIFY isSafeChanged) + +public: + explicit ChickenController(QObject *parent = 0); // don't use it + explicit ChickenController(MatchAI *matchAI, QObject *parent = 0); + ~ChickenController(); + + QPoint position() const { return m_position; } + void setPosition(const QPoint &position); + + QString direction() const { return m_direction; } + void setDirection(const QString &direction); + + bool isSafe() const { return m_isSafe; } + + Q_INVOKABLE void move(); + +signals: + void positionChanged(); + void directionChanged(); + void isSafeChanged(); + +private: + void initPosition(); + void setSafe(bool isSafe); + + QPoint m_position; + QString m_direction; + bool m_isSafe; + MatchAI *m_matchAI; +}; + +#endif diff --git a/chicken-wranglers/src/controllers/controllers.pri b/chicken-wranglers/src/controllers/controllers.pri new file mode 100644 index 0000000..e92e330 --- /dev/null +++ b/chicken-wranglers/src/controllers/controllers.pri @@ -0,0 +1,13 @@ +QT += declarative + +PATH = $$PWD + +HEADERS += \ + $$PATH/matchcontroller.h \ + $$PATH/chickencontroller.h \ + $$PATH/playercontroller.h + +SOURCES += \ + $$PATH/matchcontroller.cpp \ + $$PATH/chickencontroller.cpp \ + $$PATH/playercontroller.cpp diff --git a/chicken-wranglers/src/controllers/matchcontroller.cpp b/chicken-wranglers/src/controllers/matchcontroller.cpp new file mode 100644 index 0000000..e25d3db --- /dev/null +++ b/chicken-wranglers/src/controllers/matchcontroller.cpp @@ -0,0 +1,246 @@ +/**************************************************************************** +** +** This file is a part of QtChickenWranglers. +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).* +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +** FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +** COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +** BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +** ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +** POSSIBILITY OF SUCH DAMAGE." +** +****************************************************************************/ + +#include "matchcontroller.h" + +#include "chickencontroller.h" +#include "matchai.h" +#include "playercontroller.h" +#include "playermodel.h" +#include "settings.h" + +#include <QtDeclarative> + +MatchController::MatchController(QObject *parent) + : QObject(parent) +{ +} + +MatchController::MatchController(PlayerListModel *model, int chickens, int elapsedTime, QObject *parent) + : QObject(parent), m_playerListModel(model), m_matchAI(0), + m_chickens(chickens), m_elapsedTime(elapsedTime), m_status(Ready) +{ + qmlRegisterType<ChickenController>("game.types", 1, 0, "ChickenController"); + qmlRegisterType<PlayerController>("game.types", 1, 0, "PlayerController"); +} + +MatchController::~MatchController() +{ + if (m_matchAI) + delete m_matchAI; +} + +void MatchController::updateElapsedTime() +{ + m_time = m_time.addSecs(-1); + m_elapsedTime--; + + emit elapsedTimeChanged(); +} + +QString MatchController::elapsedTime() const +{ + return m_time.toString("mm:ss"); +} + +void MatchController::setStatus(Status status) +{ + if (m_status == status) + return; + + m_status = status; + + switch (status) { + case Started: + start(); + break; + case Paused: + pause(); + break; + case Running: + resume(); + break; + case Over: + leave(); + break; + default: + qWarning("Invalid match status"); + } + + emit statusChanged(); +} + +void MatchController::start() +{ + m_timer.start(); + + m_status = Running; +} + +void MatchController::pause() +{ + m_timer.stop(); +} + +void MatchController::resume() +{ + m_timer.start(); +} + +void MatchController::leave() +{ + emit matchOver(); +} + +void MatchController::matchTimeout() +{ + m_timer.stop(); + + emit matchFinished(); +} + +void MatchController::setupMatch() +{ + // FIXME: These should not be hardcoded + m_playerStartPositionList.append(QPoint(0, 0)); + m_playerStartPositionList.append(QPoint(9, 9)); + m_playerStartPositionList.append(QPoint(0, 9)); + m_playerStartPositionList.append(QPoint(9, 0)); + + m_matchAI = new MatchAI(QSize(10, 10)); + + m_time.setHMS(0, 0, 0); + m_time = m_time.addSecs(m_elapsedTime); + m_timer.setInterval(1000); + connect(&m_timer, SIGNAL(timeout()), + this, SLOT(onTimerTick())); + + createPlayers(); + createChickens(); +} + +void MatchController::createChickens() +{ + m_chickenCount = m_chickens; + + for (int i = 0; i < m_chickenCount; i++) { + ChickenController *chickenController = new ChickenController(m_matchAI, this); + chickenControllerList.append(chickenController); + + emit chickenCreated(i); + } +} + +void MatchController::createPlayers() +{ + int i; + + for (i = 0; i < m_playerListModel->rowCount() && i < m_playerStartPositionList.size(); i++) { + PlayerModel *playerModel = m_playerListModel->get(i); + + PlayerController *playerController = new PlayerController(playerModel, m_matchAI, this); + playerController->setPosition(m_playerStartPositionList.at(i)); + Node *henCoop = m_matchAI->addPlayer(m_playerStartPositionList.at(i)); + if (!henCoop) { + qWarning("Error adding player to match AI"); + playerController->deleteLater(); + continue; + } + + connect(henCoop, SIGNAL(chickenEntered(int)), + playerController, SLOT(onScore(int))); + + connect(henCoop, SIGNAL(chickenEntered(int)), + this, SLOT(onChickenEntered(int))); + + playerControllerList.append(playerController); + + emit playerCreated(i); + } +} + +ChickenController *MatchController::getChicken(int id) const +{ + if (id >= chickenControllerList.size() || id < 0) + return 0; + + return chickenControllerList.at(id); +} + +PlayerController *MatchController::getPlayer(int id) const +{ + if (id >= playerControllerList.size() || id < 0) + return 0; + + return playerControllerList.at(id); +} + +void MatchController::toggleLaser(int x, int y, int laserDirection) +{ + foreach(PlayerController *playerController, playerControllerList) + m_matchAI->doSafe(playerController->position()); + + bool isOn = m_matchAI->toggleLaser(QPoint(x, y), + static_cast<Global::LaserDirection>(laserDirection)); + + foreach(PlayerController *playerController, playerControllerList) + m_matchAI->doUnSafe(playerController->position()); + + emit laserUpdated(x, y, laserDirection, isOn); +} + +void MatchController::onTimerTick() +{ + updateElapsedTime(); + + if (m_elapsedTime == 0) + matchTimeout(); +} + +void MatchController::onChickenEntered(int) +{ + if (--m_chickenCount > 0) + return; + + m_timer.stop(); + + emit matchFinished(); +} diff --git a/chicken-wranglers/src/controllers/matchcontroller.h b/chicken-wranglers/src/controllers/matchcontroller.h new file mode 100644 index 0000000..c6c4e0f --- /dev/null +++ b/chicken-wranglers/src/controllers/matchcontroller.h @@ -0,0 +1,132 @@ +/**************************************************************************** +** +** This file is a part of QtChickenWranglers. +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).* +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +** FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +** COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +** BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +** ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +** POSSIBILITY OF SUCH DAMAGE." +** +****************************************************************************/ + + +#ifndef MATCHCONTROLLER_H +#define MATCHCONTROLLER_H + +#include "global.h" + +#include <QtCore/QObject> +#include <QtCore/QPoint> +#include <QtCore/QTime> +#include <QtCore/QTimer> + +class ChickenController; +class MatchAI; +class PlayerController; +class PlayerListModel; + +class MatchController : public QObject +{ + Q_OBJECT + + Q_PROPERTY(QString elapsedTime READ elapsedTime NOTIFY elapsedTimeChanged) + Q_PROPERTY(Status status READ status WRITE setStatus NOTIFY statusChanged) + + Q_ENUMS(Status) + +public: + MatchController(QObject *parent = 0); + MatchController(PlayerListModel *model, int chickens, int elapsedTime, QObject *parent = 0); + ~MatchController(); + + enum Status { + Ready, + Started, + Paused, + Running, + Over + }; + + QString elapsedTime() const; + + void setStatus(Status status); + Status status() const { return m_status; } + + Q_INVOKABLE void setupMatch(); + Q_INVOKABLE ChickenController *getChicken(int id) const; + Q_INVOKABLE PlayerController *getPlayer(int id) const; + + Q_INVOKABLE void toggleLaser(int x, int y, int laserDirection); + +signals: + void chickenCreated(int id); + void playerCreated(int id); + void laserUpdated(int x, int y, int laserDirection, bool isOn); + void elapsedTimeChanged(); + void statusChanged(); + void matchFinished(); + void matchOver(); + + void aborted(); + +private slots: + void onTimerTick(); + void onChickenEntered(int); + +private: + void setup(); + void createChickens(); + void createPlayers(); + void updateElapsedTime(); + void start(); + void pause(); + void resume(); + void leave(); + void matchTimeout(); + + QList<QPoint> m_playerStartPositionList; + + QList<ChickenController *> chickenControllerList; + QList<PlayerController *> playerControllerList; + + PlayerListModel *m_playerListModel; + MatchAI *m_matchAI; + QTimer m_timer; + QTime m_time; + int m_chickens; + int m_elapsedTime; + Status m_status; + int m_chickenCount; +}; + +#endif diff --git a/chicken-wranglers/src/controllers/playercontroller.cpp b/chicken-wranglers/src/controllers/playercontroller.cpp new file mode 100644 index 0000000..98f17fa --- /dev/null +++ b/chicken-wranglers/src/controllers/playercontroller.cpp @@ -0,0 +1,127 @@ +/**************************************************************************** +** +** This file is a part of QtChickenWranglers. +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).* +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +** FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +** COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +** BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +** ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +** POSSIBILITY OF SUCH DAMAGE." +** +****************************************************************************/ + +#include "playercontroller.h" + +#include "matchai.h" +#include "matchcontroller.h" +#include "playermodel.h" +#include "soundmanager.h" + +PlayerController::PlayerController(QObject *parent) + : QObject(parent) +{ +} + +PlayerController::PlayerController(PlayerModel *model, MatchAI *matchAI, QObject *parent) + : QObject(parent), m_model(model), m_matchAI(matchAI), m_score(0) +{ + connect(m_model, SIGNAL(laserToggleRequested(Global::LaserDirection)), + this, SLOT(onLaserToggleRequested(Global::LaserDirection))); +} + +PlayerController::~PlayerController() +{ +} + +void PlayerController::setPosition(const QPoint &position) +{ + if (position == m_position) + return; + + m_position = position; + + emit positionChanged(); +} + +void PlayerController::onScore(int score) +{ + SoundManager::play(SoundManager::Score); + + m_model->setScore(score); +} + +void PlayerController::move() +{ + Q_ASSERT(m_matchAI); + + Global::Direction direction = m_model->direction(); + QPoint nextPosition = m_matchAI->movePlayer(m_position, direction); + setPosition(nextPosition); +} + +bool PlayerController::isSameDirection(Global::LaserDirection laserDirection) +{ + Global::Direction currentDirection = m_model->direction(); + + if (currentDirection == Global::DirectionStop) + return true; + + if (laserDirection == Global::LaserUp && currentDirection == Global::DirectionUp) + return true; + + if (laserDirection == Global::LaserDown && currentDirection == Global::DirectionDown) + return true; + + if (laserDirection == Global::LaserLeft && currentDirection == Global::DirectionLeft) + return true; + + if (laserDirection == Global::LaserRight && currentDirection == Global::DirectionRight) + return true; + + return false; +} + +void PlayerController::onLaserToggleRequested(Global::LaserDirection laserDirection) +{ + SoundManager::play(SoundManager::Laser); + + if (isSameDirection(laserDirection)) { + MatchController *matchController = qobject_cast<MatchController *>(parent()); + if (!matchController) { + qWarning("Error getting MatchController from PlayerController"); + return; + } + + matchController->toggleLaser(m_position.x(), m_position.y(), laserDirection); + } else + emit laserToggleRequested(laserDirection); +} diff --git a/chicken-wranglers/src/controllers/playercontroller.h b/chicken-wranglers/src/controllers/playercontroller.h new file mode 100644 index 0000000..2295d03 --- /dev/null +++ b/chicken-wranglers/src/controllers/playercontroller.h @@ -0,0 +1,93 @@ +/**************************************************************************** +** +** This file is a part of QtChickenWranglers. +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).* +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +** FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +** COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +** BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +** ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +** POSSIBILITY OF SUCH DAMAGE." +** +****************************************************************************/ + + +#ifndef PLAYERCONTROLLER_H +#define PLAYERCONTROLLER_H + +#include <QtCore/QObject> +#include <QtCore/QPoint> + +#include "global.h" + +class MatchAI; +class PlayerModel; + +class PlayerController : public QObject +{ + Q_OBJECT + + Q_PROPERTY(QPoint position READ position NOTIFY positionChanged) + +public: + PlayerController(QObject *parent = 0); + PlayerController(PlayerModel *model, MatchAI *matchAI, QObject *parent = 0); + ~PlayerController(); + + PlayerModel *model() const { return m_model; } + + QPoint position() const { return m_position; } + void setPosition(const QPoint &position); + int score() const { return m_score; } + + Q_INVOKABLE void move(); + +public slots: + void onScore(int score); + +signals: + void positionChanged(); + void scoreChanged(); + void laserToggleRequested(int laserDirection); + +private slots: + void onLaserToggleRequested(Global::LaserDirection direction); + +private: + bool isSameDirection(Global::LaserDirection laserDirection); + + PlayerModel *m_model; + MatchAI *m_matchAI; + QPoint m_position; + int m_score; +}; + +#endif diff --git a/chicken-wranglers/src/main/argumentparser.cpp b/chicken-wranglers/src/main/argumentparser.cpp new file mode 100644 index 0000000..151ff8b --- /dev/null +++ b/chicken-wranglers/src/main/argumentparser.cpp @@ -0,0 +1,118 @@ +/**************************************************************************** +** +** This file is a part of QtChickenWranglers. +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).* +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +** FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +** COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +** BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +** ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +** POSSIBILITY OF SUCH DAMAGE." +** +****************************************************************************/ + + +#include "argumentparser.h" + +ArgumentProcessor::ArgumentProcessor(QStringList options) + : m_args(options) +{ +} + +QSize ArgumentProcessor::display() +{ + QSize result; + // -displaysize + QStringList displaySizeList = valueForOption("-displaysize").split("x"); + if (displaySizeList.size() == 2) { + result.setWidth(displaySizeList.at(0).toInt()); + result.setHeight(displaySizeList.at(1).toInt()); + } + + return result; +} + +QString ArgumentProcessor::connectivity() +{ + QString result("bluetooth"); + // -connectivity bluetooth | lan + QString argument = valueForOption("-connectivity"); + if (argument == "lan") { + result = "lan"; + } + + return result; +} + +QString ArgumentProcessor::tcpPort() +{ + QString result("-1"); + // -tcpport + QString argument = valueForOption("-tcpport"); + if (!argument.isEmpty()) + result = argument; + + return result; +} + +QString ArgumentProcessor::udpPort() +{ + QString result("-1"); + // -udpport + QString argument = valueForOption("-udpport"); + if (!argument.isEmpty()) + result = argument; + + return result; +} + +QString ArgumentProcessor::graphicsMode() +{ + QString result("opengl"); + // - opengl | raster + QString argument = valueForOption("-graphicsmode"); + if (argument == "raster") { + result = "raster"; + } + + return result; +} + +QString ArgumentProcessor::valueForOption(const QString &option) +{ + int optionIndex = m_args.indexOf(option); + + if ((optionIndex != -1) && (optionIndex + 1 < m_args.size())) + return m_args.at(optionIndex + 1); + + return QString(); +} + diff --git a/chicken-wranglers/src/main/argumentparser.h b/chicken-wranglers/src/main/argumentparser.h new file mode 100644 index 0000000..c77e644 --- /dev/null +++ b/chicken-wranglers/src/main/argumentparser.h @@ -0,0 +1,73 @@ +/**************************************************************************** +** +** This file is a part of QtChickenWranglers. +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).* +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +** FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +** COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +** BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +** ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +** POSSIBILITY OF SUCH DAMAGE." +** +****************************************************************************/ + + +#ifndef ARGUMENTPARSER_H +#define ARGUMENTPARSER_H + +#include <QtCore/QSize> +#include <QtCore/QString> +#include <QtCore/QStringList> + +class ArgumentProcessor +{ +public: + ArgumentProcessor(QStringList options); + + QSize display(); + + QString connectivity(); + + QString tcpPort(); + + QString udpPort(); + + QString graphicsMode(); + + //TODO: move to another file, etc + +private: + QString valueForOption(const QString &option); + + QStringList m_args; +}; + +#endif diff --git a/chicken-wranglers/src/main/game.cpp b/chicken-wranglers/src/main/game.cpp new file mode 100644 index 0000000..e168503 --- /dev/null +++ b/chicken-wranglers/src/main/game.cpp @@ -0,0 +1,206 @@ +/**************************************************************************** +** +** This file is a part of QtChickenWranglers. +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).* +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +** FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +** COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +** BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +** ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +** POSSIBILITY OF SUCH DAMAGE." +** +****************************************************************************/ + + +#include <QtDeclarative> +#include <QtGui/QApplication> +#include <QtOpenGL/QGLWidget> + +#include "charactermodel.h" +#include "connectivitylistmodel.h" +#include "global.h" +#include "settings.h" +#include "soundmanager.h" +#include "gameclient.h" +#include "gamehost.h" +#include "soundmanager.h" + +#include "game.h" + +Game::Game(const GraphicsMode &mode, QObject *parent) + : QObject(parent), m_gameClient(0), m_gameHost(0), + m_connectivity("bluetooth"), m_mode(None) +{ + qmlRegisterType<Global>("game.types", 1, 0, "Global"); + qmlRegisterType<Game>("game.types", 1, 0, "Game"); + qmlRegisterType<GameClient>("game.types", 1, 0, "GameClient"); + qmlRegisterType<GameHost>("game.types", 1, 0, "GameHost"); + // FIXME: Register this model later when GameClient is created. + qmlRegisterType<ConnectivityListModel>("game.types", 1, 0, "ConnectivityListModel"); + + m_view = new QDeclarativeView; + if (mode == OpenGL) { + //XXX: for some reason, setting the GLWidget is not enabling + //ogl in Symbian + if (Global::environment() == Global::Symbian) { + QApplication::setGraphicsSystem("opengl"); + } else { + m_view->setViewport(new QGLWidget); + } + } else { + QApplication::setGraphicsSystem("raster"); + } + + m_view->setResizeMode(QDeclarativeView::SizeRootObjectToView); + m_view->rootContext()->setContextProperty("game", this); + m_view->rootContext()->setContextProperty("settings", Settings::instance()); +} + +Game::~Game() +{ + delete m_gameHost; + delete m_gameClient; + delete m_view; +} + +void Game::setMode(Mode mode) +{ + if (mode == ClientMode) + startClientMode(); + else if (mode == HostMode) + startHostMode(); +} + +void Game::startClientMode() +{ + m_mode = ClientMode; + if (m_gameClient) { + emit modeChanged(); + return; + } + + if (!m_gameClient) { + m_gameClient = new GameClient(m_view->rootContext(), m_connectivity, this); + m_view->rootContext()->setContextProperty("gameClient", m_gameClient); + connect(m_gameClient, SIGNAL(ended()), this, SLOT(onClientModeEnded())); + } else + ;//TODO: client has not a way to update the connectivity + + emit modeChanged(); +} + +void Game::startHostMode() +{ + m_mode = HostMode; + if (m_gameHost) { + m_gameHost->setConnectivity(m_connectivity); + emit modeChanged(); + return; + } + + if (!m_gameHost) { + m_gameHost = new GameHost(m_view->rootContext(), m_connectivity, this); + m_view->rootContext()->setContextProperty("gameHost", m_gameHost); + connect(m_gameHost, SIGNAL(ended()), this, SLOT(onHostModeEnded())); + } + + + emit modeChanged(); +} + +void Game::start(const QSize &displaySize) +{ +#ifdef CW_DEBUG + m_view->setSource(Global::rootDirectory().absoluteFilePath() + "/src/qml/main.qml"); +#else + m_view->setSource(QUrl("qrc:/main.qml")); +#endif + + QObject::connect(m_view->engine(), SIGNAL(quit()), m_view, SLOT(close())); + + if (displaySize.isValid()) { + m_view->resize(displaySize); + m_view->show(); + } else { + m_view->showFullScreen(); + } +} + +QSize Game::displaySize() const +{ + return m_view->size(); +} + +void Game::onHostModeEnded() +{ + m_mode = None; +} + +void Game::onClientModeEnded() +{ + //TODO: client has not a way to update the connectivity + if (m_gameClient) { + delete m_gameClient; + m_gameClient = 0; + } + m_mode = None; +} + +void Game::startBackgroundSound() +{ + SoundManager::play(SoundManager::Background); +} + +int Game::environment() +{ + return Global::environment(); +} + +QString Game::connectivity() const +{ + return m_connectivity; +} + +void Game::setConnectivity(const QString &type) +{ + if (m_connectivity == type) + return; + + m_connectivity = type; + if (m_mode == HostMode) { + onHostModeEnded(); + startHostMode(); + } else { + onClientModeEnded(); + startClientMode(); + } +} + diff --git a/chicken-wranglers/src/main/game.h b/chicken-wranglers/src/main/game.h new file mode 100644 index 0000000..bf297b4 --- /dev/null +++ b/chicken-wranglers/src/main/game.h @@ -0,0 +1,114 @@ +/**************************************************************************** +** +** This file is a part of QtChickenWranglers. +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).* +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +** FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +** COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +** BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +** ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +** POSSIBILITY OF SUCH DAMAGE." +** +****************************************************************************/ + + +#ifndef GAME_H +#define GAME_H + +#include <QtCore/QObject> +#include <QtCore/QSize> + +#include "gameclient.h" +#include "gamehost.h" + +class GameClient; +class GameHost; +class QDeclarativeView; + +class Game : public QObject +{ + Q_OBJECT + + Q_PROPERTY(QSize displaySize READ displaySize NOTIFY displaySizeChanged) + Q_PROPERTY(Mode mode READ mode WRITE setMode NOTIFY modeChanged) + Q_PROPERTY(QString connectivity READ connectivity WRITE setConnectivity) + + Q_ENUMS(Mode) + +public: + enum Mode { + None, + HostMode, + ClientMode + }; + + enum GraphicsMode { + OpenGL, + Raster + }; + + Game(const GraphicsMode &mode = OpenGL, QObject *parent = 0); + ~Game(); + + void start(const QSize &size = QSize()); + + Mode mode() { return m_mode; } + void setMode(Mode mode); + + QSize displaySize() const; + + QString connectivity() const; + Q_INVOKABLE void setConnectivity(const QString &type); + + Q_INVOKABLE void startBackgroundSound(); + Q_INVOKABLE int environment(); + +signals: + void modeChanged(); + void displaySizeChanged(); + +private slots: + void onClientModeEnded(); + void onHostModeEnded(); + +private: + void startClientMode(); + void startHostMode(); + void setupSounds(); + + QDeclarativeView *m_view; + GameClient *m_gameClient; + GameHost *m_gameHost; + QString m_connectivity; + Mode m_mode; +}; + +#endif diff --git a/chicken-wranglers/src/main/gameclient.cpp b/chicken-wranglers/src/main/gameclient.cpp new file mode 100644 index 0000000..4d2e461 --- /dev/null +++ b/chicken-wranglers/src/main/gameclient.cpp @@ -0,0 +1,423 @@ +/**************************************************************************** +** +** This file is a part of QtChickenWranglers. +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).* +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +** FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +** COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +** BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +** ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +** POSSIBILITY OF SUCH DAMAGE." +** +****************************************************************************/ + +#include <QtCore/QStringList> +#include <QtDeclarative/QDeclarativeContext> + +#include "charactermodel.h" +#include "connectivitylistmodel.h" +#include "control.h" +#include "global.h" +#include "networkclient.h" +#include "sensormovement.h" +#include "settings.h" + +#include "gameclient.h" + +GameClient::GameClient(QObject *parent) + : QObject(parent) +{ +} + +GameClient::GameClient(QDeclarativeContext *context, const QString &connectivity, QObject *parent) + : QObject(parent), m_declarativeContext(context), m_networkClient(0), + m_characterListModel(0), m_connectivityListModel(0), m_control(new Control(this)), + m_status(NoStatus), m_error(NoError) +{ + m_networkClient = new NetworkClient(connectivity, Settings::lanUdpDiscoveryTimeout(), + Settings::lanUdpDiscoveryClientAttempts(), this); + m_networkClient->setLanPorts(Settings::lanUdpPort(), Settings::lanTcpPort()); + + connect(m_networkClient, SIGNAL(serverDiscoveryTimeout()), + this, SLOT(onServerDiscoveryTimeout())); + connect(m_networkClient, SIGNAL(connected()), + this, SLOT(onConnected())); + connect(m_networkClient, SIGNAL(disconnected()), + this, SLOT(onDisconnected())); + connect(m_networkClient, SIGNAL(socketError(QAbstractSocket::SocketError)), + this, SLOT(onSocketError(QAbstractSocket::SocketError))); + connect(m_networkClient, SIGNAL(messageReceived(NetworkMessage)), + this, SLOT(onMessageReceived(NetworkMessage))); + + m_connectivityListModel = new ConnectivityListModel(this); + connect(m_networkClient, SIGNAL(bluetoothDeviceDiscovered(const BluetoothDevice &)), + m_connectivityListModel, SLOT(addDevice(const BluetoothDevice &))); + connect(m_connectivityListModel, SIGNAL(selectedDevice(const QString &)), + m_networkClient, SLOT(stopDiscovery())); + connect(m_connectivityListModel, SIGNAL(selectedDevice(const QString &)), + m_networkClient, SLOT(connectToBluetoothServer(const QString &))); + m_declarativeContext->setContextProperty("connectivityListModel", m_connectivityListModel); + + SensorMovement *sensorMovement = m_control->sensorMovement(); + sensorMovement->setMinimumRotation(1); + sensorMovement->setThreshold(0.2); + + connect(m_control, SIGNAL(directionChanged(Global::Direction)), + this, SLOT(onControlDirectionChanged(Global::Direction))); + + // TODO: This was tested only on Maemo5. There should + // be specific implementations for Maemo6 and Symbian + // + // m_backlightTimer.setInterval(20000); + // connect(&m_backlightTimer, SIGNAL(timeout()), this, SLOT(forceBackLightOn())); +} + +void GameClient::setStatus(GameClient::Status status) +{ + if (m_status == status) + return; + + m_status = status; + + emit statusChanged(); +} + +void GameClient::setLeader(bool isLeader) +{ + if (m_isLeader == isLeader) + return; + + m_isLeader = isLeader; + + emit isLeaderChanged(); +} + +void GameClient::startConnection() +{ + m_error = NoError; + m_status = NoStatus; + + m_connectivityListModel->loadLastHostDevice(); + m_networkClient->startDiscovery(); +} + +void GameClient::toggleLaserUp() +{ + notifyPlayerControlLaser(CW::PlayerControlLaserUp); +} + +void GameClient::toggleLaserDown() +{ + notifyPlayerControlLaser(CW::PlayerControlLaserDown); +} + +void GameClient::toggleLaserLeft() +{ + notifyPlayerControlLaser(CW::PlayerControlLaserLeft); +} + +void GameClient::toggleLaserRight() +{ + notifyPlayerControlLaser(CW::PlayerControlLaserRight); +} + +void GameClient::moveUp() +{ + onControlDirectionChanged(Global::DirectionUp); +} + +void GameClient::moveDown() +{ + onControlDirectionChanged(Global::DirectionDown); +} + +void GameClient::moveLeft() +{ + onControlDirectionChanged(Global::DirectionLeft); +} + +void GameClient::moveRight() +{ + onControlDirectionChanged(Global::DirectionRight); +} + +void GameClient::moveStop() +{ + onControlDirectionChanged(Global::DirectionStop); +} + +void GameClient::quit() +{ + m_error = NoError; + m_status = NoStatus; + + m_networkClient->stopDiscovery(); + + emit ended(); +} + +void GameClient::onServerDiscoveryTimeout() +{ + m_error = ServerDiscoveryTimeoutError; + + setStatus(Error); + + quit(); +} + +void GameClient::onConnected() +{ + m_connectivityListModel->storeLastHostDevice(); + + disconnect(m_networkClient, SIGNAL(connected()), this, SLOT(onConnected())); + + loadCharacters(); + + setStatus(Joined); +} + +void GameClient::onDisconnected() +{ + disconnect(m_networkClient, SIGNAL(disconnected()), this, SLOT(onDisconnected())); + + setStatus(NoStatus); +} + +void GameClient::onMessageReceived(const NetworkMessage &message) +{ + switch (message.type()) { + case CW::CharacterMessageType: + handleCharacterMessage(message); + break; + case CW::MatchMessageType: + handleMatchMessage(message); + break; + case CW::PlayerInfoMessageType: + handlePlayerInfoMessage(message); + break; + default: + qWarning("Invalid message type"); + } +} + +void GameClient::onSocketError(QAbstractSocket::SocketError error) +{ + Q_UNUSED(error); + + m_error = SocketError; + + setStatus(Error); +} + +void GameClient::loadCharacters() +{ + if (!m_characterListModel) + m_characterListModel = new CharacterListModel(this); + + if (!m_characterListModel->load()) {} + + m_declarativeContext->setContextProperty("characterListModel", m_characterListModel); + + connect(m_characterListModel, SIGNAL(selectedIndexChanged()), + this, SLOT(onModelSelectedIndexChanged())); +} + +void GameClient::onModelSelectedIndexChanged() +{ + int selectedIndex = m_characterListModel->selectedIndex(); + + if (selectedIndex != -1) { + CharacterModel *characterModel = m_characterListModel->get(selectedIndex); + notifyCharacterSelected(characterModel->name()); + } else { + notifyCharacterReleased(); + } +} + +void GameClient::notifyCharacterSelected(const QString &characterName) +{ + NetworkMessage message(CW::CharacterMessageType, CW::CharacterSelected); + message.setData(characterName.toLatin1()); + + m_networkClient->send(message); +} + +void GameClient::notifyCharacterReleased() +{ + NetworkMessage message(CW::CharacterMessageType, CW::CharacterReleased); + + m_networkClient->send(message); +} + +void GameClient::notifyPlayerControlLaser(CW::PlayerControl laserDirection) +{ + NetworkMessage message(CW::PlayerControlMessageType, laserDirection); + + m_networkClient->send(message); +} + +void GameClient::handleCharacterMessage(const NetworkMessage &message) +{ + if (!m_characterListModel) { + // XXX: Properly thrown an exception for the Game class + qCritical("Error: CharacterListModel not initialized."); + return; + } + + switch (message.content()) { + case CW::CharacterSelected: { + QString characterName(message.data()); + + CharacterModel *model; + for (int i = 0; i < m_characterListModel->rowCount(); i++) { + model = m_characterListModel->get(i); + if (model->name() == characterName) + model->setAvailable(false); + } + + break; + } + case CW::CharacterAvailableList: { + QStringList availableCharacters(QString(message.data()).split("|")); + + CharacterModel *model; + for (int i = 0; i < m_characterListModel->rowCount(); i++) { + model = m_characterListModel->get(i); + if (!availableCharacters.contains(model->name())) + model->setAvailable(false); + } + + break; + } + case CW::CharacterIsAvailable: { + QStringList messageDataList(QString(message.data()).split("|")); + QString characterName = messageDataList.at(0); + + bool characterIsAvailable(true); + if (messageDataList.at(1) == "0") + characterIsAvailable = false; + + CharacterModel *model; + for (int i = 0; i < m_characterListModel->rowCount(); i++) { + model = m_characterListModel->get(i); + + if (model->name() == characterName) + model->setAvailable(characterIsAvailable); + } + + break; + } + } +} + +void GameClient::handleMatchMessage(const NetworkMessage &message) +{ + switch (message.content()) { + case CW::MatchReady: + setStatus(Ready); + m_control->start(); + forceBackLightOn(); + m_backlightTimer.start(); + break; + case CW::MatchFinished: + setStatus(LeftMatch); + m_control->stop(); + m_backlightTimer.stop(); + break; + default: + qWarning("Invalid match message"); + } +} + +void GameClient::handlePlayerInfoMessage(const NetworkMessage &message) +{ + switch (message.content()) { + case CW::PlayerInfoLeader: { + bool isLeader(false); + if (message.data() == "1") + isLeader = true; + + setLeader(isLeader); + + break; + } + default: + qWarning("Invalid player info message"); + } +} + +// FIXME: Move this function to a better place +static CW::PlayerControl directionToPlayerControl(Global::Direction direction) +{ + QMap<Global::Direction, CW::PlayerControl> playerControl; + + playerControl[Global::DirectionUp] = CW::PlayerControlUp; + playerControl[Global::DirectionDown] = CW::PlayerControlDown; + playerControl[Global::DirectionRight] = CW::PlayerControlRight; + playerControl[Global::DirectionLeft] = CW::PlayerControlLeft; + playerControl[Global::DirectionStop] = CW::PlayerControlStop; + + return playerControl[direction]; +} + +void GameClient::onControlDirectionChanged(Global::Direction direction) +{ + NetworkMessage message(CW::PlayerControlMessageType, directionToPlayerControl(direction)); + + m_networkClient->send(message); +} + +void GameClient::forceBackLightOn() +{ + /* TODO: Provide specific implementations for Maemo6 and Symbian + + if (!QDBusConnection::systemBus().isConnected()) { + qWarning("Error connecting to session bus"); + return; + } + + QDBusInterface iface("com.nokia.mce", "/com/nokia/mce/request", "com.nokia.mce.request", + QDBusConnection::systemBus()); + + if (iface.isValid()) + iface.call("req_tklock_mode_change", QString("unlocked")); + else + qWarning("Error calling com.nokia.mce.request.req_tklock_mode_change"); + */ +} + +void GameClient::scanCanceled() +{ + m_networkClient->stopDiscovery(); + + // scan is assynchronous, so wait a little bit before cleaning the model + QTimer::singleShot(300, m_connectivityListModel, SLOT(clear())); +} diff --git a/chicken-wranglers/src/main/gameclient.h b/chicken-wranglers/src/main/gameclient.h new file mode 100644 index 0000000..7e9e7ad --- /dev/null +++ b/chicken-wranglers/src/main/gameclient.h @@ -0,0 +1,156 @@ +/**************************************************************************** +** +** This file is a part of QtChickenWranglers. +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).* +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +** FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +** COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +** BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +** ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +** POSSIBILITY OF SUCH DAMAGE." +** +****************************************************************************/ + + +#ifndef GAMECLIENT_H +#define GAMECLIENT_H + +#include <QtCore/QObject> +#include <QtCore/QTimer> +#include <QtNetwork/QHostAddress> + +#include "global.h" +#include "networkmessage.h" + +class CharacterListModel; +class ConnectivityListModel; +class Control; +class NetworkClient; +class QDeclarativeContext; + +class GameClient : public QObject +{ + Q_OBJECT + + Q_PROPERTY(Status status READ status WRITE setStatus NOTIFY statusChanged) + Q_PROPERTY(bool isLeader READ isLeader WRITE setLeader NOTIFY isLeaderChanged) + Q_PROPERTY(ErrorType error READ error NOTIFY errorChanged) + Q_ENUMS(Status ErrorType) + +public: + GameClient(QObject *parent = 0); + GameClient(QDeclarativeContext *context, const QString &connectivity = "lan", + QObject *parent = 0); + + enum Status { + NoStatus, + Joined, + LeftMatch, + Ready, + Playing, + Error + }; + + enum ErrorType { + NoError, + ServerDiscoveryTimeoutError, + SocketError, + UnknownError + }; + + Status status() { return m_status; } + void setStatus(Status status); + + void setLeader(bool isLeader); + bool isLeader() const { return m_isLeader; } + + ErrorType error() { return m_error; } + +public slots: + void startConnection(); + + void scanCanceled(); + + // TODO: Use a single toggle laser method with direction parameter + void toggleLaserUp(); + void toggleLaserDown(); + void toggleLaserLeft(); + void toggleLaserRight(); + + // TODO: Use a single move method with direction parameter + void moveUp(); + void moveDown(); + void moveLeft(); + void moveRight(); + void moveStop(); + + void quit(); + +signals: + void statusChanged(); + void errorChanged(); + void isLeaderChanged(); + void ended(); + +private slots: + void onServerDiscoveryTimeout(); + void onConnected(); + void onDisconnected(); + void onMessageReceived(const NetworkMessage &message); + void onSocketError(QAbstractSocket::SocketError error); + void onModelSelectedIndexChanged(); + void onControlDirectionChanged(Global::Direction direction); + void forceBackLightOn(); + +private: + void loadCharacters(); + + void handleCharacterMessage(const NetworkMessage &message); + void handleMatchMessage(const NetworkMessage &message); + void handlePlayerInfoMessage(const NetworkMessage &message); + + void notifyCharacterSelected(const QString &characterName); + void notifyCharacterReleased(); + void notifyDirectionChanged(Global::Direction); + void notifyPlayerControlLaser(CW::PlayerControl laserDirection); + + QDeclarativeContext *m_declarativeContext; + NetworkClient *m_networkClient; + CharacterListModel *m_characterListModel; + ConnectivityListModel *m_connectivityListModel; + Control *m_control; + Status m_status; + ErrorType m_error; + bool m_isLeader; + QTimer m_backlightTimer; +}; + +#endif diff --git a/chicken-wranglers/src/main/gamehost.cpp b/chicken-wranglers/src/main/gamehost.cpp new file mode 100644 index 0000000..6948d65 --- /dev/null +++ b/chicken-wranglers/src/main/gamehost.cpp @@ -0,0 +1,199 @@ +/**************************************************************************** +** +** This file is a part of QtChickenWranglers. +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).* +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +** FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +** COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +** BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +** ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +** POSSIBILITY OF SUCH DAMAGE." +** +****************************************************************************/ + + +#include <QtDeclarative> + +#include "global.h" +#include "matchcontroller.h" +#include "networkconnection.h" +#include "playermodel.h" +#include "settings.h" + +#include "gamehost.h" + +GameHost::GameHost(QDeclarativeContext *context, const QString &connectivity, + QObject *parent) + : QObject(parent), m_declarativeContext(context), m_networkServer(0), + m_playerListModel(new PlayerListModel(this)), m_matchController(0), + m_status(NoStatus), m_error(NoError) +{ + m_declarativeContext->setContextProperty("playerListModel", m_playerListModel); + + qmlRegisterType<MatchController>("game.types", 1, 0, "Match"); + + m_networkServer = new NetworkServer(connectivity, Settings::lanUdpDiscoveryTimeout(), + Settings::lanUdpDiscoveryHostAttempts()); + m_networkServer->setLanPorts(Settings::lanUdpPort(), Settings::lanTcpPort()); + + connect(m_networkServer, SIGNAL(error(NetworkServer::ServerError)), + this, SLOT(onServerError(NetworkServer::ServerError))); + connect(m_networkServer, SIGNAL(started()), + this, SLOT(onServerStarted())); + connect(m_networkServer, SIGNAL(peerConnected(NetworkConnection *)), + this, SLOT(onPeerConnected(NetworkConnection *))); + connect(m_networkServer, SIGNAL(peerDisconnected(NetworkConnection *)), + this, SLOT(onPeerDisconnected(NetworkConnection *))); +} + +GameHost::GameHost(QObject *parent) + : QObject(parent) +{ +} + +GameHost::~GameHost() +{ + delete m_networkServer; +} + +void GameHost::setStatus(Status status) +{ + if (m_status == status) + return; + + m_status = status; + + if (m_status == Match) + newMatch(); +} + +void GameHost::newMatch() +{ + if (m_matchController) { + m_matchController->deleteLater(); + m_matchController = 0; + } + + m_matchController = new MatchController(m_playerListModel, Settings::matchChickenNumber(), + Settings::matchTime(), this); + m_declarativeContext->setContextProperty("matchController", m_matchController); + + connect(m_matchController, SIGNAL(matchOver()), + this, SLOT(onMatchOver())); + + m_playerListModel->notifyMatchReady(); +} + +void GameHost::startConnection() +{ + m_error = NoError; + m_status = NoStatus; + + m_networkServer->start(); +} + +void GameHost::quit() +{ + m_error = NoError; + m_status = NoStatus; + m_networkServer->closeAll(); + + emit ended(); +} + +void GameHost::onPeerConnected(NetworkConnection *connection) +{ + qDebug("Peer connected: %d" , connection->id()); + + addPlayer(connection); +} + +void GameHost::onPeerDisconnected(NetworkConnection *connection) +{ + qDebug("Peer disconnected: %d" , connection->id()); + + removePlayer(connection); +} + +void GameHost::addPlayer(NetworkConnection *connection) +{ + if (m_playerListModel->rowCount() == Global::maximumPlayers) { + qWarning("Maximum number of players reached (%d)", Global::maximumPlayers); + + // TODO: Notify client that host is full + return; + } + + m_playerListModel->newPlayer(connection); +} + +void GameHost::removePlayer(NetworkConnection *connection) +{ + m_playerListModel->removePlayer(connection); +} + +void GameHost::onServerError(NetworkServer::ServerError error) +{ + if (error == NetworkServer::AnotherServerRunningError) + m_error = AnotherServerRunningError; + else + m_error = UnknownError; + + if (m_status == Error) + return; + + m_status = Error; + emit statusChanged(); + + quit(); +} + +void GameHost::onServerStarted() +{ + if (m_status == Start) + return; + + m_status = Start; + emit statusChanged(); +} + +void GameHost::onMatchOver() +{ + m_status = WaitingRoom; + + m_playerListModel->reset(); + m_playerListModel->notifyMatchFinished(); +} + +void GameHost::setConnectivity(const QString &connectivity) +{ + m_networkServer->createConnectionHandler(connectivity); +} diff --git a/chicken-wranglers/src/main/gamehost.h b/chicken-wranglers/src/main/gamehost.h new file mode 100644 index 0000000..795c954 --- /dev/null +++ b/chicken-wranglers/src/main/gamehost.h @@ -0,0 +1,123 @@ +/**************************************************************************** +** +** This file is a part of QtChickenWranglers. +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).* +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +** FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +** COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +** BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +** ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +** POSSIBILITY OF SUCH DAMAGE." +** +****************************************************************************/ + + +#ifndef GAMEHOST_H +#define GAMEHOST_H + +#include <QtCore/QObject> + +#include "networkmessage.h" +#include "networkserver.h" + +class MatchController; +class PlayerListModel; +class QDeclarativeContext; + +class GameHost : public QObject +{ + Q_OBJECT + + Q_PROPERTY(Status status READ status WRITE setStatus NOTIFY statusChanged) + Q_PROPERTY(ErrorType error READ error NOTIFY errorChanged) + + Q_ENUMS(Status ErrorType GameState) + +public: + GameHost(QObject *parent = 0); + GameHost(QDeclarativeContext *context, const QString &connectivity, + QObject *parent = 0); + ~GameHost(); + + void setConnectivity(const QString &connectivity); + + enum Status { + NoStatus, + Start, + WaitingRoom, + Match, + Error + }; + + enum ErrorType { + NoError, + AnotherServerRunningError, + UnknownError + }; + + Status status() { return m_status; } + void setStatus(Status status); + + ErrorType error() { return m_error; } + +public slots: + void startConnection(); + void quit(); + +signals: + void statusChanged(); + void errorChanged(); + void ended(); + +private slots: + void onServerError(NetworkServer::ServerError error); + void onServerStarted(); + + void onPeerConnected(NetworkConnection *connection); + void onPeerDisconnected(NetworkConnection *connection); + + void onMatchOver(); + +private: + void newMatch(); + void addPlayer(NetworkConnection *connection); + void removePlayer(NetworkConnection *connection); + + QDeclarativeContext *m_declarativeContext; + NetworkServer *m_networkServer; + + PlayerListModel *m_playerListModel; + MatchController *m_matchController; + Status m_status; + ErrorType m_error; +}; + +#endif diff --git a/chicken-wranglers/src/main/main.cpp b/chicken-wranglers/src/main/main.cpp new file mode 100644 index 0000000..f98f4e6 --- /dev/null +++ b/chicken-wranglers/src/main/main.cpp @@ -0,0 +1,93 @@ +/**************************************************************************** +** +** This file is a part of QtChickenWranglers. +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).* +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +** FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +** COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +** BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +** ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +** POSSIBILITY OF SUCH DAMAGE." +** +****************************************************************************/ + + +#include <QtGui/QApplication> + +#include "argumentparser.h" +#include "game.h" +#include "global.h" +#include "settings.h" + +int main(int argc, char *argv[]) +{ + QCoreApplication::setOrganizationName(Settings::organizationName()); + QCoreApplication::setOrganizationDomain(Settings::organizationDomain()); + QCoreApplication::setApplicationName(Settings::applicationName()); + + if (!Settings::exists()) + Settings::reset(); + + QApplication app(argc, argv); + ArgumentProcessor options(app.arguments()); + QSize displaySize(options.display()); + + QString tcpPort = options.tcpPort(); + QString udpPort = options.udpPort(); + + if (tcpPort != "-1") + Settings::setLanTcpPort(tcpPort); + if (udpPort != "-1") + Settings::setLanUdpPort(udpPort); + + Settings::update(); + + Global::setScreenOrientation(Global::Landscape); + Game::GraphicsMode mode = options.graphicsMode() == "opengl" ? + Game::OpenGL : Game::Raster; + + Game game(mode); + game.setConnectivity(options.connectivity()); + if (options.connectivity() == "bluetooth") { + // FIXME: this function is not working in Symbian + // and is crashing in Meego 1.2 netbook. Need to discover + // why QBluetoothLocalDevice is misbehaving. + // Global::setPowerOn(); + } + + if (displaySize.isValid()) { + game.start(displaySize); + } else { + game.start(); + } + + return app.exec(); +} diff --git a/chicken-wranglers/src/main/main.pri b/chicken-wranglers/src/main/main.pri new file mode 100644 index 0000000..985062a --- /dev/null +++ b/chicken-wranglers/src/main/main.pri @@ -0,0 +1,18 @@ +QT += declarative + +PATH = $$PWD + +HEADERS += \ + $$PATH/game.h \ + $$PATH/gameclient.h \ + $$PATH/gamehost.h \ + $$PATH/argumentparser.h \ + $$PATH/settings.h + +SOURCES += \ + $$PATH/main.cpp \ + $$PATH/game.cpp \ + $$PATH/gameclient.cpp \ + $$PATH/gamehost.cpp \ + $$PATH/argumentparser.cpp \ + $$PATH/settings.cpp diff --git a/chicken-wranglers/src/main/settings.cpp b/chicken-wranglers/src/main/settings.cpp new file mode 100644 index 0000000..0d476ef --- /dev/null +++ b/chicken-wranglers/src/main/settings.cpp @@ -0,0 +1,284 @@ +/**************************************************************************** +** +** This file is a part of QtChickenWranglers. +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).* +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +** FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +** COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +** BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +** ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +** POSSIBILITY OF SUCH DAMAGE." +** +****************************************************************************/ + + +#include <QtCore/QFileInfo> +#include <QtCore/QString> + +#include "settings.h" + +const QString Settings::m_organizationName = "Nokia"; +const QString Settings::m_organizationDomain = "nokia.com"; +const QString Settings::m_applicationName = "chicken-wranglers"; + +// host +static const QSize defaultHostDisplaySize = QSize(1280, 768); +static const int defaultHostMaximumPlayers = 4; + +// match +static const int defaultMatchChickenNumber = 40; +static const int defaultMatchTime = 180; +static const int defaultMatchChickenMoveInterval = 700; +static const int defaultMatchChickenChangeStepsInterval = 260; +static const int defaultMatchCharacterMoveInterval = 500; +static const int defaultMatchCharacterChangeStepsInterval = 260; + +// battlefield +static const QSize defaultBattlefieldSize = QSize(10, 10); +static const int defaultBattlefieldCellSize = 70; +static const QPoint defaultBattlefieldStartPoint = QPoint(290, 34); + +// local network +static const int defaultLanTcpPort = 35000; +static const int defaultLanUdpPort = 45000; +static const int defaultLanUdpDiscoveryTimeout = 100; +static const int defaultLanUdpDiscoveryClientAttempts = 50; +static const int defaultLanUdpDiscoveryHostAttempts = 10; + +// bluetooth +static const QString defaultBluetoothHostAddress = "00:00:00:00:00:00"; +static const QString defaultBluetoothHostName = ""; + +Settings::Settings(QObject *parent) + : QSettings(QSettings::IniFormat, QSettings::UserScope, + m_organizationName, m_applicationName, parent) +{ +} + +Settings *Settings::instance() +{ + static Settings settings; + + return &settings; +} + +void Settings::update() +{ + instance()->sync(); +} + +QString Settings::organizationName() +{ + return m_organizationName; +} + +QString Settings::organizationDomain() +{ + return m_organizationDomain; +} + +QString Settings::applicationName() +{ + return m_applicationName; +} + +// host + +QSize Settings::hostDisplaySize() +{ + return instance()->value("host/displaySize", QSize()).toSize(); +} + +int Settings::hostMaximumPlayers() +{ + return instance()->value("host/maximumPlayers", defaultHostMaximumPlayers).toInt(); +} + +// match + +int Settings::matchTime() +{ + return instance()->value("match/time", defaultMatchTime).toInt(); +} + +int Settings::matchChickenNumber() +{ + return instance()->value("match/chickenNumber", defaultMatchChickenNumber).toInt(); +} + +int Settings::matchChickenMoveInterval() +{ + return instance()->value("match/chickenMoveInterval", + defaultMatchChickenMoveInterval).toInt(); +} + +int Settings::matchChickenChangeStepsInterval() +{ + return instance()->value("match/chickenChangeStepsInterval", + defaultMatchChickenChangeStepsInterval).toInt(); +} + +int Settings::matchCharacterMoveInterval() +{ + return instance()->value("match/chickenCharacterMoveInterval", + defaultMatchCharacterMoveInterval).toInt(); +} + +int Settings::matchCharacterChangeStepsInterval() +{ + return instance()->value("match/chickenCharacterStepsInterval", + defaultMatchCharacterChangeStepsInterval).toInt(); +} + +// battlefield + +QSize Settings::battlefieldSize() +{ + return instance()->value("battlefield/size", defaultBattlefieldSize).toSize(); +} + +int Settings::battlefieldCellSize() +{ + return instance()->value("battlefield/cellSize", defaultBattlefieldCellSize).toInt(); +} + +QPoint Settings::battlefieldStartPoint() +{ + return instance()->value("battlefield/startPoint", defaultBattlefieldStartPoint).toPoint(); +} + +// local network + +int Settings::lanTcpPort() +{ + return instance()->value("lan/tcpPort", defaultLanTcpPort).toInt(); +} + +void Settings::setLanTcpPort(const QString port) +{ + instance()->setValue("lan/tcpPort", port); +} + +int Settings::lanUdpPort() +{ + return instance()->value("lan/udpPort", defaultLanUdpPort).toInt(); +} + +void Settings::setLanUdpPort(const QString port) +{ + instance()->setValue("lan/udpPort", port); +} + +int Settings::lanUdpDiscoveryTimeout() +{ + return instance()->value("lan/UdpDiscoveryTimeout", defaultLanUdpDiscoveryTimeout).toInt(); +} + +int Settings::lanUdpDiscoveryClientAttempts() +{ + return instance()->value("lan/UdpDiscoveryClientAttempts", + defaultLanUdpDiscoveryClientAttempts).toInt(); +} + +int Settings::lanUdpDiscoveryHostAttempts() +{ + return instance()->value("lan/UdpDiscoveryHostAttempts", + defaultLanUdpDiscoveryHostAttempts).toInt(); +} + +// bluetooth + +QString Settings::bluetoothHostAddress() +{ + return instance()->value("bluetooth/hostAddress", QString()).toString(); +} + +void Settings::setBluetoothHostAddress(const QString &address) +{ + instance()->setValue("bluetooth/hostAddress", address); +} + +QString Settings::bluetoothHostName() +{ + return instance()->value("bluetooth/hostName", QString()).toString(); +} + +void Settings::setBluetoothHostName(const QString &name) +{ + instance()->setValue("bluetooth/hostName", name); +} + +bool Settings::exists() +{ + QFileInfo settingsFileInfo(instance()->fileName()); + + return settingsFileInfo.exists(); +} + +void Settings::reset() +{ + Settings *settings = instance(); + + settings->beginGroup("host"); + settings->setValue("displaySize", defaultHostDisplaySize); + settings->setValue("hostMaximumPlayers", defaultHostMaximumPlayers); + settings->endGroup(); + + settings->beginGroup("match"); + settings->setValue("time", defaultMatchTime); + settings->setValue("chickenNumber", defaultMatchChickenNumber); + settings->setValue("chickenMoveInterval", defaultMatchChickenMoveInterval); + settings->setValue("chickenChangeStepsInterval", defaultMatchChickenChangeStepsInterval); + settings->setValue("characterMoveInterval", defaultMatchCharacterMoveInterval); + settings->setValue("characterChangeStepsInterval", defaultMatchCharacterChangeStepsInterval); + settings->endGroup(); + + settings->beginGroup("battlefield"); + settings->setValue("size", defaultBattlefieldSize); + settings->setValue("cellSize", defaultBattlefieldCellSize); + settings->setValue("startPoint", defaultBattlefieldStartPoint); + settings->endGroup(); + + settings->beginGroup("lan"); + settings->setValue("tcpPort", defaultLanTcpPort); + settings->setValue("udpPort", defaultLanUdpPort); + settings->setValue("udpDiscoveryTimeout", defaultLanUdpDiscoveryTimeout); + settings->setValue("udpDiscoveryClientAttempts", defaultLanUdpDiscoveryClientAttempts); + settings->setValue("udpDiscoveryHostAttempts", defaultLanUdpDiscoveryHostAttempts); + settings->endGroup(); + + settings->beginGroup("bluetooth"); + settings->setValue("hostAddress", defaultBluetoothHostAddress); + settings->setValue("hostName", defaultBluetoothHostName); + settings->endGroup(); + + update(); +} diff --git a/chicken-wranglers/src/main/settings.h b/chicken-wranglers/src/main/settings.h new file mode 100644 index 0000000..1c967f3 --- /dev/null +++ b/chicken-wranglers/src/main/settings.h @@ -0,0 +1,108 @@ +/**************************************************************************** +** +** This file is a part of QtChickenWranglers. +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).* +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +** FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +** COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +** BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +** ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +** POSSIBILITY OF SUCH DAMAGE." +** +****************************************************************************/ + + +#ifndef SETTINGS_H +#define SETTINGS_H + +#include <QtCore/QObject> +#include <QtCore/QSettings> +#include <QtCore/QSize> +#include <QtCore/QPoint> + +class Settings : public QSettings +{ + Q_OBJECT + +public: + static Settings *instance(); + + static void update(); + static bool exists(); + static void reset(); + + static QString organizationName(); + static QString organizationDomain(); + static QString applicationName(); + +public slots: + // host + static QSize hostDisplaySize(); + static int hostMaximumPlayers(); + + // match + static int matchTime(); + static int matchChickenNumber(); + static int matchChickenMoveInterval(); + static int matchChickenChangeStepsInterval(); + static int matchCharacterMoveInterval(); + static int matchCharacterChangeStepsInterval(); + + // battlefield + static QSize battlefieldSize(); + static int battlefieldCellSize(); + static QPoint battlefieldStartPoint(); + + // local network + static int lanTcpPort(); + static void setLanTcpPort(const QString port); + static int lanUdpPort(); + static void setLanUdpPort(const QString port); + static int lanUdpDiscoveryTimeout(); + static int lanUdpDiscoveryClientAttempts(); + static int lanUdpDiscoveryHostAttempts(); + + // bluetooth + static QString bluetoothHostAddress(); + static void setBluetoothHostAddress(const QString &address); + + static QString bluetoothHostName(); + static void setBluetoothHostName(const QString &name); + +private: + explicit Settings(QObject *parent = 0); + + static const QString m_organizationName; + static const QString m_organizationDomain; + static const QString m_applicationName; +}; + +#endif diff --git a/chicken-wranglers/src/models/bluetoothdevice.cpp b/chicken-wranglers/src/models/bluetoothdevice.cpp new file mode 100644 index 0000000..2d72086 --- /dev/null +++ b/chicken-wranglers/src/models/bluetoothdevice.cpp @@ -0,0 +1,110 @@ +/**************************************************************************** +** +** This file is a part of QtChickenWranglers. +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).* +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +** FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +** COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +** BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +** ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +** POSSIBILITY OF SUCH DAMAGE." +** +****************************************************************************/ + + +#include "bluetoothdevice.h" + +BluetoothDevice::BluetoothDevice(QObject *parent) + : QObject(parent) +{ +} + +BluetoothDevice::BluetoothDevice(const BluetoothDevice &device) + : QObject(device.parent()) +{ + operator=(device); +} + +bool BluetoothDevice::operator==(const BluetoothDevice &device) const +{ + return (m_address == device.address()); +} + +BluetoothDevice &BluetoothDevice::operator=(const BluetoothDevice &device) +{ + m_name = device.m_name; + m_address = device.m_address; + m_paired = device.m_paired; + m_category = device.m_category; + + return *this; +} + +void BluetoothDevice::setName(const QString &name) +{ + m_name = name; +} + +QString BluetoothDevice::name() const +{ + return m_name; +} + +void BluetoothDevice::setAddress(const QString &address) +{ + m_address = address; +} + +QString BluetoothDevice::address() const +{ + return m_address; +} + +void BluetoothDevice::setPaired(const bool paired) +{ + m_paired = paired; +} + +bool BluetoothDevice::paired() const +{ + return m_paired; +} + +void BluetoothDevice::setCategory(const quint8 category) +{ + m_category = category; +} + +quint8 BluetoothDevice::category() const +{ + return m_category; +} + diff --git a/chicken-wranglers/src/models/bluetoothdevice.h b/chicken-wranglers/src/models/bluetoothdevice.h new file mode 100644 index 0000000..4bb7a36 --- /dev/null +++ b/chicken-wranglers/src/models/bluetoothdevice.h @@ -0,0 +1,90 @@ +/**************************************************************************** +** +** This file is a part of QtChickenWranglers. +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).* +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +** FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +** COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +** BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +** ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +** POSSIBILITY OF SUCH DAMAGE." +** +****************************************************************************/ + + +#ifndef BLUETOOTHDEVICE_H +#define BLUETOOTHDEVICE_H + +#include <QtCore/QObject> +#include <QtCore/QString> + +class BluetoothDevice : public QObject +{ + Q_OBJECT + + Q_PROPERTY(QString name READ name WRITE setName) + Q_PROPERTY(QString address READ address WRITE setAddress) + Q_PROPERTY(bool paired READ paired WRITE setPaired) + Q_PROPERTY(quint8 category READ category WRITE setCategory) + +public: + BluetoothDevice(QObject *parent = 0); + BluetoothDevice(const BluetoothDevice &device); + + bool operator==(const BluetoothDevice &device) const; + BluetoothDevice &operator=(const BluetoothDevice &device); + + enum Category { + Other, + Computer, + Phone + }; + + void setName(const QString &name); + QString name() const; + + void setAddress(const QString &address); + QString address() const; + + void setPaired(const bool paired); + bool paired() const; + + void setCategory(const quint8 category); + quint8 category() const; + +private: + QString m_name; + QString m_address; + bool m_paired; + quint8 m_category; +}; + +#endif diff --git a/chicken-wranglers/src/models/charactermodel.cpp b/chicken-wranglers/src/models/charactermodel.cpp new file mode 100644 index 0000000..c8f0f53 --- /dev/null +++ b/chicken-wranglers/src/models/charactermodel.cpp @@ -0,0 +1,217 @@ +/**************************************************************************** +** +** This file is a part of QtChickenWranglers. +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).* +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +** FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +** COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +** BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +** ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +** POSSIBILITY OF SUCH DAMAGE." +** +****************************************************************************/ + +#include "charactermodel.h" + +#include "global.h" + +#include <QtCore/QDir> +#include <QtCore/QUrl> +#include <QtDeclarative> +#include <QtGui/QPixmap> + +CharacterModel::CharacterModel(QObject *parent) + : QObject(parent) +{ +} + +CharacterModel::CharacterModel(const QFileInfo &characterPath, QObject *parent) + : QObject(parent), m_path(characterPath.absoluteFilePath()), m_available(true) +{ + // TODO: Maybe we need to check it for a valid directory path + m_characterName = characterPath.baseName(); +} + +CharacterModel::CharacterModel(const QString &characterName, QObject *parent) + : QObject(parent), m_characterName(characterName), + m_path(QFileInfo(basePath() + characterName).absoluteFilePath()) +{ +} + +QString CharacterModel::path() const +{ + return QUrl::fromLocalFile(m_path.toString()).toString(); +} + +QString CharacterModel::basePath() +{ + return Global::rootDirectory().absoluteFilePath() + "/characters/"; +} + +bool CharacterModel::isValid() const +{ + QString iconPath = m_path.toString(QUrl::RemoveScheme) + "/select_character.png"; + + if (QPixmap(iconPath).isNull()) + return false; + + return true; +} + +void CharacterModel::setAvailable(bool available) +{ + if (m_available == available) + return; + + m_available = available; + + emit isAvailableChanged(available); +} + +CharacterListModel::CharacterListModel(QObject *parent) + : QAbstractListModel(parent), m_selectedIndex(-1) +{ + QHash<int, QByteArray> roles; + + roles[PathRole] = "path"; + roles[IsAvailableRole] = "isAvailable"; + + setRoleNames(roles); + + qmlRegisterType<CharacterModel>("game.types", 1, 0, "CharacterModel"); +} + +bool CharacterListModel::load() +{ + QDir characterDir = QDir(CharacterModel::basePath()); + if (!characterDir.exists()) + return false; + + QFlags<QDir::Filter> flags = QDir::Dirs | QDir::NoDotAndDotDot; + QFileInfoList entries = characterDir.entryInfoList(flags, QDir::Time); + + foreach(QFileInfo entry, entries) { + CharacterModel *character = new CharacterModel(entry); + + if (character->isValid()) + addCharacter(character); + else + delete character; + } + + return true; +} + +void CharacterListModel::addCharacter(CharacterModel *character) +{ + beginInsertRows(QModelIndex(), rowCount(), rowCount()); + m_characters << character; + endInsertRows(); + + connect(character, SIGNAL(isAvailableChanged(bool)), + this, SLOT(onIsAvailableChanged(bool))); +} + +int CharacterListModel::rowCount(const QModelIndex &parent) const +{ + Q_UNUSED(parent); + + return m_characters.count(); +} + +QVariant CharacterListModel::data(const QModelIndex &index, int role) const +{ + if (index.row() < 0 || index.row() >= m_characters.count()) + return QVariant(); + + CharacterModel *character = m_characters[index.row()]; + + if (role == PathRole) + return character->path(); + if (role == IsAvailableRole) + return character->isAvailable(); + + return QVariant(); +} + +void CharacterListModel::setSelectedIndex(int selectedIndex) +{ + if (selectedIndex >= m_characters.count()) + return; + + m_selectedIndex = selectedIndex; + + selectedIndexChanged(); +} + +CharacterModel *CharacterListModel::get(int index) const +{ + if (index < 0 || index >= m_characters.count()) + return 0; + + return m_characters.at(index); +} + +CharacterModel *CharacterListModel::selected() const +{ + if (m_selectedIndex < 0 || m_selectedIndex >= m_characters.count()) + return 0; + + return m_characters.at(m_selectedIndex); +} + +QStringList CharacterListModel::characterNameList() +{ + QDir characterDir = QDir(CharacterModel::basePath()); + if (!characterDir.exists()) + return QStringList(); + + QFlags<QDir::Filter> flags = QDir::Dirs | QDir::NoDotAndDotDot; + QFileInfoList entries = characterDir.entryInfoList(flags, QDir::Time); + + QStringList nameList; + + foreach(QFileInfo entry, entries) + nameList.append(entry.baseName()); + + return nameList; +} + +void CharacterListModel::onIsAvailableChanged(bool available) +{ + Q_UNUSED(available) + + CharacterModel *model = qobject_cast<CharacterModel *>(sender()); + + int characterIndex = m_characters.indexOf(model); + + dataChanged(index(characterIndex), index(characterIndex)); +} diff --git a/chicken-wranglers/src/models/charactermodel.h b/chicken-wranglers/src/models/charactermodel.h new file mode 100644 index 0000000..b3e27f7 --- /dev/null +++ b/chicken-wranglers/src/models/charactermodel.h @@ -0,0 +1,121 @@ +/**************************************************************************** +** +** This file is a part of QtChickenWranglers. +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).* +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +** FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +** COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +** BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +** ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +** POSSIBILITY OF SUCH DAMAGE." +** +****************************************************************************/ + + +#ifndef CHARACTERMODEL_H +#define CHARACTERMODEL_H + +#include <QtCore/QAbstractListModel> +#include <QtCore/QFileInfo> +#include <QtCore/QUrl> + +class CharacterModel : public QObject +{ + Q_OBJECT + + Q_PROPERTY(QString path READ path NOTIFY pathChanged) + Q_PROPERTY(bool isAvailable READ isAvailable NOTIFY isAvailableChanged) + +public: + CharacterModel(QObject *parent = 0); + CharacterModel(const QFileInfo &characterPath, QObject *parent = 0); + CharacterModel(const QString &characterName, QObject *parent = 0); + + bool isValid() const; + + QString path() const; + QString name() const { return m_characterName; } + + bool isAvailable() const { return m_available; } + void setAvailable(bool available); + + static QString basePath(); + +signals: + void pathChanged(const QString &path); + void isAvailableChanged(bool available); + +private: + QString m_characterName; + QUrl m_path; + bool m_available; +}; + +class CharacterListModel : public QAbstractListModel +{ + Q_OBJECT + + Q_PROPERTY(int selectedIndex READ selectedIndex WRITE setSelectedIndex NOTIFY selectedIndexChanged) + +public: + enum CharacterRole { + PathRole = Qt::UserRole + 1, + IsAvailableRole + }; + + explicit CharacterListModel(QObject *parent = 0); + + bool load(); + void addCharacter(CharacterModel *character); + + int rowCount(const QModelIndex &parent = QModelIndex()) const; + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; + + int selectedIndex() const { return m_selectedIndex; } + void setSelectedIndex(int selectedIndex); + + static QStringList characterNameList(); + + Q_INVOKABLE CharacterModel *get(int index) const; + Q_INVOKABLE CharacterModel *selected() const; + +signals: + void selectedIndexChanged(); + +private slots: + void onIsAvailableChanged(bool available); + +private: + QList<CharacterModel *> m_characters; + int m_selectedIndex; +}; + +#endif diff --git a/chicken-wranglers/src/models/connectivitylistmodel.cpp b/chicken-wranglers/src/models/connectivitylistmodel.cpp new file mode 100644 index 0000000..46c4a19 --- /dev/null +++ b/chicken-wranglers/src/models/connectivitylistmodel.cpp @@ -0,0 +1,151 @@ +/**************************************************************************** +** +** This file is a part of QtChickenWranglers. +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).* +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +** FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +** COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +** BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +** ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +** POSSIBILITY OF SUCH DAMAGE." +** +****************************************************************************/ + +#include "connectivitylistmodel.h" + +#include "settings.h" + +ConnectivityListModel::ConnectivityListModel(QObject *parent) + : QAbstractListModel(parent), m_selectedIndex(-1) +{ + QHash<int, QByteArray> roles; + + roles[NameRole] = "name"; + roles[AddressRole] = "address"; + + setRoleNames(roles); +} + +void ConnectivityListModel::addDevice(const BluetoothDevice &device) +{ + for (int i = 0; i < m_devices.count(); i++) { + if (m_devices[i] == device) { + if ((m_devices[i].name() == m_devices[i].address()) + && device.name() != device.address()) { + + m_devices[i].setName(device.name()); + emit dataChanged(index(i), index(i)); + } + + return; + } + } + + beginInsertRows(QModelIndex(), rowCount(), rowCount()); + m_devices << device; + endInsertRows(); +} + +int ConnectivityListModel::rowCount(const QModelIndex &parent) const +{ + Q_UNUSED(parent); + + return m_devices.count(); +} + +QVariant ConnectivityListModel::data(const QModelIndex &index, int role) const +{ + if (index.row() < 0 || index.row() > m_devices.count()) + return QVariant(); + + const BluetoothDevice &device = m_devices[index.row()]; + + if (role == NameRole) + return device.name(); + else if (role == AddressRole) + return device.address(); + + return QVariant(); +} + +void ConnectivityListModel::setSelectedIndex(int selectedIndex) +{ + if (selectedIndex >= m_devices.count()) + return; + + m_selectedIndex = selectedIndex; + + emit selectedIndexChanged(); + + emit selectedDevice(m_devices[m_selectedIndex].address()); +} + +void ConnectivityListModel::clear() +{ + if (!rowCount()) + return; + + beginRemoveRows(QModelIndex(), 0, rowCount() - 1); + m_devices.clear(); + endRemoveRows(); +} + +void ConnectivityListModel::storeLastHostDevice() +{ + if (m_selectedIndex == -1 || m_selectedIndex >= m_devices.count()) + return; + + BluetoothDevice device = m_devices[m_selectedIndex]; + Settings::setBluetoothHostAddress(device.address()); + Settings::setBluetoothHostName(device.name()); +} + +void ConnectivityListModel::loadLastHostDevice() +{ + BluetoothDevice device; + + QString address = Settings::bluetoothHostAddress(); + QString name = Settings::bluetoothHostName(); + + if (address == "00:00:00:00:00:00" || address.isEmpty()) + return; + + device.setAddress(address); + if (!name.isEmpty()) + device.setName(name); + else + device.setName(address); + + addDevice(device); + + m_selectedIndex = m_devices.indexOf(device); + emit selectedIndexChanged(); +} diff --git a/chicken-wranglers/src/models/connectivitylistmodel.h b/chicken-wranglers/src/models/connectivitylistmodel.h new file mode 100644 index 0000000..a81d693 --- /dev/null +++ b/chicken-wranglers/src/models/connectivitylistmodel.h @@ -0,0 +1,86 @@ +/**************************************************************************** +** +** This file is a part of QtChickenWranglers. +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).* +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +** FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +** COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +** BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +** ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +** POSSIBILITY OF SUCH DAMAGE." +** +****************************************************************************/ + + +#ifndef CONNECTIVITYLISTMODEL_H +#define CONNECTIVITYLISTMODEL_H + +#include "bluetoothdevice.h" + +#include <QtCore/QAbstractListModel> + +class ConnectivityListModel : public QAbstractListModel +{ + Q_OBJECT + + Q_PROPERTY(int selectedIndex READ selectedIndex WRITE setSelectedIndex NOTIFY selectedIndexChanged) + +public: + enum DeviceRole { + NameRole = Qt::UserRole + 1, + AddressRole + }; + + ConnectivityListModel(QObject *parent = 0); + + int rowCount(const QModelIndex &parent = QModelIndex()) const; + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; + + int selectedIndex() const { return m_selectedIndex; } + void setSelectedIndex(int selectedIndex); + + void storeLastHostDevice(); + void loadLastHostDevice(); + +public slots: + void addDevice(const BluetoothDevice &device); + void clear(); + +signals: + void selectedDevice(const QString &deviceAddress); + void selectedIndexChanged(); + +private: + QList<BluetoothDevice> m_devices; + int m_selectedIndex; +}; + +#endif diff --git a/chicken-wranglers/src/models/models.pri b/chicken-wranglers/src/models/models.pri new file mode 100644 index 0000000..9859eff --- /dev/null +++ b/chicken-wranglers/src/models/models.pri @@ -0,0 +1,15 @@ +QT += declarative + +PATH = $$PWD + +HEADERS += \ + $$PATH/charactermodel.h \ + $$PATH/playermodel.h \ + $$PATH/bluetoothdevice.h \ + $$PATH/connectivitylistmodel.h + +SOURCES += \ + $$PATH/charactermodel.cpp \ + $$PATH/playermodel.cpp \ + $$PATH/bluetoothdevice.cpp \ + $$PATH/connectivitylistmodel.cpp diff --git a/chicken-wranglers/src/models/playermodel.cpp b/chicken-wranglers/src/models/playermodel.cpp new file mode 100644 index 0000000..f1ccab0 --- /dev/null +++ b/chicken-wranglers/src/models/playermodel.cpp @@ -0,0 +1,466 @@ +/**************************************************************************** +** +** This file is a part of QtChickenWranglers. +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).* +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +** FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +** COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +** BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +** ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +** POSSIBILITY OF SUCH DAMAGE." +** +****************************************************************************/ + +#include "playermodel.h" + +#include "charactermodel.h" +#include "networkconnection.h" + +#include <QtDeclarative> + +PlayerModel::PlayerModel(QObject *parent) + : QObject(parent) +{ +} + +PlayerModel::PlayerModel(NetworkConnection *connection, QObject *parent) + : QObject(parent), m_character(0), m_connection(connection), + m_status(NoCharacter), m_direction(Global::DirectionStop), + m_isLeader(false), m_score(0) +{ + connect(connection, SIGNAL(received(NetworkMessage)), + this, SLOT(onNetworkMessageReceived(NetworkMessage))); +} + +PlayerModel::~PlayerModel() +{ + if (!characterName().isEmpty()) + emit characterReleased(characterName()); +} + +QString PlayerModel::characterPath() const +{ + if (m_character) + return m_character->path(); + else + return QString(); +} + +QString PlayerModel::characterName() const +{ + if (m_character) + return m_character->name(); + else + return QString(); +} + +bool PlayerModel::setCharacter(const QString &characterName) +{ + PlayerListModel *listModel = qobject_cast<PlayerListModel *>(parent()); + if (!listModel) { + qWarning() << "Invalid PlayerListModel"; + return false; + } + + if (!listModel->availableCharacters().contains(characterName)) + return false; + + // TODO: Check if it is safe to set a new character when + // the player has already selected one. + if (m_character && m_character->name() == characterName) { + qWarning() << "Player has already an associated character"; + return false; + } + + m_character = new CharacterModel(characterName, this); + m_status = Ready; + + emit characterPathChanged(); + emit characterSelected(characterName); + + return true; +} + +bool PlayerModel::unsetCharacter(const QString &characterName) +{ + if (!m_character) { + qWarning() << "Player has no associated character"; + return false; + } + + m_character->deleteLater(); + m_character = 0; + + m_status = NoCharacter; + + emit characterPathChanged(); + emit characterReleased(characterName); + + return true; +} + +void PlayerModel::setLeader(bool isLeader) +{ + if (m_isLeader == isLeader) + return; + + m_isLeader = isLeader; + + notifyPlayerLeader(m_isLeader); +} + +void PlayerModel::setScore(int score) +{ + if (m_score == score) + return; + + m_score = score; + + emit scoreChanged(); +} + +void PlayerModel::reset() +{ + // TODO: Check what we need to cleanup at this point + m_score = 0; + m_direction = Global::DirectionStop; +} + +void PlayerModel::setDirection(Global::Direction direction) +{ + if (m_direction == direction) + return; + + m_direction = direction; + + emit directionChanged(); +} + +void PlayerModel::notifyCharacterAvailableList(const QStringList &availableCharacters) +{ + QString availableCharactersString = availableCharacters.join("|"); + + NetworkMessage message(CW::CharacterMessageType, CW::CharacterAvailableList); + message.setData(availableCharactersString.toLatin1()); + + m_connection->send(message); +} + +void PlayerModel::notifyCharacterIsAvailable(const QString &characterName, bool available) +{ + QByteArray data; + data.append(characterName); + data.append("|"); + + if (available) + data.append("1"); + else + data.append("0"); + + NetworkMessage message(CW::CharacterMessageType, CW::CharacterIsAvailable); + message.setData(data); + + m_connection->send(message); +} + +void PlayerModel::notifyPlayerLeader(bool isLeader) +{ + QByteArray data; + + if (isLeader) + data.append("1"); + else + data.append("0"); + + NetworkMessage message(CW::PlayerInfoMessageType, CW::PlayerInfoLeader); + message.setData(data); + + m_connection->send(message); +} + +void PlayerModel::onNetworkMessageReceived(const NetworkMessage &message) +{ + switch (message.type()) { + case CW::CharacterMessageType: + handleCharacterMessage(message); + break; + case CW::PlayerControlMessageType: + handlePlayerControlMessage(message); + break; + default: + qWarning("Invalid network message type"); + } +} + +void PlayerModel::handleCharacterMessage(const NetworkMessage &message) +{ + switch (message.content()) { + case CW::CharacterSelected: + setCharacter(QString(message.data())); + break; + + case CW::CharacterReleased: + unsetCharacter(characterName()); + break; + + default: + qWarning("Invalid character message"); + } +} + +// FIXME: Move the two static functions below to a better place +static Global::Direction playerControlToDirection(CW::PlayerControl control) +{ + QMap<CW::PlayerControl, Global::Direction> direction; + + direction[CW::PlayerControlUp] = Global::DirectionUp; + direction[CW::PlayerControlDown] = Global::DirectionDown; + direction[CW::PlayerControlRight] = Global::DirectionRight; + direction[CW::PlayerControlLeft] = Global::DirectionLeft; + direction[CW::PlayerControlStop] = Global::DirectionStop; + + return direction[control]; +} + +static Global::LaserDirection playerControlToLaserDirection(CW::PlayerControl control) +{ + QMap<CW::PlayerControl, Global::LaserDirection> laserDirection; + + laserDirection[CW::PlayerControlLaserUp] = Global::LaserUp; + laserDirection[CW::PlayerControlLaserDown] = Global::LaserDown; + laserDirection[CW::PlayerControlLaserRight] = Global::LaserRight; + laserDirection[CW::PlayerControlLaserLeft] = Global::LaserLeft; + + return laserDirection[control]; +} + +void PlayerModel::handlePlayerControlMessage(const NetworkMessage &message) +{ + CW::PlayerControl control = static_cast<CW::PlayerControl>(message.content()); + + switch (control) { + case CW::PlayerControlLaserUp: + case CW::PlayerControlLaserDown: + case CW::PlayerControlLaserLeft: + case CW::PlayerControlLaserRight: + requestLaserToggle(playerControlToLaserDirection(control)); + break; + case CW::PlayerControlUp: + case CW::PlayerControlDown: + case CW::PlayerControlLeft: + case CW::PlayerControlRight: + case CW::PlayerControlStop: + setDirection(playerControlToDirection(control)); + break; + default: + qWarning("Invalid player control message"); + } +} + +void PlayerModel::requestLaserToggle(Global::LaserDirection laserDirection) +{ + emit laserToggleRequested(laserDirection); +} + +PlayerListModel::PlayerListModel(QObject *parent) + : QAbstractListModel(parent), m_playersReady(false) +{ + QHash<int, QByteArray> roles; + + roles[StatusRole] = "status"; + roles[CharacterPathRole] = "characterPath"; + + setRoleNames(roles); + + qmlRegisterType<PlayerModel>("game.types", 1, 0, "PlayerModel"); + + m_availableCharacters = CharacterListModel::characterNameList(); +} + +void PlayerListModel::newPlayer(NetworkConnection *connection) +{ + PlayerModel *player = new PlayerModel(connection, this); + + beginInsertRows(QModelIndex(), rowCount(), rowCount()); + m_players << player; + endInsertRows(); + + connect(player, SIGNAL(characterPathChanged()), + this, SLOT(onCharacterPathChanged())); + connect(player, SIGNAL(characterSelected(QString)), + this, SLOT(onCharacterSelected(QString))); + connect(player, SIGNAL(characterReleased(QString)), + this, SLOT(onCharacterReleased(QString))); + + // A new player has joined, so he is not yet until he + // has chosen a character. + setPlayersReady(false); + + // Check if player is the first one connected, which + // makes him the leader. This enables some special + // abilities for his client, such as start/end a match. + if (m_players.size() == 1) + player->setLeader(true); + + player->notifyCharacterAvailableList(m_availableCharacters); +} + +void PlayerListModel::removePlayer(NetworkConnection *connection) +{ + foreach (PlayerModel *model, m_players) { + if (connection == model->connection()) { + int index = m_players.indexOf(model); + + beginRemoveRows(QModelIndex(), index, index); + m_players.removeAt(index); + endRemoveRows(); + + model->deleteLater(); + break; + } + } + + checkPlayersReady(); +} + +int PlayerListModel::rowCount(const QModelIndex &parent) const +{ + Q_UNUSED(parent); + + return m_players.count(); +} + +QVariant PlayerListModel::data(const QModelIndex &index, int role) const +{ + if (index.row() < 0 || index.row() >= m_players.count()) + return QVariant(); + + PlayerModel *player = m_players[index.row()]; + + if (role == StatusRole) + return player->status(); + if (role == CharacterPathRole) + return player->characterPath(); + + return QVariant(); +} + +void PlayerListModel::reset() +{ + foreach (PlayerModel *player, m_players) + player->reset(); +} + +void PlayerListModel::setPlayersReady(bool playersReady) +{ + if (m_playersReady == playersReady) + return; + + m_playersReady = playersReady; + + emit playersReadyChanged(); +} + +void PlayerListModel::checkPlayersReady() +{ + if (m_players.size() == 0) { + setPlayersReady(false); + return; + } + + foreach(PlayerModel *player, m_players) { + if (player->status() != PlayerModel::Ready) { + setPlayersReady(false); + return; + } + } + + setPlayersReady(true); +} + +PlayerModel *PlayerListModel::get(int index) const +{ + if (index < 0 || index >= m_players.count()) + return 0; + + return m_players.at(index); +} + +void PlayerListModel::onCharacterPathChanged() +{ + PlayerModel *playerModel = qobject_cast<PlayerModel *>(sender()); + + int playerModelIndex = m_players.indexOf(playerModel); + + emit dataChanged(index(playerModelIndex), index(playerModelIndex)); +} + +void PlayerListModel::onCharacterSelected(const QString &characterName) +{ + m_availableCharacters.removeAll(characterName); + + PlayerModel *senderModel = qobject_cast<PlayerModel *>(sender()); + + foreach (PlayerModel *model, m_players) + if (senderModel != model) + model->notifyCharacterIsAvailable(characterName, false); + + checkPlayersReady(); +} + +void PlayerListModel::onCharacterReleased(const QString &characterName) +{ + if (m_availableCharacters.contains(characterName)) + return; + + m_availableCharacters.append(characterName); + + foreach (PlayerModel *model, m_players) + model->notifyCharacterIsAvailable(characterName, true); + + checkPlayersReady(); +} + +void PlayerListModel::notifyMatchReady() +{ + NetworkMessage message(CW::MatchMessageType, CW::MatchReady); + + foreach (PlayerModel *model, m_players) + model->connection()->send(message); +} + +void PlayerListModel::notifyMatchFinished() +{ + NetworkMessage message(CW::MatchMessageType, CW::MatchFinished); + + foreach (PlayerModel *model, m_players) + model->connection()->send(message); +} diff --git a/chicken-wranglers/src/models/playermodel.h b/chicken-wranglers/src/models/playermodel.h new file mode 100644 index 0000000..2bd1d34 --- /dev/null +++ b/chicken-wranglers/src/models/playermodel.h @@ -0,0 +1,175 @@ +/**************************************************************************** +** +** This file is a part of QtChickenWranglers. +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).* +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +** FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +** COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +** BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +** ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +** POSSIBILITY OF SUCH DAMAGE." +** +****************************************************************************/ + + +#ifndef PLAYERMODEL_H +#define PLAYERMODEL_H + +#include "global.h" + +#include "networkmessage.h" + +#include <QtCore/QAbstractListModel> +#include <QtCore/QStringList> +#include <QtNetwork/QHostAddress> + +class CharacterModel; +class NetworkConnection; + +class PlayerModel : public QObject +{ + Q_OBJECT + Q_ENUMS(Status) + + Q_PROPERTY(QString characterPath READ characterPath NOTIFY characterPathChanged) + Q_PROPERTY(QString direction READ directionString NOTIFY directionChanged) + Q_PROPERTY(int score READ score NOTIFY scoreChanged) + +public: + PlayerModel(QObject *parent = 0); + PlayerModel(NetworkConnection *connection, QObject *parent = 0); + ~PlayerModel(); + + enum Status { + NoCharacter, + Ready, + Playing + }; + + QString characterPath() const; + Status status() const { return m_status; } + NetworkConnection *connection() const { return m_connection; } + + bool setCharacter(const QString &characterName); + bool unsetCharacter(const QString &characterName); + + void setLeader(bool isLeader); + bool isLeader() const { return m_isLeader; } + + void setScore(int score); + int score() const { return m_score; } + + void reset(); + + QString directionString() const { return Global::directionString(m_direction); } + Global::Direction direction() const { return m_direction; } + void setDirection(Global::Direction direction); + + void notifyCharacterAvailableList(const QStringList &availableCharacters); + void notifyCharacterIsAvailable(const QString &characterName, bool available); + void notifyPlayerLeader(bool isLeader); + + QString characterName() const; + +signals: + void characterPathChanged(); + void directionChanged(); + void scoreChanged(); + void characterSelected(const QString &characterName); + void characterReleased(const QString &characterName); + void laserToggleRequested(Global::LaserDirection laserDirection); + +private slots: + void onNetworkMessageReceived(const NetworkMessage &message); + +private: + void handleCharacterMessage(const NetworkMessage &message); + void handlePlayerControlMessage(const NetworkMessage &message); + + void requestLaserToggle(Global::LaserDirection laserDirection); + + CharacterModel *m_character; + NetworkConnection *m_connection; + Status m_status; + Global::Direction m_direction; + bool m_isLeader; + int m_score; +}; + +class PlayerListModel : public QAbstractListModel +{ + Q_OBJECT + + Q_PROPERTY(bool playersReady READ playersReady NOTIFY playersReadyChanged) + +public: + enum PlayerRole { + StatusRole = Qt::UserRole + 1, + CharacterPathRole + }; + + explicit PlayerListModel(QObject *parent = 0); + + void newPlayer(NetworkConnection *connection); + void removePlayer(NetworkConnection *connection); + + int rowCount(const QModelIndex &parent = QModelIndex()) const; + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; + + QStringList availableCharacters() const { return m_availableCharacters; } + void reset(); + + void notifyMatchReady(); + void notifyMatchFinished(); + + // Used by QML views + Q_INVOKABLE PlayerModel *get(int index) const; + Q_INVOKABLE int count() const { return rowCount(); } + +signals: + void playersReadyChanged(); + +private slots: + void onCharacterPathChanged(); + void onCharacterSelected(const QString &characterName); + void onCharacterReleased(const QString &characterName); + +private: + bool playersReady() const { return m_playersReady; } + void setPlayersReady(bool playersReady); + void checkPlayersReady(); + + QList<PlayerModel *> m_players; + QStringList m_availableCharacters; + bool m_playersReady; +}; + +#endif diff --git a/chicken-wranglers/src/network/bluetoothconnection.cpp b/chicken-wranglers/src/network/bluetoothconnection.cpp new file mode 100644 index 0000000..b315fbc --- /dev/null +++ b/chicken-wranglers/src/network/bluetoothconnection.cpp @@ -0,0 +1,119 @@ +/**************************************************************************** +** +** This file is a part of QtChickenWranglers. +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).* +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +** FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +** COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +** BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +** ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +** POSSIBILITY OF SUCH DAMAGE." +** +****************************************************************************/ + + +#include <QBluetoothAddress> +#include <QtCore/QByteArray> + +#include "bluetoothconnection.h" + +BluetoothConnection::BluetoothConnection(QObject *parent, QBluetoothSocket *socket) + : NetworkConnection(parent), m_socket(socket) +{ + if (m_socket == 0) + m_socket = new QBluetoothSocket(QBluetoothSocket::RfcommSocket, this); + + connect(m_socket, SIGNAL(connected()), + this, SIGNAL(connected())); + connect(m_socket, SIGNAL(disconnected()), + this, SIGNAL(disconnected())); + connect(m_socket, SIGNAL(error(QBluetoothSocket::SocketError)), + this, SIGNAL(error(QBluetoothSocket::SocketError))); + connect(m_socket, SIGNAL(readyRead()), + this, SLOT(processReadyRead())); +} + +BluetoothConnection::~BluetoothConnection() +{ + if (m_socket) + m_socket->abort(); +} + +void BluetoothConnection::setId(const quint16 &newId) +{ + m_id = newId; +} + +quint16 BluetoothConnection::id() const +{ + return m_id; +} + +void BluetoothConnection::send(NetworkMessage message) +{ + if (m_socket->write(message.byteArray()) == -1) + qWarning("Bluetooth Socket write error: %s", m_socket->errorString().toUtf8().constData()); +} + +void BluetoothConnection::connectToHost(const QString &address, const quint16 &port) +{ + m_socket->connectToService(QBluetoothAddress(address), port); +} + +void BluetoothConnection::disconnectFromHost() +{ + m_socket->disconnectFromService(); +} + +QAbstractSocket::SocketState BluetoothConnection::state() const +{ + return static_cast<QAbstractSocket::SocketState>(m_socket->state()); +} + +QAbstractSocket::SocketError BluetoothConnection::error() const +{ + return static_cast<QAbstractSocket::SocketError>(m_socket->error()); +} + +QString BluetoothConnection::errorString() const +{ + return m_socket->errorString(); +} + +void BluetoothConnection::processReadyRead() +{ + processRead(m_socket); +} + +void BluetoothConnection::close() +{ + m_socket.data()->close(); +} diff --git a/chicken-wranglers/src/network/bluetoothconnection.h b/chicken-wranglers/src/network/bluetoothconnection.h new file mode 100644 index 0000000..a37c5d8 --- /dev/null +++ b/chicken-wranglers/src/network/bluetoothconnection.h @@ -0,0 +1,89 @@ +/**************************************************************************** +** +** This file is a part of QtChickenWranglers. +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).* +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +** FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +** COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +** BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +** ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +** POSSIBILITY OF SUCH DAMAGE." +** +****************************************************************************/ + + +#ifndef BLUETOOTHCONNECTION_H +#define BLUETOOTHCONNECTION_H + +#include "networkconnection.h" + +#include <QBluetoothSocket> +#include <QtCore/QObject> +#include <QtCore/QPointer> +#include <QtNetwork/QHostAddress> + +QTM_USE_NAMESPACE + +class BluetoothConnection : public NetworkConnection +{ + Q_OBJECT + +public: + BluetoothConnection(QObject *parent = 0, QBluetoothSocket *socket = 0); + ~BluetoothConnection(); + + void setId(const quint16 &newId); + quint16 id() const; + + void send(NetworkMessage message); + + void connectToHost(const QString &address, const quint16 &port); + void disconnectFromHost(); + + QAbstractSocket::SocketState state() const; + QAbstractSocket::SocketError error() const; + QString errorString() const; + + void close(); + +signals: + void connected(); + void disconnected(); + void error(QBluetoothSocket::SocketError socketError); + +private slots: + void processReadyRead(); + +private: + QPointer<QBluetoothSocket> m_socket; +}; + +#endif diff --git a/chicken-wranglers/src/network/bluetoothhandler.cpp b/chicken-wranglers/src/network/bluetoothhandler.cpp new file mode 100644 index 0000000..feb5244 --- /dev/null +++ b/chicken-wranglers/src/network/bluetoothhandler.cpp @@ -0,0 +1,198 @@ +/**************************************************************************** +** +** This file is a part of QtChickenWranglers. +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).* +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +** FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +** COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +** BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +** ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +** POSSIBILITY OF SUCH DAMAGE." +** +****************************************************************************/ + +#include "bluetoothhandler.h" + +#include "connectionfactory.h" +#include "network.h" +#include "networkconnection.h" + +BluetoothHandler::BluetoothHandler(QObject *parent, int maxConnections) + : QRfcommServer(parent), m_serviceInfo(QBluetoothServiceInfo()) + , m_listenPort(14), m_maxConnections(maxConnections) +{ + connect(this, SIGNAL(newConnection()), this, SLOT(newClientConnection())); +} + +BluetoothHandler::~BluetoothHandler() +{ + closeAll(); + stop(); +} + +void BluetoothHandler::start() +{ + if (isListening()) { + emit started(); + return; + } + + QBluetoothAddress address; + + if (listen(address, m_listenPort)) { + qWarning("Server started on port: %d", serverPort()); + emit started(); + registerService(); + } else { + qWarning("Error: Unable to start server"); + emit startError(); + } +} + +void BluetoothHandler::stop() +{ + if (isListening()) + close(); + + m_serviceInfo.unregisterService(); +} + +void BluetoothHandler::setListenPort(const quint16 &port) +{ + if (m_listenPort != port) { + m_listenPort = port; + + emit listenPortChanged(); + } +} + +quint16 BluetoothHandler::listenPort() const +{ + return m_listenPort; +} + +void BluetoothHandler::newClientConnection() +{ + if (m_connections.size() == m_maxConnections) + return; + + NetworkConnection *connection; + connection = ConnectionFactory::create(ConnectionFactory::Bluetooth, + this, nextPendingConnection()); + + for (quint16 id = 0; id < m_maxConnections; id++) { + // If the peer ID is NOT on the dictionary, insert it + if (!m_connections.contains(id)) { + connection->setId(id); + + connect(connection, SIGNAL(disconnected()), + this, SLOT(peerDisconnected())); + connect(connection, SIGNAL(error(QBluetoothSocket::SocketError)), + this, SLOT(socketError(QBluetoothSocket::SocketError))); + connect(connection, SIGNAL(received(NetworkMessage)), + this, SIGNAL(received(NetworkMessage))); + + m_connections[id] = connection; + + // Signals that a new peer has connected + emit peerConnected(connection); + + break; + } + } +} + +void BluetoothHandler::closeAll() +{ + NetworkConnection *tmp; + int pos = 0; + while (m_connections.size()) { + tmp = m_connections[pos]; + tmp->close(); + delete tmp; + ++pos; + } + + m_connections.clear(); +} + +void BluetoothHandler::send(const NetworkMessage &message) +{ + m_connections[message.id()]->send(message); +} + +void BluetoothHandler::peerDisconnected() +{ + NetworkConnection *connection = qobject_cast<NetworkConnection *>(sender()); + m_connections.remove(connection->id()); + + // Signals that a peer has disconnected + emit peerDisconnected(connection); +} + +void BluetoothHandler::socketError(QBluetoothSocket::SocketError socketError) +{ + NetworkConnection *connection = qobject_cast<NetworkConnection *>(sender()); + quint16 id = connection->id(); + + qWarning("Bluetooth Socket error [ %d ]: %s", socketError, + connection->errorString().toUtf8().constData()); + emit peerError(static_cast<QAbstractSocket::SocketError>(socketError), id); +} + +void BluetoothHandler::registerService() +{ + m_serviceInfo.setAttribute(QBluetoothServiceInfo::ServiceRecordHandle, (uint) 0x00010010); + + // TODO: Profile Descriptor List: "Serial Port" (0x1101) + QBluetoothServiceInfo::Sequence classId; + classId << QVariant::fromValue(QBluetoothUuid(QBluetoothUuid::SerialPort)); + m_serviceInfo.setAttribute(QBluetoothServiceInfo::ServiceClassIds, classId); + + m_serviceInfo.setAttribute(QBluetoothServiceInfo::ServiceName, + tr("ChickenWranglers")); + m_serviceInfo.setAttribute(QBluetoothServiceInfo::ServiceDescription, + tr("Game bluetooth server")); + m_serviceInfo.setAttribute(QBluetoothServiceInfo::ServiceProvider, + tr("Openbossa")); + m_serviceInfo.setAttribute(QBluetoothServiceInfo::BrowseGroupList, + QBluetoothUuid(QBluetoothUuid::PublicBrowseGroup)); + + QBluetoothServiceInfo::Sequence protocolDescriptorList; + QBluetoothServiceInfo::Sequence protocol; + protocol << QVariant::fromValue(QBluetoothUuid(QBluetoothUuid::Rfcomm)) + << QVariant::fromValue(quint8(serverPort())); + protocolDescriptorList.append(QVariant::fromValue(protocol)); + m_serviceInfo.setAttribute(QBluetoothServiceInfo::ProtocolDescriptorList, + protocolDescriptorList); + + m_serviceInfo.registerService(); +} diff --git a/chicken-wranglers/src/network/bluetoothhandler.h b/chicken-wranglers/src/network/bluetoothhandler.h new file mode 100644 index 0000000..5248fc3 --- /dev/null +++ b/chicken-wranglers/src/network/bluetoothhandler.h @@ -0,0 +1,100 @@ +/**************************************************************************** +** +** This file is a part of QtChickenWranglers. +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).* +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +** FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +** COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +** BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +** ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +** POSSIBILITY OF SUCH DAMAGE." +** +****************************************************************************/ + + +#ifndef BLUETOOTHHANDLER_H +#define BLUETOOTHHANDLER_H + +#include "networkmessage.h" + +#include <QBluetoothServiceInfo> +#include <QBluetoothSocket> +#include <QRfcommServer> +#include <QtCore/QHash> + +class NetworkConnection; + +QTM_USE_NAMESPACE + +class BluetoothHandler : public QRfcommServer +{ + Q_OBJECT + + Q_PROPERTY(quint16 listenPort READ listenPort WRITE setListenPort NOTIFY listenPortChanged) + +public: + BluetoothHandler(QObject *parent = 0, int maxConnections = 4); + ~BluetoothHandler(); + + void start(); + void stop(); + + void setListenPort(const quint16 &port); + quint16 listenPort() const; + + void send(const NetworkMessage &message); + void closeAll(); + +signals: + void peerConnected(NetworkConnection *connection); + void peerDisconnected(NetworkConnection *connection); + void peerError(QAbstractSocket::SocketError socketError, quint16 id); + void received(const NetworkMessage &message); + void started(); + void listenPortChanged(); + void startError(); + +private slots: + void newClientConnection(); + void peerDisconnected(); + void socketError(QBluetoothSocket::SocketError socketError); + +protected: + void registerService(); + +private: + QHash<quint16, NetworkConnection *> m_connections; + QBluetoothServiceInfo m_serviceInfo; + quint16 m_listenPort; + int m_maxConnections; +}; + +#endif diff --git a/chicken-wranglers/src/network/bthandler.cpp b/chicken-wranglers/src/network/bthandler.cpp new file mode 100644 index 0000000..60d8e08 --- /dev/null +++ b/chicken-wranglers/src/network/bthandler.cpp @@ -0,0 +1,88 @@ +/**************************************************************************** +** +** This file is a part of QtChickenWranglers. +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).* +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +** FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +** COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +** BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +** ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +** POSSIBILITY OF SUCH DAMAGE." +** +****************************************************************************/ + + +#include <QBluetoothAddress> +#include <QBluetoothDeviceDiscoveryAgent> +#include <QBluetoothLocalDevice> + +#include "bthandler.h" + +BtHandler::BtHandler(QObject *parent) + : QObject(parent), m_discoveryAgent(new QBluetoothDeviceDiscoveryAgent(this)), + m_localDevice(new QBluetoothLocalDevice(this)), m_devices(new QList<BluetoothDevice>) +{ + connect(m_discoveryAgent, SIGNAL(deviceDiscovered(const QBluetoothDeviceInfo &)), + this, SLOT(deviceDiscovered(const QBluetoothDeviceInfo &))); +} + +BtHandler::~BtHandler() +{ + delete m_devices; +} + +void BtHandler::enable() +{ + m_discoveryAgent->start(); +} + +void BtHandler::disable() +{ + m_discoveryAgent->stop(); +} + +void BtHandler::deviceDiscovered(const QBluetoothDeviceInfo &deviceInfo) +{ + BluetoothDevice device; + + device.setAddress(deviceInfo.address().toString()); + if (deviceInfo.name().isEmpty()) + device.setName(device.address()); + else + device.setName(deviceInfo.name()); + + device.setPaired(m_localDevice->pairingStatus(deviceInfo.address())); + device.setCategory(quint8(deviceInfo.majorDeviceClass())); + + m_devices->append(device); + + emit discovered(device); +} diff --git a/chicken-wranglers/src/network/bthandler.h b/chicken-wranglers/src/network/bthandler.h new file mode 100644 index 0000000..243bca5 --- /dev/null +++ b/chicken-wranglers/src/network/bthandler.h @@ -0,0 +1,86 @@ +/**************************************************************************** +** +** This file is a part of QtChickenWranglers. +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).* +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +** FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +** COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +** BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +** ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +** POSSIBILITY OF SUCH DAMAGE." +** +****************************************************************************/ + + +#ifndef BTHANDLER_H +#define BTHANDLER_H + +#include "bluetoothdevice.h" + +#include <QtCore/QList> +#include <QtCore/QObject> +#include <qmobilityglobal.h> + +QTM_BEGIN_NAMESPACE + +class QBluetoothDeviceDiscoveryAgent; +class QBluetoothDeviceInfo; +class QBluetoothLocalDevice; + +QTM_END_NAMESPACE + +QTM_USE_NAMESPACE + +class BtHandler : public QObject +{ + Q_OBJECT + +public: + BtHandler(QObject *parent = 0); + ~BtHandler(); + + void enable(); + void disable(); + +signals: + void finished(); + void discovered(const BluetoothDevice &device); + +private slots: + void deviceDiscovered(const QBluetoothDeviceInfo &deviceInfo); + +private: + QBluetoothDeviceDiscoveryAgent *m_discoveryAgent; + QBluetoothLocalDevice *m_localDevice; + QList<BluetoothDevice> *m_devices; +}; + +#endif diff --git a/chicken-wranglers/src/network/connectionfactory.cpp b/chicken-wranglers/src/network/connectionfactory.cpp new file mode 100644 index 0000000..6926bcb --- /dev/null +++ b/chicken-wranglers/src/network/connectionfactory.cpp @@ -0,0 +1,70 @@ +/**************************************************************************** +** +** This file is a part of QtChickenWranglers. +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).* +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +** FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +** COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +** BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +** ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +** POSSIBILITY OF SUCH DAMAGE." +** +****************************************************************************/ + + +#include "connectionfactory.h" + +#include "bluetoothconnection.h" +#include "tcpconnection.h" + +#include <QtCore/QIODevice> +#include <QtCore/QObject> + +ConnectionFactory::ConnectionFactory() +{ +} + +NetworkConnection *ConnectionFactory::create(ConnectionType connection, QObject *parent, + QIODevice *socket) +{ + NetworkConnection *result = 0; + + switch (connection) { + case Lan: + result = new TcpConnection(parent, dynamic_cast<QTcpSocket *>(socket)); + break; + case Bluetooth: + result = new BluetoothConnection(parent, dynamic_cast<QBluetoothSocket *>(socket)); + break; + } + + return result; +} diff --git a/chicken-wranglers/src/network/connectionfactory.h b/chicken-wranglers/src/network/connectionfactory.h new file mode 100644 index 0000000..06333f0 --- /dev/null +++ b/chicken-wranglers/src/network/connectionfactory.h @@ -0,0 +1,65 @@ +/**************************************************************************** +** +** This file is a part of QtChickenWranglers. +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).* +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +** FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +** COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +** BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +** ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +** POSSIBILITY OF SUCH DAMAGE." +** +****************************************************************************/ + + +#ifndef CONNECTIONFACTORY_H +#define CONNECTIONFACTORY_H + +class QIODevice; +class QObject; +class NetworkConnection; + +class ConnectionFactory +{ +public: + enum ConnectionType { + Lan, + Bluetooth + }; + + static NetworkConnection *create(ConnectionType connection, QObject *parent = 0, + QIODevice *socket = 0); + +private: + ConnectionFactory(); +}; + +#endif diff --git a/chicken-wranglers/src/network/lanhandler.cpp b/chicken-wranglers/src/network/lanhandler.cpp new file mode 100644 index 0000000..ec1c12c --- /dev/null +++ b/chicken-wranglers/src/network/lanhandler.cpp @@ -0,0 +1,133 @@ +/**************************************************************************** +** +** This file is a part of QtChickenWranglers. +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).* +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +** FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +** COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +** BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +** ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +** POSSIBILITY OF SUCH DAMAGE." +** +****************************************************************************/ + +#include "lanhandler.h" + +#include "connectionfactory.h" +#include "network.h" +#include "networkconnection.h" + +LanHandler::LanHandler(QObject *parent, int maxConnections) + : QTcpServer(parent), m_maxConnections(maxConnections) +{ + connect(this, SIGNAL(newConnection()), this, SLOT(newClientConnection())); +} +LanHandler::~LanHandler() +{ + closeAll(); + stop(); +} + +void LanHandler::newClientConnection() +{ + if (m_connections.size() == m_maxConnections) + return; + + NetworkConnection *connection; + connection = ConnectionFactory::create(ConnectionFactory::Lan, + this, nextPendingConnection()); + + for (quint16 id = 0; id < m_maxConnections; id++) { + // If the peer ID is NOT on the dictionary, insert it + if (!m_connections.contains(id)) { + connection->setId(id); + + connect(connection, SIGNAL(disconnected()), + this, SLOT(peerDisconnected())); + connect(connection, SIGNAL(error(QAbstractSocket::SocketError)), + this, SLOT(socketError(QAbstractSocket::SocketError))); + connect(connection, SIGNAL(received(NetworkMessage)), + this, SIGNAL(received(NetworkMessage))); + + m_connections[id] = connection; + + // Signals that a new peer has connected + emit peerConnected(connection); + + break; + } + } +} + +void LanHandler::closeAll() +{ + NetworkConnection *tmp; + int pos = 0; + while (m_connections.size()) { + tmp = m_connections[pos]; + tmp->close(); + delete tmp; + ++pos; + } + + m_connections.clear(); +} + +void LanHandler::send(const NetworkMessage &message) +{ + m_connections[message.id()]->send(message); +} + +void LanHandler::peerDisconnected() +{ + NetworkConnection *connection = qobject_cast<NetworkConnection *>(sender()); + m_connections.remove(connection->id()); + + // Signals that a peer has disconnected + emit peerDisconnected(connection); +} + +void LanHandler::socketError(QAbstractSocket::SocketError socketError) +{ + NetworkConnection *connection = qobject_cast<NetworkConnection *>(sender()); + quint16 id = connection->id(); + + qWarning("TCP Socket error [ %d ]: %s", socketError, + connection->errorString().toUtf8().constData()); + + emit peerError(socketError, id); +} + +void LanHandler::stop() +{ + if (isListening()) + close(); +} diff --git a/chicken-wranglers/src/network/lanhandler.h b/chicken-wranglers/src/network/lanhandler.h new file mode 100644 index 0000000..457b474 --- /dev/null +++ b/chicken-wranglers/src/network/lanhandler.h @@ -0,0 +1,82 @@ +/**************************************************************************** +** +** This file is a part of QtChickenWranglers. +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).* +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +** FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +** COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +** BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +** ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +** POSSIBILITY OF SUCH DAMAGE." +** +****************************************************************************/ + + +#ifndef LANHANDLER_H +#define LANHANDLER_H + +#include "networkmessage.h" + +#include <QtCore/QHash> +#include <QtNetwork/QTcpServer> + +class NetworkConnection; + +class LanHandler : public QTcpServer +{ + Q_OBJECT + +public: + LanHandler(QObject *parent = 0, int maxConnections = 4); + ~LanHandler(); + + void stop(); + void send(const NetworkMessage &message); + void closeAll(); + +signals: + void peerConnected(NetworkConnection *connection); + void peerDisconnected(NetworkConnection *connection); + void peerError(QAbstractSocket::SocketError socketError, quint16 id); + void received(const NetworkMessage &message); + void startError(); + +private slots: + void newClientConnection(); + void peerDisconnected(); + void socketError(QAbstractSocket::SocketError socketError); + +private: + QHash<quint16, NetworkConnection *> m_connections; + int m_maxConnections; +}; + +#endif diff --git a/chicken-wranglers/src/network/network.h b/chicken-wranglers/src/network/network.h new file mode 100644 index 0000000..2b86ded --- /dev/null +++ b/chicken-wranglers/src/network/network.h @@ -0,0 +1,67 @@ +/**************************************************************************** +** +** This file is a part of QtChickenWranglers. +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).* +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +** FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +** COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +** BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +** ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +** POSSIBILITY OF SUCH DAMAGE." +** +****************************************************************************/ + + +#ifndef NETWORK_H +#define NETWORK_H + +#include <QtCore/QByteArray> +#include <QtGlobal> + +namespace CW +{ + enum UdpSenderType { + UdpSenderNoType = 0, + UdpSenderClient = 1, + UdpSenderServer = 2, + UdpSenderAny = UdpSenderClient | UdpSenderServer + }; + + enum UdpContentType { + UdpNoContent = 200, + UdpContentDiscovery, + UdpContentAckDiscovery, + }; + + static const char udpMessageSeparator = '/'; +} + +#endif diff --git a/chicken-wranglers/src/network/network.pri b/chicken-wranglers/src/network/network.pri new file mode 100644 index 0000000..81f9d36 --- /dev/null +++ b/chicken-wranglers/src/network/network.pri @@ -0,0 +1,37 @@ +QT += network + +maemo5 { + CONFIG += mobility12 +} else { + CONFIG += mobility +} +MOBILITY += connectivity + +PATH = $$PWD + +HEADERS += \ + $$PATH/network.h \ + $$PATH/networkclient.h \ + $$PATH/networkserver.h \ + $$PATH/udphandler.h \ + $$PATH/networkmessage.h \ + $$PATH/networkconnection.h \ + $$PATH/bluetoothconnection.h \ + $$PATH/tcpconnection.h \ + $$PATH/connectionfactory.h \ + $$PATH/lanhandler.h \ + $$PATH/bluetoothhandler.h \ + $$PATH/bthandler.h + +SOURCES += \ + $$PATH/networkclient.cpp \ + $$PATH/networkserver.cpp \ + $$PATH/udphandler.cpp \ + $$PATH/networkmessage.cpp \ + $$PATH/networkconnection.cpp \ + $$PATH/bluetoothconnection.cpp \ + $$PATH/tcpconnection.cpp \ + $$PATH/connectionfactory.cpp \ + $$PATH/lanhandler.cpp \ + $$PATH/bluetoothhandler.cpp \ + $$PATH/bthandler.cpp diff --git a/chicken-wranglers/src/network/networkclient.cpp b/chicken-wranglers/src/network/networkclient.cpp new file mode 100644 index 0000000..58dba98 --- /dev/null +++ b/chicken-wranglers/src/network/networkclient.cpp @@ -0,0 +1,196 @@ +/**************************************************************************** +** +** This file is a part of QtChickenWranglers. +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).* +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +** FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +** COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +** BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +** ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +** POSSIBILITY OF SUCH DAMAGE." +** +****************************************************************************/ + +#include "networkclient.h" + +#include "bthandler.h" +#include "connectionfactory.h" +#include "network.h" +#include "networkconnection.h" +#include "udphandler.h" + +#include <QtCore/QList> +#include <QtCore/QTimer> + + +NetworkClient::NetworkClient(const QString &connectivity, int discoveryTimeout, + int clientAttempts, QObject *parent) + : QObject(parent), m_udpHandler(0), m_btHandler(0), m_connection(0), + m_discoveryTimer(0), m_discoveryAttempts(0), + m_discoveryTimeout(discoveryTimeout), m_discoveryClientAttempts(clientAttempts) +{ + if (connectivity == "lan") { + m_udpHandler = new UdpHandler(this); + m_udpHandler->setListenPort(m_lanUdpPort); + + connect(m_udpHandler, SIGNAL(received(QHostAddress, QByteArray, quint16, QByteArray)), + this, SLOT(processUdp(QHostAddress, QByteArray, quint16, QByteArray))); + + m_connection = ConnectionFactory::create(ConnectionFactory::Lan, this); + connect(m_connection, SIGNAL(error(QAbstractSocket::SocketError)), + this, SLOT(tcpSocketError(QAbstractSocket::SocketError))); + + } else if (connectivity == "bluetooth") { + m_btHandler = new BtHandler(this); + connect(m_btHandler, SIGNAL(discovered(const BluetoothDevice &)), + this, SIGNAL(bluetoothDeviceDiscovered(const BluetoothDevice &))); + + m_connection = ConnectionFactory::create(ConnectionFactory::Bluetooth, this); + connect(m_connection, SIGNAL(error(QBluetoothSocket::SocketError)), + this, SLOT(bluetoothSocketError(QBluetoothSocket::SocketError))); + } + + // Timer for broadcasting the message + m_discoveryTimer = new QTimer(this); + // TODO: rename this settings name to DiscoveryTimeout + m_discoveryTimer->setInterval(m_discoveryTimeout); + connect(m_discoveryTimer, SIGNAL(timeout()), + this, SLOT(sendDiscovery())); + + connect(m_connection, SIGNAL(connected()), + this, SIGNAL(connected())); + connect(m_connection, SIGNAL(disconnected()), + this, SIGNAL(disconnected())); + connect(m_connection, SIGNAL(received(const NetworkMessage &)), + this, SIGNAL(messageReceived(const NetworkMessage &))); +} + +void NetworkClient::setLanPorts(int udpPort, int tcpPort) +{ + m_lanUdpPort = udpPort; + m_lanTcpPort = tcpPort; +} + +void NetworkClient::send(const NetworkMessage &message) +{ + m_connection->send(message); +} + +void NetworkClient::startDiscovery() +{ + if (m_udpHandler) { + // FIXME: Do not enable UdpHandler if it's already enabled + m_udpHandler->setListenPort(m_lanUdpPort + 1); + m_udpHandler->enable(); + + m_discoveryAttempts = 0; + m_discoveryTimer->start(); + } else { + m_btHandler->enable(); + } +} + +void NetworkClient::stopDiscovery() +{ + if (m_udpHandler) + m_discoveryTimer->stop(); + + if (m_btHandler) + m_btHandler->disable(); +} + +void NetworkClient::connectToBluetoothServer(const QString &address) +{ + m_connection->connectToHost(address, 14); +} + +void NetworkClient::processUdp(QHostAddress senderAddress, QByteArray content, + quint16 senderListenPort, QByteArray timestamp) +{ + Q_UNUSED(timestamp) + + quint16 contentData = content.toUShort(); + + if (contentData == CW::UdpContentAckDiscovery) + processAckDiscovery(senderAddress, senderListenPort); +} + +void NetworkClient::processAckDiscovery(QHostAddress senderAddress, quint16 senderListenPort) +{ + Q_UNUSED(senderListenPort) + + stopDiscovery(); + + if (m_connection->state() == QAbstractSocket::UnconnectedState) { + // Estabilish a connection to the server + m_connection->connectToHost(senderAddress.toString(), m_lanTcpPort); + } else { + qWarning("TCP Connection already open"); + } +} + +void NetworkClient::sendDiscovery() +{ + if (m_discoveryAttempts < m_discoveryClientAttempts) { + m_discoveryAttempts++; + + if (m_udpHandler) { + m_udpHandler->sendDatagram(QHostAddress::Broadcast, m_lanUdpPort, + CW::UdpSenderClient, CW::UdpContentDiscovery, + m_udpHandler->listenPort()); + } else { + // TODO: Notify upper layers about discovered bt + } + } else { + stopDiscovery(); + + if (m_udpHandler) { + m_udpHandler->disable(); + } else { + // TODO: Bluetooth stuff + } + + emit serverDiscoveryTimeout(); + } +} + +void NetworkClient::tcpSocketError(QAbstractSocket::SocketError error) +{ + qWarning("TCP Socket error [ %d ]: %s", error, + m_connection->errorString().toUtf8().constData()); + + emit socketError(error); +} + +void NetworkClient::bluetoothSocketError(QBluetoothSocket::SocketError error) +{ + emit socketError(static_cast<QAbstractSocket::SocketError>(error)); +} diff --git a/chicken-wranglers/src/network/networkclient.h b/chicken-wranglers/src/network/networkclient.h new file mode 100644 index 0000000..621fc2c --- /dev/null +++ b/chicken-wranglers/src/network/networkclient.h @@ -0,0 +1,107 @@ +/**************************************************************************** +** +** This file is a part of QtChickenWranglers. +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).* +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +** FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +** COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +** BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +** ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +** POSSIBILITY OF SUCH DAMAGE." +** +****************************************************************************/ + + +#ifndef NETWORKCLIENT_H +#define NETWORKCLIENT_H + +#include "bluetoothdevice.h" +#include "networkmessage.h" + +#include <QBluetoothSocket> +#include <QtNetwork/QAbstractSocket> +#include <QtNetwork/QHostAddress> +#include <QtCore/QByteArray> +#include <QtCore/QObject> + +class BtHandler; +class NetworkConnection; +class QTimer; +class UdpHandler; + +QTM_USE_NAMESPACE + +class NetworkClient : public QObject +{ + Q_OBJECT + +public: + NetworkClient(const QString &connectivity = "lan", int discoveryTimeout = 0, + int clientAttempts = 0, QObject *parent = 0); + + void send(const NetworkMessage &message); + void setLanPorts(int udpPort, int tcpPort); + +public slots: + void startDiscovery(); + void stopDiscovery(); + void connectToBluetoothServer(const QString &address); + +signals: + void connected(); + void disconnected(); + void socketError(QAbstractSocket::SocketError socketError); + void messageReceived(const NetworkMessage &message); + void serverDiscoveryTimeout(); + void bluetoothDeviceDiscovered(const BluetoothDevice &device); + +private slots: + void processUdp(QHostAddress senderAddress, QByteArray content, + quint16 senderListenPort, QByteArray timestamp); + void sendDiscovery(); + void tcpSocketError(QAbstractSocket::SocketError error); + void bluetoothSocketError(QBluetoothSocket::SocketError error); + +private: + void processAckDiscovery(QHostAddress senderAddress, quint16 senderListenPort); + + UdpHandler *m_udpHandler; + BtHandler *m_btHandler; + NetworkConnection *m_connection; + QTimer *m_discoveryTimer; + quint16 m_discoveryAttempts; + int m_discoveryTimeout; + int m_lanUdpPort; + int m_lanTcpPort; + int m_discoveryClientAttempts; +}; + +#endif diff --git a/chicken-wranglers/src/network/networkconnection.cpp b/chicken-wranglers/src/network/networkconnection.cpp new file mode 100644 index 0000000..6bebe58 --- /dev/null +++ b/chicken-wranglers/src/network/networkconnection.cpp @@ -0,0 +1,144 @@ +/**************************************************************************** +** +** This file is a part of QtChickenWranglers. +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).* +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +** FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +** COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +** BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +** ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +** POSSIBILITY OF SUCH DAMAGE." +** +****************************************************************************/ + + +#include "networkconnection.h" + +#include <QtCore/QByteArray> + +NetworkConnection::NetworkConnection(QObject *parent) + : QObject(parent), m_id(0), m_message(NetworkMessage()) +{ +} + +NetworkConnection::~NetworkConnection() +{ +} + +void NetworkConnection::setId(const quint16 &newId) +{ + m_id = newId; +} + +quint16 NetworkConnection::id() const +{ + return m_id; +} + +void NetworkConnection::processRead(QIODevice *m_socket) +{ + QByteArray buffer(m_socket->readAll()); + int counter = buffer.length(); + + QDataStream dataStream(&buffer, QIODevice::ReadOnly); + dataStream.setVersion(QDataStream::Qt_4_7); + + while (counter) { + // Type + if (m_message.type() == CW::NoMessageType) { + if (counter < ((int) sizeof(quint16))) + return; + + // Read the Message Type + quint16 type; + dataStream >> type; + counter -= sizeof(quint16); + + m_message.setType((CW::MessageType) type); + } + + // Content + if (m_message.content() == 0) { + if (counter < ((int) sizeof(quint16))) + return; + + // Read the Message Content + quint16 content; + dataStream >> content; + counter -= sizeof(quint16); + + m_message.setContent(content); + } + + if (m_message.data().size() == 0) { + if (counter < ((int) sizeof(quint32))) + return; + + quint32 dataSize; + dataStream >> dataSize; + counter -= sizeof(quint32); + + if (dataSize == 0xFFFFFFFF) { + m_message.setId(m_id); + + emit received(m_message); + + m_message = NetworkMessage(); + + continue; + } else { + QByteArray data; + data.resize(dataSize); + m_message.setData(data); + } + } + + if (m_message.data().size() > 0) { + if (counter < m_message.data().size()) + return; + + int dataSize = m_message.data().size(); + char *charData = new char[dataSize + 1]; + + dataStream.readRawData(charData, dataSize); + counter -= dataSize; + charData[dataSize] = '\0'; + QByteArray data(charData); + delete charData; + + m_message.setData(data); + + emit received(m_message); + + m_message = NetworkMessage(); + } + } +} diff --git a/chicken-wranglers/src/network/networkconnection.h b/chicken-wranglers/src/network/networkconnection.h new file mode 100644 index 0000000..5167804 --- /dev/null +++ b/chicken-wranglers/src/network/networkconnection.h @@ -0,0 +1,85 @@ +/**************************************************************************** +** +** This file is a part of QtChickenWranglers. +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).* +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +** FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +** COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +** BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +** ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +** POSSIBILITY OF SUCH DAMAGE." +** +****************************************************************************/ + + +#ifndef NETWORKCONNECTION_H +#define NETWORKCONNECTION_H + +#include "networkmessage.h" + +#include <QtCore/QObject> +#include <QtCore/QPointer> +#include <QtNetwork/QTcpSocket> + +class NetworkConnection : public QObject +{ + Q_OBJECT + +public: + NetworkConnection(QObject *parent = 0); + virtual ~NetworkConnection(); + + virtual void setId(const quint16 &newId); + virtual quint16 id() const; + + virtual void send(NetworkMessage message) = 0; + + virtual void connectToHost(const QString &address, const quint16 &port) = 0; + + virtual QAbstractSocket::SocketState state() const = 0; + + virtual QAbstractSocket::SocketError error() const = 0; + + virtual QString errorString() const = 0; + + virtual void close() = 0; + +signals: + void received(const NetworkMessage &message); + +protected: + void processRead(QIODevice *m_socket); + + quint16 m_id; + NetworkMessage m_message; +}; + +#endif diff --git a/chicken-wranglers/src/network/networkmessage.cpp b/chicken-wranglers/src/network/networkmessage.cpp new file mode 100644 index 0000000..55e31f9 --- /dev/null +++ b/chicken-wranglers/src/network/networkmessage.cpp @@ -0,0 +1,118 @@ +/**************************************************************************** +** +** This file is a part of QtChickenWranglers. +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).* +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +** FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +** COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +** BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +** ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +** POSSIBILITY OF SUCH DAMAGE." +** +****************************************************************************/ + + +#include <QtCore/QDataStream> + +#include "networkmessage.h" + +NetworkMessage::NetworkMessage() + : m_id(0), m_type(CW::NoMessageType), + m_content(0), m_data(QByteArray()) +{ +} + +NetworkMessage::NetworkMessage(CW::MessageType type, quint16 content) + : m_id(0), m_type(type), + m_content(content), m_data(QByteArray()) +{ +} + +void NetworkMessage::setId(const quint16 &newId) +{ + m_id = newId; +} + +quint16 NetworkMessage::id() const +{ + return m_id; +} + +void NetworkMessage::setType(const CW::MessageType &newType) +{ + m_type = newType; +} + +CW::MessageType NetworkMessage::type() const +{ + return m_type; +} + +void NetworkMessage::setContent(const quint16 &newContent) +{ + m_content = newContent; +} + +quint16 NetworkMessage::content() const +{ + return m_content; +} + +void NetworkMessage::setData(const QByteArray &newData) +{ + m_data = newData; +} + +QByteArray NetworkMessage::data() const +{ + return m_data; +} + +QByteArray NetworkMessage::byteArray() const +{ + quint16 field; + QByteArray byteArray; + + QDataStream stream(&byteArray, QIODevice::WriteOnly); + stream.setVersion(QDataStream::Qt_4_0); + + // Type + field = m_type; + stream << field; + + // Content + stream << m_content; + + // Data (optional) + stream << m_data; + + return byteArray; +} diff --git a/chicken-wranglers/src/network/networkmessage.h b/chicken-wranglers/src/network/networkmessage.h new file mode 100644 index 0000000..da650be --- /dev/null +++ b/chicken-wranglers/src/network/networkmessage.h @@ -0,0 +1,115 @@ +/**************************************************************************** +** +** This file is a part of QtChickenWranglers. +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).* +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +** FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +** COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +** BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +** ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +** POSSIBILITY OF SUCH DAMAGE." +** +****************************************************************************/ + + +#ifndef NETWORKMESSAGE_H +#define NETWORKMESSAGE_H + +#include <QtCore/QByteArray> + +namespace CW +{ + enum MessageType { + NoMessageType = 1000, + PlayerControlMessageType, + PlayerInfoMessageType, + CharacterMessageType, + MatchMessageType + }; + + enum PlayerControl { + PlayerControlStop = 2000, + PlayerControlUp, + PlayerControlDown, + PlayerControlLeft, + PlayerControlRight, + PlayerControlLaserUp, + PlayerControlLaserDown, + PlayerControlLaserLeft, + PlayerControlLaserRight + }; + + enum PlayerInfo { + PlayerInfoScore = 3000, + PlayerInfoLeader + }; + + enum Character { + CharacterSelected = 4000, + CharacterReleased, + CharacterAvailableList, + CharacterIsAvailable + }; + + enum Match { + MatchReady = 5000, + MatchFinished + }; +} + +class NetworkMessage +{ +public: + NetworkMessage(); + NetworkMessage(CW::MessageType type, quint16 content); + + void setId(const quint16 &newId); + quint16 id() const; + + void setType(const CW::MessageType &newType); + CW::MessageType type() const; + + void setContent(const quint16 &newContent); + quint16 content() const; + + void setData(const QByteArray &newData); + QByteArray data() const; + + QByteArray byteArray() const; + +private: + quint16 m_id; + CW::MessageType m_type; + quint16 m_content; + QByteArray m_data; +}; + +#endif diff --git a/chicken-wranglers/src/network/networkserver.cpp b/chicken-wranglers/src/network/networkserver.cpp new file mode 100644 index 0000000..8f13259 --- /dev/null +++ b/chicken-wranglers/src/network/networkserver.cpp @@ -0,0 +1,255 @@ +/**************************************************************************** +** +** This file is a part of QtChickenWranglers. +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).* +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +** FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +** COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +** BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +** ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +** POSSIBILITY OF SUCH DAMAGE." +** +****************************************************************************/ + + +#include "networkserver.h" + +#include "bluetoothhandler.h" +#include "lanhandler.h" +#include "network.h" +#include "udphandler.h" + +#include <QtCore/QList> +#include <QtCore/QTimer> + +NetworkServer::NetworkServer(const QString &connectivity, int discoveryTimeout, int hostAttempts, QObject *parent) + : QObject(parent), m_udpHandler(0), m_lanHandler(0) , m_blueHandler(0) + , m_discoveryAttempts(0), m_lookingForServers(true) + , m_discoveryTimeout(discoveryTimeout), m_discoveryHostAttempts(hostAttempts) + , m_serverBluetooth(true) +{ + createConnectionHandler(connectivity); +} + +void NetworkServer::createConnectionHandler(const QString &connectivity) +{ + if (connectivity == "lan") { + m_serverBluetooth = false; + if (m_udpHandler) + return; + + m_udpHandler = new UdpHandler(this); + m_udpHandler->setListenPort(m_lanUdpPort); + + connect(m_udpHandler, SIGNAL(received(QHostAddress, QByteArray, quint16, QByteArray)), + this, SLOT(processUdp(QHostAddress, QByteArray, quint16, QByteArray))); + + m_lanHandler = new LanHandler(this); + connect(m_lanHandler, SIGNAL(peerConnected(NetworkConnection *)), + this, SIGNAL(peerConnected(NetworkConnection *))); + connect(m_lanHandler, SIGNAL(peerDisconnected(NetworkConnection *)), + this, SIGNAL(peerDisconnected(NetworkConnection *))); + connect(m_lanHandler, SIGNAL(peerError(QAbstractSocket::SocketError, quint16)), + this, SIGNAL(peerError(QAbstractSocket::SocketError, quint16))); + connect(m_lanHandler, SIGNAL(received(NetworkMessage)), + this, SIGNAL(messageReceived(NetworkMessage))); + + m_discoveryTimer = new QTimer(this); + m_discoveryTimer->setInterval(m_discoveryTimeout); + connect(m_discoveryTimer, SIGNAL(timeout()), + this, SLOT(sendDiscovery())); + + } else if (connectivity == "bluetooth") { + m_serverBluetooth = true; + if (m_blueHandler) + return; + + m_blueHandler = new BluetoothHandler(this); + + connect(m_blueHandler, SIGNAL(started()), + this, SIGNAL(started())); + connect(m_blueHandler, SIGNAL(peerConnected(NetworkConnection *)), + this, SIGNAL(peerConnected(NetworkConnection *))); + connect(m_blueHandler, SIGNAL(peerDisconnected(NetworkConnection *)), + this, SIGNAL(peerDisconnected(NetworkConnection *))); + connect(m_blueHandler, SIGNAL(peerError(QAbstractSocket::SocketError, quint16)), + this, SIGNAL(peerError(QAbstractSocket::SocketError, quint16))); + connect(m_blueHandler, SIGNAL(received(NetworkMessage)), + this, SIGNAL(messageReceived(NetworkMessage))); + connect(m_blueHandler, SIGNAL(startError()), this, SLOT(startError())); + } +} + +NetworkServer::~NetworkServer() +{ +} + +void NetworkServer::send(const NetworkMessage &message) +{ + if (m_lanHandler) + m_lanHandler->send(message); + else if (m_blueHandler) + m_blueHandler->send(message); +} + +void NetworkServer::setLanPorts(int udpPort, int tcpPort) +{ + m_lanUdpPort = udpPort; + m_lanTcpPort = tcpPort; +} + +void NetworkServer::start() +{ + if (!m_serverBluetooth && m_lanHandler) { + m_udpHandler->setListenSenderType(CW::UdpSenderAny); + m_udpHandler->setListenPort(m_lanUdpPort + 1); + m_udpHandler->enable(); + // Server tries to find if there are other + // running servers in the same network + startDiscovery(); + } else if ((m_serverBluetooth == true) && m_blueHandler) { + m_blueHandler->start(); + } +} + +void NetworkServer::stop() +{ + if (!m_serverBluetooth && m_lanHandler) { + stopDiscovery(); + + if (m_lanHandler->isListening()) + m_lanHandler->close(); + + m_udpHandler->setListenSenderType(CW::UdpSenderNoType); + m_udpHandler->disable(); + } else if ((m_serverBluetooth == true) && m_blueHandler) { + m_blueHandler->stop(); + } +} + +void NetworkServer::closeAll() +{ + if (!m_serverBluetooth && m_lanHandler) { + stopDiscovery(); + + if (m_lanHandler->isListening()) + m_lanHandler->closeAll(); + + m_udpHandler->setListenSenderType(CW::UdpSenderNoType); + m_udpHandler->disable(); + } else if ((m_serverBluetooth == true) && m_blueHandler) { + m_blueHandler->closeAll(); + } + +} + + +void NetworkServer::startDiscovery() +{ + m_lookingForServers = true; + m_discoveryAttempts = 0; + m_discoveryTimer->start(); +} + +void NetworkServer::stopDiscovery() +{ + m_lookingForServers = false; + m_discoveryTimer->stop(); +} + +void NetworkServer::processUdp(QHostAddress senderAddress, QByteArray content, + quint16 senderListenPort, QByteArray timestamp) +{ + Q_UNUSED(timestamp) + + quint16 contentData = content.toUShort(); + + if (contentData == CW::UdpContentDiscovery) + processDiscovery(senderAddress, senderListenPort); + else if (contentData == CW::UdpContentAckDiscovery) + processAckDiscovery(senderAddress, senderListenPort); +} + +void NetworkServer::processDiscovery(QHostAddress senderAddress, quint16 senderListenPort) +{ + // While looking for other active servers, do not respond + // to Discovery messages. + if (m_lookingForServers) + return; + + // Received: "Discovery" --> Send: "AckDiscovery" + m_udpHandler->sendDatagram(senderAddress, senderListenPort, CW::UdpSenderServer, + CW::UdpContentAckDiscovery, m_udpHandler->listenPort()); +} + +void NetworkServer::processAckDiscovery(QHostAddress senderAddress, quint16 senderListenPort) +{ + Q_UNUSED(senderAddress) + Q_UNUSED(senderListenPort) + + stop(); + + emit error(AnotherServerRunningError); +} + +void NetworkServer::sendDiscovery() +{ + if (m_discoveryAttempts == m_discoveryHostAttempts) { + stopDiscovery(); + + m_udpHandler->disable(); + m_udpHandler->setListenSenderType(CW::UdpSenderAny); + m_udpHandler->setListenPort(m_lanUdpPort); + m_udpHandler->enable(); + + if (!m_lanHandler->isListening()) { + if (!m_lanHandler->listen(QHostAddress::Any, m_lanTcpPort)) { + startError(); + } + } + // TODO: Return the server to the stopped state in case of port binding error. + if (m_udpHandler->listenPort() != m_lanUdpPort) + qWarning("UDP Socket error: Unable to bind to port %d", m_lanUdpPort); + + started(); + return; + } + + m_discoveryAttempts++; + m_udpHandler->sendDatagram(QHostAddress::Broadcast, m_lanUdpPort, + CW::UdpSenderServer, CW::UdpContentDiscovery, + m_udpHandler->listenPort()); +} + +void NetworkServer::startError() +{ + emit error(AnotherServerRunningError); +} diff --git a/chicken-wranglers/src/network/networkserver.h b/chicken-wranglers/src/network/networkserver.h new file mode 100644 index 0000000..637a38f --- /dev/null +++ b/chicken-wranglers/src/network/networkserver.h @@ -0,0 +1,120 @@ +/**************************************************************************** +** +** This file is a part of QtChickenWranglers. +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).* +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +** FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +** COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +** BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +** ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +** POSSIBILITY OF SUCH DAMAGE." +** +****************************************************************************/ + + +#ifndef NETWORKSERVER_H +#define NETWORKSERVER_H + +#include "networkmessage.h" + +#include <QtCore/QByteArray> +#include <QtCore/QList> +#include <QtCore/QObject> +#include <QtNetwork/QHostAddress> + +class BluetoothHandler; +class LanHandler; +class NetworkConnection; +class QTimer; +class UdpHandler; + +class NetworkServer : public QObject +{ + Q_OBJECT + + Q_ENUMS(ServerError) + +public: + NetworkServer(const QString &connectivity = "lan", int hostAttempts = 0, int discoveryTimeout = 0, QObject *parent = 0); + ~NetworkServer(); + + void send(const NetworkMessage &message); + void setLanPorts(int udpPort, int tcpPort); + + enum ServerError { + AnotherServerRunningError, + UnknownError + }; + + void createConnectionHandler(const QString &connectivity); + + void closeAll(); + +public slots: + void start(); + void stop(); + +signals: + void peerConnected(NetworkConnection *connection); + void peerDisconnected(NetworkConnection *connection); + void peerError(QAbstractSocket::SocketError socketError, quint16 id); + void messageReceived(const NetworkMessage &message); + void error(NetworkServer::ServerError error); + void started(); + +private slots: + void processUdp(QHostAddress senderAddress, QByteArray content, + quint16 senderListenPort, QByteArray timestamp); + void sendDiscovery(); + + void startError(); + +private: + void startDiscovery(); + void stopDiscovery(); + void processDiscovery(QHostAddress senderAddress, quint16 senderListenPort); + void processAckDiscovery(QHostAddress senderAddress, quint16 senderListenPort); + + UdpHandler *m_udpHandler; + LanHandler *m_lanHandler; + BluetoothHandler *m_blueHandler; + QTimer *m_discoveryTimer; + quint16 m_discoveryAttempts; + bool m_lookingForServers; + int m_discoveryTimeout; + int m_lanUdpPort; + int m_lanTcpPort; + int m_discoveryHostAttempts; + bool m_serverBluetooth; + +}; + +#endif diff --git a/chicken-wranglers/src/network/tcpconnection.cpp b/chicken-wranglers/src/network/tcpconnection.cpp new file mode 100644 index 0000000..502962e --- /dev/null +++ b/chicken-wranglers/src/network/tcpconnection.cpp @@ -0,0 +1,114 @@ +/**************************************************************************** +** +** This file is a part of QtChickenWranglers. +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).* +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +** FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +** COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +** BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +** ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +** POSSIBILITY OF SUCH DAMAGE." +** +****************************************************************************/ + + +#include <QtCore/QByteArray> +#include <QtNetwork/QHostAddress> + +#include "tcpconnection.h" + +TcpConnection::TcpConnection(QObject *parent, QTcpSocket *socket) + : NetworkConnection(parent), m_socket(socket) +{ + if (m_socket == 0) + m_socket = new QTcpSocket(this); + + connect(m_socket, SIGNAL(connected()), + this, SIGNAL(connected())); + connect(m_socket, SIGNAL(disconnected()), + this, SIGNAL(disconnected())); + connect(m_socket, SIGNAL(error(QAbstractSocket::SocketError)), + this, SIGNAL(error(QAbstractSocket::SocketError))); + connect(m_socket, SIGNAL(readyRead()), + this, SLOT(processReadyRead())); +} + +TcpConnection::~TcpConnection() +{ + if (m_socket) + m_socket->close(); +} + +void TcpConnection::setId(const quint16 &newId) +{ + m_id = newId; +} + +quint16 TcpConnection::id() const +{ + return m_id; +} + +void TcpConnection::send(NetworkMessage message) +{ + if (m_socket->write(message.byteArray()) == -1) + qWarning("TCP Socket write error: %s", m_socket->errorString().toUtf8().constData()); +} + +void TcpConnection::connectToHost(const QString &address, const quint16 &port) +{ + m_socket->connectToHost(QHostAddress(address), port); +} + +QAbstractSocket::SocketState TcpConnection::state() const +{ + return m_socket->state(); +} + +QAbstractSocket::SocketError TcpConnection::error() const +{ + return m_socket->error(); +} + +QString TcpConnection::errorString() const +{ + return m_socket->errorString(); +} + +void TcpConnection::processReadyRead() +{ + processRead(m_socket); +} + +void TcpConnection::close() +{ + m_socket.data()->close(); +} diff --git a/chicken-wranglers/src/network/tcpconnection.h b/chicken-wranglers/src/network/tcpconnection.h new file mode 100644 index 0000000..464d276 --- /dev/null +++ b/chicken-wranglers/src/network/tcpconnection.h @@ -0,0 +1,87 @@ +/**************************************************************************** +** +** This file is a part of QtChickenWranglers. +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).* +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +** FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +** COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +** BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +** ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +** POSSIBILITY OF SUCH DAMAGE." +** +****************************************************************************/ + + +#ifndef TCPCONNECTION_H +#define TCPCONNECTION_H + +#include "networkconnection.h" + +#include <QtCore/QObject> +#include <QtCore/QPointer> +#include <QtNetwork/QTcpSocket> + +class TcpConnection : public NetworkConnection +{ + Q_OBJECT + +public: + TcpConnection(QObject *parent = 0, QTcpSocket *socket = 0); + ~TcpConnection(); + + void setId(const quint16 &newId); + quint16 id() const; + + void send(NetworkMessage message); + + void connectToHost(const QString &address, const quint16 &port); + + QAbstractSocket::SocketState state() const; + + QAbstractSocket::SocketError error() const; + + QString errorString() const; + + void close(); + +signals: + void connected(); + void disconnected(); + void error(QAbstractSocket::SocketError socketError); + +private slots: + void processReadyRead(); + +private: + QPointer<QTcpSocket> m_socket; +}; + +#endif diff --git a/chicken-wranglers/src/network/udphandler.cpp b/chicken-wranglers/src/network/udphandler.cpp new file mode 100644 index 0000000..2aa2635 --- /dev/null +++ b/chicken-wranglers/src/network/udphandler.cpp @@ -0,0 +1,169 @@ +/**************************************************************************** +** +** This file is a part of QtChickenWranglers. +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).* +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +** FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +** COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +** BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +** ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +** POSSIBILITY OF SUCH DAMAGE." +** +****************************************************************************/ + + +#include <QtCore/QTime> +#include <QtNetwork/QUdpSocket> + +#include "network.h" +#include "settings.h" + +#include "udphandler.h" + +UdpHandler::UdpHandler(QObject *parent) + : QObject(parent), m_listenSenderType(CW::UdpSenderServer), m_listenPort(0) +{ + m_socket = new QUdpSocket(this); + + connect(m_socket, SIGNAL(readyRead()), this, SLOT(processIncomingDatagrams())); +} + +UdpHandler::~UdpHandler() +{ + disable(); +} + +void UdpHandler::enable() +{ + for (quint16 i = 0; i < 100; i++) { + m_listenPort += i; + + if (m_socket->bind(QHostAddress::Any, m_listenPort, + QUdpSocket::DontShareAddress)) { + qWarning("UDP Socket bound to port %d", m_listenPort); + + break; + } + } +} + +void UdpHandler::disable() +{ + m_socket->close(); +} + +void UdpHandler::setListenSenderType(const CW::UdpSenderType &type) +{ + m_listenSenderType = type; +} + +CW::UdpSenderType UdpHandler::listenSenderType() const +{ + return m_listenSenderType; +} + +void UdpHandler::setListenPort(const quint16 &port) +{ + if (m_listenPort != port) + m_listenPort = port; +} + +quint16 UdpHandler::listenPort() const +{ + return m_listenPort; +} + +void UdpHandler::processIncomingDatagrams() +{ + QByteArray datagram; + QHostAddress senderAddress; + quint16 senderPort; + + while (m_socket->hasPendingDatagrams()) { + datagram.resize(m_socket->pendingDatagramSize()); + + if (m_socket->readDatagram(datagram.data(), datagram.size(), + &senderAddress, &senderPort) == -1) { + qWarning("UDP Error: Unable to read datagram."); + } else { + parseDatagram(senderAddress, senderPort, datagram); + } + + datagram.clear(); + } +} + +void UdpHandler::parseDatagram(QHostAddress address, quint16 port, QByteArray datagram) +{ + QList<QByteArray> fields = datagram.split(CW::udpMessageSeparator); + QTime time = QTime::currentTime(); + + // Message size correct (=4) + if (fields.size() == 4) { + // Message type received (='type specified') + if (fields.at(0).toUShort() & m_listenSenderType) { + qWarning("UDP Received:\t\"%s\"", datagram.constData()); + + emit received(address, fields.at(1), port, fields.at(2)); + } else { + qWarning("UDP Invalid sender type:\"%s\"", datagram.constData()); + } + } else { + qWarning("UDP Invalid message size:\"%s\"", datagram.constData()); + } +} + +void UdpHandler::sendDatagram(QHostAddress address, quint16 port, CW::UdpSenderType senderType, + CW::UdpContentType content, quint16 senderListenPort) +{ + QTime time; + QByteArray datagram; + + // Message format: + // "client/content/senderListenPort/11:22:33.444" + + // Timestamp + time = QTime::currentTime(); + + // Message type: Client or Server + datagram = QByteArray::number(senderType); + + // Message content: content + datagram += CW::udpMessageSeparator + QByteArray::number((quint16) content); + + // Message content: sender listen port + datagram += CW::udpMessageSeparator + QByteArray::number((quint16) senderListenPort); + + // Message timestamp: hours:minutes:seconds.miliseconds + datagram += CW::udpMessageSeparator + time.toString("hh:mm:ss.zzz").toUtf8(); + + m_socket->writeDatagram(datagram.data(), datagram.size(), address, port); +} diff --git a/chicken-wranglers/src/network/udphandler.h b/chicken-wranglers/src/network/udphandler.h new file mode 100644 index 0000000..6c26965 --- /dev/null +++ b/chicken-wranglers/src/network/udphandler.h @@ -0,0 +1,90 @@ +/**************************************************************************** +** +** This file is a part of QtChickenWranglers. +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).* +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +** FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +** COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +** BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +** ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +** POSSIBILITY OF SUCH DAMAGE." +** +****************************************************************************/ + + +#ifndef UDPHANDLER_H +#define UDPHANDLER_H + +#include "network.h" + +#include <QtCore/QByteArray> +#include <QtCore/QList> +#include <QtCore/QObject> +#include <QtNetwork/QHostAddress> + +class QUdpSocket; + +class UdpHandler : public QObject +{ + Q_OBJECT + +public: + UdpHandler(QObject *parent = 0); + ~UdpHandler(); + + void enable(); + void disable(); + + void setListenSenderType(const CW::UdpSenderType &type); + CW::UdpSenderType listenSenderType() const; + + void setListenPort(const quint16 &port); + quint16 listenPort() const; + + void sendDatagram(QHostAddress toAddress, quint16 toPort, CW::UdpSenderType senderType, + CW::UdpContentType content, quint16 senderListenPort); + +signals: + void received(QHostAddress senderAddress, QByteArray content, + quint16 senderListenPort, QByteArray timestamp); + +private slots: + void processIncomingDatagrams(); + +private: + void parseDatagram(QHostAddress address, quint16 port, QByteArray datagram); + + QUdpSocket *m_socket; + CW::UdpSenderType m_listenSenderType; + quint16 m_listenPort; +}; + +#endif diff --git a/chicken-wranglers/src/qml/Being.qml b/chicken-wranglers/src/qml/Being.qml new file mode 100644 index 0000000..984ee9b --- /dev/null +++ b/chicken-wranglers/src/qml/Being.qml @@ -0,0 +1,150 @@ +/**************************************************************************** +** +** This file is a part of QtChickenWranglers. +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).* +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +** FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +** COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +** BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +** ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +** POSSIBILITY OF SUCH DAMAGE." +** +****************************************************************************/ + + +import Qt 4.7 + +import "match.js" as MatchLogic +import game.types 1.0 + +Image { + id: being + + property string path: "" + property int currentRow: 0 + property int currentColumn: 0 + property int walkingStep: 1 + property string orientation: "side_" + property string movement: "stopped_" + + // Default values + property int moveInterval: 500 + property int changeStepsInterval: 260 + + scale: matchScreen.displayScale + smooth: true + + source: { + if (path == "") + return "" + + path + "/" + orientation + movement + walkingStep + ".png" + } + + state: "stopped" + + Timer { + id: changeSteps; + interval: changeStepsInterval + running: (opacity == 1) && (matchController.status != Match.Paused) + repeat: true + onTriggered: { + if (walkingStep == 1) + walkingStep = 2 + else + walkingStep = 1 + } + } + + states { + State { + name: "Up" + PropertyChanges { + target: being + orientation: "back_" + movement: "walking_" + } + } + + State { + name: "Down" + PropertyChanges { + target: being + orientation: "front_" + movement: "walking_" + } + } + + State { + name: "Left" + PropertyChanges { + target: being + orientation: "side_" + movement: "walking_" + } + } + + State { + name: "Right" + PropertyChanges { + target: being + orientation: "side_" + movement: "walking_" + } + PropertyChanges { + target: rotation + angle: 180 + } + } + + State { + name: "Stop" + PropertyChanges { + target: being + movement: "stopped_" + orientation: orientation + } + PropertyChanges { + target: rotation + angle: angle + } + } + } + + transform { + Rotation { + id: rotation + origin.x: being.width/2; origin.y: being.height/2 + axis.x: 0; axis.y: 1; axis.z: 0 + angle: 0 + } + } +} diff --git a/chicken-wranglers/src/qml/Character.qml b/chicken-wranglers/src/qml/Character.qml new file mode 100644 index 0000000..46ab988 --- /dev/null +++ b/chicken-wranglers/src/qml/Character.qml @@ -0,0 +1,121 @@ +/**************************************************************************** +** +** This file is a part of QtChickenWranglers. +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).* +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +** FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +** COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +** BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +** ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +** POSSIBILITY OF SUCH DAMAGE." +** +****************************************************************************/ + + +import Qt 4.7 + +import "match.js" as MatchLogic +import game.types 1.0 + +Being { + id: character + + property int playerNumber: 0 + property PlayerModel model + property PlayerController controller + + path: { + if (model) + return model.characterPath + else + return "" + } + + moveInterval: MatchLogic.characterMoveInterval + changeStepsInterval: MatchLogic.characterChangeStepsInterval + + function onLaserToggleRequested(laserDirection) { + var column = Math.round((x - matchScreen.fieldStartX - (matchScreen.cellSize - width) / 2) / matchScreen.cellSize) + var row = Math.round((y - matchScreen.fieldStartY - (matchScreen.cellSize - height) / 2) / matchScreen.cellSize) + matchController.toggleLaser(column, row, laserDirection) + } + + x: matchScreen.fieldStartX + (currentColumn * matchScreen.cellSize) + (matchScreen.cellSize - width) / 2 + y: matchScreen.fieldStartY + (currentRow * matchScreen.cellSize) + (matchScreen.cellSize - height) / 2 + + Behavior on x { + NumberAnimation { + duration: moveInterval; + easing.type: Easing.Linear + } + } + + Behavior on y { + NumberAnimation { + duration: moveInterval; + easing.type: Easing.Linear + } + } + + Behavior on opacity { + NumberAnimation { duration: 200 } + } + + currentRow: { + if (controller) + return controller.position.y + else + return 4 + } + + currentColumn: { + if (controller) + return controller.position.x + else + return 4 + } + + opacity: 0 + + Timer { + id: moveTimer + + triggeredOnStart: true + interval: moveInterval; + running: model != null && matchController.status != Match.Paused + repeat: true + onTriggered: { + state = model.direction + if (controller) + controller.move() + } + } +} diff --git a/chicken-wranglers/src/qml/CharacterSelectionView.qml b/chicken-wranglers/src/qml/CharacterSelectionView.qml new file mode 100644 index 0000000..e28b6f9 --- /dev/null +++ b/chicken-wranglers/src/qml/CharacterSelectionView.qml @@ -0,0 +1,235 @@ +/**************************************************************************** +** +** This file is a part of QtChickenWranglers. +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).* +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +** FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +** COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +** BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +** ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +** POSSIBILITY OF SUCH DAMAGE." +** +****************************************************************************/ + + +import Qt 4.7 + +import game.types 1.0 +import "common.js" as Common +import "widgets" + +Screen { + id: screen + + signal back + signal characterSelected(int index) + + Image { + id: background + + anchors.fill: parent + source: { + if (game.environment() == Global.Symbian) + "qrc:/images/general/symbian/bg_selectcharacter.png" + else + "qrc:/images/general/bg_selectcharacter.png" + } + } + + Component { + id: characterDelegate + + Item { + width: 191 + height: 220 + + scale: PathView.iconScale + + Image { + id: characterIcon + + y: 0 + anchors.fill: parent + anchors.horizontalCenter: parent.horizontalCenter + smooth: true + source: { + if (isAvailable) + Common.getImagePath(path, "select_character.png") + else + Common.getImagePath(path, "unavailable.png") + } + } + + MouseArea { + anchors.fill: parent + onClicked: { + view.currentIndex = index + } + } + } + } + + Item { + id: characterHighlight + + anchors { + horizontalCenter: parent.horizontalCenter + top: parent.top + bottom: view.bottom + } + + Image { + id: name + + anchors { + horizontalCenter: parent.horizontalCenter + top: parent.top + topMargin: 60 + } + + smooth: true + source: Common.getImagePath(characterListModel.get(view.currentIndex).path, "name.png") + + // XXX: When changing source property, the sourceSize.width + // is not updating accordingly. So we are forcing a hardcoded + // value for now. + onSourceChanged: sourceSize.width = 200 + + Behavior on opacity { + NumberAnimation { duration: 100 } + } + } + + ImageButton { + source: "qrc:/images/general/bt_previous.png" + + anchors.right: parent.horizontalCenter + anchors.rightMargin: 80 + anchors.verticalCenter: name.verticalCenter + + onClicked: view.decrementCurrentIndex() + } + + ImageButton { + source: "qrc:/images/general/bt_next.png" + + anchors.left: parent.horizontalCenter + anchors.leftMargin: 80 + anchors.verticalCenter: name.verticalCenter + + onClicked: view.incrementCurrentIndex() + } + } + + PathView { + id: view + + anchors { + right: parent.right + left: parent.left + verticalCenter: parent.verticalCenter + verticalCenterOffset: 20 + } + + height: 220 + model: characterListModel + delegate: characterDelegate + preferredHighlightBegin: 0.5 + preferredHighlightEnd: 0.5 + pathItemCount: 5 + highlightMoveDuration: 200 + dragMargin: 500 + + onCurrentIndexChanged: { + name.source = Common.getImagePath(characterListModel.get(currentIndex).path, "name.png") + } + + onMovementStarted: { + name.opacity = 0 + } + + onMovementEnded: { + name.source = Common.getImagePath(characterListModel.get(currentIndex).path, "name.png") + name.opacity = 1 + } + + path: Path { + startX: -40 + startY: 100 + + PathAttribute { name: "iconScale"; value: 0.3 } + + PathLine { + x: screen.width * 0.5 + y: 100 + } + + PathAttribute { name: "iconScale"; value: 1.0 } + + // 4 + PathLine { + x: screen.width + 40 + y: 100 + } + + PathAttribute { name: "iconScale"; value: 0.3 } + } + } + + Button { + id: buttonJoin + + text: "Join" + width: 200 + enabled: characterListModel.get(view.currentIndex).isAvailable + + anchors { + horizontalCenter: parent.horizontalCenter + bottom: parent.bottom + margins: 20 + } + + onClicked: characterSelected(view.currentIndex) + } + + ImageButton { + id: buttonBack + + anchors { + top: parent.top + right: parent.right + margins: 15 + } + + name: "back" + onClicked: back(); + } +} diff --git a/chicken-wranglers/src/qml/Chicken.qml b/chicken-wranglers/src/qml/Chicken.qml new file mode 100644 index 0000000..a09e9c1 --- /dev/null +++ b/chicken-wranglers/src/qml/Chicken.qml @@ -0,0 +1,159 @@ +/**************************************************************************** +** +** This file is a part of QtChickenWranglers. +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).* +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +** FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +** COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +** BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +** ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +** POSSIBILITY OF SUCH DAMAGE." +** +****************************************************************************/ + + +import Qt 4.7 +import "match.js" as MatchLogic +import game.types 1.0 + +Being { + id: chicken + + property ChickenController controller + + path: "qrc:/images/chicken" + + function kill() { + chicken.opacity = 0 + } + + function onPositionChanged() { + currentRow = controller.position.y + currentColumn = controller.position.x + + var newX = matchScreen.fieldStartX + (currentColumn * matchScreen.cellSize) + (matchScreen.cellSize - width) / 2 + var newY = matchScreen.fieldStartY + (currentRow * matchScreen.cellSize) + (matchScreen.cellSize - height) / 2 + + moveInterval = chickenMoveInterval + + if (x != newX && !xAnimation.running) { + xAnimation.to = newX + xAnimation.start() + } + + if (y != newY && !yAnimation.running) { + yAnimation.to = newY + yAnimation.start() + } + } + + function move() { + controller.move() + chicken.state = controller.direction + } + + opacity: 1 + + currentRow: MatchLogic.defaultRows / 2 + currentColumn: MatchLogic.defaultColumns / 2 + + PropertyAnimation { + id: xAnimation + + target: chicken + property: "x" + duration: moveInterval + alwaysRunToEnd: true + + onRunningChanged: { + if (!running) + chicken.move() + } + } + + PropertyAnimation { + id: yAnimation + + target: chicken + property: "y" + duration: moveInterval + alwaysRunToEnd: true + + onRunningChanged: { + if (!running) + chicken.move() + } + } + + property int chickenMoveInterval + + chickenMoveInterval: { + if (!controller) + return MatchLogic.chickenMoveIntervalNormal + + if (controller.isSafe) + return MatchLogic.chickenMoveIntervalNormal + else + return MatchLogic.chickenMoveIntervalRunning + } + + changeStepsInterval: MatchLogic.chickenChangeStepsIntervalNormal + moveInterval: MatchLogic.chickenMoveIntervalNormal + + onOpacityChanged: { + if (opacity == 0) + chicken.destroy() + } + + Behavior on opacity { + NumberAnimation { duration: 500 } + } + + Timer { + id: move; + interval: chickenMoveInterval + running: state == "Stop" && matchController.status != Match.Paused + repeat: true + onTriggered: { + chicken.move() + + if (currentRow < 0 || currentColumn < 0 + || currentRow >= MatchLogic.defaultRows + || currentColumn >= MatchLogic.defaultColumns) { + chicken.kill() + } + } + } + + Component.onCompleted: { + chicken.state = "Stop" + } +} diff --git a/chicken-wranglers/src/qml/ClientView.qml b/chicken-wranglers/src/qml/ClientView.qml new file mode 100644 index 0000000..0bb06af --- /dev/null +++ b/chicken-wranglers/src/qml/ClientView.qml @@ -0,0 +1,121 @@ +/**************************************************************************** +** +** This file is a part of QtChickenWranglers. +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).* +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +** FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +** COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +** BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +** ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +** POSSIBILITY OF SUCH DAMAGE." +** +****************************************************************************/ + + +import Qt 4.7 +import game.types 1.0 + +import "widgets" +import "common.js" as Common + +Screen { + id: clientView + + focus: true + + function showControlView() { + var character = characterListModel.get(characterListModel.selectedIndex) + + playerControlView.characterPath = character.path + Common.switchScreens(playerReadyView, playerControlView) + playerControlView.focus = true + } + + function showPlayerReadyView() { + Common.switchScreens(playerControlView, playerReadyView) + } + + + CharacterSelectionView { + id: characterSelectionView + + anchors.fill: parent + + onBack: { + closeRequested() + focus = false + } + + onCharacterSelected: { + characterListModel.selectedIndex = index + var character = characterListModel.get(index) + + if (character.isAvailable) { + playerReadyView.characterPath = character.path + Common.switchScreens(characterSelectionView, playerReadyView) + } else { + console.log("Character is not available."); + } + } + } + + PlayerReadyView { + id: playerReadyView + + anchors.fill: parent + onBack: { + characterListModel.selectedIndex = -1 + Common.switchScreens(playerReadyView, characterSelectionView) + focus = false + } + } + + PlayerControlView { + id: playerControlView + + anchors.fill: parent + onBack: { + characterListModel.selectedIndex = -1 + Common.switchScreens(playerControlView, characterSelectionView) + focus = false + } + } + + onTransitionFinished: { + if (!visible) + closeFinished() + } + + Component.onCompleted: { + characterSelectionView.show() + characterSelectionView.focus = true + } +} diff --git a/chicken-wranglers/src/qml/HenCoop.qml b/chicken-wranglers/src/qml/HenCoop.qml new file mode 100644 index 0000000..ad5db74 --- /dev/null +++ b/chicken-wranglers/src/qml/HenCoop.qml @@ -0,0 +1,149 @@ +/**************************************************************************** +** +** This file is a part of QtChickenWranglers. +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).* +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +** FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +** COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +** BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +** ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +** POSSIBILITY OF SUCH DAMAGE." +** +****************************************************************************/ + + +import Qt 4.7 +import game.types 1.0 + +Item { + id: henCoop + + property int playerNumber: 1 + property PlayerModel player: playerListModel.get(playerNumber - 1) + property string side: getSide() + + scale: matchScreen.displayScale + + function getSide () { + if ((playerNumber % 2) == 0) + return "right" + + return "left" + } + + opacity: { + if (henCoop.player == null || henCoop.player.characterPath == "") + return 0 + return 1 + } + + Image { + id: plate + source: { + if (henCoop.player == null || henCoop.player.characterPath == "") + return "" + "qrc:/images/battlefield/hencoop_plate.png" + } + + smooth: true + anchors { + top: parent.top + left: { + if (henCoop.side == "left") + return parent.left + else + return undefined + } + right: { + if (henCoop.side == "right") + return parent.right + else + return undefined + } + } + } + + Image { + id: house + + smooth: true + source: { + if (henCoop.player == null || henCoop.player.characterPath == "") + return "" + return henCoop.player.characterPath + "/hencoop.png" + } + + anchors { + top: parent.top + left: { + if (henCoop.side == "left") + return parent.left + else + return undefined + } + right: { + if (henCoop.side == "right") + return parent.right + else + return undefined + } + leftMargin: 12 + } + + Text { + id: score + + text: { + if (player != null) + return player.score + else + return "0" + } + + color: "white" + style: Text.Outline + styleColor: "black" + smooth: true + + font { + family: "Nokia Sans" + pointSize: 30 + bold: true + } + + anchors { + horizontalCenter: parent.horizontalCenter + top: parent.top + topMargin: 20 + } + } + } +} diff --git a/chicken-wranglers/src/qml/HostView.qml b/chicken-wranglers/src/qml/HostView.qml new file mode 100644 index 0000000..fd37ab2 --- /dev/null +++ b/chicken-wranglers/src/qml/HostView.qml @@ -0,0 +1,94 @@ +/**************************************************************************** +** +** This file is a part of QtChickenWranglers. +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).* +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +** FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +** COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +** BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +** ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +** POSSIBILITY OF SUCH DAMAGE." +** +****************************************************************************/ + + +import Qt 4.7 + +import "widgets" +import "common.js" as Common + +Screen { + id: hostView + + anchors.fill: parent + focus: true + + WaitingRoomView { + id: waitingRoomView + + anchors.fill: parent + + onBack: closeRequested() + + onMatchStarted: { + matchViewLoader.source = "MatchView.qml" + } + } + + Loader { + id: matchViewLoader + + signal closeRequested + signal closeFinished + + anchors.fill: parent + + onLoaded: { + Common.switchScreens(waitingRoomView, matchViewLoader.item) + focus = true + } + + onCloseRequested: Common.switchScreens(matchViewLoader.item, waitingRoomView) + onCloseFinished: { + matchViewLoader.source = "" + } + } + + onTransitionFinished: { + if (!visible) + closeFinished() + } + + Component.onCompleted: { + waitingRoomView.show() + waitingRoomView.focus = true + } +} diff --git a/chicken-wranglers/src/qml/Laser.qml b/chicken-wranglers/src/qml/Laser.qml new file mode 100644 index 0000000..2444d0f --- /dev/null +++ b/chicken-wranglers/src/qml/Laser.qml @@ -0,0 +1,147 @@ +/**************************************************************************** +** +** This file is a part of QtChickenWranglers. +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).* +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +** FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +** COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +** BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +** ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +** POSSIBILITY OF SUCH DAMAGE." +** +****************************************************************************/ + + +import Qt 4.7 + +import game.types 1.0 + +Image { + id: laser + + property int step: 1 + property int maxSteps: 5 + property string orientation: "" + property bool turnedOn: false + + property string path: "qrc:/images/laser/laser_" + orientation + "_" + step + ".png" + source: "" + + onSourceChanged: { + // FIXME: Laser image's width and height should not + // be hardcoded. We are forcing this due to a bug in + // Image element after we change source property. + if (orientation == "vertical") { + laser.width = 27 * matchScreen.displayScale + laser.height = 83 * matchScreen.displayScale + } else { + laser.width = 83 * matchScreen.displayScale + laser.height = 27 * matchScreen.displayScale + } + } + + function turnOn(cellX, cellY, cellSize, direction) { + if (direction == Global.LaserLeft || direction == Global.LaserRight) + orientation = "vertical" + else + orientation = "horizontal" + + // FIXME: Same as above. + var diffWidth = ((83 * matchScreen.displayScale) - cellSize) / 2 + var diffHeight = (27 * matchScreen.displayScale) / 2 + + if (direction == Global.LaserUp) { + laser.x = cellX - diffWidth + laser.y = cellY - diffHeight + } else if (direction == Global.LaserDown) { + laser.x = cellX - diffWidth + laser.y = cellY + cellSize - diffHeight + } else if (direction == Global.LaserRight) { + laser.x = cellX + cellSize - diffHeight + laser.y = cellY - diffWidth + } else if (direction == Global.LaserLeft) { + laser.x = cellX - diffHeight + laser.y = cellY - diffWidth + } + + step = 0 + laserOnTimer.start() + } + + function turnOff(cell, direction) { + step = 4 + laserOffTimer.start(); + } + + Timer { + id: laserOnTimer + + repeat: true + interval: 50 + + onTriggered: { + if (step == maxSteps - 1) { + running = false + turnedOn = true + return + } + + step = step + 1 + laser.source = path + } + } + + Timer { + id: laserOffTimer + + repeat: true + interval: 50 + + onTriggered: { + + // FIXME: Check if laser wasn't turned on before + // destroying the previous one + if (step === 0) { + running = false + turnedOn = false + laser.destroy() + return + } + + step = step - 1 + + if (step == 0) + laser.source = "" + else + laser.source = path + } + } +} diff --git a/chicken-wranglers/src/qml/MatchView.qml b/chicken-wranglers/src/qml/MatchView.qml new file mode 100644 index 0000000..9f26cb1 --- /dev/null +++ b/chicken-wranglers/src/qml/MatchView.qml @@ -0,0 +1,345 @@ +/**************************************************************************** +** +** This file is a part of QtChickenWranglers. +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).* +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +** FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +** COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +** BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +** ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +** POSSIBILITY OF SUCH DAMAGE." +** +****************************************************************************/ + + +import Qt 4.7 + +import game.types 1.0 +import "common.js" as Common +import "match.js" as MatchLogic +import "widgets" + +Screen { + id: matchScreen + + anchors.fill: parent + color: "black" + smooth: true + focus: true + + property real displayScale: MatchLogic.getDisplayScale() + property real cellSize: MatchLogic.defaultCellSize * displayScale + property real fieldStartX: (MatchLogic.defaultFieldStartX * displayScale) + MatchLogic.deltaX + property real fieldStartY: (MatchLogic.defaultFieldStartY * displayScale) + MatchLogic.deltaY + + function showQuitDialog() { + quitDialog.show() + } + + function closeQuitDialog() { + quitDialog.hide() + } + + function showScore() { + score.show() + } + + function hideScore() { + score.hide() + } + + Image { + id: fieldBg + source: { + if (game.environment() == Global.Symbian) + "qrc:/images/battlefield/bg_fence_stones_mobile.png" + else + "qrc:/images/battlefield/bg_fence_stones.png" + } + scale : { + if (game.environment() == Global.Symbian) + 1.0 + else + battleField.scale + } + smooth: true + anchors.centerIn: battleField + } + + Item { + id: battleField + anchors.fill: parent + scale: displayScale + + Image { + id: topLeftCorner + + property PlayerModel player: playerListModel.get(0) + + opacity: { + if (player == null || player.characterPath == "") + return 1 + return 0 + } + + source: "qrc:/images/battlefield/fence_corner_top_left.png" + smooth: true + anchors { + left: fenceLayer.left + top: fenceLayer.top + } + } + + Image { + id: bottomRightCorner + + property PlayerModel player: playerListModel.get(1) + + opacity: { + if (player == null || player.characterPath == "") + return 1 + return 0 + } + + source: "qrc:/images/battlefield/fence_corner_bottom_right.png" + smooth: true + anchors { + right: fenceLayer.right + bottom: fenceLayer.bottom + } + } + + Image { + id: bottomLeftCorner + + property PlayerModel player: playerListModel.get(2) + + opacity: { + if (player == null || player.characterPath == "") + return 1 + return 0 + } + + source: "qrc:/images/battlefield/fence_corner_bottom_left.png" + smooth: true + anchors { + left: fenceLayer.left + bottom: fenceLayer.bottom + } + } + + Image { + id: topRightCorner + + property PlayerModel player: playerListModel.get(3) + + opacity: { + if (player == null || player.characterPath == "") + return 1 + return 0 + } + + source: "qrc:/images/battlefield/fence_corner_top_right.png" + smooth: true + anchors { + right: fenceLayer.right + top: fenceLayer.top + } + } + + Image { + id: fenceLayer + source: "qrc:/images/battlefield/fence_layer_over.png" + smooth: true + anchors.centerIn: parent + focus: true + } + + Image { + id: clockContainer + source: "qrc:/images/battlefield/clock.png" + smooth: true + anchors { + top: fenceLayer.top + horizontalCenter: parent.horizontalCenter + } + + Text { + id: clock + + text: matchController.elapsedTime + color: "white" + style: Text.Outline + smooth: true + + font { + bold: true + family: "Nokia Sans" + pointSize: 20 + } + + anchors.centerIn: parent + anchors.verticalCenterOffset: -6 + } + } + + ImageButton { + id: quitButton + name: "quit" + path: "qrc:/images/battlefield" + smooth: true + anchors { + bottom: fenceLayer.bottom + horizontalCenter: parent.horizontalCenter + } + + onClicked: MatchLogic.askQuitMatch() + } + } + + HenCoop { + playerNumber: 1 + + anchors { + top: parent.top + topMargin: 35 + left: parent.left + leftMargin: 29 + } + } + + HenCoop { + playerNumber: 2 + + anchors { + top: parent.verticalCenter + topMargin: 36 + right: parent.right + rightMargin: 29 + } + } + + HenCoop { + playerNumber: 3 + + anchors { + top: parent.verticalCenter + topMargin: 36 + left: parent.left + leftMargin: 29 + } + } + + HenCoop { + playerNumber: 4 + + anchors { + top: parent.top + topMargin: 35 + right: parent.right + rightMargin: 29 + } + } + + ConfirmationDialog { + id: quitDialog + + text: "Do you want to leave this match?" + opacity: 0 + + onRejected: { + closeQuitDialog() + MatchLogic.resumeMatch() + } + + onAccepted: { + closeQuitDialog() + MatchLogic.leaveMatch() + + closeRequested() + } + + z: 10 + } + + Score { + id: score + + opacity: 0 + + onClose: { + MatchLogic.leaveMatch() + hideScore() + + closeRequested() + } + } + + Rectangle { + id: background + + anchors.fill: parent + color: "black" + opacity: 0.7 + z: 49 + + MouseArea { + anchors.fill: parent + } + + Behavior on opacity { + PropertyAnimation { duration: 200 } + } + } + + Countdown { + id: countdown + + z: 50 + + anchors.fill: parent + onTimeout: { + background.opacity = 0 + MatchLogic.startMatch() + } + } + + onTransitionFinished: { + if (visible) + countdown.start() + else + closeFinished() + } + + Component.onCompleted: MatchLogic.newMatch() + + Keys.onEscapePressed: MatchLogic.askQuitMatch() +} diff --git a/chicken-wranglers/src/qml/PlayerControlView.qml b/chicken-wranglers/src/qml/PlayerControlView.qml new file mode 100644 index 0000000..b520587 --- /dev/null +++ b/chicken-wranglers/src/qml/PlayerControlView.qml @@ -0,0 +1,147 @@ +/**************************************************************************** +** +** This file is a part of QtChickenWranglers. +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).* +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +** FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +** COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +** BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +** ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +** POSSIBILITY OF SUCH DAMAGE." +** +****************************************************************************/ + + +import Qt 4.7 + +import "widgets" +import "common.js" as Common + +Screen { + id: screen + + property string characterPath: "" + property int margins: -60 + + signal back + + focus: true + + Keys.onUpPressed: gameClient.moveUp() + Keys.onDownPressed: gameClient.moveDown() + Keys.onLeftPressed: gameClient.moveLeft() + Keys.onRightPressed: gameClient.moveRight() + Keys.onSpacePressed: gameClient.moveStop() + + Keys.onPressed: { + switch (event.key) { + + // Quit the game + case Qt.Key_Q: + back() + break + + // Laser shots + case Qt.Key_W: + gameClient.toggleLaserUp() + break + + case Qt.Key_S: + gameClient.toggleLaserDown() + break + + case Qt.Key_A: + gameClient.toggleLaserLeft() + break + + case Qt.Key_D: + gameClient.toggleLaserRight() + break + } + + event.accepted = true + } + + Image { + anchors.fill: parent + + source: Common.getImagePath(characterPath, "control.png") + } + + Row { + anchors.fill: parent + + Item { + width: parent.width / 4 + height: parent.height + + MouseArea { + anchors.fill: parent + onClicked: gameClient.toggleLaserLeft() + } + } + + Column { + width: parent.width / 2 + height: parent.height + + Item { + width: parent.width + height: parent.height / 3 * 2 + + MouseArea { + anchors.fill: parent + onClicked: gameClient.toggleLaserUp() + } + } + + Item { + width: parent.width + height: parent.height / 3 + + MouseArea { + anchors.fill: parent + onClicked: gameClient.toggleLaserDown() + } + } + } + + Item { + width: parent.width / 4 + height: parent.height + + MouseArea { + anchors.fill: parent + onClicked: gameClient.toggleLaserRight() + } + } + } +} diff --git a/chicken-wranglers/src/qml/PlayerReadyView.qml b/chicken-wranglers/src/qml/PlayerReadyView.qml new file mode 100644 index 0000000..41e8c5a --- /dev/null +++ b/chicken-wranglers/src/qml/PlayerReadyView.qml @@ -0,0 +1,115 @@ +/**************************************************************************** +** +** This file is a part of QtChickenWranglers. +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).* +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +** FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +** COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +** BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +** ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +** POSSIBILITY OF SUCH DAMAGE." +** +****************************************************************************/ + + +import Qt 4.7 + +import game.types 1.0 +import "widgets" +import "common.js" as Common + +Screen { + property string characterPath: "" + + signal back + + anchors.fill: parent + + Image { + id: background + + source: { + if (game.environment() == Global.Symbian) + "qrc:/images/general/symbian/bg_selectcharacter.png" + else + "qrc:/images/general/bg_selectcharacter.png" + } + anchors.fill: parent + } + + + Image { + id: title + + anchors { + top: parent.top + horizontalCenter: parent.horizontalCenter + margins: 40 + } + + source: "qrc:/images/general/you_are_ready.png" + smooth: true + } + + Image { + anchors.centerIn: parent + + smooth: true + source: Common.getImagePath(characterPath, "select_character.png") + } + + Button { + text: "Start" + width: 200 + + // TODO: Enable this button if this client is P1 + opacity: 0 + + anchors { + horizontalCenter: parent.horizontalCenter + bottom: parent.bottom + margins: 20 + } + + onClicked: console.log("Start game via P1 client") + } + + ImageButton { + name: "back" + onClicked: back() + + anchors { + top: parent.top + right: parent.right + margins: 15 + } + } +} diff --git a/chicken-wranglers/src/qml/Score.qml b/chicken-wranglers/src/qml/Score.qml new file mode 100644 index 0000000..1776386 --- /dev/null +++ b/chicken-wranglers/src/qml/Score.qml @@ -0,0 +1,128 @@ +/**************************************************************************** +** +** This file is a part of QtChickenWranglers. +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).* +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +** FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +** COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +** BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +** ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +** POSSIBILITY OF SUCH DAMAGE." +** +****************************************************************************/ + + +import Qt 4.7 +import "widgets" + +import "match.js" as MatchLogic +import "common.js" as Common + +Item { + id: score + + property int numberOfPlayers: playerListModel.count() + property int scoreBoxTick: width / (numberOfPlayers + 1) + + signal close + + anchors.fill: parent + z: 10 + + function sortScore(scoreBox1, scoreBox2) { + return (scoreBox2.score - scoreBox1.score) + } + + function createScore() { + var scoreBoxList = [] + + for (var i = 0; i < numberOfPlayers; i++) { + var scoreBox + scoreBox = MatchLogic.createScoreBox() + if (scoreBox == undefined) + continue + + var player = playerListModel.get(i) + if (player == null) + continue + + scoreBox.source = Common.getImagePath(player.characterPath, "score.png") + scoreBox.score = player.score + scoreBox.z = 15 + scoreBox.y = 0 + + scoreBoxList.push(scoreBox) + } + + scoreBoxList.sort(sortScore) + + for (var i = 0; i < scoreBoxList.length; i++) + scoreBoxList[i].x = (scoreBoxTick * (i + 1)) - (scoreBoxList[i].width / 2) + + closeTimer.start() + } + + function show() { + opacity = 1 + } + + function hide() { + opacity = 0 + } + + Behavior on opacity { + NumberAnimation { duration: 500 } + } + + Rectangle { + anchors.fill: parent + color: "black" + opacity: 0.8 + + MouseArea { + anchors.fill: parent + } + } + + Timer { + id: closeTimer + + interval: 5000 + + onTriggered: close() + } + + onOpacityChanged: { + if (opacity == 1) { + createScore() + } + } +} diff --git a/chicken-wranglers/src/qml/ScoreBox.qml b/chicken-wranglers/src/qml/ScoreBox.qml new file mode 100644 index 0000000..ef2f19d --- /dev/null +++ b/chicken-wranglers/src/qml/ScoreBox.qml @@ -0,0 +1,81 @@ +/**************************************************************************** +** +** This file is a part of QtChickenWranglers. +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).* +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +** FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +** COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +** BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +** ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +** POSSIBILITY OF SUCH DAMAGE." +** +****************************************************************************/ + + +import Qt 4.7 + +Image { + id: scoreBox + + property int score: 0 + + y: -593 * matchScreen.displayScale // FIXME: Use image height instead + smooth: true + width: scoreBox.sourceSize.width * matchScreen.displayScale + height: scoreBox.sourceSize.height * matchScreen.displayScale + + Text { + text: score + style: Text.Outline + color: "white" + smooth: true + + font { + family: "Nokia Sans" + pointSize: 60 * matchScreen.displayScale + bold: true + } + + anchors { + horizontalCenter: parent.horizontalCenter + bottom: parent.bottom + bottomMargin: 30 * matchScreen.displayScale + } + } + + Behavior on y { + PropertyAnimation { + duration: 1000 + easing.type: Easing.OutBounce + } + } +} + diff --git a/chicken-wranglers/src/qml/Splash.qml b/chicken-wranglers/src/qml/Splash.qml new file mode 100644 index 0000000..5a1aa38 --- /dev/null +++ b/chicken-wranglers/src/qml/Splash.qml @@ -0,0 +1,79 @@ +/**************************************************************************** +** +** This file is a part of QtChickenWranglers. +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).* +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +** FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +** COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +** BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +** ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +** POSSIBILITY OF SUCH DAMAGE." +** +****************************************************************************/ + + +import Qt 4.7 + +import game.types 1.0 +import "widgets" + +Screen { + id: screen + + property int time: 1500 + + Image { + id: background + + smooth: true + + anchors.fill: parent + source: { + if (game.environment() == Global.Symbian) + "qrc:/images/general/symbian/bg_splash.png" + else + "qrc:/images/general/bg_splash.png" + } + } + + Timer { + running: true + interval: time + repeat: false + + onTriggered: timeout() + } + + onTransitionFinished: { + if (!visible) + closeFinished() + } +} diff --git a/chicken-wranglers/src/qml/StartView.qml b/chicken-wranglers/src/qml/StartView.qml new file mode 100644 index 0000000..fd2905d --- /dev/null +++ b/chicken-wranglers/src/qml/StartView.qml @@ -0,0 +1,246 @@ +/**************************************************************************** +** +** This file is a part of QtChickenWranglers. +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).* +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +** FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +** COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +** BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +** ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +** POSSIBILITY OF SUCH DAMAGE." +** +****************************************************************************/ + + +import Qt 4.7 +import game.types 1.0 + +import "client.js" as Client +import "host.js" as Host +import "widgets" + +Screen { + id: screen + + signal hostSelected + signal clientSelected + signal clientDiscoveryCanceled + + function showStartServerDialog() { + startServerDialog.show() + } + + function hideStartServerDialog() { + startServerDialog.hide() + } + + function showStartClientDialog() { + if (game.connectivity == "bluetooth") { + connectivityDialog.model = connectivityListModel + connectivityDialog.show() + } else { + startClientDialog.show() + } + } + + function hideStartClientDialog() { + if (game.connectivity == "bluetooth") { + gameClient.scanCanceled() + connectivityDialog.hide() + } else + startClientDialog.hide() + } + + function showErrorDialog(msg) { + errorDialog.text = msg + errorDialog.show() + } + + function hideErrorDialog() { + errorDialog.hide() + } + + onHostSelected: Host.start() + onClientSelected: Client.start() + + Image { + id: background + + smooth: true + anchors.fill: parent + + source: { + if (game.environment() == Global.Symbian) + "qrc:/images/general/symbian/bg_640x360.png" + else if (game.environment() == Global.Maemo) + "qrc:/images/general/bg_800x480.png" + else + "qrc:/images/general/bg_1280x768.png" + } + } + + FeatherFall { + id: featherFall + number: { + if (game.environment() == Global.Symbian) + 2 + else if (game.environment() == Global.Maemo) + 3 + else + 5 + } + fallWidth:{ + if (game.environment() == Global.Symbian) + 640 + else + 800 + } + fallHeight:{ + if (game.environment() == Global.Symbian) + 360 + else + 768 + } + + anchors.fill: parent + } + + Item { + anchors { + centerIn: parent + horizontalCenterOffset: 90 + verticalCenterOffset: 120 + margins: 100 + } + + Button { + id: hostGameButton + + anchors { + right: parent.right + bottom: parent.bottom + } + + text: "Host game" + width: 200 + onClicked: hostSelected() + } + + Button { + id: joinGameButton + + anchors { + left: parent.left + leftMargin: 10 + bottom: parent.bottom + } + + text: "Join game" + width: 200 + onClicked: clientSelected() + } + } + + ImageButton { + anchors { + top: parent.top + left: parent.left + margins: 15 + } + + name: "close" + onClicked: Qt.quit() + } + + ToggleButton { + anchors { + top: parent.top + right: parent.right + margins: 15 + } + } + + MessageDialog { + id: startClientDialog + + text: "Searching for server" + buttonText: "Cancel" + opacity: 0 + + Loading { + anchors.horizontalCenter: startClientDialog.box.horizontalCenter + anchors.bottom: startClientDialog.box.bottom + anchors.bottomMargin: 100 + } + + onButtonClicked: clientDiscoveryCanceled() + } + + ConnectivityDialog { + id: connectivityDialog + + opacity: 0 + onCancel: { + connectivityDialog.hide() + gameClient.scanCanceled() + } + } + + MessageDialog { + id: startServerDialog + + text: "Creating server" + opacity: 0 + + Loading { + anchors.horizontalCenter: startServerDialog.box.horizontalCenter + anchors.bottom: startServerDialog.box.bottom + anchors.bottomMargin: 100 + } + } + + MessageDialog { + id: errorDialog + + text: "error" + buttonText: "Close" + opacity: 0 + + onButtonClicked: hideErrorDialog() + } + + onOpacityChanged: { + if (opacity == 1) + featherFall.start() + else if (opacity == 0) + featherFall.stop() + } +} diff --git a/chicken-wranglers/src/qml/WaitingRoomView.qml b/chicken-wranglers/src/qml/WaitingRoomView.qml new file mode 100644 index 0000000..64b0bea --- /dev/null +++ b/chicken-wranglers/src/qml/WaitingRoomView.qml @@ -0,0 +1,288 @@ +/**************************************************************************** +** +** This file is a part of QtChickenWranglers. +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).* +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +** FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +** COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +** BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +** ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +** POSSIBILITY OF SUCH DAMAGE." +** +****************************************************************************/ + + +import Qt 4.7 + +import game.types 1.0 +import "common.js" as Common +import "widgets" + +Screen { + id: screen + + signal back + signal matchStarted + + Keys.onReturnPressed: { + if (buttonStart.enabled) + matchStarted() + } + + Image { + id: background + smooth: true + anchors.fill: parent + source: { + if (game.environment() == Global.Symbian) + "qrc:/images/general/symbian/bg_640x360.png" + else if (game.environment() == Global.Maemo) + "qrc:/images/general/bg_800x480.png" + else + "qrc:/images/general/bg_1280x768.png" + } + } + + ImageButton { + anchors { + left: screen.left + top: screen.top + margins: 15 + } + + name: "back" + onClicked: back() + } + + + Button { + id: buttonStart + + anchors { + top: screen.top + right: screen.right + margins: 15 + } + + width: 160 + text: "Start" + sourceName: "bt_start" + rightBorder: 35 + horizontalCenterOffset: -6 + italic: true + + enabled: playerListModel.playersReady; + + onClicked: matchStarted() + } + + ListView { + id: playerListView + anchors { + centerIn: parent + horizontalCenterOffset: 30 + verticalCenterOffset: 130 + } + + height: 400 + width: 400 + model: playerListModel + delegate: playerListDelegate + interactive: false + } + + Component { + id: playerListDelegate + + Item { + id: delegatePlayer + + scale: { + if (game.environment() == Global.Symbian) + 0.7 + else + 1 + } + + width: 400 + height: 80 + + property bool isReady: status == PlayerModel.Ready + + states { + State { + name: "playerReady"; when: isReady + PropertyChanges { target: playerInfo; opacity: 1 } + PropertyChanges { target: playerInfoUnknown; opacity: 0 } + } + } + + Image { + id: listItemBg + + anchors { + top: playerInfoUnknown.top + topMargin: 32 + } + + source: "qrc:/images/general/list_name_bg.png" + } + + Item { + id: playerInfoUnknown + + Image { + id: listItemIconUnknown + + smooth: true + + anchors { + top: parent.top + left: parent.left + leftMargin: 25 + } + + source: "qrc:/images/general/list_unknown_character.png" + fillMode: Image.PreserveAspectFit + } + + Loading { + id: listItemLoading + + anchors { + left: listItemIconUnknown.right + leftMargin: 40 + bottom: listItemIconUnknown.bottom + bottomMargin: 20 + } + } + + } + + Item { + id: playerInfo + + opacity: 0 + + Image { + id: listItemIcon + + smooth: true + + anchors { + top: parent.top + left: parent.left + leftMargin: 25 + } + + source: Common.getImagePath(characterPath, "waitinglist.png") + fillMode: Image.PreserveAspectFit + } + + + Item { + id: listItemNameOk + + anchors { + left: listItemIcon.right + leftMargin: 15 + bottom: listItemIcon.bottom + bottomMargin: 12 + } + + Image { + id: listItemName + + smooth: true + + anchors { + left: listItemNameOk.left + bottom: listItemNameOk.bottom + } + + source: Common.getImagePath(characterPath, "name.png") + fillMode: Image.PreserveAspectFit + } + + Image { + id: listItemOk + + smooth: true + + anchors { + left: listItemName.right + leftMargin: 30 + verticalCenter: listItemName.verticalCenter + } + + source: "qrc:/images/general/list_status_ok.png" + fillMode: Image.PreserveAspectFit + } + } + + ParallelAnimation { + id: anim + + SequentialAnimation { + PropertyAnimation { + target: listItemIcon + property: "scale" + duration: 300 + easing.type: Easing.InOutBack + to: 2 + } + PropertyAnimation { + target: listItemIcon + property: "scale" + duration: 200 + to: 1 + } + } + } + + onOpacityChanged: { + anim.running = true + } + } + + ListView.onAdd: SequentialAnimation { + PropertyAction { target: delegatePlayer; property: "scale"; value: 0 } + NumberAnimation { target: delegatePlayer; property: "scale"; to: 1; duration: 250; easing.type: Easing.InOutQuad } + } + + ListView.onRemove: SequentialAnimation { + PropertyAction { target: delegatePlayer; property: "ListView.delayRemove"; value: true } + NumberAnimation { target: delegatePlayer; property: "scale"; to: 0; duration: 250; easing.type: Easing.InOutQuad } + PropertyAction { target: delegatePlayer; property: "ListView.delayRemove"; value: false } + } + } + } +} diff --git a/chicken-wranglers/src/qml/client.js b/chicken-wranglers/src/qml/client.js new file mode 100644 index 0000000..16eb9f8 --- /dev/null +++ b/chicken-wranglers/src/qml/client.js @@ -0,0 +1,72 @@ +function start() { + game.mode = Game.ClientMode + + startViewLoader.item.showStartClientDialog("Looking for server") + startViewLoader.item.clientDiscoveryCanceled.connect(cancelDiscovery) + + // gameClient only exists after game.mode is set to Game.ClientMode + gameClient.statusChanged.connect(onStatusChanged) + gameClient.startConnection() +} + +function cancelDiscovery() { + if (gameClient.status == GameClient.Joined) { + gameClient.statusChanged.disconnect(onStatusChanged) + startViewLoader.item.clientDiscoveryCanceled.disconnect(cancelDiscovery) + startViewLoader.item.hideStartClientDialog() + return + } + + quit() +} + +function quit() { + gameClient.statusChanged.disconnect(onStatusChanged) + startViewLoader.item.clientDiscoveryCanceled.disconnect(cancelDiscovery) + startViewLoader.item.hideStartClientDialog() + + gameClient.quit() +} + +function onStatusChanged() { + switch (gameClient.status) { + + case GameClient.Joined: + startViewLoader.item.hideStartClientDialog() + clientViewLoader.source = "ClientView.qml" + break + + case GameClient.LeftMatch: + clientViewLoader.item.showPlayerReadyView() + break + + case GameClient.Ready: + clientViewLoader.item.showControlView() + break + + case GameClient.Error: + startViewLoader.item.hideStartClientDialog() + handleError(gameClient.error) + break + + default: + console.log("Unknown client status") + } +} + +function handleError(error) { + switch (error) { + + case GameClient.ServerDiscoveryTimeoutError: + startViewLoader.item.showErrorDialog("Host not found") + break + + case GameClient.SocketError: + clientViewLoader.closeRequested() + startViewLoader.item.showErrorDialog("Disconnected from host") + break + + default: + console.log("Unknown client error") + } +} diff --git a/chicken-wranglers/src/qml/common.js b/chicken-wranglers/src/qml/common.js new file mode 100644 index 0000000..2ce1585 --- /dev/null +++ b/chicken-wranglers/src/qml/common.js @@ -0,0 +1,26 @@ +var tempFrom +var tempTo + +function switchScreens(from, to) { + if (!from || !to) + return + + tempFrom = from + tempTo = to + + from.hide() + from.opacityChanged.connect(showNextScreen) +} + +function showNextScreen() { + if (tempFrom.opacity == 0) { + tempTo.show() + } +} + +function getImagePath(basePath, fileName) { + if (basePath == "") + return "" + + return basePath + "/" + fileName +} diff --git a/chicken-wranglers/src/qml/host.js b/chicken-wranglers/src/qml/host.js new file mode 100644 index 0000000..d545c31 --- /dev/null +++ b/chicken-wranglers/src/qml/host.js @@ -0,0 +1,46 @@ +function start() { + game.mode = Game.HostMode + + startViewLoader.item.showStartServerDialog("Creating server") + + // gameHosts only exists after game.mode is set to Game.HostMode + gameHost.statusChanged.connect(onStatusChanged) + gameHost.startConnection() +} + +function quit() { + gameHost.statusChanged.disconnect(onStatusChanged) + startViewLoader.item.hideStartServerDialog() + + gameHost.quit(); +} + +function onStatusChanged() { + switch (gameHost.status) { + + case GameHost.Start: + startViewLoader.item.hideStartServerDialog() + hostViewLoader.source = "HostView.qml" + break + + case GameHost.Error: + startViewLoader.item.hideStartServerDialog() + handleError(gameHost.error) + break + + default: + console.log("Unknown server status") + } +} + +function handleError(error) { + switch (error) { + + case GameHost.AnotherServerRunningError: + startViewLoader.item.showErrorDialog("Server is already running") + break + + default: + console.log("Unknown server error") + } +} diff --git a/chicken-wranglers/src/qml/main.qml b/chicken-wranglers/src/qml/main.qml new file mode 100644 index 0000000..32ac3f3 --- /dev/null +++ b/chicken-wranglers/src/qml/main.qml @@ -0,0 +1,126 @@ +/**************************************************************************** +** +** This file is a part of QtChickenWranglers. +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).* +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +** FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +** COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +** BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +** ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +** POSSIBILITY OF SUCH DAMAGE." +** +****************************************************************************/ + + +import Qt 4.7 +import game.types 1.0 + +import "common.js" as Common +import "host.js" as Host +import "client.js" as Client +import "widgets" + +Rectangle { + id: main + + width: 800 + height: 480 + + focus: true + + SystemPalette { id: activePalette } + + Loader { + id: splashScreenLoader + + signal closeFinished + signal timeout + + anchors.fill: parent + + onLoaded: splashScreenLoader.item.show() + onTimeout: startViewLoader.source = "StartView.qml" + onCloseFinished: { + splashScreenLoader.source = "" + game.startBackgroundSound() + } + } + + Loader { + id: startViewLoader + + anchors.fill: parent + + onLoaded: Common.switchScreens(splashScreenLoader.item, startViewLoader.item) + } + + Loader { + id: hostViewLoader + + signal closeRequested + signal closeFinished + + anchors.fill: parent + + onLoaded: { + focus = true + Common.switchScreens(startViewLoader.item, hostViewLoader.item) + } + + onCloseRequested: Common.switchScreens(hostViewLoader.item, startViewLoader.item) + onCloseFinished: { + Host.quit() + hostViewLoader.source = "" + } + } + + Loader { + id: clientViewLoader + + signal closeRequested + signal closeFinished + + anchors.fill: parent + + onLoaded: { + focus = true + Common.switchScreens(startViewLoader.item, clientViewLoader.item) + } + + onCloseRequested: Common.switchScreens(clientViewLoader.item, startViewLoader.item) + onCloseFinished: { + Client.quit() + clientViewLoader.source = "" + } + } + + Component.onCompleted: splashScreenLoader.source = "Splash.qml" +} diff --git a/chicken-wranglers/src/qml/match.js b/chicken-wranglers/src/qml/match.js new file mode 100644 index 0000000..be9628e --- /dev/null +++ b/chicken-wranglers/src/qml/match.js @@ -0,0 +1,310 @@ +var defaultRows = settings.battlefieldSize().height +var defaultColumns = settings.battlefieldSize().width +var defaultFieldStartX = settings.battlefieldStartPoint().x +var defaultFieldStartY = settings.battlefieldStartPoint().y +var defaultCellSize = settings.battlefieldCellSize() +var defaultHostWidth = settings.hostDisplaySize().width +var defaultHostHeight = settings.hostDisplaySize().height + +// FIXME: Find better naming and place for these variables +var deltaX = 0 +var deltaY = 0 + +// Chicken values +var chickenMoveIntervalNormal = settings.matchChickenMoveInterval() +var chickenMoveIntervalRunning = chickenMoveIntervalNormal * 0.7 +var chickenChangeStepsIntervalNormal = settings.matchChickenChangeStepsInterval() +var chickenChangeStepsIntervalRunning = chickenChangeStepsIntervalNormal * 0.7 + +// Character values +var characterMoveInterval = settings.matchCharacterMoveInterval() +var characterChangeStepsInterval = settings.matchChickenChangeStepsInterval() + +var chickenComponent = null +var playerComponent = null +var playerScoreComponent = null +var henCoopComponent = null +var laserComponent = null + +var verticalLaserArray = null +var horizontalLaserArray = null +var chickenArray = new Array() +var playerArray = new Array() + +function initLaserArrays() +{ + verticalLaserArray = new Array(defaultRows) + for (var y = 0; y < defaultRows; y++) + verticalLaserArray[y] = new Array(defaultColumns - 1) + + horizontalLaserArray = new Array(defaultRows - 1) + for (var y = 0; y < defaultRows - 1; y++) + horizontalLaserArray[y] = new Array(defaultColumns) + + for (var y = 0; y < defaultRows; y++) + for (var x = 0; x < defaultColumns - 1; x++) + verticalLaserArray[y][x] = null + + for (var y = 0; y < defaultRows - 1; y++) + for (var x = 0; x < defaultColumns; x++) + horizontalLaserArray[y][x] = null +} + +function destroyLasers() +{ + for (var y = 0; y < defaultRows; y++) + for (var x = 0; x < defaultColumns - 1; x++) { + if (verticalLaserArray[y][x] != null && verticalLaserArray[y][x] != undefined) { + verticalLaserArray[y][x].destroy() + verticalLaserArray[y][x] = null + } + } + + for (var y = 0; y < defaultRows - 1; y++) + for (var x = 0; x < defaultColumns; x++) { + if (horizontalLaserArray[y][x] != null && horizontalLaserArray[y][x] != undefined) { + horizontalLaserArray[y][x].destroy() + horizontalLaserArray[y][x] = null + } + } +} + +function getDisplayScale() { + var scaleX = game.displaySize.width / defaultHostWidth + var scaleY = game.displaySize.height / defaultHostHeight + + var max = Math.max(scaleX, scaleY) + deltaX = ((max - scaleY) * defaultHostWidth) / 2 + deltaY = ((max - scaleX) * defaultHostHeight) / 2 + + return Math.min(scaleX, scaleY) +} + +function newMatch() { + gameHost.status = GameHost.Match + + initLaserArrays(); + + matchController.chickenCreated.connect(onChickenCreated); + matchController.playerCreated.connect(onPlayerCreated); + matchController.laserUpdated.connect(onLaserUpdated); + matchController.matchFinished.connect(onMatchFinished); + + matchController.setupMatch() + matchController.status = Match.Paused +} + +function startMatch() { + matchController.status = Match.Started + + for (var i = 0; i < playerArray.length; i++) + playerArray[i].opacity = 1 +} + +function askQuitMatch() { + if (matchController.status == Match.Running) + matchController.status = Match.Paused + + matchScreen.showQuitDialog() +} + +function resumeMatch() { + matchController.status = Match.Running +} + +function leaveMatch() { + destroyChickens() + destroyPlayers() + destroyLasers() + + matchController.status = Match.Over +} + +function onMatchFinished() { + matchController.status = Match.Paused + + matchScreen.showScore() +} + +function destroyChickens() +{ + for (var i = 0; i < chickenArray.length; i++) + if (chickenArray[i] != undefined && chickenArray[i] != null) { + chickenArray[i].destroy() + chickenArray[i] = null + } +} + +function destroyPlayers() +{ + for (var i = 0; i < playerArray.length; i++) + if (playerArray[i] != undefined && playerArray[i] != null) { + playerArray[i].destroy() + playerArray[i] = null + } +} + +function onChickenCreated(id) +{ + if (chickenComponent == null) + chickenComponent = Qt.createComponent("Chicken.qml"); + + if (chickenComponent.status == Component.Ready) { + var dynamicObject = chickenComponent.createObject(matchScreen); + if (dynamicObject == null) { + console.log("error creating chicken"); + console.log(chickenComponent.errorString()); + return false; + } + + chickenArray[id] = dynamicObject + + var chickenController = matchController.getChicken(id) + chickenController.positionChanged.connect(dynamicObject.onPositionChanged) + dynamicObject.controller = chickenController + dynamicObject.x = matchScreen.fieldStartX + (chickenController.position.x * matchScreen.cellSize) + (matchScreen.cellSize - dynamicObject.width) / 2 + dynamicObject.y = matchScreen.fieldStartY + (chickenController.position.y * matchScreen.cellSize) + (matchScreen.cellSize - dynamicObject.height) / 2 + } else { + console.log("error loading block chickenComponent"); + console.log(chickenComponent.errorString()); + return false; + } + + return true; +} + +function onPlayerCreated(id) +{ + if (playerComponent == null) + playerComponent = Qt.createComponent("Character.qml"); + + if (playerComponent.status == Component.Ready) { + // TODO: Only players with status Ready should be added + var dynamicObject = playerComponent.createObject(matchScreen); + if (dynamicObject == null) { + console.log("error creating character"); + console.log(playerComponent.errorString()); + return false; + } + + dynamicObject.playerNumber = id + playerArray[id] = dynamicObject + + var playerController = matchController.getPlayer(id) + dynamicObject.controller = playerController + playerController.laserToggleRequested.connect(dynamicObject.onLaserToggleRequested) + + dynamicObject.model = playerListModel.get(id) + } else { + console.log("error loading block playerComponent"); + console.log(playerComponent.errorString()); + return false; + } + + return true; +} + +function createScoreBox() +{ + if (playerScoreComponent == null) + playerScoreComponent = Qt.createComponent("ScoreBox.qml"); + + var dynamicObject = null; + + if (playerScoreComponent.status == Component.Ready) { + dynamicObject = playerScoreComponent.createObject(score); + if (dynamicObject == null) { + console.log("error creating laser"); + console.log(playerScoreComponent.errorString()); + return null; + } + } else { + console.log("error loading block playerScoreComponent"); + console.log(playerScoreComponent.errorString()); + return null; + } + + return dynamicObject + +} + +function createLaser() +{ + if (laserComponent == null) + laserComponent = Qt.createComponent("Laser.qml"); + + var dynamicObject = null; + + if (laserComponent.status == Component.Ready) { + dynamicObject = laserComponent.createObject(matchScreen); + if (dynamicObject == null) { + console.log("error creating laser"); + console.log(laserComponent.errorString()); + return null; + } + } else { + console.log("error loading block laserComponent"); + console.log(laserComponent.errorString()); + return null; + } + + return dynamicObject +} + +function removeLaser(x, y, direction) +{ + var laserObj = null + + if (direction == Global.LaserRight && x < defaultColumns - 1) { + laserObj = verticalLaserArray[y][x] + verticalLaserArray[y][x] = null + } else if (direction == Global.LaserLeft && x >= 0) { + laserObj = verticalLaserArray[y][x - 1] + verticalLaserArray[y][x - 1] = null + } else if (direction == Global.LaserUp && y > 0) { + laserObj = horizontalLaserArray[y - 1][x] + horizontalLaserArray[y - 1][x] = null + } else if (direction == Global.LaserDown && y < defaultRows - 1) { + laserObj = horizontalLaserArray[y][x] + horizontalLaserArray[y][x] = null + } + + if (laserObj == null) + return + + var cellX = matchScreen.fieldStartX + x * (defaultCellSize * matchScreen.displayScale) + var cellY = matchScreen.fieldStartY + y * (defaultCellSize * matchScreen.displayScale) + + laserObj.turnOff(cellX, cellY, defaultCellSize * matchScreen.displayScale, direction) +} + +function addLaser(x, y, direction) +{ + var laserObj = createLaser(); + + if (direction == Global.LaserRight && verticalLaserArray[y][x] == null) + verticalLaserArray[y][x] = laserObj + else if (direction == Global.LaserLeft && verticalLaserArray[y][x - 1] == null) + verticalLaserArray[y][x - 1] = laserObj + else if (direction == Global.LaserUp && horizontalLaserArray[y - 1][x] == null) + horizontalLaserArray[y - 1][x] = laserObj + else if (direction == Global.LaserDown && horizontalLaserArray[y][x] == null) + horizontalLaserArray[y][x] = laserObj + else { + laserObj.destroy() + return + } + + var cellX = matchScreen.fieldStartX + x * (defaultCellSize * matchScreen.displayScale) + var cellY = matchScreen.fieldStartY + y * (defaultCellSize * matchScreen.displayScale) + + laserObj.turnOn(cellX, cellY, defaultCellSize * matchScreen.displayScale, direction) +} + +function onLaserUpdated(posX, posY, laserDirection, isOn) +{ + if (isOn) + addLaser(posX, posY, laserDirection) + else + removeLaser(posX, posY, laserDirection) +} diff --git a/chicken-wranglers/src/qml/qml.qrc b/chicken-wranglers/src/qml/qml.qrc new file mode 100644 index 0000000..615d922 --- /dev/null +++ b/chicken-wranglers/src/qml/qml.qrc @@ -0,0 +1,43 @@ + <!DOCTYPE RCC><RCC version="1.0"> + <qresource prefix="/"> + <file>main.qml</file> + <file>common.js</file> + <file>client.js</file> + <file>host.js</file> + <file>Splash.qml</file> + <file>StartView.qml</file> + <file>widgets/Screen.qml</file> + <file>widgets/Button.qml</file> + <file>widgets/ImageButton.qml</file> + <file>widgets/Loading.qml</file> + <file>widgets/BaseDialog.qml</file> + <file>widgets/MessageDialog.qml</file> + <file>widgets/ConfirmationDialog.qml</file> + <file>widgets/Feather.qml</file> + <file>widgets/FeatherFall.qml</file> + <file>widgets/featherfall.js</file> + <file>widgets/Countdown.qml</file> + <file>widgets/OptionSlider.qml</file> + <file>widgets/Scrollbar.qml</file> + <file>widgets/ConnectivityDialog.qml</file> + <file>widgets/ConnectivityListView.qml</file> + <file>widgets/ToggleButton.qml</file> + + <file>ClientView.qml</file> + <file>CharacterSelectionView.qml</file> + <file>PlayerReadyView.qml</file> + <file>PlayerControlView.qml</file> + + <file>HostView.qml</file> + <file>WaitingRoomView.qml</file> + <file>MatchView.qml</file> + <file>Laser.qml</file> + <file>Score.qml</file> + <file>ScoreBox.qml</file> + <file>HenCoop.qml</file> + <file>Being.qml</file> + <file>Character.qml</file> + <file>Chicken.qml</file> + <file>match.js</file> + </qresource> + </RCC> diff --git a/chicken-wranglers/src/qml/widgets/BaseDialog.qml b/chicken-wranglers/src/qml/widgets/BaseDialog.qml new file mode 100644 index 0000000..e1cea04 --- /dev/null +++ b/chicken-wranglers/src/qml/widgets/BaseDialog.qml @@ -0,0 +1,112 @@ +/**************************************************************************** +** +** This file is a part of QtChickenWranglers. +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).* +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +** FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +** COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +** BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +** ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +** POSSIBILITY OF SUCH DAMAGE." +** +****************************************************************************/ + + +import Qt 4.7 + +import game.types 1.0 + +Item { + id: dialog + + property alias box: box + + signal showFinished + signal hideFinished + + anchors.fill: parent + + function show() { + dialog.opacity = 1 + } + + function hide() { + dialog.opacity = 0 + } + + onOpacityChanged: { + if (dialog.opacity == 1) + showFinished() + else if (dialog.opacity == 0) + hideFinished() + } + + Rectangle { + id: background + + anchors.fill: parent + color: "black" + opacity: 0.7 + + MouseArea { + anchors.fill: parent + } + } + + function backgroundSize() { + var res = {}; + res["height"] = 376 + res["width"] = 622 + + // XXX: if in symbian, make the dialog smaller + if (game.environment() == Global.Symbian) { + res.height = 0.9 * dialog.height + res.width = 0.9 * dialog.width + } + return res; + } + + Image { + id: box + + source: { + if (game.environment() == Global.Symbian) + "qrc:/images/general/symbian/bg_dialog.png" + else + "qrc:/images/general/bg_dialog.png" + } + anchors.centerIn: parent + } + + Behavior on opacity { + NumberAnimation { duration: 200 } + } +} diff --git a/chicken-wranglers/src/qml/widgets/Button.qml b/chicken-wranglers/src/qml/widgets/Button.qml new file mode 100644 index 0000000..6ccd512 --- /dev/null +++ b/chicken-wranglers/src/qml/widgets/Button.qml @@ -0,0 +1,133 @@ +/**************************************************************************** +** +** This file is a part of QtChickenWranglers. +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).* +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +** FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +** COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +** BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +** ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +** POSSIBILITY OF SUCH DAMAGE." +** +****************************************************************************/ + + +import Qt 4.7 + +BorderImage { + id: button + + property int leftBorder: 18 + property int rightBorder: 18 + property int horizontalCenterOffset: 0 + property string sourceName: "bt" + property string text: "" + property bool blink: false + property bool enabled: true + property bool italic: false + + signal clicked + + source: { + if (!enabled) + return "qrc:/images/general/" + sourceName + "_disabled.png" + + if (mouseArea.pressed) + return "qrc:/images/general/" + sourceName + "_pressed.png" + else + return "qrc:/images/general/" + sourceName + ".png" + } + + smooth: true + + border { + left: leftBorder + right: rightBorder + } + + width: buttonText.width + 40 + + PropertyAnimation { + id: blinkAnimation + + target: button + properties: "opacity" + loops: 2 + from: 0 + to: 1 + duration: 200 + + onRunningChanged: { + if (!running) + button.clicked() + } + } + + Text { + id: buttonText + + text: button.text + smooth: true + + color: { + if (button.enabled) + "#77262d" + else + "#666666" + } + + anchors { + centerIn: parent + verticalCenterOffset: -3 + horizontalCenterOffset: button.horizontalCenterOffset + } + + font { + family: "Nokia Sans" + pixelSize: 26 + bold: true + italic: button.italic + } + } + + MouseArea { + id: mouseArea + + enabled: button.enabled + anchors.fill: parent + onClicked: { + if (blink) + blinkAnimation.running = true + else + button.clicked() + } + } +} diff --git a/chicken-wranglers/src/qml/widgets/ConfirmationDialog.qml b/chicken-wranglers/src/qml/widgets/ConfirmationDialog.qml new file mode 100644 index 0000000..90e922d --- /dev/null +++ b/chicken-wranglers/src/qml/widgets/ConfirmationDialog.qml @@ -0,0 +1,106 @@ +/**************************************************************************** +** +** This file is a part of QtChickenWranglers. +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).* +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +** FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +** COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +** BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +** ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +** POSSIBILITY OF SUCH DAMAGE." +** +****************************************************************************/ + + +import Qt 4.7 + +BaseDialog { + id: dialog + + property string text: "Confirmation Dialog" + property string rejectText: "No" + property string acceptText: "Yes" + property int buttonWidth: 160 + + signal rejected() + signal accepted() + + Text { + color: "#4d908f" + text: dialog.text + style: Text.Raised + styleColor: "white" + + anchors.fill: box + anchors.margins: 60 + + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + wrapMode: Text.WordWrap + + font { + family: "Nokia Sans" + pixelSize: 34 + } + } + + Button { + id: rejectButton + + width: buttonWidth + text: dialog.rejectText + source: "qrc:/images/general/bt.png" + anchors { + verticalCenter: box.bottom + verticalCenterOffset: -25 + right: box.horizontalCenter + rightMargin: 20 + } + + onClicked: rejected() + } + + Button { + id: acceptButton + + width: buttonWidth + text: dialog.acceptText + source: "qrc:/images/general/bt.png" + anchors { + verticalCenter: box.bottom + verticalCenterOffset: -25 + left: box.horizontalCenter + leftMargin: 20 + } + + onClicked: accepted() + } +} diff --git a/chicken-wranglers/src/qml/widgets/ConnectivityDialog.qml b/chicken-wranglers/src/qml/widgets/ConnectivityDialog.qml new file mode 100644 index 0000000..c7a4f99 --- /dev/null +++ b/chicken-wranglers/src/qml/widgets/ConnectivityDialog.qml @@ -0,0 +1,185 @@ +/**************************************************************************** +** +** This file is a part of QtChickenWranglers. +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).* +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +** FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +** COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +** BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +** ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +** POSSIBILITY OF SUCH DAMAGE." +** +****************************************************************************/ + + +import Qt 4.7 +import game.types 1.0 + +BaseDialog { + id: dialog + + property string buttonText: "Use it" + property string cancelText: "Cancel" + property ConnectivityListModel model: ConnectivityListModel {} + signal cancel() + + Connections { + target: dialog + onHideFinished: { + title.text = "Scanning..." + button.enabled = true + quitButton.enabled = true + } + } + + ConfirmationDialog { + id: quitDialog + + text: "Do you want to cancel scanning?" + opacity: 0 + + onRejected: { + quitDialog.hide() + } + + onAccepted: { + quitDialog.hide() + dialog.cancel() + } + + z: 10 + } + + Text { + id: title + + text: "Scanning..." + style: Text.Raised + styleColor: "white" + color: "#4d908f" + + font { + family: "Nokia Sans" + bold: true + pixelSize: 34 + } + + anchors.top: box.top + anchors.topMargin: 60 + anchors.left: parent.left + anchors.right: parent.right + + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + } + + ConnectivityListView { + id: listView + + property real scrollSize: 200 + + width: 400 + height: 200 + model: dialog.model + anchors.top: title.bottom + anchors.topMargin: 15 + anchors.bottom: box.bottom + anchors.bottomMargin: 80 + anchors.horizontalCenter: parent.horizontalCenter + + onContentYChanged: { + scrollbar.setValue((contentY / scrollSize) * 100) + } + + onMovingChanged: { + if (moving) + scrollbar.opacity = 1; + else + scrollbar.opacity = 0; + } + } + + Scrollbar { + id: scrollbar + + opacity: 0 + anchors.top: title.bottom + anchors.bottom: box.bottom + anchors.left: listView.right + anchors.leftMargin: 20 + + Behavior on opacity { + NumberAnimation { + duration: 500 + easing.type: Easing.OutCirc + } + } + } + + Button { + id: button + + text: dialog.buttonText + anchors { + verticalCenter: box.bottom + verticalCenterOffset: -25 + horizontalCenter: box.horizontalCenter + horizontalCenterOffset: 90 + } + + onClicked: { + button.enabled = false + quitButton.enabled = false + title.text = "Connecting..." + + if (listView.currentIndex != -1) + listView.model.selectedIndex = listView.currentIndex + } + } + + Button { + id: quitButton + text: dialog.cancelText + anchors { + verticalCenter: box.bottom + verticalCenterOffset: -25 + horizontalCenter: box.horizontalCenter + horizontalCenterOffset: -90 + } + + onClicked: { + if (quitDialog.opacity == 0) { + quitDialog.show() + } + } + } +} + diff --git a/chicken-wranglers/src/qml/widgets/ConnectivityListModel.qml b/chicken-wranglers/src/qml/widgets/ConnectivityListModel.qml new file mode 100644 index 0000000..df1449f --- /dev/null +++ b/chicken-wranglers/src/qml/widgets/ConnectivityListModel.qml @@ -0,0 +1,82 @@ +/**************************************************************************** +** +** This file is a part of QtChickenWranglers. +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).* +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +** FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +** COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +** BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +** ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +** POSSIBILITY OF SUCH DAMAGE." +** +****************************************************************************/ + + +import Qt 4.7 + +ListModel { + ListElement { + // N8 cellphone + name: "cw"; address: "18:14:56:44:F4:DB" + category: 2; pairing: 1 + } + + ListElement { + name: "5800gard"; address: "00:25:CF:11:2B:8A" + category: 2; pairing: 1 + } + + ListElement { + name: "FabyAAAAAAAAAAAAAAAAAAAAAAAAAA"; address: "00:24:03:DA:45:00" + category: 1; pairing: 0 + } + + ListElement { + name: "device-0BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"; address: "00:24:03:DA:45:00" + category: 1; pairing: 0 + } + + ListElement { + name: "pc-1"; address: "00:24:03:DA:45:00" + category: 1; pairing: 0 + } + + ListElement { + name: "device-1"; address: "00:24:03:DA:45:00" + category: 1; pairing: 0 + } + + ListElement { + name: "mobile-0"; address: "00:24:03:DA:45:00" + category: 1; pairing: 0 + } +} + diff --git a/chicken-wranglers/src/qml/widgets/ConnectivityListView.qml b/chicken-wranglers/src/qml/widgets/ConnectivityListView.qml new file mode 100644 index 0000000..ca04c5b --- /dev/null +++ b/chicken-wranglers/src/qml/widgets/ConnectivityListView.qml @@ -0,0 +1,138 @@ +/**************************************************************************** +** +** This file is a part of QtChickenWranglers. +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).* +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +** FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +** COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +** BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +** ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +** POSSIBILITY OF SUCH DAMAGE." +** +****************************************************************************/ + + +import Qt 4.7 +import game.types 1.0 + +ListView { + id: listView + + Component { + id: delegate + + Item { + width: lineDivisor.width + height: 43 + + Image { + id: lineDivisor + + source: "qrc:/images/general/list_line_divisor.png" + + anchors.top: parent.top + } + + Text { + text: name + + width: parent.width - 110 + + style: Text.Raised + styleColor: "white" + + color: "#4d908f" + + font { + family: "Nokia Sans" + bold: true + pixelSize: 21 + } + + elide: Text.ElideRight + + anchors.verticalCenter: parent.verticalCenter + anchors.left: parent.left + anchors.leftMargin: 23 + + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + } + + MouseArea { + anchors.fill: parent + + onClicked: { + var pos = mapToItem(listView.contentItem, mouseX, mouseY) + var selectedIndex = listView.indexAt(pos.x, pos.y) + + if (selectedIndex == listView.currentIndex) { + listView.currentIndex = -1 + } else { + listView.currentIndex = selectedIndex + } + } + } + } + } + + model: ConnectivityListModel {} + delegate: delegate + + focus: false + clip: true + + Component { + id: highlightIcon + + Item { + width: listView.width + height: 43 + + Image { + source: "qrc:/images/general/list_selected_icon.png" + + anchors.left: parent.right + anchors.leftMargin: -70 + anchors.verticalCenter: parent.verticalCenter + anchors.verticalCenterOffset: 1 + } + } + } + + currentIndex: model.selectedIndex + + highlight: highlightIcon + highlightMoveDuration: 100 + + snapMode: ListView.SnapToItem +} + diff --git a/chicken-wranglers/src/qml/widgets/Countdown.qml b/chicken-wranglers/src/qml/widgets/Countdown.qml new file mode 100644 index 0000000..31b5ad9 --- /dev/null +++ b/chicken-wranglers/src/qml/widgets/Countdown.qml @@ -0,0 +1,107 @@ +/**************************************************************************** +** +** This file is a part of QtChickenWranglers. +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).* +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +** FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +** COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +** BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +** ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +** POSSIBILITY OF SUCH DAMAGE." +** +****************************************************************************/ + + +import Qt 4.7 + +Item { + id: countdown + + property int startValue: 3 + property int currentValue: startValue + property int interval: 800 + property string timeoutText: "Go!" + + signal timeout + + function start() { + countdown.opacity = 1 + animation.start() + } + + function decrement() { + if (currentValue - 1 > 0) { + currentValue-- + return + } + + if (currentValue == 1) { + number.text = countdown.timeoutText + currentValue-- + return + } + + countdown.opacity = 0 + countdown.timeout() + } + + Text { + id: number + + text: currentValue + smooth: true + anchors.centerIn: parent + color: "white" + + font { + family: "Nokia Sans" + pointSize: 100 + bold: true + } + + style: Text.Outline + styleColor: "darkgreen" + } + + SequentialAnimation { + id: animation + + loops: startValue + 1 + + ParallelAnimation { + PropertyAnimation { duration: countdown.interval; target: number; property: "scale"; from: 1; to: 2 } + PropertyAnimation { duration: countdown.interval; target: number; property: "opacity"; from: 1; to: 0 } + } + + PropertyAction { target: number; properties: "scale,opacity"; value: 1 } + ScriptAction { script: countdown.decrement() } + } +} diff --git a/chicken-wranglers/src/qml/widgets/Feather.qml b/chicken-wranglers/src/qml/widgets/Feather.qml new file mode 100644 index 0000000..b46585c --- /dev/null +++ b/chicken-wranglers/src/qml/widgets/Feather.qml @@ -0,0 +1,126 @@ +/**************************************************************************** +** +** This file is a part of QtChickenWranglers. +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).* +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +** FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +** COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +** BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +** ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +** POSSIBILITY OF SUCH DAMAGE." +** +****************************************************************************/ + + +import Qt 4.7 + +import game.types 1.0 +import "featherfall.js" as Feather + +Image { + id: feather + + property int xMax: 0 + property int xMin: 0 + property int yMax: 768 + + // the delay offset for the initial creation of each feather. + property real delay: 0 + + source: { + if (game.environment() == Global.Symbian) + "qrc:/images/general/symbian/feather1.png" + else + "qrc:/images/general/feather1.png" + } + smooth: true + y: -feather.height + + function startAnimation() { + animY.running = true + animX.running = true + animRotation.running = true + } + + function stopAnimation() { + animY.running = false + animX.running = false + animRotation.running = false + } + + SequentialAnimation on y { + id: animY + + running: false + + PauseAnimation { duration: delay } + NumberAnimation { to: 100; easing.type: Easing.InOutSine; duration: 1050 } + NumberAnimation { to: 300; easing.type: Easing.InOutSine; duration: 950 } + NumberAnimation { to: 500; easing.type: Easing.InOutSine; duration: 1050 } + NumberAnimation { to: 700; easing.type: Easing.InOutSine; duration: 950 } + NumberAnimation { to: 900; easing.type: Easing.InOutSine; duration: 1050 } + NumberAnimation { to: yMax + 2 * feather.height; easing.type: Easing.InOutSine; duration: 950 } + + onRunningChanged: { + if (!running) + feather.destroy() + } + } + + SequentialAnimation on x { + id: animX + + running: false + + PauseAnimation { duration: delay } + NumberAnimation { to: xMax; easing.type: Easing.InOutSine; duration: 950 } + NumberAnimation { to: xMin; easing.type: Easing.InOutSine; duration: 1050 } + NumberAnimation { to: xMax; easing.type: Easing.InOutSine; duration: 950 } + NumberAnimation { to: xMin; easing.type: Easing.InOutSine; duration: 1050 } + NumberAnimation { to: xMax; easing.type: Easing.InOutSine; duration: 950 } + NumberAnimation { to: xMin; easing.type: Easing.InOutSine; duration: 1050 } + } + + SequentialAnimation on rotation { + id: animRotation + + running: false + + PauseAnimation { duration: delay } + NumberAnimation { to: -40; easing.type: Easing.InOutSine; duration: 1000 } + NumberAnimation { to: 25; easing.type: Easing.InOutSine; duration: 1000 } + NumberAnimation { to: -40; easing.type: Easing.InOutSine; duration: 1000 } + NumberAnimation { to: 25; easing.type: Easing.InOutSine; duration: 1000 } + NumberAnimation { to: -40; easing.type: Easing.InOutSine; duration: 1000 } + NumberAnimation { to: 25; easing.type: Easing.InOutSine; duration: 1000 } + NumberAnimation { to: -40; easing.type: Easing.InOutSine; duration: 1000 } + } +} diff --git a/chicken-wranglers/src/qml/widgets/FeatherFall.qml b/chicken-wranglers/src/qml/widgets/FeatherFall.qml new file mode 100644 index 0000000..d8b49d7 --- /dev/null +++ b/chicken-wranglers/src/qml/widgets/FeatherFall.qml @@ -0,0 +1,74 @@ +/**************************************************************************** +** +** This file is a part of QtChickenWranglers. +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).* +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +** FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +** COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +** BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +** ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +** POSSIBILITY OF SUCH DAMAGE." +** +****************************************************************************/ + + +import Qt 4.7 + +import game.types 1.0 +import "featherfall.js" as FeatherFall + +Item { + id: featherFall + + property real fallWidth: 800 + property real fallHeight: 768 + property int number: 5 + + function start() { + timer.start() + } + + function stop() { + timer.stop() + FeatherFall.destroy() + } + + Timer { + id: timer + + triggeredOnStart: true + repeat: true + interval: 6000 + onTriggered: { + FeatherFall.create(featherFall.width, featherFall.height) + } + } +} diff --git a/chicken-wranglers/src/qml/widgets/ImageButton.qml b/chicken-wranglers/src/qml/widgets/ImageButton.qml new file mode 100644 index 0000000..2ccdbf1 --- /dev/null +++ b/chicken-wranglers/src/qml/widgets/ImageButton.qml @@ -0,0 +1,93 @@ +/**************************************************************************** +** +** This file is a part of QtChickenWranglers. +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).* +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +** FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +** COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +** BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +** ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +** POSSIBILITY OF SUCH DAMAGE." +** +****************************************************************************/ + + +import Qt 4.7 + +Image { + id: button + + property bool blink: false + property string name: "" + property string path: "qrc:/images/general" + property alias buttonPressed: mouseArea.pressed + + signal clicked + + smooth: true + source: { + if (path == "") + return "" + + if (mouseArea.pressed) + path + "/bt_" + name + "_pressed.png" + else + path + "/bt_" + name + ".png" + } + + PropertyAnimation { + id: blinkAnimation + + target: button + properties: "opacity" + loops: 2 + from: 0 + to: 1 + duration: 200 + + onRunningChanged: { + if (!running) + button.clicked() + } + } + + MouseArea { + id: mouseArea + + anchors.fill: parent + onClicked: { + if (blink) + blinkAnimation.running = true + else + button.clicked() + } + } +} diff --git a/chicken-wranglers/src/qml/widgets/Loading.qml b/chicken-wranglers/src/qml/widgets/Loading.qml new file mode 100644 index 0000000..19eeff5 --- /dev/null +++ b/chicken-wranglers/src/qml/widgets/Loading.qml @@ -0,0 +1,138 @@ +/**************************************************************************** +** +** This file is a part of QtChickenWranglers. +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).* +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +** FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +** COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +** BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +** ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +** POSSIBILITY OF SUCH DAMAGE." +** +****************************************************************************/ + + +import Qt 4.7 + +Item { + id: loading + + property int count: 0 + + width: row.width + height: row.height + + Component { + id: dot + + Rectangle { + id: outer + + width: 15 + height: 15 + color: "#e0fce5" + radius: 50 + smooth: true + + Rectangle { + id: inner + + anchors.centerIn: parent + + smooth: true + color: "#9bbaae" + radius: 50 + + anchors.fill: parent + anchors.margins: 3 + } + + states { + State { + name: "off" + PropertyChanges { target: outer; scale: 1 } + PropertyChanges { target: inner; color: "#9bbaae" } + } + State { + name: "on" + PropertyChanges { target: outer; scale: 1.33 } + PropertyChanges { target: inner; color: "#f6c200" } + } + } + + transitions: Transition { + ParallelAnimation { + NumberAnimation { target: outer; property: "scale"; easing.type: Easing.InOutQuad } + ColorAnimation { target: inner; property: "color"; easing.type: Easing.InOutQuad } + } + } + } + } + + Row { + id: row + + spacing: 4 + + children: [ + Loader { sourceComponent: dot }, + Loader { sourceComponent: dot }, + Loader { sourceComponent: dot } + ] + } + + Timer { + id: timer + + repeat: true + interval: 200 + running: true + + onTriggered: { + if (count > 0) + row.children[count - 1].item.state = "off" + + if (count < row.children.length) + row.children[count].item.state = "on" + + count = (count + 1) % (row.children.length + 1) + } + } + + onOpacityChanged: { + if (opacity == 1 && !timer.running) { + timer.start() + } + else if (opacity == 0 && timer.running) { + timer.stop() + } + } +} diff --git a/chicken-wranglers/src/qml/widgets/MessageDialog.qml b/chicken-wranglers/src/qml/widgets/MessageDialog.qml new file mode 100644 index 0000000..44cc8d1 --- /dev/null +++ b/chicken-wranglers/src/qml/widgets/MessageDialog.qml @@ -0,0 +1,85 @@ +/**************************************************************************** +** +** This file is a part of QtChickenWranglers. +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).* +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +** FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +** COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +** BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +** ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +** POSSIBILITY OF SUCH DAMAGE." +** +****************************************************************************/ + + +import Qt 4.7 + +BaseDialog { + id: dialog + + property string text: "Message Dialog" + property string buttonText: "Ok" + + signal buttonClicked + + Text { + color: "#4d908f" + text: dialog.text + style: Text.Raised + styleColor: "white" + + anchors.fill: box + anchors.margins: 60 + + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + wrapMode: Text.WordWrap + + font { + family: "Nokia Sans" + pixelSize: 34 + } + } + + Button { + id: button + + text: dialog.buttonText + anchors { + verticalCenter: box.bottom + verticalCenterOffset: -25 + horizontalCenter: box.horizontalCenter + } + + onClicked: buttonClicked() + } +} + diff --git a/chicken-wranglers/src/qml/widgets/OptionSlider.qml b/chicken-wranglers/src/qml/widgets/OptionSlider.qml new file mode 100644 index 0000000..205f299 --- /dev/null +++ b/chicken-wranglers/src/qml/widgets/OptionSlider.qml @@ -0,0 +1,131 @@ +/**************************************************************************** +** +** This file is a part of QtChickenWranglers. +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).* +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +** FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +** COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +** BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +** ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +** POSSIBILITY OF SUCH DAMAGE." +** +****************************************************************************/ + + +import Qt 4.7 + +Item { + id: slider + + property string option: "Wifi" + + signal selected(string option) + + width: sliderSelector.width + height: sliderPath.height + + Image { + id: sliderPath + + anchors.centerIn: parent + + source: "qrc:/images/general/slider_path.png" + } + + Image { + anchors { + horizontalCenter: slider.horizontalCenter + bottom: slider.verticalCenter + bottomMargin: 21 + } + + source: "qrc:/images/general/slider_wifi_icon.png" + } + + Image { + anchors { + horizontalCenter: slider.horizontalCenter + horizontalCenterOffset: 3 + top: slider.verticalCenter + topMargin: 16 + } + + source: "qrc:/images/general/slider_bluetooth_icon.png" + } + + Image { + id: sliderSelector + + source: "qrc:/images/general/slider_selector.png" + + x: 0 + y: 10 + + Behavior on y { + NumberAnimation { + id: slideAnimation + + duration: 500 + easing.type: Easing.OutCirc + } + } + } + + MouseArea { + anchors.fill: parent + + enabled: !slideAnimation.running + + onReleased: { + // Wifi selected + if (mouse.y <= ((slider.height / 2) - 1)) { + if (slider.option != "Wifi") { + slider.option = "Wifi" + + selected(slider.option) + + sliderSelector.y = 10 + } + + // Bluetooth selected + } else { + if (slider.option != "Bluetooth") { + slider.option = "Bluetooth" + + selected(slider.option) + + sliderSelector.y = (slider.height / 2) - 10 + } + } + } + } +} + diff --git a/chicken-wranglers/src/qml/widgets/Screen.qml b/chicken-wranglers/src/qml/widgets/Screen.qml new file mode 100644 index 0000000..967f443 --- /dev/null +++ b/chicken-wranglers/src/qml/widgets/Screen.qml @@ -0,0 +1,86 @@ +/**************************************************************************** +** +** This file is a part of QtChickenWranglers. +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).* +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +** FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +** COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +** BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +** ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +** POSSIBILITY OF SUCH DAMAGE." +** +****************************************************************************/ + + +import Qt 4.7 + +Rectangle { + id: screen + + signal transitionFinished(bool visible) + + anchors.fill: parent + opacity: 0 + + function show() { + screen.state = "visible" + } + + function hide() { + screen.state = "hidden" + } + + states { + State { + name: "visible" + PropertyChanges { target: screen; opacity: 1 } + } + State { + name: "hidden" + PropertyChanges { target: screen; opacity: 0 } + } + } + + Behavior on opacity { + NumberAnimation { + duration: 200 + + onRunningChanged: { + if (!running) { + if (opacity == 1) + transitionFinished(true) + else + transitionFinished(false) + } + } + } + } +} diff --git a/chicken-wranglers/src/qml/widgets/Scrollbar.qml b/chicken-wranglers/src/qml/widgets/Scrollbar.qml new file mode 100644 index 0000000..0d59208 --- /dev/null +++ b/chicken-wranglers/src/qml/widgets/Scrollbar.qml @@ -0,0 +1,87 @@ +/**************************************************************************** +** +** This file is a part of QtChickenWranglers. +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).* +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +** FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +** COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +** BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +** ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +** POSSIBILITY OF SUCH DAMAGE." +** +****************************************************************************/ + + +import Qt 4.7 + +Item { + id: scrollbar + + property real value: 0.0 + property real minimumValue: 0.0 + property real maximumValue: 100.0 + property real offset: 8.0 + property real minimumPos: offset + property real maximumPos: scrollbarPath.height - scrollbarKnob.height - offset + property real scrollSize: maximumPos - minimumPos + 1 + + width: scrollbarKnob.width + height: scrollbarPath.height + + function setValue(newValue) { + if (newValue <= minimumValue) { + value = minimumValue; + } else if (newValue >= maximumValue) { + value = maximumValue; + } else { + value = newValue; + } + } + + Image { + id: scrollbarPath + + anchors.centerIn: parent + + source: "qrc:/images/general/list_scrollbar_path.png" + } + + Image { + id: scrollbarKnob + + anchors.horizontalCenter: parent.horizontalCenter + + y: ((scrollbar.value / scrollbar.maximumValue) * scrollbar.scrollSize) + scrollbar.offset + + source: "qrc:/images/general/list_scrollbar_knob.png" + } +} + diff --git a/chicken-wranglers/src/qml/widgets/ToggleButton.qml b/chicken-wranglers/src/qml/widgets/ToggleButton.qml new file mode 100644 index 0000000..939602f --- /dev/null +++ b/chicken-wranglers/src/qml/widgets/ToggleButton.qml @@ -0,0 +1,67 @@ +/**************************************************************************** +** +** This file is a part of QtChickenWranglers. +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).* +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +** FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +** COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +** BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +** ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +** POSSIBILITY OF SUCH DAMAGE." +** +****************************************************************************/ + + +import Qt 4.7 + +Image { + id: button + signal clicked + property string mode: "bluetooth" + source: "qrc:/images/general/toggle_bt.png" + + MouseArea { + id: mouseArea + + anchors.fill: parent + onClicked: { + if (button.mode == "bluetooth") { + button.mode = "lan" + button.source = "qrc:/images/general/toggle_lan.png" + } else { + button.mode = "bluetooth" + button.source = "qrc:/images/general/toggle_bt.png" + } + + game.setConnectivity(button.mode) + } + } +} diff --git a/chicken-wranglers/src/qml/widgets/featherfall.js b/chicken-wranglers/src/qml/widgets/featherfall.js new file mode 100644 index 0000000..6ae51a4 --- /dev/null +++ b/chicken-wranglers/src/qml/widgets/featherfall.js @@ -0,0 +1,66 @@ +var component; +var featherObjList = new Array; + +function create(fallWidth, fallHeight) { + var i, range, lowRange, highRange; + + if (component == null) + component = Qt.createComponent("Feather.qml"); + + range = fallWidth / featherFall.number; + lowRange = -range; + highRange = 0; + + var resourcePath = ""; + if (game.environment() == Global.Symbian) + resourcePath = "qrc:/images/general/symbian/feather" + else + resourcePath = "qrc:/images/general/feather" + + for (i = 0; i < featherFall.number; i++) { + if (component.status == Component.Ready) { + + featherObjList[i] = component.createObject(background); + + if (featherObjList[i] == null) { + console.log("error creating featherObj"); + console.log(component.errorString()); + return false; + } + + lowRange = lowRange + range; + highRange = highRange + range; + + var xpos = (highRange - range) * Math.random() + lowRange; + featherObjList[i].x = xpos; + + featherObjList[i].delay = Math.random() * 3000 * i; + + var swing = Math.random() * range; + if (swing < 100) + swing += 100; + + featherObjList[i].xMax = xpos + swing; + featherObjList[i].xMin = xpos - swing; + featherObjList[i].yMax = fallHeight; + featherObjList[i].source = resourcePath + (Math.floor(5 * Math.random()) + 1) + ".png"; + + featherObjList[i].startAnimation(); + } else { + console.log("error loading featherObj component"); + console.log(component.errorString()); + return false; + } + } + + return true; +} + +function destroy() { + for (var i = 0; i < featherFall.number; i++) { + if (featherObjList[i] == null) + continue; + + featherObjList[i].destroy() + } +} diff --git a/chicken-wranglers/src/sound/sound.cpp b/chicken-wranglers/src/sound/sound.cpp new file mode 100644 index 0000000..0661a63 --- /dev/null +++ b/chicken-wranglers/src/sound/sound.cpp @@ -0,0 +1,62 @@ +/**************************************************************************** +** +** This file is a part of QtChickenWranglers. +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).* +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +** FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +** COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +** BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +** ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +** POSSIBILITY OF SUCH DAMAGE." +** +****************************************************************************/ + +#include "sound.h" + +#include <QtCore/QDebug> +#include <QtCore/QFile> + +Sound::Sound(const QByteArray &sound, bool isLoop, QObject *parent) + : QThread(parent), m_sound(sound), m_isLoop(isLoop) +{ +} + +Sound::~Sound() +{ +} + +void Sound::run() +{ +} + +void Sound::play() +{ +} diff --git a/chicken-wranglers/src/sound/sound.h b/chicken-wranglers/src/sound/sound.h new file mode 100644 index 0000000..86e5017 --- /dev/null +++ b/chicken-wranglers/src/sound/sound.h @@ -0,0 +1,67 @@ +/**************************************************************************** +** +** This file is a part of QtChickenWranglers. +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).* +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +** FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +** COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +** BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +** ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +** POSSIBILITY OF SUCH DAMAGE." +** +****************************************************************************/ + + +#ifndef SOUND_H +#define SOUND_H + +#include <QtCore/QByteArray> +#include <QtCore/QThread> + +class Sound : public QThread +{ + Q_OBJECT + +public: + Sound(const QByteArray &sound, bool isLoop = false, QObject *parent = 0); + ~Sound(); + + void run(); + +public slots: + void play(); + +private: + QByteArray m_sound; + bool m_isLoop; +}; + +#endif diff --git a/chicken-wranglers/src/sound/sound.pri b/chicken-wranglers/src/sound/sound.pri new file mode 100644 index 0000000..c7853fe --- /dev/null +++ b/chicken-wranglers/src/sound/sound.pri @@ -0,0 +1,9 @@ +PATH = $$PWD + +HEADERS += \ + $$PATH/soundmanager.h \ + $$PATH/sound.h + +SOURCES += \ + $$PATH/soundmanager.cpp \ + $$PATH/sound.cpp diff --git a/chicken-wranglers/src/sound/sound_linux.cpp b/chicken-wranglers/src/sound/sound_linux.cpp new file mode 100644 index 0000000..d555eb3 --- /dev/null +++ b/chicken-wranglers/src/sound/sound_linux.cpp @@ -0,0 +1,105 @@ +/**************************************************************************** +** +** This file is a part of QtChickenWranglers. +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).* +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +** FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +** COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +** BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +** ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +** POSSIBILITY OF SUCH DAMAGE." +** +****************************************************************************/ + + +#include "sound_linux.h" + +#include <pulse/error.h> +#include <pulse/gccmacro.h> +#include <pulse/simple.h> + +#include <QtCore/QDebug> +#include <QtCore/QFile> + +Sound::Sound(const QByteArray &sound, bool isLoop, QObject *parent) + : QThread(parent), m_sound(sound), m_isLoop(isLoop) +{ + int error; + + static const pa_sample_spec sampleSpec = { + PA_SAMPLE_S16LE, // format + 44100, // rate + 2 // channels + }; + + // create a new playback stream + if (!(m_playbackStream = pa_simple_new(NULL, "name", PA_STREAM_PLAYBACK, NULL, + "playback", &sampleSpec, NULL, NULL, &error))) { + // error + qWarning() << "Failure to create a new simple playback stream:" << error; + } +} + +Sound::~Sound() +{ + if (m_playbackStream) + pa_simple_free(m_playbackStream); +} + +void Sound::run() +{ + if (!m_playbackStream) { + qWarning() << "Failure to play: playback stream was not created."; + return; + } + + if (!m_sound.size()) { + qWarning() << "Failure to play: Invalid sound stream."; + return; + } + + int error; + int rtv; + + do { + rtv = pa_simple_write(m_playbackStream, m_sound.data(), (size_t) m_sound.size(), &error); + } while (m_isLoop && rtv >= 0); + + if (rtv < 0) + qWarning() << "Failure to play sound."; + + deleteLater(); +} + +void Sound::play() +{ + start(); +} diff --git a/chicken-wranglers/src/sound/sound_linux.h b/chicken-wranglers/src/sound/sound_linux.h new file mode 100644 index 0000000..ae2431a --- /dev/null +++ b/chicken-wranglers/src/sound/sound_linux.h @@ -0,0 +1,70 @@ +/**************************************************************************** +** +** This file is a part of QtChickenWranglers. +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).* +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +** FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +** COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +** BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +** ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +** POSSIBILITY OF SUCH DAMAGE." +** +****************************************************************************/ + + +#ifndef SOUND_H +#define SOUND_H + +#include <QtCore/QByteArray> +#include <QtCore/QThread> + +struct pa_simple; + +class Sound : public QThread +{ + Q_OBJECT + +public: + Sound(const QByteArray &sound, bool isLoop = false, QObject *parent = 0); + ~Sound(); + + void run(); + +public slots: + void play(); + +private: + pa_simple *m_playbackStream; + QByteArray m_sound; + bool m_isLoop; +}; + +#endif diff --git a/chicken-wranglers/src/sound/sound_linux.pri b/chicken-wranglers/src/sound/sound_linux.pri new file mode 100644 index 0000000..cfbfb58 --- /dev/null +++ b/chicken-wranglers/src/sound/sound_linux.pri @@ -0,0 +1,9 @@ +PATH = $$PWD + +HEADERS += \ + $$PATH/soundmanager.h \ + $$PATH/sound_linux.h + +SOURCES += \ + $$PATH/soundmanager.cpp \ + $$PATH/sound_linux.cpp diff --git a/chicken-wranglers/src/sound/soundmanager.cpp b/chicken-wranglers/src/sound/soundmanager.cpp new file mode 100644 index 0000000..9e190ba --- /dev/null +++ b/chicken-wranglers/src/sound/soundmanager.cpp @@ -0,0 +1,128 @@ +/**************************************************************************** +** +** This file is a part of QtChickenWranglers. +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).* +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +** FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +** COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +** BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +** ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +** POSSIBILITY OF SUCH DAMAGE." +** +****************************************************************************/ + +#include "soundmanager.h" + +#include "global.h" + +#if defined(Q_WS_X11) +#include "sound_linux.h" +#else +#include "sound.h" +#endif + +#include <QtCore/QDebug> + +SoundManager::SoundManager(QObject *parent) + : QObject(parent), m_isLoaded(false) +{ +} + +SoundManager *SoundManager::instance() +{ + static SoundManager *const soundManager = new SoundManager(); + + return soundManager; +} + +void SoundManager::load() +{ + if (m_isLoaded) + return; + + QString soundPath(Global::rootDirectory().absoluteFilePath() + "/sounds/"); + + QFile soundFile; + + soundFile.setFileName(soundPath + "match.raw"); + if (soundFile.open(QIODevice::ReadOnly)) { + m_backgroundSound = soundFile.readAll(); + soundFile.close(); + } else { + qWarning() << "Error loading sound file:" << soundFile.fileName(); + } + + soundFile.setFileName(soundPath + "laser.raw"); + if (soundFile.open(QIODevice::ReadOnly)) { + m_laserSound = soundFile.readAll(); + soundFile.close(); + } else { + qWarning() << "Error loading sound file:" << soundFile.fileName(); + } + + soundFile.setFileName(soundPath + "score.raw"); + if (soundFile.open(QIODevice::ReadOnly)) { + m_scoreSound = soundFile.readAll(); + soundFile.close(); + } else { + qWarning() << "Error loading sound file:" << soundFile.fileName(); + } + + m_isLoaded = true; +} + +void SoundManager::play(SoundType type) +{ + // NOTE: Currently sounds are supported only on Linux builds. + +#if defined(Q_WS_X11) + instance()->load(); + + Sound *sound = 0; + + switch (type) { + case Background: + sound = new Sound(instance()->m_backgroundSound, true); + break; + case Score: + sound = new Sound(instance()->m_scoreSound); + break; + case Laser: + sound = new Sound(instance()->m_laserSound); + break; + default: + qWarning("No valid sound type"); + return; + } + + sound->play(); +#endif +} diff --git a/chicken-wranglers/src/sound/soundmanager.h b/chicken-wranglers/src/sound/soundmanager.h new file mode 100644 index 0000000..52915a4 --- /dev/null +++ b/chicken-wranglers/src/sound/soundmanager.h @@ -0,0 +1,76 @@ +/**************************************************************************** +** +** This file is a part of QtChickenWranglers. +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).* +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +** FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +** COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +** BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +** ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +** POSSIBILITY OF SUCH DAMAGE." +** +****************************************************************************/ + + +#ifndef SOUNDMANAGER_H +#define SOUNDMANAGER_H + +#include <QtCore/QObject> +#include <QtCore/QString> + +class SoundManager : public QObject +{ + Q_ENUMS(SoundType) + +public: + enum SoundType { + Background, + Score, + Laser + }; + + static void play(SoundType type); + +protected: + static SoundManager *instance(); + +private: + explicit SoundManager(QObject *parent = 0); + + void load(); + + bool m_isLoaded; + QByteArray m_backgroundSound; + QByteArray m_scoreSound; + QByteArray m_laserSound; +}; + +#endif diff --git a/chicken-wranglers/src/utils/global.cpp b/chicken-wranglers/src/utils/global.cpp new file mode 100644 index 0000000..21c647f --- /dev/null +++ b/chicken-wranglers/src/utils/global.cpp @@ -0,0 +1,135 @@ +/**************************************************************************** +** +** This file is a part of QtChickenWranglers. +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).* +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +** FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +** COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +** BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +** ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +** POSSIBILITY OF SUCH DAMAGE." +** +****************************************************************************/ + +#include "global.h" + +// TODO: conditional compilation module instead of ifdef's +#ifdef Q_OS_SYMBIAN +#include <eikenv.h> +#include <coemain.h> +#include <aknappui.h> +#endif + +#include <QBluetoothLocalDevice> +#include <qmobilityglobal.h> +#include <QtCore/QStringList> +#include <QtGlobal> + +QTM_USE_NAMESPACE + +QFileInfo Global::rootDirectory() +{ +#ifdef Q_OS_SYMBIAN + return QFileInfo("c:\\data\\chicken-wranglers\\"); +#endif + QStringList pathList(QString(XSTR(DATA_PATH)).split(":", QString::SkipEmptyParts)); + + foreach (QFileInfo path, pathList) + if (path.exists() && path.isDir()) + return path; + + return QFileInfo(); +} + +QString Global::directionString(Global::Direction direction) +{ + switch (direction) { + case Global::DirectionUp: + return QString("Up"); + case Global::DirectionDown: + return QString("Down"); + case Global::DirectionRight: + return QString("Right"); + case Global::DirectionLeft: + return QString("Left"); + default: + return QString("Stop"); + } +} + +void Global::setScreenOrientation(const ScreenOrientation &orientation) +{ +#ifdef Q_OS_SYMBIAN + CAknAppUi *aknAppUi = dynamic_cast<CAknAppUi *>(CEikonEnv::Static()->AppUi()); + if (!aknAppUi) + return; + + switch (orientation) { + case Landscape: + aknAppUi->SetOrientationL(CAknAppUi::EAppUiOrientationLandscape); + break; + case Portrait: + aknAppUi->SetOrientationL(CAknAppUi::EAppUiOrientationPortrait); + break; + case Auto: + aknAppUi->SetOrientationL(CAknAppUi::EAppUiOrientationAutomatic); + } +#endif +} + +void Global::setPowerOn() +{ + QList<QBluetoothHostInfo> devices(QBluetoothLocalDevice::allDevices()); + foreach(const QBluetoothHostInfo &i, devices) { + QBluetoothLocalDevice hci(i.getAddress()); + hci.setHostMode(QBluetoothLocalDevice::HostDiscoverable); + hci.powerOn(); + } +} + +Global::Environment Global::environment() +{ + // Set default environment to Linux + Environment result = Linux; +#if defined(Q_WS_MAEMO_5) + result = Maemo; +#elif defined(Q_WS_X11) + result = Linux; +#elif defined(Q_WS_S60) + result = Symbian; +#elif defined(Q_WS_WIN) + result = Windows; +#elif defined(Q_WS_MAC) + result = Mac; +#endif + + return result; +} diff --git a/chicken-wranglers/src/utils/global.h b/chicken-wranglers/src/utils/global.h new file mode 100644 index 0000000..b69b3cc --- /dev/null +++ b/chicken-wranglers/src/utils/global.h @@ -0,0 +1,102 @@ +/**************************************************************************** +** +** This file is a part of QtChickenWranglers. +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).* +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +** FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +** COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +** BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +** ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +** POSSIBILITY OF SUCH DAMAGE." +** +****************************************************************************/ + + +#ifndef GLOBAL_H +#define GLOBAL_H + +#define XSTR(s) STR(s) +#define STR(s) #s + +#include <QtCore/QFileInfo> +#include <QtCore/QObject> +#include <QtGlobal> + +class Global : public QObject +{ + Q_OBJECT + + Q_ENUMS(Direction LaserDirection ScreenOrientation Environment) + +public: + enum Direction { + DirectionUp, + DirectionDown, + DirectionLeft, + DirectionRight, + DirectionStop + }; + + enum LaserDirection { + LaserUp, + LaserDown, + LaserLeft, + LaserRight + }; + + enum ScreenOrientation { + Portrait, + Landscape, + Auto + }; + + enum Environment { + Linux, + Symbian, + Maemo, + Windows, + Mac + }; + + static QFileInfo rootDirectory(); + + static QString directionString(Direction direction); + + static void setScreenOrientation(const ScreenOrientation &orientation = Portrait); + + static void setPowerOn(); + + static Environment environment(); + + static const int maximumPlayers = 4; +}; + +#endif diff --git a/chicken-wranglers/src/utils/utils.pri b/chicken-wranglers/src/utils/utils.pri new file mode 100644 index 0000000..b7444a5 --- /dev/null +++ b/chicken-wranglers/src/utils/utils.pri @@ -0,0 +1,9 @@ +DEFINES += DATA_PATH=$$SOURCE_TREE/:$$INSTALL_PREFIX/share/chicken-wranglers/ + +PATH = $$PWD + +HEADERS += \ + $$PATH/global.h + +SOURCES += \ + $$PATH/global.cpp |