You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
265 lines
9.4 KiB
265 lines
9.4 KiB
// CSweeper.cpp: implementation of the CSweeper class.
|
|
//
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
#include "CSweeper.h"
|
|
|
|
extern TextureBrush *g_paBrCleanBkg;
|
|
extern Bitmap *g_paBmDirtyBkg;
|
|
|
|
CSweeper::CSweeper()
|
|
{
|
|
ZeroMemory(&m_rDesktop,sizeof(m_rDesktop));
|
|
ZeroMemory(&m_vLastPos,sizeof(m_vLastPos));
|
|
m_flStepRadius=0.0f;
|
|
m_flBroomWidth=0.0f;
|
|
m_flSweepLength=0.0f;
|
|
m_paBroomOn=NULL;
|
|
m_paBroomOff=NULL;
|
|
m_paBackground=NULL;
|
|
m_bSweeping=false;
|
|
m_flLastAngle=0.0f;
|
|
m_flDist=0.0f;
|
|
}
|
|
|
|
CSweeper::~CSweeper()
|
|
{
|
|
Destroy();
|
|
}
|
|
|
|
void CSweeper::Destroy()
|
|
{
|
|
if (m_paBroomOn!=NULL) {
|
|
delete m_paBroomOn;
|
|
m_paBroomOn=NULL;
|
|
}
|
|
if (m_paBroomOff!=NULL) {
|
|
delete m_paBroomOff;
|
|
m_paBroomOff=NULL;
|
|
}
|
|
if (m_paBackground!=NULL) {
|
|
delete m_paBackground;
|
|
m_paBackground=NULL;
|
|
}
|
|
}
|
|
|
|
BOOL CSweeper::Init(HWND hWnd)
|
|
{
|
|
int nRand;
|
|
float flWidth;
|
|
float flHeight;
|
|
|
|
Destroy();
|
|
|
|
// Get desktop dimensions (top/left can be negative on multimon)
|
|
GetClientRect(hWnd,&m_rDesktop);
|
|
flWidth=(float)m_rDesktop.right;
|
|
flHeight=(float)m_rDesktop.bottom;
|
|
m_rDesktop.top+=GetSystemMetrics(SM_YVIRTUALSCREEN);
|
|
m_rDesktop.bottom+=GetSystemMetrics(SM_YVIRTUALSCREEN);
|
|
m_rDesktop.left+=GetSystemMetrics(SM_XVIRTUALSCREEN);
|
|
m_rDesktop.right+=GetSystemMetrics(SM_XVIRTUALSCREEN);
|
|
|
|
m_flVelMax=((float)rand()/(float)RAND_MAX)*20.0f+20.0f;
|
|
m_paBroomOn=LoadTGAResource(MAKEINTRESOURCE(IDR_BROOMON));
|
|
m_paBroomOff=LoadTGAResource(MAKEINTRESOURCE(IDR_BROOMOFF));
|
|
m_nSnapshotSize=(int)sqrt(m_paBroomOn->GetWidth()*m_paBroomOn->GetWidth()+(m_paBroomOn->GetHeight()+m_flVelMax*2.0f)*(m_paBroomOn->GetHeight()+m_flVelMax*2.0f));
|
|
m_paBackground=new Bitmap(m_nSnapshotSize,m_nSnapshotSize,PixelFormat32bppPARGB);
|
|
|
|
nRand=rand();
|
|
if (nRand<RAND_MAX/4) { // Start walking from the left side of desktop
|
|
m_vPos.X=(float)m_rDesktop.left;
|
|
m_vPos.Y=((float)rand()/(float)RAND_MAX)*flHeight+m_rDesktop.top;
|
|
m_vVel.X=((float)rand()/(float)RAND_MAX)*5.0f;
|
|
m_vVel.Y=((float)rand()/(float)RAND_MAX)*10.0f-5.0f;
|
|
}
|
|
else if (nRand<2*RAND_MAX/4) { // Start walking from the right side of desktop
|
|
m_vPos.X=(float)m_rDesktop.right;
|
|
m_vPos.Y=((float)rand()/(float)RAND_MAX)*flHeight+m_rDesktop.top;
|
|
m_vVel.X=((float)rand()/(float)RAND_MAX)*-5.0f;
|
|
m_vVel.Y=((float)rand()/(float)RAND_MAX)*10.0f-5.0f;
|
|
}
|
|
else if (nRand<3*RAND_MAX/4) { // Start walking from the top side of desktop
|
|
m_vPos.X=((float)rand()/(float)RAND_MAX)*flWidth+m_rDesktop.left;
|
|
m_vPos.Y=(float)m_rDesktop.top;
|
|
m_vVel.X=((float)rand()/(float)RAND_MAX)*10.0f-5.0f;
|
|
m_vVel.Y=((float)rand()/(float)RAND_MAX)*5.0f;
|
|
}
|
|
else { // Start walking from the bottom side of desktop
|
|
m_vPos.X=((float)rand()/(float)RAND_MAX)*flWidth+m_rDesktop.left;
|
|
m_vPos.Y=(float)m_rDesktop.bottom;
|
|
m_vVel.X=((float)rand()/(float)RAND_MAX)*10.0f-5.0f;
|
|
m_vVel.Y=((float)rand()/(float)RAND_MAX)*-5.0f;
|
|
}
|
|
|
|
m_vAcc.X=((float)rand()/(float)RAND_MAX)*1.0f-0.5f;
|
|
m_vAcc.Y=((float)rand()/(float)RAND_MAX)*1.0f-0.5f;
|
|
m_flStepRadius=((float)rand()/(float)RAND_MAX)*10.0f+45.0f;
|
|
m_flBroomWidth=m_paBroomOn->GetWidth()-6.0f;
|
|
m_flSweepLength=((float)rand()/(float)RAND_MAX)*50.0f+200.0f;
|
|
m_flStepRadius=m_flSweepLength;
|
|
m_vVel=Normalize(m_vVel);
|
|
m_vVel.X*=m_flVelMax;
|
|
m_vVel.Y*=m_flVelMax;
|
|
m_vLastPos=m_vPos;
|
|
|
|
m_bSweeping=false;
|
|
m_flDist=0.0f;
|
|
m_flLastAngle=((float)atan2(m_vVel.Y,m_vVel.X)*180.0f/3.1415f);
|
|
|
|
return true;
|
|
}
|
|
|
|
BOOL CSweeper::Move(Graphics *g)
|
|
// Returns true if moved on screen, false if moved outside screen
|
|
{
|
|
float flAngle;
|
|
float flAngleDist;
|
|
|
|
if (m_bSweeping) {
|
|
m_vPos=m_vPos+m_vVel;
|
|
if ((m_vPos.X<(float)m_rDesktop.left-m_flSweepLength) ||
|
|
(m_vPos.X>(float)m_rDesktop.right+m_flSweepLength) ||
|
|
(m_vPos.Y<(float)m_rDesktop.top-m_flSweepLength) ||
|
|
(m_vPos.Y>(float)m_rDesktop.bottom+m_flSweepLength)) {
|
|
// If sweeper is outside desktop, erase it and remove it
|
|
NoSweep(g);
|
|
return false;
|
|
}
|
|
|
|
Sweep(g);
|
|
}
|
|
else {
|
|
NoSweep(g);
|
|
}
|
|
|
|
if (!m_bSweeping && (m_flDist==0.0f)) {
|
|
// If not sweeping and broom is back at distance 0, start next sweep
|
|
m_bSweeping=true;
|
|
m_flLastAngle=((float)atan2(m_vVel.Y,m_vVel.X)*180.0f/3.1415f);
|
|
m_vPos.X=m_vPos.X-m_vVel.X*(m_flSweepLength/m_flVelMax*0.75f);
|
|
m_vPos.Y=m_vPos.Y-m_vVel.Y*(m_flSweepLength/m_flVelMax*0.75f);
|
|
m_vLastPos=m_vPos;
|
|
|
|
flAngle=((float)atan2(m_vVel.Y,m_vVel.X)*180.0f/3.1415f);
|
|
flAngleDist=((float)rand()/(float)RAND_MAX)*40.0f-20.0f;
|
|
flAngle+=flAngleDist;
|
|
m_vVel.X=(float)cos(flAngle*3.1415f/180.0f)*m_flVelMax;
|
|
m_vVel.Y=(float)sin(flAngle*3.1415f/180.0f)*m_flVelMax;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void CSweeper::Sweep(Graphics *g)
|
|
{
|
|
Graphics *gBackground;
|
|
RectF rect(0.0f,0.0f,m_flBroomWidth,m_flVelMax);
|
|
RectF rect2(0.0f,0.0f,(float)m_paBroomOn->GetWidth(),(float)m_paBroomOn->GetHeight()+m_flVelMax);
|
|
Matrix mat;
|
|
GraphicsPath Path;
|
|
Pen pen(Color(10,0,0,0),2);
|
|
Graphics *gDirty;
|
|
|
|
if (m_flDist!=0.0f) { // If broom has moved already, erase a rect on dirty background
|
|
// Set up the brush transform (opposite from original transform)
|
|
g_paBrCleanBkg->ResetTransform();
|
|
mat.Reset();
|
|
mat.Translate(0.0f,-m_flDist);
|
|
mat.Translate(-(float)m_paBroomOn->GetWidth()/2.0f,-(float)m_paBroomOn->GetHeight()+20.0f);
|
|
mat.Rotate(-m_flLastAngle-270.0f);
|
|
mat.Translate(-m_vLastPos.X+m_rDesktop.left,-m_vLastPos.Y+m_rDesktop.top);
|
|
g_paBrCleanBkg->SetTransform(&mat);
|
|
|
|
// Set up original transform and erase from DirtyBkg a rectangle where the broom moved
|
|
gDirty=new Graphics(g_paBmDirtyBkg);
|
|
gDirty->TranslateTransform(m_vLastPos.X-m_rDesktop.left,m_vLastPos.Y-m_rDesktop.top);
|
|
gDirty->RotateTransform(m_flLastAngle+270.0f);
|
|
gDirty->TranslateTransform((float)m_paBroomOn->GetWidth()/2.0f,(float)m_paBroomOn->GetHeight()-20.0f);
|
|
gDirty->TranslateTransform(0.0f,m_flDist);
|
|
gDirty->FillRectangle(g_paBrCleanBkg,rect);
|
|
|
|
// Draw dirty lines around the broom, to simulate dirty that fell beside the broom
|
|
gDirty->DrawLine(&pen,0.0f,0.0f,0.0f,m_flVelMax+2);
|
|
gDirty->DrawLine(&pen,0.0f,m_flVelMax+2,m_flBroomWidth,m_flVelMax+2);
|
|
gDirty->DrawLine(&pen,m_flBroomWidth,m_flVelMax+2,m_flBroomWidth,0.0f);
|
|
|
|
delete gDirty;
|
|
}
|
|
|
|
// Get the bounds of the broom after rotations
|
|
Path.AddRectangle(rect2);
|
|
mat.Reset();
|
|
mat.Translate(m_vLastPos.X-m_rDesktop.left,m_vLastPos.Y-m_rDesktop.top);
|
|
mat.Rotate(m_flLastAngle+270.0f);
|
|
mat.Translate(m_flBroomWidth/2.0f,0.0);
|
|
mat.Translate(0.0f,m_flDist);
|
|
Path.GetBounds(&rect,&mat,&pen);
|
|
|
|
// Draw on a temp surface whatever was on the dirty background where the broom is to be drawn
|
|
gBackground=new Graphics(m_paBackground);
|
|
gBackground->DrawImage(g_paBmDirtyBkg,0,0,(int)rect.X,(int)rect.Y,(int)rect.Width,(int)rect.Height,UnitPixel);
|
|
|
|
// Draw broom on temp surface
|
|
gBackground->ResetTransform();
|
|
gBackground->TranslateTransform(rect.Width/2.0f,rect.Height/2.0f);
|
|
gBackground->RotateTransform(m_flLastAngle+270.0f);
|
|
gBackground->TranslateTransform(-(float)m_paBroomOn->GetWidth()/2.0f,-(float)m_paBroomOn->GetHeight()/2.0f+m_flVelMax/2.0f);
|
|
gBackground->DrawImage(m_paBroomOn,0,0,0,0,m_paBroomOn->GetWidth(),m_paBroomOn->GetHeight(),UnitPixel);
|
|
delete gBackground;
|
|
|
|
// Draw temp surface to screen
|
|
g->ResetTransform();
|
|
g->DrawImage(m_paBackground,(int)rect.X,(int)rect.Y,0,0,(int)rect.Width,(int)rect.Height,UnitPixel);
|
|
|
|
// Update distance, continue the sweep
|
|
m_flDist+=m_flVelMax;
|
|
if (m_flDist>m_flSweepLength) {
|
|
// If sweep is at the end, start moving broom back
|
|
m_flDist-=m_flVelMax;
|
|
m_bSweeping=false;
|
|
}
|
|
}
|
|
|
|
void CSweeper::NoSweep(Graphics *g)
|
|
{
|
|
Graphics *gBackground;
|
|
RectF rect(0.0f,0.0f,m_flBroomWidth,m_flVelMax);
|
|
RectF rect2(0.0f,0.0f,(float)m_paBroomOn->GetWidth(),(float)m_paBroomOn->GetHeight()+m_flVelMax);
|
|
Matrix mat;
|
|
GraphicsPath Path;
|
|
Pen pen(Color(20,0,0,0),2);
|
|
|
|
// Get the bounds of the broom after rotations
|
|
Path.AddRectangle(rect2);
|
|
mat.Reset();
|
|
mat.Translate(m_vLastPos.X,m_vLastPos.Y);
|
|
mat.Rotate(m_flLastAngle+270.0f);
|
|
mat.Translate(m_flBroomWidth/2.0f,0.0f);
|
|
mat.Translate(0.0f,m_flDist);
|
|
Path.GetBounds(&rect,&mat,&pen);
|
|
|
|
// Draw on a temp surface whatever was on the dirty background where the broom is to be drawn
|
|
gBackground=new Graphics(m_paBackground);
|
|
gBackground->DrawImage(g_paBmDirtyBkg,0,0,(int)rect.X-m_rDesktop.left,(int)rect.Y-m_rDesktop.top,(int)rect.Width,(int)rect.Height,UnitPixel);
|
|
|
|
// Draw broom on temp surface
|
|
gBackground->ResetTransform();
|
|
gBackground->TranslateTransform(rect.Width/2.0f,rect.Height/2.0f);
|
|
gBackground->RotateTransform(m_flLastAngle+270.0f);
|
|
gBackground->TranslateTransform(-(float)m_paBroomOn->GetWidth()/2.0f,-(float)m_paBroomOn->GetHeight()/2.0f-m_flVelMax/2.0f);
|
|
gBackground->DrawImage(m_paBroomOff,0,0,0,0,m_paBroomOn->GetWidth(),m_paBroomOn->GetHeight(),UnitPixel);
|
|
delete gBackground;
|
|
|
|
// Draw temp surface to screen
|
|
g->ResetTransform();
|
|
g->DrawImage(m_paBackground,(int)rect.X-m_rDesktop.left,(int)rect.Y-m_rDesktop.top,0,0,(int)rect.Width,(int)rect.Height,UnitPixel);
|
|
|
|
// Update distance, continue moving back to start of sweep
|
|
m_flDist-=m_flVelMax;
|
|
if (m_flDist<=(m_flSweepLength/m_flVelMax*0.25f)*Magnitude(m_vVel)) {
|
|
// If all the way back, erase last broom, and get ready for next sweep
|
|
g->DrawImage(g_paBmDirtyBkg,(int)rect.X-m_rDesktop.left,(int)rect.Y-m_rDesktop.top,(int)rect.X-m_rDesktop.left,(int)rect.Y-m_rDesktop.top,(int)rect.Width,(int)rect.Height,UnitPixel);
|
|
m_flDist=0.0f;
|
|
}
|
|
}
|