Δρομέας

Rakeesh είπε:
Αν ενδιαφερεται κανενας, ξερω μια τεχνικη σχεδιασης για να κανεις τις οριζοντιες γραμμες να εχουν τετοιες αποστασεις μεταξυ τους ωστε να φαινεται ρεαλιστικο το βαθος
Το θεμα ειναι οτι την τεχνικη αυτη την ξερω με χαρακα και δεν εχω ιδεα πως αποδιδεται αλγοριθμικα... αν μπορουσε να ενσωματωθει στο προγραμμα παντως θα ειχε ωραιο αποτελεσμα
Θα είχε πολύ ενδιαφέρον να την διαβάσουμε, οπότε αν έχεις χρόνο και κέφι, θα ήθελα να δω ένα post επ’ αυτού.

Τώρα όσον αφορά την _Make3D, την σχεδίασα πρώτη φορά σήμερα το πρωί (θέλει λίγο χτένισμα ώστε να δουλεύει σωστά σε κάθε nMax τιμή), ήταν μια καλή ευκαιρία να ικανοποιήσω ένα απωθημένο μου σχεδιάζοντας έναν ορίζοντα όπως θυμόμουν πως φαινότανε αυτό το εφε σε κάτι παλιά γιαπωνέζικα καρτούν των ‘80s με τις γραμμές εκεί βέβαια βαμμένες σε neon χρώμα :D

Κάθε πρόταση δεκτή!!
 
Τελευταία επεξεργασία από έναν συντονιστή:
Μπράβο παιδιά.

Ωραία δουλειά xdir και προσεγμένη, καλώς ήρθες.

Στο δεύτερο script ο 3D ορίζοντας δεν μου εμφανίζεται παρά μόνο οι βουνοκορφές. τρέχω xp sp3

ΑΑ+ μου άρεσε η version σου :)

Ετσι παιδιά, βάλτε υλικό.
 
Σε ευχαριστώ πολύ! #)

Τώρα σχετικά με το δεύτερο script... χμ... εκίνησε μια νέα console (cmd.exe) πήγαινε στα Properties της και στο Tab "Font" όρισε ως φόντο το "Raster Fonts" με διαστάσεις 10x20. Ύστερα από το Tab "Layout" όρισε τις διαστάσεις τόσο του "Screen Buffer" όσο και του "Window Size" σε 80x25. Μετά κάνε OK ώστε να περαστούν οι νέες επιλογές στην κονσόλα.

Λογικά, θα πρέπει να εμφανισθεί ο τεχνιτός ορίζοντας ... ???
 
Τελευταία επεξεργασία από έναν συντονιστή:
Shock είπε:
AA+ που ήσουν τόσο καιρό ? :cool: Παιδιά συγχαρητήρια σε όλους. Δεσμεύομαι για το port στην Amiga σε ένα μήνα από τώρα που θα τελειώσω με τα τρεχάματα μου.

Φυσικά όποιος θέλει μπορεί να το φτιάξει ΚΑΙ εκεί, όσα περισσότερα ports τόσο καλύτερα.

Μας λείπουν και τα υπόλοιπα 8bita:cool:

Y.Γ @ΑΑ+ μου αρέσει το όνομα των μεταβλητών σου :)

Και εμένα μ'αρέσουν τα ονόματα ΑΝ τα έγραφα και σωστά! Μέσα στην νύστα μου 5:30 το πρωί αντί για retromaniax έγραψα retronaniax...

Ευχαριστώ για τα καλά σας λόγια και παρακολουθώ τις αξιόλογες προσπάθειες όλων των παιδιών εδώ..
 
Running Man v3

Μιας και η ανάλυση της κονσόλας μπορεί να δημιουργήσει ορισμένα προβλήματα στην οπτική απεικόνιση των εφέ, αποφάσισα να μετατρέψω το πρόγραμμα από Console σε Window εφαρμογή, γραμμένη σε CodeGear Turbo C++.




Το δοκίμασα σε MS-Windows XP (SP3) και MS-Windows ’98 (MS Virtual-PC ’04).

Ακολουθεί ο κώδικας:

Κώδικας:
/*******************************************************************************
 Running Man Asm originally written by Nick Kouvaris "retromaniax FTL"
 (http://lightforce.freestuff.gr/),                                          
 C port of Running Man, by xdir (directx@freemail.gr) 	

 v2 - Adds a road under the man, spiked mountains on the background and a
   3D Horizon effect.
 v3 - Rewritten in CodeGear Turbo C++ as a standard Windows application 
   (no console interface).

   Tested under Windows XP (SP3) - 1024x768.	
*******************************************************************************/

#include 
#pragma hdrstop

#define	_FRAME	7
#define	_SPEED	60

//---------------------------------------------------------------------------
LRESULT CALLBACK WindowProcedure(HWND, UINT, WPARAM, LPARAM);
BOOL _DrawRoad(HWND, int nY, RECT*);
BOOL _DrawMountain(HWND, POINT[], int nMax, RECT*);
BOOL _DrawMan(HWND, HICON[], int nX, int nY, RECT*);
BOOL _ClearRect(HWND, RECT*);

void _LoadMan(HICON icoArray[], int nMax = _FRAME);
void _MakeMountain(POINT point[], int nMaxElement, int nSpace = 10, 
							  int nTopline = 70, int nBaseline = 30);
BOOL _Make3D(HWND hWnd, RECT *rcClient, int nOffset, int nMax, BOOL bInit);

#pragma argsused
WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
WNDCLASS wcOwner;
HWND hWnd;

try
 {
	try
	 {
		// Create Window Class ...
		ZeroMemory(&wcOwner, sizeof(wcOwner));
		wcOwner.style = CS_HREDRAW|CS_VREDRAW;
		wcOwner.lpfnWndProc = (WNDPROC)WindowProcedure;
		wcOwner.hInstance = hInstance;
		wcOwner.hbrBackground = GetStockObject(BLACK_BRUSH);
		wcOwner.lpszClassName = "RunManV3";
		wcOwner.hCursor = LoadCursor(NULL, IDC_ARROW);
		if(!RegisterClass(&wcOwner))
			throw "Window Error: Cannot "Register Class"";

		// Create Window ...
		hWnd = CreateWindow(wcOwner.lpszClassName,
							"Running Man v3",
							WS_MINIMIZEBOX|WS_SYSMENU|WS_VISIBLE|WS_OVERLAPPED,
							CW_USEDEFAULT, CW_USEDEFAULT,
							350, 350,
							NULL, NULL, 
							hInstance, 
							NULL);
		if(hWnd == NULL)
			throw "Window Error: Cannot "Create Window"";

		// Kickstart Window (do not use ShowWindow -- ignore nCmdShow) ...
		UpdateWindow(hWnd);

		int nSuccess;
		MSG msgData;
		// Set-up primary message loop ...
		while((nSuccess = GetMessage(&msgData, hWnd, 0, 0L))!=0)
		 {
               // Microsoft suggestion, since GetMessage can return -1
			if(nSuccess == -1)
				break;

			TranslateMessage(&msgData);
			DispatchMessage(&msgData);
		 }
	 }
	catch(char *pszError)
	 {			
		// Error!
		KillTimer(hWnd, WM_USER+5);
		MessageBeep(MB_ICONSTOP);
		MessageBox(NULL, pszError, NULL, MB_ICONSTOP);
	 }
 }
__finally
 {
	// Application clean-up ...
	UnregisterClass(wcOwner.lpszClassName, hInstance);				
 }

return 0;
}
//---------------------------------------------------------------------------
LRESULT CALLBACK WindowProcedure(HWND hWnd, UINT nMessage, 
							 WPARAM wParam, LPARAM lParam)
{
   // Main window procedure
static RECT rcClient, rcClear;
static POINT ptMountain[100];
static HICON hIcon[7];
static PAINTSTRUCT PS;
static int nMan_X = -32;

switch(nMessage)
 {
	case WM_CREATE:
		// Load sprite ...
		_LoadMan(hIcon);
		// Initialize Mountain points ...			
		_MakeMountain(ptMountain, 100);				
		// Get Client dimensions
		GetClientRect(hWnd, &rcClient);
		// Make initial 3D horizon
		_Make3D(hWnd, &rcClient, 210, 210, TRUE);
		// Setup our live-beat timer
		SetTimer(hWnd, WM_USER+5,_SPEED, NULL);
	return	TRUE;
	case WM_TIMER:
	 switch(wParam)
	  {
		case WM_USER+5:
			// Force a non destructive DC invalidation
			InvalidateRect(hWnd, NULL, FALSE);
		return	FALSE;
	  }
	return	TRUE;
	case WM_DESTROY:
		// Shutdown live-beat timer
		KillTimer(hWnd, WM_USER+5);
		// Quit!
		PostQuitMessage(0L);
	return	TRUE;
	case WM_PAINT:
		// Signal DC for paint
		if(BeginPaint(hWnd, &PS) != NULL)
		 {				
			// Get Client dimensions
			GetClientRect(hWnd, &rcClient);
			// v2) Draw mountains
			_DrawMountain(hWnd, ptMountain, 100, &rcClient);
			// v2) Draw a road */ 			
			_DrawRoad(hWnd, 200, &rcClient);
			// v1) Draw man on road
			_DrawMan(hWnd, hIcon, nMan_X++, 200 - 32, &rcClient);	
			// v1) Move man along the road
			if(nMan_X > rcClient.right + 32)
			 {
				// v1) Flip man to left
				nMan_X = -32;				
				// v2) Clear previous mountain
				rcClear.left = rcClear.top = 0;
				rcClear.right= rcClient.right;
				rcClear.bottom=100;
				_ClearRect(hWnd, &rcClear);
				// v2) Generate a new mountain background
				_MakeMountain(ptMountain, 100);
			 }
			// v2) Clear previous horizon
			rcClear.left = 0;
			rcClear.top = 210;
			rcClear.right= rcClient.right;
			rcClear.bottom=rcClient.bottom;
			_ClearRect(hWnd, &rcClear);
			_Make3D(hWnd, &rcClient, 210, 210, FALSE);
			// Signal DC off paint
			EndPaint(hWnd, &PS);			
		 }
	break;
 }

return	DefWindowProc(hWnd, nMessage, wParam, lParam);
}

BOOL _DrawRoad(HWND hWnd, int nY, RECT *prcClient)
{
static HDC	hDC;

// Get DC for draw ...
if((hDC=GetDC(hWnd))!=NULL)
 {
	// Set Road color to Red
	SelectObject(hDC, GetStockObject(WHITE_PEN));
	// Draw Road ...
	MoveToEx(hDC, 0, nY, NULL);
	LineTo(hDC, prcClient->right, nY);		
	// Release DC
	ReleaseDC(hWnd, hDC);
	// No error!
	return	TRUE;
 }

return	FALSE;
}

void _MakeMountain(POINT point[], int nMaxElement, int nSpace, 
							  int nTopline, int nBaseline)
{
/* Generate a extra-large enough mountain like polyline point array */
int nPointCount = 0;
for(; nPointCount < nMaxElement; nPointCount++)
 {
	point[nPointCount].x = nPointCount*nSpace;
	point[nPointCount].y = (rand() % nBaseline) + nTopline; 
 }
}

BOOL _DrawMountain(HWND hWnd, POINT point[], int nMax, RECT *prcClient)
{
static HDC	hDC;

// Get DC for draw ...
if((hDC=GetDC(hWnd))!=NULL)
 {
	// Create a thick Green pen ...		
	LOGPEN penGray;
	penGray.lopnStyle = PS_SOLID;
	penGray.lopnWidth.x = 2;
	penGray.lopnColor = RGB(0, 255, 0);

	HPEN hOldPen = NULL,
		 hPen = CreatePenIndirect(&penGray);

	// Set Mountain color to Green
	hOldPen = SelectObject(hDC, hPen);
	// Draw Mountains ...
	Polyline(hDC, point, nMax);
	// Restore previous pen ...
	SelectObject(hDC, hOldPen);
	// Delete Green pen ...
	DeleteObject(hPen);
	// Release DC
	ReleaseDC(hWnd, hDC);
	// No error!
	return	TRUE;
 }

return	FALSE;		
}

void _LoadMan(HICON icoArray[], int nMax)
{
/* Read Man icons directly from disk (no PE resource) */
int	nIconCount = 0;
for(; nIconCount < nMax; nIconCount++)
 {
	static char szFileName[128];
	wsprintf(szFileName, "IMG%d.ICO", nIconCount + 1);
	if((icoArray[nIconCount] = LoadImage(0, szFileName, IMAGE_ICON, 32, 32, 
								   		 LR_DEFAULTCOLOR|LR_LOADFROMFILE )) == NULL)
	 {
		wsprintf(szFileName,"DOS Error: Cannot load file - "IMG%d.ICO"", 
				 nIconCount + 1);
		throw szFileName;
	 }
 }	
}

