Sign in to follow this  

Pointer Question

This topic is 3337 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I'm creating a Tetris game using C++ and SDL, but I'm having a bit of trouble with getting some of my code to work. I have a TetrisBlock class that serves as a base class for the the different shapes (Tshape, Line, LLeft, Lright and Odd ) so that they can redefine how they're created and how they rotate. I also have a BlockLogic class that uses a TetrisBlock* as a representation of the block that the user is controlling. BlockLogic has a CreateBlock method that accepts a TetrisBlock& to initialize the TetrisBlock* So, my question is, is there a way to determine what type was passed to CreateBlock and recreate it in BlockLogic? Here's a snippet of my code with commented intentions.
//TSHAPE	userBlock;
//BlockLogic	logic;
//logic.InitBlock( userBlock );

void BlockLogic::InitBlock( const TetrisBlock& newBlock )
{
	delete mTestBlock;
	mTestBlock = new TetrisBlock( newBlock ); //copy info from newBlock

	BlockPosition origin = BlockPosition( ARRAY_CENTER, ARRAY_TOP - 1);

	//I want this to call TSHAPE's create method, not TetrisBlock's
	mTestBlock->Create( origin ); 
	
	SetBlock( ); //modify tetris array
}

Share this post


Link to post
Share on other sites
The general answer for this is: look into 'virtual functions'. They allow a function to be resolved according to the run-time type of the object.

Now, in particular, I think you are overenginnering this. Don't create a new class for every single slight difference you see. Many times the simplest solution is the optimal. A single TetrisBlock class representing a rotating 4x4 grid would be more than enough.

Share this post


Link to post
Share on other sites
I know a simple solution would be for BlockLogic to know all of the different shapes there are and create one depending on what the user wants to create, but I'm trying to wrap my head around the different limitations of abstracting concepts. In this case, I want BlockLogic to be able to create objects derived from TetrisBlock, but I'm not sure if it can do that without knowing exactly which object to create.


class TetrisBlock
{
/* snip */
virtual void Create( const BlockPosition& );
};

class TSHAPE : public TetrisBlock
{
virtual void Create( const BlockPosition& );
};

Create is a virtual function, but since BlockLogic has no information about the TSHAPE class, I'm not sure if it can create a TSHAPE to call its Create function.

Share this post


Link to post
Share on other sites
Then what you want to do is to (modify and) call newBlock's Create function:


class TetrisBlock
{
/* snip */
virtual TetrisBlock* Create( const BlockPosition& );
};

class TSHAPE : public TetrisBlock
{
virtual TetrisBlock* Create( const BlockPosition& );
};

void BlockLogic::InitBlock( const TetrisBlock& newBlock )
{
delete mTestBlock;
BlockPosition origin = BlockPosition( ARRAY_CENTER, ARRAY_TOP - 1);
mTestBlock = newBlock.Create(origin); // Create() now creates a copy of the object and returns it.
SetBlock( ); //modify tetris array
}





Or call it CreateCopy() or something.

Share this post


Link to post
Share on other sites
Quote:
Original post by pLikT
I have a TetrisBlock class that serves as a base class for the the different shapes

Total overkill. For example, you wouldn't think of writing a new class for every possible character string, would you?

Share this post


Link to post
Share on other sites
Then I can just have TSHAPE Create method return a new TSHAPE, or if I want to copy another TetrisBlock, return a new dynamic_cast< TSHAPE* > ( copyTetrisBlock ). That idea hadn't occured to me. Thanks. =)
Quote:
Original post by DevFred
Total overkill. For example, you wouldn't think of writing a new class for every possible character string, would you?
I designed it like that because when I originally made my BlockLogic class, I didn't remember all of the different block shapes.

When I went back to add additional code for the different shapes, I realized I was changing and recompiling the code for block logic, which doesn't need to know that, the Square doesn't rotate, or how the T-shape is formed, it only needs to know what spots in the array the TetrisBlock is taking up. In the case of Tetris, the block shapes are all static, but applying the concept will help me for future projects. At least, that's how I see it.

Share this post


Link to post
Share on other sites
Quote:
Original post by pLikT
I originally made my BlockLogic class, I didn't remember all of the different block shapes.


?!

Quote:
When I went back to add additional code for the different shapes, I realized I was changing and recompiling the code for block logic, which doesn't need to know that


Different shapes do not require any different block logic.

Quote:
the Square doesn't rotate


The square does rotate. It just happens to look the same after rotation as before.

Share this post


Link to post
Share on other sites
Quote:
Original post by pLikT
Then I can just have TSHAPE Create method return a new TSHAPE, or if I want to copy another TetrisBlock, return a new dynamic_cast<TSHAPE*>( copyTetrisBlock ).

Be careful: You cannot simply cast any TSHAPE to any other.
What you write is wrong, you might want
return dynamic_cast<TSHAPE*>(copyTetrisBlock->Create());
or
return dynamic_cast<TSHAPE*>(copyTetrisBlock)->Create();
but both are wrong (if copyTetrisBlock is not a TSHAPE the first returns null and the second crashes). You can at most write a constructor TSHAPE(const TetrisBlock&) for each TSHAPE and then make the Create method return a new TSHAPE(copyTetrisBlock).

I agree with DevFred; I believe your model is much too complicated for that problem (different TSHAPES are not compatible: You really want that?!). Try to keep your design simple and effective (IMHO that part is of greater importance with respect to learning how to make complicated things work).
E.g. You really need a specific empty Rotate function for the square object, or you could simply implement a unique Rotate function which returns Next[shape], with Next[square] = square?

Share this post


Link to post
Share on other sites

This topic is 3337 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this