Jump to content

SUBIECTE NOI
« 1 / 5 »
RSS
Cu ce va aparati de cainii agresi...

Nu imi platiti coletul cu cardul ...

Mi-au disparut amigdalitele ?

Exista vreun plan de terorizare p...
 Schimbare adresa DNS IPv4 pe rout...

Recomandare Barebone

Monede JO 2024

Suprasolicitare sistem electric
 CIV auto import

Mutare in MOZAMBIC - pareri, expe...

Scoatere antifurt airtag de pe ha...

Magnet in loc de clește pent...
 Cumparat/Locuit in apartament si ...

Pot folosi sistemul PC pe post de...

Sokol cu distorsiuni de cross-over

Filtru apa potabila cu osmoza inv...
 

Afisare text ca in Matrix folosind C & WinAPI

- - - - -
  • Please log in to reply
6 replies to this topic

#1
dani.user

dani.user

    Guru Member

  • Grup: Senior Members
  • Posts: 30,236
  • Înscris: 24.02.2007
Un scurt exemplu de cum se poate combina C cu WinAPI pentru a afisa text "curgator" inspirat din filmul The Matrix.

Attached File  Untitled.png   13.67K   83 downloads

A se observa impartirea codului in mai multe functii, fiecare avand treaba ei precum si evitarea variabilelor globale.

#include <Windows.h>
#include <stdlib.h>
#include <time.h>

typedef struct Context
{
	const char* availableChars;
	size_t availableCharsLen;
	CHAR_INFO* buffer;
	HANDLE consoleHandle;
	int iteration;
	int millisecondsToWait;
	int maxIterations;
	int newColumnEveryIterations;
	int textStyle;
	int width;
	int height;
} Context;

const char* TODISPLAY = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";

void ClearScreen(const Context* context, char withChar)
{
	COORD start = {0, 0};
	DWORD charsWritten;

	FillConsoleOutputCharacterA(context->consoleHandle, withChar, 
		context->width * context->height, start, &charsWritten);
}

void ClearBuffer(const Context* context, char withChar)
{
	int i;
	for (i = 0; i < context->width * context->height; i++)
	{
		context->buffer[i].Char.AsciiChar = withChar;
		context->buffer[i].Attributes = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE;
	}
}

BOOL IsEmpty(char value)
{
	return ' ' == value;
}

void SetCharacter(Context* context, int row, int column, char value)
{
	CHAR_INFO* info = &(context->buffer[row * context->width + column]);
	info->Attributes = context->textStyle;
	info->Char.AsciiChar = value;
}

void ExpandColumn(Context* context, int column, char value)
{
	CHAR_INFO *current, *below;
	int j;
	for (j = context->height - 1; j > 0; j--)
	{		
		current = &(context->buffer[j * context->width + column]);
		below = &(context->buffer[(j - 1) * context->width + column]);
		if ( ! IsEmpty(below->Char.AsciiChar))
		{
			current->Char.AsciiChar = below->Char.AsciiChar;
			current->Attributes = below->Attributes;
		}
	}
	SetCharacter(context, 0, column, value);
}

void UpdateBuffer(Context* context)
{
	int* emptyColumns = NULL;
	int currentEmptyColumns = 0;
	int i;

	if (context->iteration % context->newColumnEveryIterations == 0)
	{
		//a new column will be added
		//first, search empty columns
		emptyColumns = (int*)malloc(context->width * sizeof(int));
		for (i = 0; i < context->width; i++)
		{
			if (IsEmpty(context->buffer[i].Char.AsciiChar))
			{
				emptyColumns[currentEmptyColumns++] = i;
			}
		}
	}

	for (i = 0; i < context->width; i++)
	{
		if ( ! IsEmpty(context->buffer[i].Char.AsciiChar))
		{
			//move all items on the column 1 step below
			//and add a new character at the first position
			ExpandColumn(context, i, context->availableChars[rand() % context->availableCharsLen]);
		}
	}

	if (currentEmptyColumns > 0)
	{
		//empty columns are available to add
		//pick a random empty one and add a character
		i = emptyColumns[rand() % currentEmptyColumns];
		SetCharacter(context, 0, i, context->availableChars[rand() % context->availableCharsLen]);
	}

	if (NULL != emptyColumns) {
		free(emptyColumns);
	}
}

void DisplayAnimation(Context* context)
{
	COORD bufferSize, bufferStart;
	SMALL_RECT writeRegion;

	bufferSize.X = context->width;
	bufferSize.Y = context->height;
	bufferStart.X = bufferStart.Y = 0;
	writeRegion.Left = writeRegion.Top = 0;
	writeRegion.Right = context->width;
	writeRegion.Bottom = context->height;
	context->iteration = -1;		 

	ClearBuffer(context, ' ');
	ClearScreen(context, ' ');

	while (context->iteration++ < context->maxIterations)
	{
		UpdateBuffer(context);
		WriteConsoleOutputA(context->consoleHandle, context->buffer, bufferSize, bufferStart, &writeRegion);
		Sleep(context->millisecondsToWait);
	}
}

void InitContext(Context* context)
{
	CONSOLE_SCREEN_BUFFER_INFO bufferInfo;
	CONSOLE_CURSOR_INFO cursorInfo;

	context->availableChars = TODISPLAY;
	context->availableCharsLen = strlen(context->availableChars);
	context->millisecondsToWait = 50;
	context->maxIterations = 1000;
	context->newColumnEveryIterations = 3;
	context->textStyle = FOREGROUND_GREEN | FOREGROUND_INTENSITY;
	context->consoleHandle = GetStdHandle(STD_OUTPUT_HANDLE);

	GetConsoleScreenBufferInfo(context->consoleHandle, &bufferInfo);

	context->width = bufferInfo.srwindow.Right - bufferInfo.srwindow.Left + 1;
	context->height = bufferInfo.srwindow.Bottom - bufferInfo.srwindow.Top + 1;
	context->buffer = (CHAR_INFO*)malloc(context->width * context->height * sizeof(CHAR_INFO));

	cursorInfo.dwSize = 1;
	cursorInfo.bVisible = FALSE;
	SetConsoleCursorInfo(context->consoleHandle, &cursorInfo);
}

void ClearContext(Context* context)
{
	free(context->buffer);
}

void InitRandomEngine()
{
	srand((unsigned int)time(0));
}

int main(void)
{
	Context context;

	InitContext(&context);
	InitRandomEngine();

	DisplayAnimation(&context);

	ClearContext(&context);

	return 0;
}


Edited by dani.user, 14 March 2015 - 18:36.


#2
EnachescuAlin

EnachescuAlin

    Active Member

  • Grup: Members
  • Posts: 1,008
  • Înscris: 08.07.2013
Astept o versiune si pentru linux.

#3
dani.user

dani.user

    Guru Member

  • Grup: Senior Members
  • Posts: 30,236
  • Înscris: 24.02.2007
Astepta :D
Dar poate o faci tu pana atunci.

Edited by dani.user, 14 March 2015 - 18:38.


#4
neagu_laurentiu

neagu_laurentiu

    Guru Member

  • Grup: Senior Members
  • Posts: 40,604
  • Înscris: 30.07.2003

 dani.user, on 13 martie 2015 - 18:17, said:

void InitContext(Context* context)
{
CONSOLE_SCREEN_BUFFER_INFO bufferInfo;
...
context->width = bufferInfo.srwindow.Right - bufferInfo.srwindow.Left + 1;
context->height = bufferInfo.srwindow.Bottom - bufferInfo.srwindow.Top + 1;

srWindow in loc de srwindow

#5
dani.user

dani.user

    Guru Member

  • Grup: Senior Members
  • Posts: 30,236
  • Înscris: 24.02.2007
Am observat, dar oricat il editez, forumul il face mic.

#6
OriginalCopy

OriginalCopy

    I'm harmful, fear me please! :))

  • Grup: Senior Members
  • Posts: 27,268
  • Înscris: 10.08.2006

 EnachescuAlin, on 14 martie 2015 - 18:21, said:

Astept o versiune si pentru linux.

Tradu https://github.com/d...d/matrix-curses din python in C. ncurses e acelasi.

#7
EnachescuAlin

EnachescuAlin

    Active Member

  • Grup: Members
  • Posts: 1,008
  • Înscris: 08.07.2013

 OriginalCopy, on 14 martie 2015 - 18:47, said:

Tradu https://github.com/d...d/matrix-curses din python in C. ncurses e acelasi.

Eu il voiam deja facut :)))

Anunturi

Neurochirurgie minim invazivă Neurochirurgie minim invazivă

"Primum non nocere" este ideea ce a deschis drumul medicinei spre minim invaziv.

Avansul tehnologic extraordinar din ultimele decenii a permis dezvoltarea tuturor domeniilor medicinei. Microscopul operator, neuronavigația, tehnicile anestezice avansate permit intervenții chirurgicale tot mai precise, tot mai sigure. Neurochirurgia minim invazivă, sau prin "gaura cheii", oferă pacienților posibilitatea de a se opera cu riscuri minime, fie ele neurologice, infecțioase, medicale sau estetice.

www.neurohope.ro

0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users

Forumul Softpedia foloseste "cookies" pentru a imbunatati experienta utilizatorilor Accept
Pentru detalii si optiuni legate de cookies si datele personale, consultati Politica de utilizare cookies si Politica de confidentialitate