Asteroids

Advice on general approaches or feasibility and discussions about game design

Re: Asteroids

Postby rodot » Sat Apr 26, 2014 10:05 am

Another idea would be to make a game *based* on asteroid but with different sprites a a few addition.

For example we could draw nice asteroid bitmaps with black/gray/white, and shape them as approximate circles to simplify the collision detection. I would look better and be less complicated than the vector approach... but it will be different from the original, I agree.
User avatar
rodot
Site Admin
 
Posts: 1290
Joined: Mon Nov 19, 2012 11:54 pm
Location: France

Re: Asteroids

Postby yodasvideoarcade » Sun Apr 27, 2014 1:26 pm

@ripper121:

Nice work! Make sure the bullets are just one pixel. Even in the original vector-screen, they were just a dot, i.e. the smallest possible size. And also no rapid-fire. For 4 bullets, you need to press the button 4 times, because it's neccesary to shoot very accurately.

I guess a port that is as close to the original as possible would be most interesting. Later of course we can have another version with all kinds of different features. But the original game is most fun to play - they really dedicated a lot of time for testing and making it perfect back in the 80'. Ops, sorry, actually 70'. It was released in 1979.
User avatar
yodasvideoarcade
 
Posts: 102
Joined: Sat Apr 19, 2014 10:48 am
Location: Frankfurt/Germany

Re: Asteroids

Postby ripper121 » Wed Apr 30, 2014 10:37 am

The Mid Asteroid have a movement i dont know at the moment how i can fix it.
But so far this is the code at the moment.
Code: Select all
#include <Adafruit_GFX.h>
#include <Adafruit_PCD8544.h>
Adafruit_PCD8544 display = Adafruit_PCD8544(8, 9, 10, 12, 11);
int IBridge_Column_Pin0 = 7;
int IBridge_Column_Pin1 = 6;
int IBridge_Column_Pin2 = 5;
int IBridge_Column_Pin3 = 4;
int IBridge_Row_Pin0 = 3;
int IBridge_Row_Pin1 = 2;
int IBridge_Row_Pin2 = 18;
int IBridge_Row_Pin3 = 19;


void setup() {
  display.begin();
  display.setContrast(60);

  randomSeed(analogRead(0));

  pinMode(IBridge_Column_Pin0, OUTPUT);
  pinMode(IBridge_Column_Pin1, OUTPUT);
  pinMode(IBridge_Column_Pin2, OUTPUT);
  pinMode(IBridge_Column_Pin3, OUTPUT);
  pinMode(IBridge_Row_Pin0, INPUT);
  pinMode(IBridge_Row_Pin1, INPUT);
  pinMode(IBridge_Row_Pin2, INPUT);
  pinMode(IBridge_Row_Pin3, INPUT);

  display.clearDisplay();
}

//Ship Sprite
static const unsigned char PROGMEM ShipN[] = {
  B01000000,
  B01000000,
  B10100000,
  B11100000
};
static unsigned char PROGMEM ShipNE[] = {
  B00010000,
  B01100000,
  B10100000,
  B01000000
};
static unsigned char PROGMEM ShipE[] = {
  B11000000,
  B10110000,
  B11000000,
  B00000000
};
static unsigned char PROGMEM ShipSE[] = {
  B01000000,
  B10100000,
  B01100000,
  B00010000
};
static unsigned char PROGMEM ShipS[] = {
  B11100000,
  B10100000,
  B01000000,
  B01000000
};
static unsigned char PROGMEM ShipSW[] = {
  B00100000,
  B01010000,
  B01100000,
  B10000000
};
static unsigned char PROGMEM ShipW[] = {
  B00110000,
  B11010000,
  B00110000,
  B00000000
};
static unsigned char PROGMEM ShipNW[] = {
  B10000000,
  B01100000,
  B01010000,
  B00100000
};

static unsigned char PROGMEM SBullet[] = {
  B01000000,
  B11100000,
  B01000000,
  B00000000
};

