Maya Tetris

From bernie's
Jump to: navigation, search

wip

proc string createText(string $string){
    //creates a text object and merges it into a single shape
    //returns object name
    
    $textGrp = `group -n $string -em`;
    string $textObj[] = `textCurves -t $string`;
    delete $textObj[1];
    string $subObjs[] = `listRelatives $textObj[0]`;
    makeIdentity -a 1 $subObjs;
    string $subShapes[] = `listRelatives $subObjs`;
    $subShapes = `listRelatives -s $subShapes`;
    parent -s -r $subShapes $textGrp;
    delete $textObj[0];
    return $textGrp;
}
proc string instanceCounter(int $digits){
    //creates an updatable text counter using a particle + instance system, requires createText()
    //returns particle system
    
    $numbers = {"-","0","1","2","3","4","5","6","7","8","9"};
    string $numberObj[]={};
    string $objlist = "";
    $textGrp = `group -em -n "digits_and_particleSystem"`;
    setAttr($textGrp+".visibility") 0;
    for($n in $numbers){
        $object = createText($n);
        parent $object $textGrp;
        $objlist += " -object "+$object;
    }
    $pSystem = "particle";
    for($i=0;$i<$digits;$i++){
        $pSystem += " -p "+$i+" 0 0";
    }
    string $pobj[] = eval($pSystem);
    addAttr -ln "index"  -dt doubleArray $pobj[1];
    string $instancerEval = "particleInstancer -addObject "+$objlist+" -cycle None -cycleStep 1 -cycleStepUnits Frames -levelOfDetail Geometry -rotationUnits Degrees -rotationOrder XYZ -n digitscounter -position worldPosition -age age -objectIndex index -visibility index "+$pobj[1];
    string $particleInstanc = eval($instancerEval);
    parent $pobj[0] $textGrp;
    return $pobj[1];
}

proc updateCounter(string $particleShape,int $number, int $numberOfDigits){
    //updates a counter created using instanceCounter()
    $strN = string($number);
    $strS = size($strN);
    for($j = 0;$j<$numberOfDigits;$j++){
            if($j<$strS){
                $n = substring($strN,$strS-$j,$strS-$j);
                particle -e -at "index" -id ($numberOfDigits-$j-1) -fv (float($n)+1) $particleShape;
            }else{
                particle -e -at "index" -id ($numberOfDigits-$j-1) -fv 0 $particleShape;                
            }
    }
}
proc setCubeColor(string $cube){
    // give a polygon cube random-ish colors on each face
    
    constructionHistory -tgl off;
    string $shapes[] = `listRelatives -s $cube`;
    setAttr($shapes[0]+".displayColors") 1;
    float $hue = rand(0,1);
    for($i=0;$i<6;$i++){
        float $hue2 = rand(-.07,.07);
        $hue = (abs($hue2 + $hue))%1;
        float $sat = rand(.6,.8);
        float $value = rand(.6,.8);
        float $color[] = `hsv_to_rgb <<$hue,$sat,$value>>`;
        polyColorPerVertex -nun -rgb $color[0] $color[1] $color[2] ($cube+".f["+$i+"]");
    }
    constructionHistory -tgl on;
}



//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////




proc setupTetrisControls(){
    // set ups a bunch of objects that are parented in a way you can use the keyboard arrows ('pickwalk' function - eww) to travel through them
    // a scriptjob will alway select the center 'neutral' object, like a joystick coming back to the center position
    // object names will be hardcoded because I code like a monkey
    
    if(`objExists "TetrisGroup"`) delete "TetrisGroup";
    $nullGrp = `group -n "TetrisGroup" -em`;
    $top = `spaceLocator -n "topCtrl"`;
    setAttr($top[0]+".visibility",0);
    spaceLocator -n "leftCtrl";
    spaceLocator -n "rightCtrl";
    spaceLocator -n "neutralCtrl";
    parent "leftCtrl" "topCtrl";
    parent "neutralCtrl" "topCtrl";
    parent "rightCtrl" "topCtrl";
    rename "neutralCtrlShape" "bottomCtrl";
    $testObject = `polyCylinder -n "TestObject"`;
    string $deleteCtrl = createText("delete");
    $nullDeleteGrp = `group -n "DeleteGroup" -em`;
    parent $nullDeleteGrp $nullGrp;
    parent $deleteCtrl $nullDeleteGrp;
    rename $deleteCtrl "deleteCtrl";
    parent $top $nullGrp;

}

