Commit 3c4c2c2c authored by Roney Gomes's avatar Roney Gomes

Borders are now drawn in a different manner, avoiding painting at the...

Borders are now drawn in a different manner, avoiding painting at the construction stage and taking control of the order in which things are done.

svn path=/branches/work/kgoldrunner-qgv/; revision=1307938
parent 7cabb337
......@@ -187,7 +187,6 @@ void KGoldrunner::KGoldrunner_2()
KGoldrunner::~KGoldrunner()
{
delete m_scene;
}
void KGoldrunner::setupActions()
......
......@@ -52,20 +52,6 @@ const int STEP = 4;
const int gameCycle = 4; // Animation frames per playfield tile.
const int graphicsCycle = 8; // Animation frames per running cycle.
// Indexes for the first and last tiles for each side of the background border
// in the list generated by KGrRenderer::borderTiles().
const int TOP_BORDER_BEGIN = 4;
const int TOP_BORDER_END = 31;
const int BOTTOM_BORDER_BEGIN = 32;
const int BOTTOM_BORDER_END = 59;
const int LEFT_BORDER_BEGIN = 60;
const int LEFT_BORDER_END = 79;
const int RIGHT_BORDER_BEGIN = 80;
const int RIGHT_BORDER_END = 99;
// Keyboard action codes
enum KBAction {KB_UP, KB_DOWN, KB_LEFT, KB_RIGHT,
KB_DIGLEFT, KB_DIGRIGHT, KB_STOP};
......
......@@ -74,11 +74,8 @@ KGrRenderer::KGrRenderer (KGrScene * scene)
connect (m_setProvider, SIGNAL(currentThemeChanged(const KgTheme*)),
this, SLOT(currentThemeChanged(const KgTheme*)));
connect (m_setProvider, SIGNAL(currentThemeChanged(const KgTheme *)),
m_scene, SLOT(currentThemeChanged(const KgTheme *)));
// Match the starting SVG theme for the Actors to the one for the Set.
currentThemeChanged (m_setProvider->currentTheme());
matchThemes (m_setProvider->currentTheme());
}
KGrRenderer::~KGrRenderer()
......@@ -86,15 +83,11 @@ KGrRenderer::~KGrRenderer()
delete m_themeSelector;
}
void KGrRenderer::currentThemeChanged (const KgTheme* currentSetTheme)
void KGrRenderer::matchThemes (const KgTheme * currentSetTheme)
{
qDebug() << "KGrRenderer::currentThemeChanged()";
// Start of game or change of theme: initialise the counts of pixmap keys.
initPixmapKeys();
// Make the Actors theme (hero, etc.) match the Set theme (bricks, etc.).
// qDebug() << "KGrRenderer::currentThemeChanged()" << currentSetTheme->name();
foreach (const KgTheme * actorsTheme, m_actorsProvider->themes()) {
if (actorsTheme->customData("Set") ==
currentSetTheme->customData("Set")) {
......@@ -102,14 +95,14 @@ void KGrRenderer::currentThemeChanged (const KgTheme* currentSetTheme)
break;
}
}
}
// Save the KGoldrunner attributes of the current theme.
QString s = currentSetTheme->customData("DrawCanvasBorder", "0");
m_hasBorder = (s == QString ("1"));
s = currentSetTheme->customData("BorderColor", "#000000");
m_borderColor = QColor (s);
s = currentSetTheme->customData("TextColor", "#FFFFFF");
m_textColor = QColor (s);
void KGrRenderer::currentThemeChanged (const KgTheme* currentSetTheme)
{
qDebug() << "KGrRenderer::currentThemeChanged()" << currentSetTheme->name();
matchThemes (currentSetTheme);
m_scene->changeTheme();
}
void KGrRenderer::selectTheme()
......@@ -175,40 +168,48 @@ KGameRenderedItem * KGrRenderer::getBackground
QString key = getBackgroundKey (level);
KGameRenderedItem * background = new KGameRenderedItem (m_setRenderer, key);
m_scene->addItem (background);
return background;
}
QList <KGameRenderedItem *> KGrRenderer::borderTiles() const
KGameRenderedItem * KGrRenderer::getBorderItem
(QString spriteKey, KGameRenderedItem * currentItem)
{
qDebug() << "KGrRenderer::borderTiles()";
qDebug() << "m_setRenderer:" << m_setRenderer;
QList <KGameRenderedItem *> list;
if (currentItem) {
m_scene->removeItem (currentItem);
delete currentItem;
}
// Corners.
list.append (new KGameRenderedItem (m_setRenderer, "frame-topleft"));
list.append (new KGameRenderedItem (m_setRenderer, "frame-topright"));
list.append (new KGameRenderedItem (m_setRenderer, "frame-bottomleft"));
list.append (new KGameRenderedItem (m_setRenderer, "frame-bottomright"));
if (!hasBorder()) {
return 0;
}
// Upper side.
for (int i = 0; i < FIELDWIDTH; i++)
list.append (new KGameRenderedItem (m_setRenderer, "frame-top"));
KGameRenderedItem * item = new KGameRenderedItem (m_setRenderer, spriteKey);
m_scene->addItem (item);
return item;
}
// Lower side.
for (int i = 0; i < FIELDWIDTH; i++)
list.append (new KGameRenderedItem (m_setRenderer, "frame-bottom"));
bool KGrRenderer::hasBorder() const
{
QString s = m_setRenderer->theme()->customData("DrawCanvasBorder", "0");
// Left side.
for (int i = 0; i < FIELDHEIGHT; i++)
list.append (new KGameRenderedItem (m_setRenderer, "frame-left"));
if (s == "1")
return true;
else
return false;
}
// Right side.
for (int i = 0; i < FIELDHEIGHT; i++)
list.append (new KGameRenderedItem (m_setRenderer, "frame-right"));
QColor KGrRenderer::borderColor() const
{
QString s = m_setRenderer->theme()->customData("BorderColor", "#000000");
return QColor (s);
}
return list;
QColor KGrRenderer::textColor() const
{
QString s = m_setRenderer->theme()->customData("TextColor", "#FFFFFF");
return QColor (s);
}
QString KGrRenderer::getPixmapKey (const char picType, const int index)
......
/****************************************************************************
* Copyright 2012 Ian Wadham <iandw.au@gmail.com> *
* Copyright 2012 Ian Wadham <iandw.au@gmail.com> *
* Copyright 2012 Roney Gomes <roney477@gmail.com> *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License as *
......@@ -95,29 +96,33 @@ public:
KGameRenderedItem * getBackground (const int level,
KGameRenderedItem * currentBackground);
/*
* Create the QGraphicsScene item for a border tile.
*
* @param spriteKey The name of the sprite which will be rendered.
* @param currentItem The pre-existing item that is to be replaced, or
* zero if the previous theme had no border.
*/
KGameRenderedItem * getBorderItem (QString spriteKey,
KGameRenderedItem * currentItem);
/*
* Returns true case the current theme has a border around its background
* and false otherwise.
*/
bool hasBorder() const { return m_hasBorder; }
bool hasBorder() const;
/*
* Get the color of the scene's background brush requested for the current
* theme.
*/
QColor borderColor() const { return m_borderColor; }
QColor borderColor() const;
/*
* Get the color of the on-screen text which appears in certain game stages
* (the demo stage for instance) and in the score box.
*/
QColor textColor() const { return m_textColor; }
QColor textColor() const;
/*
* Get a list containing all the KGameRenderedItem's which make up the
* theme's border.
*/
QList <KGameRenderedItem * > borderTiles() const;
public slots:
/*
* Show the theme-selector dialog. When the theme changes, KGrRenderer uses
......@@ -154,24 +159,22 @@ private:
KgThemeSelector * m_themeSelector; // Selector (dialog) for themes.
bool m_hasBorder; // Whether the theme has a border or the
// background pixmap fills the view.
QColor m_borderColor; // The color of the theme's border.
QColor m_textColor; // The color of the theme's text.
KGameRenderer * m_setRenderer; // Renderer for Set SVG files.
KGameRenderer * m_actorsRenderer; // Renderer for Actors SVG files.
static PixmapSpec keyTable []; // Table of tile/background specs.
// Set the frame counts to -2 at startup and when the theme changes.
void initPixmapKeys();
void initPixmapKeys();
// Make the Actors theme (hero, etc.) match the Set theme (bricks, etc.).
void matchThemes (const KgTheme * currentSetTheme);
// Find a tile type or background in the table of tiles and backgrounds.
int findKeyTableIndex (const char picType);
int findKeyTableIndex (const char picType);
// Count the number of variants of a tile or background.
int countFrames (const int index);
int countFrames (const int index);
/*
* Get the SVG element name for a KGoldrunner tile type. If the theme has
......@@ -186,7 +189,7 @@ private:
* more than one background, cycle though the choices as the KGoldrunner
* game's level changes.
*
* @param level The current level in a KGoldrunner game.
* @param level The current level in a KGoldrunner game.
*/
QString getBackgroundKey (const int level);
};
......
/****************************************************************************
* Copyright 2012 Ian Wadham <iandw.au@gmail.com> *
* Copyright 2012 Roney Gomes <roney477@gmail.com> *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License as *
......@@ -36,14 +36,11 @@ KGrScene::KGrScene (QObject * parent)
m_background (0),
m_tilesWide (FIELDWIDTH + 2 * 2),
m_tilesHigh (FIELDHEIGHT + 2 * 2),
m_tileSize (10)
m_tileSize (10),
m_themeChanged (true)
{
m_renderer = new KGrRenderer (this);
setBackgroundBrush (m_renderer->borderColor());
if (m_renderer->hasBorder())
drawBorder();
m_tiles.fill (0, m_tilesWide * m_tilesHigh);
}
KGrScene::~KGrScene()
......@@ -52,44 +49,54 @@ KGrScene::~KGrScene()
void KGrScene::redrawScene ()
{
// Calculate what size of tile will fit in the view.
QSize size = views().at(0)->size();
int tileSize = qMin (size.width()/m_tilesWide, size.height()/m_tilesHigh);
qreal unusedX = (size.width() - m_tilesWide * tileSize)/2.0;
qreal unusedY = (size.height() - m_tilesHigh * tileSize)/2.0;
unusedX = unusedX / tileSize; // Fraction of a tile at L and R.
unusedY = unusedY / tileSize; // Fraction of a tile at T and B.
setSceneRect (-1.0 - unusedX, -1.0 - unusedY,
m_tilesWide + 2.0 * unusedX, m_tilesHigh + 2.0 * unusedY);
loadBackground(1); // Test level 1.
// Checks wether the background and all the other visual elements need to be
// resized.
if (tileSize != m_tileSize) {
m_background->setRenderSize (QSize ((m_tilesWide - 4) * tileSize,
(m_tilesHigh - 4) * tileSize));
m_background->setScale (1.0 / tileSize);
if (!borderElements.isEmpty()) {
foreach (KGameRenderedItem * item, borderElements)
setTileSize (item, tileSize);
if (m_sizeChanged) {
// Calculate what size of tile will fit in the view.
QSize size = views().at(0)->size();
int tileSize = qMin (size.width() / m_tilesWide,
size.height() / m_tilesHigh);
qreal unusedX = (size.width() - m_tilesWide * tileSize)/2.0;
qreal unusedY = (size.height() - m_tilesHigh * tileSize)/2.0;
unusedX = unusedX / tileSize; // Fraction of a tile at L and R.
unusedY = unusedY / tileSize; // Fraction of a tile at T and B.
setSceneRect (-1.0 - unusedX, -1.0 - unusedY,
m_tilesWide + 2.0 * unusedX, m_tilesHigh + 2.0 * unusedY);
foreach (KGameRenderedItem * tile, m_tiles) {
if (tile) {
setTileSize (tile, tileSize);
}
}
m_sizeChanged = false;
m_tileSize = tileSize;
}
m_background->setPos (1, 1);
// NOTE: This is for testing only. As long as the scene is not connected to
// the game engine loadBackground() will behave this way.
loadBackground (1);
if (m_themeChanged) {
// Fill the scene (and view) with the new background color. Do this
// even if the background has no border, to avoid ugly white rectangles
// appearing if rendering and painting is momentarily a bit slow.
setBackgroundBrush (m_renderer->borderColor());
drawBorder();
m_themeChanged = false;
}
}
void KGrScene::currentThemeChanged (const KgTheme *)
void KGrScene::changeTheme()
{
if (m_renderer->hasBorder())
drawBorder();
m_themeChanged = true;
redrawScene();
}
// Fill the scene (and view) with the new background color. Do this even if
// the background has no border, to avoid ugly white rectangles appearing
// if rendering and painting is momentarily a bit slow.
setBackgroundBrush (m_renderer->borderColor());
void KGrScene::changeSize()
{
m_sizeChanged = true;
redrawScene();
}
......@@ -97,11 +104,13 @@ void KGrScene::loadBackground (const int level)
{
// NOTE: The background picture can be the same size as the level-layout (as
// in the Egypt theme) OR it can be the same size as the entire viewport.
if (m_tiles.count() == 0) {
// In this example the background is fitted into the level-layout.
m_background = m_renderer->getBackground (level, m_background);
addItem(m_background);
}
// In this example the background is fitted into the level-layout.
m_background = m_renderer->getBackground (level, m_background);
m_background->setRenderSize (QSize ((m_tilesWide - 4) * m_tileSize,
(m_tilesHigh - 4) * m_tileSize));
m_background->setPos (1, 1);
m_background->setScale (1.0 / m_tileSize);
}
void KGrScene::setTileSize (KGameRenderedItem * tile, const int tileSize)
......@@ -110,77 +119,42 @@ void KGrScene::setTileSize (KGameRenderedItem * tile, const int tileSize)
tile->setScale (1.0 / tileSize);
}
void KGrScene::drawBorder()
void KGrScene::setBorderTile (const QString spriteKey, const int x, const int y)
{
foreach (KGameRenderedItem * item, borderElements) {
removeItem (item);
delete item;
int index = x * m_tilesHigh + y;
KGameRenderedItem * t = m_renderer->getBorderItem (spriteKey,
m_tiles.at(index));
m_tiles[index] = t;
if (t) {
setTileSize (t, m_tileSize);
t->setPos (x, y);
}
}
borderElements.clear();
borderElements = m_renderer->borderTiles();
KGameRenderedItem * item;
// Top-left corner.
item = borderElements.at(0);
addItem (item);
item->setPos(0, 0);
// Top-right corner.
item = borderElements.at(1);
addItem (item);
item->setPos(FIELDWIDTH + 1, 0);
// Bottom-left corner.
item = borderElements.at(2);
addItem (item);
item->setPos(0, FIELDHEIGHT + 1);
// Bottom-right corner.
item = borderElements.at(3);
addItem (item);
item->setPos(FIELDWIDTH + 1, FIELDHEIGHT + 1);
// Defines either the x or y coordinate of a border tile. In each loop its
// value follows the sequence {1, 2, 3, ...}.
int pos;
// Adds the top side tiles to the scene.
for (int i = TOP_BORDER_BEGIN; i <= TOP_BORDER_END; i++) {
item = borderElements.at(i);
pos = (i - TOP_BORDER_BEGIN) + 1;
addItem (item);
item->setPos (pos, 0);
}
// Adds the bottom side tiles to the scene.
for (int i = BOTTOM_BORDER_BEGIN; i <= BOTTOM_BORDER_END; i++) {
item = borderElements.at(i);
pos = (i - BOTTOM_BORDER_BEGIN) + 1;
addItem (item);
item->setPos (pos, FIELDHEIGHT + 1);
}
// Adds the left side tiles to the scene.
for (int i = LEFT_BORDER_BEGIN; i <= LEFT_BORDER_END; i++) {
item = borderElements.at(i);
pos = (i - LEFT_BORDER_BEGIN) + 1;
addItem (item);
item->setPos (0, pos);
}
// Adds the right side tiles to the scene.
for (int i = RIGHT_BORDER_BEGIN; i <= RIGHT_BORDER_END; i++) {
item = borderElements.at(i);
pos = (i - RIGHT_BORDER_BEGIN) + 1;
addItem (item);
item->setPos (FIELDWIDTH + 1, pos);
}
void KGrScene::drawBorder()
{
// Corners.
setBorderTile ("frame-topleft", 0, 0);
setBorderTile ("frame-topright", FIELDWIDTH + 1, 0);
setBorderTile ("frame-bottomleft", 0, FIELDHEIGHT + 1);
setBorderTile ("frame-bottomright", FIELDWIDTH + 1, FIELDHEIGHT + 1);
// Upper side.
for (int i = 1; i <= FIELDWIDTH; i++)
setBorderTile ("frame-top", i, 0);
// Lower side.
for (int i = 1; i <= FIELDWIDTH; i++)
setBorderTile ("frame-bottom", i, FIELDHEIGHT + 1);
// Left side.
for (int i = 1; i <= FIELDHEIGHT; i++)
setBorderTile ("frame-left", 0, i);
// Right side.
for (int i = 1; i <= FIELDHEIGHT; i++)
setBorderTile ("frame-right", FIELDWIDTH + 1, i);
}
#include "kgrscene.moc"
/****************************************************************************
* Copyright 2012 Ian Wadham <iandw.au@gmail.com> *
* Copyright 2012 Roney Gomes <roney477@gmail.com> *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License as *
......@@ -63,26 +63,56 @@ public:
~KGrScene ();
/*
* Resize the scene and its contents depending on the size of its primary
* viewport.
* Redraw the scene whenever the current theme has changed.
*/
void redrawScene ();
void changeTheme ();
/*
* Requests the KGameRenderedItem's which make up the fancy border around
* the background and set their position accordingly.
* Redraw the scene whenever the scene is resized.
*/
void drawBorder();
void changeSize ();
/*
* Get a pointer to scene's renderer.
* Get a pointer to the scene's renderer.
*/
KGrRenderer * renderer () const { return m_renderer; }
public slots:
void currentThemeChanged(const KgTheme *);
KGrRenderer * renderer () const { return m_renderer; }
private:
/*
* Actions performed whenever the viewport is resized or a different theme
* is loaded.
*/
void redrawScene ();
/*
* Load and set the size and position of the KGameRenderedItem's which make
* up the border layout.
*/
void drawBorder ();
/*
* Load and set the size and position of the background image for the
* current level.
*
* @param level The current level.
*/
void loadBackground (const int level);
void setTileSize (KGameRenderedItem * tile, const int tileSize);
/*
* Add a new element, with coordinates x and y, to the border-layout.
*
* @param spriteKey The sprite key of the requested item.
* @param x The item's x coordinate.
* @param y The item's y coordinate.
*/
void setBorderTile (const QString spriteKey, const int x, const int y);
/*
* Resize a game's visual element.
*
* @param tile The element to be resized.
* @param tileSize The new size.
*/
void setTileSize (KGameRenderedItem * tile, const int tileSize);
KGrRenderer * m_renderer;
KGameRenderedItem * m_background;
......@@ -91,8 +121,12 @@ private:
int m_tilesHigh;
int m_tileSize;
QVector<KGameRenderedItem *> m_tiles; // The items of the scenario.
QList< KGameRenderedItem * > borderElements; // The items of the border.
bool m_sizeChanged;
bool m_themeChanged;
// The visible elements of the scenario (tiles and borders), excluding the
// background picture.
QVector <KGameRenderedItem *> m_tiles;
};
#endif // KGRSCENE_H
/****************************************************************************
* Copyright 2012 Ian Wadham <iandw.au@gmail.com> *
* Copyright 2012 Roney Gomes <roney477@gmail.com> *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License as *
......@@ -41,7 +41,7 @@ void KGrView::keyReleaseEvent (QKeyEvent * event)
void KGrView::resizeEvent (QResizeEvent * event)
{
if (scene() != 0) {
m_scene->redrawScene ();
m_scene->changeSize ();
fitInView (scene()->sceneRect(), Qt::KeepAspectRatio);
}
}
/****************************************************************************
* Copyright 2012 Ian Wadham <iandw.au@gmail.com> *
* Copyright 2012 Roney Gomes <roney477@gmail.com> *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License as *
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment