Draw a square line by line

I am trying to draw a square one line at a time, with a keypress. In other words, press “1” to draw a line, turn 90 degrees, press “1” to draw a line, turn 90 degrees, etc. I know about the rectangle function. This is just a small part of a bigger project I am working on. Here is the code I have now:

``````int length=10; //length of line segment
int xPos=0;
int yPos=0;
void setup() {
size(500,500);
}

void draw () {
}

void keyPressed() {
translate(xPos, yPos);

if (key == '1') {
line(0,0,1*length, 0);
xPos += 10;
rotate(PI/2);
}
}
``````

It draws the line on the keypress but it doesn’t rotate. When I have used the rotate function without the keypresses aspect it has worked fine. What makes this different?

2 Likes

At the moment you have to press wasd in my code in this order

To change , store the angle and say rotate directly after translate as I suggested

1 Like

oh, it’s harder than I thought…

I am sorry

1 Like

OLD version - new version below

Turtle program.

Use wasd keys.

• The movement is always seen relative from the Turtle perspective.
• w is forward, a is left, d is right, s is backward
• c is reset.
• p Pen up/down.
• l (L) prints the commands (to save).

Chrisir

``````

// A String exec gets recorded (in keyPressed()) and then evaluated (executed) in evaluateInputs().

// https://discourse.processing.org/t/drawing-connected-lines-with-keystroke-commands/17947/5
// with help from Jeremy et al., see https://forum.processing.org/two/discussion/20706/how-3d-turtle-like-in-logo-but-3d-math-problem

final String helpText =
"Turtle program. Use wasd keys. The movement is always seen relative from the Turtle perspective. w is forward, a is left, d is right, s is backward, c is reset. p Pen up/down. l (L) prints the commands (to save).";

final color BLACK = color(0);
final color RED = color(255, 0, 0);

// For the Turtle:
int lineSegment=30; //length of line segment

String exec=""; // A String exec gets recorded (in keyPressed()) and then evaluated (executed) in evaluateInputs().
boolean penUp=false; // when the pen is up (true), it is not touching the ground, the Turtle is not drawing. penUp = false means the Turtle draws.

// For the User Interface (UI):
boolean showHelp = true; // show help text / UI

//----------------------------------------------------------------------------

void setup() {
size(1500, 500);
background(111);

println(helpText);
}

void draw() {
//
background(111);

// Help text
if (showHelp) {
fill(0);
text(helpText,
17, 17);
text(penUpText(),
width-135, 17);
}

translate(width/2, height/2);
rotate(-HALF_PI);
penUp=false;

evaluateInputs();

if (showHelp) {
// show Turtle
noFill();
stroke(RED);
ellipse(0, 0, 6, 6);
}
}

//----------------------------------------------------------------------------

void keyPressed() {
// wasd
if (key == 'w' ||
key == 'a'  ||
key == 's'  ||
key == 'd' ||
key == 'p' ) {
// record keys ----
exec += key;
//
} else if (key=='c') {
// clear
println(exec);
exec="";
} else if (key=='l') {
// print
println(exec);
} else if (key==' ') {
// showHelp
showHelp = !showHelp;
}
}

//----------------------------------------------------------------------------

void evaluateInputs() {

// eval the recorded String
for (int i=0; i < exec.length(); i++) {
// println (exec.charAt(i));

// the line color is between black and red
float amtValue = map( i,
0, exec.length(),
0, 1);
stroke(lerpColor(BLACK, RED, amtValue));

switch (exec.charAt(i)) {
//
case 'w':
tLine(lineSegment);
break;

case 's':
tLine(-lineSegment);
break;

case 'a':
rotate(-HALF_PI);
tLine(lineSegment);
break;

case 'd':
rotate(HALF_PI);
tLine(lineSegment);
break;

case 'p':
penUp = !penUp;
break;
}//switch
}//for
}//func

// ------------------------------------------------------------------------------

void tLine(int x) {
if (penUp)
tStep(x);
else
tLineDraw(x);
}

void tLineDraw(int x) {
// draw and move
line(0, 0,
x, 0);
translate(x, 0);
}

void tStep(int x) {
// just move (if pen is up)
translate(x, 0);
}

// ------------------------------------------------------------------------------

String penUpText() {
if (penUp)
return"Turtle only moves.";
else
return"Turtle draws: Pen down.";
}//func
//
``````

Here is a full blown version with wasd and many other things

Turtle program.

• Escape key brings you this help.
• X leave program (Shift-x).
• Space bar - small text in the main program on / off.
• l (L) prints the commands (to save).
• c is reset / delete all.
• Backspace - undo last step(s)
• Cursor keys - move the entire canvas (useful when you reached a screen border)
• S - save (shift-s) (with date and time stamp)

The following keys control the Turtle and get recorded

• Use wasd keys. The movement is always seen relative from the Turtle perspective. w is forward, a is left, d is right, s is backward, seen from the Turtle.
• p Pen up / down. Useful when you want to move the Turtle to another place on the screen without drawing.
• Use r(ed), g(reen) and b(lue) and v (black) and n (white) for the color the Turtle draws.
• Use + / - for Stroke Weight.

Chrisir

``````
// A String turtleCommandString gets recorded (in keyPressed()) and then evaluated (executed) in evaluateInputs().
//
// Keys:
//    Escape = HELP
//    Space Bar
//    wasd / Backspace / c
//    r g b Colors
//    v / n colors
//    many more.... see Help.

// https://discourse.processing.org/t/drawing-connected-lines-with-keystroke-commands/17947/5
// with help from Jeremy et al., see https://forum.processing.org/two/discussion/20706/how-3d-turtle-like-in-logo-but-3d-math-problem

// To Do / Wishes :
//    Edit command Strings / copy paste
//    3D
//    Splash Screen
//    Color Selector
//    change of length of lineSegment

final String helpText =
"Turtle program. Use wasd keys. The movement is always seen relative from the Turtle perspective. w is forward, a is left, d is right, s is backward, c is reset. p Pen up/down. Esc for Help.";

final String helpTextLong =
"Turtle program. "
+"\n\nEscape key brings you this help. "
+"\nX leave program (Shift-x).\n"
+"Space bar - small text in the main program on / off.\n"
+"l (L) prints the commands (to save).\n"
+"c is reset / delete all."
+"\nBackspace - undo last step(s)"
+"\nCursor keys - move the entire canvas (useful when you reached a screen border)"
+"\nS - save (shift-s) (with date and time stamp)"

+"\n\n\nThe following keys control the Turtle and get recorded \n"
+"\n"

+"Use wasd keys. The movement is always seen relative from the Turtle perspective. w is forward, a is left, d is right, s is backward, seen from the Turtle. "
+"\np Pen up / down. Useful when you want to move the Turtle to another place on the screen without drawing."
+"\nUse r(ed), g(reen) and b(lue) and v (black) and n (white) for the color the Turtle draws."
+"\nUse + / - for Stroke Weight.   \n\n \n\n"
+"Hit Escape key to leave the help.";

final color BLACK  = color(0);
final color WHITE  = color(255);

final color RED    = color(255, 0, 0);
final color GREEN  = color(0, 255, 0);
final color BLUE   = color(0, 0, 255);

// states
final int NORMAL_STATE = 0;
final int HELP_STATE   = 1;
int state = NORMAL_STATE;

// For the Turtle:
color colorTurtle = WHITE; // initial color - see Help
int strokeWeightTurtle=1;
int lineSegment   = 30;    //length of line segment
String turtleCommandString = "";     // A String turtleCommandString gets recorded (in keyPressed()) and then evaluated (executed) in evaluateInputs().
boolean penUp=false;  // when the pen is up (true), it is not touching the ground, the Turtle is not drawing. penUp = false means the Turtle draws.

// For the User Interface (UI):
boolean showHelp = true; // show help text / UI
float posCanvasX, posCanvasY;  // change with cursor

//----------------------------------------------------------------------------

void setup() {
size(1500, 900);
background(111);

// println(helpText);
println("");
println(helpTextLong);
}

void draw() {
// Depending on state

switch(state) {

case NORMAL_STATE:
drawForStateNORMAL_STATE();
break;

case HELP_STATE:
drawForStateHELP_STATE();
break;

default:
// Error
break;
//
}//switch
//
}//func

//----------------------------------------------------------------------------
// These functions are called from draw()

