Click here to Skip to main content
15,898,732 members
Home / Discussions / C / C++ / MFC
   

C / C++ / MFC

 
GeneralDisplay PostScript file. Pin
Anonymous6-Aug-04 23:39
Anonymous6-Aug-04 23:39 
GeneralRe: Display PostScript file. Pin
Ryan Binns8-Aug-04 18:37
Ryan Binns8-Aug-04 18:37 
GeneralCListBox Control Pin
Neelesh K J Jain6-Aug-04 22:48
Neelesh K J Jain6-Aug-04 22:48 
GeneralRe: CListBox Control Pin
Gary R. Wheeler7-Aug-04 0:36
Gary R. Wheeler7-Aug-04 0:36 
Generalnext dialog Pin
doraemon16-Aug-04 22:15
doraemon16-Aug-04 22:15 
GeneralRe: next dialog Pin
Gary R. Wheeler7-Aug-04 0:41
Gary R. Wheeler7-Aug-04 0:41 
GeneralRe: next dialog Pin
DavidR_r7-Aug-04 1:22
DavidR_r7-Aug-04 1:22 
GeneralFlicker free drawing in MFC... Pin
JamRoll6-Aug-04 22:10
JamRoll6-Aug-04 22:10 
Wink | ;) Hi! My name is Jarett - a budding MFC programmer!!! Smile | :) yay.

Anyways, I am having some difficulties getting rid of some flicker. Now, before ignoring the rest of this, and telling me to look up info on the net; I have! And I am at my wits end. Nothing seems to refer to my specific issue. Here's my program (I know, it's long and boring).

Before reading any code, let me explain my idea (if the code isn't clear enough). The idea is this: It's battleship. Battleship has a board for both players (computer, and human in this case). Each board has cells (or places for pegs and ships). each board also gets five ships (duh). Now, I want to have the program display a cute little yellow line around a cell or ship (easily accomplished using a CPen (which I call 'hiliter')), but I get harsh flickering. So, I created CELL, SHIP and BOARD objects. A ship has cells, and so does the board. A ship will have 5 cells, and the board will have 10 by 10 cells (100). Easy enuf to figger out, right?

One last thing: I hope I don't have incomplete lines of code here. If so, just ignore them.


//////////////////////////////////////////////////////////////////////////////////
// battleshit.h
//////////////////////////////////////////////////////////////////////////////////

#define IDR_MENU1 100
#define CELLSIZE 20
#define CELLSPACING 0

// the cell class. the basics of battleship.
class CELL {
protected:
CPoint location;
CRect rect;

CPen pen, hiliter;
CBrush cellBrush, pegBrush;

bool hilited, occupied, shot, displayed, selected;
public:
CELL();

// this shall do the actual drawing on screen...acourse
void draw(CPaintDC *pdc);

// "get" functions

bool isHilited() { return hilited; }
bool isOccupied() { return occupied; }
bool isShot() { return shot; }
bool isDisplayed() { return displayed; }
bool isSelected() { return selected; }
// returns true if CPoint specified is within this CELL
bool pointInside(CPoint point) { if (rect.PtInRect(point) == 0) return false; else return true; }
// this will return the upper-left coordinate of the cell
CPoint getLocaton() { return location; }
// this will return (left, right, top, bottom) of the CELL in stored in a CRect
CRect getRect() { return rect; }

// "set" functions.

// sets the upper-left location of the CELL only.
// pass in either (int x, int y) or (CPoint point).
void setLocation(int x, int y);
void setLocation(CPoint point);
// sets the upper-left location of the cell, AND its lower-right as well.
// pass in either (int x, int y, int w, int h) or (CRect rect).
void setRect(int x, int y, int w, int h);
void setRect(CRect r);
// hilights the cell!
void hilite() { hilited = true; }
// tells the cell that a ship is currently occupying this square.
void occupy() { occupied = true; }
// 'shoots' the cell, placing a WHITE peg in it.
void shoot() { shot = true; }
// to toggle-on the display of the cell
void display() { displayed = true; }
// to toggle-off the display of the cell
void hide() { displayed = false; }
// used to reset ALL cell data to defaults.
void reset();
void select() { selected = true; }
void deselect() { selected = false; }
void unHilite() { hilited = false; }
};

/////////////////////////////////////////////////////////////////////////////////////////////////

// the SHIP class HAS A grouping of cells (for informational/data purposes only)
class SHIP {
protected:
CPoint location;
CRect rect;

CPen pen, hiliter;
CBrush shipBrush, sunkBrush, pegBrush;

bool hilited, displayed, vertical, selected;

int size;

CELL cells[5]; // yes, five. some ships may be smaller, and the 'extra' cells will just be ignored.
public:
SHIP();

// this shall do the actual drawing on screen...acourse
void draw(CPaintDC *pdc);

// "get" functions
bool sunk();
bool isHilited() { return hilited; }
bool isDisplayed() { return displayed; }
bool isVertical() { return vertical; }
bool isSelected() { return selected; }
// returns true if CPoint specified is within this SHIP
bool pointInside(CPoint point) { if (rect.PtInRect(point) == 0) return false; else return true; }
// this will return the upper-left coordinate of the SHIP
CPoint getLocation() { return location; }
// this will return (left, right, top, bottom) of the SHIP in stored in a CRect
CRect getRect() { return rect; }

// "set" functions
void setShip(int x, int y, int sz, bool vert);
void setPen(CPen p);
void setHiliter(CPen h);
void setShipBrush(CBrush b);
void setPegBrush(COLORREF color) { pegBrush.CreateSolidBrush(color); }
void select() { selected = true; }
void deselect() { selected = false; }
void rotate() { vertical = !vertical; }
void unHilite() { hilited = false; }
void hilite() { hilited = true; }
};

/////////////////////////////////////////////////////////////////////////////////////////////////

// the board class HAS A grouping of cells and ships.
class BOARD {
protected:
CPoint location;
CRect rect;

CPen pen, hiliter;
CBrush boardBrush;

bool displayed;

int size;
char *title;
public:
CELL cells[10][10];
SHIP ships[5];

BOARD(char *title, CPoint point, int sz); // sz isn't really used yet...so, ignore it for the most part.

void draw(CPaintDC *pdc);

void leftClick();
void rightClick();

CPoint getLocation() { return location; }
CRect getRect() { return rect; }
int getSize() { return size; }

void reset(); // this will remove ships, and shots from the board.
};

/////////////////////////////////////////////////////////////////////////////////////////////////

// main application
class BSApp : public CWinApp {
public:
virtual BOOL InitInstance();
};

/////////////////////////////////////////////////////////////////////////////////////////////////

// the game!
class battleshit : public CFrameWnd {
public:
battleshit();

protected:
BOARD *player, *computer;
CMenu menu;

virtual void PostNcDestroy();

afx_msg void OnPaint();
afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
afx_msg void OnRButtonDown(UINT nFlags, CPoint point);
afx_msg void OnMouseMove(UINT nFlags, CPoint point);

afx_msg void OnFileExit();
afx_msg void OnGameReset();
afx_msg void OnHelpContents();
afx_msg void OnHelpAbout();

DECLARE_MESSAGE_MAP();
};

//////////////////////////////////////////////////////////////////////////////////
// battleshit.cpp
//////////////////////////////////////////////////////////////////////////////////


#include <afxwin.h>
#include "battleshit.h"

BSApp battleshitApp;

//////////////////////////////////////////////////////////////////////////////////////////////////
// battleshitApp member functions //
//////////////////////////////////////////////////////////////////////////////////////////////////
BOOL BSApp::InitInstance() {
m_pMainWnd = new battleshit;

m_pMainWnd->ShowWindow(m_nCmdShow);
m_pMainWnd->UpdateWindow();
return TRUE;
} // InitInstance();

//////////////////////////////////////////////////////////////////////////////////////////////////
// battleshit member functions //
//////////////////////////////////////////////////////////////////////////////////////////////////
BEGIN_MESSAGE_MAP(battleshit, CFrameWnd)
ON_WM_PAINT()
ON_WM_LBUTTONDOWN()
ON_WM_RBUTTONDOWN()
ON_WM_MOUSEMOVE()
ON_COMMAND(100, OnFileExit)
ON_COMMAND(200, OnGameReset)
ON_COMMAND(500, OnHelpContents)
ON_COMMAND(501, OnHelpAbout)
END_MESSAGE_MAP()

////////////////////
// Initialization //
////////////////////
battleshit::battleshit() {
CString strWndClass = AfxRegisterWndClass(
CS_DBLCLKS,
AfxGetApp()->LoadStandardCursor(IDC_ARROW),
(HBRUSH) ::GetStockObject(WHITE_BRUSH),
AfxGetApp()->LoadStandardIcon(IDI_WINLOGO)
);

CreateEx(0, strWndClass, _T("Battleshit"),
WS_OVERLAPPED | WS_SYSMENU | WS_CAPTION | WS_MINIMIZEBOX,
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, NULL);

CRect rect(0, 0, 400, 552);
CalcWindowRect(&rect);
SetWindowPos(NULL, 0, 0, rect.Width(), rect.Height(), SWP_NOZORDER | SWP_NOMOVE | SWP_NOREDRAW);

CPoint boardLoc(40, 50);
player = new BOARD("You sail here...", boardLoc, 10);

boardLoc.y += 250;
computer = new BOARD("You shoot here...", boardLoc, 10);

menu.CreateMenu();
CMenu popup;

popup.CreatePopupMenu();
popup.AppendMenu(MF_STRING, 100, "E&xit");
menu.AppendMenu(MF_POPUP, (UINT)popup.Detach(), "&File");

popup.CreatePopupMenu();
popup.AppendMenu(MF_STRING, 200, "&Reset");
menu.AppendMenu(MF_POPUP, (UINT)popup.Detach(), "&Game");

popup.CreatePopupMenu();
popup.AppendMenu(MF_STRING, 500, "&Contents\tF1");
popup.AppendMenu(MF_STRING, 501, "&About");
menu.AppendMenu(MF_POPUP, (UINT)popup.Detach(), "&Help");
SetMenu(&menu);
menu.Detach();

} // battleshit();

void battleshit::PostNcDestroy() {
DestroyMenu(menu);
delete this;
} // PostNcDestroy();

//////////////////
// Painting //
//////////////////
void battleshit::OnPaint() {
CPaintDC dc(this);

CPen pen;
pen.CreatePen(PS_SOLID, 1, RGB(0, 0, 150));

CBrush brush;
brush.CreateSolidBrush(RGB(0, 0, 200));

dc.SelectObject(&pen);
dc.SelectObject(&brush);

dc.Rectangle(0, 0, 400, 552);

player->draw(&dc);
computer->draw(&dc);
} // OnPaint();

//////////////////
// Mouse clicks //
//////////////////
void battleshit::OnLButtonDown(UINT nFlags, CPoint point) {
} // OnLButtonDown();

void battleshit::OnRButtonDown(UINT nFlags, CPoint point) {
// check if a ship is selected, if so, rotate it.
for (int i = 0; i < 5; i++) {
if (player->ships[i].isSelected()) {
player->ships[i].rotate();
}
}
} // OnRButtonDown();

////////////////////
// Mouse movement // LOOK HERE - THIS IS WHERE MY PROBLEM IS!!!
////////////////////
void battleshit::OnMouseMove(UINT nFlags, CPoint point) {
// check if mouse is 'over' a cell in the PLAYER and COMPUTER board.
// if so, hilite the cell.
// before hiliting, tho, make sure all other cells are not hilited.
for (int y = 0; y < player->getSize(); y++) {
for (int x = 0; x < player->getSize(); x++) {
if (player->cells[x][y].isHilited()) {
player->cells[x][y].unHilite();
InvalidateRect(player->cells[x][y].getRect(), false);
}

if (player->cells[x][y].pointInside(point)) {
player->cells[x][y].hilite();
InvalidateRect(player->cells[x][y].getRect(), false);
}
}
}

for (y = 0; y < computer->getSize(); y++) {
for (int x = 0; x < computer->getSize(); x++) {
if (computer->cells[x][y].isHilited()) {
computer->cells[x][y].unHilite();
InvalidateRect(computer->cells[x][y].getRect(), false);
}

if (computer->cells[x][y].pointInside(point)) {
computer->cells[x][y].hilite();
InvalidateRect(computer->cells[x][y].getRect(), false);
}
}
}

// then, check if mouse is 'over' a ship. if so, hilite the ship.
for (int i = 0; i < 5; i++) {
if (player->ships[i].isHilited()) {
player->ships[i].unHilite();
InvalidateRect(player->ships[i].getRect(), false);
}

if (player->ships[i].pointInside(point)) {
player->ships[i].hilite();
InvalidateRect(player->ships[i].getRect(), false);
}
}

for (i = 0; i < 5; i++) {
if (computer->ships[i].isHilited()) {
computer->ships[i].unHilite();
InvalidateRect(computer->ships[i].getRect(), false);
}

if (computer->ships[i].pointInside(point)) {
computer->ships[i].hilite();
InvalidateRect(computer->ships[i].getRect(), false);
}
}
} // OnMouseMove();

////////////////////
// Menu events //
////////////////////
afx_msg void battleshit::OnFileExit() {
SendMessage(WM_CLOSE);
}

afx_msg void battleshit::OnGameReset() {
MessageBox(_T("Coming soon..."));
}

afx_msg void battleshit::OnHelpContents() {
MessageBox(_T("More help coming soon..."));
}

afx_msg void battleshit::OnHelpAbout() {
MessageBox(_T("Completed: <no eta,="" as="" yet="">\nWritten by: Jarett Lloyd\nLanguage: VS v6.0, C++, MFC\n\nHomePage: http://jamroll.dyndns.org/"), _T("About Battleshit"));
}

/////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////

CELL::CELL() {
location.x = 0;
location.y = 0;

rect.SetRect(0, 0, 0, 0);

pen.CreatePen(PS_SOLID, 1, RGB(0, 0, 0));
hiliter.CreatePen(PS_SOLID, 1, RGB(255, 255, 0));

cellBrush.CreateSolidBrush(RGB(0, 200, 200));
pegBrush.CreateSolidBrush(RGB(0, 160, 160));

hilited = false;
occupied = false;
shot = false;
}


void CELL::setLocation(CPoint point) {
location = point;
}

void CELL::setLocation(int x, int y) {
location.x = x;
location.y = y;
}

void CELL::setRect(CRect r) {
rect = r;
}

void CELL::setRect(int x, int y, int w, int h) {
rect.left = x;
rect.top = y;
rect.right = w;
rect.bottom = h;
}

void CELL::draw(CPaintDC *pdc) {
if (hilited)
pdc->SelectObject(&hiliter); else
pdc->SelectObject(&pen);

pdc->SelectObject(&cellBrush);
pdc->Rectangle(rect);

CRect circle = rect;
circle.left += 5;
circle.top += 5;
circle.right -= 5;
circle.bottom -= 5;

pdc->SelectObject(&pen);
pdc->SelectObject(&pegBrush);
pdc->Ellipse(circle);
}

/////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////

SHIP::SHIP() {
location.x = 0;
location.y = 0;
rect.SetRect(0, 0, 0, 0);
displayed = true;
hilited = false;
size = 2;
vertical = false;

for (int i = 0; i < 5; i++) {
cells[i].hide();
}

pen.CreatePen(PS_SOLID, 1, RGB(0, 0, 0));
hiliter.CreatePen(PS_SOLID, 1, RGB(255, 255, 0));

shipBrush.CreateSolidBrush(RGB(200, 200, 200));
pegBrush.CreateSolidBrush(RGB(160, 160, 160));
sunkBrush.CreateSolidBrush(RGB(160, 0, 0));
}

void SHIP::draw(CPaintDC *pdc) {
if (hilited)
pdc->SelectObject(&hiliter); else
pdc->SelectObject(&pen);

if (sunk())
pdc->SelectObject(&sunkBrush); else
pdc->SelectObject(&shipBrush);

if (size != 5) {
pdc->Rectangle(rect);
} else {
pdc->Rectangle(rect);

if (hilited)
pdc->FloodFill(location.x + (CELLSIZE / 2), location.y + (CELLSIZE / 2), RGB(0, 255, 255)); else
pdc->FloodFill(location.x + (CELLSIZE / 2), location.y + (CELLSIZE / 2), RGB(0, 0, 0));

if (vertical) {
} else {
}
}

pdc->SelectObject(&pegBrush);
for (int c = 0; c < size; c++) {
pdc->SelectObject(&pen);
pdc->SelectObject(&pegBrush);
}
}

void SHIP::setShip(int x, int y, int sz, bool vert) {
if (sz < 2) sz = 2;
if (sz > 5) sz = 5;

size = sz;

vertical = vert;

location.x = x;
location.y = y;

rect.left = x;
rect.top = y;

if (vertical) {
rect.right = x + 20;
rect.bottom = y + (size * (CELLSIZE + CELLSPACING));
} else {
rect.right = x + (size * (CELLSIZE + CELLSPACING));
rect.bottom = y + 20;
}

for (int i = 0; i < size; i++) {
cells[i].display();
int px, py, pw, ph;

if (vertical) {
px = x;
py = y + (i * (CELLSIZE + CELLSPACING));
pw = px + 20;
ph = py + 20;
} else {
px = x + (i * (CELLSIZE + CELLSPACING));
py = y;
pw = px + 20;
ph = py + 20;
}

cells[i].setRect(px, py, pw, ph);
}
}

bool SHIP::sunk() {
for (int i = 0; i < size; i++) {
if (cells[i].isShot() == false) return false;
}
return true;
}

/////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////

BOARD::BOARD(char *title, CPoint point, int sz = 10) {
pen.CreatePen(PS_SOLID, 1, RGB(0, 0, 0));
boardBrush.CreateSolidBrush(RGB(0, 0, 240));

location = point;
sz = 10;
size = sz;

rect.left = point.x - 5;
rect.top = point.y - 5;
rect.right = (point.x + ((CELLSIZE + CELLSPACING) * sz)) + 5;
rect.bottom = (point.y + ((CELLSIZE + CELLSPACING) * sz)) + 5;

int cx = point.x,
cy = point.y,
cw = cx + CELLSIZE,
ch = cy + CELLSIZE;

for (int y = 0; y < sz; y++) {
for (int x = 0; x < sz; x++) {
cells[x][y].setRect(cx, cy, cw, ch);
cx += CELLSIZE + CELLSPACING;
cw = cx + CELLSIZE;
}

cx = point.x;
cy += CELLSIZE + CELLSPACING;
cw = cx + CELLSIZE;
ch = cy + CELLSIZE;
}

bool v = false;

for (int ship = 0; ship < 5; ship++) {
int sz = 2;
switch (ship) {
case 0: sz = 2; break;
case 1:
case 2: sz = 3; break;
case 3: sz = 4; break;
case 4: sz = 5; break;
default: sz = 2; break;
}

if (v)
ships[ship].setShip(rect.right + CELLSIZE, point.y, sz, true); else
ships[ship].setShip(rect.right + CELLSIZE, point.y + (ship * (CELLSIZE + CELLSPACING)), sz, false);
}

this->title = title;
}

void BOARD::draw(CPaintDC *pdc) {
pdc->SelectObject(&pen);
pdc->SelectObject(&boardBrush);

pdc->Rectangle(rect);

for (int y = 0; y < size; y++) {
for (int x = 0; x < size; x++) {
cells[x][y].draw(pdc);
}
}

for (int ship = 0; ship < 5; ship++) {
ships[ship].draw(pdc);
}

CRect tRect, sRect;
tRect.left = rect.left - (CELLSIZE + CELLSPACING);
tRect.top = rect.top - (CELLSIZE + CELLSPACING);
tRect.right = rect.left + 300;
tRect.bottom = rect.top + CELLSIZE;
sRect = tRect;
sRect.left += 2;
sRect.top += 2;

pdc->SetTextColor(RGB(0, 0, 0));
pdc->SetBkMode(TRANSPARENT);
pdc->DrawText(_T(title), -1, sRect, DT_SINGLELINE);
pdc->SetTextColor(RGB(255, 255, 0));
pdc->DrawText(_T(title), -1, tRect, DT_SINGLELINE);
}

/////////////////////////////////////////////////////////////////////////////

I don't want the flicker!!!

At first, I thot just changing the data in the CELL and SHIP objects would do the trick. But no, that doesn't work! Of course it doesn't - it's Microsoft - he can't make anything easy!!!! Now, I know for a fact the flicker is caused by InvalidateRect(...) - is there a way around this problem, or do I just put up with it?

Anyways, if yer confused, take a look at the DRAW member functions of the CELL and SHIP objects and the OnPaint and OnMouseMove member functions of the 'battleshit' object. Maybe I should just bury my head up my backside and forget this whole endeavor, but I don't relish that idea - I want to be successful; so I beg for your kind assistance.

TY in advance, JamRoll

PS: I don't care what you do to my code. use it, delete it, or serve it for dinner. If it isn't real good, let me know how I can improve it - I'm always trying to create code that is readable, and friendly! Wink | ;)


---
jamroll@telus.net
http://jamroll.dyndns.org/
GeneralRe: Flicker free drawing in MFC... Pin
Neville Franks6-Aug-04 23:08
Neville Franks6-Aug-04 23:08 
GeneralRe: Flicker free drawing in MFC... Pin
Ryan Binns8-Aug-04 18:41
Ryan Binns8-Aug-04 18:41 
GeneralRe: Flicker free drawing in MFC... Pin
JamRoll10-Aug-04 18:06
JamRoll10-Aug-04 18:06 
GeneralRe: Flicker free drawing in MFC... Pin
Ryan Binns10-Aug-04 18:39
Ryan Binns10-Aug-04 18:39 
GeneralRe: Flicker free drawing in MFC... Pin
JamRoll12-Aug-04 10:48
JamRoll12-Aug-04 10:48 
GeneralRe: Flicker free drawing in MFC... Pin
Ryan Binns12-Aug-04 13:56
Ryan Binns12-Aug-04 13:56 
QuestionPlease Help me about Digital Map Help ?Help ?Help ?Help ? Please ? Pin
A_Fa6-Aug-04 21:06
A_Fa6-Aug-04 21:06 
Generalproblem with STL Vector Pin
Sivaji6-Aug-04 20:41
Sivaji6-Aug-04 20:41 
GeneralRe: problem with STL Vector Pin
DavidR_r7-Aug-04 1:26
DavidR_r7-Aug-04 1:26 
GeneralHey problem with STL Vector Pin
Sivaji6-Aug-04 20:39
Sivaji6-Aug-04 20:39 
Questionhow to change the shape of the SDI window Pin
n.srinukumar6-Aug-04 19:49
n.srinukumar6-Aug-04 19:49 
QuestionWhat is the difference between LPWSTR and WCHAR * Pin
ting6686-Aug-04 19:40
ting6686-Aug-04 19:40 
AnswerRe: What is the difference between LPWSTR and WCHAR * Pin
Gary R. Wheeler7-Aug-04 1:13
Gary R. Wheeler7-Aug-04 1:13 
GeneralRe: What is the difference between LPWSTR and WCHAR * Pin
ting6687-Aug-04 2:45
ting6687-Aug-04 2:45 
GeneralRe: What is the difference between LPWSTR and WCHAR * Pin
Tim Smith7-Aug-04 19:22
Tim Smith7-Aug-04 19:22 
GeneralVC6 IDE Bookmarks question Pin
Gammill6-Aug-04 19:02
Gammill6-Aug-04 19:02 
GeneralShell extension...help Pin
Member 12827896-Aug-04 18:34
Member 12827896-Aug-04 18:34 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.