Click here to Skip to main content
15,881,281 members
Articles / Multimedia / DirectX

Falling Blocks

Rate me:
Please Sign up or sign in to vote.
4.95/5 (11 votes)
17 Apr 2008CPOL 270.1K   9.2K   72  
A game written using Visual C++ and DirectX.
// Shape.cpp: implementation of the CShape class.
//
//////////////////////////////////////////////////////////////////////

#include <windows.h>
#include "BlockList.h"
#include "FlooredBlocks.h"
#include "Shape.h"
#include "resource.h"

extern HINSTANCE g_hInstance;

const short CShape::m_pStockShapes[] = { 
	    11,   // No Of shapes in the array
		2 /*No of orientation shapes */, 4 /*No Of blocks for this shape*/, 
		2,1, 2,2, 3,2, 3,3,     //  O
		1,2, 2,2, 2,1, 3,1,     //  OO 
		                        //   O 
		0,   // Each shape ends with a 0, Takes out the maths challenge :)

		2,4, 
		1,2, 2,2, 3,2, 4,2,     // OOOO
		2,1, 2,2, 2,3, 2,4,
		0,
		2,4, 
		2,1, 2,2, 1,2, 1,3,     //   O
		1,1, 2,1, 2,2, 3,2,     //  OO
		0,                      //  O 

		1,4, 
		2,1, 3,1, 3,2, 2,2,     //  OO
		0,                      //  OO  

		4,4, 
		2,2, 3,2, 2,3, 2,4,     //  OO 
		2,2, 2,3, 3,3, 4,3,     //  O
		3,1, 3,2, 2,3, 3,3,     //  O
		1,2, 2,2, 3,2, 3,3,
		0,

		4,4, 
		2,1, 2,2, 2,3, 3,3,     //  O
		1,3, 2,3, 3,3, 3,2,     //  O
		2,2, 3,2, 3,3, 3,4,     //  OO
		2,2, 3,2, 4,2, 2,3,     
		0,

		4,4, 
		2,1, 1,2, 2,2, 3,2,     //   O
		2,1, 1,2, 2,2, 2,3,     //  OOO 
		1,2, 2,2, 3,2, 2,3,     //   
		2,1, 2,2, 3,2, 2,3,
		0,
///////////////////////   Crazy //////////////////////
		1,4,
		2,1,1,2,3,2,2,3,        //   O
		0,                      //  O O
		                        //   O

    	1,8,                                  //  OOO
		1,1,2,1,3,1, 1,2,3,2, 1,3,2,3,3,3,    //  O O
		0,						              //  OOO

    	4,5,                                  //  OOO
		1,1,2,1,3,1, 1,2,3,2,                 //  O O
		1,1,2,1, 1,2, 1,3,2,3,
		1,2,1,3,2,3,3,3, 3,2,
		2,1,3,1,3,2,2,3,3,3,
		0,

		1,5, 
		2,1, 1,2, 2,2, 3,2, 2,3,    //   O
		                            //  OOO 
		                            //   O
		0,

};

short CShape::s_nNoOfShapes =0;
short CShape::s_cShapesArrayUsage=0;
short CShape::s_nMaxNoOfShapesAllowed=0;
const short** CShape::s_pShapes = NULL;

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CShape::CShape(CFlooredBlocks* pFlooredBlocks, const short* pShapes):m_nX(0), m_nY(0)
{
	m_pFlooredBlocks = pFlooredBlocks;
	
	if (s_cShapesArrayUsage == 0) {
		s_nNoOfShapes = *pShapes;
		if (s_nMaxNoOfShapesAllowed == 0)
			s_nMaxNoOfShapesAllowed = s_nNoOfShapes;
		s_pShapes = new const short*[	s_nNoOfShapes];
		if (s_pShapes == NULL) {
			OutputDebugString("Failed to allocate memory to help the pointer to shape array\n");
			return;
		}
		const short* pCurrShape = pShapes + 1; // +1 to go past the No of shapes 
		
		for (short nI =0; nI < 	s_nNoOfShapes ; nI++)
		{
			s_pShapes[nI]= pCurrShape;
			while (*pCurrShape++); // Go to the next shape.
		}
	}
	s_cShapesArrayUsage++; // Increment the array usage
	
	/* if s_nMaxNoOfShapesAllowed is out of range set it to Total No of shapes */
	if (s_nMaxNoOfShapesAllowed < 0 && s_nMaxNoOfShapesAllowed > s_nNoOfShapes) {
		s_nMaxNoOfShapesAllowed = s_nNoOfShapes;
	}

}

CShape::~CShape()
{
	s_cShapesArrayUsage--; // Decrement the array usage
	if (s_cShapesArrayUsage == 0 ) { // If no one is using it delete the array
		delete[] s_pShapes;
		s_pShapes = NULL;
	}
}

