Zum Inhalt springen

Empfohlene Beiträge

Geschrieben

Hi,

ich habe so für mich ein kleines TIC TAC TOE Spiel

programmiert. Das dumme ist nur, dass die Grafik weg ist,

sobald sie von einem Fenster verdeckt wird.

Jetzt habe ich gelesen, dass man das mit der OnDraw Methode im View lösen muss. Doch irgendwie blicke ich da nicht durch. Was muss ich da genau machen?

Geschrieben

Hier ist meine OnPaint Methode, bisher ist es nur das Aussehen:

void spiel::OnPaint()

{

	CPaintDC dc(this); // device context for painting

	// TODO: Fügen Sie hier Ihren Meldungsbehandlungscode ein.

	// CDialog::OnPaint() soll zum Zeichnen von Meldungen nicht aufgerufen werden.

	dc.FillRect(frame,&stdbrush.white);


	for(int z=0;z<3;z++)

	{


		for(int s=0;s<3;s++)

		{

			int x = frame.left+s*feldbreite;

			int y = frame.top+z*feldhoehe;


			feld.SetRect(x,y,x+feldbreite,y+feldhoehe);

			dc.Rectangle(feld);


			felder[z][s]=feld;

		}

	}


	void* oldpen;


	if(kreuz==true)

	{

		oldpen = dc.SelectObject(&stdpen.rgb5);

		CPoint topleft = kreuz_rechteck.TopLeft();

		CPoint bottomright = kreuz_rechteck.BottomRight();


		int x = topleft.x;

		int y = topleft.y;


		int x2 = bottomright.x;

		int y2 = bottomright.y;


		dc.MoveTo(kreuz_rechteck.TopLeft());


		dc.LineTo(kreuz_rechteck.BottomRight());


		dc.MoveTo(x,bottomright.y);

		dc.LineTo(bottomright.x,topleft.y);


		kreuz=false;

		kreis=true;

	}

	else //Kreis

	{

		oldpen = dc.SelectObject(&stdpen.blue5);


		dc.Ellipse(kreis_rechteck);

		kreis=false;

		kreuz=true;

	}



}
Die OnDraw Methode ist jetzt so ähnlich wie die OnPaint, doch da passiert es, dass beim Verdecken sich nur willkürlich Grafiken gemerkt werden. :( Ich verstehe es nicht mehr. :(


void CtictactoeView::OnDraw(CDC* pDC)

{

	CtictactoeDoc* pDoc = GetDocument();

	ASSERT_VALID(pDoc);

	if (!pDoc)

		return;


	CRect feld;

	GetClientRect(&feld);

	game.zeichnen(pDC);

}
game ist dabei ein extern meiner Spieldatei, wo die OnPaint Methode ausprogrammiert wurde. Die Zeichnen Methode ist dann folgendermaßen:

void spiel::zeichnen(CDC* pDC)

{

	pDC->FillRect(frame,&stdbrush.white);


	for(int z=0;z<3;z++)

	{


		for(int s=0;s<3;s++)

		{

			int x = frame.left+s*feldbreite;

			int y = frame.top+z*feldhoehe;


			feld.SetRect(x,y,x+feldbreite,y+feldhoehe);

			//dc.Rectangle(feld);

			pDC->Rectangle(feld);

			felder[z][s]=feld;

		}

	}


	void* oldpen;


	if(kreuz==true)

	{

		oldpen = pDC->SelectObject(&stdpen.rgb5);

		CPoint topleft = kreuz_rechteck.TopLeft();

		CPoint bottomright = kreuz_rechteck.BottomRight();


		int x = topleft.x;

		int y = topleft.y;


		int x2 = bottomright.x;

		int y2 = bottomright.y;


		pDC->MoveTo(kreuz_rechteck.TopLeft());


		pDC->LineTo(kreuz_rechteck.BottomRight());


		pDC->MoveTo(x,bottomright.y);

		pDC->LineTo(bottomright.x,topleft.y);


		kreuz=false;

		kreis=true;

	}

	else //Kreis

	{

		oldpen = pDC->SelectObject(&stdpen.blue5);


		pDC->Ellipse(kreis_rechteck);

		kreis=false;

		kreuz=true;

	}


}

kreis und kreuz sind zwei boolean.

Dies dient dazu, damit wirklich abwechselnd gespielt wird.

Kann mir jemand helfen?

Geschrieben

Für mich sieht das so aus, als ob du immer nur das Feld für den zuletzt gemachten Zug ausmalst. Du malst ja immer nur entweder einen Kreis oder ein Kreuz. Die vorausgegangenen Züge musst du auch malen.

P.S.: Wenn kreis sowieso immer !kreuz, kannst du auch auf eine der beiden Variablen verzichten.

Geschrieben

Nach einer Fehleranalyse habe ich gemerkt, dass er sich immer die vorherige Grafik merkt. Die Boolean Variablen habe ich mal aus OnDraw rausgeschmissen.

Hm...stimmt, er soll alles zeichnen. Könnte man das evtl. mit einem Array lösen, welches die Werte ausliest ? (x und y werte)

Wie ist denn überhaupt das prinzipielle Vorgehen bei der OnDraw Methode?

Geschrieben

Habe es mal folgendermaßen abgeändert. Die Rechtecke werden in ein 3x3 Array abgespeichert. Nur irgendwie funktioniert das auch nicht, und ich weiß nicht warum.


void spiel::zeichnen(CDC* pDC)

{

	/*

		Hier wird der Fensterinhalt zurückgeschrieben

	*/



	for(int z=0;z<3;z++)

	{

		for(int s=0;s<3;s++)

		{	

			pDC->SelectObject(&stdpen.rgb5);

			// Kreuze neu zeichnen

			CPoint topleft = r_array[z][s].TopLeft();

			CPoint bottomright = r_array[z][s].BottomRight();


			int x = topleft.x;

			int y = topleft.y;


			int x2 = bottomright.x;

			int y2 = bottomright.y;


			pDC->MoveTo(r_array[z][s].TopLeft());

			pDC->LineTo(bottomright.x,topleft.y);


			//Kreise neu zeichnen


			pDC->SelectObject(&stdpen.blue5);


			pDC->Ellipse(r_array[z][s]);

		}

	}

}
Der Code zum klicken wurde folgendermaßen verändert:

void spiel::OnLButtonDown(UINT nFlags, CPoint point)

{

	if(!frame.PtInRect(point))

		return;



	int spalte=point.x/feldbreite;

	int zeile=point.y/feldhoehe;



	if(geklickt[zeile][spalte])

		return;


	if(kreuz)

	{	

		kreuz_rechteck.SetRect(felder[zeile][spalte].TopLeft(),felder[zeile][spalte].BottomRight());

		r_array[zeile][spalte]=kreuz_rechteck;

		zaehler++;

		InvalidateRect(kreuz_rechteck,false);

		geklickt[zeile][spalte]=1;

	}


	else //Kreis

	{

		kreis_rechteck.SetRect(felder[zeile][spalte].TopLeft(),felder[zeile][spalte].BottomRight());

		r_array[zeile][spalte]=kreis_rechteck;

		zaehler++;

		InvalidateRect(kreis_rechteck,false);

		geklickt[zeile][spalte]=1;

	}



	CDialog::OnLButtonDown(nFlags, point);

}

Alles andere ist gleich geblieben.

Geschrieben

Hi,

habe das Problem gelöst!! :)

Es ist ziemlich egal ob man OnDraw oder OnPaint nimmt.

Obwohl in OnPaint funktioniert es.

Hier der Code ohne Spiellogik (noch ist ein brutales Invalidate() enthalten, dies sollte man durch invalidaterect(rechteck) oder einem offscreen ersetzen):


// spiel.cpp : Implementierungsdatei

//


#include "stdafx.h"

#include "tictactoe.h"

#include "spiel.h"

#include ".\spiel.h"

#include "draw.h"


spiel game;



// spiel-Dialogfeld


IMPLEMENT_DYNAMIC(spiel, CDialog)

spiel::spiel(CWnd* pParent /*=NULL*/)

	: CDialog(spiel::IDD, pParent)

{

	abstand = 5;


	for(int i=0;i<3;i++)

	{

		for(int j=0;j<3;j++)

		{

			geklickt[i][j]=0;

		}

	}


	for(int i=0;i<3;i++)

	{

		for(int j=0;j<3;j++)

		{

			inhalt[i][j]=0;

		}

	}

}


spiel::~spiel()

{

}


void spiel::DoDataExchange(CDataExchange* pDX)

{

	CDialog::DoDataExchange(pDX);

	DDX_Control(pDX, IDC_RAHMEN, rahmen);

}



BEGIN_MESSAGE_MAP(spiel, CDialog)

	ON_WM_PAINT()

	ON_WM_LBUTTONDOWN()

END_MESSAGE_MAP()



// spiel-Meldungshandler


void spiel::OnPaint()

{

	UpdateData(TRUE);


	CPaintDC dc(this); // device context for painting

	// TODO: Fügen Sie hier Ihren Meldungsbehandlungscode ein.

	// CDialog::OnPaint() soll zum Zeichnen von Meldungen nicht aufgerufen werden.

	dc.FillRect(frame,&stdbrush.white);


	void* oldpen;


	for(int z=0;z<3;z++)

	{


		for(int s=0;s<3;s++)

		{

			int x = frame.left+s*feldbreite;

			int y = frame.top+z*feldhoehe;


			feld.SetRect(x,y,x+feldbreite,y+feldhoehe);

			dc.Rectangle(feld);


			felder[z][s]=feld;

		}

	}


	for(int z=0;z<3;z++)

	{

		for(int s=0;s<3;s++)

		{

			if(inhalt[z][s]==KREUZ)

			{

				oldpen = dc.SelectObject(&stdpen.rgb5);

				CPoint topleft = gezeichnet[z][s].TopLeft();

				CPoint bottomright = gezeichnet[z][s].BottomRight();


				int x = topleft.x;

				int y = topleft.y;


				int x2 = bottomright.x;

				int y2 = bottomright.y;


				dc.MoveTo(topleft);


				dc.LineTo(bottomright);


				dc.MoveTo(x,bottomright.y);

				dc.LineTo(bottomright.x,topleft.y);

			}


			if(inhalt[z][s]==KREIS)

			{

						oldpen = dc.SelectObject(&stdpen.blue5);


						dc.Ellipse(gezeichnet[z][s]);

			}

		}


		UpdateData(false);

	}




	if(kreuz==true)

	{

		oldpen = dc.SelectObject(&stdpen.rgb5);

		CPoint topleft = kreuz_rechteck.TopLeft();

		CPoint bottomright = kreuz_rechteck.BottomRight();


		int x = topleft.x;

		int y = topleft.y;


		int x2 = bottomright.x;

		int y2 = bottomright.y;


		dc.MoveTo(kreuz_rechteck.TopLeft());


		dc.LineTo(kreuz_rechteck.BottomRight());


		dc.MoveTo(x,bottomright.y);

		dc.LineTo(bottomright.x,topleft.y);


		kreuz=false;

	}

	else //Kreis

	{

		oldpen = dc.SelectObject(&stdpen.blue5);


		dc.Ellipse(kreis_rechteck);

		kreuz=true;

	}



}



BOOL spiel::OnInitDialog()

{

	CDialog::OnInitDialog();


	rahmen.GetWindowRect(&frame);

	ScreenToClient(&frame);


	breite = frame.Width();

	hoehe = frame.Height();


	feldbreite = breite / 3;

	feldhoehe = hoehe / 3;


	return TRUE;  // return TRUE unless you set the focus to a control

	// AUSNAHME: OCX-Eigenschaftenseite muss FALSE zurückgeben.

}


void spiel::OnLButtonDown(UINT nFlags, CPoint point)

{

	UpdateData(TRUE);


	if(!frame.PtInRect(point))

		return;



	int spalte=point.x/feldbreite;

	int zeile=point.y/feldhoehe;



	if(geklickt[zeile][spalte])

		return;


	if(kreuz)

	{	

		kreuz_rechteck.SetRect(felder[zeile][spalte].TopLeft(),felder[zeile][spalte].BottomRight());

		inhalt[zeile][spalte]=KREUZ;

		gezeichnet[zeile][spalte]=kreuz_rechteck;

		Invalidate();

		geklickt[zeile][spalte]=1;

	}


	else //Kreis

	{

		kreis_rechteck.SetRect(felder[zeile][spalte].TopLeft(),felder[zeile][spalte].BottomRight());

		inhalt[zeile][spalte]=KREIS;

		gezeichnet[zeile][spalte]=kreis_rechteck;

		Invalidate();

		geklickt[zeile][spalte]=1;

	}


	UpdateData(false);


	CDialog::OnLButtonDown(nFlags, point);

}

Und hier noch die dazugehörige Headerdatei. Ich habe noch zwei symbolische Konstanten KREUZ und KREIS hinzugefügt, die in der Abfrage des Arrays genutzt werden.

#pragma once

#include "afxwin.h"


#define KREUZ 1

#define KREIS 2


// spiel-Dialogfeld


class spiel : public CDialog

{

	DECLARE_DYNAMIC(spiel)


public:

	spiel(CWnd* pParent = NULL);   // Standardkonstruktor

	virtual ~spiel();


	CRect frame;


	CRect felder[3][3];

	CRect feld;

	//int feld[3][3];


	int breite;

	int hoehe;

	int abstand;


	int feldbreite;

	int feldhoehe;


	bool kreuz;

	bool kreis;


	CRect kreuz_rechteck;

	CRect kreis_rechteck;


	int geklickt[3][3];

	CRect gezeichnet[3][3];

	int inhalt[3][3];


// Dialogfelddaten

	enum { IDD = IDD_spiel };


protected:

	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV-Unterstützung


	DECLARE_MESSAGE_MAP()

public:

	CStatic rahmen;

	afx_msg void OnPaint();

	virtual BOOL OnInitDialog();

	afx_msg void OnLButtonDown(UINT nFlags, CPoint point);

};

Dein Kommentar

Du kannst jetzt schreiben und Dich später registrieren. Wenn Du ein Konto hast, melde Dich jetzt an, um unter Deinem Benutzernamen zu schreiben.

Gast
Auf dieses Thema antworten...

×   Du hast formatierten Text eingefügt.   Formatierung wiederherstellen

  Nur 75 Emojis sind erlaubt.

×   Dein Link wurde automatisch eingebettet.   Einbetten rückgängig machen und als Link darstellen

×   Dein vorheriger Inhalt wurde wiederhergestellt.   Editor leeren

×   Du kannst Bilder nicht direkt einfügen. Lade Bilder hoch oder lade sie von einer URL.

Fachinformatiker.de, 2024 by SE Internet Services

fidelogo_small.png

Schicke uns eine Nachricht!

Fachinformatiker.de ist die größte IT-Community
rund um Ausbildung, Job, Weiterbildung für IT-Fachkräfte.

Fachinformatiker.de App

Download on the App Store
Get it on Google Play

Kontakt

Hier werben?
Oder sende eine E-Mail an

Social media u. feeds

Jobboard für Fachinformatiker und IT-Fachkräfte

×
×
  • Neu erstellen...