Original Post
Hi, I'm running this in Ubuntu 13.04. This is my compiler version:
$ g++ --version
g++ (Ubuntu/Linaro 4.7.3-1ubuntu1) 4.7.3
Copyright (C) 2012 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. This is the error that I'm getting (and I'm not sure why): $ g++ main.cpp main.h shape.cpp shape.h tetris.cpp tetris.h board.cpp board.h `wx-config --libs` `wx-config --cxxflags` -o main
/tmp/ccXvWFjZ.o: In function `Shape::RotateLeft() const':
shape.cpp:(.text+0x29d): undefined reference to `Shape::y(int) const'
shape.cpp:(.text+0x2b3): undefined reference to `Shape::SetX(int, int)'
shape.cpp:(.text+0x2c5): undefined reference to `Shape::x(int) const'
shape.cpp:(.text+0x2dd): undefined reference to `Shape::SetY(int, int)'
/tmp/ccXvWFjZ.o: In function `Shape::RotateRight() const':
shape.cpp:(.text+0x3b3): undefined reference to `Shape::y(int) const'
shape.cpp:(.text+0x3cb): undefined reference to `Shape::SetX(int, int)'
shape.cpp:(.text+0x3dd): undefined reference to `Shape::x(int) const'
shape.cpp:(.text+0x3f3): undefined reference to `Shape::SetY(int, int)'
/tmp/ccXSXGaN.o: In function `Board::OnPaint(wxPaintEvent&)':
board.cpp:(.text+0x62f): undefined reference to `Shape::GetShape() const'
board.cpp:(.text+0x66f): undefined reference to `Shape::x(int) const'
board.cpp:(.text+0x69b): undefined reference to `Shape::y(int) const'
board.cpp:(.text+0x6b3): undefined reference to `Shape::GetShape() const'
/tmp/ccXSXGaN.o: In function `Board::OnKeyDown(wxKeyEvent&)':
board.cpp:(.text+0x780): undefined reference to `Shape::GetShape() const'
/tmp/ccXSXGaN.o: In function `Board::PieceDropped()':
board.cpp:(.text+0xaee): undefined reference to `Shape::x(int) const'
board.cpp:(.text+0xb14): undefined reference to `Shape::y(int) const'
board.cpp:(.text+0xb48): undefined reference to `Shape::GetShape() const'
/tmp/ccXSXGaN.o: In function `Board::TryMove(Shape const&, int, int)':
board.cpp:(.text+0xeac): undefined reference to `Shape::x(int) const'
board.cpp:(.text+0xec8): undefined reference to `Shape::y(int) const'
collect2: error: ld returned 1 exit status This is the code listed: shape.h: #ifndef __SHAPE_H__
#define __SHAPE_H__
#include
#include
using namespace std;
enum Tetrominoes { NoShape, ZShape, SShape, LineShape, TShape, SquareShape,
LShape, MirroredLShape };
class Shape
{
public:
Shape();
void SetShape(Tetrominoes shape);
void SetRandomShape();
Tetrominoes GetShape() const;
int x(int index) const;
int y(int index) const;
int MinX() const;
int MinY() const;
int MaxX() const;
int MaxY() const;
Shape RotateLeft() const;
Shape RotateRight() const;
private:
void SetX(int index, int x);
void SetY(int index, int y);
Tetrominoes pieceShape;
int coords[4][2];
};
#endif shape.cpp: #include "shape.h"
Shape::Shape()
{
this -> SetShape(NoShape);
}
void Shape::SetShape(Tetrominoes shape)
{
static const int coordsTable[8][4][2] =
{
{ {0, 0}, {0, 0}, {0, 0}, {0, 0} },
{ {0, -1}, {0, 0}, {-1, 0}, {-1, 1} },
{ {0, -1}, {0, 0}, {1, 0}, {1, 1} },
{ {0, -1}, {0, 0}, {0, 1}, {0, 2} },
{ {-1, 0}, {0, 0}, {1, 0}, {0, 1} },
{ {0, 0}, {1, 0}, {0, 1}, {1, 1} },
{ {-1, -1}, {0, -1}, {0, 0}, {0, 1} },
{ {1, -1}, {0, -1}, {0, 0}, {0, 1} }
};
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 2; j++)
{
coords[i][j] = coordsTable[shape][i][j];
}
}
pieceShape = shape;
}
void Shape::SetRandomShape()
{
int x = rand() % 7 + 1;
SetShape(Tetrominoes(x));
}
int Shape::MinX() const
{
int m = coords[0][0];
for (int i = 0; i < 4; i++)
{
m = min(m, coords[i][0]);
}
return m;
}
int Shape::MaxX() const
{
int m = coords[0][0];
for (int i = 0; i < 4; i++)
{
m = max(m, coords[i][0]);
}
return m;
}
int Shape::MinY() const
{
int m = coords[0][1];
for (int i = 0; i < 4; i++)
{
m = min(m, coords[i][1]);
}
return m;
}
int Shape::MaxY() const
{
int m = coords[0][1];
for (int i = 0; i < 4; i++)
{
m = max(m, coords[i][1]);
}
return m;
}
Shape Shape::RotateLeft() const
{
if (SquareShape == pieceShape)
{
return ( * this);
}
Shape result;
result.pieceShape = pieceShape;
for (int i = 0; i < 4; i++)
{
result.SetX(i, y(i));
result.SetY(i, -x(i));
}
return result;
}
Shape Shape::RotateRight() const
{
if (SquareShape == pieceShape)
{
return ( * this);
}
Shape result;
result.pieceShape = pieceShape;
for (int i = 0; i < 4; i++)
{
result.SetX(i, -y(i));
result.SetY(i, x(i));
}
return result;
} board.h: #ifndef __BOARD_H__
#define __BOARD_H__
#include "shape.h"
#include
class Board : public wxPanel
{
public:
Board(wxFrame * parent);
void Start();
void Pause();
void linesRemovedChanged(int numLines);
protected:
void OnPaint(wxPaintEvent & event);
void OnKeyDown(wxKeyEvent & event);
void OnTimer(wxCommandEvent & event);
private:
enum { BoardWidth = 10, BoardHeight = 22 };
Tetrominoes & ShapeAt(int x, int y);
int SquareWidth();
int SquareHeight();
void ClearBoard();
void DropDown();
void OneLineDown();
void PieceDropped();
void RemoveFullLines();
void NewPiece();
bool TryMove(const Shape & newPiece, int newX, int newY);
void DrawSquare(wxPaintDC & dc, int x, int y, Tetrominoes shape);
wxTimer * timer;
bool isStarted;
bool isPaused;
bool isFallingFinished;
Shape curPiece;
int curX;
int curY;
int numLinesRemoved;
Tetrominoes board[BoardWidth * BoardHeight];
wxStatusBar * m_stsbar;
};
#endif board.cpp: #include "board.h"
Board::Board(wxFrame * parent)
: wxPanel(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxBORDER_NONE)
{
timer = new wxTimer(this, 1);
m_stsbar = parent -> GetStatusBar();
isFallingFinished = false;
isStarted = false;
isPaused = false;
numLinesRemoved = 0;
curX = 0;
curY = 0;
ClearBoard();
Connect(wxEVT_PAINT, wxPaintEventHandler(Board::OnPaint));
Connect(wxEVT_KEY_DOWN, wxKeyEventHandler(Board::OnKeyDown));
Connect(wxEVT_TIMER, wxCommandEventHandler(Board::OnTimer));
}
int Board::SquareWidth()
{
return GetClientSize().GetWidth() / BoardWidth;
}
int Board::SquareHeight()
{
return GetClientSize().GetHeight() / BoardHeight;
}
Tetrominoes & Board::ShapeAt(int x, int y)
{
return board[(y * BoardWidth) + x];
}
void Board::Start()
{
if (isPaused)
{
return;
}
isStarted = true;
isFallingFinished = false;
numLinesRemoved = 0;
ClearBoard();
NewPiece();
timer -> Start(300, wxTIMER_CONTINUOUS);
}
void Board::Pause()
{
if (!isPaused)
{
return;
}
isPaused = !isPaused;
if (isPaused)
{
timer -> Stop();
m_stsbar -> SetStatusText(wxT("paused"));
}
else
{
timer -> Start(300, wxTIMER_CONTINUOUS);
wxString str;
str.Printf(wxT("%d"), numLinesRemoved);
m_stsbar -> SetStatusText(str);
}
Refresh();
}
void Board::OnPaint(wxPaintEvent & event)
{
wxPaintDC dc(this);
wxSize size = GetClientSize();
int boardTop = size.GetHeight() - BoardHeight * SquareHeight();
for (int i = 0; i < BoardHeight; ++i)
{
for (int j = 0; j < BoardWidth; ++j)
{
Tetrominoes shape = ShapeAt(j, BoardHeight - i - 1);
if (shape != NoShape)
{
DrawSquare(dc, 0 + j * SquareWidth(), boardTop + i * SquareHeight(),
shape);
}
}
}
if (curPiece.GetShape() != NoShape)
{
for (int i = 0; i < 4; i++)
{
int x = curX + curPiece.x(i);
int y = curY + curPiece.y(i);
DrawSquare(dc, 0 + x * SquareWidth(),
boardTop + (BoardHeight - y - 1) * SquareHeight(),
curPiece.GetShape());
}
}
}
void Board::OnKeyDown(wxKeyEvent & event)
{
if (NoShape == (!isStarted || curPiece.GetShape()))
{
event.Skip();
return;
}
int keycode = event.GetKeyCode();
if ('p' == keycode || 'P' == keycode)
{
Pause();
return;
}
if (isPaused)
{
return;
}
switch (keycode)
{
case WXK_LEFT:
TryMove(curPiece, curX - 1, curY);
break;
case WXK_RIGHT:
TryMove(curPiece, curX + 1, curY);
break;
case WXK_DOWN:
TryMove(curPiece.RotateRight(), curX, curY);
break;
case WXK_UP:
TryMove(curPiece.RotateLeft(), curX, curY);
break;
case WXK_SPACE:
DropDown();
break;
case 'd':
OneLineDown();
break;
case 'D':
OneLineDown();
break;
default:
event.Skip();
};
}
void Board::OnTimer(wxCommandEvent & event)
{
if (isFallingFinished)
{
isFallingFinished = false;
NewPiece();
}
else
{
OneLineDown();
}
}
void Board::ClearBoard()
{
for (int i = 0; i < BoardHeight * BoardWidth; ++i)
{
board[i] = NoShape;
}
}
void Board::DropDown()
{
int newY = curY;
while (newY > 0)
{
if (!TryMove(curPiece, curX, newY - 1))
{
break;
}
--newY;
}
PieceDropped();
}
void Board::OneLineDown()
{
if (!TryMove(curPiece, curX, curY - 1))
{
PieceDropped();
}
}
void Board::PieceDropped()
{
for (int i = 0; i < 4; i++)
{
int x = curX + curPiece.x(i);
int y = curY - curPiece.y(i);
ShapeAt(x, y) = curPiece.GetShape();
}
RemoveFullLines();
if (!isFallingFinished)
{
NewPiece();
}
}
void Board::RemoveFullLines()
{
int numFullLines = 0;
for (int i = BoardHeight - 1; i >= 0; --i)
{
bool lineIsFull = true;
for (int j = 0; j < BoardWidth; ++j)
{
if (ShapeAt(j, i) == NoShape)
{
lineIsFull = false;
break;
}
}
if (lineIsFull)
{
++numFullLines;
for (int k = i; k < BoardHeight - 1; ++k)
{
for (int j = 0; j < BoardWidth; ++j)
{
ShapeAt(j, k) = ShapeAt(j, k + 1);
}
}
}
}
if (numFullLines > 0)
{
numLinesRemoved += numFullLines;
wxString str;
str.Printf(wxT("%d"), numLinesRemoved);
m_stsbar -> SetStatusText(str);
isFallingFinished = true;
curPiece.SetShape(NoShape);
Refresh();
}
}
void Board::NewPiece()
{
curPiece.SetRandomShape();
curX = BoardWidth / 2 + 1;
curY = BoardHeight - 1 + curPiece.MinY();
if (!TryMove(curPiece, curX, curY))
{
curPiece.SetShape(NoShape);
timer -> Stop();
isStarted = false;
m_stsbar -> SetStatusText(wxT("Game Over"));
}
}
bool Board::TryMove(const Shape & newPiece, int newX, int newY)
{
for (int i = 0; i < 4; i++)
{
int x = newX + newPiece.x(i);
int y = newY + newPiece.y(i);
if (x < 0 || x >= BoardWidth || y < 0 || y >= BoardHeight)
{
return false;
}
if (ShapeAt(x, y) != NoShape)
{
return false;
}
}
curPiece = newPiece;
curX = newX;
curY = newY;
Refresh();
return true;
}
void Board::DrawSquare(wxPaintDC & dc, int x, int y, Tetrominoes shape)
{
static wxColour colors [] = { wxColour(0, 0, 0), wxColour(204, 102, 102),
wxColour(102, 204, 102), wxColour(102, 102, 204), wxColour(204, 204, 102),
wxColour(204, 102, 204), wxColour(102, 204, 204), wxColour(218, 170, 0) };
static wxColour light [] = { wxColour(0, 0, 0), wxColour(248, 159, 171),
wxColour(121, 252, 121), wxColour(121, 121, 252), wxColour(252, 252, 121),
wxColour(252, 121, 252), wxColour(121, 252, 252), wxColour(252, 198, 0) };
static wxColour dark [] = { wxColour(0, 0, 0), wxColour(128, 59, 59),
wxColour(59, 128, 59), wxColour(59, 59, 128), wxColour(128, 128, 59),
wxColour(128, 59, 128), wxColour(59, 128, 128), wxColour(128, 98, 0) };
wxPen pen(light[int(shape)]);
pen.SetCap(wxCAP_PROJECTING);
dc.SetPen(pen);
dc.DrawLine(x, y + SquareHeight() - 1, x, y);
dc.DrawLine(x, y, x + SquareWidth() - 1, y);
wxPen darkpen(dark[int(shape)]);
darkpen.SetCap(wxCAP_PROJECTING);
dc.SetPen(darkpen);
dc.DrawLine(x + 1, y + SquareHeight() - 1, x + SquareWidth() - 1,
y + SquareHeight() - 1);
dc.DrawLine(x + SquareWidth() - 1, y + SquareHeight() - 1,
x + SquareWidth() - 1, y + 1);
dc.SetPen( * wxTRANSPARENT_PEN);
dc.SetBrush(wxBrush(colors[int(shape)]));
dc.DrawRectangle(x + 1, y + 1, SquareWidth() - 2, SquareHeight() - 2);
} tetris.h: #ifndef __TETRIS_H__
#define __TETRIS_H__
#include "board.h"
class Tetris : public wxFrame
{
public:
Tetris(const wxString & title);
};
#endif tetris.cpp: #include "tetris.h"
Tetris::Tetris(const wxString & title)
: wxFrame(NULL, wxID_ANY, title, wxDefaultPosition, wxSize(180, 380))
{
wxStatusBar * sb = CreateStatusBar();
sb -> SetStatusText(wxT("0"));
Board * board = new Board(this);
board -> SetFocus();
board -> Start();
} main.h: #ifndef __MAIN_H__
#define __MAIN_H__
#include "tetris.h"
class MyApp : public wxApp
{
public:
virtual bool OnInit();
};
#endif main.cpp: #include "main.h"
IMPLEMENT_APP(MyApp)
bool MyApp::OnInit()
{
srand(time(NULL));
Tetris * tetris = new Tetris(wxT("Tetris"));
tetris -> Centre();
tetris -> Show(true);
return true;
}