Look Here First

Curious why I created this blog? The following two posts explain it all. Click on the titles below to read more.

What this Blog is about.

Project Description.

Saturday, April 23, 2011

Still working

I've been working on finishing the game, presenting the project, and writing the paper due with the project.  I'll finish writing about the project soon.  I just have to get things in before they are due first.

Saturday, April 16, 2011

Game Design: Running Out of Ram

While coding the last bit of game, the compiler/linker setup game the following error.


Linking: main.elf
arm-elf-gcc -mthumb -mcpu=arm7tdmi-s -mthumb-interwork -I. -gdwarf-2 -DROM_RUN  -D__WinARM__ -I ./Common_WinARM/src/ -Os -Wall -Wcast-align -Wimplicit  -Wpointer-arith -Wswitch -Wredundant-decls -Wreturn-type -Wshadow -Wunused -Wa,-adhlns=Startup.lst  -I./SYSTEM/ -I././Common_WinARM/inc/ -Wcast-qual -MD -MP -MF .dep/main.elf.d Startup.o ./Common_WinARM/src/swi_handler.o  ./Common_WinARM/src/irq.o ./Common_WinARM/src/target.o ./Common_WinARM/src/timer.o main.o  system.o ./SYSTEM/syscalls.o  ./SYSTEM/rprintf.o  ./SYSTEM/serial.o MyLCD_Driver.o font.o gamescreen.o pacsprite.o MyAccelDriver.o Game.o IntersectionArray.o     --output main.elf -nostartfiles -Wl,-Map=main.map,--cref -lc  -lm -lc -lgcc     -Tmain_memory_block.ld 
c:/winarm/bin/../lib/gcc/arm-elf/4.1.1/../../../../arm-elf/bin/ld.exe: region RAM is full (main.elf section .bss)
c:/winarm/bin/../lib/gcc/arm-elf/4.1.1/../../../../arm-elf/bin/ld.exe: address 0x40008d00 of main.elf section .stack is not within region RAM
collect2: ld returned 1 exit status
make.exe: *** [main.elf] Error 1


The RAM space allocated by the linker had run out.  The student had planned on having two copies of the maze array, one that was the current maze, and one that stored the original state of the maze (so the user could do multiple levels.)  Having two copies of the array took 32kB or the 40 kB of static RAM available on the LPC2148.  With the program code and other memory needs, having multiple copies of the maze array is not feasible.  The Pac-Man game now only have one board.  There is certainly a way to store the backup array only non RAM memory, but due to the time constraint the student could not include such a feature.

Brainstorm

I have given myself two days to 'wrap up'  the project, then I need to focus on the final write up and presentation.  I'd like to have a working game by Sunday evening.... the following list is a brainstorm of ideas of how to accomplish this and a list of what I need to do to achieve this.



Pac-Man Movement
Probably should be done first
Control input done
Need intersection array
Need ability to tell when Pac-Man is in between two intersections.
Intersection behavior control
Between Intersection behavior control
Eat a pac-dot control
Eat a Power-Pellet control
Eat a Ghost Control
Eat a fruit control
Level end Control
Game End Control


Ghost movement...
Need to have 2 or 3 movement algos...
And a separate algo for power pellets (maybe)
and an algo to get them back to the ghost box.

Sunday, April 10, 2011

Game Design: Character Sprites

Accelerometer: Determining Direction

The accelerometer measures the amount of force by returning a voltage which is then converted to a digital value.  The digital value is a 10 bit number which means that the result can have 1024 different values ranging from.   2^10 = 1024.   1111111111b = 1023d. 

The accelerometer measures force in either a positive or negative direction with respect to an axis of direction.  Negative G's in a direction are will result in a value less than 511/512, positive G's will be greater than 511/512.  Tipping the device can result in positive or negative force with respect to a particular axis.   

The Pac-Man character can move in one of 4 directions.  To determine which of those directions to move the axis which is exhibiting the greatest displacement from center must first be found, then the direction of that displacement is then considered to come up with a direction that Pac-Man is to be directed to move to.

After the voltage is accurately measured in both directions the following code could be used to determine which direction the user wishes to move Pac-Man, or no direction at all if the device was held at a position close to rest.


//  enumerate directions
enum direction
{
    up = 0,
    right = 1, 
    down = 2,
    left = 3,
    none = 4
};

// The direction of force in relation to axis.
enum AxisDirection
{
    negative = 0,
    positive = 1
};

// A value which magnitude must be above to register movement.
const short kThreshHold = 5;

unsigned char AccelDirection( short xVal,  short yVal)
{
   short xMag = xVal  - 512;
   short yMag = yVal - 512; 
   unsigned char xDirection = positive;
   unsigned char yDirection = positive;
   if (xMag < 0)
   {
      xMag = xMag * -1;
      xDirection = negative;
   }
   if (yMag < 0)
   {
      yMag = yMag * -1;
      yDirection = negative;
   }
   if (xMag  - kThreshHold > 0 && xMag > yMag)
     if (xDirection == negative )
       return left;
     else
       return right;
  else if (yMag -kThreshHold > 0 && yMag > xMag)
     if (yDirection == negative )
       return down;
     else
       return up;
   else 
      return none;
}

Game Design: Character Storage.

The idea of most video games is you have a character that affects the environment around it.  Pac-Man runs through a maze gobbling up Pac-Dots and the occasional ghost.  The ghosts in turn can ruin Pac-Man's day if they touch him, while they are strong.  The purpose of this section is to identify data which would be valuable to be associated with Pac-Man or each of the four ghosts.

Position:  If Pac-Man and the Ghosts are confined to the maze, there must be information at hand of where to draw the sprite that represents the character.  Position helps determine if what direction the character can move, whether it has run into another character, pac-dot, power pellet or wall.  Position is probably the single most important attribute about the character.

State: Is a ghost dark blue and ready to be eaten?  Is Pac-Man in the throes of his over-dramatic death animation?  Does Pac-Man have his mouth open or shut?  All this information can be stored in one or more variables that tell the program about the characters state.

Sprites: If each character has quick access to information on how to draw it.  Drawing the screen can be simplified.

Color Palette: The sprites were designed so that the colors can be changed easily. On the ghosts that only thing that changes from character to character (in appearance) is the colors.  Storing the color palette for each character makes sense.

Direction: In Pac-Man the characters are always in motion.  Storing the position in which a character is moving seems natural.

There may be other data that makes sense to be added to the character record later on.
Below are examples of possible structures (the student would prefer to avoid classes and other C++ code if possible) to serve as character storage.

struct  PacMan
{
    point  mPosition;
    pstate  mState;
    int     mColors[12];
    unsigned char mSprites[X][64];
    usigned char mDirection;
};

struct Ghost
{
    point  mPosition;
    gstate  mState;
    int     mColors[12];
    unsigned char mSprites[Y][64];
    usigned char mDirection;
}


Pac-Man will most likely have more states and sprites than the ghosts.

Game Design: Event Loop Timer

Consider the pseudo code below.

while ( not done)
{
ReadInput();
MovementLogic();
DrawScreen();
for (counter = 0;  counter < LargeNumber; counter++)
{
NOP();
}
}

The code above, represents a simple event loop that could be used for a game.  But it has a weakness that it will always 'wait' the same amount of time between iterations of the loop no matter how long each job takes to complete.

Imagine that the time taken (TT) to complete ReadInput(), MovementLogic() and  DrawScreen() is much less then LargeNumber... (TT << LargeNumber).  Then the time taken for one complete iteration of the while loop is about LargeNumber.  Now imagine TT approaches LargeNumber,  the time needed to complete one iteration of the while loop would be 2 * Large Number.  If the designer of a game was trying to achieve a certain amount of frames per second, the game loop above could take up to twice the target time per frame, even though the operations needed to complete a draw cycle take less time than the target time. The code above will always wait a certain amount of time no matter how large TT is.

Perhaps a better way to code a loop is shown below

while ( not done)
{
// current time is set to the on chip timer
if (currentTime >= targetTime)
{
targetTime = currentTime + LargeNumber;
ReadInput();
MovementLogic();
DrawScreen();
}
else
{
NOP();
}
}

In the pseudo code above if TT approaches LargeNumber, the time taken for each screen draw is still around LargeNumber instead of 2*LargeNumber.   The LPC2148 has two 32 bit timers.  The student will use one to implement the type of code in the second example.

Phillips provides the files timer.h and timer.c to allow use of a timer.  The student will be including these files in the game.