Location: PHPKode > scripts > Logo class > logo-class/logo.php
<?

/*
**
** The basic Logo commands:
**
** FD 100  Move the turtle forward 100 steps.  
** RT 90  Turn the turtle to the right 90º.  
** LT 90  Turn the turtle to the left 90º.  
** BK 100  Move the turtle backwards 100 steps.  
** PU  Pick the turtle's pen up off the paper.  
** PD  Put the turtles pen back down on the paper.  
** CS  Clear the screen and start over.  
** HT  Hide the turtle (triangle).  
** ST  Show the turtle (triangle).  
** REPEAT 3 [...]  Repeat the commands 3 times.  
**
** POLY sides side Draw polygon
** SETFLOODCOLOR color
** FILL
** PRINT "string" Prints string
** SETXY 100 200 Set cursor at location 100,200
** MAKE "var value Set variabele var to value
** LOCAL "var Variabele var is local to the word (function)
** TO wordname :par1 :par2 ... Wordname is a new word with par1, par2... as parameters
** IF expression [ ... ] Exec command if expression evaluates to true
**
*/


class logoclass {

	var $_tx;		// integer: turtle x
	var $_ty;		// integer: turtle y
	var $_pendown;		// boolean: pen is down (or up)
	var $_showturtle;	// boolean: turtle is shown (or not)
	var $_program;		// string: the logo program
	var $_orig_program;	// string: the same, to use functions within a repeat
	var $_angle;		// integer: current cursor angle
	var $_repcount;		// integer: current repeat count
	var $_movie;		// the swf logo movie
	var $_turtle;		// the turtle sprite
	var $_pc;		// program counter
	var $_finalpc;		// pointer to end of program
	var $_locals;		// local variables
	var $_globals;		// global variables

	function logoclass($program) {
		$program .= "\r\n";
		preg_match_all("/(to\\s)?\\w+\\s(\"\\w+\\s)?(((repcount\\s*|\\d+\\s*|:\\w+\\s*)([\\*\\+\\-\\/]\\s*)?)+|\\[.+\\])*/i", $program, $matches);
		$this->_program = $matches[0];
		$this->_program[] = "END";
		$this->_finalpc = sizeof($this->_program);
		$this->_pc = 0;
		$this->_tx = 100;
		$this->_ty = 100;
		$this->_angle = -90;
		$this->_locals = array();
		$this->_globals = array();
		$this->_pendown = true;
		$this->_showturtle = true;
		$this->_repcount = 0;
		$this->_movie = new SWFMovie();
		$this->_movie->SetRate(2.0);
		$this->_movie->setDimension(320, 240);
		$this->create_turtle();
	}

	function create_turtle() {

		$s = new SWFShape();
		$s->setLine(1, 0, 0, 0);
		$s->setRightFill($s->addFill(0xff, 0, 0));
		$s->movePenTo(-6, 0);
		$s->drawLineTo(12, 0);
		$s->drawLineTo( 3, -6);
		$s->drawLineTo(-6, 0);

		$p = new SWFSprite();
		$i = $p->Add($s);
		$p->NextFrame();
		// todo
		$this->_turtle = $this->_movie->add($p);
		$this->_movie->nextframe();
		$this->showturtle();

	}

	function showturtle() {
		if ($this->_showturtle) {
			$this->_turtle->moveTo($this->_tx, $this->_ty);
		}
		$this->_movie->nextframe();
	}

	function lineto($newx, $newy) {
		$s = new SWFShape();
		$s->setLine(4, 0x7f, 0, 0);
		$s->movePenTo($this->_tx, $this->_ty);
		if ($this->_pendown) {
			$s->drawLineTo($newx, $newy);
		}
		$this->_movie->add($s);
		//$this->_movie->nextFrame();
	}

	function logo_fd($steps) {
		$newx = $this->_tx + ($steps * cos(deg2rad($this->_angle)));
		$newy = $this->_ty + ($steps * sin(deg2rad($this->_angle)));
		$this->lineto($newx, $newy);
		$this->_tx = $newx;
		$this->_ty = $newy;
		$this->showturtle();
	}

	function logo_rt($angle) {
		$this->_angle += $angle;
		$this->_turtle->Rotate(-1 * $angle);
		$this->showturtle();
	}

	function logo_lt($angle) {
		$this->_angle -= $angle;
		$this->_turtle->Rotate($angle);
		$this->showturtle();
	}

	function logo_bk($steps) {
		$newx = $this->_tx - ($steps * cos(deg2rad($this->_angle)));
		$newy = $this->_ty - ($steps * sin(deg2rad($this->_angle)));
		$this->lineto($newx, $newy);
		$this->_tx = $newx;
		$this->_ty = $newy;
		$this->showturtle();
	}

	function logo_pu() {
		$this->_pendown = false;
	}

	function logo_pd () {
		$this->_pendown = true;
	}

	function logo_cs() {
	}

	function logo_ht() {
		$this->_turtle->moveTo(-100, -100);
		$this->_showturtle = false;
	}

	function logo_st() {
		$this->_showturtle = true;
	}

	function logo_repeat($count, $program) {
		$program = preg_replace("/\\[(.*)\\]/", "\\1\r\n", $program);
		preg_match_all("/(to\\s)?\\w+\\s(\"\\w+\\s)?(((repcount\\s*|\\d+\\s*|:\\w+\\s*)([\\*\\+\\-\\/]\\s*)?)+|\\[.+\\])*/i", $program, $matches);
		$matches = $matches[0];
		$matches[] = "END";
		$loopcnt = sizeof($matches);
		for ($pc = 0; $pc < $loopcnt; $pc++) {
			$this->_program[$this->_finalpc + $pc] = $matches[$pc];
		}
		$holdrepcount = $this->_repcount;
		$holdfinal = $this->_finalpc;
		$holdpc = $this->_pc;
		$this->_finalpc += $loopcnt;
		for ($loop = 0; $loop < $count; $loop++) {
			$this->_repcount = $loop + 1;
			$this->_pc = $holdfinal;
			while ($this->exec_line()) {
				// loop through the loop
			}
		}
		$this->_repcount = $holdrepcount;
		$this->_pc = $holdpc;
		$this->_finalpc = $holdfinal;
	}

	function logo_setxy($x, $y) {
	}

	function logo_make($var, $value) {
		$var = strtoupper(substr($var, 1));
		// todo: globals
		$this->_locals[$var] = $value;
	}

	function exec_fn($function, $params) {
		$found = false;
		$pc = 0;
		while (!$found) {
			if ($pc >= sizeof($this->_program)) {
				return;
			}
			$line = $this->_program[$pc];
			$pc++;
			$commands = preg_match_all("/[\\w:\"]+/", $line, $matches);
			$matches = $matches[0];
			$command = strtoupper($matches[0]);
			if ($command == "TO") {
				if ($matches[1] == $function) {
					$found = true;
				}
			}
		}
		if ($found) {
			$holdlocals = $this->_locals;
			$holdpc = $this->_pc;
			$this->_pc = $pc;
			$newlocals = array();
			for ($par = 2; $par < sizeof($matches); $par++) {
				$key = strtoupper(substr($matches[$par], 1));
				$newlocals[$key] = $this->retvar($params[$par - 1]);
			}
			$this->_locals = $newlocals;
			while ($this->exec_line()) {
				// loop through the loop
			}
			$this->_pc = $holdpc;
			$this->_locals = $holdlocals;
		}
	}

	function skip_fn() {
		while (true) {
			if ($this->_pc >= sizeof($this->_program)) {
				return;
			}
			$line = $this->_program[$this->_pc];
			$this->_pc++;
			$commands = preg_match_all("/[\\w:\\[\\]]+/", $line, $matches);
			$matches = $matches[0];
			$command = strtoupper($matches[0]);
			if ($command == "END") return;
		}
	}

	function setlocalvar($key, $val) {
		$key = substr($key, 1);
		$this->_locals[$key] = $val;
	}

	function myvar($var) {
		$default = 0;

		$var = strtoupper($var);
		if (isset($this->_locals[$var])) {
			$res = $this->_locals[$var];
		}
		elseif (isset($this->_globals[$var])) {
			$res = $this->_globals[$var];
		}
		else {
			$res = $default;
		}
		return $res;
	}

	function retvar($var) {
		$var = preg_replace("/repcount/i", $this->_repcount, $var);
		$var = preg_replace("/:(\\w+)/e", "\$this->myvar(\"\\1\")", $var);
		eval("\$res = $var;");
		return $res;
	}

	function exec_line() {
		if ($this->_pc >= $this->_finalpc) {
			return false;
		}
		$line = $this->_program[$this->_pc];
		$this->_pc++;
		preg_match_all("/^\\w+|\"\\w+|\\[.*\\]|(((\\d+|:\\w+|repcount)\\s*([\\*\\+\\-\\/]\\s*)?))+/i", $line, $matches);
		$matches = $matches[0];
		$command = strtoupper($matches[0]);
		switch ($command) {
		case "FD":
		case "FORWARD":
			$this->logo_fd($this->retvar($matches[1]));
			break;
		case "RT":
		case "RIGHT":
			$this->logo_rt($this->retvar($matches[1]));
			break;
		case "LT":
		case "LEFT":
			$this->logo_lt($this->retvar($matches[1]));
			break;
		case "BK":
		case "BACKWARD":
			$this->logo_bk($this->retvar($matches[1]));
			break;
		case "PU":
		case "PENUP":
			$this->logo_pu();
			break;
		case "PD":
		case "PENDOWN":
			$this->logo_pd();
			break;
		case "CS":
		case "CLEARSCREEN":
			$this->logo_cs();
			break;
		case "HT":
		case "HIDETURTLE":
			$this->logo_ht();
			break;
		case "ST":
		case "SHOWTURTLE":
			$this->logo_st();
			break;
		case "REPEAT":
			$count = $matches[1];
			unset($matches[0]);
			unset($matches[1]);
			$program = implode($matches, " ");
			$this->logo_repeat($this->retvar($count), $program);
			break;
		case "MAKE":
			$this->logo_make($matches[1], $this->retvar($matches[2]));
			break;
		case "END":
			return false;
		case "TO":
			$this->skip_fn();
			break;
		default:
			$this->exec_fn(trim($matches[0]), $matches);
			break;
		}
		return true;
	}

	function output() {

		while ($this->exec_line()) {
			// loop through our program
		}
		$this->_movie->nextframe();
		Header('Content-type: application/x-shockwave-flash');
		$this->_movie->output();

	}
};

?>
Return current item: Logo class