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 + -
显示快捷键?