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

📄 boxman.c

📁 手机8032的完整代码。吐血推荐。小做改动就可以生产。
💻 C
📖 第 1 页 / 共 2 页
字号:

#define _BOXMAN_C_

#pragma NOAREGS

#include "general.h"
#include "osdshow.h"

#ifdef  OSD_GAME_SOKOBAN
///////////////////////////////////////////////////////////////////////////////

// #define _BOX_DEBUG_
// #define _BOX_ASSERT_

extern void DRS232LogS(char *pcStr);
extern void DRS232LogB(BYTE bV1, BYTE bV2, BYTE bV3, BYTE bV4);

#ifdef _BOX_DEBUG_
#define BOX_DBGLogB(b1, b2, b3, b4) DRS232LogB(b1, b2, b3, b4)
#define BOX_DBGLogW(wTemp)          DRS232LogB(0, 0, bHiByte(wTemp), bLoByte(wTemp))
#define BOX_DBGLogDW(dwTemp)        DRS232LogB(bHiByte(wHiWord(dwTemp)), bLoByte(wHiWord(dwTemp)), bHiByte(wLoWord(dwTemp)), bLoByte(wLoWord(dwTemp)))
#define BOX_DBGLogS(s)              DRS232LogS(s)
#else
#define BOX_DBGLogB(b1, b2, b3, b4)
#define BOX_DBGLogW(wTemp)
#define BOX_DBGLogDW(dwTemp)
#define BOX_DBGLogS(s)
#endif

#ifdef  _BOX_ASSERT_
#define BOX_ASSERT(fgAssert) \
do  \
{ \
  if(!(fgAssert)) \
  { \
    DRS232LogS("\nAssert Error!");  \
    DRS232LogS(_FILE_); \
    DRS232LogB((BYTE)(_LINE_ >> 24), (BYTE)(_LINE_ >> 16), (BYTE)(_LINE_ >> 8), (BYTE)(_LINE_ >> 0)); \
  } \
}while(0)
#else
#define BOX_ASSERT(fgAssert)
#endif

///////////////////////////////////////////////////////////////////////////////

static void vBoxManVarInit(void) large
{
  _bGameState = 0;
  _bGameSubState = 0;
  _bGameItem = 0;
  _bGameGrade = 0;
#ifdef OSD_GAME_SOUND
  _bGameSndTimer = 0;
  _bGameSndId = 0;
#endif
}


static void vBoxManNewTurnInit(void) large
{
  BYTE i;

  vSetSharedInfo(SI_MAN_X, pMap[_bGameGrade]->rManPos.x);
  vSetSharedInfo(SI_MAN_Y, pMap[_bGameGrade]->rManPos.y);

  for (i = 0; i < pMap[_bGameGrade]->bBoxNo; i++)
  {
    vSetSharedInfo(SI_BOX_X(i), pMap[_bGameGrade]->rBoxPos[i].x);
    vSetSharedInfo(SI_BOX_Y(i), pMap[_bGameGrade]->rBoxPos[i].y);
  }

  //clear all flag of box
  _bfgApBox = 0x00;
  _bNowRebackNo = 0x00;
  _bNowRebackedNo = REBACK_NS;
  _bPushBoxNo = 0x00;
  _bOren = THINK;

  _fgCanShift = FALSE;
  _fgGameOver = FALSE;
  _fgManPushBox = FALSE; // user has push the box initial at map change
  _fgLastStep = FALSE;
  _fgManNextBox = FALSE;  // set or not when judge at next to box
  _fgBadPosiWarn = FALSE;
  _fgAnswer = FALSE;

  _bLastStepStack = 0;
  _bNowNextBoxId = 0;
  _bBMShowTimer = 0;
  _wAswStep = 0;
}


