📄 game.c
字号:
// Make the X axis difference be zero so that the next move
// attempt will be along the Y axis.
//
lX = 0;
}
else
{
//
// The monster is further away on the Y axis. See if it should
// be moved up or down.
//
if(bDown && (lY != 0))
{
//
// See if there is a wall blocking the monster's movement
// down.
//
if((g_ppcMaze[(g_pusMonsterY[ulLoop] + 12) / 12]
[g_pusMonsterX[ulLoop] / 12] == 0) &&
(g_ppcMaze[(g_pusMonsterY[ulLoop] + 12) / 12]
[(g_pusMonsterX[ulLoop] + 11) / 12] == 0))
{
//
// There is no wall obstructing the monster, so move it
// down.
//
g_pusMonsterY[ulLoop] += 2;
//
// The monster has been moved, so do not attempt to
// move it further.
//
break;
}
}
else if(lY != 0)
{
//
// See if there is a wall blocking the monster's movement
// up.
//
if((g_ppcMaze[(g_pusMonsterY[ulLoop] - 2) / 12]
[g_pusMonsterX[ulLoop] / 12] == 0) &&
(g_ppcMaze[(g_pusMonsterY[ulLoop] - 2) / 12]
[(g_pusMonsterX[ulLoop] + 11) / 12] == 0))
{
//
// There is no wall obstructing the monster, so move it
// up.
//
g_pusMonsterY[ulLoop] -= 2;
//
// The monster has been moved, so do not attempt to
// move it further.
//
break;
}
}
//
// Make the Y axis difference be zero so that the next move
// attempt will be along the X axis.
//
lY = 0;
}
}
}
}
//*****************************************************************************
//
// Draws the visible monsters onto the display.
//
//*****************************************************************************
static void
DrawMonsters(void)
{
long lMonsterX, lMonsterY, lX, lY;
unsigned char ucData1, ucData2;
unsigned long ulLoop, ulIdx;
//
// Loop through all the monsters.
//
for(ulLoop = 0; ulLoop < 100; ulLoop++)
{
//
// Skip this monster if it is dead.
//
if((g_pusMonsterX[ulLoop] == 0) && (g_pusMonsterY[ulLoop] == 0))
{
continue;
}
//
// Increment the monster animation count.
//
g_pucMonsterCount[ulLoop]++;
//
// Find the index into the animation sequence based on the current
// animation count.
//
for(ulIdx = 0; ulIdx < sizeof(g_pucMonster); ulIdx += 2)
{
if(g_pucMonster[ulIdx] > g_pucMonsterCount[ulLoop])
{
break;
}
}
//
// See if the animation sequence has been completed.
//
if(ulIdx == sizeof(g_pucMonster))
{
//
// Reset the animation count.
//
g_pucMonsterCount[ulLoop] = 0;
//
// Use the first image in the animation sequence.
//
ulIdx = g_pucMonster[1];
}
else
{
//
// Otherwise, use the most recent image in the animation sequence.
//
ulIdx = g_pucMonster[ulIdx - 1];
}
//
// Find the position of this monster on the display.
//
lMonsterX = g_pusMonsterX[ulLoop] - (g_usPlayerX - (64 - 6));
lMonsterY = g_pusMonsterY[ulLoop] - (g_usPlayerY - (47 - 6));
//
// Skip this monster if it is not on the display.
//
if((lMonsterX < -12) || (lMonsterX > 128) ||
(lMonsterY < -12) || (lMonsterY > 94))
{
continue;
}
//
// Loop through the scan lines of this monster.
//
for(lY = (lMonsterY < 0) ? -lMonsterY : 0;
(lY < 12) && ((lMonsterY + lY) < 94); lY++)
{
//
// Loop through the columns of this monster.
//
for(lX = (lMonsterX < 0) ? -lMonsterX : 0;
(lX < 12) && ((lMonsterX + lX) < 128); lX++)
{
//
// Copy the sprite data into the local frame buffer.
//
ucData1 = g_pucFrame[((lMonsterY + lY) * 64) +
((lMonsterX + lX) / 2)];
ucData2 = g_ppucSprites[ulIdx][(lY * 6) + (lX / 2)];
if((ucData2 & 0xf0) != 0x00)
{
ucData1 &= 0x0f;
}
if((ucData2 & 0x0f) != 0x00)
{
ucData1 &= 0xf0;
}
g_pucFrame[((lMonsterY + lY) * 64) + ((lMonsterX + lX) / 2)] =
ucData1 | ucData2;
}
}
}
}
//*****************************************************************************
//
// Adds a new explosion.
//
//*****************************************************************************
static void
AddExplosion(unsigned long ulX, unsigned long ulY)
{
unsigned long ulLoop;
//
// Loop through all the explosions looking for an inactive explosion.
//
for(ulLoop = 0; ulLoop < 4; ulLoop++)
{
if((g_pusExplosionX[ulLoop] == 0) && (g_pusExplosionY[ulLoop] == 0))
{
break;
}
}
//
// See if an inactive explosion was found.
//
if(ulLoop != 4)
{
//
// Add the new explosion.
//
g_pusExplosionX[ulLoop] = ulX;
g_pusExplosionY[ulLoop] = ulY;
//
// Start the explosion animation from the beginning.
//
g_pucExplosionCount[ulLoop] = 0;
}
}
//*****************************************************************************
//
// Sets the direction that the player's bullet will be fired.
//
//*****************************************************************************
static void
SetBulletDir(unsigned long ulBullet)
{
unsigned long ulLoop, ulDist, ulMin, ulIdx;
long lX, lY;
//
// The bullet will be fired towards the nearest monster. Loop through the
// monsters to find the one that is closest.
//
for(ulLoop = 0, ulMin = 0xffffffff, ulIdx = 0; ulLoop < 100; ulLoop++)
{
//
// Do not consider this monster if it is already dead.
//
if((g_pusMonsterX[ulLoop] == 0) && (g_pusMonsterY[ulLoop] == 0))
{
continue;
}
//
// Get the distance along the X and Y axis to this monster.
//
lX = (long)g_pusMonsterX[ulLoop] - (long)g_usPlayerX;
lY = (long)g_pusMonsterY[ulLoop] - (long)g_usPlayerY;
//
// Get the diagonal distance to this monster. The square root is
// omitted to speed computation (and since the actual distance is not
// required).
//
ulDist = (lX * lX) + (lY * lY);
//
// See if this monster is closer than the previously found closest
// monster.
//
if(ulDist < ulMin)
{
//
// This is now the closest monster found.
//
ulMin = ulDist;
ulIdx = ulLoop;
}
}
//
// See if a monster was found.
//
if(ulMin == 0xffffffff)
{
//
// There are no monsters left in the maze, so fire in the direction
// that the player is facing.
//
g_pucBulletDir[ulBullet] = ((g_ucDirection & 0x0f) |
(g_ucDirection >> 4));
if(g_pucBulletDir[ulBullet] == 0)
{
g_pucBulletDir[ulBullet] = 2;
}
}
else
{
//
// Get the distance along the X and Y axis to the monster.
//
lX = (long)g_pusMonsterX[ulIdx] - (long)g_usPlayerX;
lY = (long)g_pusMonsterY[ulIdx] - (long)g_usPlayerY;
//
// See if the monster is closer along the X or Y axis. The square is
// used to make both values be positive (as opposed to doing an
// absolute value). This is actually faster than an absolute value
// since multiply is single cycle whereas an absolute value will
// require a compare and conditional execution.
//
if((lX * lX) > (lY * lY))
{
//
// The monster is closer along the Y axis, so fire along the X
// axis. Determine if the monster is to the left or right.
//
if(lX < 0)
{
//
// The monster is to the left, so fire to the left.
//
g_pucBulletDir[ulBullet] = 4;
}
else
{
//
// The monster is to the right, so fire to the right.
//
g_pucBulletDir[ulBullet] = 8;
}
}
else
{
//
// The monster is closer along the X axis, so fire along the Y
// axis. Determine if the monster is above or below.
//
if(lY < 0)
{
//
// The monster is above, so fire up.
//
g_pucBulletDir[ulBullet] = 1;
}
else
{
//
// The monster is below, so fire down.
//
g_pucBulletDir[ulBullet] = 2;
}
}
}
}
//*****************************************************************************
//
// Draws the bullets onto the display.
//
//*****************************************************************************
static void
DrawBullets(tBoolean bFire)
{
unsigned long ulLoop, ulIdx;
tBoolean bHit;
long lX, lY;
//
// See if a new bullet should be fired.
//
if(bFire)
{
//
// Loop through the bullets looking for one that hasn't been fired.
//
for(ulLoop = 0; ulLoop < 4; ulLoop++)
{
if((g_pusBulletX[ulLoop] == 0) && (g_pusBulletY[ulLoop] == 0))
{
break;
}
}
//
// See if an unfired bullet was found.
//
if(ulLoop < 4)
{
//
// Play the bullet firing sound.
//
AudioPlaySound(g_pusFireEffect, sizeof(g_pusFireEffect) / 2);
//
// Set the direction for this bullet.
//
SetBulletDir(ulLoop);
//
// Set the initial position of the bullet based on the direction.
//
switch(g_pucBulletDir[ulLoop])
{
//
// The bullet is being fired up.
//
case 1:
{
//
// Set the position of the bullet at the top of the player.
//
g_pusBulletX[ulLoop] = g_usPlayerX + 4;
g_pusBulletY[ulLoop] = g_usPlayerY;
//
// This bullet has been positioned.
//
break;
}
//
// The bullet is being fired down.
//
case 2:
{
//
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -