diff options
author | gregory guy <gregory-tde@laposte.net> | 2021-04-26 18:43:25 +0200 |
---|---|---|
committer | gregory guy <gregory-tde@laposte.net> | 2021-05-20 20:16:35 +0200 |
commit | 749694a3f2fecddf44633067c24851d8719b181e (patch) | |
tree | 27c58f5c28223c8ae9aa5a01409a5e12ff0c52ca /tdescreensaver/kdesavers/tdeasciiquarium/screen.cpp | |
parent | b0ef1b76e6bc94f5a8a35b9a43573eab81bca459 (diff) | |
download | tdeartwork-749694a3f2fecddf44633067c24851d8719b181e.tar.gz tdeartwork-749694a3f2fecddf44633067c24851d8719b181e.zip |
asciiquarium: Add cmake build support, app is renamed tdeasciiquarium.
Signed-off-by: gregory guy <gregory-tde@laposte.net>
Diffstat (limited to 'tdescreensaver/kdesavers/tdeasciiquarium/screen.cpp')
-rw-r--r-- | tdescreensaver/kdesavers/tdeasciiquarium/screen.cpp | 222 |
1 files changed, 222 insertions, 0 deletions
diff --git a/tdescreensaver/kdesavers/tdeasciiquarium/screen.cpp b/tdescreensaver/kdesavers/tdeasciiquarium/screen.cpp new file mode 100644 index 00000000..ade5abc1 --- /dev/null +++ b/tdescreensaver/kdesavers/tdeasciiquarium/screen.cpp @@ -0,0 +1,222 @@ +#include <tqcolor.h> +#include <tqfontmetrics.h> +#include <tqpainter.h> +#include <tqpixmap.h> +#include <tqtimer.h> +#include <tqwidget.h> + +#include <tdeglobalsettings.h> + +#include "screen.h" +#include "sprite.h" +#include "aasaver.h" + +Screen::Screen(AASaver* widget): m_widget(widget) +{ + TQFontMetrics fm(TDEGlobalSettings::fixedFont()); + + // Compute cell geometries. + m_cellW = fm.maxWidth(); + m_cellH = fm.lineSpacing(); + + // Computer number of full cells that will fit. + m_width = widget->width() / m_cellW; + m_height = widget->height() / m_cellH; + + // Calculate offset needed to evenly distribute excess screen space. + m_offX = (widget->width() - m_width * m_cellW) / 2; + m_offY = (widget->height() - m_height * m_cellH) / 2; + + // Create double buffer. + m_backBuffer = TQPixmap(m_widget->size()); + m_backBuffer.fill(black); + + // FIXME: handle resizing! + + // Setup animation timer. + TQTimer* timer = new TQTimer(this); + connect(timer, SIGNAL(timeout()), SLOT(doAnimate())); + + timer->start(msPerTick()); +} + +int Screen::msPerTick() const +{ + return 50; +} + +Screen::~Screen() +{ +} + +void Screen::updateSpan(int x, int y, const TQPixmap &updatePixmap) +{ + if (y < 0 || y >= m_height) return; + + TQPoint upperLeft(m_offX + x * m_cellW, m_offY + y * m_cellH); + bitBlt(&m_backBuffer, upperLeft, &updatePixmap, updatePixmap.rect(), TQt::CopyROP); + m_widget->update(TQRect(upperLeft, updatePixmap.size())); +} + +void Screen::clearSpan(int x, int y, const TQPixmap &clearPixmap) +{ + if (y < 0 || y >= m_height) return; + + TQPoint upperLeft(m_offX + x * m_cellW, m_offY + y * m_cellH); + bitBlt(&m_backBuffer, upperLeft, &clearPixmap, clearPixmap.rect(), TQt::CopyROP); + m_widget->update(TQRect(upperLeft, clearPixmap.size())); +} + +//Actually paints the region on the widget. +void Screen::paint(TQRegion r) +{ + TQPainter p(m_widget); + TQMemArray<TQRect> rects = r.rects(); + + for (int r = 0; r < rects.size(); ++r) + { + //Determine the grid locations described by the rect + TQRect bound = rects[r]; + + bitBlt(m_widget, bound.topLeft(), &m_backBuffer, bound, TQt::CopyROP); + } //for rect in region +}; + +/** + * Utility type used to faciliate sorting of the Sprite list in order to + * implement the Painter's Algorithm when painting the back buffer. + */ +struct ZKey +{ + /** + * Logical depth of sprite. Now 0 is farthest away from the eyes, unlike + * with Sprite::depth(). + */ + int z; + + Sprite* addr; + + ZKey(): z(0), addr(0) + {} + + ZKey(Sprite* spr): z(1000 - spr->depth()), addr(spr) + {} + + bool operator<(const ZKey& other) const + { + if (z < other.z) return true; + if (z > other.z) return false; + + return addr < other.addr; + } +}; + +void Screen::doAnimate() +{ + //First, rebuild a new list of sprites, and build a dirty region + TQRegion dirtyRegion; + + TQValueVector<Sprite*> sprites; + TQValueVector<Sprite*> colliders; + + // Look for sprites that can suffer a collision. + for (unsigned pos = 0; pos < m_sprites.size(); ++pos) + { + if(m_sprites[pos]->canCollide()) + colliders.append(m_sprites[pos]); + } + + // Find collisions. + // FIXME: Use transparent regions for accuracy. + for (unsigned pos = 0; pos < colliders.size(); ++pos) + for (unsigned sprite = 0; sprite < m_sprites.size(); ++sprite) + { + if(m_sprites[sprite] == colliders[pos]) + continue; + + if(colliders[pos]->geom().intersects(m_sprites[sprite]->geom())) + colliders[pos]->collision(m_sprites[sprite]); + } + + //Retain all live existing sprites + for (int pos = 0; pos < m_sprites.size(); ++pos) + { + Sprite* sprite = m_sprites[pos]; + TQRect oldRect = sprite->geom(); + if (!sprite->isKilled()) { + bool dirty = sprite->tickUpdate(); + + if (dirty) + dirtyRegion |= oldRect | sprite->geom(); + + if (!sprite->isKilled()) + sprites.append(sprite); + } + + if (sprite->isKilled()) //note:may be made true by updateTick! + { + dirtyRegion |= oldRect; + delete sprite; + } + } + + //Add new sprites. + for (int pos = 0; pos < m_addedSprites.size(); ++pos) + { + dirtyRegion |= m_addedSprites[pos]->geom(); + sprites.append(m_addedSprites[pos]); + } + + m_addedSprites.clear(); + m_sprites = sprites; + + //Compute the list of sprites affected. Note that this is + //done iteratively until fixed point. + TQValueVector<Sprite*> paintSprites; + TQValueVector<Sprite*> remSprites; + + bool changed; + do + { + changed = false; + remSprites.clear(); + + for (int c = 0; c < sprites.size(); ++c) + { + Sprite* sprite = sprites[c]; + + if (dirtyRegion.intersect(sprite->geom()).isEmpty()) + remSprites.append(sprite); //not to be painted thus far + else + { + //This sprite is to be painted + paintSprites.append(sprite); + + //make sure we repaint everything overlapping it + dirtyRegion |= sprite->geom(); + changed = true; + } + } + sprites = remSprites; + } + while (changed); + + //Z-sort the items. + TQMap<ZKey, Sprite* > sorted; + for (int pos = 0; pos < paintSprites.size(); ++pos) + sorted[ZKey(paintSprites[pos])] = paintSprites[pos]; + + //Paint, in Z-order + for (TQMapIterator<ZKey, Sprite*> i = sorted.begin(); + i != sorted.end(); ++i) + i.data()->paint(); + + // Make sure black strip at edge is still present. + if(!paintSprites.isEmpty()) + { + TQPainter p(&m_backBuffer); + p.fillRect(m_backBuffer.width() - m_offX, 0, m_offX, m_backBuffer.height(), TQt::black); + } +} + +#include "screen.moc" |