📄 game.c
字号:
//*****************************************************************************
//
// game.c - A "fly through the tunnel and shoot things" game.
//
// Copyright (c) 2006-2007 Luminary Micro, Inc. All rights reserved.
//
// Software License Agreement
//
// Luminary Micro, Inc. (LMI) is supplying this software for use solely and
// exclusively on LMI's microcontroller products.
//
// The software is owned by LMI and/or its suppliers, and is protected under
// applicable copyright laws. All rights are reserved. You may not combine
// this software with "viral" open-source software in order to form a larger
// program. Any use in violation of the foregoing restrictions may subject
// the user to criminal sanctions under applicable laws, as well as to civil
// liability for the breach of the terms and conditions of this license.
//
// THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED
// OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
// LMI SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR
// CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
//
// This is part of revision 1952 of the Stellaris Peripheral Driver Library.
//
//*****************************************************************************
#include "../../../hw_memmap.h"
#include "../../../hw_types.h"
#include "../../../src/uart.h"
#include "../osram96x16x1.h"
#include "game.h"
#include "globals.h"
#include "random.h"
//*****************************************************************************
//
// A bitmap for the "Press Button To Play" screen. The bitmap is as follows:
//
// xxx.........................xxx........x...x...............xxxxx.......
// x..x........................x..x.......x...x.................x.........
// x..x.x.xx..xx...xxx..xxx....x..x.x..x.xxx.xxx..xx..xxx.......x..xx.....
// xxx..xx...x..x.x....x.......xxx..x..x..x...x..x..x.x..x......x.x..x....
// x....x....xxxx..xx...xx.....x..x.x..x..x...x..x..x.x..x......x.x..x....
// x....x....x.......x....x....x..x.x..x..x...x..x..x.x..x......x.x..x....
// x....x.....xxx.xxx..xxx.....xxx...xxx...x...x..xx..x..x......x..xx.....
// .......................................................................
//
// Continued...
//
// xxx..x..........
// x..x.x..........
// x..x.x..xx..x..x
// xxx..x.x..x.x..x
// x....x.x..x.x..x
// x....x.x..x..xxx
// x....x..xxx....x
// ............xxx.
//
//*****************************************************************************
static const unsigned char g_pucPlay[87] =
{
0x7f, 0x09, 0x09, 0x06, 0x00, 0x7c, 0x08, 0x04, 0x04, 0x00, 0x38, 0x54,
0x54, 0x58, 0x00, 0x48, 0x54, 0x54, 0x24, 0x00, 0x48, 0x54, 0x54, 0x24,
0x00, 0x00, 0x00, 0x00, 0x7f, 0x49, 0x49, 0x36, 0x00, 0x3c, 0x40, 0x40,
0x7c, 0x00, 0x04, 0x3f, 0x44, 0x00, 0x04, 0x3f, 0x44, 0x00, 0x38, 0x44,
0x44, 0x38, 0x00, 0x7c, 0x04, 0x04, 0x78, 0x00, 0x00, 0x00, 0x00, 0x01,
0x01, 0x7f, 0x01, 0x39, 0x44, 0x44, 0x38, 0x00, 0x00, 0x00, 0x00, 0x7f,
0x09, 0x09, 0x06, 0x00, 0x7f, 0x00, 0x38, 0x44, 0x44, 0x78, 0x00, 0x9c,
0xa0, 0xa0, 0x7c
};
//*****************************************************************************
//
// A bitmap for the space ship. The bitmap is as follows:
//
// x....
// xxx..
// xxxxx
//
//*****************************************************************************
static const unsigned char g_pucShip[5] =
{
0x07, 0x06, 0x06, 0x04, 0x04
};
//*****************************************************************************
//
// A bitmap for mine type one. The bitmap is as follows:
//
// .x.
// xxx
// .x.
//
//*****************************************************************************
static const unsigned char g_pucMine1[3] =
{
0x02, 0x07, 0x02
};
//*****************************************************************************
//
// A bitmap for mine type two. The bitmap is as follows:
//
// x..x
// .xx.
// .xx.
// x..x
//
//*****************************************************************************
static const unsigned char g_pucMine2[4] =
{
0x09, 0x06, 0x06, 0x09
};
//*****************************************************************************
//
// A bitmap for the first stage of an explosion. The bitmap is as follows:
//
// x
//
//*****************************************************************************
static const unsigned char g_pucExplosion1[1] =
{
0x01
};
//*****************************************************************************
//
// A bitmap for the second stage of an explosion. The bitmap is as follows:
//
// x.x
// .x.
// x.x
//
//*****************************************************************************
static const unsigned char g_pucExplosion2[3] =
{
0x05, 0x02, 0x05
};
//*****************************************************************************
//
// A bitmap for the third stage of an explosion. The bitmap is as follows:
//
// x...x
// .x.x.
// ..x..
// .x.x.
// x...x
//
//*****************************************************************************
static const unsigned char g_pucExplosion3[5] =
{
0x11, 0x0a, 0x04, 0x0a, 0x11
};
//*****************************************************************************
//
// A bitmap for the fourth stage of an explosion. The bitmap is as follows:
//
// x..x..x
// .x.x.x.
// ..x.x..
// xx.x.xx
// ..x.x..
// .x.x.x.
// x..x..x
//
//*****************************************************************************
static const unsigned char g_pucExplosion4[7] =
{
0x49, 0x2a, 0x14, 0x6b, 0x14, 0x2a, 0x49
};
//*****************************************************************************
//
// This array contains the sequence of explosion images, along with the width
// of each one.
//
//*****************************************************************************
static const struct
{
const unsigned char *pucImage;
unsigned char ucAdjust;
unsigned char ucWidth;
}
g_psExplosion[4] =
{
{ g_pucExplosion1, 0, 1 },
{ g_pucExplosion2, 1, 3 },
{ g_pucExplosion3, 2, 5 },
{ g_pucExplosion4, 3, 7 }
};
//*****************************************************************************
//
// Storage for the background image of the tunnel. This is copied to the local
// frame buffer and then the other elements are overlaid upon it.
//
//*****************************************************************************
unsigned char g_pucBackground[192];
//*****************************************************************************
//
// The offsets from the top and bottom scan lines of the display to the wall of
// the tunnel. The first element is the offset from the top scan line and the
// second element is the offfset from the bottom scan line.
//
//*****************************************************************************
static unsigned char g_pucOffset[2];
//*****************************************************************************
//
// An array of mines currently visible on the display. Up to five mines can be
// displayed, and each has three variables associated with it: the type (in
// index zero), the horizontal position (in index one), and the vertical
// position (in index two). If all three variables are negative one, then that
// mine does not exist.
//
//*****************************************************************************
static char g_pcMines[5][3];
//*****************************************************************************
//
// The location of the missile, if it has been fired. The first entry contains
// the horizontal position and the second entry contains the vertical position.
// If both are negative one, then the missile has not been fired.
//
//*****************************************************************************
static char g_pcMissile[2];
//*****************************************************************************
//
// An array of explosions currently active on the display. Up to five
// explosions can be displayed (the fifth being dedicated to the ship
// explosion), and each has three variables associated with it: the explosion
// step number (in index zero), the horizontal position (in index one), and the
// vertical position (in index two). If the step number is negative one, then
// that explosion is not active.
//
//*****************************************************************************
static char g_pcExplosions[5][3];
//*****************************************************************************
//
// The point accumulated during the game. One point is added for each time the
// display is scrolled to the left (i.e. the ship travels one step through the
// tunnel) and twenty-five points are added for each obstacle that is shot.
//
//*****************************************************************************
static unsigned long g_ulScore;
//*****************************************************************************
//
// Scroll the tunnel image one column to the left and add a new column of
// tunnel on the right side of the display.
//
//*****************************************************************************
static void
UpdateBackground(unsigned long ulGap)
{
unsigned long ulCount, ulIdx;
//
// Loop through the array of mines.
//
for(ulIdx = 0; ulIdx < 5; ulIdx++)
{
//
// Skip this mine if it is disabled.
//
if((g_pcMines[ulIdx][0] == (char)-1) &&
(g_pcMines[ulIdx][1] == (char)-1) &&
(g_pcMines[ulIdx][2] == (char)-1))
{
continue;
}
//
// Stop searching if this mine is near or on the right side of the
// display.
//
if(g_pcMines[ulIdx][1] > 91)
{
break;
}
}
//
// Get a random number based on the collected entropy.
//
ulCount = RandomNumber();
//
// If the top part of the tunnel is not at the top of the display, then
// move it up 18.75% of the time.
//
if((ulCount < 0x30000000) && (g_pucOffset[0] != 0))
{
g_pucOffset[0]--;
}
//
// If the top part of the tunnel is not too close to the bottom part of the
// tunnel, and there is no mine on the right side of the display or the top
// part of the tunnel is far enough away from the mine, then move it down
// 18.75% of the time.
//
if((ulCount > 0xd0000000) && ((g_pucOffset[0] + ulGap) < g_pucOffset[1]) &&
((ulIdx == 5) || ((g_pcMines[ulIdx][2] - g_pucOffset[0]) > 1)))
{
g_pucOffset[0]++;
}
//
// Get a new pseudo random number based on the original random number (no
// new entropy will have been collected, so it will return the exact same
// random number, which isn't so random).
//
ulCount = NEXT_RAND(ulCount);
//
// If the bottom part of the tunnel is not too close to the top part of the
// tunnel, and there is no mine on the right side of the display or the
// bottom part of the tunnel is far enough away from the mine, then move it
// up 18.75% of the time.
//
if((ulCount < 0x30000000) && ((g_pucOffset[1] - ulGap) > g_pucOffset[0]) &&
((ulIdx == 5) || ((g_pucOffset[1] - g_pcMines[ulIdx][2]) > 5)))
{
g_pucOffset[1]--;
}
//
// If the bottom part of the tunnel is not at the bottom of the display,
// then move it down 18.75% of the time.
//
if((ulCount > 0xd0000000) && (g_pucOffset[1] != 16))
{
g_pucOffset[1]++;
}
//
// Move the background image one column to the left.
//
for(ulCount = 0; ulCount < 192; ulCount++)
{
g_pucBackground[ulCount] = g_pucBackground[ulCount + 1];
}
//
// Generate a new column on the right side of the background image.
//
g_pucBackground[95] = 0xff >> (8 - g_pucOffset[0]);
g_pucBackground[191] = 0xff << (g_pucOffset[1] - 8);
//
// Copy the background image to the local frame buffer.
//
for(ulCount = 0; ulCount < 192; ulCount += 4)
{
*(unsigned long *)(g_pucFrame + ulCount) =
*(unsigned long *)(g_pucBackground + ulCount);
}
}
//*****************************************************************************
//
// Draws a image on the local frame buffer.
//
//*****************************************************************************
static void
DrawImage(const unsigned char *pucImage, long lX, long lY,
unsigned long ulWidth)
{
unsigned long ulIdx;
//
// Loop through the columns of this mine.
//
for(ulIdx = 0; ulIdx < ulWidth; ulIdx++)
{
//
// See if this column is on the display.
//
if(((lX + (long)ulIdx) >= 0) && ((lX + ulIdx) < 96))
{
//
// See if this mine is in the upper or lower row.
//
if(lY < 8)
{
//
// Add this mine to the first row of the local frame buffer.
// Part of the mine image may be in the second row as well, so
// possibly add it there as well.
//
g_pucFrame[lX + ulIdx] |= pucImage[ulIdx] << lY;
g_pucFrame[lX + ulIdx + 96] |= pucImage[ulIdx] >> (8 - lY);
}
else
{
//
// Add this mine to the second row of the local frame buffer.
//
g_pucFrame[lX + ulIdx + 96] |= pucImage[ulIdx] << (lY - 8);
}
}
}
}
//*****************************************************************************
//
// Update the mines in the tunnel.
//
//*****************************************************************************
static void
UpdateMines(void)
{
unsigned long ulCount, ulIdx, ulMax;
//
// The maximum horizontal position of any mine found.
//
ulMax = 0;
//
// Loop through the five possible mines.
//
for(ulCount = 0; ulCount < 5; ulCount++)
{
//
// Skip this mine if it does not exist.
//
if((g_pcMines[ulCount][0] == (char)-1) &&
(g_pcMines[ulCount][1] == (char)-1) &&
(g_pcMines[ulCount][2] == (char)-1))
{
continue;
}
//
// Move the mine one step to the left (i.e. keep it in the same place
// within the tunnel).
//
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -