【APP GAME KIT】能碰到障碍物的移动小人

来源:互联网 发布:淘宝裸根月季苗 编辑:程序博客网 时间:2024/05/01 03:18

网上下载的例子运行以后会出现以下情况:

① 小人移动速度较慢。

② 小人移动动画不准确,即移动时候小人的双脚并不会运动。反而是站着的时候双脚会走。

③ 小人向下或向下移动的时候同时按左键或右键,小人方向不会发生改变,但是会向左或向右移动;小人向左或向右移动的时候按上下键,小人方向会发生改变。这是因为 if 和 else if 导致的按键事故。


原版代码:

// Includes, namespace and prototypes#include "template.h"using namespace AGK;app App;// Function prototypesvoid loadTiles();void displayTiles();void updateAlecX(float);void updateAlecY(float);// Constants for the screen resolutionconst int SCREEN_WIDTH  = 640;const int SCREEN_HEIGHT = 480;// Constants for the image numbersconst int GRASS  = 1;const int PATH   = 2;const int PATHNE = 3;const int PATHNW = 4;const int PATHSE = 5;const int PATHSW = 6;const int TREENW = 7;const int TREENE = 8;const int TREESW = 9;const int TREESE = 10;const int ROCK   = 11;// Constants for the tile image sizesconst int TILE_WIDTH  = 64;const int TILE_HEIGHT = 48;// Constants for the tile map size declaratorsconst int TILE_ROWS = 10;const int TILE_COLS = 10;// Constants for the Alec sprite sheetconst int ALEC_IMAGE        = 12;  // Texture atlas image indexconst int ALEC_SPRITE       = 100; // Alec's sprite indexconst int ALEC_FRAME_WIDTH  = 40;  // Alec's frame widthconst int ALEC_FRAME_HEIGHT = 75;  // Alec's frame heightconst int ALEC_FRAME_COUNT  = 16;  // Alec's frame countconst int EAST_START        = 1;   // First frame for going eastconst int EAST_END          = 4;   // Last frame for going eastconst int NORTH_START       = 5;   // First frame for going northconst int NORTH_END         = 8;   // Last frame for going northconst int SOUTH_START       = 9;   // First frame for going southconst int SOUTH_END         = 12;  // Last frame for going southconst int WEST_START        = 13;  // First frame for going westconst int WEST_END          = 16;  // Last frame for going westconst int ALEC_FPS          = 5;   // Alec's frames per secondconst int ANIMATION_LOOP    = 1;   // To make Alec loopconst float ALEC_STARTING_X = 0;   // Alec's starting X coordinateconst float ALEC_STARTING_Y = 150; // Alec's starting Y coordinate// Constants for Alec's directionconst int NORTH   = 1;const int SOUTH = 2;const int EAST  = 3;const int WEST  = 4;// The tile mapint g_tileMap[TILE_ROWS][TILE_COLS] ={ {GRASS, GRASS, GRASS, GRASS, GRASS,  GRASS,  GRASS,  GRASS,  GRASS, GRASS},  {GRASS, GRASS, GRASS, ROCK,  GRASS,  GRASS,  GRASS,  GRASS,  GRASS, GRASS},  {GRASS, GRASS, GRASS, GRASS, GRASS,  GRASS,  GRASS,  PATHNW, PATH,  PATH },  {GRASS, GRASS, GRASS, GRASS, GRASS,  TREENW, TREENE, PATH,   GRASS, GRASS},  {PATH,  PATH,  PATH,  PATH,  PATHNE, TREESW, TREESE, PATH,   ROCK,  GRASS},  {GRASS, GRASS, GRASS, GRASS, PATH,   GRASS,  GRASS,  PATH,   GRASS, GRASS},  {GRASS, GRASS, GRASS, GRASS, PATHSW, PATH,   PATH,   PATHSE, GRASS, GRASS},  {GRASS, GRASS, GRASS, GRASS, GRASS,  GRASS,  GRASS,  GRASS,  GRASS, GRASS},  {GRASS, ROCK,  GRASS, GRASS, GRASS,  GRASS,  GRASS,  GRASS,  GRASS, GRASS},  {GRASS, GRASS, GRASS, GRASS, GRASS,  GRASS,  GRASS,  GRASS,  GRASS, GRASS}};// Variable for Alec's directionint g_alecDirection = EAST;// Begin app, called once at the startvoid app::Begin( void ){   // Set the window title.   agk::SetWindowTitle("Walking Alec");   // Set the virtual resolution.   agk::SetVirtualResolution(SCREEN_WIDTH, SCREEN_HEIGHT);   // Load the texture atlas.   agk::LoadImage(ALEC_IMAGE, "Alec/Alec.png");   // Create the sprite using the texture atlas as the image.   agk::CreateSprite(ALEC_SPRITE, ALEC_IMAGE);   // Make sure Alec is displayed on top of the tile sprites.   agk::SetSpriteDepth(ALEC_SPRITE, 0);   // Set Alec's starting position.   agk::SetSpritePosition(ALEC_SPRITE, ALEC_STARTING_X,                           ALEC_STARTING_Y);   // Set the sprite animation.   agk::SetSpriteAnimation(ALEC_SPRITE, ALEC_FRAME_WIDTH,                            ALEC_FRAME_HEIGHT, ALEC_FRAME_COUNT);   // Load the tile images.   loadTiles();   // Create the tile sprites and display them.   displayTiles();}// Main loop, called every framevoid app::Loop ( void ){   // Get the state of the direction keys.   float directionX = agk::GetDirectionX();   float directionY = agk::GetDirectionY();   // If the right or left arrow keys are pressed,   // update Alec's X coordinate.   if (directionX != 0)   {      updateAlecX(directionX);   }   // If the up or down arrow keys are pressed,   // update Alec's Y coordinate.   if (directionY != 0)   {      updateAlecY(directionY);   }   // Refresh the screen.    agk::Sync();}// Called when the app endsvoid app::End ( void ){}// The loadTiles function loads the images that will be// used for tiles.void loadTiles(){   agk::LoadImage(GRASS,  "Alec/Grass.png");   agk::LoadImage(PATH,   "Alec/Path.png");   agk::LoadImage(PATHNE, "Alec/PathNE.png");   agk::LoadImage(PATHNW, "Alec/PathNW.png");   agk::LoadImage(PATHSE, "Alec/PathSE.png");   agk::LoadImage(PATHSW, "Alec/PathSW.png");   agk::LoadImage(TREENE, "Alec/TreeNE.png");   agk::LoadImage(TREENW, "Alec/TreeNW.png");   agk::LoadImage(TREESE, "Alec/TreeSE.png");   agk::LoadImage(TREESW, "Alec/TreeSW.png");   agk::LoadImage(ROCK,   "Alec/Rock.png");}// The displayTiles function displays the tiles, as// specified by the tile map.void displayTiles(){   // Variables for the tile coordinates   float x = 0, y = 0;   // Variable to temporarily hold a sprite index   int spriteIndex;      // Display all the tiles specified in the map.   for (int r = 0; r < TILE_ROWS; r++)   {      // Set x to 0.      x = 0;      // Display all the tiles in this row.      for (int c = 0; c < TILE_COLS; c++)      {         // Create a sprite for this tile.         spriteIndex = agk::CreateSprite(g_tileMap[r][c]);         // Set the tile's position.         agk::SetSpritePosition(spriteIndex, x, y);         // Update the X coordinate for the next tile.         x += TILE_WIDTH;      }         // Increase y for the next row.      y += TILE_HEIGHT;    }}// The updateAlecX function turns Alec either east or west,// depending on which arrow key is being pressed, and moves// him to his new X coordinate.void updateAlecX(float directionX){   float alecX,   // Alec's current X position         newX;    // Alec's new X coordinate   // Get Alec's X coordinate   alecX = agk::GetSpriteX(ALEC_SPRITE);   // Which key was pressed? Right or left?   if (directionX > 0)   {      // Turn Alec east      agk::PlaySprite(ALEC_SPRITE, ALEC_FPS,                       ANIMATION_LOOP,                       EAST_START, EAST_END);      // Save Alec's current direction.      g_alecDirection = EAST;      // Calculate Alec's new X coordinate.      newX = alecX + 1;   }   else if (directionX < 0)   {      // Turn Alec west      agk::PlaySprite(ALEC_SPRITE, ALEC_FPS,                       ANIMATION_LOOP,                       WEST_START, WEST_END);      // Save Alec's current direction.      g_alecDirection = WEST;      // Calculate Alec's new X coordinate      newX = alecX - 1;   }   // Move Alec   agk::SetSpriteX(ALEC_SPRITE, newX);}// The updateAlecY function turns Alec either north or south,// depending on which arrow key is being pressed, and moves// him to his new Y coordinate.void updateAlecY(float directionY){   float alecY,   // Alec's current Y position         newY;    // Alec's new Y coordinate   // Get Alec's Y coordinate   alecY = agk::GetSpriteY(ALEC_SPRITE);   // Which key was pressed? Up or down?   if (directionY < 0)   {      // Turn Alec north      agk::PlaySprite(ALEC_SPRITE, ALEC_FPS,                       ANIMATION_LOOP,                       NORTH_START, NORTH_END);      // Save Alec's current direction.      g_alecDirection = NORTH;      // Calculate Alec's new Y coordinate.      newY = alecY - 1;   }   else if (directionY > 0)   {      // Turn Alec south      agk::PlaySprite(ALEC_SPRITE, ALEC_FPS,                       ANIMATION_LOOP,                      SOUTH_START, SOUTH_END);      // Save Alec's current direction.      g_alecDirection = SOUTH;      // Calculate Alec's new Y coordinate.      newY = alecY + 1;   }   // Move Alec   agk::SetSpriteY(ALEC_SPRITE, newY);}


自己尝试独立打了一次代码:

#include "template.h"using namespace AGK;app App;//tile图片编号const int GRASS = 1;//草坪图片const int PATH = 2;//石径满const int PATHNE = 3;//石径左拐下const int PATHNW = 4;//石径右拐下const int PATHSE = 5;//石径左拐上const int PATHSW = 6;//石径上拐右const int TREENW = 7;//树左上部分const int TREENE = 8;//树右上部分const int TREESW = 9;//树坐下部分const int TREESE = 10;//树右下部分const int ROCK = 11;//石头//每张矩图的大小const int TILE_WIDTH = 64;const int TILE_HEIGHT = 48;//地图矩阵n x nconst int TILE_ROWS = 10;const int TILE_COLS = 10;//屏幕大小const int SCREEN_WIDTH = 640;const int SCREEN_HEIGHT = 480;int g_tileMap[TILE_ROWS][TILE_COLS] = {GRASS,GRASS,GRASS,GRASS,GRASS,GRASS,GRASS,GRASS,GRASS,GRASS,GRASS,GRASS,GRASS,GRASS,GRASS,GRASS,GRASS,GRASS,GRASS,GRASS,GRASS,GRASS,GRASS,GRASS,GRASS,GRASS,GRASS,PATHNW,PATH,PATH,GRASS,GRASS,GRASS,GRASS,GRASS,TREENW,TREENE,PATH,GRASS,GRASS,PATH ,PATH ,PATH ,PATH ,PATHNE,TREESW,TREESE,PATH,ROCK,GRASS,GRASS,GRASS,GRASS,GRASS,PATH,GRASS,GRASS,PATH,GRASS,GRASS,GRASS,GRASS,GRASS,GRASS,PATHSW,PATH,PATH,PATHSE,GRASS,GRASS,GRASS,GRASS,GRASS,GRASS,GRASS,GRASS,GRASS,GRASS,GRASS,GRASS,GRASS,ROCK,GRASS,GRASS,GRASS,GRASS,GRASS,GRASS,GRASS,GRASS,GRASS,GRASS,GRASS,GRASS,GRASS,GRASS,GRASS,GRASS,GRASS,GRASS,};//四个方向const int NORTH = 1;const int SOUTH = 2;const int EAST = 3;const int WEST = 4;//人物参数const int ALEC_IMAGE = 12;//ALEC图片const int ALEC_SPRITE = 100;//ALEC精灵const int ALEC_FRAME_WIDTH = 40;//alec人物图片宽度const int ALEC_FRAME_HEIGHT = 75;//alec人物图片高度const int ALEC_FRAME_COUNT = 16;//总共16幅图片const int EAST_START = 1;//向东开始const int EAST_END = 4;//向东结束const int NORTH_START = 5;//向北开始const int NORTH_END = 8;//向北结束const int SOUTH_START = 9;//向南开始const int SOUTH_END = 12;//向南结束const int WEST_START = 13;//向西开始const int WEST_END = 16;//向西结束const int ALEC_FPS = 5;//帧率const int ANIMATION_LOOP = 1;//循环const int WALK_DISTANCE = 4;const int STANDING = 0;//站立const int WALKING = 1;//行走const float ALEC_STARTING_X = 0;//X坐标const float ALEC_STARTING_Y = 150;//Y坐标int g_alecDirection = EAST;//人物朝向int g_state = STANDING;//人物当前状态//测试数据const int X = 1;const int Y = 2;//Functionvoid loadTiles();//加载tile图片void displayTiles();//输出地图void updateAlecX(float);void updateAlecY(float);int direction(float,float);bool checkCollision(float x,float y);void app::Begin(void){agk::SetVirtualResolution (SCREEN_WIDTH, SCREEN_HEIGHT);agk::SetWindowTitle("Walking Alec");agk::LoadImage(ALEC_IMAGE,"Alec/Alec.png");agk::CreateSprite(ALEC_SPRITE,ALEC_IMAGE);agk::SetSpriteDepth(ALEC_SPRITE,0);agk::SetSpritePosition(ALEC_SPRITE,ALEC_STARTING_X,ALEC_STARTING_Y);agk::SetSpriteAnimation(ALEC_SPRITE,ALEC_FRAME_WIDTH,ALEC_FRAME_HEIGHT,ALEC_FRAME_COUNT);agk::CreateText(X,agk::Str(ALEC_STARTING_X));agk::SetTextSize(X,24);agk::SetTextPosition(X,SCREEN_WIDTH - agk::GetTextTotalWidth(X),0);agk::CreateText(Y,agk::Str(ALEC_STARTING_Y));agk::SetTextSize(Y,24);agk::SetTextPosition(Y,SCREEN_WIDTH - agk::GetTextTotalWidth(Y),agk::GetTextTotalHeight(X)+5);agk::CreateText(200,"10");agk::SetTextSize(200,24);agk::SetTextPosition(200,SCREEN_WIDTH - agk::GetTextTotalWidth(200),agk::GetTextTotalHeight(X)+5+agk::GetTextTotalHeight(Y)+5);agk::CreateText(201,"10");agk::SetTextSize(201,24);agk::SetTextPosition(201,SCREEN_WIDTH - agk::GetTextTotalWidth(201),agk::GetTextTotalHeight(X)+5+agk::GetTextTotalHeight(Y)+5+agk::GetTextTotalHeight(200)+5);agk::CreateText(202,"1");agk::SetTextSize(202,24);agk::SetTextPosition(202,0,400);loadTiles();displayTiles();}void app::Loop (void){float directionX = agk::GetDirectionX();float directionY = agk::GetDirectionY();agk::SetTextString(X,agk::Str(agk::GetSpriteX(ALEC_SPRITE)));agk::SetTextString(Y,agk::Str(agk::GetSpriteY(ALEC_SPRITE)));int isLEFTRIGHT = direction(directionX,directionY);switch(isLEFTRIGHT){case 0:if(g_state==WALKING){g_state = STANDING;switch(g_alecDirection){case NORTH:agk::PlaySprite(ALEC_SPRITE,1,ANIMATION_LOOP,6,6);break;case SOUTH:agk::PlaySprite(ALEC_SPRITE,1,ANIMATION_LOOP,10,10);break;case WEST:agk::PlaySprite(ALEC_SPRITE,1,ANIMATION_LOOP,14,14);break;case EAST:agk::PlaySprite(ALEC_SPRITE,1,ANIMATION_LOOP,2,2);break;}}break;case 1:updateAlecX(directionX);break;case 2:updateAlecY(directionY);break;}agk::Sync();}void app::End (void){}void loadTiles(){//加载tile图片agk::LoadImage(GRASS,"Alec/Grass.png");agk::LoadImage(PATH,"Alec/Path.png");agk::LoadImage(PATHNE,"Alec/PathNE.png");agk::LoadImage(PATHNW,"Alec/PathNW.png");agk::LoadImage(PATHSE,"Alec/PathSE.png");agk::LoadImage(PATHSW,"Alec/PathSW.png");agk::LoadImage(TREENW,"Alec/TreeNW.png");agk::LoadImage(TREENE,"Alec/TreeNE.png");agk::LoadImage(TREESW,"Alec/TreeSW.png");agk::LoadImage(TREESE,"Alec/TreeSE.png");agk::LoadImage(ROCK,"Alec/Rock.png");}void displayTiles(){float x = 0, y = 0;int spriteIndex;for(int r = 0;r<TILE_ROWS;r++){x = 0;for(int c = 0 ; c < TILE_COLS; c++){spriteIndex = agk::CreateSprite(g_tileMap[r][c]);agk::SetSpritePosition(spriteIndex,x,y);x+=TILE_WIDTH;}y+=TILE_HEIGHT;}}void updateAlecX(float directionX){float alecX,newX;alecX = agk::GetSpriteX(ALEC_SPRITE);if(directionX>0){if(g_alecDirection !=EAST || g_state==STANDING){agk::PlaySprite(ALEC_SPRITE,ALEC_FPS,ANIMATION_LOOP,EAST_START,EAST_END);g_alecDirection = EAST;g_state = WALKING;}if(alecX+ALEC_FRAME_WIDTH <= SCREEN_WIDTH-WALK_DISTANCE && checkCollision(alecX+WALK_DISTANCE,agk::GetSpriteY(ALEC_SPRITE))){newX = alecX + WALK_DISTANCE;agk::SetSpriteX(ALEC_SPRITE,newX);}}else if(directionX < 0){if(g_alecDirection !=WEST || g_state==STANDING){agk::PlaySprite(ALEC_SPRITE,ALEC_FPS,ANIMATION_LOOP,WEST_START,WEST_END);g_alecDirection = WEST;g_state = WALKING;}if(alecX>=WALK_DISTANCE && checkCollision(alecX-WALK_DISTANCE,agk::GetSpriteY(ALEC_SPRITE))){newX = alecX - WALK_DISTANCE;agk::SetSpriteX(ALEC_SPRITE,newX);}}}void updateAlecY(float directionY){float alecY,newY;alecY = agk::GetSpriteY(ALEC_SPRITE);if(directionY > 0){if(g_alecDirection != SOUTH || g_state==STANDING){agk::PlaySprite(ALEC_SPRITE,ALEC_FPS,ANIMATION_LOOP,SOUTH_START,SOUTH_END);g_alecDirection = SOUTH;g_state = WALKING;}if(alecY+ALEC_FRAME_HEIGHT <= SCREEN_HEIGHT-WALK_DISTANCE && checkCollision(agk::GetSpriteX(ALEC_SPRITE),alecY+WALK_DISTANCE)){newY = alecY + WALK_DISTANCE;agk::SetSpriteY(ALEC_SPRITE,newY);}}else if(directionY < 0){if(g_alecDirection != NORTH || g_state==STANDING){agk::PlaySprite(ALEC_SPRITE,ALEC_FPS,ANIMATION_LOOP,NORTH_START,NORTH_END);g_alecDirection = NORTH;g_state = WALKING;}if(alecY>=WALK_DISTANCE && checkCollision(agk::GetSpriteX(ALEC_SPRITE),alecY-WALK_DISTANCE)){newY = alecY - WALK_DISTANCE;agk::SetSpriteY(ALEC_SPRITE,newY);}}}int direction(float x,float y){int c=0,isx = -1;if(x!=0){c++;isx = 1;}if(y!=0){c++;isx = 0;}switch(c){case 0:return 0;break;case 1:if(isx == 1){return 1;}else if(isx == 0){return 2;}break;case 2:switch(g_alecDirection){case NORTH:case SOUTH:return 1;break;case WEST:case EAST:return 2;break;}break;}return 0;}bool checkCollision(float a,float b){int y = (int)((a + ALEC_FRAME_WIDTH/2)/TILE_WIDTH);int x = (int)((b + ALEC_FRAME_HEIGHT)/TILE_HEIGHT);agk::SetTextString(200,agk::Str(x));agk::SetTextString(201,agk::Str(y));agk::SetTextString(202,agk::Str(g_tileMap[x][y]));if(g_tileMap[x][y]>=7){return false;}return true;}


做出的修改如下:

① 小人速度加快。

② 增加了阻碍移动的物体。

③ 按下左右键时候按下上下键的时候互相切换,反之亦然。这样虽然避免了if和else if导致有一个键先行判断而另一个键后判断的情况。但是人物移动的时候两个方向快速切换也是影响视觉效果。最好还是绘制四个斜方向的移动小人动画。

④ 小人移动的时候双脚摆动,站立时停止摆动。


实际上的速度要比gif图片要快的多。中间的图上右上右动的极快。

agk有一点致命的地方是并不支持中文文本。中文文本输出会出现乱码。所以想要中文只能用图片的形式输出了。

0 0