C 保存游戏状态,减少传递的变量
我一直在想,是否有一种方法可以以透明的方式保存游戏状态。这不是一个关于实际保存的问题(我知道如何保存到文件等),而是以一种清晰、简单和易懂的方式编写 到目前为止,我有三个想法(记住,我希望它可以是一个函数或一些简单的东西,如C 保存游戏状态,减少传递的变量,c,C,我一直在想,是否有一种方法可以以透明的方式保存游戏状态。这不是一个关于实际保存的问题(我知道如何保存到文件等),而是以一种清晰、简单和易懂的方式编写 到目前为止,我有三个想法(记住,我希望它可以是一个函数或一些简单的东西,如savegame()),没有一个是完美的: 将我要保存的每个变量放入结构中,如: 正如您所看到的,它看起来不太好,只保存一个变量需要这么多行:如果我想保存40个变量呢?如果我想在代码中保存5-6个位置,该怎么办 将我的函数设为snake长(这会导致加载回函数时出现问题,因此,
savegame()
),没有一个是完美的:
loadgame
func):s
”
结论:
我的想法是改变第二种选择,只是为了减少每次调用
savegame(…)
;要简化savegame()代码>,有办法吗?如果不使用define
?这里有一种动态方法,可以执行与您在第一个选项中描述的类似的操作,即使用指向结构的指针跟踪游戏状态,但也可以在二进制文件中存储和恢复该数据
下面的.c和.h文件说明了可以使用复合结构的想法,即一个包含多个其他结构的结构,该结构在任何时候都包含表示程序中状态的所有值。这很容易通过一个(多个)具有很少参数的函数(原型,例如char*GetState(state*in,const char*filespec);和char*SetState(state*out,const char*filespec);)进行传递,而这些参数反过来又会将结构的内容写入或读取二进制缓冲区。我使用此方法在文件中存储和检索多组状态数据
请注意,结构具有随机场,您当然可以根据需要修改这些随机场,但其思想是您可以在状态日期更新或需要存储的每个函数中传递一个指向所有状态数据的指针值
所以,保存gamestate.c
#include <so_SaveGameState.h>
unsigned char *pByteA;
GAME_STATE game = {{{"jim", "C:\\ico1.ico", {10, 120, 3}}, {"joe", "C:\\ico2.ico", {80, 10, -5}},{"larry", "C:\\ico3.ico", {15, -45, -45}},{"sue", "C:\\ico4.ico", {-100, -45, 45}}}, ENVR_3};
GAME_STATE *pGame = NULL;
int main(void)
{
pGame = &game;//point to populated memory
printf("Player 3 position\nx = %d\ny = %d\nz = %d\n", game.plyr[2].pos.x, game.plyr[2].pos.y, game.plyr[2].pos.z);
//example function that changes game state
UpdatePlayerPosition(&pGame, 2);
printf("Player 3 position\nx = %d\ny = %d\nz = %d\n", game.plyr[2].pos.x, game.plyr[2].pos.y, game.plyr[2].pos.z);
UpdatePlayerPosition(&pGame, 2);
printf("Player 3 position\nx = %d\ny = %d\nz = %d\n", game.plyr[2].pos.x, game.plyr[2].pos.y, game.plyr[2].pos.z);
UpdatePlayerPosition(&pGame, 2);
printf("Player 3 position\nx = %d\ny = %d\nz = %d\n", game.plyr[2].pos.x, game.plyr[2].pos.y, game.plyr[2].pos.z);
//prepare an instance of game state for storeing
(const GAME_STATE *)pByteA = &game;
int len1 = sizeof(game);
BOOL status = storeState("C:\\tempextract\\binFileStruct.bin", pByteA, len1);
//recover a stored state
unsigned char *buf = recoverState("C:\\tempextract\\binFileStruct.bin");
GAME_STATE *game_2 = (GAME_STATE *)buf;
free(game_2);
return 0;
}
unsigned char * recoverState(const char *filespec)
{
size_t sz = 0;
int n = 0;
unsigned char *binBuf = NULL;
FILE *fp = fopen(filespec, "rb");
if(fp)
{
fseek(fp, 0L, SEEK_END);
sz = ftell(fp);
fseek(fp, 0L, SEEK_SET);
rewind(fp);
binBuf = calloc(sz, sizeof(*binBuf));
n = fread(binBuf, sizeof(unsigned char), sz, fp);
fclose(fp);
}
if(n == sz)
{
return binBuf;
}
else
{
return NULL;
}
}
int storeState(const char *filespec, const unsigned char *buf, size_t sz)
{
int count = 0;
FILE *fp = fopen(filespec, "wb");
if(fp)
{
count = fwrite(buf, sizeof(unsigned char), sz, fp);
fclose(fp);
}
return (count == sz) ? 1 : 0;
}
void UpdatePlayerPosition(GAME_STATE **game, int player)
{
static int x=0, y=0, z=0;
static BOOL toggle = TRUE;
toggle = (toggle == 1) ? -1 : 1;
srand(clock());
//using fake assignment here
//i.e. you would have other criteria to set actual position
x += toggle * rand()%300;
y += toggle * rand()%300;
z += toggle * rand()%300;
(*game)->plyr[player].pos.x = x;
(*game)->plyr[player].pos.y = y;
(*game)->plyr[player].pos.y = z;
}
这些都是您明智的选择。如果您将游戏存储在一个文件中,您可以直接fread()
和fwrite()
结构。您还可以将所有游戏状态变量放入一个分区,并保存和加载整个分区。这是非标准的,并且会出错(特别是当您重新编译程序并且变量的顺序不同时)。因此,加载游戏fread()就足够了,但无论如何,除非我使用选项3,否则我必须执行类似于struct mystruct=loadgame()的操作;x=mystruct.x;等
void savegame(int hp, pos position, int x, int y,...) // too long
{ ... }
void loadgame(int &hp, pos &position, int &x, int &y,...) // too long
{ ... }
...
int main()
{
...
savegame(hp, pos, x, y, ...) // too long
...
loadgame(hp, pos, x, y, ...) // too long
}
struct gamestate{
int hp;
pos position;
int x;
int y;
}
...
int main()
{
struct gamestate s;
s.x++;
...
}
#include <so_SaveGameState.h>
unsigned char *pByteA;
GAME_STATE game = {{{"jim", "C:\\ico1.ico", {10, 120, 3}}, {"joe", "C:\\ico2.ico", {80, 10, -5}},{"larry", "C:\\ico3.ico", {15, -45, -45}},{"sue", "C:\\ico4.ico", {-100, -45, 45}}}, ENVR_3};
GAME_STATE *pGame = NULL;
int main(void)
{
pGame = &game;//point to populated memory
printf("Player 3 position\nx = %d\ny = %d\nz = %d\n", game.plyr[2].pos.x, game.plyr[2].pos.y, game.plyr[2].pos.z);
//example function that changes game state
UpdatePlayerPosition(&pGame, 2);
printf("Player 3 position\nx = %d\ny = %d\nz = %d\n", game.plyr[2].pos.x, game.plyr[2].pos.y, game.plyr[2].pos.z);
UpdatePlayerPosition(&pGame, 2);
printf("Player 3 position\nx = %d\ny = %d\nz = %d\n", game.plyr[2].pos.x, game.plyr[2].pos.y, game.plyr[2].pos.z);
UpdatePlayerPosition(&pGame, 2);
printf("Player 3 position\nx = %d\ny = %d\nz = %d\n", game.plyr[2].pos.x, game.plyr[2].pos.y, game.plyr[2].pos.z);
//prepare an instance of game state for storeing
(const GAME_STATE *)pByteA = &game;
int len1 = sizeof(game);
BOOL status = storeState("C:\\tempextract\\binFileStruct.bin", pByteA, len1);
//recover a stored state
unsigned char *buf = recoverState("C:\\tempextract\\binFileStruct.bin");
GAME_STATE *game_2 = (GAME_STATE *)buf;
free(game_2);
return 0;
}
unsigned char * recoverState(const char *filespec)
{
size_t sz = 0;
int n = 0;
unsigned char *binBuf = NULL;
FILE *fp = fopen(filespec, "rb");
if(fp)
{
fseek(fp, 0L, SEEK_END);
sz = ftell(fp);
fseek(fp, 0L, SEEK_SET);
rewind(fp);
binBuf = calloc(sz, sizeof(*binBuf));
n = fread(binBuf, sizeof(unsigned char), sz, fp);
fclose(fp);
}
if(n == sz)
{
return binBuf;
}
else
{
return NULL;
}
}
int storeState(const char *filespec, const unsigned char *buf, size_t sz)
{
int count = 0;
FILE *fp = fopen(filespec, "wb");
if(fp)
{
count = fwrite(buf, sizeof(unsigned char), sz, fp);
fclose(fp);
}
return (count == sz) ? 1 : 0;
}
void UpdatePlayerPosition(GAME_STATE **game, int player)
{
static int x=0, y=0, z=0;
static BOOL toggle = TRUE;
toggle = (toggle == 1) ? -1 : 1;
srand(clock());
//using fake assignment here
//i.e. you would have other criteria to set actual position
x += toggle * rand()%300;
y += toggle * rand()%300;
z += toggle * rand()%300;
(*game)->plyr[player].pos.x = x;
(*game)->plyr[player].pos.y = y;
(*game)->plyr[player].pos.y = z;
}
typedef enum {//environment
ENVR_1, //bad weather
ENVR_2, //hill
ENVR_3, //pit
ENVR_4, //angry birds
ENVR_5, //enemy guard
MAX_OBST
}ENVR_TYPE;
typedef struct {
int x;
int y;
int z;
}POS;
typedef struct {
ENVR_TYPE envir;
//...
}ENVIR;
typedef struct {
char name[20];
char iconFile[260];
POS pos;
//...
}PLAYER;
typedef struct {
PLAYER plyr[4];
ENVIR env;
//...
}GAME_STATE;
extern GAME_STATE game;
unsigned char * recoverState(const char *filespec);
int storeState(const char *filespec, const unsigned char *buf, size_t sz);