X-Git-Url: https://git.sven.stormbind.net/?a=blobdiff_plain;f=src%2Fwinter.cpp;fp=src%2Fwinter.cpp;h=996e763c04be50e498f47a06447b44cf3ded6048;hb=d483bd8e6523c23c6f1d8908a2e0611c2bc9ff4f;hp=0000000000000000000000000000000000000000;hpb=7dfa3fe589d1722d49681f42cdb0bf1e6efb5223;p=sven%2Fvym.git diff --git a/src/winter.cpp b/src/winter.cpp new file mode 100644 index 0000000..996e763 --- /dev/null +++ b/src/winter.cpp @@ -0,0 +1,290 @@ +#include "winter.h" + +#include +#include +#include +#include +#include + + +#include "mapobj.h" +#include "misc.h" + +SnowFlake::SnowFlake(QGraphicsScene *scene, SnowType t) +{ + type = t; + + size = QRandomGenerator::global()->bounded(10) + 3; + QPen p(Qt::white); + dv = QPointF( + QRandomGenerator::global()->bounded(10) / 10.0 - 0.5, + QRandomGenerator::global()->bounded(10) / 10.0 + 1); + + switch (type) { + case Smilla: { + int s4 = size / 4; + int s3 = size / 3; + int s6 = size / 6; + + for (int a = 0; a < 6; a++) { + lines.append(scene->addLine(0, -s6, 0, -size)); + lines.last()->setRotation(a * 60); + + lines.append(scene->addLine(-s4, -size + s6, 0, -size + s3)); + lines.last()->setRotation(a * 60); + + lines.append(scene->addLine(s4, -size + s6, 0, -size + s3)); + lines.last()->setRotation(a * 60); + } + + foreach (QGraphicsLineItem *l, lines) { + l->setZValue(1000); + l->setPen(p); + l->setParentItem(this); + l->setZValue(Z_SNOW); + } + da = QRandomGenerator::global()->bounded(20) / 10.0 - 1; + } + setRotation(QRandomGenerator::global()->bounded(60)); + break; + case Disc: + disc = scene->addEllipse(0, 0, size, size, p); + disc->setParentItem(this); + disc->setBrush(Qt::white); + disc->setZValue(Z_SNOW); + break; + case Egg: + disc = scene->addEllipse(0, 0, size, size * 1.5, p); + disc->setParentItem(this); + disc->setBrush(QColor( + QRandomGenerator::global()->bounded(100) + 150, + QRandomGenerator::global()->bounded(100) + 150, + QRandomGenerator::global()->bounded(100) + 150, 255)); + disc->setZValue(Z_SNOW); + break; + default: + break; + } +} + +SnowFlake::~SnowFlake() +{ + // qDebug()<<"Destr. SnowFlake"; + switch (type) { + case (Smilla): + while (lines.isEmpty()) + delete lines.takeFirst(); + break; + case Egg: + delete disc; + break; + case Disc: + delete disc; + break; + default: + break; + } +} + +QRectF SnowFlake::boundingRect() const +{ + return QRectF(-size, -size, size * 2, size * 2); +} + +void SnowFlake::paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *) +{ +} + +void SnowFlake::animate() +{ + moveBy(dv.x() + dblow.x(), dv.y() + dblow.y()); + + if (type == SnowFlake::Smilla) + setRotation(rotation() + da); + + dblow = dblow * 0.9; +} + +void SnowFlake::blow(const QPointF &v) { dblow = v; } + +Winter::Winter(QGraphicsView *v) +{ + view = v; + + updateView(); + /* + test = view->scene()->addRect( + QRectF(viewRect.topLeft(), viewRect.bottomRight()), + QPen(Qt::blue) ); + */ + + type = SnowFlake::Egg; + + switch (type) { + case SnowFlake::Smilla: + maxFlakes = 1500; + maxFalling = 140; + maxUnfreeze = 50; + break; + case SnowFlake::Egg: + maxFlakes = 500; + maxFalling = 150; + maxUnfreeze = 50; + break; + default: + maxFlakes = 6500; + maxFalling = 850; + maxUnfreeze = 50; + break; + } + + animTimer = new QTimer; + connect(animTimer, SIGNAL(timeout()), this, SLOT(animate())); + animTimer->start(50); + + snowTimer = new QTimer; + connect(snowTimer, SIGNAL(timeout()), this, SLOT(makeSnow())); + //snowTimer->setSingleShot(true); + + makeSnow(); +} + +Winter::~Winter() +{ + delete animTimer; + delete snowTimer; + while (!fallingSnow.isEmpty()) + delete fallingSnow.takeFirst(); + while (!frozenSnow.isEmpty()) + delete frozenSnow.takeFirst(); +} + +void Winter::updateView() +{ + QPointF topLeft = view->mapToScene(0, 0); + QPointF topRight = view->mapToScene(view->rect().width(), 0); + QPointF botLeft = view->mapToScene(0, view->rect().height()); + QPointF botRight = + view->mapToScene(view->rect().width(), view->rect().height()); + + QPointF p0; + QPointF p1; + + topLeft.y() < topRight.y() ? p0.setY(topLeft.y()) : p0.setY(topRight.y()); + topLeft.x() < topRight.x() ? p0.setX(topLeft.x()) : p0.setX(topRight.x()); + + botLeft.y() > botRight.y() ? p1.setY(botLeft.y()) : p1.setY(botRight.y()); + botLeft.x() > botRight.x() ? p1.setX(botLeft.x()) : p1.setX(botRight.x()); + + viewRect = QRectF(p0, p1); +} + +void Winter::setObstacles(QList obslist) +{ + obstacles = obslist; + + QList unfreeze; + + // Find frozen snowflakes, which are free again + QPointF p; + int i = 0; + bool frozen; + while (i < frozenSnow.count()) { + p = frozenSnow.at(i)->pos(); + frozen = false; + + int j = 0; + while (j < obstacles.count() && !frozen) + + { + if (obstacles.at(j).contains(p)) + frozen = true; + j++; + } + if (!frozen) { + unfreeze.append(frozenSnow.at(i)); + frozenSnow.removeAt(i); + } + else + i++; + } + + // Remove some flakes, if too many + while (fallingSnow.count() + unfreeze.count() > maxFalling + maxUnfreeze) + delete unfreeze.takeFirst(); + + while (!unfreeze.isEmpty()) { + // Blow a bit up + unfreeze.first()->blow( + QPointF( + QRandomGenerator::global()->bounded(10) / 10.0 - 0.5, + QRandomGenerator::global()->bounded(10) / 10.0 - 5)); + fallingSnow.append(unfreeze.takeFirst()); + } +} + +void Winter::animate() +{ + // test->setRect(QRectF(viewRect.topLeft(), viewRect.bottomRight())); + + QPointF p; + int i = 0; + bool cont; + while (i < fallingSnow.count()) { + p = fallingSnow.at(i)->pos(); + cont = true; + + int j = 0; + while (j < obstacles.count() && cont) { + if (obstacles.at(j).contains(p) && + QRandomGenerator::global()->bounded(obstacles.count() + 1) > obstacles.count() - 1) { + // Freeze snowflake on obstacle + // Probality is equale for obstacles or falling through + frozenSnow.append(fallingSnow.at(i)); + fallingSnow.removeAt(i); + cont = false; + } + j++; + } + if (cont && p.y() > viewRect.bottomRight().y() + 20) + + { + delete fallingSnow.takeAt(i); + cont = false; + } + // Let snowflake fall further + if (cont) + fallingSnow.at(i)->animate(); + i++; + } +} + +void Winter::makeSnow() +{ + // qDebug()<<"falling: "<scene(), type); + view->scene()->addItem(snowflake); + snowflake->setPos(rand() % round_int(viewRect.width()) + + viewRect.x(), + viewRect.y() - 20); + fallingSnow.append(snowflake); + } + } + } + else { + // Remove some of the existing frozen flakes + for (int i = 0; i < 10; i++) { + if (frozenSnow.count() > 0) { + int j = QRandomGenerator::global()->bounded(frozenSnow.count()); + delete frozenSnow.takeAt(j); + } + } + } + snowTimer->start(2000); +}