summaryrefslogtreecommitdiffstats
path: root/tdescreensaver/kdesavers/tdeasciiquarium/aasaver.cpp
diff options
context:
space:
mode:
authorgregory guy <gregory-tde@laposte.net>2021-04-26 18:43:25 +0200
committergregory guy <gregory-tde@laposte.net>2021-05-20 20:16:35 +0200
commit749694a3f2fecddf44633067c24851d8719b181e (patch)
tree27c58f5c28223c8ae9aa5a01409a5e12ff0c52ca /tdescreensaver/kdesavers/tdeasciiquarium/aasaver.cpp
parentb0ef1b76e6bc94f5a8a35b9a43573eab81bca459 (diff)
downloadtdeartwork-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/aasaver.cpp')
-rw-r--r--tdescreensaver/kdesavers/tdeasciiquarium/aasaver.cpp1220
1 files changed, 1220 insertions, 0 deletions
diff --git a/tdescreensaver/kdesavers/tdeasciiquarium/aasaver.cpp b/tdescreensaver/kdesavers/tdeasciiquarium/aasaver.cpp
new file mode 100644
index 00000000..daf09d97
--- /dev/null
+++ b/tdescreensaver/kdesavers/tdeasciiquarium/aasaver.cpp
@@ -0,0 +1,1220 @@
+//Stub stolen from:
+// klines 0.1.1 - Basic screen saver for KDE
+// by Dirk Staneker 1997
+
+#include <kdebug.h>
+#include <tdelocale.h>
+#include <tdeconfigdialog.h>
+
+#include <tqdesktopwidget.h>
+#include <tqpainter.h>
+#include <tqbrush.h>
+
+#include "screen.h"
+#include "frame.h"
+#include "sprite.h"
+#include "aasaver.h"
+
+#include "AASaverConfig.h"
+#include "settingswidget.h"
+
+#define ARRAY_SIZE(arr) sizeof(arr)/sizeof(arr[0])
+
+AASaver::AASaver( WId id ): KScreenSaver(id)
+{
+ screen = new Screen(this);
+ addEnvironment();
+ addCastle();
+ addAllSeaweed();
+ addAllFish();
+ addRandom(screen);
+
+ setBackgroundMode(NoBackground);
+ setWFlags(WNoAutoErase);
+ update(rect());
+}
+
+
+TQString AASaver::randColor(TQString color_mask)
+{
+ char colors[] = {'c','C','r','R','y','Y','b','B','g','G','m','M'};
+ for (int i = 1; i <= 9; ++i)
+ {
+ char color = colors[intRand(ARRAY_SIZE(colors))];
+ color_mask.replace('0' + i, color);
+ }
+ return color_mask;
+}
+
+void AASaver::addCastle()
+{
+ TQString castle_image =
+ " T~~\n"
+ " |\n"
+ " /^\\\n"
+ " / \\\n"
+ " _ _ _ / \\ _ _ _\n"
+ "[ ]_[ ]_[ ]/ _ _ \\[ ]_[ ]_[ ]\n"
+ "|_=__-_ =_|_[ ]_[ ]_|_=-___-__|\n"
+ " | _- = | =_ = _ |= _= |\n"
+ " |= -[] |- = _ = |_-=_[] |\n"
+ " | =_ |= - ___ | =_ = |\n"
+ " |= []- |- /| |\\ |=_ =[] |\n"
+ " |- =_ | =| | | | |- = - |\n"
+ " |_______|__|_|_|_|__|_______|\n";
+
+
+ TQString castle_mask =
+ " RR\n"
+ "\n"
+ " yyy\n"
+ " y y\n"
+ " y y\n"
+ " y y\n"
+ "\n"
+ "\n"
+ "\n"
+ " yyy\n"
+ " yy yy\n"
+ " y y y y\n"
+ " yyyyyyy\n";
+
+ Frame f(castle_image, castle_mask, 0x686868/* XXX: why grey? */ );
+
+ Sprite* castle = new Sprite(screen,
+ screen->width() - 32, screen->height() - 13, 22);
+ castle->addFrame(f);
+ screen->addSprite(castle);
+}
+
+void AASaver::addEnvironment()
+{
+ TQString water_line_segment[] = {
+ "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~",
+ "^^^^ ^^^ ^^^ ^^^ ^^^^ ",
+ "^^^^ ^^^^ ^^^ ^^ ",
+ "^^ ^^^^ ^^^ ^^^^^^ "
+ };
+
+ // tile the segments so they stretch across the screen
+ int segment_size = water_line_segment[0].length();
+ int segment_repeat = int(screen->width()/segment_size) + 1;
+
+ for (unsigned i = 0; i < ARRAY_SIZE(water_line_segment); ++i) {
+ //do the tiling
+ TQString out;
+ for (int r = 0; r < segment_repeat; ++r)
+ out += water_line_segment[i];
+
+ //create a sprite.
+ Sprite* s = new Sprite(screen, 0, i + 5, 22);
+ s->addFrame(Frame(out, TQString::null, 0x149494));
+ screen->addSprite(s);
+ }
+}
+
+void AASaver::addAllSeaweed()
+{
+ // figure out how many seaweed to add by the width of the screen
+ int seaweed_count = int(screen->width() / 15.0);
+ for (int i = 1; i <= seaweed_count; ++i)
+ addSeaweed(screen);
+}
+
+/**
+ * Special class to represent seaweed. Seaweed can disappear over time, and
+ * when this happens, this class will automatically spawn another one.
+ */
+class Seaweed: public Sprite
+{
+ int m_ticks; ///< Number of animation ticks elapsed.
+ int m_lifeTimeMS; ///< Life time of seaweed in milliseconds.
+
+public:
+ /**
+ * Constructor. The \p x, \p y, and \p z coordinates are all in logical
+ * coordinates.
+ *
+ * @param s The Screen to be created in.
+ * @param x The x coordinate to place the seaweed at.
+ * @param y The y coordinate to place the seaweed at.
+ * @param life The length of time in milliseconds the seaweed will live for.
+ */
+ Seaweed(Screen* s, int x, int y, int life): Sprite(s, x, y, 21),
+ m_ticks(0), m_lifeTimeMS(life)
+ {
+ }
+
+ /**
+ * Reimplemented from Sprite::tickUpdate() to handle keeping track of
+ * Seaweed lifetime. Calls the inherited tickUpdate() as well.
+ */
+ virtual bool tickUpdate()
+ {
+ ++m_ticks;
+ if (m_ticks * m_screen->msPerTick() > m_lifeTimeMS)
+ {
+ kill();
+ AASaver::addSeaweed(m_screen);
+ }
+
+ return Sprite::tickUpdate();
+ }
+};
+
+void AASaver::addSeaweed(Screen* screen)
+{
+ TQString seaweed_image[] = {"", ""};
+ int height = intRand(5) + 3;
+ for (int i = 1; i <= height; ++i)
+ {
+ int left_side = i % 2;
+ int right_side = !left_side;
+ seaweed_image[left_side] += "(\n";
+ seaweed_image[right_side] += " )\n";
+ }
+
+ int x = intRand(screen->width() - 2) + 1;
+ int y = screen->height() - height;
+
+ Seaweed* s = new Seaweed(screen, x, y,
+ intRand(4*60000) + (8*60000)); // seaweed lives for 8 to 12 minutes
+ s->addFrame(Frame(seaweed_image[0], TQString::null, 0x18AF18));
+ s->addFrame(Frame(seaweed_image[1], TQString::null, 0x18AF18));
+ s->setFrameDelay(intRand(50) + 250);
+ screen->addSprite(s);
+}
+
+/**
+ * Class to represent an AirBubble. The bubble will automatically float up,
+ * even though it is not descended from MovingSprite.
+ */
+class AirBubble : public Sprite
+{
+ const int m_startY; ///< Y coordinate we started at, needed to choose a frame.
+
+public:
+ /**
+ * Constructor. The \p x, \p y, and \p z coordinates are all in logical
+ * coordinates.
+ *
+ * @param screen The Screen to be created in.
+ * @param x The x coordinate to start at.
+ * @param y The y coordinate to start at.
+ * @param z The depth to start at.
+ */
+ AirBubble(Screen *screen, int x, int y, int z) :
+ Sprite(screen, x, y, z), m_startY(y)
+ {
+ addFrame(Frame(".", TQString(), 0x18B2B2));
+ addFrame(Frame("o", TQString(), 0x18B2B2));
+ addFrame(Frame("O", TQString(), 0x18B2B2));
+
+ setFrameDelay(100);
+ }
+
+ /**
+ * Reimplemented from Sprite::tickUpdate() to handle moving the sprite and
+ * updating the current frame. The inherited tickUpdate() is not called.
+ */
+ virtual bool tickUpdate()
+ {
+ if (!timerTick())
+ return false;
+
+ erase();
+
+ m_currentFrame = 0;
+ if(m_startY - m_y > 5)
+ m_currentFrame = 1;
+ if(m_startY - m_y > 11)
+ m_currentFrame = 2;
+
+ m_y--;
+ if(m_y < 9)
+ kill();
+
+ return true;
+ }
+};
+
+/**
+ * Moving sprite, will be killed when it moves off of the screen.
+ */
+class MovingSprite: public Sprite
+{
+protected:
+ int m_direct; ///< Direction to move in, -1 == left, 1 == right.
+ double m_speed; ///< Speed to move at (Currently m_speed per tick).
+ double m_realX; ///< Used for accuracy, holds fractional x position.
+ int m_ticksSinceLastChange; ///< Number of timer ticks since last frame change.
+ int m_frameTime; ///< Amount of time in milliseconds to show each frame.
+
+public:
+ /**
+ * Constructor. The \p x, \p y, and \p z coordinates are all in logical
+ * coordinates.
+ *
+ * @param screen The Screen to be created in.
+ * @param direct The direction to move the sprite in along the X axis, either
+ * -1 for the left direction, or 1 for the right direction.
+ * @param speed The speed to move the sprite in along the X axis, in
+ * character cells per tick. Use Screen::msPerTick() to find
+ * out how long a tick takes. The speed can be fractional
+ * (e.g. 1.5 cells per tick).
+ * @param x The x coordinate to start at.
+ * @param y The y coordinate to start at.
+ * @param z The depth to start at.
+ */
+ MovingSprite(Screen* screen, int direct, double speed, int x, int y, int z):
+ Sprite(screen, x, y, z), m_direct(direct), m_speed(speed), m_realX(x),
+ m_ticksSinceLastChange(0), m_frameTime(250)
+ {
+ }
+
+ /**
+ * Sets the amount of time a frame is shown. Use this function for
+ * MovingSprites that are also animated.
+ *
+ * @param milliseconds Amount of time to show a frame for in milliseconds.
+ */
+ void setFrameTime(int milliseconds)
+ {
+ m_frameTime = milliseconds;
+ }
+
+ /// Returns the amount of time a frame lasts in milliseconds.
+ int frameTime() const { return m_frameTime; }
+
+ /// Returns the direction the sprite travels in.
+ int direction() const
+ {
+ return m_direct;
+ }
+
+ /// Returns the fractional speed of the sprite.
+ double realSpeed() const
+ {
+ return m_speed;
+ }
+
+ /// Returns the real (fractional) X position of the sprite.
+ double realX() const
+ {
+ return m_realX;
+ }
+
+ /**
+ * Reimplemented from Sprite::tickUpdate() to handle motion and frame
+ * animation. This function will automatically kill() this sprite when
+ * it moves off screen. The inherited tickUpdate() is not called.
+ */
+ virtual bool tickUpdate()
+ {
+ if (!timerTick())
+ return false;
+
+ erase();
+ m_realX += (m_direct * m_speed);
+ m_x = (int) m_realX;
+
+ ++m_ticksSinceLastChange;
+ if(m_ticksSinceLastChange * m_screen->msPerTick() > m_frameTime)
+ {
+ m_ticksSinceLastChange = 0;
+
+ ++m_currentFrame;
+ if(m_currentFrame == m_frames.size())
+ m_currentFrame = 0;
+ }
+
+ if((m_x + m_frames[m_currentFrame].width() < 0) || (m_x > m_screen->width()))
+ kill();
+
+ return true;
+ }
+};
+
+/**
+ * Will spawn a random sprite when killed, otherwise behaves just like
+ * MovingSprite.
+ */
+class RandomMovingSprite : public MovingSprite
+{
+public:
+ RandomMovingSprite(Screen *screen, int direct, double speed, int x, int y, int z):
+ MovingSprite(screen, direct, speed, x, y, z)
+ {
+ }
+
+ /// Spawns another RandomMovingSprite before dying.
+ virtual void kill()
+ {
+ MovingSprite::kill();
+ AASaver::addRandom(m_screen);
+ }
+};
+
+/**
+ * Special subclass that represents a fish. Used so TeethSprite knows when it
+ * has caused a collision, and also to handle air bubble generation.
+ */
+class FishSprite : public MovingSprite
+{
+ double m_spacesPerBubble; ///< Amount of spaces a fish moves for each bubble.
+ double m_lastBubbleRelease; ///< Amount of space traveled since the last bubble.
+
+public:
+ FishSprite(Screen* screen, int direct, double speed, int x, int y, int z):
+ MovingSprite(screen, direct, speed, x, y, z), m_lastBubbleRelease(x)
+ {
+ m_spacesPerBubble = AASaver::doubleRand(screen->width()) + 12.0;
+ }
+
+ /// Spawns another fish before dying.
+ virtual void kill()
+ {
+ MovingSprite::kill();
+ AASaver::addFish(m_screen);
+ }
+
+ /**
+ * Reimplemented from MovingSprite::tickUpdate() to handle creating air
+ * bubbles. Inherited tickUpdate() is still called.
+ */
+ virtual bool tickUpdate()
+ {
+ if(!MovingSprite::tickUpdate())
+ return false;
+
+ if(isKilled())
+ return true;
+
+ if(TQABS(realX() - m_lastBubbleRelease) >= m_spacesPerBubble)
+ {
+ m_lastBubbleRelease = realX();
+
+ int bubbleX = m_x;
+ TQRect geometry = geom();
+
+ if(m_direct > 0) // Moving right
+ bubbleX += geometry.width();
+
+ AASaver::addBubble(m_screen, bubbleX, m_y + geometry.height() / 2 - 1, m_z - 1);
+ }
+
+ return true;
+ }
+};
+
+void AASaver::addAllFish()
+{
+ // Determine how many logical pixels we are dealing with, and find out how
+ // many we'd be dealing with in full screen, and then scale the user's
+ // number down to adjust so that we look about the same in a window as we
+ // do fullscreen. TODO: Xinerama issues?
+ TQRect fullScreenGeometry = kapp->desktop()->screenGeometry();
+
+ int full_width = fullScreenGeometry.width() / screen->cellWidth();
+ int full_height = fullScreenGeometry.height() / screen->cellHeight() - 9;
+ int full_size = full_width * full_height;
+ int screen_size = (screen->height() - 9) * screen->width();
+
+ int fish_count = AASaverConfig::fishCount() * screen_size / full_size;
+ if(fish_count < 5)
+ fish_count = 5;
+
+ for (int i = 1; i <= fish_count; ++ i)
+ addFish(screen);
+}
+
+Sprite *AASaver::newFish(Screen *screen)
+{
+ TQString fish_image[] = {
+" \\\n"
+" ...\\..,\n"
+"\\" "??" "/' \\\n" // trigraphs suck
+" >= ( ' >\n"
+"/??\\ / /\n"
+" `\"'\"'/''\n",
+
+" 2\n"
+" 1112111\n"
+"6 11 1\n"
+" 66 7 4 5\n"
+"6 1 3 1\n"
+" 11111311\n",
+
+//////////////////////////////
+" /\n"
+" ,../...\n"
+" / '\\" "??" "/\n" // trigraphs suck
+"< ' ) =<\n"
+" \\ \\ /??\\\n"
+" `'\\'\"'\"'\n",
+
+" 2\n"
+" 1112111\n"
+" 1 11 6\n"
+"5 4 7 66\n"
+" 1 3 1 6\n"
+" 11311111\n",
+//////////////////////////////
+" \\\n"
+"\\?/--\\\n"
+">= (o>\n"
+"/?\\__/\n"
+" /\n",
+
+" 2\n"
+"6 1111\n"
+"66 745\n"
+"6 1111\n"
+" 3\n",
+
+//////////////////////////////
+" /\n"
+" /--\\?/\n"
+"<o) =<\n"
+" \\__/?\\\n"
+" \\\n",
+
+" 2\n"
+" 1111 6\n"
+"547 66\n"
+" 1111 6\n"
+" 3\n",
+
+//////////////////////////////
+" \\:.\n"
+"\\;,???,;\\\\\\\\\\,,\n"
+" \\\\\\\\\\;;:::::o\n"
+" ///;;::::::::<\n"
+" /;`?``/////``\n",
+
+" 222\n"
+"666 1122211\n"
+" 6661111111114\n"
+" 66611111111115\n"
+" 666 113333311\n",
+
+//////////////////////////////
+" .:/\n"
+" ,,///;,???,;/\n"
+" o:::::::;;///\n"
+">::::::::;;\\\\\\\n"
+" ''\\\\\\\\\\''?';\\\n",
+
+" 222\n"
+" 1122211 666\n"
+" 4111111111666\n"
+"51111111111666\n"
+" 113333311 666\n",
+
+//////////////////////////////
+" __\n"
+"><_'>\n"
+" '\n",
+
+" 11\n"
+"61145\n"
+" 3\n",
+
+//////////////////////////////
+" __\n"
+"<'_><\n"
+" `\n",
+
+" 11\n"
+"54116\n"
+" 3\n",
+
+//////////////////////////////
+" ..\\,\n"
+">=' ('>\n"
+" '''/''\n",
+
+" 1121\n"
+"661 745\n"
+" 111311\n",
+
+//////////////////////////////
+" ,/..\n"
+"<') `=<\n"
+" ``\\```\n",
+
+" 1211\n"
+"547 166\n"
+" 113111\n",
+
+//////////////////////////////
+" \\\n"
+" / \\\n"
+">=_('>\n"
+" \\_/\n"
+" /\n",
+
+" 2\n"
+" 1 1\n"
+"661745\n"
+" 111\n"
+" 3\n",
+
+//////////////////////////////
+" /\n"
+" / \\\n"
+"<')_=<\n"
+" \\_/\n"
+" \\\n",
+
+" 2\n"
+" 1 1\n"
+"547166\n"
+" 111\n"
+" 3\n",
+
+//////////////////////////////
+" ,\\\n"
+">=('>\n"
+" '/\n",
+
+" 12\n"
+"66745\n"
+" 13\n",
+
+//////////////////////////////
+" /,\n"
+"<')=<\n"
+" \\`\n",
+
+" 21\n"
+"54766\n"
+" 31\n",
+
+//////////////////////////////
+" __\n"
+"\\/ o\\\n"
+"/\\__/\n",
+
+" 11\n"
+"61 41\n"
+"61111\n",
+
+//////////////////////////////
+" __\n"
+"/o \\/\n"
+"\\__/\\\n",
+
+" 11\n"
+"14 16\n"
+"11116\n"
+};
+
+ // # 1: body
+ // # 2: dorsal fin
+ // # 3: flippers
+ // # 4: eye
+ // # 5: mouth
+ // # 6: tailfin
+ // # 7: gills*
+ int fish_num = intRand(ARRAY_SIZE(fish_image)/2);
+ int fish_index = fish_num * 2;
+
+ double speed = doubleRand(2) + 0.25;
+ int depth = 3 + intRand(18);
+
+ TQString color_mask = fish_image[fish_index+1];
+ color_mask.replace('4', 'W');
+
+ color_mask = randColor(color_mask);
+
+ Frame fishFrame(fish_image[fish_index], color_mask, 0);
+ int max_height = 9;
+ int min_height = screen->height() - fishFrame.height();
+
+ int x, y, dir;
+ y = max_height + intRand(min_height - max_height);
+ if (fish_num % 2)
+ {
+ x = screen->width() - 2;
+ dir = -1;
+ }
+ else
+ {
+ x = 1 - fishFrame.width();
+ dir = 1;
+ }
+
+ Sprite* fish = new FishSprite(screen, dir, speed, x, y, depth);
+ fish->addFrame(fishFrame);
+
+ return fish;
+}
+
+void AASaver::addFish(Screen* screen)
+{
+ screen->addSprite(newFish(screen));
+}
+
+/**
+ * Sprite that represents a blood "splat" in the water.
+ */
+class Splat : public Sprite
+{
+public:
+ /**
+ * Constructor.
+ *
+ * @param screen The Screen to create the splat in.
+ * @param center The point to center the splat around.
+ * @param depth The depth to create the splat at.
+ */
+ Splat(Screen *screen, TQPoint center, int depth) :
+ Sprite(screen, 0, 0, depth, 450 /* frame Delay */)
+ {
+ TQString splats[] = {
+"\n"
+" .\n"
+" ***\n"
+" '\n"
+""
+,
+
+"\n"
+" \",*;`\n"
+" \"*,**\n"
+" *\"'~'\n"
+""
+,
+" , ,\n"
+" \" \",\"'\n"
+" *\" *'\"\n"
+" \" ; .\n"
+""
+,
+"* ' , ' `\n"
+"' ` * . '\n"
+" ' `' \",'\n"
+"* ' \" * .\n"
+"\" * ', '"
+ };
+
+ for(unsigned i = 0; i < ARRAY_SIZE(splats); ++i)
+ addFrame(Frame(splats[i], TQString(), 0xB21818, ' '));
+
+ TQRect r(center, TQSize(9, 5));
+ r.moveCenter(center);
+ m_x = r.x();
+ m_y = r.y();
+
+ setDieAfterLastFrame(true);
+ }
+};
+
+/**
+ * Invisible sprite which are created on a shark's teeth, to handle collisions
+ * with fish, creating splats and kill()'ing the fish.
+ */
+class TeethSprite : public MovingSprite
+{
+public:
+ /**
+ * Constructor. Copied parameters as appropriate from \p shark.
+ *
+ * @param shark The shark to create the teeth over.
+ */
+ TeethSprite(MovingSprite *shark) : MovingSprite(shark->screen(), shark->direction(),
+ shark->realSpeed(), 2 + shark->geom().left(), shark->geom().top(), shark->depth())
+ {
+ m_y += 7;
+ m_z -= 1;
+ m_realX = 2 + shark->realX();
+
+ if(m_direct > 0) // Moving to right.
+ m_realX = -10;
+
+ addFrame(Frame("????????", TQString(), 0));
+ }
+
+ /// Returns true since we can collide.
+ bool canCollide() const { return true; }
+
+ /**
+ * Reimplemented in order to handle collisions. When colliding with a
+ * FishSprite, the fish is kill()'ed and a splat is created in its place.
+ * Otherwise, nothing is done.
+ *
+ * @param sprite The Sprite we collided with.
+ */
+ void collision(Sprite *sprite)
+ {
+ if(dynamic_cast<FishSprite *>(sprite)) {
+ kdDebug() << "A fish just got killinated!\n";
+
+ sprite->erase();
+ sprite->kill();
+
+ screen()->addSprite(new Splat(screen(), sprite->geom().center(), depth() - 1));
+ }
+ }
+};
+
+void AASaver::addShark(Screen* screen)
+{
+ TQString shark_image[] = {
+" __\n"
+" ( `\\\n"
+" ,??????????????????????????" ") `\\\n" // trigraphs suck
+";' `.????????????????????????" "( `\\__\n" // trigraphs suck
+" ; `.?????????????__..---'' `~~~~-._\n"
+" `. `.____...--'' (b `--._\n"
+" > _.-' .(( ._ )\n"
+" .`.-`--...__ .-' -.___.....-(|/|/|/|/'\n"
+" ;.'?????????`. ...----`.___.',,,_______......---'\n"
+" '???????????" "'-'\n", // trigraphs suck
+
+" \n"
+" \n"
+" \n"
+" \n"
+" \n"
+" cR \n"
+" \n"
+" cWWWWWWWW \n"
+" \n"
+" \n",
+
+" __\n"
+" /' )\n"
+" /' (??????????????????????????,\n"
+" __/' )????????????????????????.' `;\n"
+" _.-~~~~' ``---..__?????????????.' ;\n"
+" _.--' b) ``--...____.' .'\n"
+"( _. )). `-._ <\n"
+" `\\|\\|\\|\\|)-.....___.- `-. __...--'-.'.\n"
+" `---......_______,,,`.___.'----... .'?????????`.;\n"
+" `-`???????????`\n",
+
+" \n"
+" \n"
+" \n"
+" \n"
+" \n"
+" Rc \n"
+" \n"
+" WWWWWWWWc \n"
+" \n"
+" \n"
+ };
+
+ int shark_num = intRand(ARRAY_SIZE(shark_image)/2);
+ int shark_index = shark_num * 2;
+ TQString color_mask = randColor(shark_image[shark_index+1]);
+ Frame sharkFrame(shark_image[shark_index], color_mask, 0x18B2B2);
+
+ int x = -53;
+ int y = 9 + intRand(screen->height() - (10 + 9));
+ int dir = (shark_num % 2) ? -1 : 1;
+
+ if(dir < 0)
+ x = screen->width() - 2;
+
+ RandomMovingSprite* shark = new RandomMovingSprite(screen, dir, 2, x, y, 2 /* Always at 2 */);
+ shark->addFrame(sharkFrame);
+ screen->addSprite(shark);
+
+ TeethSprite *teeth = new TeethSprite(shark);
+ screen->addSprite(teeth);
+}
+
+void AASaver::addBubble(Screen *screen, int x, int y, int z)
+{
+ screen->addSprite(new AirBubble(screen, x, y, z));
+}
+
+void AASaver::addShip(Screen* screen)
+{
+ TQString ship_image[] = {
+" | | |\n"
+" )_) )_) )_)\n"
+" )___))___))___)\\\n"
+" )____)____)_____)\\\\\n"
+"_____|____|____|____\\\\\\__\n"
+"\\ /",
+
+" y y y\n"
+" \n"
+" w\n"
+" ww\n"
+"yyyyyyyyyyyyyyyyyyyywwwyy\n"
+"y y",
+
+" | | |\n"
+" (_( (_( (_(\n"
+" /(___((___((___(\n"
+" //(_____(____(____(\n"
+"__///____|____|____|_____\n"
+" \\ /",
+
+" y y y\n"
+" \n"
+" w \n"
+" ww \n"
+"yywwwyyyyyyyyyyyyyyyyyyyy\n"
+" y y"
+ };
+
+ int ship_num = intRand(17) % 2; // right == 0, left == 1
+ int x = -24, dir = 1;
+
+ if(ship_num == 1) {
+ x = screen->width() - 2;
+ dir = -1;
+ }
+
+ RandomMovingSprite *ship = new RandomMovingSprite(screen, dir, 1.0, x, 0, 2);
+ ship->addFrame(Frame(ship_image[2 * ship_num], ship_image[2 * ship_num + 1], 0xFFFFFF));
+ screen->addSprite(ship);
+}
+
+void AASaver::addWhale(Screen* screen)
+{
+ TQString whale_image[] = {
+" .-----:\n"
+" .' `.\n"
+",????/ (o) \\\n"
+"\\`._/ ,__)",
+
+" C C\n"
+" CCCCCCC\n"
+" C C C\n"
+" BBBBBBB\n"
+" BB BB\n"
+"B B BWB B\n"
+"BBBBB BBBB",
+
+" :-----.\n"
+" .' `.\n"
+" / (o) \\????,\n"
+"(__, \\_.'/",
+
+" C C\n"
+" CCCCCCC\n"
+" C C C\n"
+" BBBBBBB\n"
+" BB BB\n"
+" B BWB B B\n"
+"BBBB BBBBB"
+ };
+
+ TQString spouty[] = {
+"\n"
+"\n"
+" :",
+
+"\n"
+" :\n"
+" :",
+
+" . .\n"
+" -:-\n"
+" :",
+
+" . .\n"
+" .-:-.\n"
+" :",
+
+" . .\n"
+"'.-:-.`\n"
+"' : '",
+
+"\n"
+" .- -.\n"
+"; : ;",
+
+"\n"
+"\n"
+"; ;"
+ };
+
+ int whale_num = intRand(2); // 0 = right, 1 = left
+ int x = -18, spout_align = 11, dir = 1;
+
+ if (whale_num == 1)
+ {
+ x = screen->width() - 2;
+ spout_align = 1; // Waterspout closer to left side now.
+ dir = -1;
+ }
+
+ TQString mask = whale_image[2 * whale_num + 1];
+
+ RandomMovingSprite *whale = new RandomMovingSprite(screen, dir, 1.0, x, 0, 2);
+ whale->setFrameDelay(80);
+ whale->setFrameTime(40);
+
+ // We have to add some frames now. The first five will have no water spout.
+ TQString blankWhaleFrame = TQString("\n\n\n") + whale_image[2 * whale_num];
+
+ for(unsigned i = 0; i < 5; ++i)
+ whale->addFrame(Frame(blankWhaleFrame, mask, 0xFFFFFF));
+
+ // Now add frames for the animated water spout.
+ TQString whaleFrame = whale_image[2 * whale_num];
+ for (unsigned i = 0; i < ARRAY_SIZE(spouty); ++i)
+ {
+ TQStringList spoutLines = TQStringList::split("\n", spouty[i], true);
+ TQString spout;
+ TQString padding;
+
+ padding.fill(' ', spout_align);
+
+ // Move spout over an appropriate distance to line up right.
+ for(TQStringList::ConstIterator it = spoutLines.begin(); it != spoutLines.end(); ++it)
+ {
+ spout += padding;
+ spout += *it;
+ spout += "\n";
+ }
+
+ // Add spout to whale frame.
+ whale->addFrame(Frame(spout + whaleFrame, mask, 0xFFFFFF));
+ }
+
+ screen->addSprite(whale);
+}
+
+void AASaver::addBigFish(Screen* screen)
+{
+ TQString big_fish_image[] = {
+" ______\n"
+"`\"\"-. `````-----.....__\n"
+" `. . . `-.\n"
+" : . . `.\n"
+" ,?????: . . _ :\n"
+": `.???: (@) `._\n"
+" `. `..' . =`-. .__)\n"
+" ; . = ~ : .-\"\n"
+" .' .'`. . . =.-' `._ .'\n"
+": .'???: . .'\n"
+" '???.' . . . .-'\n"
+" .'____....----''.'=.'\n"
+" \"\"?????????????.'.'\n"
+" ''\"'`",
+
+" 111111\n"
+"11111 11111111111111111\n"
+" 11 2 2 111\n"
+" 1 2 2 11\n"
+" 1 1 2 2 1 1\n"
+"1 11 1 1W1 111\n"
+" 11 1111 2 1111 1111\n"
+" 1 2 1 1 1 111\n"
+" 11 1111 2 2 1111 111 11\n"
+"1 11 1 2 11\n"
+" 1 11 2 2 2 111\n"
+" 111111111111111111111\n"
+" 11 1111\n"
+" 11111",
+
+" ______\n"
+" __.....-----''''' .-\"\"'\n"
+" .-' . . .'\n"
+" .' . . :\n"
+" : _ . . :?????,\n"
+" _.' (@) :???.' :\n"
+"(__. .-'= . `..' .'\n"
+" \"-. : ~ = . ;\n"
+" `. _.' `-.= . . .'`. `.\n"
+" `. . :???`. :\n"
+" `-. . . . `.???`\n"
+" `.=`.``----....____`.\n"
+" `.`.?????????????\"\"\n"
+" '`\"``",
+
+" 111111\n"
+" 11111111111111111 11111\n"
+" 111 2 2 11\n"
+" 11 2 2 1\n"
+" 1 1 2 2 1 1\n"
+" 111 1W1 1 11 1\n"
+"1111 1111 2 1111 11\n"
+" 111 1 1 1 2 1\n"
+" 11 111 1111 2 2 1111 11\n"
+" 11 2 1 11 1\n"
+" 111 2 2 2 11 1\n"
+" 111111111111111111111\n"
+" 1111 11\n"
+" 11111"
+ };
+
+ int big_fish_num = intRand(2); // right = 0, left = 1
+
+ int maxHeight = 9, minHeight = screen->height() - 15;
+ int y = intRand(minHeight - maxHeight) + maxHeight;
+ int x = -34, dir = 1;
+
+ if(big_fish_num == 1)
+ {
+ x = screen->width() - 1;
+ dir = -1;
+ }
+
+ TQString colors = randColor(big_fish_image[2 * big_fish_num + 1]);
+ RandomMovingSprite *bigFish = new RandomMovingSprite(screen, dir, 3.0, x, y, 2);
+ bigFish->addFrame(Frame(big_fish_image[2 * big_fish_num], colors, 0xFFFF54));
+
+ screen->addSprite(bigFish);
+}
+
+void AASaver::addNessie(Screen* screen)
+{
+ TQString nessie_image[] = {
+" ____\n"
+" __??????????????????????????????????????????/ o \\\n"
+" / \\????????_?????????????????????_???????/ ____ >\n"
+" _??????| __ |?????/ \\????????_????????/ \\????| |\n"
+" | \\?????| || |????| |?????/ \\?????| |???| |",
+
+" ____\n"
+" __?????????/ o \\\n"
+" _?????????????????????_???????/ \\?????/ ____ >\n"
+" _???????/ \\????????_????????/ \\????| __ |???| |\n"
+" | \\?????| |?????/ \\?????| |???| || |???| |\n",
+
+" ____\n"
+" __????????????????????/ o \\\n"
+" _??????????????????????_???????/ \\????????_???????/ ____ >\n"
+"| \\??????????_????????/ \\????| __ |?????/ \\????| |\n"
+" \\ \\???????/ \\?????| |???| || |????| |???| |",
+
+" ____\n"
+" __???????????????????????????????/ o \\\n"
+" _??????????_???????/ \\????????_??????????????????/ ____ >\n"
+" | \\???????/ \\????| __ |?????/ \\????????_??????| |\n"
+" \\ \\?????| |???| || |????| |?????/ \\????| |",
+
+" ____\n"
+" / o \\??????????????????????????????????????????__\n"
+"< ____ \\???????_?????????????????????_????????/ \\\n"
+" | |????/ \\????????_????????/ \\?????| __ |??????_\n"
+" | |???| |?????/ \\?????| |????| || |?????/ |",
+
+" ____\n"
+" / o \\?????????__\n"
+"< ____ \\?????/ \\???????_?????????????????????_\n"
+" | |???| __ |????/ \\????????_????????/ \\???????_\n"
+" | |???| || |???| |?????/ \\?????| |?????/ |",
+
+" ____\n"
+" / o \\????????????????????__\n"
+"< ____ \\???????_????????/ \\???????_??????????????????????_\n"
+" | |????/ \\?????| __ |????/ \\????????_??????????/ |\n"
+" | |???| |????| || |???| |?????/ \\???????/ /",
+
+" ____\n"
+" / o \\???????????????????????????????__\n"
+"< ____ \\??????????????????_????????/ \\???????_??????????_\n"
+" | |??????_????????/ \\?????| __ |????/ \\???????/ |\n"
+" | |????/ \\?????| |????| || |???| |?????/ /"
+ };
+
+ TQString nessie_mask[] = {
+"\n"
+" W\n"
+"\n"
+"\n"
+"\n"
+"",
+
+"\n"
+" W\n"
+"\n"
+"\n"
+"\n"
+""
+ };
+
+ int nessie_num = intRand(2); // 0 = right, 1 = left.
+ int x = -64, dir = 1;
+
+ if(nessie_num == 1) {
+ x = screen->width() - 2;
+ dir = -1;
+ }
+
+ RandomMovingSprite *nessie = new RandomMovingSprite(screen, dir, 1.4, x, 2, 2);
+ nessie->setFrameDelay(75);
+ nessie->setFrameTime(400);
+
+ for(unsigned i = 0; i < 4; ++i)
+ nessie->addFrame(Frame(nessie_image[nessie_num * 4 + i], nessie_mask[nessie_num], 0x18B218));
+
+ screen->addSprite(nessie);
+}
+
+void AASaver::addRandom(Screen* screen)
+{
+ const char *const cute_messages[] = {
+ "Quick, someone cue the ominous music!",
+ "Her continuing mission... to explore strange new seas...",
+ "I caught one that big once, but it got away. :(",
+ "Nessie, an Earthbound hero's best friend...",
+ "Thar be WHALES, Cap'n!!"
+ };
+ int choice = intRand(5);
+
+ if(intRand(45) < 7 && choice < ARRAY_SIZE(cute_messages))
+ kdDebug() << cute_messages[choice] << endl;
+
+ switch(choice)
+ {
+ case 0:
+ addShark(screen);
+ break;
+ case 1:
+ addShip(screen);
+ break;
+ case 2:
+ addBigFish(screen);
+ break;
+ case 3:
+ addNessie(screen);
+ break;
+ case 4:
+ addWhale(screen);
+ break;
+ }
+}
+
+void AASaver::paintEvent(TQPaintEvent* pe)
+{
+ screen->paint(pe->region());
+}
+
+// libkscreensaver interface
+extern "C"
+{
+ KDE_EXPORT const char *kss_applicationName = "tdeasciiquarium.kss";
+ KDE_EXPORT const char *kss_description = I18N_NOOP( "TDEAsciiquarium" );
+ KDE_EXPORT const char *kss_version = "0.3.2";
+
+ KDE_EXPORT KScreenSaver *kss_create( WId id )
+ {
+ return new AASaver( id );
+ }
+
+ KDE_EXPORT TQDialog *kss_setup()
+ {
+ TDEConfigDialog *dialog = TDEConfigDialog::exists("settings");
+ if(dialog)
+ return dialog;
+
+ dialog = new TDEConfigDialog(0, "settings", AASaverConfig::self());
+ SettingsWidget *settings = new SettingsWidget(0, "settings_widget");
+
+ dialog->addPage(settings, i18n("TDEAsciiquarium Settings"), "tdescreensaver");
+
+ return dialog;
+ }
+}