void drawForStateNORMAL_STATE() {

// clear all
background(111);

// Help text and text for penUp
showHelpText();

// Init Turtle (reset a few parameters)
translate((width/2) + posCanvasX, (height/2) + posCanvasY);
rotate(-HALF_PI);
penUp=false;
colorTurtle = WHITE; // reset initial color - see Help
stroke(colorTurtle);
strokeWeightTurtle=1;  // reset
strokeWeight(strokeWeightTurtle);

// Eval Input String
evaluateInputs();

// draw Turtle
drawTurtle();
}

void drawForStateHELP_STATE() {
// clear all
background(0);
// show text
fill(255);
text(helpTextLong,
17, 17);
}

//----------------------------------------------------------------------------
// Inputs

void keyPressed() {

switch(state) {

case NORMAL_STATE:
keyPressedForStateNORMAL_STATE();
break;

case HELP_STATE:
keyPressedForStateHELP_STATE();
break;

default:
// Error
break;
//
}//switch
//
}//func

// These functions are called from keyPressed()

void keyPressedForStateHELP_STATE() {
// Esc
if (key==ESC) {
key=0;
state = NORMAL_STATE;
}//if
}//func

void keyPressedForStateNORMAL_STATE() {
// Many keys

if (key==CODED) {
switch(keyCode) {
case UP:
posCanvasY--;
break;
case DOWN:
posCanvasY++;
break;

case LEFT:
posCanvasX--;
break;
case RIGHT:
posCanvasX++;
break;
}//switch

// Leave here
return;
} // CODED -----------------------------------------------

// All not coded here:

// wasd etc. - these get recorded
if (key == 'w' ||
key == 'a'  ||
key == 's'  ||
key == 'd' ||

key == 'p' ||

key == 'r' ||
key == 'g' ||
key == 'b' ||

key == 'v' ||
key == 'n' ||
key == '+' ||
key == '-' ) {
// record keys ----
turtleCommandString += key;
//---
} else if (key==BACKSPACE) {
// shorten by 1 (undo)
if (turtleCommandString.length()>0) {
turtleCommandString=turtleCommandString.substring(0, turtleCommandString.length()-1);
}//if
} else if (key=='c') {
// clear
println(turtleCommandString);
turtleCommandString="";
} else if (key=='l') {
// print
println(turtleCommandString);
} else if (key==' ') {
// showHelp
showHelp = !showHelp;
} else if (key=='X') {
// print and quit
println(turtleCommandString);
exit();
} else if (key=='S') {
save(timeStamp()
+".jpg");
} else if (key==ESC||key=='h'||key=='H') {
// Help
key=0; // kill Esc
println(turtleCommandString);
state=HELP_STATE;
} // else if Esc key
//
}//func

//----------------------------------------------------------------------------

void evaluateInputs() {

// eval the recorded String with the Turtle Commands

for (int i=0; i < turtleCommandString.length(); i++) {
// println (turtleCommandString.charAt(i));

/*
// the line color is between black and red
float amtValue = map( i,
0, turtleCommandString.length(),
0, 1);
stroke(lerpColor(BLACK, RED, amtValue));
*/

switch (turtleCommandString.charAt(i)) {
//
case 'w':
tLine(lineSegment);
break;

case 's':
tLine(-lineSegment);
break;

case 'a':
rotate(-HALF_PI);
tLine(lineSegment);
break;

case 'd':
rotate(HALF_PI);
tLine(lineSegment);
break;

case 'p':
penUp = !penUp;
break;

// colors -------

case 'r':
stroke(RED);
colorTurtle = RED;
break;

case 'g':
stroke(GREEN);
colorTurtle = GREEN;
break;

case 'b':
stroke(BLUE);
colorTurtle = BLUE;
break;

case 'v':
stroke(BLACK);
colorTurtle = BLACK;
break;

case 'n':
stroke(WHITE);
colorTurtle = WHITE;
break;

//-------------------

case '+':
strokeWeightTurtle++;
strokeWeight(strokeWeightTurtle);
break;

case '-':
strokeWeightTurtle--;
if (strokeWeightTurtle<0)
strokeWeightTurtle=0;
strokeWeight(strokeWeightTurtle);
break;

//-------------------
//
}//switch
//
}//for
}//func

// ------------------------------------------------------------------------------
// Turtle functions

void tLine(int x) {
// Depending on penUp
// we move or draw
if (penUp)
tStep(x);
else
tLineDraw(x);
}

void tLineDraw(int x) {
// draw and move (pen is down, penUp=false)
line(0, 0,
x, 0);
translate(x, 0);
}

void tStep(int x) {
// just move (if pen is up, penUp=true)
translate(x, 0);
}

void drawTurtle() {
// show the Turtle itself as a triangle
noFill();
stroke(colorTurtle);
ellipse(-2, 0, 2, 2);
line(0, -5, 7, 0);
line(0, 5, 7, 0);
}//func

// ------------------------------------------------------------------------------
// Minor functions

void showHelpText() {
// help text
if (showHelp) {
// help text
fill(0);
text(helpText,
17, 17);
text("Turtle commands: "
+turtleCommandString
+" (Backspace to undo last step(s))",
17, height-17);
// Text for pen up yes / no:
text(penUpText(),
width-135, 17);
// Turtle color
fill(colorTurtle);
text("Turtle color",
width-135, 17*2);
fill(0);
text("Stroke Weight: "+strokeWeightTurtle,
width-135, 17*3);
}
}

String penUpText() {
// Depending on penUp
if (penUp)
return"Turtle only moves.";
else
return"Turtle draws: Pen down.";
}//func

// -----------------------------------------------------------------------------
// Tools: Date and time

String timeStamp() {
+ "_"
+ timeNow () ;
}

String todaysDate () {
int d = day();    // Values from 1 - 31
int m = month();  // Values from 1 - 12
int y = year();   // 2003, 2004, 2005, etc.

String Result =
nf(y, 2)+
nf(m, 2)+
nf(d, 2);
return( Result );
}

String timeNow () {
int h = hour();    // Values from 1 - 23
int m = minute();  // Values from 1 - 60
int s = second();   // 1-60

String Result =
nf(h, 2) + "" +
nf(m, 2) + "" +
nf(s, 2);
return( Result );
}
//
``````
2 Likes

@MichelO – hope you are finding help on the forum!

2 Likes

Thank you again for your generous help. Your turtle program does exactly what I want my program to do. However, I do not understand much of what is in your code. I tried to just paste pieces and edit for what I want my code to do but I am running into some issues. Here is a piece of my code:

``````int lineSeg=10; //length of line segment
int xPos=0;
int yPos=0;
String exec="";  // A String exec gets recorded (in keyPressed()) and then evaluated (executed) in evaluateInputs().

void setup() {
size(500,500);
background(#FFFFFF);
}

//translate
//rotate(-HALF_PI);

void draw () {
translate(width/2, height/2);
rotate (-HALF_PI);
evaluateInputs();
}

void keyPressed() {

if (key == '1' ||
key == '2' ||
key == '3' ||
key == '4' ||
key == '5' ||
key == '6' ||
key == '7' ||
key == '8' ||
key == '9' ||
key == '0' ) {
exec += key; //record keys
}
}

void evaluateInputs() {

for (int i=0; i < exec.length(); i++) {

float amtValue = map (i, 0, exec.length(), 0, 1);

switch (exec.charAt(i)) {

case '1':
rotate(-HALF_PI);
tLine(lineSeg);
break;
``````

I am getting the following error message: “The function tLine(int) does not exist.” Any idea why? From what I can tell, you don’t define it anywhere in your code, but maybe I missed something.

2 Likes

I just checked, it’s at the very end in version 1 and a bit before in version 2

``````// ------------------------------------------------------------------------------
// Turtle functions

void tLine(int x) {
// Depending on penUp
// we move or draw
if (penUp)
tStep(x);
else
tLineDraw(x);
}

void tLineDraw(int x) {
// draw and move (pen is down, penUp=false)
line(0, 0,
x, 0);
translate(x, 0);
}

void tStep(int x) {
// just move (if pen is up, penUp=true)
translate(x, 0);
}

void drawTurtle() {
// show the Turtle itself as a triangle
noFill();
stroke(colorTurtle);
ellipse(-2, 0, 2, 2);
line(0, -5, 7, 0);
line(0, 5, 7, 0);
}//func

// ------------------------------------------------------------------------------
``````
1 Like

The basic idea is from Jeremy and you can read about it on the other discussion (the one I linked to).

Basically we use the translate/ rotate functions to steer the Turtle. The translate and rotate commands add up, hence it moves across the screen

1 Like

Hello,

This may be out of sync with current discussion but sharing nonetheless.

Here is an example that draws 2 of the lines:

``````// Draw a square by rotating lines
// v1.0.0
// GLV 2020-02-28

int length = 50; //length of line segment
int xPos = 0;
int yPos = 0;

int count = 0;

void setup()
{
size(640, 360);
}

void draw()
{
translate(width/4, height/2);

push();
translate(xPos+50*sin(0*TAU/4), yPos+50*cos(0*TAU/4));        // 0, 50
rotate(0*TAU/4);
line(-length, 0, length, 0);
pop();

push();
translate(xPos+50*+sin(1*TAU/4), yPos+50*cos(1*TAU/4));       // 50, 0
rotate(1*TAU/4);
line(-length, 0, length, 0);
pop();

// And so on...
}
``````

I saw patterns (see comments for x,y) and added some trigonometry; this may be advanced but offers another perspective.

This is not complete and I removed the last 2 sides; you can add these.

You will notice a pattern in the factors (0, 1, 2, 3) and can make a for() loop out of this.

Later you can integrate keyPressed().

I was able to write code based on this and draw a square with 4 key presses.

Have fun!

1 Like

Because, how do the movements of the Turtle (cause that’s what it is) add up?

I’d expected you say: xPos+=50; yPos+=0; turtleAngle+=Tau; etc.

In my version they add up, because I don’t use push and pop but just let translate and rotate add up (idea by Jeremy).

I mean, could you draw something like this:

Worked on it a bit, you can save and load now and have a menu

1 Like

here is your version with 1 and 2 key

(and Backspace)

``````//translate
//rotate(-HALF_PI);

final color GREEN = color (0, 255, 0);

int lineSeg=40; //length of line segment
int xPos=0;
int yPos=0;
String exec="";  // A String exec gets recorded (in keyPressed()) and then evaluated (executed) in evaluateInputs().

boolean penUp = false;

color colorTurtle = color(0);

void setup() {
size(500, 500);
background(#FFFFFF);
}

void draw () {
background(#FFFFFF);

fill(0);
text(exec, 17, 17);

// bring Turtle to start position
translate(width/2, height/2);
rotate (-HALF_PI);

// Eval Turtle
evaluateInputs();

// show Turtle
showTurtleItself();
}

// -----------------------------------------------------------------------

void showTurtleItself() {
noFill();
stroke(GREEN);
strokeWeight(2);
ellipse(0, 0, 8, 8);
strokeWeight(1);//reset
}

void keyPressed() {

if (key == '1' ||
key == '2' ||
key == '3' ||
key == '4' ||
key == '5' ||
key == '6' ||
key == '7' ||
key == '8' ||
key == '9' ||
key == '0' ) {
exec += key; //record keys
}
//------------------------
// delete last step
else if (key==BACKSPACE) {
if (exec.length()>0) {
exec=exec.substring(0, exec.length()-1);
}//if
}
}

void evaluateInputs() {

for (int i=0; i < exec.length(); i++) {

float amtValue = map (i, 0, exec.length(), 0, 1);

switch (exec.charAt(i)) {

case '1':
rotate(-HALF_PI);
tLine(lineSeg);
break;

case '2':
rotate(-HALF_PI);
tLine(lineSeg/2);
break;
}
}
}

// ------------------------------------------------------------------------------
// Turtle functions

void tLine(int x) {
// Depending on penUp
// we move or draw
if (penUp)
tStep(x);
else
tLineDraw(x);
}

void tLineDraw(int x) {
// draw and move (pen is down, penUp=false)
line(0, 0,
x, 0);
translate(x, 0);
}

void tStep(int x) {
// just move (if pen is up, penUp=true)
translate(x, 0);
}

void drawTurtle() {
// show the Turtle itself as a triangle
noFill();
stroke(colorTurtle);
ellipse(-2, 0, 2, 2);
line(0, -5, 7, 0);
line(0, 5, 7, 0);
}//func

// --------------------------------------------------------------------------
``````
1 Like

It works! I can’t thank you enough for all of your help!!!

1 Like