View Full Version : Tetris Questions
KneeGrow
10-26-2003, 02:22 PM
Alright, I'm trying to make tetris in console but i have a few questions.
1. Do I use the _kbhit() function to get the keyboard input from the user. Because with getch(), it waits until the user inputs but i want the game to continue to run even if the user doesnt input anything. Can anyone help me out with this like give example?
2. Also, how would i detect when a falling piece hits the block of pieces on the bottom? Like collision sorta
3. How to make screen not flicker so much when pieces are falling down?
i, too, made tetris in console. heres my source, you can look at it and maybe get some ideas. its a little buggy, and its kind of an abandoned project because i recently ported it to windows.
for keyboard input, i used the windows function GetAsyncKeyState. i suggest looking it up because its great to use for most any type of input. ( when combined with GetClientRect and GetCursorPos, it can even be used for rudimentary mouse input in console. i suggest looking those up too ).
anyway, here is my source:
and, as far as the flicker goes: to get rid of it, i used my ever so famous display and anim classes. here they are, along with a readme on how to use them:
KneeGrow
10-26-2003, 06:32 PM
Originally posted by ...
and, as far as the flicker goes: to get rid of it, i used my ever so famous display and anim classes. here they are, along with a readme on how to use them:
By the way, thanks for posting your code and helping.
The following errors come up when i try to compile tetris.cpp
--------------------Configuration: Tetris - Win32 Debug--------------------
Compiling...
Tetris.cpp
c:\documents and settings\wayne tie\my documents\c++\downloads\tetris\board.h(38) : error C2374: 'i' : redefinition; multiple initialization
c:\documents and settings\wayne tie\my documents\c++\downloads\tetris\board.h(36) : see declaration of 'i'
c:\documents and settings\wayne tie\my documents\c++\downloads\tetris\tetris.cpp(125) : error C2893: Failed to specialize function template 'void __thiscall Display::variable(any,unsigned short,struct _COORD)'
With the following template arguments:
'unsigned int'
c:\documents and settings\wayne tie\my documents\c++\downloads\tetris\tetris.cpp(126) : error C2893: Failed to specialize function template 'void __thiscall Display::variable(any,unsigned short,struct _COORD)'
With the following template arguments:
'unsigned int'
c:\documents and settings\wayne tie\my documents\c++\downloads\tetris\tetris.cpp(127) : error C2893: Failed to specialize function template 'void __thiscall Display::variable(any,unsigned short,struct _COORD)'
With the following template arguments:
'unsigned int'
c:\documents and settings\wayne tie\my documents\c++\downloads\tetris\tetris.cpp(720) : error C2893: Failed to specialize function template 'void __thiscall Display::variable(any,unsigned short,struct _COORD)'
With the following template arguments:
'int'
Error executing cl.exe.
Tetris.exe - 5 error(s), 0 warning(s)
Also, i have downloaded your disp/anim classes before. The thing is, i dont know which function is used to remove the flickers, could you please help out. Thanks alot
XSquared
10-26-2003, 06:34 PM
Add this at the top of his code to get rid of the first error:
#define for if( 0 ); else for
DavidP
10-26-2003, 06:35 PM
>Do I use the _kbhit() function to get the keyboard input from the user. Because with getch(), it waits until the user inputs but i want the game to continue to run even if the user doesnt input anything. Can anyone help me out with this like give example?
To eliminate this problem, do this:
if ( kbhit( ) )
getch();
It will detect if a key was pressed or not. If a key was pressed, getch() will catch it, if a key was not pressed, it will simply continue onward.
KneeGrow
10-26-2003, 06:41 PM
Thanks guys for all the help... I still don't know how to get the screen to not flicker during clrscr()
I don't know how to use the Display + Anim classes to remove the flicker. Is there any other way to reduce flicker?
the display and anim classes dont flicker at all. the only weird part with using them is drawing out the animation frames and then loading them.
once you get that taken care of ( i explained it as best i could in the readme ). then you basically just put stuff on the display and then show it. it kinda works like a stack. the first things you put into the display will be the background.
you basically "push" all the images onto into the display class buffer, and then use the show() function to "pop" them.
like i said, i really explained them the best i could in the readme. you can copy my code pretty much word for word (changing variables, of course) for any time you use my functions. i tried to make them simple to use where all you have to do is specify an animation and pass it to the display.
the source code is in there, though. if you dont want to use my classes exactly then you can dig through my source and see how i did it. the secret behind the display class is the function WriteConsoleOutput(). i suggest you do some reasearch and figure out how it works, becuase it will make "graphical" console games a WHOLE lot better. it writes everything into the console window at once rather than going through it cell by cell and drawing, therefore eliminating flicker. i can get 2000+ frames per second in console with my display class.
the problem you have with the first error, as was fixed before by XSquared, is that i always use "i" for my iteration in my for loop. if you dont have for loop declarations limited to the scope of the loop, then you will get redefinition errors every time there is a for loop. i use MSVC++.NET and it doesnt give me errors.
as far as the function template errors go, im not sure. it compiles fine on my compiler.
harryP
10-26-2003, 09:30 PM
Yeah, I converted all my drawing functions in MY console graphics library to using 'FillConsoleOutputCharacter' and 'FillConsoleOutputAttributes', which works the same way as WriteConsoleOutput. I noticed a dramatic difference. It's MUCH nicer having it display it all at once rather than character by character. I'm re-uploading my library to its website now, but I have TONS to change in the documentation, so I'd recommend not using it (if you plan to at all ;)) until I've gotten my documentation up to date, because I've changed TONS of stuff.
Basically, my library tries to mimic the way you code things for Windows (well not exactly, but kind of) and the reason I did that was to give people moving from console to Windows a better understanding of Window objects, message loops, etc. You create a Window object, and from there you can do all sorts of stuff. There's a blitmap class which holds bitmap-like images, a sprite class to animate blitmaps, and tons more. I've recently added more Windows-like options by creating a GraphicObject class. This allows you to create pens which modify how lines look when you draw them, and it also allows you to easily display blitmaps and other graphical functions. It's a very handy library, I'm using it right now in my Medieval Conquest game. In that game, I used the library for the mouse and the buttons and message boxes you see.
But yeah...don't use clrscr() everytime you move a drawing, that will cause flicker. Use either '...'s Display and Animation library or my Console Graphics Library, because either of those will help you a lot. The link to my library is in my sig. Good luck!
Brendan
KneeGrow
10-26-2003, 09:42 PM
'...' and HarryP
thanks for help
i ve had both of your graphics libs for a while (CGL and Anim/Disp Functions)
Alright so in the libraries that you two created, what was the function that can allow you to not draw character by character?
and harryp, , what is this WriteConsoleOutput you are talking about? What base library should i use to use this? Windows.h?
'...' how did you detect collision between the falling pieces and the landed pieces/walls in your tetris game?
harryP
10-26-2003, 10:23 PM
Lol oh. Well in mine, I'm guessing you have an older version. I've updated my library now, you can get the new version on my site (in my sig). The updated version has TONS of new stuff. I'll give a really short explanation here of some of the newer stuff, and I'll update the documentation as soon as possible.
Mainly, the blitmap class was updated. Now you don't need to know the size of the blitmap before you use it. It's actually a whole new class. Rather than entering
BLITMAP<X,Y> blt;
It's now
Blitmap blt;
Then you load up the blitmap like with the old version ("blt.LoadBlitmap(someFileName)"). To draw a blitmap, you use the new graphics class I created. Create a GraphicObject object and you'll be able to do tons of stuff.
GraphicObject go(wnd); // Assume wnd is your Window object
go.DrawBlt(blt); // Draw the previously shown blitmap
You can also draw rectangles, lines, points, etc. I'm assuming you're using MSVC++, so that should bring up the list of functions each class has when you want to use one.
The Sprite class was also changed. Instead of using the older blitmap style, you can use the new Blitmap class. To make a sprite of 4 blitmaps, you'd go:
Sprite<4> spr; // 4 blitmaps in the sprite
spr.AddFrame(frame1);
spr.AddFrame(frame2);
// etc.
Whew. I'll get the documentation done asap.
Brendan
ill be honest, i didnt do the collision detection in my tetris game. me and a friend worked on it ( as you can see from the comments at the top of the files ). i did all the interface and graphic stuff and he did all the collision detection.
basically what we did was store an array that represented the game board. each array position was either a block or an empty space. the blocks themselves were seperate arrays that are kind of loaded onto the board, erased, moved down, and then loaded back, etc...
when the array position directly under the block had a block already in it, we wrote the block permenantly to the board and created a new one.
the board class is a little buggy, and like i said we have completely redid it for windows and are working on getting the board class bug free. just take a look at the board class for how we handled the collisions.
here is the documentation for WriteConsoleOutput straight from visual C++.NET:
WriteConsoleOutput
The WriteConsoleOutput function writes character and color attribute data to a specified rectangular block of character cells in a console screen buffer. The data to be written is taken from a correspondingly sized rectangular block at a specified location in the source buffer.
BOOL WriteConsoleOutput(
HANDLE hConsoleOutput, // handle to screen buffer
CONST CHAR_INFO *lpBuffer, // data buffer
COORD dwBufferSize, // size of data buffer
COORD dwBufferCoord, // cell coordinates
PSMALL_RECT lpWriteRegion // rectangle to write
);
Parameters
hConsoleOutput
[in] Handle to the screen buffer. The handle must have GENERIC_WRITE access.
lpBuffer
[in] Pointer to a source buffer that contains the data to be written to the screen buffer. This pointer is treated as the origin of a two-dimensional array of CHAR_INFO structures whose size is specified by the dwBufferSize parameter.
dwBufferSize
[in] Specifies the size, in character cells, of the buffer pointed to by the lpBuffer parameter. The X member of the COORD structure is the number of columns; the Y member is the number of rows.
dwBufferCoord
[in] Specifies the coordinates of the upper-left cell in the buffer pointed to by the lpBuffer parameter to write data from. The X member of the COORD structure is the column, and the Y member is the row.
lpWriteRegion
[in/out] Pointer to a SMALL_RECT structure. On input, the structure members specify the upper-left and lower-right coordinates of the screen buffer rectangle to write to. On output, the structure members specify the actual rectangle that was written to.
Return Values
If the function succeeds, the return value is nonzero.
If the function fails, the return value is zero. To get extended error information, call GetLastError.
Remarks
WriteConsoleOutput treats the source buffer and the destination screen buffer as two-dimensional arrays (columns and rows of character cells). The rectangle pointed to by the lpWriteRegion parameter specifies the size and location of the block to be written to in the screen buffer. A rectangle of the same size is located with its upper-left cell at the coordinates of the dwBufferCoord parameter in the lpBuffer array. Data from the cells that are in the intersection of this rectangle and the source buffer rectangle (whose dimensions are specified by the dwBufferSize parameter) is written to the destination rectangle.
Cells in the destination rectangle whose corresponding source location are outside the boundaries of the source buffer rectangle are left unaffected by the write operation. In other words, these are the cells for which no data is available to be written.
Before WriteConsoleOutput returns, it sets the members of lpWriteRegion to the actual screen buffer rectangle affected by the write operation. This rectangle reflects the cells in the destination rectangle for which there existed a corresponding cell in the source buffer, because WriteConsoleOutput clips the dimensions of the destination rectangle to the boundaries of the screen buffer.
If the rectangle specified by lpWriteRegion lies completely outside the boundaries of the screen buffer, or if the corresponding rectangle is positioned completely outside the boundaries of the source buffer, no data is written. In this case, the function returns with the members of the structure pointed to by the lpWriteRegion parameter set such that the Right member is less than the Left, or the Bottom member is less than the Top. To determine the size of the screen buffer, use the GetConsoleScreenBufferInfo function.
WriteConsoleOutput has no effect on the cursor position.
Windows NT/2000/XP: This function uses either Unicode characters or 8-bit characters from the console's current code page. The console's code page defaults initially to the system's OEM code page. To change the console's code page, use the SetConsoleCP or SetConsoleOutputCP functions, or use the chcp or mode con cp select= commands.
Windows 95/98/Me: WriteConsoleOutputW is supported by the Microsoft Layer for Unicode. To use this, you must add certain files to your application, as outlined in Microsoft Layer for Unicode on Windows 95/98/Me Systems.
Example Code
For an example, see Reading and Writing Blocks of Characters and Attributes.
Requirements
Windows NT/2000/XP: Included in Windows NT 3.1 and later.
Windows 95/98/Me: Included in Windows 95 and later.
Header: Declared in Wincon.h; include Windows.h.
Library: Use Kernel32.lib.
Unicode: Implemented as Unicode and ANSI versions on Windows NT/2000/XP. Also supported by Microsoft Layer for Unicode.
and here is the info for CHAR_INFO, which you will need to know to use WriteConsoleOutput:
CHAR_INFO
The CHAR_INFO structure specifies the Unicode or ANSI character and its attributes. This structure is used by console functions to read from and write to a console screen buffer.
typedef struct _CHAR_INFO {
union {
WCHAR UnicodeChar;
CHAR AsciiChar;
} Char;
WORD Attributes;
} CHAR_INFO, *PCHAR_INFO;
Members
Char
Unicode (wide-character) or ANSI character of a screen buffer character cell, depending on whether it is used with the Unicode or ANSI version of a function.
Attributes
Character attributes. This member can be zero or any combination of the following attributes. Attribute Meaning
FOREGROUND_BLUE Text color contains blue.
FOREGROUND_GREEN Text color contains green.
FOREGROUND_RED Text color contains red.
FOREGROUND_INTENSITY Text color is intensified.
BACKGROUND_BLUE Background color contains blue.
BACKGROUND_GREEN Background color contains green.
BACKGROUND_RED Background color contains red.
BACKGROUND_INTENSITY Background color is intensified.
COMMON_LVB_LEADING_BYTE Leading byte.
COMMON_LVB_TRAILING_BYTE Training byte.
COMMON_LVB_GRID_HORIZONTAL Top horizontal
COMMON_LVB_GRID_LVERTICAL Left vertical.
COMMON_LVB_GRID_RVERTICAL Right vertical.
COMMON_LVB_REVERSE_VIDEO Reverse foreground and background attribute.
COMMON_LVB_UNDERSCORE Underscore.
Requirements
Windows NT/2000/XP: Included in Windows NT 3.1 and later.
Windows 95/98/Me: Included in Windows 95 and later.
Header: Declared in Wincon.h; include Windows.h.
harryP
10-26-2003, 10:58 PM
Eep, my newest update won't work. Give me till tomorrow, it's late lol. I'll let you know when it's up and running.
Brendan
KneeGrow
10-27-2003, 10:09 PM
HarryP, i have a question about the WriteConsoleOutput... I don't understand how it is used and what form the function should take. Could you please give me an example like how i would use it to display things and rid my program of flickers?
... or HarryP do you guys have AIM or MSN or any sort of messenger cause i gotta get some thigns cleared up. I just downloaded the latest CGL but how to remove the flickering from Clrscr with CGL?
and '...', how do i use your Disp and anim classes to remove flickering?
harryP
10-27-2003, 10:50 PM
Sure thing. A quick example:
// Assume that a map has been loaded into a file the characters
// used are stored in a MAP struct (assume it has two 2D arrays:
// one to hold the map's characters and the other holding the
// respective colours)
MAP mp;
// The size of the map
COORD size = { mapSizeX, mapSizeY };
// The location in the array to start drawing from (usually 0,0)
COORD coord = { 0, 0 };
// WriteConsoleOutput needs to use a CHAR_INFO structure as
// it's source buffer (where it's taking the data from), which makes
// things more complicated. I suppose they do it for just that
// reason.
CHAR_INFO *buffer = new CHAR_INFO[mapSizeX * mapSizeY];
// That ^ declared a 1-dimensional CHAR_INFO array. I guess
// they use CHAR_INFO because it can hold character information
// and colour attributes. Anyways, this made the array be the size
// of the picture (or in this case, map) to draw
// Now set up the region on-screen where we will draw
SMALL_RECT rect;
rect.Top = 0;
rect.Left = 0; // Upper-left corner will be 0,0 (adjust this to your
// needs)
rect.Bottom = mapSizeY;
rect.Right = mapSizeX;
// Standard output handle
HANDLE stdOut = GetStdHandle(STD_OUTPUT_HANDLE);
// Now fill the array with the data from the map
int offset = 0;
for(int i = 0; i < height; i++)
{
for(int j = 0; j < width; j++,offset++)
{
buffer[offset].Char.AsciiChar = mp.mapChars[i][j];
buffer[offset].Attributes = mp.mapColours[i][j];
}
}
// Now output the data all at once with WriteConsoleOutput
WriteConsoleOutput(stdOut, // The output handle
buffer, // The source array
size, // The size of the block to draw
coord, // The place to start copying from the source buffer (0,0)
&rect); // The block on-screen to write to
// Erase the buffer
delete [] buffer;
See? It's quite a bit of work. I recommend sticking to one of those libraries, it'll save boatloads of time. But if you really want to do it, more power to you :).
Brendan
EDIT: I have AIM. My sn is HPotter385. And the newest CGL won't quite work, so I'll upload the fixed version here. Again, the documentation won't help you at all, just IM me or email me at steve_alberto@yahoo.com for information, cos a LOT has changed.
harryP
10-27-2003, 11:00 PM
Ok, here it is. Now this is JUST the two required header files. No documentation, no Blitmap Creator, nothing. But this SHOULD work now.
KneeGrow
10-28-2003, 09:03 PM
HarryP:
Did you take out the M_BUTTON_CLICKED identifier from CGL? cause when i try to run the sample documentation code for the buttons, it gives me the error that M_BUTTON_CLICKED is undeclared... help lar lol
harryP
10-28-2003, 10:01 PM
Lol yeah. It's now 'M_LEFT_BUTTON_CLICKED' and 'M_RIGHT_BUTTON_CLICKED'. Sorry -sheepish grin-.
Brendan
harryP
10-28-2003, 11:12 PM
Also, I don't know if you're there yet, but a lot of the graphical functions there now have been superceded with a new class. The GraphicObject class lets you do everything you could before, plus lots more. It takes a reference to a Window object when you create a GraphicObject object. For example:
GraphicObject gfxObj(wnd);
From there, you can do loads of stuff. Draw lines with the MoveTo and LineTo functions (use MoveTo to specify the end point of the line, and LineTo to specify the beginning point). You can also use MoveTo to set the location of where to draw a point with the PointTo function.
Lines are modified through pens. Use the GraphicObject function CreatePen to make a new pen.
GraphicObject gfxObj(wnd);
// Make a new pen
gfxObj.CreatePen(2, // 2 characters wide\tall
STYLE_DOT, // Dotted line (use STYLE_SOLID for a solid line or
// STYLE_DASH for a dashed line
F_BLUE | B_BLUE); // Blue
// If you draw a line, point, or rectangle without creating a pen, a
// default pen is used (1 point width, solid, black)
// Draw a line
gfxObj.MoveTo(10,20);
gfxObj.LineTo(0,0);
// Draws a line from 0,0 to 10,20
Yeah there's a lot more but I don't want to clog this thread with this stuff, so email me and I'll send you some information (I'm still working on updates to the documentation).
Brendan
vBulletin® v3.7.0, Copyright ©2000-2009, Jelsoft Enterprises Ltd.