?? cbmouse.cpp
字號:
/////////////////////
// CBDraw.cpp : v0021
// Written by : Liu Gang
// Compiler : Microsoft Visual C++ 4.2 & DirectX
// Library : DDraw.Lib
// Copyright (C) : 1996-1997 WayAhead Corporation
// v0021 : Jan.22.1997, devided from CBDraw.cpp
// v0022 : Sep.11.1997, HitTestU() parameters changed
/////////////////////
#include "stdafx.h"
#include <stdio.h>
#include "CBMouse.h"
#include "Assert.h"
#include "DDCompo.h"
#include "CBMap.h"
#include "CBGame.h"
#include "CBDraw.h"
#include "CBCtrl.h"
#include "CBEyes.h"
#include "CBMini.h"
#include "CBShadow.h"
#include "Marco.h"
/////////////////////
// external globals
// declared in CBDraw.cpp
extern RECT DRAW_rcScreen;
extern RECT DRAW_rcClient;
extern POINT DRAW_ptScreenOffset;
extern POINT DRAW_ptCovering[2][9];
/////////////////////
// private globals,for mouse control
/////////////////////
// array used for detecting if mouse hit the region
// 探測鼠標點擊
int nByConts[MAP_ITEM_WIDTH][MAP_ITEM_HEIGHT];
/////////////////////
/////////////////////
// state of the cursor, 但是不一定與pCursor的狀態一樣
int MOUSE_nState = MOUSE_STATE_NONE;
/////////////////////
/////////////////////
// local functions
BOOL MOUSE_bEnableTest=TRUE;
void MOUSE_testState( int nPosX, int nPosY );
/////////////////////
/////////////////////
// 初始化探測用數據
extern CDDPalette palMain;
void MOUSE_InitByConts()
{
//為數組nByConts[MAP_ITEM_WIDTH][MAP_ITEM_HEIGHT]賦值
memset( nByConts, 0, MAP_ITEM_WIDTH*MAP_ITEM_HEIGHT );
int halfwidth = MAP_ITEM_WIDTH>>1;
int jj;
for(int j=0; j<(MAP_ITEM_HEIGHT>>1); j++ )
{
jj = (j+1)<<1;
for(int i=halfwidth-jj; i<halfwidth+jj; i++ )
{
nByConts[i][j]=1;
nByConts[i][MAP_ITEM_HEIGHT-j-2]=1;
}
}
}
/////////////////////
/////////////////////
// 檢驗鼠標點擊的效果
// pt : 鼠標點擊的坐標,直接從GetCursorPos()中的得到的,以點為單位。
// 返回格子(行、列)
inline POINT MOUSE_hitTestPoint( POINT pt )
{
POINT ptReturn;
POINT ptGrid[3], ptOff[3];
SIZE szItem;
// initialize
szItem.cx = MAP_Lib.szItem.cx, szItem.cy = MAP_Lib.szItem.cy;
ptReturn.x = ptReturn.y = -1;
// OutputString( pt.x, "," );
// OutputString( pt.y, "\n" );
// get grids position
int halfy = szItem.cy>>1;
int halfx = szItem.cx>>1;
ptGrid[0].y = pt.y/(halfy);
ptGrid[1].y = ptGrid[0].y-1;
ptGrid[2].y = ptGrid[0].y-1;
ptOff[0].y = pt.y - ptGrid[0].y*(halfy);
ptOff[1].y = ptOff[0].y + halfy;
ptOff[2].y = ptOff[0].y + halfy;
int bOdd = ptGrid[0].y&1;
int bEven = 1 - bOdd;
ptGrid[0].x = (pt.x - halfx*bOdd) / szItem.cx;
ptGrid[1].x = ptGrid[0].x + bOdd - 1;
ptGrid[2].x = ptGrid[0].x + bOdd;
ptOff[0].x = pt.x - ptGrid[0].x*szItem.cx - halfx*bOdd;
ptOff[1].x = pt.x - ptGrid[1].x*szItem.cx - halfx*bEven;
ptOff[2].x = pt.x - ptGrid[2].x*szItem.cx - halfx*bEven;
// check
for( int i=0; i<3; i++ )
{
if( ptOff[i].x >= 0 && ptOff[i].y >= 0 &&
ptOff[i].x < szItem.cx && ptOff[i].y < szItem.cy )
{
// test if in the points
if( nByConts[ptOff[i].x][ptOff[i].y] == 1 )
{
// global position
// ptReturn.x = DRAW_rcScreen.left + ptGrid[i].x + DRAW_SCREEN_ADJUST;
// ptReturn.y = DRAW_rcScreen.top + ptGrid[i].y;
ptReturn.x = ptGrid[i].x;// + DRAW_SCREEN_ADJUST;
ptReturn.y = ptGrid[i].y;
return ptReturn;
}
}
}
// set coords
return ptReturn;
}
// 檢測單元
// pt : 鼠標點擊的坐標,直接從GetCursorPos()中的得到的,以點為單位。
// pHitResult : 檢測的結果
// bEnemy : 只選擇敵人時為真
// 返回FALSE時pHitResult無效
BOOL MOUSE_HitTestU( POINT pt, struct MOUSE_HITRESULT_STRUCT *pHitResult, BOOL bEnemy/*=0*/ )
{
POINT point, ptGrid;
ptGrid.x = -1, ptGrid.y = -1;
pHitResult->nType = MOUSE_HITRESULT_NONE; // initialize
pt.x += DRAW_ptScreenOffset.x, pt.y += DRAW_ptScreenOffset.y;
ptGrid = MOUSE_hitTestPoint( pt );
if( ptGrid.x == -1 || ptGrid.y == -1 ) return FALSE;
Assert( ptGrid.x != -1 && ptGrid.y != -1 );
pt.x -= DRAW_ptScreenOffset.x, pt.y -= DRAW_ptScreenOffset.y;
// get display data
point.x = ptGrid.x, point.y = ptGrid.y;
WORD codeUEx = MAP_GetUnitDataEx( point.x, point.y );
if( codeUEx != MAP_DATA_NONE )
{
struct UNIT_STRUCT * pUnit = MAP_GetUnit( codeUEx );
// reset position
point.x = pUnit->Draw.nX, point.y = pUnit->Draw.nY;
// Please note:
RECT rect = MAP_GetUnitRect( DRAW_ptScreenOffset, &pUnit->Draw );
if( rect.left < pt.x && rect.right >= pt.x &&
rect.top < pt.y && rect.bottom >= pt.y )
{
// 如果該單元已經死亡,則不算
// 如果該單元不是敵人,而且bEnemy是TRUE,則不算, Sep.11.1997
struct UNIT_STRUCT *pUnit = MAP_GetUnit( codeUEx );
Assert( pUnit );
if( !EYE_IfUnitIsDead( pUnit )
&& !( bEnemy == TRUE && pUnit->Draw.nPlayer == GAME.nMe ) )
{
BOOL bSet = TRUE;
if( SHADOW_IfEnabled() )
{
WORD codeR = MAP_GetRegionData( point.x, point.y );
struct MAP_REGION_CODE_STRUCT stctR;
MAP_RegionDeCode( codeR, &stctR );
if( stctR.nShadow == MAP_SHADOW_NONE || stctR.nShadowEx == 1 )
{// 有任何形式的陰影,不響應
bSet = FALSE;
}
if( pUnit->Draw.nPlayer == 0 )
{// 是資源,可以響應
bSet = TRUE;
}
}
if( bSet == TRUE )
{
pHitResult->nType = MOUSE_HITRESULT_UNIT;
pHitResult->nLayer = pUnit->Draw.nLayer;
Assert( pHitResult->nLayer < 3 );
pHitResult->wCode = codeUEx;
pHitResult->ptHit.x = point.x;
pHitResult->ptHit.y = point.y;
return TRUE;
}
}
}
}
for( int y=4; y>=0; y-- )
for( int x=0; x<9; x++ )
{
// calc next position
int bOdd = pt.y&1;
point.x = ptGrid.x+DRAW_ptCovering[bOdd][x].x;
point.y = ptGrid.y+DRAW_ptCovering[bOdd][x].y+y*2;
if( EYE_IfOutOfRange( point.x, point.y ) )
continue;
// get display data
WORD codeUEx = MAP_GetUnitDataEx( point.x, point.y );
if( codeUEx != MAP_DATA_NONE )
{
struct UNIT_STRUCT * pUnit = MAP_GetUnit( codeUEx );
// reset position
point.x = pUnit->Draw.nX, point.y = pUnit->Draw.nY;
RECT rect = MAP_GetUnitRect( DRAW_ptScreenOffset, &pUnit->Draw );
if( rect.left < pt.x && rect.right >= pt.x &&
rect.top < pt.y && rect.bottom >= pt.y )
{
// 如果該單元已經死亡,則不算
// 如果該單元不是敵人,而且bEnemy是TRUE,則不算, Sep.11.1997
struct UNIT_STRUCT *pUnit = MAP_GetUnit( codeUEx );
Assert( pUnit );
if( !EYE_IfUnitIsDead( pUnit )
&& !( bEnemy == TRUE && pUnit->Draw.nPlayer == GAME.nMe ) )
{
BOOL bSet = TRUE;
if( SHADOW_IfEnabled() )
{
WORD codeR = MAP_GetRegionData( point.x, point.y );
struct MAP_REGION_CODE_STRUCT stctR;
MAP_RegionDeCode( codeR, &stctR );
if( stctR.nShadow == MAP_SHADOW_NONE || stctR.nShadowEx == 1 )
{
bSet = FALSE;
}
}
if( bSet == TRUE )
{
pHitResult->nType = MOUSE_HITRESULT_UNIT;
pHitResult->nLayer = pUnit->Draw.nLayer;
pHitResult->wCode = codeUEx;
pHitResult->ptHit.x = point.x;
pHitResult->ptHit.y = point.y;
return TRUE;
}
}
}
}
}
// else return false
// OutputDebugString( "HitTestU: Not Detected!\n" );
return FALSE;
}
// 檢測地形
// pt : 鼠標點擊的坐標,直接從GetCursorPos()中的得到的,以點為單位。
// pHitResult : 檢測的結果
// nLayer : 檢測的層數,缺省值為2,所有三層的地形都要檢測
// 返回FALSE時pHitResult無效
BOOL MOUSE_HitTestG( POINT pt, struct MOUSE_HITRESULT_STRUCT *pHitResult, int nLayer/* = 2*/ )
{
POINT ptGrid;
POINT point;
WORD codeG;
// initialize
ptGrid.x = -1, ptGrid.y = -1;
pHitResult->nType = MOUSE_HITRESULT_NONE;
pt.x += DRAW_ptScreenOffset.x, pt.y += DRAW_ptScreenOffset.y;
point.x = pt.x;
for( int i=nLayer; i>=0 ; i-- )
{
point.y = pt.y+MAP_Lib.nHeight[i+1];
ptGrid = MOUSE_hitTestPoint( point );
// hit point test
if( ptGrid.x == -1 || ptGrid.y == -1 ) return FALSE; // not hit any point
codeG = MAP_GetGroundData( i, ptGrid.x, ptGrid.y );
if( codeG != MAP_DATA_NONE )
{
pHitResult->nType = MOUSE_HITRESULT_GROUND;
pHitResult->nLayer = i;
Assert( i < 3 );
pHitResult->wCode = codeG;
pHitResult->ptHit.x = ptGrid.x;
pHitResult->ptHit.y = ptGrid.y;
return TRUE;
}
}
// else return false
// OutputDebugString( "HitTestG: Not Detected!\n" );
return FALSE;
}
// 先檢測地形后檢測單元
// pt : 鼠標點擊的坐標,直接從GetCursorPos()中的得到的,以點為單位。
// pHitResult : 檢測的結果
// 返回FALSE時pHitResult無效
BOOL MOUSE_HitTestGU( POINT pt, struct MOUSE_HITRESULT_STRUCT *pHitResult )
{
if( !MOUSE_HitTestG( pt, pHitResult ) )
{
return MOUSE_HitTestU( pt, pHitResult );
}
return TRUE;
}
// 先檢測單元后檢測地形
// pt : 鼠標點擊的坐標,直接從GetCursorPos()中的得到的,以點為單位。
// pHitResult : 檢測的結果
// bEnemy : 只選擇敵人時為真
// 返回FALSE時pHitResult無效
BOOL MOUSE_HitTestUG( POINT pt, struct MOUSE_HITRESULT_STRUCT *pHitResult, BOOL bEnemy /*=0*/ )
{
if( !MOUSE_HitTestU( pt, pHitResult, bEnemy ) )
{
return MOUSE_HitTestG( pt, pHitResult );
}
return TRUE;
}
/////////////////////
/////////////////////
// test mouse dragging
// globals
// synchronization for drag and draw
BOOL MOUSE_bSemaphore = FALSE;
// if left mouse button is down
BOOL MOUSE_bLeftDown = FALSE;
BOOL MOUSE_bLeftDownLast = FALSE;
/*
// if right mouse button is down
BOOL MOUSE_bRightDown = FALSE;
BOOL MOUSE_bRightDownLast = FALSE;
*/
// dragging rectangle, and the old one
RECT MOUSE_rcDrag, MOUSE_rcDragLast;
// the first point mouse button down
POINT MOUSE_ptFirst;
// save the origional mouse moving range
RECT rcOldRange;
// if mouse left button down, set down flag, begin dragging process
// nPosX, nPosY : mouse cursor position
void MOUSE_LeftDown( int nPosX, int nPosY )
{
// clear semaphore flag
MOUSE_bSemaphore = FALSE;
// set the flag
if( MOUSE_bLeftDown == TRUE )
return;
MOUSE_bLeftDown = TRUE;
MOUSE_bLeftDownLast = TRUE;
// set value to MOUSE_rcDrag
SetRect( &MOUSE_rcDrag, nPosX, nPosY, nPosX, nPosY );
SetRect( &MOUSE_rcDragLast, nPosX, nPosY, nPosX, nPosY );
MOUSE_ptFirst.x = nPosX, MOUSE_ptFirst.y = nPosY;
// set mouse cursor new range
class CDDCursor *pCursor;
pCursor = CURSOR_Get();
Assert( pCursor!= NULL );
rcOldRange = pCursor->SetRange( &DRAW_rcClient );
Assert( rcOldRange.left == 0 && rcOldRange.top == 0 );
// change cursor state
MOUSE_testState( nPosX, nPosY );
}
// if mouse left button up, clear down flag, end dragging process
// nPosX, nPosY : mouse cursor position
// return : dragging rectangle
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -