📄 mainwindow.cpp
字号:
// Copyright (C) 2004, 2005 Andi Peredri <andi@ukr.net>#include <math.h>#include <qapplication.h>#include <qbitmap.h>#include <qdir.h>#include <qimage.h>#include <qpainter.h>#include <qsettings.h>#include <stdio.h>#include <stdlib.h>#include <time.h>#include "mainwindow.h"static int w = 600;static int h = 420;static QImage background;// Star --------------------------------------------------------------------Star::Star(){ restart();}void Star::restart(){ x = rand() % (w + Border); y = rand() % h; color = (rand() % 16) * (rand() % 16) + 30; movecounter = 0;}void Star::paint(QPainter *p){ if(x < -1) { x = w + rand() % Border; y = rand() % h; return; } if(movecounter--) return; movecounter = (255 - color) >> 4; if(color == 255) { clearPoint(p, x + 1, y); clearPoint(p, x + 1, y + 1); } else clearPoint(p, x, y); drawPoint(p, --x, y); if(color == 255) drawPoint(p, x, y + 1);}void Star::drawPoint(QPainter* p, int px, int py){ if(background.valid(px, py)) { p->setPen(QColor(color, color, color)); p->drawPoint(px, py); }}void Star::clearPoint(QPainter* p, int px, int py){ if(background.valid(px, py)) { p->setPen(background.pixel(px, py)); p->drawPoint(px, py); }}// Demo --------------------------------------------------------------------class Demo{public: virtual ~Demo(); virtual void paint(QPainter*) = 0; static const QString& shareDir(); static QImage loadRandomImage(const QString& dirname);};Demo::~Demo(){}const QString& Demo::shareDir(){ static const QString dir1 = qApp->applicationDirPath(); static const QString dir2 = dir1 + "/../share/qstars"; return QFile::exists(dir2) ? dir2 : dir1;}QImage Demo::loadRandomImage(const QString& dirname){ QString path = shareDir() + "/" + dirname + "/"; QDir dir(path); dir.setFilter(QDir::Files); unsigned int count = dir.count(); if(count) return QImage(path + dir[rand() % count]); return QImage();}// Asteroid ----------------------------------------------------------------class Asteroid{public: Asteroid(QPixmap* pix); void paint(QPainter* p);private: void restart(); int x; int y; int nextframe; int frame; int movecounts; int movecounter; int rottimeout; QTime timer; QPixmap* pixmap;};Asteroid::Asteroid(QPixmap* pix){ timer.start(); pixmap = pix; restart();}void Asteroid::restart(){ rottimeout = rand() % 20 + 20; nextframe = rand() % 2 ? 1 : -1; frame = rand() % (pixmap->width() / pixmap->height()); movecounts = rand() % 5; movecounter = movecounts; x = rand() % (2 * w); y = rand() % (h - pixmap->height());}void Asteroid::paint(QPainter* p){ if(timer.elapsed() > rottimeout) { timer.restart(); frame += nextframe; const int maxframe = pixmap->width() / pixmap->height() - 1; if(frame < 0) frame = maxframe; if(frame > maxframe) frame = 0; } if(x + pixmap->height() < 0) { restart(); x = w + rand() % w; return; } if(!movecounter--) { movecounter = movecounts; x--; } p->drawPixmap(x, y, *pixmap, pixmap->height() * frame, 0, pixmap->height());}// Asteroids ---------------------------------------------------------------class Asteroids : public Demo{public: Asteroids(); void paint(QPainter* p);private: QPtrList<QPixmap> pixmaps; QPtrList<Asteroid> asteroids;};Asteroids::Asteroids(){ pixmaps.setAutoDelete(true); asteroids.setAutoDelete(true); const QString path = shareDir() + "/asteroids/"; QDir dir(path); dir.setFilter(QDir::Files); for(unsigned int i = 0; i < dir.count(); i++) { QPixmap* pixmap = new QPixmap(path + dir[i]); pixmaps.append(pixmap); int num = 80 / pixmap->height(); for(int i = 0; i < num; i++) asteroids.append(new Asteroid(pixmap)); }}void Asteroids::paint(QPainter* p){ for(Asteroid* a = asteroids.first(); a; a = asteroids.next()) a->paint(p);}// Planet ------------------------------------------------------------------class Planet : public Demo{public: Planet(); void paint(QPainter* p);private: struct Map { int texturex; int texturey; int spherex; int spherey; }; int radius; QBitmap mask; QImage texture; QImage image; QPixmap pixmap; QPtrList<Map> maps;};Planet::Planet(){ texture = loadRandomImage("planets"); radius = (int) (texture.height() / 3.14); image.create(2 * radius, 2 * radius, 32); image.fill(0); maps.setAutoDelete(true); for(double spherey = -radius; spherey < radius; spherey++) { const double angley = asin(spherey / radius); const double xmax = radius * cos(angley); const double texturey = angley * radius; for(double spherex = -xmax; spherex < xmax; spherex++) { const double texturex = radius * asin(spherex / xmax); Map* map = new Map; map->texturex = (int) (texture.height() / 2 + texturex); map->texturey = (int) (texture.height() / 2 + texturey); map->spherex = (int) (radius + spherex); map->spherey = (int) (radius + spherey); maps.append(map); } } for(Map* map = maps.first(); map; map = maps.next()) { QRgb* line = (QRgb*) image.scanLine(map->spherey); line[map->spherex] = qRgb(255, 255, 255); } pixmap.convertFromImage(image); mask = pixmap.createHeuristicMask();}void Planet::paint(QPainter* p){ static int counter = 0; if(counter > texture.width()) counter = 0; for(Map* map = maps.first(); map; map = maps.next()) { int x = map->texturex + counter; if(x >= texture.width()) x -= texture.width(); QRgb* line = (QRgb*) image.scanLine(map->spherey); line[map->spherex] = texture.pixel(x, map->texturey); } counter++; pixmap.convertFromImage(image); pixmap.setMask(mask); p->drawPixmap(w / 2 - radius, h / 2 - radius, pixmap);}// Ship --------------------------------------------------------------------class Ship : public Demo{public: Ship(); void paint(QPainter* p);private: int x; int y; QPixmap pixmap;};Ship::Ship(){ QImage image = loadRandomImage("ships"); x = (w - image.width()) / 2; y = (h - image.height()) / 2; pixmap.convertFromImage(image); pixmap.setMask(pixmap.createHeuristicMask());}void Ship::paint(QPainter* p){ p->drawPixmap(x, y, pixmap);}// MainWindow --------------------------------------------------------------MainWindow::MainWindow(WId wid) : QWidget(){ if(wid) { create(wid); w = width(); h = height(); } else setFixedSize(w, h); demo = 0; restarttimer = 0; stars.setAutoDelete(true); starground.resize(w, h); workground.resize(w, h); background.create(w, h, 32); setBackgroundMode(NoBackground); setIcon(QPixmap::fromMimeSource("qstars.png")); setCaption("QStars"); srand(time(0)); QSettings settings; settings.beginGroup("QStars"); speed = settings.readNumEntry("Speed", 50); showships = settings.readBoolEntry("ShowShips", true); showplanets = settings.readBoolEntry("ShowPlanets", true); showgalaxies = settings.readBoolEntry("ShowGalaxies", true); showasteroids = settings.readBoolEntry("ShowAsteroids", true); restarttimeout = settings.readNumEntry("Timer", 30); unsigned int density = settings.readNumEntry("Density", 50); int numstars = (w + Star::Border) * h * (density + 1) / 5000; for(int i = 0; i < numstars; i++) stars.append(new Star()); if(restarttimeout) restarttimer = startTimer(restarttimeout * 1000); restart(); updateRepaintTimer();}MainWindow::~MainWindow(){ QSettings settings; settings.writeEntry("/QStars/Speed", speed); delete demo;}void MainWindow::updateRepaintTimer(){ static int repainttimer = 0; if(speed < 0) speed = 0; if(speed > 100) speed = 100; killTimer(repainttimer); repainttimer = startTimer(1000 / (speed + 20));}void MainWindow::restart(){ delete demo; demo = 0; background.fill(0); starground.fill(black); for(Star* star = stars.first(); star; star = stars.next()) star->restart(); QValueList<int> list; if(showasteroids) list << 1; if(showplanets) list << 2 << 2 << 2 << 2; if(showships) list << 3; if(list.count() && (w > 300) && (h > 200)) { int random = list[rand() % list.count()]; if(random == 1) demo = new Asteroids; else if(random == 2) demo = new Planet; else demo = new Ship; } if(showgalaxies) { QWMatrix matrix; QImage galaxy = Demo::loadRandomImage("galaxies"); galaxy = galaxy.xForm(matrix.rotate(rand() % 360)); int x = (rand() % 2) ? 0 : (w - galaxy.width()); int y = (rand() % 2) ? 0 : (h - galaxy.height()); bitBlt(&background, x, y, &galaxy); bitBlt(&starground, 0, 0, &background); } update();}void MainWindow::timerEvent(QTimerEvent* e){ if(e->timerId() == restarttimer) restart(); else { QPainter p(&starground); for(Star* star = stars.first(); star; star = stars.next()) star->paint(&p); p.end(); bitBlt(&workground, 0, 0, &starground); p.begin(&workground); if(demo) demo->paint(&p); bitBlt(this, 0, 0, &workground); }}void MainWindow::keyPressEvent(QKeyEvent* e){ switch(e->key()) { case Key_Up: speed += 20; updateRepaintTimer(); break; case Key_Down: speed -= 20; updateRepaintTimer(); break; case Key_Right: if(restarttimeout) { killTimer(restarttimer); restarttimer = startTimer(restarttimeout * 1000); } restart(); break; case Key_Q: QApplication::exit(); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -