Δρομέας

FTL

Retro Member
Joined
4 Ιουλ 2007
Μηνύματα
187
Αντιδράσεις
10
Ένας δρομέας διασχίζει το παράθυρο της κονσόλας των Windows XP, είναι γραμμένο με τον Fasm Assembler και χρησιμοποιώ ορισμένα animation frames.

Στο zip αρχείο θα βρείτε το εκτελέσιμο, πιθανόν να μην τρέξει στα Vista όμως, δεν το έχω δοκιμάσει πάντως εκεί.

Το κάνω πόστ παρόλο που ίσως να μην ταιριάζει απόλυτα με το 'Game Programming...the old way' ελπίζω να είναι οκ.

Κώδικας:
; Running Man Asm written by Nick Kouvaris
; http://lightforce.freestuff.gr
; Fasm Assembler v1.67.26

    format pe console
    entry start

    include 'c:\fasm\include\win32axp.inc'

    ICON_SIZE = 744 
    COLUMNS = 80
    ROWS = 25

macro ImageData {
   rept 7 x \{ 
      img\#x FILE 'img'\#\`x\#'.ico':22      
      \}
   } 

macro CreateImages {
   rept 7 x \{
      invoke CreateIconFromResource,img\#x,ICON_SIZE,TRUE,030000h
          mov [hImg\#x],eax     
          \}
       }

section '.code' code readable writeable executable 

start:   
    invoke GetStdHandle,STD_OUTPUT_HANDLE
    mov [stdout],eax

    mov [rect.Left],0
    mov [rect.Top],0
    mov [rect.Right],COLUMNS -1
    mov [rect.Bottom],ROWS -1
    mov [coord.x],COLUMNS
    mov [coord.y],ROWS
    mov [cur.dwSize],25
    mov [cur.bVisible],FALSE

    cinvoke system,<'cls'>
    invoke SetConsoleTitle,<'Running Man'>
    invoke SetConsoleWindowInfo,[stdout],1,rect
    invoke SetConsoleScreenBufferSize,[stdout],dword[coord]   
    invoke SetConsoleCursorInfo,[stdout],cur

    invoke FindWindow,NULL,<'Running Man'>  
    mov [hWnd],eax
    invoke GetDC,[hWnd]
    mov [hDC],eax   

    CreateImages          

    mov esi,-32
run: 
rept 7 x {  
   invoke DrawIcon,[hDC],esi,270,[hImg#x]
   invoke Sleep,60
   inc esi
   inc esi     
   }
    cmp esi,COLUMNS*8
    jl @f
    mov esi,-32
@@:
    cinvoke _kbhit
    test eax,eax
    jz run

    invoke ReleaseDC,[hWnd],[hDC]        
    invoke ExitProcess,0  


section '.data' data readable writeable

struc COORD {
    .x dw ?
    .y dw ?
   } 

struc SMALL_RECT {
    .Left dw ?
    .Top dw ?
    .Right dw ?
    .Bottom dw ?
   } 

struc LPCONSOLE_CURSOR_INFO {
    .dwSize dd ?
    .bVisible db ?
   }      

    cur LPCONSOLE_CURSOR_INFO
    rect SMALL_RECT
    coord COORD           

    stdout dd ?
    hWnd dd ?
    hDC dd ?     
    hImg1 dd ?
    hImg2 dd ?
    hImg3 dd ?
    hImg4 dd ?
    hImg5 dd ?
    hImg6 dd ?
    hImg7 dd ?     

    ImageData


section '.idata' import data readable writeable

    library kernel32,'kernel32.dll',\
   msvcrt,'msvcrt.dll',\
   user32,'user32.dll'   

    import msvcrt,\
   system,'system',\
   _kbhit,'_kbhit'   

    include 'c:\fasm\include\api\kernel32.inc'
    include 'c:\fasm\include\api\user32.inc'
 
Μας αρεσουν μας αρεσουν!

Thanx
 
:worship: :worship: :worship: :worship: :worship: :worship:

Κάθε φορά που ποστάρει ο FTL με πονάνε τα γόνατά μου από τις μετάνοιες :D :D:D:D
 
....και τα δαχτυλα μου απο το παιξιμο :thumbup:
 
Χαίρομαι που σας αρέσουν παιδιά αυτά τα μικρά προγραμματάκια γραμμένα σε asm.

Ψάχνω ένα με πολύχρωμα C-64 μπαλονάκια που πετάνε στην οθόνη και δεν το βρίσκω γμτ.. :D
 
Καλό...πολύ καλό !!! Αν και δεν έχω ασχοληθεί ποτέ με προγραμματισμό ( με εξαίρεση FORTRAN, QBASIC, VB, C++, στη σχολή ) και φυσικά scriptιng....αναγκαστικά για την δουλειά μου... μου αρέσει να βλέπω κώδικα...και να ψάχνομαι να καταλάβω τι κάνει η κάθε γραμμή.
 
Μια ερωτησουλα απο περιεργεια, αν επιτρεπεται, χωρις να εχω την προθεση να εμβαθυνω παραπανω

Απο οτι εχω διαβασει, ειναι ολοκληρη διαδικασια να γραψει κανεις ενα προγραμμα σε γλωσσα υψηλου επιπεδου, μονο και μονο για να μπορει να διαβασει ενα bitmap

Θα περιμενα να ειναι πολυ πιο περιπλοκο σε assembly, μιας και 'παραδοσιακα' τα προγραμματα σε αυτη τη γλωσσα ειναι εξ ορισμου και κατα κανονα πιο περιπλοκα απο αντιστοιχα σε αλλες γλωσσες, ενω το συγγεκριμενο προγραμμα κανει χρηση .ico (bitmap δηλαδη)

Αντιθετα, βλεπω μονο λιγες γραμμες για το ανοιγμα των .ico. Να υποθεσω λοιπον οτι τη διαχειρηση της εικονας την κανουν οι βιβλιοθηκες, και οτι αυτα που εχω διαβασει ειναι Outdated; (πολυ πιθανο)
 
Γειά παιδιά,

disman μου αρέσει και μένα αυτό :)

Rakeesh σε γλώσσα υψηλού επιπέδου είναι εύκολο να φορτώσεις μια εικόνα αφού συνήθως θα υπάρχουν συναρτήσεις όπως η LoadImage() η παρόμοιες για διάφορα format εικόνας gif, jpeg, png κ.τ.λ

Σε γλώσσα χαμηλού επιπέδου όμως όπως η Assembly θα ήτανε λιγάκι πολύπλοκο την εποχή του dos αν έγραφες απο το 0 τον κώδικα.

Το συγκεκριμένο πρόγραμμα είναι μεν παράθυρο κονσόλας αλλά στην ουσία είναι win 32bit εφαρμογή.

Είναι ένα windows παράθυρο περίπου όπως όλα όμως με δικό του console api για προγραμματισμό.

Χρησιμοποιώ επίσης λιγάκι το api των Windows και C βιβλιοθήκη, τίποτα σπουδαίο.

John νάσαι καλά, θα τα πούμε απο κοντά σύντομα.
 
FTL Δρομέας in Borland C

Συγχαρητήρια FTL, μου άρεσε τόσο ώστε αποφάσισα να το κάνω port σε Borland C/C++ compiler.

Το πρόγραμμα απαιτεί τα .ico στο ίδιο κατάλογο όπου βρίσκεται το exe – δεν τα διασύνδεω ως PE resources για να κρατήσω το source όσο πιο απλό γίνεται (μόνο ένα αρχείο .C)

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

#define	COLUMNS	80
#define	ROWS 25
#define	_FRAME 7

int main(int argc, char* argv[])
{
/* Program variables */
SMALL_RECT rcConsole;
COORD crCoord;
CONSOLE_CURSOR_INFO ccInfo;
HDC hDC;
HWND hwndConsole;
INPUT_RECORD inBuffer[16];
DWORD dwInBufferCount;
HANDLE hStdin, hStdout, hIcon[_FRAME];
int nIconCount = 0;
BOOL bEscape = FALSE;

/* Variables initilization */
ZeroMemory(&inBuffer, sizeof(inBuffer));

rcConsole.Left = rcConsole.Top = 0;
rcConsole.Right = COLUMNS - 1;
rcConsole.Bottom= ROWS - 1;

crCoord.X = COLUMNS;
crCoord.Y = ROWS;	

ccInfo.dwSize = 25;
ccInfo.bVisible = FALSE;			

/* Read Man icons directly from disk (no PE resource) */
for( ; nIconCount < _FRAME; nIconCount++)
 {
	static char szFileName[128];
	wsprintf(szFileName, "IMG%d.ICO", nIconCount + 1);
	if((hIcon[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);
		MessageBeep(MB_ICONSTOP);
		MessageBox(NULL, szFileName, NULL, MB_ICONSTOP);
		return	-1;
	 }
 }
nIconCount = 0;	

/* Setup Console window properties and message while loop */
if((hStdin=GetStdHandle(STD_INPUT_HANDLE)) != NULL)
 if((hStdout=GetStdHandle(STD_OUTPUT_HANDLE)) != NULL)
  if(SetConsoleTitle("Running Man"))
   if(SetConsoleWindowInfo(hStdout ,TRUE, &rcConsole))
	if(SetConsoleScreenBufferSize(hStdout, crCoord))		
	 if(SetConsoleCursorInfo(hStdout, &ccInfo))
	  if((hDC=GetDC((hwndConsole = GetConsoleWindow()))) != NULL)
	   if(FlushConsoleInputBuffer(hStdin))
		{
               /* Clear console */
			crCoord.X = crCoord.Y = 0;
			FillConsoleOutputCharacter(hStdout, ' ', COLUMNS * ROWS , crCoord, &dwInBufferCount);

			while(!bEscape)
			 {
				static int nX = 0;
				static DWORD dwKeyEventCount;
				static RECT rcArea;

				/* Peek Console Input Queue - break on ESCAPE key! */
				if(PeekConsoleInput( hStdin , inBuffer, 15, &dwInBufferCount))
				 {
					for(dwKeyEventCount = 0; dwKeyEventCount < dwInBufferCount; dwKeyEventCount++)					
						if(inBuffer[dwKeyEventCount].EventType == KEY_EVENT 
						&& inBuffer[dwKeyEventCount].Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE)
							bEscape = TRUE;
					FlushConsoleInputBuffer(hStdin);						
				 }							

				/* Draw Man icon over Window DC */
				DrawIcon(hDC, nX, 270, hIcon[nIconCount]);				
				/* Wait for a while */
				Sleep(60);

				/* 
				 * Move animation to the Rightmost part of Window then loop it 
				 * from Left */
				if(GetClientRect( hwndConsole, &rcArea) )				
					if(nX++ > rcArea.right)
						nX = -32;
					else
						nX++;

				/* Loop animation */
				if(nIconCount >= _FRAME-1)
					nIconCount = 0;
				else
					nIconCount++;
			 }
		}

// Free system resources
for(nIconCount = 0; nIconCount < _FRAME; nIconCount++)
	DestroyIcon(hIcon[nIconCount]);
ReleaseDC(hwndConsole, hDC);

return 0;
}
Φυσικά μπορεί να υπάρχουν bugs ή άλλες αβλεψίες...

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

FTL ξεκίνησες τον χείμαρο και συνεχίζει ο xdir τώρα :)

Επόμενο port κανείς? :cool:
 
Κανένας με XDK να το μεταφέρει σε XBOX; :D
 
δε κόβω κάνα δάχτυλο καλύτερα? Έχω άλλα 9. Και πες ότι κάποιος το φτιάχνει. Εσύ θα το αγοράσεις? Γιατί μόνο έτσι μπορείς να το "αποκτήσεις" :D
 
Και τι χρειάζεται για να γίνει κάποιος premioum member?

comm_res_feature.jpg


At $49 for 4 months, and $99 per year, premium membership gets you everything you need to get your game in front of Xbox LIVE users.
Τι να πληρώσει? Άααααντε :D Δεν υποστηρίζεται στην Ελλάδα? Μπααα δε το πιστεύω :)

Τεσπα το σκίσαμε το thread

Σχετικό με το θέμα μας τώρα. Μάλλον θα πρέπει να φτιάξουμε εκείνη την βιβλιοθήκη προγραμμάτων που λέγαμε.

Να τα σπάσουμε σε κατηγορίες, πλατφόρμες, ports
 
AMSTRAD PORT ! :D

Shock είπε:
Μπράβο ρε παιδιά !!!FTL ξεκίνησες τον χείμαρο και συνεχίζει ο xdir τώρα :)

Επόμενο port κανείς? :cool:
ΤΩΡΑ ΘΑ ΣΑΣ ΚΟΥΦΑΝΩ... εφτιαξα το port για amstrad !!!

Ορίστε ο κώδικας..

Κώδικας:
10 INK 0,0:BORDER 1:INK 1,18:PEN 1
20 SYMBOL AFTER 32
30 SYMBOL 49,28,28,8,62,8,20,20,20
40 SYMBOL 50,56,56,16,60,80,40,40,72
50 SYMBOL 51,28,28,8,29,42,20,18,34
60 SYMBOL 52,28,28,9,62,72,20,98,2
70 SYMBOL 53,56,56,18,124,144,40,100,4
80 SYMBOL 54,56,56,16,58,84,40,104,4
90 SYMBOL 55,56,56,16,60,48,24,56,8
100 MODE 1
110 TAG
120 x=0
130 y=15
140 r=49
150 re$=""
160 WHILE re$<>"n"
170 re$=INKEY$
180 IF r=55 THEN r=49
190 MOVE x,y:PRINT " ";=x+3:r=r+1:MOVE x,y:PRINT CHR$(r); 
200 FOR retronaniax=1 TO 100:NEXT
210 IF x>640 THEN x=-10
220 WEND
run
Για να το δείτε τώρα να τρέχει έχετε 2 επιλογές!

1) Πατε στον online emulator του Markus cpc.devilmarkus.de και έχοντας Java εγκαταστημένη χρησιμοποιείτε το autotype -->copy-paste.

2) Κατεβάζετε την τελευταία έκδοση του WinApe και έχει File-Paste :thumbup: !!!

Οπότε το βλέπετε και στις δύο περιπτώσεις να πληκτρολογείτε μόνο του σιγα σιγά σαν να υπάρχει ένας δαιμόνιος προγραμματιστής. Αφού τελειώσει πατάτε απλά ENTER αφού σας έχω και το run έτοιμο :D

:happyjump:Amstrad rules:happyjump:

με το πλήκτρο "n" σταματάει η εκτέλεση του κώδικα ή με το γνωστό διπλό esc
 
Τελευταία επεξεργασία από έναν συντονιστή:
Εμμ...ομολογω οτι εντυπωσιαστηκα τα μαλα...μας εφτιαξες ΑΑ+ :thumbup:
 
AA+ που ήσουν τόσο καιρό ? :cool:

Παιδιά συγχαρητήρια σε όλους. Δεσμεύομαι για το port στην Amiga σε ένα μήνα από τώρα που θα τελειώσω με τα τρεχάματα μου.

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

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

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

@AA+:

Ωραίος! Ο Amstrad ( 6128 ) ήταν ο πρώτος μου Η/Υ, αγορασμένος τα Χριστούγεννα του 1987, ωραίες εποχές!! :D

--

Ακολουθεί μια δεύτερη έκδοση στην οποία πρόσθεσα ένα απλό background (ας πούμε κοφτερές βουνοκορφές), έναν δρόμο πάνω στον οποίο τρέχει ο δρομέας και τέλος ένα εφέ βάθους (3D ορίζοντα).

Το πρόγραμμα το δοκίμασα σε Windows XP (SP3) σε ανάλυση 1024x768 - ελπίζω να δουλέψει σε κάθε άλλο διαφορετικό configuration.

Ακολουθεί ένα screen shot για το πως φαίνεται ...



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

 v2 - Adds a road under the man, spiked mountains on the background and a
   3D Horizon effect.

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

#define	COLUMNS	80
#define	ROWS 25
#define	_FRAME 7

void _MakeMountain(POINT point[], int nMaxElement); /* v2 */
void _Make3D(HDC, RECT*, int nOffset, int nMax, BOOL); /* v2 */

int main(int argc, char* argv[])
{
/* Program variables */
SMALL_RECT rcConsole;
COORD crCoord;
CONSOLE_CURSOR_INFO ccInfo;
HDC hDC;
HWND hwndConsole;
INPUT_RECORD inBuffer[16];
DWORD dwInBufferCount;
HANDLE hStdin, hStdout, hIcon[_FRAME];
int nIconCount = 0;
BOOL bEscape = FALSE;

/* Variables initilization */
ZeroMemory(&inBuffer, sizeof(inBuffer));

rcConsole.Left = rcConsole.Top = 0;
rcConsole.Right = COLUMNS - 1;
rcConsole.Bottom= ROWS - 1;

crCoord.X = COLUMNS;
crCoord.Y = ROWS;	

ccInfo.dwSize = 25;
ccInfo.bVisible = FALSE;			

   /* v2) randomize with current time_t */
srand(time(NULL));

/* Read Man icons directly from disk (no PE resource) */
for( ; nIconCount < _FRAME; nIconCount++)
 {
	static char szFileName[128];
	wsprintf(szFileName, "IMG%d.ICO", nIconCount + 1);
	if((hIcon[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);
		MessageBeep(MB_ICONSTOP);
		MessageBox(NULL, szFileName, NULL, MB_ICONSTOP);
		return	-1;
	 }
 }
nIconCount = 0;	

/* Setup Console window properties and message while loop */
if((hStdin=GetStdHandle(STD_INPUT_HANDLE)) != NULL)
 if((hStdout=GetStdHandle(STD_OUTPUT_HANDLE)) != NULL)
  if(SetConsoleTitle("Running Man v2"))
   if(SetConsoleWindowInfo(hStdout ,TRUE, &rcConsole))
	if(SetConsoleScreenBufferSize(hStdout, crCoord))		
	 if(SetConsoleCursorInfo(hStdout, &ccInfo))
	  if((hDC=GetDC((hwndConsole = GetConsoleWindow()))) != NULL)
	   if(FlushConsoleInputBuffer(hStdin))
		{
			/* Make initial mountain */
			static POINT ptMountain[100];				
			_MakeMountain(ptMountain, 100);				

			/* Make initial 3D horizon */
			_Make3D(hDC, NULL, 0, 310, TRUE);

			/* Clear console */
			crCoord.X = crCoord.Y = 0;
			FillConsoleOutputCharacter(hStdout, ' ', COLUMNS * ROWS , crCoord, &dwInBufferCount);

			/* v2) Set Road color to White */
			SelectObject(hDC, GetStockObject(WHITE_PEN));				

			while(!bEscape)
			 {
				static int nX = 0;
				static DWORD dwKeyEventCount;
				static RECT rcArea, rcMountain;

				/* Peek Console Input Queue - break on ESCAPE key! */
				if(PeekConsoleInput( hStdin , inBuffer, 15, &dwInBufferCount))
				 {
					for(dwKeyEventCount = 0; dwKeyEventCount < dwInBufferCount; dwKeyEventCount++)					
						if(inBuffer[dwKeyEventCount].EventType == KEY_EVENT 
						&& inBuffer[dwKeyEventCount].Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE)
							bEscape = TRUE;
					FlushConsoleInputBuffer(hStdin);						
				 }							

				/* Draw Man icon over Window DC */
				DrawIcon(hDC, nX, 270, hIcon[nIconCount]);				
				/* v2) Draw a road */
				MoveToEx(hDC, 0, 300, NULL);
				LineTo(hDC, rcArea.right , 300);
				/* v2) Draw mountains */					
				Polyline(hDC, ptMountain, 100 );					
				/* v2) Update 3d horizon */					
				_Make3D(hDC, &rcArea, 10, 310, FALSE);
				/* Wait for a while */
				Sleep(60);					

				/*
				 * Move animation to the Rightmost part of Window then loop it 
				 * from Left 
				 */
				if(GetClientRect( hwndConsole, &rcArea) )
					if(nX++ > rcArea.right)
					 {
						nX = -32;
						/* v2) Generate new mountains */
						_MakeMountain(ptMountain, 100);	
						rcMountain.top = 0;
						rcMountain.right = rcArea.right;
						rcMountain.bottom = 150;
						FillRect(hDC, &rcMountain, GetStockObject(BLACK_BRUSH));							
					 }
					else
						nX++;

				/* Loop animation */
				if(nIconCount >= _FRAME-1)
					nIconCount = 0;
				else
					nIconCount++;
			 }
		}

// Free system resources
for(nIconCount = 0; nIconCount < _FRAME; nIconCount++)
	DestroyIcon(hIcon[nIconCount]);
ReleaseDC(hwndConsole, hDC);

return 0;
}

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

void _Make3D(HDC hDC, RECT *rcClient, int nOffset, int nMax, BOOL bInit)
{
   /* Generate (if bInit=TRUE) a 3D depth Horizon, else (bInit=FALSE) roll/update it */
static int n3D, nLineCount;
static RECT rcHorizon;
static POINT ptLines[10];

if(bInit)
 {
	for(nLineCount = 0; nLineCount < 10; nLineCount++)
	 {
		ptLines[nLineCount].x = 1000; /* Very large client area -just in case */
		ptLines[nLineCount].y = nMax + (nOffset+=20);
	 }

	return;
 }

rcHorizon.top = nMax;
rcHorizon.right = rcClient->right;
rcHorizon.bottom = rcClient->bottom;
FillRect(hDC, &rcHorizon, GetStockObject(BLACK_BRUSH));							

for(n3D = 8000; n3D > -8000; n3D -= 300)
 {
	MoveToEx(hDC, 400, 300, NULL);
	LineTo(hDC, n3D, 810);
 }	 
for(nLineCount = 0; nLineCount < 9; nLineCount++)
 {
	MoveToEx(hDC, 0, ptLines[nLineCount].y, NULL);
	LineTo(hDC, 1000, ptLines[nLineCount].y);														

	/* Line roll/update */
	ptLines[nLineCount].y+=5;		
	if(ptLines[nLineCount].y>=495)
		ptLines[nLineCount].y = nMax;
 }	
}
Ελπίζω να δουλέψει σωστά!
 
Τελευταία επεξεργασία από έναν συντονιστή:
Αν ενδιαφερεται κανενας, ξερω μια τεχνικη σχεδιασης για να κανεις τις οριζοντιες γραμμες να εχουν τετοιες αποστασεις μεταξυ τους ωστε να φαινεται ρεαλιστικο το βαθος

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