Tetris Clone zu Anfang als leichtes 2D-Projekt?



  • Wer kommt eigentlich immmer auf die Idee, Anfängern tetris als Einstiegsprojekt zu empfehlen? Das ist alles andere als einfach! Hier ein Irrlicht-Beispiel:
    http://abusoft.g0dsoft.com/
    Das sieht doch alles andere als einfach aus, oder?



  • denke, dass das auch einfacher geht



  • denke, dass das auch einfacher geht

    Dann gib mir bitte einen Link auf einen einfacheren Source. 😉

    EDIT: mit der Irrlicht Engine 🙂


  • |  Mod



  • Imho nicht zu vergleichen.


  • |  Mod

    hab gerade waehrend mein backup lief (und ich eh nichts produktives machen konnte) auch mal nen clone gemacht

    //	Copyright (c) 2008, rapso (www.rapso.de)
    //	All rights reserved.
    //
    //	BSD license ( http://en.wikipedia.org/wiki/BSD_license )
    //
    //	constact at rapsoo@hotmail.com 
    //	or
    //	http://www.c-plusplus.net/forum/viewforum-var-f-is-7.html
    ///////////////////////////////////////////////////////////////////////////////
    
    #include <assert.h>
    #include <stdio.h>
    #include <conio.h>
    #include <windows.h>
    #include <intrin.h>
    
    #pragma intrinsic(_rotl16)
    
    const unsigned int	SIZE_X		=	10+2;				//orginal width + border
    const unsigned int	SIZE_Y		=	20+1;				//orginal height + border
    const unsigned int	GAME_SPEED	=	250;				//in ms
    const unsigned int	ROW_SCORE	=	10;					//random number
    const unsigned int	ROW_BORDER	=	1|(1<<(SIZE_X-1));	//left and right border
    const unsigned int	ROW_FILLED	=	(1<<SIZE_X)-1;		//1<<8		==	0x100;
    														//0x100-1	==	0xff;
    typedef unsigned short	tdTetrad;
    
    enum EState
    {
    	ES_START,
    	ES_RESETGAME,
    	ES_GAME,
    	ES_LOSE,
    	ES_END,
    	ES_QUIT
    };
    
    enum ETetrad
    {
    	ET_INVALIDE	=	0,
    	ET_I		=	0x0F00,
    	ET_J		=	0x0470,
    	ET_L		=	0x02e0,
    	ET_O		=	0x0660,
    	ET_S		=	0x06C0,
    	ET_T		=	0x04E0,
    	ET_Z		=	0x0C60,
    	ET_COUNT	=	7
    };
    
    unsigned int	g_Score;
    tdTetrad		g_Tetrad;
    unsigned int	g_PosX;
    unsigned int	g_PosY;
    unsigned short	g_Field[SIZE_Y+3];	//too lazy to bound check in Valid(...)
    unsigned int	g_LastPressedKey;
    
    void GotoPixel(unsigned int x,unsigned int  y) 
    {
    	const HANDLE Out	=	GetStdHandle(STD_OUTPUT_HANDLE);
    	const COORD Pos	=	{x,y};
    	SetConsoleCursorPosition(Out,Pos);
    }
    
    EState ProcessReset(const bool LogicStep)
    {
    	GotoPixel(0,0);
    	printf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n");//clear screen :P
    	printf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n");
    	printf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n");
    
    	for(unsigned int a=0;a<SIZE_Y-1;a++)
    		g_Field[a]	=	ROW_BORDER;
    	g_Field[SIZE_Y-1]	=	~0;//floor
    
    	g_Score				=	0;
    	g_Tetrad			=	ET_INVALIDE;
    	g_LastPressedKey	=	0;
    
    	return ES_GAME;
    }
    
    EState ProcessStart(const bool LogicStep)
    {
    	printf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n");//clear screen :P
    	GotoPixel(20,20);
    	printf("TetriXTM");
    	GotoPixel(10,25);
    	printf("Press SPACE to Start or ESCAPE to quit");
    
    	if(GetAsyncKeyState(VK_SPACE))
    		return ES_RESETGAME;
    	return GetAsyncKeyState(VK_ESCAPE)?ES_END:ES_START;
    }
    
    bool Valid(const unsigned int PosX,const unsigned int PosY,tdTetrad Tetrad)
    {
    	const unsigned int Mask	=	(_rotl16((Tetrad&0xf000)>>12,PosX)&g_Field[PosY+0])|
    								(_rotl16((Tetrad&0x0f00)>> 8,PosX)&g_Field[PosY+1])|
    								(_rotl16((Tetrad&0x00f0)>> 4,PosX)&g_Field[PosY+2])|
    								(_rotl16((Tetrad&0x000f)>> 0,PosX)&g_Field[PosY+3]);
    	return Mask==0;
    }
    
    tdTetrad Rotate(const tdTetrad Tetrad)
    {
    	tdTetrad Ret	=	0;
    	for(unsigned int y=0;y<4;y++)
    		for(unsigned int x=0;x<4;x++)
    			Ret	|=	(Tetrad>>y+x*4&1)<<3-x+y*4;
    
    	return Ret;
    }
    
    void Merge(unsigned short* pField,const unsigned int PosX,const unsigned int PosY,const tdTetrad Tetrad)
    {
    	for(unsigned int y=0;y<SIZE_Y;y++)
    		pField[y]	=	g_Field[y];
    
    	pField[PosY+0]	=	g_Field[PosY+0]	|	(((Tetrad&0xf000)>>12)<<PosX);
    	if(PosY+1<SIZE_Y)
    		pField[PosY+1]	=	g_Field[PosY+1]	|	(((Tetrad&0x0f00)>> 8)<<PosX);
    	if(PosY+2<SIZE_Y)
    		pField[PosY+2]	=	g_Field[PosY+2]	|	(((Tetrad&0x00f0)>> 4)<<PosX);
    	if(PosY+3<SIZE_Y)
    		pField[PosY+3]	=	g_Field[PosY+3]	|	(((Tetrad&0x000f)>> 0)<<PosX);
    }
    
    void CheckScore()
    {
    	//start one row above the floor
    	//topmost row is not taken into account
    	for(unsigned int y=SIZE_Y-2;y>0;y--)
    	{
    		if(g_Field[y]==ROW_FILLED)
    		{
    			g_Score	+=	ROW_SCORE;
    			//collaps stack
    			for(unsigned int y2=y;y2>0;y2--)
    				g_Field[y2]	=	g_Field[y2-1];
    			g_Field[0]	=	ROW_BORDER;
    			y++;	//push by one to compensate the loop y--
    		}
    	}
    }
    
    EState ProcessGame(const bool LogicStep)
    {
    	if(GetAsyncKeyState(VK_ESCAPE))
    		return ES_LOSE;
    
    	//spawn logic
    	if(g_Tetrad==ET_INVALIDE)
    	{
    		switch(rand()%ET_COUNT)
    		{
    			case 0:g_Tetrad	=	ET_I;break;
    			case 1:g_Tetrad	=	ET_J;break;
    			case 2:g_Tetrad	=	ET_L;break;
    			case 3:g_Tetrad	=	ET_O;break;
    			case 4:g_Tetrad	=	ET_S;break;
    			case 5:g_Tetrad	=	ET_T;break;
    			case 6:g_Tetrad	=	ET_Z;break;
    		}
    		g_PosX	=	SIZE_X/2-2;	//half is center of screen, sub 2 for half Tetrad width
    		g_PosY	=	0;
    		if(!Valid(g_PosX,g_PosY,g_Tetrad))
    			return ES_LOSE;
    	}
    	//logic time step
    	if(LogicStep)
    	{
    		if(Valid(g_PosX,g_PosY+1,g_Tetrad))
    			g_PosY++;
    		else
    		{
    			Merge(g_Field,g_PosX,g_PosY,g_Tetrad);
    			CheckScore();
    			g_Tetrad=ET_INVALIDE;
    		}
    	}
    	else
    	{
    		//avoid same action while key still pressed
    		if(!g_LastPressedKey || !GetAsyncKeyState(g_LastPressedKey))	
    		{
    			g_LastPressedKey	=	0;
    			if(GetAsyncKeyState(VK_LEFT) && Valid(g_PosX-1,g_PosY,g_Tetrad))
    			{
    				g_PosX--;
    				g_LastPressedKey	=	VK_LEFT;
    			}
    			if(GetAsyncKeyState(VK_RIGHT) && Valid(g_PosX+1,g_PosY,g_Tetrad))
    			{
    				g_PosX++;
    				g_LastPressedKey	=	VK_RIGHT;
    			}
    			if(GetAsyncKeyState(VK_UP) && Valid(g_PosX,g_PosY,Rotate(g_Tetrad)))
    			{
    				g_Tetrad	=	Rotate(g_Tetrad);
    				g_LastPressedKey	=	VK_UP;
    			}
    			if(GetAsyncKeyState(VK_DOWN))
    			{
    				while(Valid(g_PosX,g_PosY+1,g_Tetrad))
    					g_PosY++;
    				CheckScore();
    				g_LastPressedKey	=	VK_DOWN;
    			}
    		}
    	}
    
    	//display
    	{
    		unsigned short	DrawField[SIZE_Y];
    		Merge(DrawField,g_PosX,g_PosY,g_Tetrad);
    		for(unsigned int y=0;y<SIZE_Y;y++)
    		{
    			GotoPixel(20,y);
    			for(unsigned int x=0;x<SIZE_X;x++)
    				printf(DrawField[y]&(1<<x)?"ÌÌ":"  ");
    		}
    	}
    	GotoPixel(0,2);
    	printf("Score is:\n%8d",g_Score);
    
    	return ES_GAME;
    }
    
    EState ProcessLose(const bool LogicStep)
    {
    	printf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n");//clear screen :P
    	GotoPixel(20,20);
    	printf("Game Over");
    	GotoPixel(20,21);
    	printf("your highscore was:",g_Score);
    	GotoPixel(10,40);
    	printf("Press SPACE to Start or ESCAPE to quit");
    
    	if(GetAsyncKeyState(VK_SPACE))
    		return ES_RESETGAME;
    	return GetAsyncKeyState(VK_ESCAPE)?ES_END:ES_LOSE;
    }
    
    EState ProcessEnd(const bool LogicStep)
    {
    	printf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n");//clear screen :P
    	GotoPixel(20,20);
    	printf("Thx for playing TetriXTM");
    	GotoPixel(15,40);
    
    	Sleep(2500);
    
    	return ES_QUIT;
    }
    
    int main(int argc,char* argv[])
    {
    	const unsigned int	StartTime	=	GetTickCount();
    	unsigned int	LastTick	=	0;
    	EState State	=	ES_START;
    
    	while(State!=ES_QUIT)
    	{
    		const unsigned int CurrentTick	=	(GetTickCount()-StartTime)/GAME_SPEED;
    		const bool LogicTick	=	LastTick!=CurrentTick;
    		LastTick	=	CurrentTick;
    		switch(State)
    		{
    			case ES_START:		State	=	ProcessStart(LogicTick);	break;
    			case ES_RESETGAME:	State	=	ProcessReset(LogicTick);	break;
    			case ES_GAME:		State	=	ProcessGame(LogicTick);		break;
    			case ES_LOSE:		State	=	ProcessLose(LogicTick);		break;
    			case ES_END:		State	=	ProcessEnd(LogicTick);		break;
    		}
    		Sleep(20);//to reduce flickering
    	}
    	return 0;
    }
    

    so, n8



  • ich bin beeindruckt. Habe noch nie ein Konsolenbasiertes Tetris gesehen. Sind aber noch bug drinne



  • ..



  • Tetris hat als Konsolen-Programm begonnen:
    http://www.colinfahey.com/tetris/tetris_de.html
    http://www.colinfahey.com/tetris/original_tetris_start_game02.jpg
    👍

    rapso kommt also ca. 20 Jahre zu spät. 😃

    Schafft einer dieses Programm zum Laufen zu bekommen?
    http://homepages.cwi.nl/~tromp/tetris.html