// global variables

global int $jobCtrl;                  // id of the scriptjob that will always select the neutral control defined by setupTetrisControls() - launches the ctrls() function
global int $jobLoop;                  // id of the scriptjob that will launch the loop() function

global float $startTime;
global float $previousSecond;

$startTime = `timerX`;
$previousSecond = `timerX -startTime $startTime`;

proc ctrls(){
    // fires on any object selection in the scene, if it finds one of our control objects is selected, selects neutral one
    // also kills scriptjobs if it finds 
    
    global int $jobCtrl;
    global int $jobLoop;
    
    global float $startTime;
    global float $previousSecond;
    
    string $sel[] = `ls -sl`;
    select -r "neutralCtrl";
    if($sel[0]=="deleteCtrl"){
        evalDeferred("scriptJob -kill "+$jobCtrl+" -force");
        scriptJob -kill $jobLoop -force;
        delete "TetrisGroup";
        //delete "deleteCtrl";
        //delete "TestObject";
    }else{
        $c = $sel[0];

        if($c=="topCtrl"){
            setAttr("TestObject.rz") ((getAttr("TestObject.rz")+90)%360);
        }
        if($c=="leftCtrl"){
            setAttr("TestObject.tx") (getAttr("TestObject.tx")-1);
        }
        if($c=="rightCtrl"){
            setAttr("TestObject.tx") (getAttr("TestObject.tx")+1);
        }
        if($c=="bottomCtrl"){
            $elapsedTime = `timerX -startTime $startTime`;
            $previousSecond = $elapsedTime-1;
        }
        
    }
    
}



proc startTetris(){
    //sets up ctrls, UI, game elements, and launches scriptjobs that actually start the game

    global int $jobCtrl;
    global int $jobLoop;
    
    setupTetrisControls;
    
    // actual script jobs
    // one controls what happens on selection change
    // the other one is the 'iterator', which controls the speed of the game
    
    $jobCtrl = `scriptJob -e "SelectionChanged" "ctrls()" -protected`;
    print $jobCtrl;
    $jobLoop = `scriptJob -ie "loop(.2)" -protected`;
    

}




proc loop(float $speed){
    //function that fires at every n millisecond, updates game
    global float $startTime;
    global float $previousSecond;
    $elapsedTime = `timerX -startTime $startTime`;
    if( ($previousSecond + $speed ) < $elapsedTime){
        //print ("Total Time: "+$elapsedTime+"\n");
        setAttr("TestObject.ty") ((getAttr("TestObject.ty")-1)%10);
        testStuff();
        //setAttr -type "string" annotationShape1.text $elapsedTime;
        $previousSecond = $elapsedTime;
    }else{
        //empty cycle
        //print($previousSecond+" "+$elapsedTime+"\n");
    }
}


proc testStuff(){
    for($i = 0;$i<50;$i++){
        particle -e -at "index" -id (floor(rand(0,50))) -fv (floor(rand(0,8))) "particleShape1";
    }
    currentTime (`currentTime -q`);
    
}






////////////////////////////////////////
////////////////////////////////////////
////////////////////////////////////////
////////////////////////////////////////
////////////////////////////////////////
////////////////////////////////////////
////////////////////////////////////////
////////////////////////////////////////
////////////////////////////////////////
////////////////////////////////////////
////////////////////////////////////////
////////////////////////////////////////
////////////////////////////////////////
setUpTetrisGrid(10,5);

proc setUpTetrisGrid(int $rows, int $cols){
    
    
    // create particle system with an 'index' pp attr
    string $p = "particle -n TetrisGridParticles";
    global int $rows;
    global int $cols;
    global float $grid[];
  
    float $pscale = 1.5;
    for($i=0;$i<$rows;$i++){
        for($j=0;$j<$cols;$j++){
            $p+= "-p 0 "+($i*$pscale+$pscale/2)+" "+($j-$cols/2)*$pscale+ " ";
        }
    }
    string $pSystem[] = eval($p);
    setAttr ($pSystem[1]+".particleRenderType") 6;       //streak mode no velocity = no streaks, I could hide particles too
    addAttr -ln "index"  -dt doubleArray $pSystem[1];    
    
    // create colored cubes to be instanced in particle system
    string $objList = "";
    for($i=0;$i<9;$i++){
        string $pCube[] = `polyCube -w ($pscale*.98) -h ($pscale*.98) -d ($pscale*.98) -sx 1 -sy 1 -sz 1 -ax 0 1 0 -cuv 4 -ch 0`;
        $objList += "-object \""+$pCube[0]+"\" ";
        setCubeColor($pCube[0]);
        setAttr($pCube[0]+".visibility") 0;
    }
    
    // create an instancer using the previous objects. '0' will be useless as it also maps visibility
    string $particleInstanc = eval("particleInstancer -addObject "+$objList+"-cycle None -cycleStep 1 -cycleStepUnits Frames -levelOfDetail Geometry -rotationUnits Degrees -rotationOrder XYZ -position worldPosition -age age -objectIndex index -visibility index "+$pSystem[1]);
}


// available pieces in a big 7 * 4*4 array
global int $pieces[];
$pieces = {
    0, 1, 0, 0,    // #
    0, 1, 0, 0,    // #
    0, 1, 0, 0,    // #
    0, 1, 0, 0,    // #
    
    0, 0, 0, 0,    //
    0, 1, 0, 0,    //  #
    1, 1, 1, 0,    // ###
    0, 0, 0, 0,    //
    
    0, 0, 1, 0,    //  #
    0, 0, 1, 0,    //  #
    0, 1, 1, 0,    // ##
    0, 0, 0, 0,    //
    
    0, 1, 0, 0,    //  #
    0, 1, 0, 0,    //  #
    0, 1, 1, 0,    //  ##
    0, 0, 0, 0,    //
    
    0, 0, 0, 0,    //  
    0, 1, 1, 0,    //  ##
    0, 1, 1, 0,    //  ##
    0, 0, 0, 0,    //
    
    
    0, 0, 0, 0,    //  
    0, 0, 1, 1,    //  ##
    0, 1, 1, 0,    // ##
    0, 0, 0, 0,    //
    
    
    0, 0, 0, 0,    //  
    0, 1, 1, 0,    //  ##
    0, 0, 1, 1,    //   ##
    0, 0, 0, 0     //
    };


//return a random piece as 4*4 (16) array
proc int[] randomPiece(){
    global int $pieces[];
    $p = $pieces;
    int $r = rand(7);
    $r = $r * 16;
    int $returnPiece[] = {
        0,        $p[$r+1 ], $p[$r+2 ], 0,
        0,        $p[$r+5 ], $p[$r+6 ], $p[$r+7 ],
        $p[$r+8], $p[$r+9 ], $p[$r+10], $p[$r+11],
        0,        $p[$r+13], 0        , 0
    };
    return $returnPiece;
}

//print current piece to script editor
proc printPiece(int $p[]){
    print("\n");
    for($i=0;$i<4;$i++){
        for($j=0;$j<4;$j++){
            //print($i*4+$j);
            print(($p[$i*4+$j]==1)?"#":".");
        }
        print("\n");
    }
    
}

//rotate a 4*4 piece around its center:
//
//   a b c d      m i e a
//   e f g h  ->  n j f b
//   i j k l  ->  o k g c
//   m n o p      p l h d
//
proc int[] rotatePiece(int $p[]){
    int $rotatedPiece[] = {$p[12],$p[8],$p[4],$p[0],$p[13],$p[9],$p[5],$p[1],$p[14],$p[10],$p[6],$p[2],$p[15],$p[11],$p[7],$p[3]};  //if 4x4 -> x=y, y=-x+3, clockwise rotation of matrix
    return $rotatedPiece;
}



// int $pp[] = randomPiece(); 
// printPiece($pp);
// printPiece(rotatePiece(rotatePiece($pp)));


proc updateInstanceIndexesFromArray(string $particleShape,float $gridArray[]){
    global int $rows;
    global int $cols;
    global float $grid[];
    for($j = 0;$j<$rows;$j++){
        for($i = 0;$i<$cols;$i++){
            int $id = $j*$cols+$i;
            particle -e -at "index" -id $id -fv ($grid[$id]) $particleShape;
        }
        
    }
    currentTime (`currentTime -q`);
    
}

$grid = {};
$counter = -1;
$rows = 10;
$cols = 5;
for($i = 0;$i<$rows;$i++){
    for($j = 0;$j<$cols;$j++){
        $counter = $counter+1;
        //$grid[$j*$cols+$i] = $counter+1+$i%2;
        $grid[$counter] = $i%2*($i%3+1);
        print($counter+1+$j%2+"\n");
    }
    
}
updateInstanceIndexesFromArray("TetrisGridParticlesShape",$grid);