diff options
| author | tomsmeding <hallo@tomsmeding.nl> | 2015-10-03 14:18:27 +0200 | 
|---|---|---|
| committer | tomsmeding <hallo@tomsmeding.nl> | 2015-10-03 14:18:27 +0200 | 
| commit | 0eb6ce70981deb5b711f49c77930c49181f59d95 (patch) | |
| tree | 8ef4d30734993bd3ee3f95fd08c9573a23baeea8 | |
| parent | 5a93cdaf5d4fcefe664271bb8f233044059f3ad3 (diff) | |
¯\_(ツ)_/¯
| -rw-r--r-- | engine.cpp | 73 | ||||
| -rw-r--r-- | flogo.cpp | 103 | ||||
| -rw-r--r-- | flogo.h | 12 | 
3 files changed, 157 insertions, 31 deletions
@@ -1,9 +1,80 @@  #include <iostream> +#include <vector> +#include <string> +#include <cstring> +#include <cmath> +#include <cctype> +#include <cassert> +#include "flogo.h"  #include "engine.h"  using namespace std; +bool iswordstartchar(char c){return isalpha(c)||c=='_'||c=='.'||c==':';} +bool iswordchar(char c){return iswordstartchar(c)||isdigit(c);} +bool isoperator(char c){return strchr("+-*/=<>()[]",c)!=NULL;} + +vector<string> tokenise(const char *str){ +	vector<string> tkns; +	const char *p=str; +	while(true){ +		while(*p&&isspace(*p))p++; +		if(!*p)break; +		if(*p==';'){ +			while(*p&&*p!='\n')p++; +			continue; +		} +		string s; +		if(iswordstartchar(*p)){ +			do s+=*p++; +			while(*p&&iswordchar(*p)); +		} else if(isdigit(*p)){ +			bool havedot=false; +			do { +				if(*p=='.'){ +					if(!havedot)havedot=true; +					else break; +				} else if(!isdigit(*p))break; +				s+=*p++; +			} while(*p); +		} else if(*p=='"'){ +			while(*p&&!isspace(*p))s+=*p++; +		} else if(isoperator(*p))s+=*p++; +		else { +			cerr<<"UNKNOWN CHAR <"<<*p<<'>'<<endl; +			p++; +		} +		tkns.push_back(move(s)); +	} +	return tkns; +} +  void logocommand(const char *str){ -	cout<<str<<endl; +	int i; +	vector<string> tkns=tokenise(str); +	const int ntkns=tkns.size(); +	for(i=0;i<ntkns;i++){ +		if(tkns[i]=="forward"||tkns[i]=="fd"){ +			if(i+1>=ntkns)assert(false); +			const int n=stoi(tkns[i+1]); +			const int newx=turtle.x+n*sin(turtle.dir*M_PI/180),newy=turtle.y-n*cos(turtle.dir*M_PI/180); +			drawline(turtle.x,turtle.y,newx,newy); +			turtle.x=newx; turtle.y=newy; +			drawturtle(); +			i++; +		} else if(tkns[i]=="left"||tkns[i]=="lt"){ +			if(i+1>=ntkns)assert(false); +			const int n=stoi(tkns[i+1]); +			turtle.dir-=n; +			drawturtle(); +			i++; +		} else if(tkns[i]=="right"||tkns[i]=="rt"){ +			if(i+1>=ntkns)assert(false); +			const int n=stoi(tkns[i+1]); +			turtle.dir+=n; +			drawturtle(); +			i++; +		} else if(tkns[i]=="bye")exit(0); +	}  } @@ -1,5 +1,9 @@  #include <iostream> +#include <cstdlib>  #include <cmath> +#include <cstdint> +#include <cassert> +  #include <FL/Fl.H>  #include <FL/Fl_Window.H>  #include <FL/Fl_Box.H> @@ -11,13 +15,11 @@  #include <FL/Fl_Button.H>  #include <FL/Fl_draw.H> +#include "flogo.h"  #include "engine.h"  using namespace std; -const int WIDTH=1000,HEIGHT=1000; - -  Fl_Window *window;  Fl_Scroll *drawscroll;  Fl_Box *drawimagebox,*turtleimagebox; @@ -28,34 +30,78 @@ Fl_Button *evaluatebutton;  uchar *imagebuf,*turtlebuf; +Turtle turtle; + -const uchar* someimg(void){ -	uchar *buf=new uchar[3*WIDTH*HEIGHT]; -	int x,y; -	for(y=0;y<HEIGHT;y++){ -		for(x=0;x<WIDTH;x++){ -			buf[(WIDTH*y+x)*3+0]=(int)sqrt((999-x)*(999-x)+y*y)/100*20; -			buf[(WIDTH*y+x)*3+1]=(int)sqrt(x*x+y*y)/100*20; -			buf[(WIDTH*y+x)*3+2]=(int)sqrt((500-x)*(500-x)+(0-y)*(0-y))/100*20; +void bresenham(int x1,int y1,int x2,int y2,uchar *buf,int bufintsz,int bufcellsz,uint32_t v){ +	int steep,deltax,deltay,error,ystep,x,y; +	steep=abs(y2-y1)>abs(x2-x1); +	if(steep){ +		swap(x1,y1); +		swap(x2,y2); +	} +	if(x1>x2){ +		swap(x1,x2); +		swap(y1,y2); +	} +	deltax=x2-x1; +	deltay=abs(y2-y1); +	error=deltax/2; +	if(y1<y2)ystep=1; else ystep=-1; +	for(x=x1,y=y1;x<=x2;x++){ +		if(steep){ +			switch(bufintsz){ +				case 1: buf[bufcellsz*(WIDTH*x+y)]=(uchar)v; break; +				case 2: *(uint16_t*)(buf+bufcellsz*(WIDTH*x+y))=(uint16_t)v; break; +				case 4: *(uint32_t*)(buf+bufcellsz*(WIDTH*x+y))=(uint32_t)v; break; +				default: assert(false); +			} +		} else { +			switch(bufintsz){ +				case 1: buf[bufcellsz*(WIDTH*y+x)]=(uchar)v; break; +				case 2: *(uint16_t*)(buf+bufcellsz*(WIDTH*y+x))=(uint16_t)v; break; +				case 4: *(uint32_t*)(buf+bufcellsz*(WIDTH*y+x))=(uint32_t)v; break; +				default: assert(false); +			} +		} +		error=error-deltay; +		if(error<0){ +			y+=ystep; +			error+=deltax;  		}  	} -	return buf;  } +void drawline(int x1,int y1,int x2,int y2){ +	bresenham(x1,y1,x2,y2,imagebuf,4,4,0xff000000); +	drawimage->uncache(); +	window->redraw(); +} + +void drawturtle(void){ +	memset(turtlebuf,0,WIDTH*HEIGHT*2*sizeof(uchar)); +	const double raddir=turtle.dir*M_PI/180; +	const int x1=turtle.x-15*cos(raddir), //left-bottom +	          y1=turtle.y-15*sin(raddir), +	          x2=turtle.x+15*cos(raddir), //right-bottom +	          y2=turtle.y+15*sin(raddir), +	          x3=turtle.x+15*sin(raddir), //top +	          y3=turtle.y-15*cos(raddir); +	bresenham(x1,y1,x2,y2,turtlebuf+1,1,2,255); +	bresenham(x2,y2,x3,y3,turtlebuf+1,1,2,255); +	bresenham(x3,y3,x1,y1,turtlebuf+1,1,2,255); +	turtleimage->uncache(); +	window->redraw(); +} + +  void maincallback(Fl_Widget*,void*){  	if(Fl::event()==FL_SHORTCUT&&Fl::event_key()==FL_Escape)return;  	exit(0);  } -void cmdinputcallback(Fl_Widget *wid){ -	Fl_Input *inp=(Fl_Input*)wid; -	histbrowser->insert(histbrowser->size(),inp->value()); -	histbrowser->bottomline(histbrowser->size()); -	logocommand(inp->value()); -	inp->value(NULL); -} -  void evaluatebuttoncallback(Fl_Widget*){ +	if(cmdinput->value()[0]=='\0')return;  	histbrowser->insert(histbrowser->size(),cmdinput->value());  	histbrowser->bottomline(histbrowser->size());  	logocommand(cmdinput->value()); @@ -69,28 +115,26 @@ void histcallback(Fl_Widget *wid){  int main(int argc,char **argv){  	window=new Fl_Window(1016,700,"FLogo"); -	Fl_Group::current(0); //manual adding to widgets -	imagebuf=new uchar[WIDTH*HEIGHT*3]; //RGB -	memset(imagebuf,255,WIDTH*HEIGHT*3*sizeof(uchar)); +	imagebuf=new uchar[WIDTH*HEIGHT*4]; //RGB(A) +	memset(imagebuf,255,WIDTH*HEIGHT*4*sizeof(uchar));  	turtlebuf=new uchar[WIDTH*HEIGHT*2]; //GA  	memset(turtlebuf,0,WIDTH*HEIGHT*2*sizeof(uchar));  	drawscroll=new Fl_Scroll(0,0,window->w(),window->h()-150);  		drawimagebox=new Fl_Box(0,0,WIDTH,HEIGHT); -			drawimage=new Fl_RGB_Image(imagebuf,WIDTH,HEIGHT); +			drawimage=new Fl_RGB_Image(imagebuf,WIDTH,HEIGHT,4);  			drawimagebox->image(drawimage); -		drawscroll->add(drawimagebox);  		turtleimagebox=new Fl_Box(0,0,WIDTH,HEIGHT);  			turtleimage=new Fl_RGB_Image(turtlebuf,WIDTH,HEIGHT,2);  			turtleimagebox->image(turtleimage); -		drawscroll->add(turtleimagebox); -	window->add(drawscroll); +	drawscroll->end(); +	drawscroll->scroll_to(max(0,WIDTH-drawscroll->w())/2,max(0,HEIGHT-drawscroll->h())/2); +	drawturtle();  	cmdinput=new Fl_Input(0,window->h()-25,window->w()-150,25);  		cmdinput->when(FL_WHEN_ENTER_KEY|FL_WHEN_NOT_CHANGED); -		cmdinput->callback(cmdinputcallback); -	window->add(cmdinput); +		cmdinput->callback(evaluatebuttoncallback);  	evaluatebutton=new Fl_Button(cmdinput->x()+cmdinput->w(),cmdinput->y(),80,cmdinput->h(),"Evaluate");  		evaluatebutton->callback(evaluatebuttoncallback); @@ -98,7 +142,6 @@ int main(int argc,char **argv){  	histbrowser=new Fl_Select_Browser(0,drawscroll->y()+drawscroll->h(),cmdinput->w(),cmdinput->y()-(drawscroll->y()+drawscroll->h()));  		histbrowser->callback(histcallback); -	window->add(histbrowser);  	histbrowser->add(""); //add blank line  	window->resizable(drawscroll); @@ -0,0 +1,12 @@ +#pragma once + +const int WIDTH=1000,HEIGHT=1000; + +struct Turtle{ +	double x=WIDTH/2,y=HEIGHT/2,dir=0; //dir in degrees, URDL +}; + +extern Turtle turtle; + +void drawturtle(void); +void drawline(int x1,int y1,int x2,int y2);  | 
