这可能需要一段时间来解释 - 去品尝小吃你读到这一段时间。
我开发++中的音乐游戏机在C(我是一个相当新的程序员)一个2D益智游戏构建平台。 直到昨天晚上,我一直在做,我用这是GBA的屏幕的尺寸水平测试phyics引擎(只是一些轴线对齐边框的东西)。 然而,最后一场比赛将要求有一个水平,这个水平比屏幕的尺寸大,所以我试图建立一个系统,它允许GBA的屏幕跟随玩家,并作为一个结果,我只好动用一切在相对于屏幕的偏移屏幕。
但是,我有麻烦时,我显示可拿起和操纵的水平立方体。 每当玩家移动,屏幕上的方块的位置似乎漂离的水平它们的实际位置了。 这就像在那里绘制立方体为单个帧同步的 - 如果我暂停当玩家移动时,框显示在完全正确的位置,本场比赛,但是当我取消暂停,他们飘出来的地方,直到玩家停止再次移动。
我的类的简要描述 - 有一个基类称为对象定义(X,Y)位置和宽度和高度,有从对象继承,并增加了速度分量的实体类,并且从实体继承的字符类并增加了运动功能。 我的球员是一个Character对象,而我要拿起立方体是实体对象的数组。 无论是球员和立方体阵列是二级类,这也从Object继承的成员。
我怀疑问题出在最后的代码示例中,然而,对于什么,我试图做我在一个稍微更符合逻辑顺序排列的样品完全理解。
这里有水平的截头:
class Level : public Object
{
private:
//Data
int backgroundoffsetx;
int backgroundoffsety;
//Methods
void ApplyEntityOffsets();
void DetermineBackgroundOffsets();
public:
//Data
enum {MAXCUBES = 20};
Entity cube[MAXCUBES];
Character player;
int numofcubes;
//Methods
Level();
void Draw();
void DrawBackground(dimension);
void UpdateLevelObjects();
};
...和实体:
class Entity : public Object
{
private:
//Methods
int GetScreenAxis(int &, int &, const int, int &, const int);
public:
//Data
int drawx; //Where the Entity's x position is relative to the screen
int drawy; //Where the Entity's y position is relative to the screen
//Methods
void SetScreenPosition(int &, int &);
};
这里是我的主游戏循环中的相关部分:
//Main loop
while (true)
{
...
level.MoveObjects(buttons);
level.Draw();
level.UpdateLevelObjects();
...
}
由于精灵都显示在暂停时正确的地方的路上,我敢肯定,问题不在于MoveObjects()
这决定了相对于水平等级玩家和立方体的poitions。 使叶片Draw()
和UpdateLevelObjects()
好吧, Draw()
我在事件提供这一点,这不是我的立方体正在显示不正确,但水平和平台时,他们坐(我不认为这是问题,但可能)。 Draw()
只要求一个相关功能, DrawBackground()
/**
Draws the background of the level;
*/
void Level::DrawBackground(dimension curdimension)
{
...
//Platforms
for (int i = 0; i < numofplatforms; i++)
{
for (int y = platform[i].Gety() / 8 ; y < platform[i].GetBottom() / 8; y++)
{
for (int x = platform[i].Getx() / 8; x < platform[i].GetRight() / 8; x++)
{
if (x < 32)
{
if (y < 32)
{
SetTile(25, x, y, 103);
}
else
{
SetTile(27, x, y - 32, 103);
}
}
else
{
if (y < 32)
{
SetTile(26, x - 32, y, 103);
}
else
{
SetTile(28, x - 32, y - 32, 103);
}
}
}
}
}
}
这不可避免地需要解释的一些量。 我的平台,以像素为单位,但在8×8像素的瓷砖显示,所以我必须划分它们的大小这个循环。 SetTile()
首先需要screenblock数。 我使用的显示平台的背景层为64×64瓦,所以需要每个32×32×2瓦到screenblocks显示它们。 该screenblocks编号为25-28。 103是我tilemap的瓦数。
这里的UpdateLevelObjects()
/**
Updates all gba objects in Level
*/
void Level::UpdateLevelObjects()
{
DetermineBackgroundOffsets();
ApplyEntityOffsets();
REG_BG2HOFS = backgroundoffsetx;
REG_BG3HOFS = backgroundoffsetx / 2;
REG_BG2VOFS = backgroundoffsety;
REG_BG3VOFS = backgroundoffsety / 2;
...
//Code which sets player position (drawx, drawy);
//Draw cubes
for (int i = 0; i < numofcubes; i++)
{
//Code which sets cube[i] position to (drawx, drawy);
}
}
的REG_BG
位是其允许背景层要由像素的数目垂直和水平偏移的GBA的寄存器。 这些偏移在第一计算DetermineBackgroundOffsets()
/**
Calculate the offsets of screen based on where the player is in the level
*/
void Level::DetermineBackgroundOffsets()
{
if (player.Getx() < SCREEN_WIDTH / 2) //If player is less than half the width of the screen away from the left wall of the level
{
backgroundoffsetx = 0;
}
else if (player.Getx() > width - (SCREEN_WIDTH / 2)) //If player is less than half the width of the screen away from the right wall of the level
{
backgroundoffsetx = width - SCREEN_WIDTH;
}
else //If the player is in the middle of the level
{
backgroundoffsetx = -((SCREEN_WIDTH / 2) - player.Getx());
}
if (player.Gety() < SCREEN_HEIGHT / 2)
{
backgroundoffsety = 0;
}
else if (player.Gety() > height - (SCREEN_HEIGHT / 2))
{
backgroundoffsety = height - SCREEN_HEIGHT;
}
else
{
backgroundoffsety = -((SCREEN_HEIGHT / 2) - player.Gety());
}
}
只是要清楚, width
是指以像素级的宽度,而SCREEN_WIDTH
指的是GBA的屏幕宽度的恒定值。 此外,比较遗憾的是懒惰的重复。
这里的ApplyEntityOffsets
:
/**
Determines the offsets that keep the player in the middle of the screen
*/
void Level::ApplyEntityOffsets()
{
//Player offsets
player.drawx = player.Getx() - backgroundoffsetx;
player.drawy = player.Gety() - backgroundoffsety;
//Cube offsets
for (int i = 0; i < numofcubes; i++)
{
cube[i].SetScreenPosition(backgroundoffsetx, backgroundoffsety);
}
}
基本上这个中心屏幕上的播放器时,它在水平的中间,并允许它移动到边缘时,对水平的边缘屏幕颠簸。 至于立方体:
/**
Determines the x and y positions of an entity relative to the screen
*/
void Entity::SetScreenPosition(int &backgroundoffsetx, int &backgroundoffsety)
{
drawx = GetScreenAxis(x, width, 512, backgroundoffsetx, SCREEN_WIDTH);
drawy = GetScreenAxis(y, height, 256, backgroundoffsety, SCREEN_HEIGHT);
}
忍耐一下 - 我将解释在某一时刻的512和256。 这里的GetScreenAxis()
/**
Sets the position along an axis of an entity relative to the screen's position
*/
int Entity::GetScreenAxis(int &axis, int &dimensioninaxis, const int OBJECT_OFFSET,
int &backgroundoffsetaxis, const int SCREEN_DIMENSION)
{
int newposition;
bool onawkwardedgeofscreen = false;
//If position of entity is partially off screen in -ve direction
if (axis - backgroundoffsetaxis < dimensioninaxis)
{
newposition = axis - backgroundoffsetaxis + OBJECT_OFFSET;
onawkwardedgeofscreen = true;
}
else
{
newposition = axis - backgroundoffsetaxis;
}
if ((newposition > SCREEN_DIMENSION) && !onawkwardedgeofscreen)
{
newposition = SCREEN_DIMENSION; //Gets rid of glitchy squares appearing on screen
}
return newposition;
}
OBJECT_OFFSET
(512和256)是GBA具体的东西-一个对象的x或y位置设置为负数不会做你通常打算什么-它弄乱了用于显示它的精灵。 但还有一招:如果你想设置一个负的X位置,您可以添加512至负数,并且(例如,如果你打算把它设置为-1,然后将其设置为精灵将出现在正确的地方512 + -1 = 511)。 同样,加入256个工程负Y位置(这是所有相对于屏幕,而不是水平)。 最后的if语句挡,如果他们通常会更远显示在屏幕显示的分数的立方体,为试图显示他们太远的出现,再次GBA具体的东西出问题平方结果。
你是一个绝对的圣人,如果你已经走到这一步已经阅读一切。 如果你能找到什么潜在的可能导致该漂流立方体,我将非常感激。 此外,为了普遍提高我的代码任何提示将不胜感激。
编辑:GBA的对象是设置播放器和多维数据集位置更新的方法如下:
for (int i = 0; i < numofcubes; i++)
{
SetObject(cube[i].GetObjNum(),
ATTR0_SHAPE(0) | ATTR0_8BPP | ATTR0_REG | ATTR0_Y(cube[i].drawy),
ATTR1_SIZE(0) | ATTR1_X(cube[i].drawx),
ATTR2_ID8(0) | ATTR2_PRIO(2));
}