From ce48af53646cd9e7ec762fc1ac176b3aa620b11d Mon Sep 17 00:00:00 2001 From: manuel Date: Thu, 5 May 2011 00:57:07 +0200 Subject: - refactorized the whole project and made a few subprojects - replaced tcp with enet - added connect dialog - some smaller bugfixes --- pacman-c++/common/actor.cpp | 375 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 375 insertions(+) create mode 100644 pacman-c++/common/actor.cpp (limited to 'pacman-c++/common/actor.cpp') diff --git a/pacman-c++/common/actor.cpp b/pacman-c++/common/actor.cpp new file mode 100644 index 0000000..de8d77e --- /dev/null +++ b/pacman-c++/common/actor.cpp @@ -0,0 +1,375 @@ +#include "actor.h" +#include "util.h" +#include +#include +#include + +static QVariant myBooleanInterpolator(const bool &start, const bool &end, qreal progress) +{ + return (progress == 1.0) ? end : start; +} + +Actor::Actor(Color::Color color, bool local, QGraphicsItem *parent) + : GameEntity(color, parent), m_direction(Actor::None), m_local(local), m_reset(true), + m_wakaPlayer(NULL), m_roundPoints(0), m_gamePoints(0) +{ + m_type = Type; + + /* DON'T set any pixmap here. we've a pixmap in the animation + * but we need a sprite for the collision detection + */ + setSprite(Constants::sprite_margin, Constants::sprite_margin, Constants::field_size.width, Constants::field_size.height); + /* higher player "over" lower player */ + setZValue(m_color * 10); + + /* rest of the ctor is only for clients */ + if (Constants::server) + return; + + /* our actor pixmap. created after server part */ + m_pix = ":/" + QString("actor%1").arg(Util::floorLog2(color) + 1); + + /* setup icon for player */ + m_icon.setPixmap(m_pix); + m_icon.setSprite(Constants::sprite_margin, Constants::sprite_margin, Constants::field_size.width, Constants::field_size.height); + + /* setup static images first + * they are visible if no animation is running + * and will be the first in m_images + */ + for (int i = 0; i < 5; i++) + { + PixmapItem *img = new PixmapItem(m_pix, this); + m_images.append(img); + int x = i * Constants::sprite_offset + Constants::sprite_margin; + int y = Actor::None * Constants::sprite_offset + Constants::sprite_margin; + img->setSprite(x, y, Constants::field_size.width, Constants::field_size.height); + img->setVisible(false); + } + + /* setup animation stuff */ + qRegisterAnimationInterpolator(myBooleanInterpolator); + m_moving = new QParallelAnimationGroup(this); + m_eating.append(NULL); // Actor::None + m_eating.append(setupEatingAnimation(Actor::Left)); + m_eating.append(setupEatingAnimation(Actor::Right)); + m_eating.append(setupEatingAnimation(Actor::Up)); + m_eating.append(setupEatingAnimation(Actor::Down)); + + /* dieing animation */ + m_dieing = new QSequentialAnimationGroup(this); + for (int i = 0; i < 11; i++) + { + PixmapItem *img = new PixmapItem(m_pix, this); + m_images.append(img); + int x = i * Constants::sprite_offset + Constants::sprite_margin; + int y = 5 * Constants::sprite_offset + Constants::sprite_margin; + img->setSprite(x, y, Constants::field_size.width, Constants::field_size.height); + img->setVisible(false); + + QPropertyAnimation *fadein = new QPropertyAnimation(img, "visible", m_dieing); + fadein->setDuration(0); + fadein->setEndValue(true); + + m_dieing->addPause(130); + + QPropertyAnimation *fadeout = new QPropertyAnimation(img, "visible", m_dieing); + fadeout->setDuration(0); + fadeout->setEndValue(false); + } + + /* setup waka sound */ + if (local) + m_wakaPlayer = new GaplessAudioPlayer(Sound::WakaWaka, 100, this); + + /* make the picture showing the current direction visible */ + m_images[m_direction]->setVisible(true); +} + +QSequentialAnimationGroup *Actor::setupEatingAnimation(Actor::Movement direction) +{ + QSequentialAnimationGroup *eating = new QSequentialAnimationGroup(this); + eating->setLoopCount(-1); + for (int i = 0; i < 4; i++) + { + PixmapItem *img = new PixmapItem(m_pix, this); + m_images.append(img); + int x = i * Constants::sprite_offset + Constants::sprite_margin; + int y = direction * Constants::sprite_offset + Constants::sprite_margin; + img->setSprite(x, y, Constants::field_size.width, Constants::field_size.height); + img->setVisible(false); + + QPropertyAnimation *fadein = new QPropertyAnimation(img, "visible", eating); + fadein->setDuration(0); + fadein->setEndValue(true); + + eating->addPause(100); + + QPropertyAnimation *fadeout = new QPropertyAnimation(img, "visible", eating); + fadeout->setDuration(0); + fadeout->setEndValue(false); + + QPropertyAnimation *move = new QPropertyAnimation(img, "pos", m_moving); + move->setDuration(Constants::tick - 30); + move->setEndValue(QPoint(0, 0)); + } + + return eating; +} + +PixmapItem &Actor::icon() +{ + return m_icon; +} + +const QString Actor::iconStr() +{ + return QString(":/actor%1icon").arg(Util::floorLog2(m_color) + 1); +} + +Actor::Movement Actor::direction() +{ + return m_direction; +} + + +void Actor::setDirection(Movement direction) +{ + m_direction = direction; +} + +bool Actor::isLocal() +{ + return m_local; +} + +bool Actor::hadReset() +{ + if (!m_reset) + return false; + m_reset = false; + return true; +} + +void Actor::reset() +{ + m_reset = true; + if (Constants::server) + { + m_direction = Actor::None; + return; + } + + stopEating(); + m_moving->stop(); + setZValue(m_color * 10); + m_dieing->stop(); + /* hide all pictures */ + for (int i = 0; i < m_images.size(); ++i) + m_images.at(i)->setVisible(false); + + if (m_eating[m_direction] != NULL) + m_eating[m_direction]->stop(); + + m_direction = Actor::None; + m_images[m_direction]->setVisible(true); +} + +void Actor::move(QPoint newpos) +{ + QPoint oldpos = pos().toPoint(); + Actor::Movement direction = Actor::None; + if (oldpos.x() - newpos.x() < 0) + direction = Actor::Right; + else if (oldpos.x() - newpos.x() > 0) + direction = Actor::Left; + else if (oldpos.y() - newpos.y() < 0) + direction = Actor::Down; + else if (oldpos.y() - newpos.y() > 0) + direction = Actor::Up; + move(direction); +} + +void Actor::move(Actor::Movement direction) +{ + if (Constants::server) + return moveByServer(direction); + + /* stop current animation if direction changed */ + if (direction != m_direction) + { + /* hide all pictures */ + for (int i = 0; i < m_images.size(); ++i) + m_images.at(i)->setVisible(false); + + if (m_eating[m_direction] != NULL) + m_eating[m_direction]->stop(); + } + + QPointF endpos = movementToPoint(direction); + switch(direction) + { + case Actor::Left: + case Actor::Right: + endpos *= Constants::field_size.width; + break; + case Actor::Up: + case Actor::Down: + endpos *= Constants::field_size.height; + break; + case Actor::None: + default: + break; + } + + for(int i = 0; i < m_moving->animationCount(); ++i) + { + QPropertyAnimation *move = dynamic_cast(m_moving->animationAt(i)); + move->setStartValue(QPoint(0, 0) - endpos); + } + setPos(pos() + endpos); + + /* start new animation if direction changed */ + if (direction != m_direction) + { + if (direction == Actor::None) + m_images[m_direction]->setVisible(true); + else + m_eating[direction]->start(); + } + + /* start moving animation */ + if (direction != Actor::None) + m_moving->start(); + + m_direction = direction; +} + +void Actor::moveByServer(Actor::Movement direction) +{ + QPointF endpos = movementToPoint(direction); + switch(direction) + { + case Actor::Left: + case Actor::Right: + endpos *= Constants::field_size.width; + break; + case Actor::Up: + case Actor::Down: + endpos *= Constants::field_size.height; + break; + case Actor::None: + default: + break; + } + setPos(pos() + endpos); + m_direction = direction; +} + +bool Actor::isMoving() +{ + return (m_moving->state() == QAbstractAnimation::Running); +} + +bool Actor::canEat(Actor *other, const QList &order) +{ + if (other == NULL || order.empty() || m_color == other->color()) + return false; + + int idx = order.indexOf(m_color); + return (order.at(idx + 1) == other->color()); +} + +void Actor::onDie(Actor *other) +{ + other->eatingPacman(); + die(); +} + +void Actor::die() +{ + if (Constants::server) + return; + + reset(); + m_images[m_direction]->setVisible(false); + setZValue(zValue() * 10); + m_dieing->start(); + if (m_local) + AudioManager::self()->play(Sound::Die); +} + +void Actor::eatingFruit() +{ + if (!m_local) + return; + AudioManager::self()->play(Sound::EatingFruit); +} + +void Actor::eatingPacman() +{ + if (!m_local) + return; + AudioManager::self()->play(Sound::EatingGhost); +} + +void Actor::startEating() +{ + if (!m_local || !m_wakaPlayer->isWorking()) + return; + m_wakaPlayer->play(); +} + +void Actor::stopEating() +{ + if (!m_local || !m_wakaPlayer->isWorking()) + return; + m_wakaPlayer->pause(); +} + +unsigned int Actor::getRoundPoints() +{ + return m_roundPoints; +} + +unsigned int Actor::getGamePoints() +{ + return m_gamePoints; +} + +void Actor::addRoundPoints(unsigned int amount) +{ + m_roundPoints += amount; +} + +void Actor::finishRound(bool died) +{ + if (!died) + m_gamePoints += m_roundPoints; + m_roundPoints = 0; +} + +QPoint Actor::movementToPoint(const Actor::Movement direction) +{ + QPoint endpos(0,0); + switch (direction) + { + case Actor::Up: + endpos = QPoint(0, -1); + break; + case Actor::Down: + endpos = QPoint(0, 1); + break; + case Actor::Left: + endpos = QPoint(-1, 0); + break; + case Actor::Right: + endpos = QPoint(1, 0); + break; + case Actor::None: + break; + default: + Q_ASSERT(false); + } + return endpos; +} -- cgit v1.2.3