]> git.sven.stormbind.net Git - sven/vym.git/blob - winter.cpp
4575e75d9265d169923773243c51af91ba54428d
[sven/vym.git] / winter.cpp
1 #include "winter.h"
2
3 #include "misc.h"
4
5 #include <QDebug>
6 #include <QGraphicsScene>
7 #include <QGraphicsView>
8 #include <QPen>
9
10 SnowFlake::SnowFlake(QGraphicsScene *scene)
11 {
12     size=qrand()%10+3;
13
14     int s4=size/4;
15     int s3=size/3;
16     int s6=size/6;
17
18     for (int a=0; a<6; a++)
19     {
20         lines.append(scene->addLine(0, -s6, 0, -size));
21         lines.last()->setRotation(a*60);
22
23         lines.append(scene->addLine(-s4, -size + s6, 0, -size + s3));
24         lines.last()->setRotation(a*60);
25
26         lines.append(scene->addLine( s4, -size + s6, 0, -size + s3));
27         lines.last()->setRotation(a*60);
28     }
29
30     QPen p(Qt::white);
31     foreach (QGraphicsLineItem *l, lines)
32     {
33         l->setZValue(1000);
34         l->setPen(p);
35         l->setParentItem(this);
36     }
37     dv=QPointF(qrand()%10/10.0-0.5, qrand()%10/10.0 +1);
38     da=qrand()%20 / 10.0 - 1;
39 }
40
41 SnowFlake::~SnowFlake()
42 {
43     //qDebug()<<"Destr. SnowFlake";
44     while(lines.isEmpty())
45         delete lines.takeFirst();
46 }
47
48 QRectF SnowFlake::boundingRect() const 
49 {
50     return QRectF (-size, -size, size*2, size*2);
51 }
52
53 void SnowFlake::paint(QPainter*, const QStyleOptionGraphicsItem*, QWidget*)
54 {
55 }
56
57 void SnowFlake::animate()
58 {
59     moveBy(dv.x() + dblow.x(), dv.y() + dblow.y());
60     setRotation(rotation() + da);
61     dblow = dblow *0.9;
62 }
63
64 void SnowFlake::blow(const QPointF &v)
65 {
66     dblow=v;
67 }
68
69 Winter::Winter(QGraphicsView *v)
70 {
71     view=v;
72
73     updateView();
74     /*
75     test=view->scene()->addLine(
76             QLineF(viewRect.topLeft(), viewRect.bottomRight()), 
77             QPen(Qt::blue) );
78     */
79
80     maxFlakes=1500;
81     maxFalling=140;
82     maxUnfreeze=50;
83
84     makeSnow();
85
86     animTimer = new QTimer;
87     connect (animTimer, SIGNAL (timeout()), this, SLOT (animate() ));
88     animTimer->start(50);
89
90     snowTimer = new QTimer;
91     connect (snowTimer, SIGNAL (timeout()), this, SLOT (makeSnow() ));
92     snowTimer->start(1000);
93 }
94
95 Winter::~Winter()
96 {
97     delete animTimer;
98     delete snowTimer;
99     while (!fallingSnow.isEmpty())
100         delete fallingSnow.takeFirst();
101     while (!frozenSnow.isEmpty())
102         delete frozenSnow.takeFirst();
103 }
104
105 void Winter::updateView()
106 {
107     QPointF p0=view->mapToScene( QPoint(0,0));
108     QPointF p1=view->mapToScene( view->rect().width(), view->rect().height() );
109     viewRect=QRectF(p0,p1);
110 }
111
112 void Winter::setObstacles(QList <QRectF> obslist)
113 {
114     obstacles=obslist;
115
116     QList <SnowFlake*> unfreeze;
117
118     // Find frozen snowflakes, which are free again
119     QPointF p;
120     int i=0;
121     bool frozen;
122     while (i < frozenSnow.count())
123     {
124         p=frozenSnow.at(i)->pos();
125         frozen=false;
126         
127         int j=0;
128         while (j<obstacles.count() && !frozen)
129
130         {
131             if (obstacles.at(j).contains(p) )
132                 frozen=true;
133             j++;
134         }
135         if (!frozen)
136         {
137             unfreeze.append(frozenSnow.at(i));
138             frozenSnow.removeAt(i);
139         } else
140             i++;
141     }
142     
143     // Remove some flakes, if too many
144     while (fallingSnow.count() + unfreeze.count() > maxFalling + maxUnfreeze)
145         delete unfreeze.takeFirst();
146
147     while (!unfreeze.isEmpty())
148     {
149         // Blow a bit up
150         unfreeze.first()->blow( QPointF(qrand()%10/10.0-0.5, qrand()%10/10.0 -5));
151         fallingSnow.append(unfreeze.takeFirst());
152     }
153 }
154
155
156 void Winter::animate()
157 {
158     updateView();
159     //test->setLine(QLineF(viewRect.topLeft(), viewRect.bottomRight())); 
160
161     QPointF p;
162     int i=0;
163     bool cont;
164     while (i<fallingSnow.count())
165     {
166         p=fallingSnow.at(i)->pos();
167         cont=true;
168         
169         int j=0;
170         while (j<obstacles.count() && cont)
171         {
172             if (obstacles.at(j).contains(p) && qrand()%(obstacles.count()+1) > obstacles.count()-1)
173             {
174                 // Freeze snowflake on obstacle
175                 // Probality is equale for obstacles or falling through
176                 frozenSnow.append(fallingSnow.at(i));
177                 fallingSnow.removeAt(i);
178                 cont=false;
179             } 
180             j++;
181         }
182         if (cont && p.y() > viewRect.y() + viewRect.height() + 20)
183         {
184             delete fallingSnow.takeAt(i);
185             cont=false;
186         }
187         // Let snowflake fall further
188         if (cont) fallingSnow.at(i)->animate();
189         i++;
190     }
191 }
192
193 void Winter::makeSnow()
194 {
195     //qDebug()<<"falling: "<<fallingSnow.count()<<"  frozen: "<<frozenSnow.count();
196     if (fallingSnow.count() + frozenSnow.count() <maxFlakes)
197     {
198         if (fallingSnow.count() < maxFalling)
199         {
200             // Create more snowflakes
201             SnowFlake *snowflake;
202             for (int i=0; i<10; i++)
203             {
204                 snowflake=new SnowFlake(view->scene());
205                 snowflake->setPos( 0,0);
206                 snowflake->setRotation(qrand()%60);
207                 view->scene()->addItem(snowflake);
208                 snowflake->setPos( 
209                         rand()%round_int(viewRect.width()) + viewRect.x(),
210                         viewRect.y() -20
211                 );
212                 fallingSnow.append(snowflake);
213             }
214         }
215     } else
216     {
217         // Remove some of the existing frozen flakes
218         for (int i=0; i<10; i++)
219         {
220             if (frozenSnow.count()>0)
221             {
222                 int j=qrand()%frozenSnow.count();
223                 delete frozenSnow.takeAt(j);
224             }
225         }
226     }
227     
228 }
229