summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortomsmeding <hallo@tomsmeding.nl>2015-10-03 14:18:27 +0200
committertomsmeding <hallo@tomsmeding.nl>2015-10-03 14:18:27 +0200
commit0eb6ce70981deb5b711f49c77930c49181f59d95 (patch)
tree8ef4d30734993bd3ee3f95fd08c9573a23baeea8
parent5a93cdaf5d4fcefe664271bb8f233044059f3ad3 (diff)
¯\_(ツ)_/¯
-rw-r--r--engine.cpp73
-rw-r--r--flogo.cpp103
-rw-r--r--flogo.h12
3 files changed, 157 insertions, 31 deletions
diff --git a/engine.cpp b/engine.cpp
index 2f4fb79..7e178ff 100644
--- a/engine.cpp
+++ b/engine.cpp
@@ -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);
+ }
}
diff --git a/flogo.cpp b/flogo.cpp
index 28b754b..acb03ca 100644
--- a/flogo.cpp
+++ b/flogo.cpp
@@ -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);
diff --git a/flogo.h b/flogo.h
new file mode 100644
index 0000000..f5b1065
--- /dev/null
+++ b/flogo.h
@@ -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);