bool CShape::CreateRandShape(short nX, short nY)
{
	m_nColor = rand() % NUM_COLORS;
	m_nShape = rand() % s_nMaxNoOfShapesAllowed;
	m_nRotate = 0;
	m_nX = nX;
	m_nY = nY;
	return CreateShape();
}
//////////////////////////////////////////////////////////
// Creates a shape using the Shape array information
// Creates a list of blocks and gives them the coordinates
// from the array.
//////////////////////////////////////////////////////////
bool CShape::CreateShape()
{
	const short* pShape = s_pShapes[m_nShape];
	SBlock Block;
	m_nTotalRotate = *pShape++;  
	short nNoOfBlocks   = *pShape++;
	pShape+= m_nRotate * nNoOfBlocks * 2;

	const short* pShapeSave = pShape;  // Save the pointer

    // Check for Boundary and Collusion.
	for (int nI = 0 ; nI < nNoOfBlocks ; nI++) {
		Block.nX = *pShape + m_nX;
		pShape++;
		Block.nY = *pShape + m_nY;
		pShape++;
		if (Block.nX  < m_pFlooredBlocks->m_rcBoundary.left || 
			Block.nX  > m_pFlooredBlocks->m_rcBoundary.right)
			return false;
		
		if (Block.nY  > m_pFlooredBlocks->m_rcBoundary.bottom || 
			Block.nY  < m_pFlooredBlocks->m_rcBoundary.top)
			return false;

		if (m_pFlooredBlocks->IsOccupied(Block.nX,Block.nY))
			return false;
	}

	pShape = pShapeSave;  // Use the saved pointer
	Destroy();
	for (nI = 0 ; nI < nNoOfBlocks ; nI++) {
		Block.nColor = m_nColor;
		Block.nX = *pShape;
		pShape++;
		Block.nY = *pShape;
		pShape++;
		Add(Block);
	}
	return true;
}

void CShape::Display()
{
	CBlockList::Display(m_nX, m_nY);
}

bool CShape::MoveTo(short nX, short nY)
{
	m_nX = nX;
	m_nY = nY;
	return true;
}

//////////////////////////////////
// Dumps the List to debugger
///////////////////////////////////
void CShape::dbgDisplay()
{
	CBlockList::dbgDisplay();

}

bool CShape::MoveLeft()
{
	if (IsContained(m_pFlooredBlocks->m_rcBoundary, m_nX-1, m_nY)) {
		if (m_pFlooredBlocks->IsOccupied(*this, m_nX-1, m_nY) == false) {
			m_nX--;
			return true;
		}
	}
	return false;
}

bool CShape::MoveRight()
{
	if (IsContained(m_pFlooredBlocks->m_rcBoundary, m_nX+1, m_nY)) {
		if (m_pFlooredBlocks->IsOccupied(*this, m_nX+1, m_nY) == false) {
			m_nX++;
			return true;
		}
	}
	return false;

}

bool CShape::MoveDown()
{
	if (IsContained(m_pFlooredBlocks->m_rcBoundary, m_nX, m_nY+1)) {
		if (m_pFlooredBlocks->IsOccupied(*this, m_nX, m_nY+1) == false) {
			m_nY++;
			return true;
		}
	}
 
	return false;
}

bool CShape::MoveUp()
{
	if (IsContained(m_pFlooredBlocks->m_rcBoundary, m_nX, m_nY-1)) {
		m_nY--;
		return true;
	}
	return false;
}


bool CShape::Rotate()
{
	short nRotate = m_nRotate;
	m_nRotate++;
	if (m_nRotate == m_nTotalRotate)
		m_nRotate = 0;
		
	if (CreateShape() == false)
		m_nRotate = nRotate;
	return true;
}

void CShape::NextShape()
{
	m_nShape += 1;
	if (m_nShape == s_nMaxNoOfShapesAllowed)
		m_nShape = 0;

	m_nRotate =0;
	Destroy();
	CreateShape();

}

////////////////////////////////////////////////////
//  Check if the Block offset by X ,Y is within
//  given boundary
////////////////////////////////////////////////////
bool CShape::IsContained(RECT rcBoundary, short nX, short nY)
{
	SNODE* pCurr = m_pListHead->pNext;
	while (pCurr) {
		SBlock Block= pCurr->Block;
		if ((Block.nX + nX) < rcBoundary.left || (Block.nX + nX) > rcBoundary.right)
			return false;
		
		if ((Block.nY + nY) > rcBoundary.bottom || (Block.nY + nY) < rcBoundary.top)
			return false;
		pCurr=pCurr->pNext;
	}
	return true;
}

/////////////////////////////////////////////
// Convert to actual coordinates in space
/////////////////////////////////////////////
void CShape::ConvertToSpaceCoord()
{
	SNODE* pCurr = m_pListHead->pNext;
	while (pCurr) {
		pCurr->Block.nX =pCurr->Block.nX  + m_nX;
		pCurr->Block.nY =pCurr->Block.nY + m_nY;
		pCurr= pCurr->pNext;
	}
}

//////////////////////////////////////////////////////////////////
// This number can be set to limit the shapes that will be 
// used from the array. 
// This way some crazy shapes can be added to the end of the 
// array and only be used if the user switches to the crazy mode.
/////////////////////////////////////////////////////////////////
bool CShape::SetMaxNoOfShapesAllowed(short nMax /*= s_nNoOfShapes*/)
{
	if (s_cShapesArrayUsage ==0)  {// No objects are created so s_nNoShapes may be 0
		                          // because the constructor may not have been called yet
								  // Testing on s_nMaxNoOfShapesAllowed is done in the constructor
		s_nMaxNoOfShapesAllowed = nMax;
	}
	if (nMax > 0 && nMax <= s_nNoOfShapes) {
		s_nMaxNoOfShapesAllowed = nMax;
		return true;
	}
	return false;
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions