Metroid Sidescroller Game

Overview

For our project, we made a sidescroller very loosely based on Metroid. This game uses the joystick to control the character and fire a shot at the oncoming metroids. If the metroids touch the player character, the character loses one point of health. At the loss of all points of health, the game ends. The joystick center button is used to fire the weapon, and cardinal directions are used for jumping, crouching, and movement left and right. One SD card is used for the image at the end, the other is used for the audio.


Components

  • mbed LPC1768

  • uLCD-144-G2 128 by 128 Smart Color LCD

  • Sparkfun 5-Way Tactile Switch Breakout

  • Sparkfun microSD Transflash Breakout

  • Sparkfun PCB mount Speaker (8 Ohm, .1W)

  • Either (2N3904 BJT) or (TI TPA2005D1 Class D Audio Amplifier)
    Audio Breakout

  • (Optional) 10KOhm Potentiometer for Volume Control

Wiring

MbedSD Card Reader
p5DI
p6DO
p7SCK
p8CS
GNDGND
VoutVCC
MbeduLCD
p9 TXRX
p10 RXTX
p11Reset
Vu5V
GNDGND
MbedJoystick
p12Up
p13Center
p14Left
p15Down
p16Right
GND-
NC+

If Using Transistor and Speaker

MbedBJTSpeaker
p18Base
GNDEmitter
Collector-
Vout+

If Using Audio Breakout and Potentiometer

MbedAudio BreakoutPotentiometerSpeaker
p18In+
GNDIn-, Pwr-,
VuPwr+
Out++
Out--
VOL pins1 pin/VOL pin



Program

Import programmetroid1


Main.cpp

main.cpp

#include <mbed.h>
#include "uLCD_4DGL.h"
#include "SDFileSystem.h"
#include "wave_player.h"
#include <rtos.h>
#include <graphics.h>
 
 
 
 
//define joystick
DigitalIn up(p12);
DigitalIn fire(p13);
DigitalIn left(p14);
DigitalIn down(p15);
DigitalIn right(p16);
 
DigitalOut led1(LED1);
DigitalOut led2(LED2);
DigitalOut led3(LED3);
DigitalOut led4(LED4);
 
 
//define uLCD
uLCD_4DGL ulcd(p9,p10,p11);
 
 
 
 
//define sd card reader
 SDFileSystem sd(p5, p6, p7, p8, "sd");
 
 
 
 
//define speaker
AnalogOut DACout(p18);
wave_player waver(&DACout);
 
 
 
 
//Mutex for uLCD
Mutex uLCD_mutex;
 
 
FILE *wave_file;
 
 
Samus samus;
Gunshot gunshot;
Metroid metroid;
 
 
 
 
bool GameOver=0;
 
 
bool dFormula(int ux, int uy, int mx, int my)
{
    double ans,dx,dy;
    dx = mx-ux;
    dy = my-uy;
    ans = sqrt((dx*dx)+(dy*dy));
    if(ans<=8) return 1;
    else return 0;
}
 
 
 
 
 
void sound(void const *args){
        while(true){
            wave_file=fopen("/sd/brinstar.wav", "r");
            led1 =1;
            waver.play(wave_file);
            led2 = 1;
            fclose(wave_file);
            Thread::wait(500);
        }
}
 
 
int main(){
    Thread soundthread(sound);
    Thread::wait(1000);
    int score = 0;
    up.mode(PullUp);
    fire.mode(PullUp);
    left.mode(PullUp);
    right.mode(PullUp);
    down.mode(PullUp);
    Thread::wait(25);
    ulcd.filled_rectangle(samus.xpos,samus.ypos,samus.xpos-4,samus.ypos-samus.currentheight,0xFFA500);
    ulcd.filled_circle(118, 8, 3, RED);
    ulcd.filled_circle(108, 8, 3, RED);
    ulcd.filled_circle(98, 8, 3, RED);
//     while(1);
    while(!GameOver){
        ulcd.locate(0,0);
        ulcd.printf("Score: %i", score);
        if(samus.isJumping){
            samus.prevypos = samus.ypos;
            samus.prevxpos = samus.xpos;
            if(samus.jump<5){
                samus.ypos -= 3;
                samus.jump += 1;
                ulcd.filled_rectangle(samus.prevxpos+1,samus.prevypos,samus.prevxpos-5,samus.prevypos-samus.height, BLACK);
                
            }
            else if(samus.jump<10){
                samus.ypos += 3;
                samus.jump += 1;
                ulcd.filled_rectangle(samus.prevxpos+1,samus.prevypos,samus.prevxpos-5,samus.prevypos-samus.height, BLACK);
            }
            else{
                samus.jump = 0;
                samus.isJumping = 0;
            }
        }
        ulcd.filled_rectangle(samus.xpos,samus.ypos,samus.xpos-4,samus.ypos-samus.currentheight,0xFFA500);
        
        if((up==0) && (!samus.crouch))
            samus.isJumping = 1;
        if(down==0 && (!samus.isJumping)){
            samus.crouch = !samus.crouch;
            if (samus.crouch==1){
            samus.currentheight=samus.crouchheight;
            ulcd.filled_rectangle(samus.xpos,samus.ypos,samus.xpos-4,samus.ypos-samus.height, BLACK);
            ulcd.filled_rectangle(samus.xpos,samus.ypos,samus.xpos-4,samus.ypos-samus.currentheight,0xFFA500);
            }
            else{
                samus.currentheight=samus.height;
           }
        }
        if(right==0){
            samus.prevxpos=samus.xpos;
            samus.xpos=samus.xpos+1;
            ulcd.filled_rectangle(samus.prevxpos, samus.prevypos, samus.prevxpos-4, samus.prevypos-samus.currentheight, BLACK);
            ulcd.filled_rectangle(samus.xpos,samus.ypos,samus.xpos-4,samus.ypos-samus.currentheight,0xFFA500);
            }
 
 
        if(left==0){
            samus.prevxpos=samus.xpos;
            samus.xpos=samus.xpos-1;
            ulcd.filled_rectangle(samus.prevxpos, samus.prevypos, samus.prevxpos-4, samus.prevypos-samus.currentheight, BLACK);
            ulcd.filled_rectangle(samus.xpos,samus.ypos,samus.xpos-4,samus.ypos-samus.currentheight,0xFFA500);
            }
 
 
 
 
        if((fire==0)&&(!gunshot.isOnScreen)){
            gunshot.isOnScreen = 1;
            gunshot.xpos=samus.xpos;
            gunshot.ypos=samus.ypos-(samus.currentheight*.5);
            gunshot.prevxpos=gunshot.xpos;
            gunshot.prevypos=gunshot.ypos;
}
 
 
 
 
        for(int j=0; j<3;j++){
            if((rand()%30 == 1)&&(!metroid.isAlive[j])){
                metroid.isAlive[j] = 1;
                metroid.xpos[j]=0;
                metroid.ypos[j]=(123-(rand()%15));
                ulcd.filled_circle(metroid.xpos[j], metroid.ypos[j], metroid.radius, WHITE);
            }
        }
 
 
 
 
        if (gunshot.xpos<=0){
            gunshot.isOnScreen=0;
            ulcd.filled_circle(gunshot.xpos, gunshot.ypos, gunshot.radius, BLACK);
        }
        if (gunshot.isOnScreen){
            ulcd.filled_circle(gunshot.xpos, gunshot.ypos, gunshot.radius, BLACK);
            gunshot.Move();
            ulcd.filled_circle(gunshot.xpos, gunshot.ypos, gunshot.radius, BLUE);
            }
 
 
 
        for(int j =0; j<3; j++){
            if ((dFormula(gunshot.xpos,gunshot.ypos,metroid.xpos[j],metroid.ypos[j])) && (metroid.isAlive[j]) && (gunshot.isOnScreen)){
                metroid.isAlive[j]=0;
                gunshot.isOnScreen=0;
                score++;
                ulcd.filled_circle(gunshot.xpos, gunshot.ypos, gunshot.radius, BLACK);
                ulcd.filled_circle(metroid.xpos[j], metroid.ypos[j], metroid.radius, BLACK);
                }
        }
 
 
 
 
        for(int j =0; j<3; j++){
            if (metroid.isAlive[j]){
                ulcd.filled_circle(metroid.xpos[j],metroid.ypos[j],metroid.radius,BLACK);
                metroid.Move(j);
                ulcd.filled_circle(metroid.xpos[j],metroid.ypos[j],metroid.radius,WHITE);
            }
        }
 
        for(int j =0; j<3; j++){
            if ((metroid.isAlive[j]) && (metroid.xpos[j]>=128)){
                metroid.isAlive[j] = 0;
                ulcd.filled_circle(metroid.xpos[j],metroid.ypos[j],metroid.radius,BLACK);
            }
        }
 
 
 
        for(int j =0; j<3; j++){
        if ((dFormula(samus.xpos-2,samus.ypos-.5*samus.currentheight,metroid.xpos[j],metroid.ypos[j])) && metroid.isAlive[j]){
            metroid.isAlive[j] = 0;
            ulcd.filled_circle(metroid.xpos[j],metroid.ypos[j],metroid.radius,BLACK);
            samus.health=samus.health-1;}
        }
        if (samus.health==2)
            ulcd.filled_circle(118, 8, 3, BLACK);
        else if (samus.health==1)
            ulcd.filled_circle(108, 8, 3, BLACK);
        if(samus.health==0){
            GameOver=1;
            soundthread.terminate();
        }
}
DACout = 0.0;
Thread::wait(50);
ulcd.cls();
//ulcd.media_init();
//ulcd.set_sector_address(0x0000, 0x0000);
//ulcd.display_image(0,0);
ulcd.printf("Game Over");
Thread::wait(3000);
ulcd.cls();
 
FILE *fp = fopen("/sd/highscore.txt", "rw");  // open the file in 'read' mode
char c[1];
//string sc;
fgets(c,1,fp);                         // get a character/byte from the file
 
if(score > atoi(c)){
    ulcd.printf("You Beat the High Score\nYour Score: %i",score);
    sprintf(c,"%d",score);
    fprintf(fp,c);}
else
    ulcd.printf("You Did Not Beat the High Score\nHigh Score: %c",c);
fclose(fp); 
}


Please log in to post comments.