⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mouse.cpp

📁 仿游戏 Diablo 的源代码
💻 CPP
字号:
#include "gl.h"
#include "gengine.h"

#define DEFAULT_MOUSE_CURSOR "mouse.tga"
#define DEFAULT_CURSOR_SIZE   18 //16

int mouseInstalled = false;
int volatile mouseX, mouseY;	// used by the external code
DWORD volatile mousePos;	// high word for X, low word for Y
int volatile mouseB; 		// mouse button state
int mouseCursorFroze = false;

static int volatile mousex, mousey;	// store the up-to-date mouse position
static DWORD c, currentCursor, currentFrame, frames, types;
static int on = -1;
static Bitmap *bmpWork, *bmpCursor;
static int mouseFocusX = 0, mouseFocusY = 0;
static int mx, my; // internally used for updating mouse cursor
static int timer, speed; // used for animate curosr, 20ms
static int ml, mt, mr, mb;	// mouse cursor range;

/*  illustrate 
 double buffer 用来缓冲向screen的输出
 save screen 保存将被破坏的屏幕
 注意:由于采用了分页动画,当screen切换到backscreen后,原来screen上被破坏的
	 内容不被恢复 !!
 
	bmpWork: |~~~~~~~~~~~|~~~~~|
			 |           |     | <---- save screen 
			 |   double  |-----|   
			 |   buffer  |     |
			 |___________|_____|
	bmpCursor:
			|~~~~|~~~~|~~~~|~
			|    |    |    | ...  animate cursor type 1
			|~~~~|~~~~|~~~~|~
			|    |    |    | ...  animate cursor type 2
			|~~~~|~~~~|~~~~|~
			|    |    |    | ...  animate cursor type 3 ...
*/

// select current cursor bitmap
void MouseSetCursor( DWORD type )
{
	if( type > types )
		return;
	currentFrame = 0;
	currentCursor = type;
	if( on < 0 )
		return;
	// copy to double buffer
	bmpWork->Blit( bmpWork, 0, 0, 2 * c, 0, c, c );
	// draw mouse cursor in double buffer
	bmpCursor->BlitMask( bmpWork, 0, 0, currentFrame * c, currentCursor * c, c, c );

	int cl = screen->GetClip( );
	screen->SetClip( false );
	// copy double buffer to screen
	bmpWork->Blit( screen, mx - mouseFocusX, my - mouseFocusY, 0, 0, c, c );
	screen->SetClip( cl );
}

void MouseSetRange( int l, int t, int r, int b )
{
	l = MIN( l, (int)screenInfo.width );
	r = MIN( r, (int)screenInfo.width );
	t = MIN( t, (int)screenInfo.height );
	b = MIN( b, (int)screenInfo.height );
	l = MAX( l, 0 );
	r = MAX( r, 0 );
	t = MAX( t, 0 );
	b = MAX( b, 0 );
	ml = MIN( l, r );
	mr = MAX( l, r );
	mt = MIN( t, b );
	mb = MAX( t, b );
	
	MouseSetPos( mx, my );	//adjust mousecursor position
}

void MouseSetSpeed( int xspeed, int yspeed )
{
}


// how far(mickeys) has the mouse moved since the last call to this function
void MouseGetMickeys( int& x, int& y )
{
}

// this function is used by UpdateScfeen()
void MouseBeforeUpdatescreen( void )
{
	if( mouseInstalled && on == 0 ){
		int cl = backScreen->GetClip();
		backScreen->SetClip( false );
		// save backscreen
		backScreen->Blit( bmpWork, 2 * c, 0, mx - mouseFocusX, my - mouseFocusY, c, c );
		// draw mouse cursor on backScreen
		bmpCursor->BlitMask( backScreen, mx - mouseFocusX, my - mouseFocusY, 
							currentFrame * c, currentCursor * c, c, c );
		backScreen->SetClip( cl );
	}
}

void MouseSetPos( int x, int y )
{
	if( x < ml ) x = ml;
	else if( x >= mr ) x = mr-1;
	if( y < mt ) y = mt;
	else if( y >= mb ) y = mb-1;

	if( on == 0 ){
		MouseOff();
		mx = mousex = mouseX = x;
		my = mousey = mouseY = y;
		mousePos = ( mx << 16 ) | ( my & 0xffff );
		MouseOn();
	}
}

int MouseLoadCursor( DWORD cl, DWORD ts, DWORD fs, DWORD fps, Bitmap *bmp )
{ // c:边长 ts:光标类型数 fs:帧数 v:帧速 bmp:图片
	if( (DWORD)bmp->width < cl * fs || (DWORD)bmp->height < cl * ts || bmp == NULL )
		return -1;

	Bitmap* bmpW = CreateBitmap( cl*2, cl*2 );
	if( bmpWork == NULL )
		return -1;
		
	MouseOff();
	if( bmpCursor )	delete bmpCursor;
	bmpCursor = bmp;
	if( bmpWork )	delete bmpWork;
	bmpWork = bmpW;
	
	types = ts;
	frames = fs;
	c = cl;
	timer = 0;
	speed = 1000 / fps / 20;
	MouseOn();
	
	return 0;
}


void MouseSetFocusPos( int x, int y )
{
	if( x >= (int)c || y >= (int)c || x < 0 || y < 0 )
		return;
		
	MouseOff();
	mouseFocusX = x;
	mouseFocusY = y;
	MouseOn();
}

// turn on mouse cursor, if on == 0, cursor is visible
void MouseOn( void )
{
	if( on < 0 ){
		on ++;
		if( on == 0 && LockScreen() == 0 ){
			int cl = screen->GetClip( );
			screen->SetClip( false );
			// save screen
			screen->Blit( bmpWork, 2*c, 0, mx - mouseFocusX, my - mouseFocusY, c, c );
			// draw mouse cursor on screen
			bmpCursor->BlitMask( screen, mx - mouseFocusX, my - mouseFocusY,
								currentFrame * c, currentCursor * c, c, c );
			screen->SetClip( cl );
			UnlockScreen();
		}
	}
}

// turn off mouse  cursor
void MouseOff( void )
{
	if( on == 0 && LockScreen() == 0 ){
		int cl = screen->GetClip( );
		screen->SetClip( false );
		// erase mouse cursor from screen
		bmpWork->Blit( screen, mx - mouseFocusX, my - mouseFocusY, 2 * c, 0, c, c );
		screen->SetClip( cl );
		UnlockScreen();
	}
	on --;
}

// draw mouse cursor on screen
static void MouseDrawCursor( void )
{
	// Are we need to update cursor ?
	if( on < 0 ){
		return;
	}

	int mousePos = ::mousePos;
	int mouseX = ( mousePos >> 16 ) & 0xffff;
	int mouseY = mousePos & 0xffff;
//printf( "mouseDrawCursor: %d, %d, %d\n", ABS( mouseY - mousePrevY ), mouseY );
	if( ABS( mouseX - mx ) >= (int)c || ABS( mouseY - my ) >= (int)c ){
		MouseOff();
		mx = mouseX; my = mouseY;
		MouseOn();
	}
	else{
		if( LockScreen() != 0 )
			return;
		int cl = screen->GetClip( );
		screen->SetClip( false );
	//hz.TextOut( screen, 100,0, "in mousedrawcursor", 0xff );
		
		int tx, ty;
		tx = MIN( mx, mouseX );
		ty = MIN( my, mouseY );
		// copy screen to double buffer
		screen->Blit( bmpWork, 0, 0, tx - mouseFocusX, ty - mouseFocusY, 2*c, 2*c );
		// erase mouse cursor in double buffer
		bmpWork->Blit( bmpWork, mx - tx, my - ty, 2*c, 0, c, c );
		// save screen
		bmpWork->Blit( bmpWork, 2*c, 0, mouseX - tx, mouseY - ty, c, c );
//puts( "in mousedrawCursor" );
		// draw mouse cursor in double buffer
		bmpCursor->BlitMask( bmpWork, mouseX - tx, mouseY - ty, 
							currentFrame*c, currentCursor*c, c, c );
		// copy double buffer to screen
		bmpWork->Blit( screen, tx - mouseFocusX, ty - mouseFocusY, 0, 0, 2*c, 2*c );
		screen->SetClip( cl );
		
		mx = mouseX; my = mouseY;
		UnlockScreen();
	}
}

// we update mouse cursor up to 50 times per second
void MouseTimerHandler( void )
{
	DIMOUSESTATE mouseState;

	EnterCriticalSection( &dDrawCritical );
	lpDIMouse->GetDeviceState( sizeof(mouseState), &mouseState );
	mousex += mouseState.lX;
	mousey += mouseState.lY;
	if( mousex < ml ) mousex = ml;
	else if( mousex >= mr ) mousex = mr-1;
	if( mousey < mt ) mousey = mt;
	else if( mousey >= mb ) mousey = mb-1;
	
	if( ! mouseCursorFroze ){
		mouseX = mousex;
		mouseY = mousey;
		mousePos = ( mousex << 16 ) | mousey;
	}
	//button
	if( mouseState.rgbButtons[0] & 0x80 ) mouseB |= MOUSE_L_DOWN;
	//else mouseB &= ~MOUSE_L_DOWN;
	if( mouseState.rgbButtons[1] & 0x80 ) mouseB |= MOUSE_R_DOWN;
	//else mouseB &= ~MOUSE_R_DOWN;

	timer ++;
	if( speed && timer >= speed ){
		timer = 0;
		currentFrame = ( currentFrame + 1 ) % frames;
		MouseDrawCursor();
		return;
	}
	if( mouseX != mx || mouseY != my ){
		MouseDrawCursor();
	}
	LeaveCriticalSection( &dDrawCritical );
}

int InitMouse( void )
{
	if( mouseInstalled )
		return -1;
	
	MouseSetRange( 0, 0, screenInfo.width, screenInfo.height );
	
	bmpCursor = LoadPicture( DEFAULT_MOUSE_CURSOR );
	bmpWork = CreateBitmap( DEFAULT_CURSOR_SIZE * 3, DEFAULT_CURSOR_SIZE * 2 );
	if( bmpWork == NULL || bmpCursor == NULL 
		|| bmpCursor->width < DEFAULT_CURSOR_SIZE 
		|| bmpCursor->height < DEFAULT_CURSOR_SIZE ){
		delete bmpCursor;
		delete bmpWork;
		return -1;
	}
 
	// set mouse position
	mousex = mouseX = mx = screenInfo.width/2;
	mousey = mouseY = my = screenInfo.height/2;
	
	c = DEFAULT_CURSOR_SIZE;
	currentCursor = 0;currentFrame = 0;
	mouseInstalled = true;
	timer = speed = 0;
//	frames = 10;
//	types = 2;
	
	return 0;
}

void MouseExit( void )
{
	if( ! mouseInstalled )
		return;
	
	MouseOff();
		
	delete bmpWork;
	delete bmpCursor;
	
	mouseX = 0;
	mouseY = 0;
	mouseB = 0;
	mousePos = 0;
	
	mouseInstalled = false;
}

⌨️ 快捷键说明

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