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); |