static unsigned char PROGMEM BAsteroid[] = {
  B01101100,
  B10010010,
  B01000010,
  B00100001,
  B01000001,
  B10000001,
  B01000010,
  B00111100
};
static unsigned char PROGMEM MAsteroid[] = {
  B01011000,
  B10100100,
  B10001000,
  B10000100,
  B01001000,
  B00110000
};
static unsigned char PROGMEM SAsteroid[] = {
  B01011000,
  B10100100,
  B10001000,
  B10000100,
  B01001000,
  B00110000
};

#define lcdheight 48
#define lcdwidth 84
#define maxBullets 4
#define maxBigAsteroid 2
#define maxMidAsteroid 5
#define maxSmallAsteroid 8
#define DetectionOffset 2
typedef struct
{
  int x;
  int y;
  int w;
  int h;
  int dir;
  int Speed;
  boolean exist;
}  ship;

typedef struct
{
  int x;
  int y;
  int w;
  int h;
  int Speed;
  int TTL;
  int dir;
  boolean exist;
}  bullet;

typedef struct
{
  int x;
  int y;
  int vx;
  int vy;
  int w;
  int h;
  int Speed;
  int Size;
  int dir;
  boolean exist;
}  asteroid;

byte gamespeed = 100;


void loop() {
  ship Ship;
  Ship.y = lcdheight / 2 - Ship.h;
  Ship.x = lcdwidth / 2 - Ship.w;
  Ship.dir = 0;
  Ship.w = 4;
  Ship.h = 4;
  Ship.Speed = 2;
  Ship.exist = true;

  bullet Bullet[maxBullets];
  for (byte i = 0; i < maxBullets; i++) {
    Bullet[i].x = 0;
    Bullet[i].y = 0;
    Bullet[i].w = 3;
    Bullet[i].h = 3;
    Bullet[i].Speed = 2;
    Bullet[i].TTL = 0;
    Bullet[i].dir = 0;
    Bullet[i].exist = false;
  }

  asteroid BigAsteroid[maxBigAsteroid];
  for (byte i = 0; i < maxBigAsteroid; i++) {
    BigAsteroid[i].w = 8;
    BigAsteroid[i].h = 8;
    int y = random(lcdheight) - BigAsteroid[i].h;
    int x = random(lcdwidth) - BigAsteroid[i].w;
    if (!CollisionDetection(x, y, BigAsteroid[i].w, BigAsteroid[i].h, Ship.x, Ship.y, Ship.w, Ship.h)) {
      BigAsteroid[i].x = x;
      BigAsteroid[i].y = y;
    }
    else {
      BigAsteroid[i].x = x + Ship.w * 4;
      BigAsteroid[i].y = y + Ship.h * 4;
    }

    BigAsteroid[i].Speed = 1;
    if (random(2) == 0)
      BigAsteroid[i].vx = -BigAsteroid[i].Speed;
    else
      BigAsteroid[i].vx = BigAsteroid[i].Speed;
    if (random(2) == 0)
      BigAsteroid[i].vy = -BigAsteroid[i].Speed;
    else
      BigAsteroid[i].vy = BigAsteroid[i].Speed;

    BigAsteroid[i].Size = 0;
    BigAsteroid[i].dir = random(8);
    BigAsteroid[i].exist = true;
  }

  asteroid MidAsteroid[maxMidAsteroid];
  for (byte i = 0; i < maxMidAsteroid; i++) {
    MidAsteroid[i].w = 6;
    MidAsteroid[i].h = 6;
    MidAsteroid[i].x = lcdheight / 2;
    MidAsteroid[i].y = lcdwidth / 2;
    MidAsteroid[i].Speed = 1;
    MidAsteroid[i].vx = MidAsteroid[i].Speed;
    MidAsteroid[i].vy = MidAsteroid[i].Speed;
    MidAsteroid[i].Size = 1;
    MidAsteroid[i].dir = 0;
    MidAsteroid[i].exist = false;
  }

  display.clearDisplay();
  display.setTextSize(1);
  display.setTextColor(BLACK);
  display.setCursor(0, 0);
  display.println("Asteroid v.0.1");
  display.println(".by Ripper121");
  display.display();
  delay(1000);

  unsigned char key = 0;
  while (1) {
    display.clearDisplay();
    //Get input & draw Player
    key = IBridge_Read_Key();
    //Ship Dir
    if (key == 7)
      if (Ship.dir < 7)
        Ship.dir++;
      else
        Ship.dir = 0;
    if (key == 15)
      if (Ship.dir > 0)
        Ship.dir--;
      else
        Ship.dir = 7;
    //Ship Move
    if (key == 12) {
      switch (Ship.dir) {
        case 0:
          Ship.y -= Ship.Speed;
          break;
        case 1:
          Ship.y -= Ship.Speed;
          Ship.x += Ship.Speed;
          break;
        case 2:
          Ship.x += Ship.Speed;
          break;
        case 3:
          Ship.y += Ship.Speed;
          Ship.x += Ship.Speed;
          break;
        case 4:
          Ship.y += Ship.Speed;
          break;
        case 5:
          Ship.y += Ship.Speed;
          Ship.x -= Ship.Speed;
          break;
        case 6:
          Ship.x -= Ship.Speed;
          break;
        case 7:
          Ship.y -= Ship.Speed;
          Ship.x -= Ship.Speed;
          break;
      }
    }
    if (key == 10) {
      switch (Ship.dir) {
        case 0:
          Ship.y += Ship.Speed;
          break;
        case 1:
          Ship.y += Ship.Speed;
          Ship.x -= Ship.Speed;
          break;
        case 2:
          Ship.x -= Ship.Speed;
          break;
        case 3:
          Ship.y -= Ship.Speed;
          Ship.x -= Ship.Speed;
          break;
        case 4:
          Ship.y -= Ship.Speed;
          break;
        case 5:
          Ship.y -= Ship.Speed;
          Ship.x += Ship.Speed;
          break;
        case 6:
          Ship.x += Ship.Speed;
          break;
        case 7:
          Ship.y += Ship.Speed;
          Ship.x += Ship.Speed;
          break;
      }
    }

    if (Ship.x < 0)
      Ship.x = 0;
    if (Ship.y < 0)
      Ship.y = 0;
    if (Ship.x > lcdwidth - Ship.w)
      Ship.x = lcdwidth - Ship.w;
    if (Ship.y > lcdheight - Ship.h)
      Ship.y = lcdheight - Ship.h;

    if (Ship.exist) {
      switch (Ship.dir) {
        case 0: display.drawBitmap(Ship.x, Ship.y, ShipN, Ship.w, Ship.h, BLACK);
          break;
        case 1: display.drawBitmap(Ship.x, Ship.y, ShipNE, Ship.w, Ship.h, BLACK);
          break;
        case 2: display.drawBitmap(Ship.x, Ship.y, ShipE, Ship.w, Ship.h, BLACK);
          break;
        case 3: display.drawBitmap(Ship.x, Ship.y, ShipSE, Ship.w, Ship.h, BLACK);
          break;
        case 4: display.drawBitmap(Ship.x, Ship.y, ShipS, Ship.w, Ship.h, BLACK);
          break;
        case 5: display.drawBitmap(Ship.x, Ship.y, ShipSW, Ship.w, Ship.h, BLACK);
          break;
        case 6: display.drawBitmap(Ship.x, Ship.y, ShipW, Ship.w, Ship.h, BLACK);
          break;
        case 7: display.drawBitmap(Ship.x, Ship.y, ShipNW, Ship.w, Ship.h, BLACK);
          break;
      }
    }


    //Bullets Create
    key = IBridge_Read_Key();
    if (key == 5) {
      for (byte i = 0; i < maxBullets; i++) {
        if (!Bullet[i].exist)
        {
          Bullet[i].dir = Ship.dir;
          Bullet[i].x = Ship.x;
          Bullet[i].y = Ship.y;
          Bullet[i].exist = true;
          break;
        }
      }
    }
    for (byte i = 0; i < maxBullets; i++) {
      if (Bullet[i].exist)
      {
        switch (Bullet[i].dir) {
          case 0:
            Bullet[i].y -= Bullet[i].Speed;
            break;
          case 1:
            Bullet[i].y -= Bullet[i].Speed;
            Bullet[i].x += Bullet[i].Speed;
            break;
          case 2:
            Bullet[i].x += Bullet[i].Speed;
            break;
          case 3:
            Bullet[i].y += Bullet[i].Speed;
            Bullet[i].x += Bullet[i].Speed;
            break;
          case 4:
            Bullet[i].y += Bullet[i].Speed;
            break;
          case 5:
            Bullet[i].y += Bullet[i].Speed;
            Bullet[i].x -= Bullet[i].Speed;
            break;
          case 6:
            Bullet[i].x -= Bullet[i].Speed;
            break;
          case 7:
            Bullet[i].y -= Bullet[i].Speed;
            Bullet[i].x -= Bullet[i].Speed;
            break;
        }
        //Destroy Bullet
        if (Bullet[i].x < 0 || Bullet[i].y < 0 || Bullet[i].x > lcdwidth - Bullet[i].w || Bullet[i].y > lcdheight - Bullet[i].h)
          Bullet[i].exist = false;
        display.drawBitmap(Bullet[i].x, Bullet[i].y, SBullet, Bullet[i].w, Bullet[i].h, BLACK);
      }
    }
   
    for (byte i = 0; i < maxBigAsteroid; i++) {
      if (CollisionDetection(BigAsteroid[i].x + DetectionOffset, BigAsteroid[i].y + DetectionOffset, BigAsteroid[i].w - DetectionOffset, BigAsteroid[i].h - DetectionOffset, Ship.x, Ship.y, Ship.w, Ship.h) && BigAsteroid[i].exist) {
        Ship.exist = false;
      }
      for (byte j = 0; j < maxBullets; j++) {
        if (CollisionDetection(BigAsteroid[i].x + DetectionOffset, BigAsteroid[i].y + DetectionOffset, BigAsteroid[i].w - DetectionOffset, BigAsteroid[i].h - DetectionOffset, Bullet[j].x, Bullet[j].y, Bullet[j].w, Bullet[j].h) && BigAsteroid[i].exist && Bullet[j].exist){
          byte dir=2;
          for (byte j = 0; j < 2; j++) {
            for (byte i = 0; i < maxMidAsteroid; i++) {             
              if (!MidAsteroid[i].exist) {
                MidAsteroid[i].x = BigAsteroid[i].x-BigAsteroid[i].w;
                MidAsteroid[i].y = BigAsteroid[i].y-BigAsteroid[i].h;
                MidAsteroid[i].dir = dir;
                dir+=4;               
                MidAsteroid[i].exist = true;
                break;
              }
            }
          }
          BigAsteroid[i].exist = false;
          Bullet[j].exist = false;
        }
      }
    }
   
    //Asteroids Move
    for (byte i = 0; i < maxBigAsteroid; i++) {
      if (BigAsteroid[i].exist)
      {
        BigAsteroid[i].y += BigAsteroid[i].vy;
        BigAsteroid[i].x += BigAsteroid[i].vx;
        //Destroy Bullet
        if (BigAsteroid[i].x <= 0) {
          BigAsteroid[i].vx = +BigAsteroid[i].Speed;
        }
        if (BigAsteroid[i].y <= 0) {
          BigAsteroid[i].vy = +BigAsteroid[i].Speed;
        }
        if (BigAsteroid[i].x >= lcdwidth - BigAsteroid[i].w) {
          BigAsteroid[i].vx = -BigAsteroid[i].Speed;
        }
        if (BigAsteroid[i].y >= lcdheight - BigAsteroid[i].h) {
          BigAsteroid[i].vy = -BigAsteroid[i].Speed;
        }
        display.drawBitmap(BigAsteroid[i].x, BigAsteroid[i].y, BAsteroid, BigAsteroid[i].w, BigAsteroid[i].h, BLACK);
        //Bullets Move
      }
    }
   
    for (byte i = 0; i < maxMidAsteroid; i++) {
      if (MidAsteroid[i].exist)
      {
        MidAsteroid[i].y += MidAsteroid[i].vy;
        MidAsteroid[i].x += MidAsteroid[i].vx;
        //Destroy Bullet
        if (MidAsteroid[i].x <= 0) {
          MidAsteroid[i].vx = +MidAsteroid[i].Speed;
        }
        if (MidAsteroid[i].y <= 0) {
          MidAsteroid[i].vy = +MidAsteroid[i].Speed;
        }
        if (MidAsteroid[i].x >= lcdwidth - MidAsteroid[i].w) {
          MidAsteroid[i].vx = -MidAsteroid[i].Speed;
        }
        if (MidAsteroid[i].y >= lcdheight - MidAsteroid[i].h) {
          MidAsteroid[i].vy = -MidAsteroid[i].Speed;
        }
        display.drawBitmap(MidAsteroid[i].x, MidAsteroid[i].y, MAsteroid, MidAsteroid[i].w, MidAsteroid[i].h, BLACK);
        //Bullets Move
      }
    }



    //Draw to Screen
    display.display();
    delay(gamespeed);

    if (!Ship.exist)
      break;
  }
  display.setTextSize(1);
  display.setTextColor(BLACK);
  display.setCursor(0, 0);
  display.println("Game Over");
  display.display();
  delay(3000);
}

bool CollisionDetection(byte ax, byte ay, byte aw, byte ah, byte bx, byte by, byte bw, byte bh) {
  return (abs(ax - bx) * 2 < (aw + bw)) &&
         (abs(ay - by) * 2 < (ah + bh));
}

unsigned char IBridge_Read_Key()
{
  //unsigned char i = 10;

  //Column 0 scan


  digitalWrite(IBridge_Column_Pin1, LOW);
  digitalWrite(IBridge_Column_Pin2, LOW);
  digitalWrite(IBridge_Column_Pin3, LOW);
  digitalWrite(IBridge_Column_Pin0, HIGH);

  //i=10;
  //while(i--);
  delay(1);

  if ((digitalRead(IBridge_Row_Pin0)) &&
      !(digitalRead(IBridge_Row_Pin1))  &&
      !(digitalRead(IBridge_Row_Pin2))  &&
      !(digitalRead(IBridge_Row_Pin3)))
    return (1);

  if (!(digitalRead(IBridge_Row_Pin0)) &&
      (digitalRead(IBridge_Row_Pin1))  &&
      !(digitalRead(IBridge_Row_Pin2))  &&
      !(digitalRead(IBridge_Row_Pin3)))
    return (2);

  if (!(digitalRead(IBridge_Row_Pin0)) &&
      !(digitalRead(IBridge_Row_Pin1))  &&
      (digitalRead(IBridge_Row_Pin2))  &&
      !(digitalRead(IBridge_Row_Pin3)))
    return (3);

  if (!(digitalRead(IBridge_Row_Pin0)) &&
      !(digitalRead(IBridge_Row_Pin1))  &&
      !(digitalRead(IBridge_Row_Pin2))  &&
      (digitalRead(IBridge_Row_Pin3)))
    return (4);

  //Column 2 Scan

  digitalWrite(IBridge_Column_Pin0, LOW);
  digitalWrite(IBridge_Column_Pin1, HIGH);
  digitalWrite(IBridge_Column_Pin2, LOW);
  digitalWrite(IBridge_Column_Pin3, LOW);

  //i=10;
  //while(i--);
  delay(1);

  if ((digitalRead(IBridge_Row_Pin0)) &&
      !(digitalRead(IBridge_Row_Pin1))  &&
      !(digitalRead(IBridge_Row_Pin2))  &&
      !(digitalRead(IBridge_Row_Pin3)))
    return (5);

  if (!(digitalRead(IBridge_Row_Pin0)) &&
      (digitalRead(IBridge_Row_Pin1))  &&
      !(digitalRead(IBridge_Row_Pin2))  &&
      !(digitalRead(IBridge_Row_Pin3)))
    return (6);

  if (!(digitalRead(IBridge_Row_Pin0)) &&
      !(digitalRead(IBridge_Row_Pin1))  &&
      (digitalRead(IBridge_Row_Pin2))  &&
      !(digitalRead(IBridge_Row_Pin3)))
    return (7);

  if (!(digitalRead(IBridge_Row_Pin0)) &&
      !(digitalRead(IBridge_Row_Pin1))  &&
      !(digitalRead(IBridge_Row_Pin2))  &&
      (digitalRead(IBridge_Row_Pin3)))
    return (8);

  //Column 3 Scan

  digitalWrite(IBridge_Column_Pin0, LOW);
  digitalWrite(IBridge_Column_Pin1, LOW);
  digitalWrite(IBridge_Column_Pin2, HIGH);
  digitalWrite(IBridge_Column_Pin3, LOW);

  //i=10;
  //while(i--);
  delay(1);

  if ((digitalRead(IBridge_Row_Pin0)) &&
      !(digitalRead(IBridge_Row_Pin1))  &&
      !(digitalRead(IBridge_Row_Pin2))  &&
      !(digitalRead(IBridge_Row_Pin3)))
    return (9);

  if (!(digitalRead(IBridge_Row_Pin0)) &&
      (digitalRead(IBridge_Row_Pin1))  &&
      !(digitalRead(IBridge_Row_Pin2))  &&
      !(digitalRead(IBridge_Row_Pin3)))
    return (10);

  if (!(digitalRead(IBridge_Row_Pin0)) &&
      !(digitalRead(IBridge_Row_Pin1))  &&
      (digitalRead(IBridge_Row_Pin2))  &&
      !(digitalRead(IBridge_Row_Pin3)))
    return (11);

  if (!(digitalRead(IBridge_Row_Pin0)) &&
      !(digitalRead(IBridge_Row_Pin1))  &&
      !(digitalRead(IBridge_Row_Pin2))  &&
      (digitalRead(IBridge_Row_Pin3)))
    return (12);

  //Column 4 Scan

  digitalWrite(IBridge_Column_Pin0, LOW);
  digitalWrite(IBridge_Column_Pin1, LOW);
  digitalWrite(IBridge_Column_Pin2, LOW);
  digitalWrite(IBridge_Column_Pin3, HIGH);


  delay(1);

  if ((digitalRead(IBridge_Row_Pin0)) &&
      !(digitalRead(IBridge_Row_Pin1))  &&
      !(digitalRead(IBridge_Row_Pin2))  &&
      !(digitalRead(IBridge_Row_Pin3)))
    return (13);

  if (!(digitalRead(IBridge_Row_Pin0)) &&
      (digitalRead(IBridge_Row_Pin1))  &&
      !(digitalRead(IBridge_Row_Pin2))  &&
      !(digitalRead(IBridge_Row_Pin3)))
    return (14);

  if (!(digitalRead(IBridge_Row_Pin0)) &&
      !(digitalRead(IBridge_Row_Pin1))  &&
      (digitalRead(IBridge_Row_Pin2))  &&
      !(digitalRead(IBridge_Row_Pin3)))
    return (15);

  if (!(digitalRead(IBridge_Row_Pin0)) &&
      !(digitalRead(IBridge_Row_Pin1))  &&
      !(digitalRead(IBridge_Row_Pin2))  &&
      (digitalRead(IBridge_Row_Pin3)))
    return (16);

  return (0);

}



User avatar
ripper121
 
Posts: 224
Joined: Fri Apr 04, 2014 2:02 pm
Location: Germany

Re: Asteroids

Postby yodasvideoarcade » Thu May 01, 2014 10:47 pm

By "movement" you mean the fact that the appear at the wrong position?

- When an asteroid is shot and splits into two smaller, they appear at the same position the larger one has been in the moment of the hit.

- The asteroids don't bounce off the walls but pass through and appear at the opposite side of the screen again. Same with the shots, spaceship and everything else.
User avatar
yodasvideoarcade
 
Posts: 102
Joined: Sat Apr 19, 2014 10:48 am
Location: Frankfurt/Germany

Re: Asteroids

Postby yodasvideoarcade » Thu May 01, 2014 10:58 pm

The problem could be that you have a for-next loop with "i" and one with "j" inside the already existing loops that also use "i" and "j", and you refer to the BigAsteroid position with index "i" (which should be the outer loop's "i", but maybe it is taken from the inner loop's value. Maybe better to use "k" and "l" for the two inner loops?
User avatar
yodasvideoarcade
 
Posts: 102
Joined: Sat Apr 19, 2014 10:48 am
Location: Frankfurt/Germany

Previous

Return to Project Guidance & Game development

Who is online

Users browsing this forum: No registered users and 88 guests

cron