BOOL _DrawMan(HWND hWnd, HICON icoArray[], int nX, int nY, RECT *prcClient)
{
static HDC	hDC;
static int nFrameCount = 0;

// Get DC for draw ...
if((hDC=GetDC(hWnd))!=NULL)
 {
	// Set Mountain color to White
	SelectObject(hDC, GetStockObject(WHITE_PEN));
	// Draw Man ...
	DrawIcon(hDC, nX, nY, icoArray[nFrameCount]);
	// Update frame ...
	if(nFrameCount++ >= _FRAME - 1)
		nFrameCount = 0;
	// Release DC
	ReleaseDC(hWnd, hDC);
	// No error!
	return	TRUE;
 }

return	FALSE;			
}

BOOL _ClearRect(HWND hWnd, RECT *prcClient)
{
static HDC	hDC;

// Get DC for draw ...
if((hDC=GetDC(hWnd))!=NULL)
 {
       // Paint prcClient black ...
	FillRect(hDC, prcClient, GetStockObject(BLACK_BRUSH));
	// Release DC
	ReleaseDC(hWnd, hDC);
	// No error!
	return	TRUE;
 }

return	FALSE;			
}

BOOL _Make3D(HWND hWnd, RECT *prcClient, int nOffset, int nMax, BOOL bInit)
{
static HDC	hDC;
static POINT ptLine[10];
static int nLineCount;

// Init 
if(bInit)
 {
	for(nLineCount = 0; nLineCount < 10; nLineCount++)
	 {
		ptLine[nLineCount].x = prcClient->right;
		ptLine[nLineCount].y = (nLineCount * 10) + nOffset;
	 }
	return	TRUE;
 }

// Get DC for draw ...
if((hDC=GetDC(hWnd))!=NULL)
 {
	// Create a thick Green pen ...		
	LOGPEN penGray;
	penGray.lopnStyle = PS_SOLID;
	penGray.lopnWidth.x = 1;
	penGray.lopnColor = RGB(0, 0, 255);

	HPEN hOldPen = NULL,
		 hPen = CreatePenIndirect(&penGray);

	// Set Mountain color to Blue
	hOldPen = SelectObject(hDC, hPen);
	// Set Horizon color to White
	for(int n3D = 3000; n3D > -3000; n3D -= 50)
	 {
		MoveToEx(hDC, 170, 201, NULL);
		LineTo(hDC, n3D, prcClient->bottom);
	 }	 		
	// Draw horizontal Horizon 
	for(nLineCount = 0; nLineCount < 10; nLineCount++)
	 {
		MoveToEx(hDC, 0 , ptLine[nLineCount].y, NULL);
		LineTo(hDC, prcClient->right, ptLine[nLineCount].y);			

		/* Line roll/update */
		ptLine[nLineCount].y+=3;		
		if(ptLine[nLineCount].y >= prcClient->bottom-5)
			ptLine[nLineCount].y = nMax;			
	 }
	// Restore previous pen ...
	SelectObject(hDC, hOldPen);
	// Delete Blue pen
	DeleteObject(hPen);		
	// Release DC
	ReleaseDC(hWnd, hDC);
	// No error!
	return	TRUE;
 }

return	FALSE;					
}
Υ.Γ.


1. Έχω καιρό να γράψω σε καθαρό Windows API καθώς λόγο CodeGear Turbo C++ χρησιμοποιώ πια την βιβλιοθήκη προγραμματισμού VCL.


 


2. Αν υπάρξει ενδιαφέρον – μπορεί κάποια στιγμή να προσθέσω δυνατότητα Double Buffer (στον ορίζοντα) ώστε να ομαλοποιηθεί το rendering.


Καλή συνέχεια!!
 
Τελευταία επεξεργασία από έναν συντονιστή:
xdir είπε:
Μπορείς να κάνεις το σημείο αρχής του ορίζοντα ΜΗ σταθερό; γιατί δεν δείχνει φυσικό να ξεκινάνε όλες οι γραμμές από το ίδιο σημείο!
 
Οκ η τεχνικη (με το χαρακα, χωρις γεωμετρια και υπολογισμους) παει ως εξης

Κανουμε τον οριζοντα και δυο γραμμες που ερχονται προς εμας. Αυτες οι γραμμες ειναι ειτε ενας δρομος που εκτεινεται ευθεια μπροστα μας ειτε μια σειρα απο πλακακια. Η γωνια που σχηματιζουν δεν εχει σημασια, αλλα οσο πιο ανοιχτη τοσο πιο ευκολα

Θετουμε δυο οριζοντιες γραμμες, μια κοντα μας και μια αρκετα μακρυα. Στο τραπεζιο που σχηματιζεται κανουμε ενα Χ (εικ 1)

Ακριβως στο σημειο που τεμονονται οι γραμμες, βαζουμε μια αλλη οριζοντια γραμμη. (2) Υποτιθεται αυτη η γραμμη αν κοιταξουμε το τοπιο ακριβως απο κατοψη, βρισκεται ενδιαμεσα της αποστασης των δυο γραμμων. Εφοσον ομως το βλεπουμε 'πλαγια', η προοπτικη κανει το παιχνιδι της και οι αποστασεις αλλοιωνονται

Στα νεα δυο τραπεζια που σχηματιζονται κανουμε αλλα 2 Χ και περναμε και απο αυτα ενδιαμεσες οριζοντιες γραμμες (3) και επαναλαμβανουμε οσο παρει (4).

Πιθανοτατα να εχουμε ενα προβλημα να σχεδιασουμε τις οριζοντιες γραμμες που ειναι μακρυα μας, ειδικα αν κανουμε τη βλακεια να χρησιμοποιουμε χοντρη γραμμη (οπως εγω! :D )

Το μοπνο που μενει ειναι να επεκτεινουμε τις γραμμες δεξια και αριστερα, να απλωθουν σε ολο το μηκος του σχεδιου. Αν θελουμε πλακακια, σχεδιαζουμε αναλογα και 'καθετες'

Οποτε για να το διατυπωσω μαθηματικα-γεωμετρικα: εστω ενα ισοσκελες τραπεζιο... να βρεθει η μαθηματικη φορμουλα που υπολογιζει την αποσταση μεταξυ κορυφης και σημειου τομης των διαγωνιων του :D
 
Ορίστε και ένας απλός τρόπος με πολύ μικρές αλλαγές στον κώδικα... Το κόλπο είναι να μεταφέρεις το σημείο (χ) που είναι το κέντρο του ορίζοντα σε υψηλότερο σημείο στην οθόνη. Η εικόνα Α είναι όπως είναι τώρα, η Β όπως θα γίνει αν το Χ=0 και το Γ είναι όταν μπεί ένα ωραίο μαύρο παραλληλογραμμο για να καλύψη την πατέντα αχαχαχαχαχαχα... πάντως οπτικά είναι μια χαρά!

picture.php
 
Running Man in C v4.2

@Rakeesh:

Πολύ ενδιαφέρουσα τεχνική. Είμαι σίγουρος ότι την έχω δει σε κάποια παλιά Amiga demos - θα πειραματιστώ οπωσδήποτε μαζί της.

@AA+:

Πράγματι η υλοποίηση της είναι πολύ εύκολη, ειδικά με την βοήθεια του GDI Clipping, οπότε ιδού το νέο αποτέλεσμα (αισίως φτάσαμε στην έκδοση 4.2 :D ):





Κώδικας:
/*******************************************************************************
 Running Man Asm originally written by Nick Kouvaris "retromaniax FTL"
 (http://lightforce.freestuff.gr/),                                          
 C port of Running Man, by xdir (directx@freemail.gr) 	

 v2 - Adds a road under the man, spiked mountains on the background and a
   3D Horizon effect.
 v3 - Rewritten in CodeGear Turbo C++ as a standard Windows application 
   (no console interface).
 v4 - Refined (_Make3D) horizon.
  .1- Refined WindowProcedure
   Proper RNG initilization
  .2- Timing logic isolated from paint logic (eliminating out-of-sync WM_PAINT bugs)

   Tested under Windows XP (SP3) - 1024x768.	
*******************************************************************************/

#include 
#include  /* v4.1 */
#pragma hdrstop

#define	_FRAME	7
#define	_SPEED	60
#define	_MAX_3D_LINE 10

//---------------------------------------------------------------------------
LRESULT CALLBACK WindowProcedure(HWND, UINT, WPARAM, LPARAM);
BOOL _DrawRoad(HWND, int nY, RECT*);
BOOL _DrawMountain(HWND, POINT[], int nMax, RECT*);
BOOL _DrawMan(HWND, HICON[], int nX, int nY, int nFrame, RECT*);
BOOL _ClearRect(HWND, RECT*);

void _LoadMan(HICON icoArray[], int nMax = _FRAME);
void _MakeMountain(POINT point[], int nMaxElement, int nSpace = 10, 
							  int nTopline = 70, int nBaseline = 30);

BOOL _Make3D(HWND hWnd, POINT[], RECT *rcClient, int nOffset, BOOL bInit = FALSE);
void _Update3D(POINT[], int nOffset, RECT*);

#pragma argsused
WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
WNDCLASS wcOwner;
HWND hWnd;

try
 {
	try
	 {
		// Create Window Class ...
		ZeroMemory(&wcOwner, sizeof(wcOwner));
		wcOwner.style = CS_HREDRAW|CS_VREDRAW;
		wcOwner.lpfnWndProc = (WNDPROC)WindowProcedure;
		wcOwner.hInstance = hInstance;
		wcOwner.hbrBackground = GetStockObject(BLACK_BRUSH);
		wcOwner.lpszClassName = "RunManV4";
		wcOwner.hCursor = LoadCursor(NULL, IDC_ARROW);
		if(!RegisterClass(&wcOwner))
			throw "Window Error: Cannot "Register Class"";

		// Create Window ...
		hWnd = CreateWindow(wcOwner.lpszClassName,
							"Running Man v4",
							WS_MINIMIZEBOX|WS_SYSMENU|WS_VISIBLE|WS_OVERLAPPED,
							CW_USEDEFAULT, CW_USEDEFAULT,
							350, 350,
							NULL, NULL, 
							hInstance, 
							NULL);
		if(hWnd == NULL)
			throw "Window Error: Cannot "Create Window"";

		// Kickstart Window (do not use ShowWindow -- ignore nCmdShow) ...
		UpdateWindow(hWnd);

		int nSuccess;
		MSG msgData;
		// Set-up primary message loop ...
		while((nSuccess = GetMessage(&msgData, hWnd, 0, 0L))!=0)
		 {
               // Microsoft suggestion, since GetMessage can return -1
			if(nSuccess == -1)
				break;

			TranslateMessage(&msgData);
			DispatchMessage(&msgData);
		 }
	 }
	catch(char *pszError)
	 {			
		// Error!
		KillTimer(hWnd, WM_USER+5);
		MessageBeep(MB_ICONSTOP);
		MessageBox(NULL, pszError, NULL, MB_ICONSTOP);
	 }
 }
__finally
 {
	// Application clean-up ...
	UnregisterClass(wcOwner.lpszClassName, hInstance);				
 }

return 0;
}
//---------------------------------------------------------------------------
LRESULT CALLBACK WindowProcedure(HWND hWnd, UINT nMessage, 
							 WPARAM wParam, LPARAM lParam)
{
   // Main window procedure
static RECT rcClient, rcClear;
static POINT ptMountain[100];
static HICON hIcon[7];
static PAINTSTRUCT PS;
static int nMan_X = -32, 
		   nMan_Frame = 0;
static POINT pt3D_Lines[10]; /* v4.2 */
static BOOL bMountainUpd = FALSE;

switch(nMessage)
 {
	case WM_CREATE:
		// Load sprite ...
		_LoadMan(hIcon);
		// v4.1) Randomize pseudo-RNG
		srand(time(NULL));
		// Initialize Mountain points ...			
		_MakeMountain(ptMountain, 100);				
		// Get Client dimensions
		GetClientRect(hWnd, &rcClient);
		// Make initial 3D horizon
		_Make3D(hWnd, pt3D_Lines, &rcClient, 201, TRUE);			
		// Setup our live-beat timer
		SetTimer(hWnd, WM_USER+5,_SPEED, NULL);
	return	FALSE;
	case WM_TIMER:
	 switch(wParam)
	  {
		case WM_USER+5:
			// v4.2) Update man position ...
			if(nMan_X++ >= rcClient.right + 32)
			 {
				// v1) Flip man to left
				nMan_X = -32; 
                   // v4.2) Issue a mountain background update
				bMountainUpd = TRUE;
			 }
			// v4.2) Update man frame ...
			if(nMan_Frame++ >= _FRAME - 1)
				nMan_Frame = 0;
			// v4.2) Update horizon wireframe ...
			_Update3D(pt3D_Lines, 205, &rcClient);				
			// Force a non destructive DC invalidation
			InvalidateRect(hWnd, NULL, FALSE);
		return	FALSE;
	  }
	return	FALSE;
	case WM_DESTROY:
		// Shutdown live-beat timer
		KillTimer(hWnd, WM_USER+5);
		// Quit!
		PostQuitMessage(0L);
	return	FALSE;
	case WM_PAINT:
		// Signal DC for paint
		if(BeginPaint(hWnd, &PS) != NULL)
		 {				
			// Get Client dimensions
			GetClientRect(hWnd, &rcClient);
			// v2) Draw mountains
			_DrawMountain(hWnd, ptMountain, 100, &rcClient);
			// v2) Draw a road */ 			
			_DrawRoad(hWnd, 209, &rcClient);
			// v1) Draw man on road
			_DrawMan(hWnd, hIcon, nMan_X, 209 - 32, nMan_Frame, &rcClient);	
			// v1) Move man along the road
			//if(nMan_X > rcClient.right + 32)
			if(bMountainUpd)
			 {
				// Shutdown current update
				bMountainUpd = FALSE;
				// v2) Clear previous mountain
				rcClear.left = rcClear.top = 0;
				rcClear.right= rcClient.right;
				rcClear.bottom=100;
				_ClearRect(hWnd, &rcClear);
				// v2) Generate a new mountain background
				_MakeMountain(ptMountain, 100);
			 }
			// v2) Clear previous horizon
			rcClear.left = 0;
			rcClear.top = 210;
			rcClear.right= rcClient.right;
			rcClear.bottom=rcClient.bottom;
			_ClearRect(hWnd, &rcClear);
			_Make3D(hWnd, pt3D_Lines, &rcClient, 210);
			// Signal DC off paint
			EndPaint(hWnd, &PS);			
		 }
	return	FALSE; /* v4.1) big-fix */
 }

return	DefWindowProc(hWnd, nMessage, wParam, lParam);
}

BOOL _DrawRoad(HWND hWnd, int nY, RECT *prcClient)
{
static HDC	hDC;

// Get DC for draw ...
if((hDC=GetDC(hWnd))!=NULL)
 {
	// Set Road color to Red
	SelectObject(hDC, GetStockObject(WHITE_PEN));
	// Draw Road ...
	MoveToEx(hDC, 0, nY, NULL);
	LineTo(hDC, prcClient->right, nY);		
	// Release DC
	ReleaseDC(hWnd, hDC);
	// No error!
	return	TRUE;
 }

return	FALSE;
}

void _MakeMountain(POINT point[], int nMaxElement, int nSpace, 
							  int nTopline, int nBaseline)
{
/* Generate a extra-large enough mountain like polyline point array */
int nPointCount = 0;
for(; nPointCount < nMaxElement; nPointCount++)
 {
	point[nPointCount].x = nPointCount*nSpace;
	point[nPointCount].y = (rand() % nBaseline) + nTopline; 
 }
}

BOOL _DrawMountain(HWND hWnd, POINT point[], int nMax, RECT *prcClient)
{
static HDC	hDC;

// Get DC for draw ...
if((hDC=GetDC(hWnd))!=NULL)
 {
	// Create a thick Green pen ...		
	LOGPEN penGray;
	penGray.lopnStyle = PS_SOLID;
	penGray.lopnWidth.x = 2;
	penGray.lopnColor = RGB(0, 255, 0);

	HPEN hOldPen = NULL,
		 hPen = CreatePenIndirect(&penGray);

	// Set Mountain color to Green
	hOldPen = SelectObject(hDC, hPen);
	// Draw Mountains ...
	Polyline(hDC, point, nMax);
	// Restore previous pen ...
	SelectObject(hDC, hOldPen);
	// Delete Green pen ...
	DeleteObject(hPen);
	// Release DC
	ReleaseDC(hWnd, hDC);
	// No error!
	return	TRUE;
 }

return	FALSE;		
}

void _LoadMan(HICON icoArray[], int nMax)
{
/* Read Man icons directly from disk (no PE resource) */
int	nIconCount = 0;
for(; nIconCount < nMax; nIconCount++)
 {
	static char szFileName[128];
	wsprintf(szFileName, "IMG%d.ICO", nIconCount + 1);
	if((icoArray[nIconCount] = LoadImage(0, szFileName, IMAGE_ICON, 32, 32, 
								   		 LR_DEFAULTCOLOR|LR_LOADFROMFILE )) == NULL)
	 {
		wsprintf(szFileName,"DOS Error: Cannot load file - "IMG%d.ICO"", 
				 nIconCount + 1);
		throw szFileName;
	 }
 }	
}

BOOL _DrawMan(HWND hWnd, HICON icoArray[], int nX, int nY, int nFrame, RECT *prcClient)
{
static HDC	hDC;

// Get DC for draw ...
if((hDC=GetDC(hWnd))!=NULL)
 {
	// Set Mountain color to White
	SelectObject(hDC, GetStockObject(WHITE_PEN));
	// Draw Man ...
	DrawIcon(hDC, nX, nY, icoArray[nFrame]);
	// Release DC
	ReleaseDC(hWnd, hDC);
	// No error!
	return	TRUE;
 }

return	FALSE;			
}

BOOL _ClearRect(HWND hWnd, RECT *prcClient)
{
static HDC	hDC;

// Get DC for draw ...
if((hDC=GetDC(hWnd))!=NULL)
 {
       // Paint prcClient black ...
	FillRect(hDC, prcClient, GetStockObject(BLACK_BRUSH));
	// Release DC
	ReleaseDC(hWnd, hDC);
	// No error!
	return	TRUE;
 }

return	FALSE;			
}

BOOL _Make3D(HWND hWnd, POINT ptLine[], RECT *prcClient, int nOffset, BOOL bInit)
{
static HDC	hDC;
static int nLineCount;

// Init 
if(bInit)
 {
	for(nLineCount = 0; nLineCount < _MAX_3D_LINE; nLineCount++)
	 {
		ptLine[nLineCount].x = prcClient->right;
		ptLine[nLineCount].y = (nLineCount * 11) + nOffset;
	 }
	return	TRUE;
 }

// Get DC for draw ...
if((hDC=GetDC(hWnd))!=NULL)
 {
	// v4) Define & set a clip region (used later by vertical Horizon)
	HRGN rgnClip = CreateRectRgn(0, nOffset, 
								 prcClient->right, prcClient->bottom);
	SelectClipRgn(hDC, rgnClip);		

	// Create a thick Green pen ...		
	LOGPEN penGray;
	penGray.lopnStyle = PS_SOLID;
	penGray.lopnWidth.x = 1;
	penGray.lopnColor = RGB(0, 0, 255);

	HPEN hOldPen = NULL,
		 hPen = CreatePenIndirect(&penGray);

	// Set Horizon color to Blue
	hOldPen = SelectObject(hDC, hPen);
	// Draw vertical Horizon
	for(int n3D = 3000; n3D > -3000; n3D -= 150)
	 {
		MoveToEx(hDC, 170, 195, NULL);
		LineTo(hDC  , n3D, prcClient->bottom);
	 }

	// Draw horizontal Horizon
	for(nLineCount = 0; nLineCount < 10; nLineCount++)
	 {
		MoveToEx(hDC, 0 , ptLine[nLineCount].y, NULL);
		LineTo(hDC, prcClient->right, ptLine[nLineCount].y);								
	 }
	// Restore previous pen ...
	SelectObject(hDC, hOldPen);
	// Delete Blue pen
	DeleteObject(hPen);		
	// Release Region
	SelectClipRgn(hDC, NULL);
	DeleteObject(rgnClip);
	// Release DC
	ReleaseDC(hWnd, hDC);			
	// No error!
	return	TRUE;
 }

return	FALSE;					
}

void _Update3D(POINT ptLine[], int nOffset, RECT *prcClient)
{
// v4.2) 3D Horizon Lines Roll/Update (as a separated function)
for(int nLineCount = 0; nLineCount < _MAX_3D_LINE; nLineCount++)
	if(ptLine[nLineCount].y > prcClient->bottom-5)
		ptLine[nLineCount].y = nOffset;
	else
		ptLine[nLineCount].y+=3;			
}
 
Τελευταία επεξεργασία από έναν συντονιστή:
xdir τα έγραψες και στα γρήγορα, έτσι μου φαίνεται, και είναι εξαιρετικά τα παραδείγματα σου, συγχαρητήρια.

Μου τρέξαν όλα, ακολούθησα τις οδηγίες για την κονσόλα.
 
Μπράβο σε όλους παιδιά!!!! Αγγελε, δε φτιάχνεις και κανέναν SQL server για 6128; :D
 
FTL είπε:
xdir τα έγραψες και στα γρήγορα, έτσι μου φαίνεται, και είναι εξαιρετικά τα παραδείγματα σου, συγχαρητήρια.Μου τρέξαν όλα, ακολούθησα τις οδηγίες για την κονσόλα.
Σε ευχαριστώ πολύ!! #) -- πράγματι, τα έγραψα γρήγορα, μου αρέσει να γυρίζω που και που σε καθαρό Windows API είναι αναζωογονητικό :D
 
Τελευταία επεξεργασία από έναν συντονιστή:
Rygar είπε:
Μπράβο σε όλους παιδιά!!!! Αγγελε, δε φτιάχνεις και κανέναν SQL server για 6128; :D

Να σου πω το σκεφτόμουν να φτιαξω τον 2005, αλλά τώρα είπα να περιμένω τον 2008 ::) lol... thx for watching dudes... :eek:
 
Πίσω
Μπλουζα