What is wrong with my view calculations as well as my collision detection? (a lot, probably)

I am working on a 3D game, just for fun, and I spent a while figuring out how I could look around. I finally created what I thought was my solution, but occasionally when the cam passes over two certain points, it freaks out and locks into this seizure thing and wont let you move the cam most of the time. I've been working with these view calculations for a while now because they work(most of the time), but it's starting to bother me. In the code, I made lines to show the axes as well as where the cam target is. When the cam target(blue line) passes over the red line, that is where the seizure occurs, although sometimes you have to move it back and forth for a bit to get it to happen. (I already tried this out on multiple computers. It is a problem in the code.)

The other problem: collision detection. In the game, there are platforms that are already built, and platforms that you make. This was also something I thought I had figured out till some small bug manifested itself. When you build platforms very close together where they overlap, building upwards(like a staircase), if you try to walk up the "stairs," you don't go up, but rather walk through the other stairs and fall off the first step. However, if you build downwards, once again very close together where they overlap, and then go up the stairs, then it works. >:(

If I did not clarify something well enough, let me know and I will try to further explain it. Here is the code. I have to put it in comments since it makes this too long.(note: I'm sorry if this is a lot :( I already trimmed it down a ton.) A platform preview can be formed by pressing shift. You can look around while pressing shift to choose where to built it. You build the platform by pressing "b" while shift is pressed.

Comments

  • edited April 2014
    import java.awt.Robot;
    PShape[] Brick = new PShape[7];
    PImage wall;
    Platform[] plat = new Platform[19];
    Robot robot;
    float[] specs = new float[50];
    float[] heights = new float[20];
    int platNum = 0;
    int ppN = 0;
    int platMax = 8;
    
    boolean keyw = false, keys = false, keyd = false, keya = false, keybar = false, tilde = false;
    boolean pause = false, mMenu = false, settings = false;
    boolean shift = false;
    
    float xx = 0, yy = 0, zz = 0, Y = 0;
    float xxx =1, yyy = 0, zzz = 1, camY = -400;//camY is the height of the camera or "person"
    float SET = 0;
    float feet = 400;
    float tx = 0, ty = 0;
    float lastDX = 0, lastDY = 0;
    boolean sketchFullScreen() {
      return true;
    }
    
    boolean Jumping = false;
    boolean surface = true;
    float gravCo = .5, gravInc = 0;//gravity coefficient and multiplier
    float gravYA = 0;//Final gravity value adding to Y
    float jumpY = 0, jumpingY = 0;//jump value added to Y, and jump value assigned in Jump()
    boolean FOUND = false;
    float add1, add2, sub1;
    float standard = 75;
    boolean setGround(float x1in, float x2in, float z1in, float z2in) {
      if (((tx>=x1in)&&(tx<=x2in))&&((ty>=z1in)&&(ty<=z2in))) {
        return true;
      }
      else {
        return false;
      }
    }
    boolean WithinVerticle(float y1in) {
      if (((Y+feet)>=(y1in))&&((Y+feet)<=y1in+standard)) {
        return true;
      }
      else {
        return false;
      }
    }
    
    void setup() {
      size(displayWidth, displayHeight, P3D);
      LOAD();
      noCursor();
      try {
        robot = new Robot();
      }
      catch(Throwable e) {
      }
      robot.mouseMove(width/2, height/2);
    }
    
  • edited April 2014
    void draw() {
      background(20, 50);
      pushMatrix();
      Y = camY + jumpY + gravYA + SET;  
      camera(tx, Y, ty, 
      zzz+tx, yyy+(height/2) + Y, xxx+ty, //xxx is in the z slot because lastDX is added to it, and in my mind, that is just simpler. :P
      0.0, 1.0, 0.0);
    
      MiscViewLines();
    
      for (int i=0;i<10;i++) {//builds the ten preset platforms
        plat[i].Build();
      }
    
      if (shift) {
        plat[18] = new Platform(zzz+tx, yyy+(height/2)+Y, xxx+ty, 5, 1); 
        plat[18].Build();
      }//when shift is pressed this is seen as a guideline for the plat building
    
    
      if ((platNum>ppN)&&(platNum<=platMax)) {//if a new plat is built, define its specs
        plat[10+(platNum-1)] = new Platform(specs[22+((platNum-1)*2)], heights[11+(platNum-1)], specs[23+((platNum-1)*2)], 5, 1);
      }
    
    
      if (platNum>platMax) {
        ShowBuiltPlats(platMax);
      }
      else {
        ShowBuiltPlats(platNum);
      }
    
      ppN = platNum;  
    
      translate(specs[20], heights[10], specs[21]);
      shape(Brick[6]);
      translate(-specs[20], -heights[10], -specs[21]);
      popMatrix();
    
      GUI();
      if (!tilde) {
        getGravity();
        MoveHPosition();
        MoveView();    
        robot.mouseMove(width/2, height/2);
      }
      noStroke();
    }
    
    
    void ShowBuiltPlats(int nop) {
      for (int i=0;i<(nop);i++) {
        plat[i+10].Build();
      }
    }
    
    
    void keyPressed() {
      if (key == 'w') keyw = true; 
      if (key == 's') keys = true; 
      if (key == 'd') keyd = true; 
      if (key == 'a') keya = true; 
      if (key == ' ') keybar = true;
      if (key == '`') {
        if (tilde) {
          robot.mouseMove(width/2, height/2);
        }
      }
      if (keyCode == SHIFT) {
        shift=true;
      }
    } 
    void keyReleased() {
      if (key == 'w') keyw = false; 
      if (key == 's') keys = false; 
      if (key == 'd') keyd = false; 
      if (key == 'a') keya = false; 
      if (key == ' ') keybar = false;
      if (key == '`') {
        if (!tilde) {
          tilde=true;
        }
        else if (tilde) {
          tilde=false;
        }
      }
      if (keyCode == SHIFT) {
        shift=false;
      }
      if (key == 'B') {//notice that this not not just b, but SHIFT+b
        if (platNum<platMax) {
          specs[22+(platNum*2)] = zzz+tx;   
          heights[11+platNum] = yyy+(height/2)+Y;   
          specs[23+(platNum*2)] = xxx+ty;
        }
        platNum += 1;
      }
    }
    
    //--------------------------------CONTROLS---------------------------------
    void MoveHPosition() {  
      //---MOVEMENT CONTROLS------WASD--------          
      if (keyd) {//move right
        tx = tx - (xxx*.01);  
        ty = ty + (zzz*.01);
      }
      if (keya) {//move left
        tx = tx + (xxx*.01);  
        ty = ty - (zzz*.01);
      }
      if (keys) {//move back
        tx = tx - (zzz*.01);  
        ty = ty - (xxx*.01);
      }
      if (keyw) {//move forward
        tx = tx + (zzz*.01);  
        ty = ty + (xxx*.01);
      }
      if (keybar) {//jump
        Jump(-16);
      }
    }
    void MoveView() {
      //---VIEW CALCULATIONS-----------------------  
      lastDX = ((width/2)-mouseX)*1.4;//change the 1.4 to adjust mouse sensitivity
      lastDY = ((height/2)-mouseY)*1.4;
      yyy = yyy - lastDY;//make this + or - to invert view up and down
      if (zzz < 0) {        //VIEW CALCULATIONS FOR QUADS 3 & 4---------------
        xxx = xxx + lastDX;//make this - and the other + to invert view left and right
        if (xxx < 0) { 
          zzz = -width - xxx;
        }
        else { 
          zzz = -width + xxx;
        }
      }
      else if (zzz >= 0) {      //VIEW CALCULATIONS FOR QUADS 1 & 2--------------
        xxx = xxx - lastDX;
        if (xxx < 0) { 
          zzz = width + xxx;
        }
        else { 
          zzz = width - xxx;
        }
      }
    }
    
    void resetVPos(float res) {
      SET = res;
      jumpY = 0;
      gravYA = 0;
      gravInc = 0;
      jumpingY = 0;
      surface = true;
    }
    
  • edited April 2014
    void getGravity() {
      if (!surface) {
        gravYA  += (gravCo*gravInc);//later, add a timer to help calculate this if there are     timers
        gravInc += 1;//later make terminal velocity
        if (Jumping) {
          jumpY += jumpingY;
        }
      }
      else {
        gravInc = 0;
        jumpingY = 0;
        Jumping = false;
      }
      FOUND=false;
      for (int i=0; i<heights.length; i++) {
        if (!FOUND) {
          if (i<=9) {
            add1=500;  
            add2=400;  
            sub1=100;
          }
      else if (i==10) {
        add1=7000; 
        add2=6900; 
        sub1=100;
          }
          else if (i>10) {
            add1=500;  
            add2=400;  
            sub1=100;
          }
          if (WithinVerticle(heights[i])) {
            if (setGround(specs[(i*2)], specs[(i*2)]+add1, specs[(i*2)+1]-sub1, specs[(i*2)+1]+add2)) {
              FOUND=true;
              if (!surface) {
                resetVPos(heights[i]);
              }
            }
            else {
              surface=false;
            }
          }
        }
      }
    }
    
    void Jump(float jumpAdd) {
      if (!Jumping) {
        if (surface) {
          jumpingY = jumpAdd;
          Jumping = true;
          SET -= 1;
          surface = false;
        }
      }
    }
    
    void GUI() {
      hint(DISABLE_DEPTH_TEST);
      stroke(255);
      text("Position and View coordinates:", 100, 90);
      text("MouseX:"+mouseX+"    MouseY:"+mouseY+" ", 100, 102);
      text("ZZZ:"+zzz+"     XXX:"+xxx+" ", 100, 114);
      text("Y:"+Y+"     Y+Feet:"+(Y+feet)+"   "+"YYY:"+(yyy+(height/2)), 100, 126);   
      text("TX:"+tx+"    TY:"+ty+" ", 100, 138);
      text("SET:"+SET+" ", 100, 150);
      text("Gravity:", 100, 190);
      text("Surface:"+surface+"   Jumping:"+Jumping+" ", 100, 202);
      text("Gravity Increment:"+gravInc+"    Gravity Coefficient:"+gravCo+" ", 100, 214);
      text("JumpY:"+jumpY+"    gravYA:"+gravYA+"    jumpingY:"+jumpingY+" ", 100, 226);
      hint(ENABLE_DEPTH_TEST);
    }
    
    void MiscViewLines() {//these are the lines that are drawn so you can see the problematic view issue
      stroke(255);
      line(  width+tx, Y+yyy+(height/2), 0+ty, -width+tx, Y+yyy+(height/2), 0+ty);
      stroke(255, 0, 0);
      line(      0+tx, Y+yyy+(height/2), width+ty, 0+tx, Y+yyy+(height/2), -width+ty);
      stroke(255);
      line(  width+tx, Y+yyy+(height/2), 0+ty, 0+tx, Y+yyy+(height/2), width+ty);
      line(      0+tx, Y+yyy+(height/2), width+ty, -width+tx, Y+yyy+(height/2), 0+ty);
      line( -width+tx, Y+yyy+(height/2), 0+ty, 0+tx, Y+yyy+(height/2), -width+ty);
      line(      0+tx, Y+yyy+(height/2), -width+ty, width+tx, Y+yyy+(height/2), 0+ty);
      stroke(0, 0, 255);
      line(    zzz+tx, 25+Y+yyy+(height/2), xxx+ty, zzz+tx, -25+Y+yyy+(height/2), xxx+ty); 
      stroke(0);
    } 
    
    class Platform {
      float bxpos, bypos, bzpos, bwidth, bheight;
      Platform(float cv1, float cv2, float cv3, float cv4, float cv5) {
        bxpos = cv1;
        bypos = cv2;
        bzpos = cv3;
        bwidth = cv4;
        bheight = cv5;
      }
      private void Build() {//this allows for platforms of different sizes
        translate(bxpos, bypos, bzpos); //move draw point to location
        for (int k = 0; k < bwidth; k += 1) {//Z position
          translate(0, 0, k*100);//layer movement
          for (int i = 0; i < bheight; i += 1) {//Y position
            for (int j = 0; j < bwidth; j += 1) { //X position
              if ((bwidth==1)&&(bheight==1)) {
                block(j*100, i*100);
              }
              else {
                if (k==0) {
                  if (i==0) {
                    if (j==0) {
                      btlcorner(j*100, i*100);
                    }
                    else if ((j>0)&&(j<bwidth-1)) {
                      btedge(j*100, i*100);
                    }
                    else if (j==bwidth-1) {
                      btrcorner(j*100, i*100);
                    }
                  }
                  else if ((i>0)&&(i<bheight-1)) { 
                    if (j==0) {
                      bledge(j*100, i*100);
                    }
                    else if ((j>0)&&(j<bwidth-1)) {
                      back(j*100, i*100);
                    }
                    else if (j==bwidth-1) {
                      bredge(j*100, i*100);
                    }
                  }
                  else if (i==bheight-1) {
                    if (j==0) {
                      bblcorner(j*100, i*100);
                    }
                    else if ((j>0)&&(j<bwidth-1)) {
                      bbedge(j*100, i*100);
                    }
                    else if (j==bwidth-1) {
                      bbrcorner(j*100, i*100);
                    }
                  }
                }
                else if ((k>0)&&(k<bwidth-1)) {  
                  if (i==0) {
                    if (j==0) {
                      ltedge(j*100, i*100);
                    }
                    else if ((j>0)&&(j<bwidth-1)) {
                      top(j*100, i*100);
                    }
                    else if (j==bwidth-1) {
                      rtedge(j*100, i*100);
                    }
                  }
                  else if ((i>0)&&(i<bheight-1)) { 
                    if (j==0) {
                      left(j*100, i*100);
                    }
                    else if (j==bwidth-1) {
                      right(j*100, i*100);
                    }
                  }
                  else if (i==bheight-1) {
                    if (j==0) {
                      lbedge(j*100, i*100);
                    }
                    else if ((j>0)&&(j<bwidth-1)) {
                      bottom(j*100, i*100);
                    }
                    else if (j==bwidth-1) {
                      rbedge(j*100, i*100);
                    }
                  }
                }              
                else if (k==bwidth-1) {
                  if (i==0) {
                    if (j==0) {
                      ftlcorner(j*100, i*100);
                    }
                    else if ((j>0)&&(j<bwidth-1)) {
                      ftedge(j*100, i*100);
                    }
                    else if (j==bwidth-1) {
                      ftrcorner(j*100, i*100);
                    }
                  }
                  else if ((i>0)&&(i<bheight-1)) { 
                    if (j==0) {
                      fledge(j*100, i*100);
                    }
                    else if ((j>0)&&(j<bwidth-1)) {
                      front(j*100, i*100);
                    }
                    else if (j==bwidth-1) {
                      fredge(j*100, i*100);
                    }
                  }
                  else if (i==bheight-1) {
                    if (j==0) {
                      fblcorner(j*100, i*100);
                    }
                    else if ((j>0)&&(j<bwidth-1)) {
                      fbedge(j*100, i*100);
                    }
                    else if (j==bwidth-1) {
                      fbrcorner(j*100, i*100);
                    }
                  }
                }
              }
            }
          }
          translate(0, 0, -k*100);
        }//z layer adjustment
        translate(-bxpos, -bypos, -bzpos);
      }
    }//move the draw point back to origin 
    //-----------------------------------------------------Surface Constructors     for Platforms 
    void block(int bx, int by) {//one 6 sided block----------------------------
      shape(Brick[0], bx, by);//front
      shape(Brick[1], bx, by);//left
      shape(Brick[2], bx, by);//right
      shape(Brick[3], bx, by);//back
      shape(Brick[4], bx, by);//top
      shape(Brick[5], bx, by);
    }//bottom
    void ftlcorner(int bx, int by) {//corners-----------------------------------
      shape(Brick[0], bx, by);//front
      shape(Brick[1], bx, by);//left
      shape(Brick[4], bx, by);
    }//top
    void ftrcorner(int bx, int by) {
      shape(Brick[0], bx, by);//front
      shape(Brick[2], bx, by);//right
      shape(Brick[4], bx, by);
    }//top
    void fblcorner(int bx, int by) {
      shape(Brick[0], bx, by);//front
      shape(Brick[1], bx, by);//left
      shape(Brick[5], bx, by);
    }//bottom  
    void fbrcorner(int bx, int by) {
      shape(Brick[0], bx, by);//front 
      shape(Brick[2], bx, by);//right 
      shape(Brick[5], bx, by);
    }//bottom  
    void btlcorner(int bx, int by) {
      shape(Brick[3], bx, by);//back
      shape(Brick[1], bx, by);//left
      shape(Brick[4], bx, by);
    }//top
    void btrcorner(int bx, int by) {
      shape(Brick[3], bx, by);//back
      shape(Brick[2], bx, by);//right
      shape(Brick[4], bx, by);
    }//top
    void bblcorner(int bx, int by) {
      shape(Brick[3], bx, by);//back
      shape(Brick[1], bx, by);//left
      shape(Brick[5], bx, by);
    }//bottom  
    void bbrcorner(int bx, int by) {
      shape(Brick[3], bx, by);//back 
      shape(Brick[2], bx, by);//right 
      shape(Brick[5], bx, by);
    }//bottom
    void ftedge(int bx, int by) {//edges----------------------------------------
      shape(Brick[0], bx, by);//front
      shape(Brick[4], bx, by);
    }//top
    void fledge(int bx, int by) {
      shape(Brick[0], bx, by);//front
      shape(Brick[1], bx, by);
    }//left
    void fredge(int bx, int by) {
      shape(Brick[0], bx, by);//front
      shape(Brick[2], bx, by);
    }//right
    void fbedge(int bx, int by) {
      shape(Brick[0], bx, by);//front
      shape(Brick[5], bx, by);
    }//bottom
    void btedge(int bx, int by) {
      shape(Brick[3], bx, by);//back
      shape(Brick[4], bx, by);
    }//top
    void bledge(int bx, int by) {
      shape(Brick[3], bx, by);//back
      shape(Brick[1], bx, by);
    }//left
    void bredge(int bx, int by) {
      shape(Brick[3], bx, by);//back
      shape(Brick[2], bx, by);
    }//right
    void bbedge(int bx, int by) {
      shape(Brick[3], bx, by);//back
      shape(Brick[5], bx, by);
    }//bottom
    void ltedge(int bx, int by) {
      shape(Brick[1], bx, by);//left
      shape(Brick[4], bx, by);
    } //top
    void lbedge(int bx, int by) {
      shape(Brick[1], bx, by);//left
      shape(Brick[5], bx, by);
    } //bottom
    void rtedge(int bx, int by) {
      shape(Brick[2], bx, by);//right
      shape(Brick[4], bx, by);
    } //top
    void rbedge(int bx, int by) {
      shape(Brick[2], bx, by);//right
      shape(Brick[5], bx, by);
    } //bottom
    //faces--------------- 
    void front (int bx, int by) {
      shape(Brick[0], bx, by);
    }//front
    void left  (int bx, int by) {
      shape(Brick[1], bx, by);
    }//left
    void right (int bx, int by) {
      shape(Brick[2], bx, by);
    }//right
    void back  (int bx, int by) {
      shape(Brick[3], bx, by);
    }//back
    void top   (int bx, int by) {
      shape(Brick[4], bx, by);
    }//top
    void bottom(int bx, int by) {
      shape(Brick[5], bx, by);
    }//bottom
    
    void definePlats() {
      for (int i=0; i<10; i++) {//preset plat heights
        heights[i]=-200+(i*200);
        println(i);
      }
      heights[10]=3000;//this is the height of the large img below, and is not called through Build();
    
    
      for (int i=0; i<20; i+=2) {//define preset plat specifications
        specs[i] = -600+((i/2)*600);      
        specs[i+1] = -600+((i/2)*600);
      }
    
      specs[18] = 3600;
      specs[19] = 4000;
    
      specs[20] = -600;
      specs[21] = -600;
    
      for (int i=0; i<10; i++) {//enter preset plat specifications
        plat[i] = new Platform(specs[(i*2)], heights[i], specs[(i*2)+1], 5, 1);
      }
    }
    
    void LOAD() {
      imgLoad();
      loadBrick();
      definePlats();
    }
    
    void imgLoad() {
      wall = loadImage("wall.png");
    }
    
    void loadBrick() {
      //FRONT
      Brick[0] = createShape();
      Brick[0].beginShape();
      Brick[0].noStroke();
      Brick[0].texture(wall);
      Brick[0].vertex(     0, 0, 0, 0, 0);
      Brick[0].vertex(   100, 0, 0, 50, 0);
      Brick[0].vertex(   100, 100, 0, 50, 50);
      Brick[0].vertex(     0, 100, 0, 0, 50);
      Brick[0].endShape();
      //LEFT
      Brick[1] = createShape();
      Brick[1].beginShape();
      Brick[1].noStroke();
      Brick[1].texture(wall);
      Brick[1].vertex(     0, 0, 0, 0, 0);
      Brick[1].vertex(     0, 0, -100, 50, 0);
      Brick[1].vertex(     0, 100, -100, 50, 50);
      Brick[1].vertex(     0, 100, 0, 0, 50);
      Brick[1].endShape();
      //RIGHT
      Brick[2] = createShape();
      Brick[2].beginShape();
      Brick[2].noStroke();
      Brick[2].texture(wall);
      Brick[2].vertex(   100, 0, 0, 0, 0);
      Brick[2].vertex(   100, 0, -100, 50, 0);
      Brick[2].vertex(   100, 100, -100, 50, 50);
      Brick[2].vertex(   100, 100, 0, 0, 50);
      Brick[2].endShape();
      //BACK
      Brick[3] = createShape();
      Brick[3].beginShape();
      Brick[3].noStroke();
      Brick[3].texture(wall);
      Brick[3].vertex(     0, 0, -100, 0, 0);
      Brick[3].vertex(   100, 0, -100, 50, 0);
      Brick[3].vertex(   100, 100, -100, 50, 50);
      Brick[3].vertex(     0, 100, -100, 0, 50);
      Brick[3].endShape();
      //TOP
      Brick[4] = createShape();
      Brick[4].beginShape();
      Brick[4].noStroke();
      Brick[4].texture(wall);
      Brick[4].vertex(     0, 0, -100, 0, 0);
      Brick[4].vertex(   100, 0, -100, 50, 0);
      Brick[4].vertex(   100, 0, 0, 50, 50);
      Brick[4].vertex(     0, 0, 0, 0, 50);
      Brick[4].endShape();
      //BOTTOM
      Brick[5] = createShape();
      Brick[5].beginShape();
      Brick[5].noStroke();
      Brick[5].texture(wall);
      Brick[5].vertex(     0, 100, -100, 0, 0);
      Brick[5].vertex(   100, 100, -100, 50, 0);
      Brick[5].vertex(   100, 100, 0, 50, 50);
      Brick[5].vertex(     0, 100, 0, 0, 50);
      Brick[5].endShape();
      //Brick[6] is a very large version of the image
      Brick[6] = createShape();
      Brick[6].beginShape();
      Brick[6].noStroke();
      Brick[6].texture(wall);
      Brick[6].vertex(     0, 0, -100, 0, 0);
      Brick[6].vertex(  7000, 0, -100, 50, 0);
      Brick[6].vertex(  7000, 0, 7000, 50, 50);
      Brick[6].vertex(     0, 0, 7000, 0, 50);
      Brick[6].endShape();
    }
    
  • edited April 2014

    I apologize, but neither the Ctrl+k was working, nor the C button :( not sure why that is. I made sure there were blank lines before and after.

    EDIT: switched computers and ctrl+k worked. Thanks, I didn't know about formatting it in the IDE.

  • edited April 2014
    • Even before posting your code here, when it's still in Processing's IDE, hit CTRL+T there in order to properly rearrange it! o->
    • After pasting you post here, highlight it and hit CTRL+K. Now you got yourself a pleasing formated code! :-bd
  • wall this is the "wall.png" called for in the code.

  • Yikes, you rly should use more arrays. Those plat01 to plat19 & brick1 to brick9 are fit candidates!

  • edited April 2014

    I'm relatively new to processing(as well as coding in general) :P so I'm not quite certain what you mean by that. Aren't I already using them in that situation? at least for the plat1-19? Any help with my code in general is welcome(seriously, what should I be doing?), but help about the issue at hand is more welcome. ;)

    EDIT: oh wait a second, are you saying it is possible to have an object array? Never tried it. I will when I have time.

  • edited April 2014

    ... are you saying it is possible to have an object array?

    Yup! Besides the 8 primitive types, any object type is valid for arrays as well:

    Platform[] platforms = new Platform[18];
    PShape[] bricks = new PShape[7];  
    

    Otherwise, arrays in Java would be very limited! :P

  • edited April 2014

    That is quite handy when there are a lot of 'em, and in the whole program, there is. Thanks for mentioning that. I applied it to my code(thank heavens for Ctrl+f). Although I don't understand why the PShape or really any basic array has to declare one too many or else it errors with "out of bounds," while the object array is fine. I understand that there are seven shapes, but shouldn't PShape[6] including [0] be enough? (ya know... 0,1,2,3,4,5,6)

    EDIT: oh wait lol, even the object array errors out on me if at [18].

  • edited April 2014

    I updated the code above, it now has the arrays we discussed, as well as more condensed sections and minor changes. Hopefully it is now pleasing to your eye ;)

Sign In or Register to comment.