processing - Working Fine In Java Mode, Not So In Javascript (Also Trouble With Algorithm) -


i'm teaching myself game programming , remaking of classic games learn different tricks , stuff(as suggested fine article on gamedev.net).

i coded pong , working on snake(i assume that's meant worm). figured out lot of stuff, except 2 things can't wrap mind around.

my algorithm simple enough: player controls head , body follows. head has it's own class , there each segment controlled separate object. segments each control own movement defined velocity vector. first segment independent array controls rest of segments. head sends orders first segment , first segment transmits rest of segments.

the system based on bendinpoints. each segment has variable storing bendingpoint coordinate , velocity vector take on when reaching bendingpoint. flag tells whether posses bendingpoint or free accept new coordinate.

so head, when turns, transmits location where turned , direction(velocity vector) in turned. first segment passes on second, second passes on third , on. each segment passes order next if has 1 pass. each segment receives new orders once old 1 has been completed.

now problem two-fold. one: works fine in java mode not working in javascript mode , can't figure out why. , two: sometimes, when i'm changing direction rapidly, rest of body apart head , first segment seem lose track , wander off.

i hope code comments explain rest. forgive newbishness.

string mode;  menu menu; string[] menuitems={"start","instructions","credits","exit"};  /*@ pjs font="data/waved.ttf" */ /*@ pjs font="data/sixty.ttf" */ pfont smenu=createfont("waved",72); pfont sitem=createfont("sixty",35);  string govertext="game over"; string hscoretext="your score is: ";  string icontrol="w,a,s,d turns snake in respective direction."; string iscore="each food increases score 1 , segement added."; string iscore2="after every 10 points, number of segments added per food increases 1.";  string cby="coded by"; string cname="le shaun";  menuitem back;  snake snk; food fd;  int hscore; int df;  float swidth=800; float sheight=600;  pvector sloc=new pvector(swidth/2,sheight/2); pvector svel=new pvector(0,-1); float srad=10; color scol=#9d6c0a;  pvector floc=new pvector(450,300); float frad=10; color fcol=#fcf18c;  void setup(){   size(int(swidth),int(sheight));   snk=new snake(sloc,svel,srad,scol);   fd=new food(floc,frad,fcol);   framerate(60);    hscore=0;   df=1;    menu=new menu("snake",menuitems,smenu,sitem,color(#9d6c0a),color(#8cc610),color(#ede724),color(#674707),color(255,0));    mode="nil";    back=new menuitem("back",sitem,width/2,height/1.5,height/25,color(#8cc610),color(#ede724),color(#674707),color(255,0));    //common button of screens. }  //current screen controlled modes. each mode defines parts of game run, whether individual screens or main gameplay itself.  void draw(){   background(#edb824);    if(mode.equals("nil")){     menu.render();     mode=menu.whichitem();   }   else if(mode.equals("start")){       fd.render();     if(fd.iseaten(snk)){       for(int i=1;i<=df;i++){       snk.sinc();       }       hscore++;     }      snk.render();     snk.update();     if(snk.isdead()){      mode="gameover";      sloc=new pvector(width/2,height/2);      floc=new pvector(width/2+100,height/2+100);      svel=new pvector(+1,0);      snk=new snake(sloc,svel,srad,scol);     }      df=int(hscore/10)+1;      textfont(sitem);     textsize(height/25);     text(str(hscore),width-textwidth(str(hscore))*3,height-height/25);   }   else if(mode.equals("gameover")){     stroke(0);     fill(#9d6c0a);     textfont(smenu);     textsize(72);     text(govertext,width/2-textwidth(govertext)/2,height/3);     text(hscoretext+hscore,width/2-textwidth(govertext)/2,height/2);      back.render();     back.update();     if(back.getclicked()){       back.unclick();       mode="nil";       hscore=0;       framerate(60);     }   }   else if(mode.equals("instructions")){     stroke(0);     fill(#9d6c0a);     textfont(smenu);     textsize(72);     text("instructions",width/2-textwidth("instructions")/2,height/3);      textfont(sitem);     textsize(20);     text(icontrol,width/2-textwidth(icontrol)/2,height/2);     text(iscore,width/2-textwidth(iscore)/2,height/2+35);     text(iscore2,width/2-textwidth(iscore2)/2,height/2+70);      back.render();     back.update();     if(back.getclicked()){       back.unclick();       mode="nil";     }   }   else if(mode.equals("credits")){     stroke(0);     fill(#9d6c0a);     textfont(sitem);      textsize(35);     text(cby,width/2-textwidth(cby)/2,height/2);      textsize(45);     text(cname,width/2-textwidth(cname)/2,height/1.7);      back.render();     back.update();     if(back.getclicked()){       back.unclick();       mode="nil";     }   }     //println(mode); }  void keyreleased(){   if(mode.equals("start")){     string temp="";     temp+=key;     temp=temp.touppercase();     snk.changedir(temp);      if(key=='v' || key=='v'){       framerate(60);     }   } }  void keypressed(){     if(mode.equals("start")){     if(key=='v' || key=='v'){       framerate(180);     }   } }  void mouseclicked(){   if(mode.equals("nil")){     menu.passto(mousex,mousey);   }   if(mode.equals("gameover") || mode.equals("instructions") || mode.equals("credits")){     back.mclicked(mousex,mousey);   } }   //menu class uses objects menuitem , forms menu title , list of menuitem objects.  /*   constructor: str-menutitle, str[]-menuitems, pf-menufont, pf-menuitemfont, c-titlecolor, c-itemtextcolor, c-itembackcolor, c-itemhovertextcolor, c-itemhoverbackcolor.    methods:       void render() - renders menutitle , menuitems.       void passto(float,float) - passes mouse coords each menuitem check whether has been clicked.       void passto(int) - resets clickstate of specified menuitem calling unclick() method on menuitem.       string whichitem() - checks menuitems clickstate , returns 1 that's been clicked. */  class menu{   string titlet;    pfont titlef;   pfont menuitem;    color titlec;    float spacer;    //this used define space between successive menuitem objects.   float iniy=height/2.5;    menuitem[] menuitems;    menu(string titlet,string[] menuitemsnames,pfont titlef,pfont menuitemf,color titlec,color menuitemc,color menubackc,color itemhoverc,color backhoverc){     this.titlet=titlet;     this.titlef=titlef;     this.titlec=titlec;      menuitems=new menuitem[menuitemsnames.length];  //initializes menuitem objects depending on array passed it. makes menu system flexible.     spacer=48;     for(int i=0;i<menuitemsnames.length;i++){             menuitems[i]=new menuitem(menuitemsnames[i],menuitemf,width/2,iniy+(spacer*i),height/25,menuitemc,menubackc,itemhoverc,backhoverc);     }   }    void render(){  //renders menu.     textfont(titlef);     textsize(92);     fill(titlec);     text(titlet,width/2-(textwidth(titlet)/2),height/3.8);      for(int i=0;i<menuitems.length;i++){       menuitems[i].update();       menuitems[i].render();     }   }    void passto(float mx,float my){    //this accepts x,y mouse coords when mouse clicked , passes relevant menuitem object check if click occurs on object.     for(int i=0;i<menuitems.length;i++){       menuitems[i].mclicked(mx,my);     }   }    /*void passto(int item){  //this accepts ineteger value , resets particular menu item's click state.     menuitems[item].unclick();   }*/    string whichitem(){  //checks each time if clickstate of menuitem object true. if is, returns array position of relevant object.     for(int i=0;i<menuitems.length;i++){       if(menuitems[i].getclicked()){         menuitems[i].unclick();         return menuitems[i].menuitem;       }     }     return "nil";   } }   //menuitem holds attributes , methods relating each single item on menu. each item treated separate object. //each menuitem object comprises of foreground text , background object.     class menuitem{    string menuitem;   pfont menufont;   float itemx;   float itemy;   float itemsize;   color itemcolor;   color backcolor;   color pressedcolor;   color pressedback;    color presentitem;   color presentback;    float textwidth;    boolean clickstate=false;  //this vairable used check clickstate of menu item. if mouse clicked on menu item, variable becomes true.    menuitem(string menuitem,pfont menufont,float itemx,float itemy,float itemsize,color itemcolor,color backcolor,color pressedcolor,color pressedback){     this.menuitem=menuitem;     this.menufont=menufont;     this.itemx=itemx;     this.itemy=itemy;     this.itemsize=itemsize;     this.itemcolor=itemcolor;     this.backcolor=backcolor;     this.pressedcolor=pressedcolor;     this.pressedback=pressedback;   }    void render(){    //handles rendering individual menu objects.     textfont(menufont);     textsize(itemsize);     textwidth=textwidth(menuitem);      stroke(0);     fill(presentback);     rectmode(center);     rect(itemx,itemy,textwidth*1.3,itemsize*1.4,50);      fill(presentitem);     text(menuitem,itemx-textwidth/2,itemy+itemsize*.3);   }    void update(){             //constatnly checks state of object. if mouse on style show , otherwise style shown.     if(mousex<(itemx+(textwidth*1.3)/2) && mousex>(itemx-(textwidth*1.3)/2) && mousey<(itemy+(itemsize*1.4)/2) && mousey>(itemy-(itemsize*1.4)/2)){      presentitem=pressedcolor;      presentback=pressedback;      nostroke();     }     else{      presentitem=itemcolor;      presentback=backcolor;     }   }    boolean getclicked(){    //returns clickstate of object.     return clickstate;   }    void unclick(){      //resets click state after having been clicked once.     clickstate=false;   }    void mclicked(float mx,float my){  //changes clickstate of object depending on position of mouse inputs.     if(mx<(itemx+(textwidth*1.3)/2) && mx>(itemx-(textwidth*1.3)/2) && my<(itemy+(itemsize*1.4)/2) && my>(itemy-(itemsize*1.4)/2)){       clickstate=true;       println(menuitem);     }   } }    /*   control comes snake's head. head works directly first segment(snakebits object) , first segement works rest of body.   each time food consumed, new segment created, it's position , velocity calculated per position of last segment.   loop checks whether each segment open receiving new set of orders(bendingpoint , velocity point), , passes on if so.  */  class snake{  //controls snake's head segment objects.      pvector sloc;  //location , velocity.   pvector svel;    float srad;  //radius , color   float shrad;       color scol;    float basevel;  //the base velocity of snake.    snakebits[] sbits={};  //array of snakebits objects forms segments.    pvector hold;    snake(pvector sloc,pvector svel,float srad,color scol){     this.sloc=sloc;     this.svel=svel;     this.srad=srad;     this.shrad=srad*1.;     this.scol=scol;     this.basevel=abs(svel.x>0 ? svel.x : svel.y);  //the snake given vector in 1 of cardinal directions. whatever value of velocity in either direction stored.      hold=pvector.mult(svel,shrad+srad);     hold=pvector.sub(sloc,hold);     sbits=(snakebits[])append(sbits,new snakebits(hold,svel,srad,scol));   }    void update(){  //updates movement of head segments.     updatebp();      sloc.add(svel);     for(int i=0;i<sbits.length;i++){       sbits[i].update();     }       }    void render(){  //the display.     stroke(0);     fill(scol);     ellipse(sloc.x,sloc.y,shrad*2.2,shrad*2.2);      for(int i=0;i<sbits.length;i++){       sbits[i].render();     }   }    void sinc(){  //gets called each time food item eaten, , increases size of snake adding segments based on velocity vector of last segment.     int lastind=sbits.length-1;     hold=pvector.mult(sbits[lastind].sbvel,srad*2);     hold=pvector.sub(sbits[lastind].sbloc,hold);     pvector appvel=new pvector(sbits[lastind].sbvel.x,sbits[lastind].sbvel.y);     snakebits appbits=new snakebits(hold,appvel,srad,scol);     sbits=(snakebits[])append(sbits,appbits);   }    void changedir(string dir){  //gets called when directional button pressed.      pvector chng=new pvector(0,0);  //direction change can occur perpendicular current direction. uses basevel set new direction.     if(!sbits[0].hasbp){       if(degrees(svel.heading())==0 || degrees(svel.heading())==180){         if(dir.equals("w")){           chng=new pvector(0,-basevel);           svel=chng;           updatefbp();         }         else if(dir.equals("s")){           chng=new pvector(0,basevel);           svel=chng;           updatefbp();         }       }       else if(degrees(svel.heading())==90 || degrees(svel.heading())==-90){         if(dir.equals("d")){           chng=new pvector(basevel,0);           svel=chng;           updatefbp();         }         else if(dir.equals("a")){           chng=new pvector(-basevel,0);           svel=chng;           updatefbp();         }       }     }   }    boolean isdead(){  //checks collision against wall or it's own tail.     if((sloc.x-shrad)<0 || (sloc.x+shrad)>width || (sloc.y-shrad)<0 || (sloc.y+shrad)>height){        println("wall");       return true;     }     pvector temp;     for(int i=0;i<sbits.length;i++){        if(dist(sloc.x,sloc.y,sbits[i].sbloc.x,sbits[i].sbloc.y)<(shrad+srad-srad*.6)){         println("tail");         println(sloc.x+" "+sloc.y+" "+sbits[i].sbloc.x+" "+sbits[i].sbloc.y+" "+dist(sloc.x,sloc.y,sbits[i].sbloc.x,sbits[i].sbloc.y)+" "+(shrad+srad-srad*.6));         return true;       }     }      return false;  }   void updatefbp(){     //updates first segment's bendingpoint.       sbits[0].takenewbp(sloc,svel);       sbits[0].hasnewbp(true);     }   void updatebp(){  //updates rest of segments per system of receiving new orders once current orders have been executed.    for(int i=0;i<sbits.length-1;i++){      if(sbits[i].hasbp && !sbits[i+1].hasbp){        sbits[i+1].takenewbp(sbits[i].newbp,sbits[i].newvel);        sbits[i+1].hasnewbp(true);      }    }  }   }   /*   each snakebit has it's independent movement system. holds bendpoint(newbp) variable, new bp velocity(newvel) variable , flag(hasbp) show whether has new bend point.   when snakebit has bp, wait till reaches bp , take on velocity newvel. it's flag set false.   in state open receiving new set of orders: new bp , velocity take on bp. new bp's not taken on till previous bp has been cleared. */  class snakebits{  //the individual bits of snake make body.    boolean hasbp;    pvector sbloc;  //location , velocity vectors.   pvector sbvel;    float sbrad;  //radius , color of segment.   color sbcol;    pvector newbp;  //this works changedir() method. holds position @ direction changed.   pvector newvel;  //stores new velocity vector applied when above position reached.    snakebits(pvector sbloc,pvector sbvel,float sbrad,color sbcol){     this.sbloc=sbloc;     this.sbvel=sbvel;     this.sbrad=sbrad;     this.sbcol=sbcol;     newvel=new pvector(sbvel.x,sbvel.y);     newbp=new pvector(width*2,height*2);  //initialized such avoid problems during first run.     hasbp=false;   }    void render(){     stroke(0);     fill(sbcol);     ellipse(sbloc.x,sbloc.y,sbrad*2,sbrad*2);   }    void update(){     sbloc.add(sbvel);  //both updates location , checks if it's time change direction.     changedir();    }    void changedir(){     if(sbloc.x==newbp.x && sbloc.y==newbp.y && hasbp){  //as segment reaches location change in dir needed, velocity changed on new velocity vector.       println("ftrue");       hasnewbp(false);       sbvel.x=newvel.x;  sbvel.y=newvel.y;       newbp=new pvector(width*2,height*2);     }    }    void takenewbp(pvector pos,pvector vel){  //called externally snake class. takes last segment changed direction , stores location new velocity vector.     newbp.x=pos.x;  newbp.y=pos.y;     newvel.x=vel.x; newvel.y=vel.y;    }    void hasnewbp(boolean dat){  //updates hasbp state accepting boolean , assigning hasbp.     hasbp=dat;   } }   class food{    pvector floc;    float frad;   color fcol;    food(pvector floc,float frad,color fcol){     this.floc=floc;     this.frad=frad;     this.fcol=fcol;   }    void render(){     stroke(0);     fill(fcol);     ellipse(floc.x,floc.y,frad*2,frad*2);   }    boolean iseaten(snake sn){     pvector temp;     temp=pvector.sub(floc,sn.sloc);     if(temp.mag()<(sn.shrad+frad)){       reset(sn);       return true;     }      return false;   }    void reset(snake sn){     boolean set=false;     pvector tmp=new pvector();     while(!set){       tmp=new pvector(random(frad,width-frad),random(frad,height-frad));       set=true;       for(int i=0;i<sn.sbits.length;i++){         if(dist(tmp.x,tmp.y,sn.sbits[i].sbloc.x,sn.sbits[i].sbloc.y)<(frad+sn.srad) || dist(tmp.x,tmp.y,sn.sloc.x,sn.sloc.y)<(frad+sn.shrad)){           set=false;           break;         }       }     }     floc=tmp;   } } 

javascript mode seems have problem textwidth(); on can change textwidth=textwidth(menuitem); in menuitem.render() textwidth=200; or find working equivalent.

by way, noticed when run in javascript, wouldn't take full size , size(); command culprit. seems require numbers instead of variables function (setting size(800,600); worked)

your other problem seems stem fact change things when press button dont apply change until draw() function. unfortunately can't pinpoint in code making small changes, makes me believe need refactor turning system in different fashion. suggestion decouple has go previous 1 goes, opting instead store positions , directions has go in arraylist, grow each turn. then, each bit of snake has go through own arraylist of directions , positions without regarding momentary changes of previous one. when reach 1 of positions turn in proper direction, delete reached direction , position , start heading next one. arraylist functions queue, add end remove beginning.

maybe makes sense post second part of question https://gamedev.stackexchange.com/


Comments

Popular posts from this blog

php - Calling a template part from a post -

Firefox SVG shape not printing when it has stroke -

How to mention the localhost in android -