static void vBoxManOsdInit(void) large
{
  vOsdSetSt(OSD_ST_BURST);
  
  vCreateWB(WB_OSD_GAME, TRUE);

  vSetWBTcColor(WB_OSD_GAME);

  vSetTransEn(WB_OSD_GAME, 0);

  vBoxManShowMap();

  vBoxManShowInfo(BM_INFO_ALL1);

  vHiliBoxManMenuItem(_bGameItem, ITEM_HILI);

  vEnableWB(WB_OSD_GAME);
}


static void vGameBoxManOsdRecover(void) large
{
  vBoxManNewTurnInit();
  vBoxManShowMap();
  vBoxManShowInfo(BM_INFO_ALL2);
}


static void vChangDisplay(void) large
{
  BYTE i;

  if (_fgCanShift || _fgLastStep)
  {
    if (_fgCanShift && _fgManNextBox)
    {
      _bPushBoxNo++;
      vBoxManShowInfo(BM_INFO_PUSH_STEP);
      //show the push box step
    }

    vDrawMap(_bStartPosBmpId, bSharedInfo(SI_SHIFT_SR_X), bSharedInfo(SI_SHIFT_SR_Y));
    vDrawBox(_bNowNextBoxId);
    if (_fgLastStep)
    {
      vDrawMap(_bEndPosBmpId, bSharedInfo(SI_SHIFT_DS_X), bSharedInfo(SI_SHIFT_DS_Y));

      _bPushBoxNo-- ;
      if (_bPushBoxNo == 0)
      {
        _fgManPushBox = FALSE;
      }
      //show the push box step
      vBoxManShowInfo(BM_INFO_PUSH_STEP);
      // _bNowNextBoxId = bSharedInfo(SI_MEM_BOXID((_bLastStepStack - 1)));
    }
    vDrawMan(bSharedInfo(SI_MAN_X), bSharedInfo(SI_MAN_Y));

    _fgLastStep = FALSE;
    _fgCanShift = FALSE;
    _fgManNextBox = FALSE;
  }

  if (!_fgGameOver)
  {
    // judge the flag
    for ( i = 0; i < pMap[_bGameGrade]->bBoxNo; i++)
    {
      if (!fgBox(i))
      {
        break;
      }
    }

    if (i < pMap[_bGameGrade]->bBoxNo)
    {
      _fgGameOver = FALSE;
    }
    else
    {
      _fgGameOver = TRUE;
    }

    if (_fgGameOver)
    {
      #ifdef OSD_GAME_SOUND
        vGameDelayMs(10);
        vSendUopCmd(UOP_AUDIO_CLIP, SV_ACLIP_FLASH, CLIP_WIN, 0);
        _bGameSndId = 0xFF;
        _bGameSndTimer = 75;
      #endif

      if (_fgAnswer)
      {
        vChgGameState(BM_DIALOG_STATE);
        vChgGameSubState(BM_DIALOG_TRY_STATE);
        vBoxManShowDialog();
      }
      else
      {
        vChgGameState(BM_DIALOG_STATE);
        vChgGameSubState(BM_DIALOG_NEXT_STATE);
        vBoxManShowDialog();
      }
    }
  }

#ifdef OSD_GAME_SOUND
  // Pupop & Walk
  if (_bGameSndId < CLIP_NS)
  {
    vGameDelayMs(10);
    vSendUopCmd(UOP_AUDIO_CLIP, SV_ACLIP_FLASH, _bGameSndId, 0);
    _bGameSndId = 0xFF;
    _bGameSndTimer = 15;
  }
#endif
}


//find the index of the box from map
static BOOL fgJudgeNextBox(BYTE x, BYTE y, BOOL fgManJudgeNextBox) large
{
  BOOL fgNextBox;
  BYTE i;

  i = 0;
  fgNextBox = FALSE;
  while((!fgNextBox) && (i < pMap[_bGameGrade]->bBoxNo))
  {
    // if ((x == rNowBoxPos[i].x) && (y == rNowBoxPos[i].y))
    if ((x == bSharedInfo(SI_BOX_X(i))) && (y == bSharedInfo(SI_BOX_Y(i))))
    {
      if (fgManJudgeNextBox)
      {
        //when the man is next to the box then get now push box id
        _bNowNextBoxId = i;
      }
      fgNextBox = TRUE;
    }
    i++;
  }
  return fgNextBox;
}


static code char cStepx[] = {0, 1, 0, -1, 0, 0};
static code char cStepy[] = {0, 0, -1, 0, 1, 0};
static void vJudgeCanShift(BYTE bOren) large
{
  sBMANPos rJudgePos;
  BOOL fgManJudgeNextBox;
  BYTE i;

  fgManJudgeNextBox = TRUE;
  _fgManNextBox = FALSE;
  _fgCanShift = FALSE;

  rJudgePos.x = bSharedInfo(SI_MAN_X) + cStepx[bOren];
  rJudgePos.y = bSharedInfo(SI_MAN_Y) + cStepy[bOren];

  if (fgJudgeNextBox(rJudgePos.x, rJudgePos.y, fgManJudgeNextBox)) // the next is box
  {
    fgManJudgeNextBox = FALSE;
    _fgManNextBox = TRUE;
    if ( fgJudgeNextBox(rJudgePos.x + cStepx[bOren], // the next to next is box
                        rJudgePos.y + cStepy[bOren],
                        fgManJudgeNextBox)
      || (pMap[_bGameGrade]->bMapData[rJudgePos.y + cStepy[bOren]][rJudgePos.x + cStepx[bOren]] == WALL))
    {
      _fgCanShift = FALSE;
    }
    else if (pMap[_bGameGrade]->bMapData[rJudgePos.y + cStepy[bOren]][rJudgePos.x + cStepx[bOren]] == BADPOS)
    {
      // here add the conditon judge is bad positon or not;
      _fgCanShift = FALSE;
      // show the warning osd
      // ShowMessage("the positon is bad positon, please think another way");
      vShowBmBadPosiWarn();
      _bBMShowTimer = BAD_POSI_INT;
      _fgBadPosiWarn = TRUE;
    #ifdef OSD_GAME_SOUND
      vGameDelayMs(10);
      vSendUopCmd(UOP_AUDIO_CLIP, SV_ACLIP_FLASH, CLIP_WARNING, 0);
      _bGameSndId = 0xFF;
      _bGameSndTimer = 15;
    #endif
    }
    else
    {
      _fgCanShift = TRUE;
    }
  }
  else  if (pMap[_bGameGrade]->bMapData[rJudgePos.y][rJudgePos.x] == WALL) //it is wall
  {
    _fgCanShift = FALSE;
  }
  else
  {
    _fgCanShift = TRUE;
  }
  if (_fgCanShift)
  {
    // draw start and dram man
    _bStartPosBmpId = pMap[_bGameGrade]->bMapData[bSharedInfo(SI_MAN_Y)][bSharedInfo(SI_MAN_X)];
    vSetSharedInfo(SI_SHIFT_SR_X, bSharedInfo(SI_MAN_X));
    vSetSharedInfo(SI_SHIFT_SR_Y, bSharedInfo(SI_MAN_Y));

    vSetSharedInfo(SI_MAN_X, rJudgePos.x);
    vSetSharedInfo(SI_MAN_Y, rJudgePos.y);

    if (_fgManNextBox) // draw box
    {
      vSetSharedInfo(SI_BOX_Y(_bNowNextBoxId), rJudgePos.y + cStepy[bOren]);
      vSetSharedInfo(SI_BOX_X(_bNowNextBoxId), rJudgePos.x + cStepx[bOren]);

      _fgManPushBox = TRUE;
      //when the remember stack is full then push the stack
      if ((_bLastStepStack) == MAX_REBACK_STEP)
      {
        for ( i = 0; i < MAX_REBACK_STEP - 1; i++)
        {
          vSetSharedInfo(SI_MEM_BOXID(i), bSharedInfo(SI_MEM_BOXID((i + 1))));
          vSetSharedInfo(SI_MEM_OREN(i), bSharedInfo(SI_MEM_OREN((i + 1))));
        }
        _bLastStepStack = MAX_REBACK_STEP - 1;
      }
      //remember the box id of last step
      vSetSharedInfo(SI_MEM_BOXID(_bLastStepStack), _bNowNextBoxId);
      //remember the orientation of last step
      vSetSharedInfo(SI_MEM_OREN(_bLastStepStack), (bOren + 1) % 4 + 1);

      //remember stack pointer add
      _bLastStepStack++;
      BOX_DBGLogB(0, 0, 0, _bLastStepStack);
      //show the number step to reback
    }
  #ifdef OSD_GAME_SOUND
    _bGameSndId = CLIP_POPUP;
    _bGameSndTimer = 15;
  #endif
  }
}


static void vLeftClick(void) large
{
  _bOren = LEFT;
  _bBMShowTimer = MAN_SHOW_INT;
  vJudgeCanShift(_bOren);
  vChangDisplay();
}


static void vUpClick(void) large
{
  _bOren = UP;
  _bBMShowTimer = MAN_SHOW_INT;
  vJudgeCanShift( _bOren);
  vChangDisplay();
}


static void vDownClick(void) large
{
  _bOren = DOWN;
  _bBMShowTimer = MAN_SHOW_INT;
  vJudgeCanShift(_bOren);
  vChangDisplay();
}


static void vRightClick(void) large
{
  _bOren = RIGHT;
  _bBMShowTimer = MAN_SHOW_INT;
  vJudgeCanShift(_bOren);
  vChangDisplay();
}


static void vReback(void) large
{
  if (_bLastStepStack == 0)
  {
    // ShowMessage("have return the end");
    return;
  }
  if (_fgManPushBox && _bNowRebackedNo)
  {
    char x;
    char y;

    //get the reverse of last push orientation
    x = cStepx[bSharedInfo(SI_MEM_OREN(_bLastStepStack - 1))];
    y = cStepy[bSharedInfo(SI_MEM_OREN(_bLastStepStack - 1))];

    if (_bLastStepStack > 0)
    {
      _bNowNextBoxId = bSharedInfo(SI_MEM_BOXID(_bLastStepStack - 1));
    }

    // the space man stand in
    _bStartPosBmpId = pMap[_bGameGrade]->bMapData[ bSharedInfo(SI_MAN_Y)][ bSharedInfo(SI_MAN_X)];

    vSetSharedInfo(SI_SHIFT_SR_X, bSharedInfo(SI_MAN_X));
    vSetSharedInfo(SI_SHIFT_SR_Y, bSharedInfo(SI_MAN_Y));

    // the space box stand in
    _bEndPosBmpId = pMap[_bGameGrade]->bMapData[bSharedInfo(SI_BOX_Y(_bNowNextBoxId))][bSharedInfo(SI_BOX_X(_bNowNextBoxId))];

    vSetSharedInfo(SI_SHIFT_DS_X, bSharedInfo(SI_BOX_X(_bNowNextBoxId)));
    vSetSharedInfo(SI_SHIFT_DS_Y, bSharedInfo(SI_BOX_Y(_bNowNextBoxId)));

    // the box position back for one step
    vSetSharedInfo(SI_BOX_Y(_bNowNextBoxId), bSharedInfo(SI_SHIFT_DS_Y) + y);
    vSetSharedInfo(SI_BOX_X(_bNowNextBoxId), bSharedInfo(SI_SHIFT_DS_X) + x);

    // the man position back for one step
    vSetSharedInfo(SI_MAN_X, bSharedInfo(SI_BOX_X(_bNowNextBoxId)) + x);
    vSetSharedInfo(SI_MAN_Y, bSharedInfo(SI_BOX_Y(_bNowNextBoxId)) + y);

    BOX_DBGLogB(0, _bNowRebackNo, _bNowRebackedNo, _bLastStepStack);

    //if user reback the number add

⌨️ 快捷键说明

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