bubblescene.cpp

来自「网络泡泡被.net管理」· C++ 代码 · 共 667 行

CPP
667
字号
// BubbleScene.cpp: implementation of the BibbleScene class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "..\BubbleLib.h"
#include <math.h>

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

BubbleScene::BubbleScene()
{
	m_width	= 0;
	m_height	= 0;
	m_level	= 0;
	m_data	= NULL;
	m_fWidth	= 0;
	m_fHeight	= 0;
	m_num_data	= 0;
	m_data_temp	= NULL;
	current_bubble_type	= 0;
	next_bubble_type	= 0;
	num_bubble_store	= 0;
	num_bubble_bad		= 0;
	m_state	= PLAYER_STATE_NULL;
}

BubbleScene::~BubbleScene()
{
	Clearup();
}
void BubbleScene::Clearup()
{
	if(m_data)
		delete[] m_data;
	if(m_data_temp)
		delete[] m_data_temp;
	m_width	= 0;
	m_height	= 0;
	m_level	= 0;
	m_data	= NULL;
	m_fWidth	= 0;
	m_fHeight	= 0;
	m_num_data	= 0;
	m_data_temp	= NULL;
	current_bubble_type	= 0;
	next_bubble_type	= 0;
	num_bubble_store	= 0;
	num_bubble_bad		= 0;
	m_state				= PLAYER_STATE_NULL;
}

bool BubbleScene::Create(BYTE width, BYTE height)
{
	if(width<=2 || height<=3)
		return false;
	Clearup();

	m_width		= width;
	m_height	= height;
	m_fWidth	= width-1;
	m_fHeight	= (height-1)*CONST_H*2 + 1;

	m_num_data	= width*height;

	if(m_data)
		delete[] m_data;
	
	m_data	= new UCHAR[m_num_data];
	memset(m_data, 0, m_num_data);
	
	m_data_temp	= new UCHAR[m_num_data];

	current_bubble_type	= 0;
	next_bubble_type	= 0;
	num_bubble_store	= 0;
	num_bubble_bad		= 0;
	return true;
}

bool BubbleScene::CaleShoot(STRUCT_SHOOT_DATA &shoot)
{
	if( m_data==NULL
		|| shoot.x_org<-m_fWidth || shoot.x_org>m_fWidth 
		|| shoot.y_org<0 || shoot.y_org>m_fHeight
		|| shoot.ftan==0)
		return false;
	_CaleShoot(shoot);
//	current_bubble_type	= next_bubble_type;

	return true;
}

void BubbleScene::_CaleShoot(STRUCT_SHOOT_DATA &shoot)
{//要保证shoot的有效

	STRUCT_SHOOT_DATA sd = shoot;
	int left,right,top,bottom;
	if(shoot.ftan>0)
	{//偏右射,反弹点
		sd.x_org = m_fWidth;
		sd.y_org = shoot.y_org + (sd.x_org-shoot.x_org)*shoot.ftan;
		left	= (m_fWidth-shoot.x_org)/2-1;
		if(left<0)
			left=0;
		right	= m_width;
	}
	else
	{
		sd.x_org = -m_fWidth;
		sd.y_org = shoot.y_org + (sd.x_org-shoot.x_org)*shoot.ftan;
		left	= 0;
		right	= (m_fWidth+sd.x_org+1)/2+1;
		if(right>m_width)
		{
			right = m_width;
		}
	}
	//检测有没有和其它泡泡相碰
	{
		float sx=0,sy=0;
		float d2	= 100000000;
		bottom	= shoot.y_org/CONST_H;
		top		= (sd.y_org-1+CONST_H)/2/CONST_H+2;
		if(top>m_height)
		{
			top	= m_height;
		}
		sd.ftan	= -shoot.ftan;
		for(int x=0; x<m_width ; x++)
		{
			for(int y=0; y<m_height; y++)
			{
				if(m_data[x + y*m_width]>0)
				{//有泡泡,检测是否相碰
					float fx=x, fy =y;
					_GetBubbleCenter(fx,fy);
					float fa	= fy - shoot.y_org - (fx-shoot.x_org)*shoot.ftan;
					float d		= fa*fa/(1 + shoot.ftan*shoot.ftan);//被检测泡泡中心到轨迹的距离的平方
#define _RADIUS_COLLIDED	1.8F
					if(d<_RADIUS_COLLIDED*_RADIUS_COLLIDED)
					{//可能相碰了
						//算出相碰点到发射点的距离
						fa = sqrt((fx-shoot.x_org)*(fx-shoot.x_org) + (fy-shoot.y_org)*(fy-shoot.y_org) - d) - sqrt(_RADIUS_COLLIDED*_RADIUS_COLLIDED - d);
						if(fa<d2)
						{//求出相碰时的泡泡坐标
							d2	= fa;
							float dx = fa/sqrt(1 + shoot.ftan*shoot.ftan);
							if(shoot.ftan<0)
								dx	= -dx;
							sx	= shoot.x_org + dx;//sin
							sy	= shoot.y_org + dx*shoot.ftan;//cos
						}
					}
				}
			}
		}
		if(d2==100000000 || sx>m_fWidth || sx<-m_fWidth)
		{
			if(sd.y_org>=m_fHeight)
			{//到顶
				sx	= shoot.x_org + (m_fHeight - shoot.y_org)/shoot.ftan;//(sd.y_org-m_fHeight)/shoot.ftan;
				shoot.f_stop = m_fHeight;
				sy	= m_fHeight;
				_GetBubblePos(sx, sy);
				shoot.x_stop	= sx;
				shoot.y_stop	= sy;
				return;
			}
			_CaleShoot(sd);
			shoot.x_stop	= sd.x_stop;
			shoot.y_stop	= sd.y_stop;
			shoot.f_stop	= sd.f_stop;
			return;
		}
		else
		{
			if(sy>=m_fHeight)
			{//到顶
				sx	= shoot.x_org + (m_fHeight - shoot.y_org)/shoot.ftan;//(sd.y_org-m_fHeight)/shoot.ftan;
				shoot.f_stop = m_fHeight;
				sy	= m_fHeight;
				_GetBubblePos(sx, sy);
				shoot.x_stop	= sx;
				shoot.y_stop	= sy;
				return;
			}
			shoot.f_stop	= sy;
			_GetBubblePos(sx, sy);
			shoot.x_stop	= sx;
			shoot.y_stop	= sy;
			return;
		}
	}



	return ;
}

bool BubbleScene::GetBubbleCenter(float& x, float& y)
{//
	if(m_data==NULL
		|| x<0 || x>=m_width
		|| y<0 || y>=m_height)
		return false;
	_GetBubbleCenter(x,y);
	return true;
}

void BubbleScene::_GetBubbleCenter(float& x, float& y)
{//要保证x,y的有效
	int odd = (m_level+int(y))%2;
	y	= 1 + y*CONST_H*2;
	x	= int(x)*2 - m_fWidth;
	if(odd)
	{
		x+=1;
	}
	return;
}

bool BubbleScene::GetBubblePos(float& x, float& y)
{//
	if(m_data==NULL
		|| x<-m_fWidth || x>m_fWidth 
		|| y<0 || y>m_fHeight
		|| x<0 || x>=m_width
		|| y<0 || y>=m_height)
		return false;
	_GetBubblePos(x,y);
	return true;
}
void BubbleScene::_GetBubblePos(float& x, float& y)
{//要保证x,y的有效
	if(y<1-CONST_H)
		y=0;
	else
		y = int((y-1+CONST_H)/2/CONST_H);//	= 1 + y*CONST_H*2;
	int odd = (m_level+int(y))%2;
	if(odd)
	{
		x-=1;
	}
	x	= int((x + m_width)/2);//	= int(x)*2 - m_fWidth;
	if(odd && x==m_width-1)
	{
		x-=1;
	}
	return;
}


float BubbleScene::TrackFun(STRUCT_SHOOT_DATA* p_shoot, float y)
{
	if( p_shoot==NULL)
		return 0;
	STRUCT_SHOOT_DATA sd = *p_shoot;
	if(p_shoot->ftan>0)
	{//偏右射,反弹点
		sd.x_org = m_fWidth;
	}
	else
	{
		sd.x_org = -m_fWidth;
	}
	sd.y_org = p_shoot->y_org + (sd.x_org-p_shoot->x_org)*p_shoot->ftan;
	
	if(sd.y_org>=y)
	{
		return p_shoot->x_org + (y - p_shoot->y_org)/p_shoot->ftan;
	}
	else
	{//反弹
		sd.ftan	= -p_shoot->ftan;
		return TrackFun(&sd, y);
	}
	
}

BYTE BubbleScene::GetBubble(int x, int y)
{
	if(x<0 || x>=m_width
		|| y<0 || y>=m_height
		|| m_data==NULL)
		return 0;
	return m_data[y*m_width+x];
}

void BubbleScene::SetBubble(int x, int y, BYTE bubble)
{
	if(x<0 || x>=m_width
		|| y<0 || y>=m_height
		|| m_data==NULL)
		return;
	m_data[y*m_width+x]	= bubble;
}

void BubbleScene::SetBubble(int idx, BYTE bubble)
{
	if(idx<0 || idx>=m_num_data)
		return;
	m_data[idx]	= bubble;
}

BYTE BubbleScene::GetBubble(int idx)
{
	if(idx<0 || idx>=m_num_data)
		return 0;
	return m_data[idx];
}

int BubbleScene::PopBubble(int x, int y, int pop_num)
{
	if(x<0 || x>=m_width
		|| y<0 || y>=m_height
		|| m_data==NULL
		|| m_data[y*m_width + x]%10==0)
		return 0;
	for(int i=0; i<m_num_data; i++)
	{
		m_data_temp[i]	= 0;
	}
	_MarkPop(x, y, m_data[y*m_width + x]%10);//爆掉的
	int iRet	= 0;
	for(i=0; i<m_num_data; i++)
	{
		if(m_data_temp[i]==1)
		{
			iRet ++;
		}
	}
	if(iRet<pop_num)
		return 0;
	std::set<BYTE>	set_block_mark;
	set_block_mark.insert(1);
	set_block_mark.insert(2);
	set_block_mark.insert(3);
	_PopBubble(x, y, set_block_mark);
	for(i=0; i<m_num_data; i++)
	{
		if(m_data_temp[i]==2)
		{
			on_bubble_pop(i);
			m_data[i]	= 0;
		}
		else if(set_block_mark.find(m_data_temp[i])!=set_block_mark.end())
		{
			on_bubble_spread(i);
			m_data[i]	= 0;
			iRet++;
		}
	}
	return iRet;
}

void BubbleScene::_PopBubble(int x, int y, std::set<BYTE>& set_block_mark)
{
	if(x<0 || x>=m_width || y<0 || y>=m_height)
		return;//出界,返回
	int idx		= y*m_width + x;
//	if(m_data[idx]%10==0)
//	{//没有泡泡,返回
//		return;
//	}
	if(m_data_temp[idx]==2)
		return;
	if(m_data_temp[idx]==1)
	{//是爆破的泡
		m_data_temp[idx]=2;
		if((y+m_level)%2)
		{
			_PopBubble(x, y+1, set_block_mark);
			_PopBubble(x+1, y+1, set_block_mark);
			_PopBubble(x-1, y, set_block_mark);
			_PopBubble(x+1, y, set_block_mark);
			_PopBubble(x, y-1, set_block_mark);
			_PopBubble(x+1, y-1, set_block_mark);
		}
		else
		{
			_PopBubble(x-1, y+1, set_block_mark);
			_PopBubble(x, y+1, set_block_mark);
			_PopBubble(x-1, y, set_block_mark);
			_PopBubble(x+1, y, set_block_mark);
			_PopBubble(x-1, y-1, set_block_mark);
			_PopBubble(x, y-1, set_block_mark);
		}
		return;
	}
	if(m_data[idx]%10!=0 && set_block_mark.find(m_data_temp[idx])==set_block_mark.end())
	{//有泡泡而且没有标记
		//	std::set<BYTE>::iterator	it = set_block_mark.lower_bound(255);
		int mark	= *set_block_mark.rbegin();//生成新的标记
		set_block_mark.insert(mark+1);
		if(_MarkBlock(x, y, mark))//标记封闭区域
		{
			//set_block_mark.insert(mark+1);
		}
		else
		{//不是封闭区域,删除标记表记录
			set_block_mark.erase(mark);
		}
	}
	return;
}
void BubbleScene::_MarkPop(int x, int y, BYTE bubble)
{
	if(x<0 || x>=m_width || y<0 || y>=m_height)
		return;//出界,返回
	int idx		= y*m_width + x;
	if(m_data_temp[idx]==1)
		return;//已经标志了
	if(m_data[idx]%10==bubble)
	{
		m_data_temp[idx]	= 1;
		if((y+m_level)%2)
		{
			_MarkPop(x, y+1, bubble);
			_MarkPop(x+1, y+1, bubble);
			_MarkPop(x-1, y, bubble);
			_MarkPop(x+1, y, bubble);
			_MarkPop(x, y-1, bubble);
			_MarkPop(x+1, y-1, bubble);
		}
		else
		{
			_MarkPop(x-1, y+1, bubble);
			_MarkPop(x, y+1, bubble);
			_MarkPop(x-1, y, bubble);
			_MarkPop(x+1, y, bubble);
			_MarkPop(x-1, y-1, bubble);
			_MarkPop(x, y-1, bubble);
		}
	}
	return;
}

bool BubbleScene::_MarkBlock(int x, int y, BYTE mark)
{//标记一个封闭范围
	if(x<0 || x>=m_width || y<0)
		return true;//出界,返回
	int idx		= y*m_width + x;
	if(m_data_temp[idx]>0)
	{
		if(m_data_temp[idx]==mark)
		{//已经标记过了
			return true;
		}
		if(m_data_temp[idx]>2)
			return false;//测到标记,封闭范围无效
		return true;
	}
	if(m_data[idx]==0)
	{//没有泡泡,返回
		return true;
	}
	else
	{//有泡泡,递归进入下一层
		if(y>=m_height-1)
			return false;//到顶,封闭范围无效
		m_data_temp[idx]	= mark;
		if((y+m_level)%2)
		{
			if(_MarkBlock(x, y+1, mark))//左上
				if(_MarkBlock(x+1, y+1, mark))//右上
					if(_MarkBlock(x-1, y, mark))//左
						if(_MarkBlock(x+1, y, mark))//右
							if(_MarkBlock(x, y-1, mark))//左下
								return _MarkBlock(x+1, y-1, mark);//右下
		}
		else
		{
			if(_MarkBlock(x-1, y+1, mark))//左上
				if(_MarkBlock(x, y+1, mark))//右上
					if(_MarkBlock(x-1, y, mark))//左
						if(_MarkBlock(x+1, y, mark))//右
							if(_MarkBlock(x-1, y-1, mark))//左下
								return _MarkBlock(x, y-1, mark);//右下
		}
		return false;
	}
}

int BubbleScene::GetIndexAround(int x, int y, int way)
{
	if ((y+m_level)%2)
	{
		switch(way%WAY_SIZE) {
		case WAY_NORTH_WEST:
			if (y+1>=m_height)
				return -1;
			return (y+1)*m_width+x;
		case WAY_NORTH_EAST:
			if (y+1>=m_height)
				return -1;
			if (x+1>=m_width)
				return -1;
			return (y+1)*m_width+x+1;
		case WAY_WEST:
			if (x-1<0)
				return -1;
			return y*m_width+x-1;
		case WAY_EAST:
			if (x+1>=m_width)
				return -1;
			return y*m_width+x+1;
		case WAY_SOUTH_WEST:
			if (y-1<0)
				return -1;
			return (y-1)*m_width+x;
		case WAY_SOUTH_EAST:
			if (y-1<0)
				return -1;
			if (x+1>=m_width)
				return -1;
			return (y-1)*m_width+x+1;
		}
	}
	else
	{
		switch(way%WAY_SIZE) {
		case WAY_NORTH_WEST:
			if (y+1>=m_height)
				return -1;
			if (x-1<0)
				return -1;
			return (y+1)*m_width+x-1;
		case WAY_NORTH_EAST:
			if (y+1>=m_height)
				return -1;
			return (y+1)*m_width+x;
		case WAY_EAST:
			if (x+1>=m_width)
				return -1;
			return y*m_width+x+1;
		case WAY_WEST:
			if (x-1<0)
				return -1;
			return y*m_width+x-1;
		case WAY_SOUTH_WEST:
			if (y-1<0)
				return -1;
			if (x-1<0)
				return -1;
			return (y-1)*m_width+x-1;
		case WAY_SOUTH_EAST:
			if (y-1<0)
				return -1;
			return (y-1)*m_width+x;
		}
	}
	return -1;
}

bool BubbleScene::IsValid()
{
	return (m_data!=NULL && m_data_temp!=NULL && m_width!=0 && m_height!=0);
}

bool BubbleScene::IsLost()
{
	if(!IsValid())
		return true;
	for(int i=0; i<m_width; i++)
	{
		if(m_data[i]!=0)
			return true;
	}
	return false;
}

bool BubbleScene::IsWin()
{
	if(!IsValid())
		return false;
	for(int i=m_width; i>0; i--)
	{
		if(m_data[m_num_data-i]!=0)
			return false;
	}
	return true;
}


void BubbleScene::Win()
{
	if(m_state==PLAYER_STATE_PLAYING)
	{
		m_state	= PLAYER_STATE_WIN;
		on_state_change();
	}
}

void BubbleScene::Lost()
{
	if(m_state==PLAYER_STATE_PLAYING)
	{
		m_state	= PLAYER_STATE_LOST;
		on_state_change();
	}

}

void BubbleScene::switch_ready()
{
	switch(m_state) {
	case PLAYER_STATE_READY:
		m_state	= PLAYER_STATE_NULL;
		on_state_change();
		break;
	case PLAYER_STATE_NULL:
	case PLAYER_STATE_LOST:
	case PLAYER_STATE_WIN:
		m_state	= PLAYER_STATE_READY;
		on_state_change();
		break;
	default:
		break;
	}
}


bool BubbleScene::update_state()
{
	if (m_state!=PLAYER_STATE_PLAYING)
	{
		return false;
	}
	if(IsLost())
	{
		m_state	= PLAYER_STATE_LOST;
		on_state_change();
		return true;
	}
	if(IsWin())
	{
		m_state	= PLAYER_STATE_WIN;
		on_state_change();
		return true;
	}
	return false;
}


void BubbleScene::AddGoodBubble(int num)
{
	if(num + num_bubble_store > 255)
		num_bubble_store=255;
	else if (num + num_bubble_store < 0)
		num_bubble_store=0;
	else
		num_bubble_store	+= num;
}

void BubbleScene::AddBadBubble(int num)
{
	if(num + num_bubble_bad > 255)
		num_bubble_bad=255;
	else if (num + num_bubble_bad < 0)
		num_bubble_bad=0;
	else
		num_bubble_bad	+= num;
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?