-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathp3.html
1011 lines (906 loc) · 39.3 KB
/
p3.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<!DOCTYPE html>
<html lang="en">
<head>
<title>Code 2 | Projects</title>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<!-- import the webpage's stylesheet -->
<link rel="stylesheet" href="style.css" />
<!-- import the webpage's javascript + jQuery file -->
<script src="/script.js" defer></script>
<script src="jquery-3.4.1.min.js"></script>
</head>
<body>
<div class="nav">
<h1>Code 2</h1>
<ul>
<li>
<a
href="https://docs.google.com/document/d/16yNNHgZIqe3B8W9TLSEBrOSo2KsAF5qVFqkZ8sEh2mc/edit?usp=sharing"
target="blank"
>Syllabus</a
>
</li>
<li>
Projects <a href="p1.html">#1</a> <a href="p2.html">#2</a>
<a href="p3.html">#3</a> <a href="p4.html">#4</a> <a href="p5.html">#5</a>
</li>
<li><a href="events.html">Public Events</a></li>
<li><a href="readings.html">References</a></li>
<!-- <li><a href="people.html">People</a></li> -->
</ul>
</div>
<div class="content">
<h1>Project #3 Generative Fiction</h1>
<div class="full-width-box">
<img
src="https://cdn.glitch.com/5dd99b18-3ebb-45c5-90fb-b4b67dc2e128%2FScreen%20Shot%202020-02-26%20at%201.30.35%20AM.png?v=1582698644405"
/>
</div>
<p>
Image from
<a href="http://www.generative-gestaltung.de/2/">Generative Design</a>
</p>
<p>
“It is very easy to pour 10,000 bowls of plain oatmeal, with each oat
being in a different position and each bowl essentially unique, but it
is very hard to make these differences *matter* to an audience, and be
perceived as truly different in any memorable or thought-provoking way.”
<br /><br />
— @dryman
</p>
<h2>Description</h2>
<p>
For Project #3, you will create a generative short story with a clear
beginning, middle, and end. Your goal is to make a highly re-readable
story that would make your readers (me and your peers) want to re-read
it over and over again. Your story should be at least 750 words
(equivalent to 1.5 pages). Your choice of words, layout, and interaction
should thoughtfully reflect on the structure and greater meaning of the
story.
</p>
<h2>Required Reading</h2>
<p>
(1)
<a
href="https://galaxykate0.tumblr.com/post/139774965871/so-you-want-to-build-a-generator"
>So you want to build a generator…</a
>, Kate Compton
</p>
<h2>References</h2>
<p>
(1)
<a href="https://play.aidungeon.io">AI Dungeon</a>
by Nick Walton, built on GPT-2
<br />
(2)
<a
href="https://github.com/NaNoGenMo/2019/issues?q=is%3Aissue+is%3Aopen+label%3Acompleted"
>NaNoGenMo (National Novel Generating Month) Archive, 2019</a
>
<br />
(3)
<a
href="https://drive.google.com/file/d/0B97d5C256qbrOHFwSUhsZE4tU0k/view"
>The Annals of the Parrigues</a
>, Emily Short — procedurally generated guidebook to a fictional
pseudo-English kingdom, along with a making-of commentary on the process
of generation.
<br />
(4) <a href="https://rednoise.org/rita/gallery.php">RiTa.js Gallery</a>
<br />
(5)
<a href="https://rednoise.org/sketches/Shanshui/">Shanshui</a>, Chen
Qianxun
<br/>
(6)
<a href="https://ianmaclarty.itch.io/if-we-were-allowed-to-visit">If We Were Alllowed to Visit</a>, Ian MacLarty
<br/>
(8)
<a href="https://sophiemallinson.itch.io/the-crying-game">The Crying Game</a>, Sophie Mallinson
</p>
<h2>Resources</h2>
<p>
(1)
<a href="https://github.com/dariusk/corpora">Corpora</a>, Darius Kazemi
and Many Wonderful Contributors
<br />
(2)
<a href="https://apilist.fun/">API List</a> — a public list of
free APIS for programmers
<br />
(3)
<a href="https://creative-coding.decontextualize.com/csv-files/"
>CSV Files (tutorial)</a
>, Allison Parrish
<br />
(4)
<a href="https://rednoise.org/rita/tutorial/index.php"
>Rita.js tutorials</a
>
<br />
(5)
<a
href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String"
>JavaScript Strings</a
>
</p>
<h2>Timeline & Deliverables</h2>
<p>
Feb 26: Submit proposal slideshow for your generative fiction to Canvas.
The proposal should include an overall description of your story and a
narrative diagram showing various versions of the story. Address
conceptual / aesthetic goals as well as technical steps and submit it to
canvas
<br /><br />
March 4: Complete white-boxed version of the project for peer-reading
session. Your sketch should generate a story of at least 750 words.
<br /><br />
March 11: Project due, present in class
</p>
<h2>Submission Guidelines</h2>
<p>
Submit proposal and white-boxed version of your project to Canvas
<br />
Submit your finalized sketch to Canvas as well as the
<a
href="https://glitch.com/edit/#!/join/e915fd2e-b3b1-4189-82ea-fdd5f7d53c3d"
>Project #3 Glitch page</a
>
for presentation purposes
</p>
<h2>Design Constraints</h2>
<p>(1) Your canvas size should be 600px * 600px <br /></p>
<h1>Study Guide</h1>
<h2>
Table of Content
</h2>
<p>
(1) <a href="#basic">Working with Local Data</a><br />
(2) <a href="#join">JavaScript join()</a><br />
(3) <a href="#substring">JavaScript substring()</a><br />
(4) <a href="#input">Bonus Feature: User Input</a><br />
(5) <a href="#external">Working with External Data</a><br />
(6) <a href="#api">Working with API</a><br />
(7) <a href="#rita">RiTa.js</a> <br />
(8) <a href="#trig">Sin() and Cos()</a>
</p>
<div id="basic"><h2>Working with Local Data</h2></div>
<h3>
Loading & Displaying Data
</h3>
<p>
<a href="https://p5js.org/reference/#/p5/loadTable">loadTable()</a>
is a p5 function that reads the contents of a CSV file and creates a
<a href="https://p5js.org/reference/#/p5.Table">p5.Table</a> object with
its values. The CSV file must either be located in the sketch's folder
or elsewhere online.
</p>
<div class="full-width-box">
<img
src="https://cdn.images.fecom-media.com/HE1546624_160911-HOP-ENG-P01.jpg?width=348"
/>
</div>
<p>
Using loadTable() with a local CSV file, let's try to recreate the
"sentence flip book" children often use to learn how to construct
sentences. First, open your desktop spreadsheet software (e.g. Excel) or
Google spreadsheet, and let's create a couple possible sentences for the
flip book. In the example below I'm using a name, a verb, and a food
item to construct every sentence. Keep in mind that these sentences must
follow the rules of modular design, so that different combinations of
the words would still make out logical sentences.
</p>
<p>
Once you're done with that, download the spreadsheet as a CSV file, and
upload it to your p5 sketch folder. When you click on the CSV file
inside the p5 editor, you should see something like this:
</p>
<div class="full-width-box">
<img
src="https://cdn.glitch.com/5dd99b18-3ebb-45c5-90fb-b4b67dc2e128%2FScreen%20Shot%202020-02-26%20at%201.25.08%20AM.png?v=1582698317988"
/>
</div>
<p>
If you look carefully, you might notice that every new line creates a
new row, and every comma creates a new column. You can edit your CSV
file inside the editor if you decide that something needs to change.
</p>
<p>
Great! Now let's load the table into the sketch! Just like loading any
other files in p5, you need to load the CSV file using
<i>function preload()</i>. Also, inside the p5.Table object, there are a
couple methods you should know about in order to properly load and
display the data:
</p>
<ul>
<li class="bullet">
<a href="https://p5js.org/reference/#/p5.Table/getString"
>getString(row, column)</a
>: retrieves a String value from the Table's specified row and column.
Based on the example above, <i>getString(0,0)</i> will retrieve the
word "Anshuman", and <i>getString(3,2)</i> will retrieve "dumplings"
</li>
<li class="bullet">
<a href="https://p5js.org/reference/#/p5.Table/getColumnCount"
>getColumnCount()</a
>
or
<a href="https://p5js.org/reference/#/p5.Table/getRowCount"
>getRowCount()</a
>: returns the total number of columns or rows in a Table. It's used
in a similar way as array.length
</li>
</ul>
<div class="full-width-box">
<iframe src="https://editor.p5js.org/xinxin/embed/hb73hbbK"></iframe>
<p>↳ click to randomize sentence</p>
<p>
To put it all together, I have used <i>random()</i> to generate three
different row numbers within the range of <i>getRowCount()</i> at the
start of the sketch as well as when every time mouse is pressed. And I
use <i>text()</i> three times to load the possible sentences
individually:
</p>
</div>
<div class="full-width-box">
<script src="https://gist.github.com/xinemata/aacbce3f23bcddff8b82b8380c7987e5.js"></script>
</div>
<a href="https://editor.p5js.org/xinxin/sketches/hb73hbbK"
>Link to Source Code</a
>
<p>
So while you're trying this out on your own, you might have noticed that
a couple lines are being repeated a couple different times to do similar
things. You could try to combine them into for Loops to write less lines
of code. However, you'd need to turn your <i>row1</i>, <i>row2</i>, and
<i>row3</i> variables into a <i>row[]</i> array in order to load them
properly. Here's the
<a href="https://editor.p5js.org/xinxin/sketches/n_1zbjwh"
>optimized version</a
>
of the code above.
</p>
<h3>
Overwriting Data
</h3>
<p>
Now that we know how to load data from a CSV file and turn it into a
p5.Table object. Let's learn how to overwrite a cell value inside a
table object using
<a href="https://p5js.org/reference/#/p5.Table/set"
>set(row, column, value)</a
>. Add the lines below to the end of setup() inside the previous code
example:
</p>
<script src="https://gist.github.com/xinemata/ffe3e8bd8d75785e21a245380834581b.js"></script>
<p>
Now when you click on the screen, you should see that column 0 - row 0
has now been set to "Chloe":
</p>
<iframe src="https://editor.p5js.org/xinxin/embed/SBGCIRZo"></iframe>
<a href="https://editor.p5js.org/xinxin/sketches/SBGCIRZo"
>Link to Source Code</a
>
<p>
There are
<a href="https://p5js.org/reference/#/p5.Table">many other methods</a>
you could use under p5.Table that goes beyond what has been mentioned
above. Take a look at them to get a sense of what's possible.
</p>
<div id="join">
<h2>
JavaScript join()
</h2>
</div>
<p>
In the examples above, each word has a position X and Y. What if we want
to connect the words together so that there are no spacings in between?
This is where
<a
href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/join"
>JavaScript join()</a
>
comes in handy. join() is a method that connects all the items inside an
array together to form a string. For instance, copy & paste the code
below into your p5 editor:
</p>
<script src="https://gist.github.com/xinemata/c9be3e001d14eda3b34b1b6657939a95.js"></script>
<p>
Now try to replace <i>sentence.join(" ")</i> to
<i>sentence.join("-")</i>:
</p>
<script src="https://gist.github.com/xinemata/7b896ff92dfb127dda6ee5e31eb288f7.js"></script>
<p>
You will see that console now prints 'I-<3-programming'. Essentially,
join() makes all the items inside an array hold hands with each other!
</p>
<p>
Next, let's add join() and splice() to our previous example, so that
when mouse is pressed, splice() will add sentences to an empty array,
and join() will help to format the sentence.
</p>
<iframe src="https://editor.p5js.org/xinxin/embed/Mqn01a4f"></iframe>
<p>↳ click to add sentence to the array</p>
<script src="https://gist.github.com/xinemata/5105f0f6f122081e05a3b4ff2fade9b7.js"></script>
<a href="https://editor.p5js.org/xinxin/sketches/Mqn01a4f"
>Link to Source Code</a
>
<div id="substring">
<h2>
JavaScript substring()
</h2>
</div>
<p>
The
<a
href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/substring"
>substring()</a
>
method lets you access and load part of a string. The method takes up to
two parameters: the start of the index and the end of the index. By
using this method, we could create a typewriter effect inside our
sketch. This makes the reading experience more engaging and less
daunting, especially when you're displaying a large amount of texts:
</p>
<iframe src="https://editor.p5js.org/xinxin/embed/_HvJLGKo"></iframe>
<p>↳ click to see the typewriter effect</p>
<script src="https://gist.github.com/xinemata/8b4534d0d9de9cb84aa216715fa85270.js"></script>
<a href="https://editor.p5js.org/xinxin/sketches/_HvJLGKo"
>Link to Source Code</a
>
<div id="input">
<h2>
Bonus Feature: User Input
</h2>
</div>
<p>
If you want to incorporate user's input, such as a character's name into
the story, you could add a text field using
<a href="https://p5js.org/reference/#/p5/createInput">createInput()</a>
and a button using
<a href="https://p5js.org/reference/#/p5/createButton"
>createButton()</a
>
for text submission. This get into accessing the
<a href="https://www.w3schools.com/whatis/whatis_htmldom.asp"
>HTML DOM</a
>, which will be covered extensively in the next project. So don't worry
if you feel like you don't completely understand how it works on the
backend for now.
</p>
<p>
Let's start by creating a button that will let us randomize the
background color every time it's pressed. The first step is to simply
create the button, and make the button display a string to indicate what
it does:
</p>
<script src="https://gist.github.com/xinemata/4f8dcad2b1ed8ad6ceb9330cc4fcb1ca.js"></script>
<p>
Now you've got a clickable button, but the button doesn't do anything
yet. So let's add another line of code inside setup() that will make the
button executes a function:
</p>
<script src="https://gist.github.com/xinemata/866f46be751d4b406c23698019a5c081.js"></script>
<p>
And let's create <i>function changeBG()</i> and define what is supposed
to happen when the function is executed:
</p>
<script src="https://gist.github.com/xinemata/17e2c36df1d3b740866d1762637db347.js"></script>
<p>
Neat! Now when you pressed the button, it should randomly changes the
background color. Next, let's change the position of the button so that
it's overlapped with the sketch. For this, you would have to go to your
style.css file inside the data folder. Add the following lines to the
file:
</p>
<script src="https://gist.github.com/xinemata/75bbcec2408f59e26d8d215c64c5b2ae.js"></script>
<p>
Your sketch should looks like this:
</p>
<iframe src="https://editor.p5js.org/xinxin/embed/8fbpy54r"></iframe>
<a href="https://editor.p5js.org/xinxin/sketches/8fbpy54r"
>Link to Source Code</a
>
<p>
There are many other options for styling the CSS button. You can learn
more about them
<a href="https://www.w3schools.com/css/css3_buttons.asp">HERE</a> and
try it out in your sketch.
</p>
<p>
Next, let's add a text field so that when the user enters their name
into the program, it will be stored inside an array. Besides the text
field, we also need a button so that the user can submit their text.
Let's start by creating the variables:
</p>
<script src="https://gist.github.com/xinemata/c351e8f9203dc872d9976e11c5a58a34.js"></script>
<p>And then create the text field and the button inside setup():</p>
<script src="https://gist.github.com/xinemata/65af232a76410535eda9f17f2da617ee.js"></script>
<p>
The next step is to create a function called <i>addName</i>, and use
splice() to add a new name into our empty array every time
<i>function addName()</i> is executed.
</p>
<script src="https://gist.github.com/xinemata/ada2ba5262b2054f0606bf56c6e4e78d.js"></script>
<p>
Try to enter a couple names into the text field. Because we've set
splice() to delete one item every time it's executed,, you should see
the new name replacing the old name. Now let's display this information
inside draw():
</p>
<script src="https://gist.github.com/xinemata/a0804f6ec33ce651f6ffc83ad5a9a1fa.js"></script>
<p>
And finally, let's style the text field and the button inside style.css
so that they would be overlapped with the sketch. You can take a look at
<a href="https://www.w3schools.com/css/css_form.asp">CSS Forms</a> to
learn more about styling the text field.
</p>
<script src="https://gist.github.com/xinemata/97d3257f7803dca58996320cf60af4a2.js"></script>
<p>
Your sketch should look like this:
</p>
<iframe src="https://editor.p5js.org/xinxin/embed/vXKDpa-S"></iframe>
<a href="https://editor.p5js.org/xinxin/sketches/vXKDpa-S"
>Link to Source Code</a
>
<div id="external"><h2>Working with External Data</h2></div>
<p>
Working with external data is a huge topic. There are endless amount of
data on the internet we could possibly draw from, and the topic of your
story could really determine what kind of data you would be searching
for. As of today, CSV, XML, and JSON are the most commonly seen data
format on the web. CSV is older and still widely used in the fields of
science, while JSON is newer and widely used in commercial applications.
</p>
<h3>
Intro to JSON
</h3>
<p>
JSON stands for JavaScript Object Notation. It was derived from
JavaScript and therefore looks
<a
href="https://medium.com/@easyexpresssoft/object-literal-vs-json-7a2084872907"
>similar</a
>
to a JavaScript object literal, however JSON is an independent data
format and uses the extension name <b>.json</b>! I'm not expecting you
to become a fluent JSON programmer through this project, however, since
JSON is going to be one of the most common data format you will be
encountering online, let's learn about the basic JSON syntax so that we
are not totally lost when we encounter this type of external data.
</p>
<p>
Let's say I'd like to create a profile for a cat I've met in Portland,
Oregon last summer. On a spreadsheet it would look like this:
</p>
<div class="full-width-box">
<img
src="https://cdn.glitch.com/5dd99b18-3ebb-45c5-90fb-b4b67dc2e128%2FScreen%20Shot%202020-03-04%20at%201.49.17%20AM.png?v=1583304565741"
style="height:70px"
/>
</div>
<p>
As a JavaScript object literal it would look like this:
</p>
<script src="https://gist.github.com/xinemata/07c53dc8c07663d35dc3344d4de0ef38.js"></script>
<p>
And as a JSON object it would look like this:
</p>
<script src="https://gist.github.com/xinemata/e2c33296f3587ae5dd56ead2ef981c81.js"></script>
<p>
The outer pair of curly brackets (line 1 & 10) indicate the begining and
closing of the JSON object; and the inner pair of curly brackets (line 3
& 9) indicate an object within an object.
</p>
<p>
Next, let's take a look at Darius Kazemi's wonderful project
<a href="https://github.com/dariusk/corpora">Corpora</a>, a repository
of JSON files containing words ranging from the animals to the
government. Let's use the
<a
href="https://raw.githubusercontent.com/dariusk/corpora/master/data/animals/cats.json"
>cats.json</a
>
file in the repository for our next example. Similar to loading the CSV
file, we're going to load the JSON file in p5 preload() using
<a href="https://p5js.org/reference/#/p5/loadJSON">loadJSON()</a>:
</p>
<script src="https://gist.github.com/xinemata/90b2500556fd77bf3e98f955d6ee6832.js"></script>
<p>
When <i>catObj</i> gets printed into your console, you should see that
there is an array called <i>cats</i> living inside the JSON object. This
is an important piece of information that would help us access the
specific cats inside the array in the next step.
</p>
<div class="full-width-box">
<img
src="https://cdn.glitch.com/5dd99b18-3ebb-45c5-90fb-b4b67dc2e128%2FScreen%20Shot%202020-03-04%20at%202.09.15%20AM.png?v=1583305765096"
/>
</div>
<p>
Now we can use a dot operator to access deeper layers of the JSON file:
</p>
<script src="https://gist.github.com/xinemata/6dd012fd280b56d563e95108b39a473c.js"></script>
<p>
Here's a developed version of the sketch that would choose a random cat
from the list and use it inside a sentence:
</p>
<iframe src="https://editor.p5js.org/xinxin/embed/Q7yUr-WB"></iframe>
<div class="full-width-box">
<script src="https://gist.github.com/xinemata/3037a89f3ae91edbaaa07e78ecc6baa2.js"></script>
</div>
<p>
The entirety of JSON syntax is basically made up of objects {} and
arrays []. The basic idea is simple but the structure could get really
complicated when the amount of data is large. If you're interested in
learning more, read about nested arrays and nested objects
<a
href="https://www.digitalocean.com/community/tutorials/an-introduction-to-json"
>here</a
>.
</p>
<div id="api">
<h2>
Working with API
</h2>
</div>
<h3>
What is an API?
</h3>
<p>
API stands for application programming interface. It consists of
pre-written commands that allow two different pieces of software to
speak to one another. Allegorically, API is like a
<a href="https://youtu.be/w224x9Z4YYs?t=3">bird whistle</a>
that helps human (software 1) to communicate with birds (software 2).
When we work with an API over the web, we are most likely trying to
retreive some form of data from a server into our p5 sketch. For
example, let's say we would like to retreive live weather data from the
<a href="https://openweathermap.org/">Open Weather Map</a>. In order to
do this, we need to check whether it's got an API, and most importantly,
whether the API is well documented with clear instructions for how to
use it. You should refrain from using an API that has vague
instructions.
</p>
<h3>
What is an API key?
</h3>
<p>
In order to proceed with your API journey safely, you need an API key.
You can think of an API key as a password that has been randomly
generated for you by the server in order for you to access its database.
Every time your program runs, you'd be making a request to the server to
send data over. Before the server sends the data back to you it would
asks for your API key. Usually, you would generate a new API key for
every software you create. And you can cancel / delete the API key when
the software is no longer in use. A more detailed explanation can be
found in this video:
</p>
<p>
Next, walk through the process of
<a href="https://openweathermap.org/price">signing up</a> and obtaining
an API key from Open Weather Map. And let's move into p5 editor to
implement the API!
</p>
<h3>
Implementing the API
</h3>
<p>
Take a look at the
<a href="https://openweathermap.org/current">instruction</a> for making
an API call on Open Weather Map, and you should see that this is how
you'd make an API call (just like a bird call!):
</p>
<p>
api.openweathermap.org/data/2.5/weather?q={city name}&appid={your api
key}
</p>
<p>
When you adapt the call for your own use, you need to swap
<i>{city name}</i> to the name of your city (e.g. New York) and
<i>{your api key}</i> to your API key. Paste the line into the URL field
inside your browser and you should see raw JSON data that shows the most
updated information on the current weather. Amazing!
</p>
<p>
Now let's take this info into p5. First, we'll use a variable to hold
the URL for our API call. And we'll load in using loadJSON():
</p>
<script src="https://gist.github.com/xinemata/90c3d7a9b91c3ff7b568dea420509f1f.js"></script>
<p>
Next, let's create a function called <i>getData</i>. This function will
handle the JSON object that is retrieved when setup() is executed.
</p>
<script src="https://gist.github.com/xinemata/409d156e80c3e77a37dba0d0735c72b6.js"></script>
<p>
Now, when you print <i>data</i> inside <i>getData()</i>, you should see
the JSON data inside the console. Use dot notation to access deeper
layers of the data. For instance:
</p>
<div class="full-width-box">
<script src="https://gist.github.com/xinemata/1b851837667b9f8fcad930d3cca3575c.js"></script>
</div>
<iframe src="https://editor.p5js.org/xinxin/embed/J0jvg0x-"></iframe>
<a href="https://editor.p5js.org/xinxin/sketches/J0jvg0x-"
>Link to Source Code</a
>
<p>
Here is another example of an API implementation, using
<a href="https://developer.wordnik.com/">Wordnik's API</a>. It lets you
access various types of dictionary data:
</p>
<iframe src="https://editor.p5js.org/xinxin/embed/ShxivblX"></iframe>
<a href="https://editor.p5js.org/xinxin/sketches/ShxivblX"
>Link to Source Code</a
>
<div id="rita">
<h2>
RiTa.js
</h2>
</div>
<p>
RiTa.js is a powerful external JavaScript library that is made for
creating digital literature. It is connected to a lexicon and can do
things such as generating verbs, nouns, and adjectives; generating words
that sound similar to each other or rhymes with one another. RiTa.js is
a good way to add a cherry on the top of your generative story, but it
isn't a good tool to create your entire story — it's your job to
do that.
</p>
<p>
The first step is to load RiTa.js in the p5 editor. Visit
<a href="https://cdnjs.com/libraries/rita"
>https://cdnjs.com/libraries/rita</a
>
and copy the URL for the version of RiTa.js you'd like to use for the
sketch. You might notice that the page is hosted by
<a href="https://cdnjs.com/">cdnjs</a>, this is an open-source,
community-driven project that hosts all the popular libraries online so
that you do not need to manually download them to your sketch folder.
You can learn more about CDN
<a href="https://www.cloudflare.com/learning/cdn/what-is-a-cdn/">here</a
>.
</p>
<p>
Let's create a new sketch and open your index.html file. Right
underneath the <i><head></i> tag let's add this line:
</p>
<script src="https://gist.github.com/xinemata/11c740c27049219f62c60f542a7a4519.js"></script>
<p>
Congratulations! You have just added a new JavaScript library into your
program! Now visit the
<a href="https://rednoise.org/rita/reference/index.php"
>reference page</a
>
for RiTa.js and see what you could do with it.
</p>
<h3>
RiTa.similarBySound
</h3>
<p>
<a
href="https://rednoise.org/rita/reference/RiTa/RiTa.similarBySound/index.php"
>RiTa.similarBySound()</a
>
lets you enter a word and it would return with all the words in the
lexicon that sound similar. For example, I have enetered the word "code"
into the program and this is the output:
</p>
<iframe src="https://editor.p5js.org/xinxin/embed/b583wxH4"></iframe>
<p>
Here is the source code for my sketch:
</p>
<script src="https://gist.github.com/xinemata/941828434e6007523708b3ca4d7aaf7a.js"></script>
<div id="trig">
<h2>
Sin() and Cos()
</h2>
</div>
<h3>
Polar Coordinates System
</h3>
<p>
Before getting into sin() and cos(), we need to first learn about a
different kind of coorinates system called the polar coordinates system.
So far we have only been using the Cartesian coordinate system to define
positions on a canvas. For instance, if your friend is looking for you
in Union Sq, you can describe your x, y positions using the Cartesian
coordinates:
</p>
<div class="full-width-box">
<img
src="https://cdn.glitch.com/5dd99b18-3ebb-45c5-90fb-b4b67dc2e128%2FCode%202%20Project%20%233%20(1).jpg?v=1583618624773"
/>
</div>
<p>
There is however another way to describe positions by using something
called the polar coordinates system. Polar coordinates take two
parameters — distance and degrees. So instead of telling your
friend that you are at -3 units on the x-axis and 2 units on the y-axis,
you could also say that you are located at 150 degrees and 2 units away
from the center:
</p>
<div class="full-width-box">
<img
src="https://cdn.glitch.com/5dd99b18-3ebb-45c5-90fb-b4b67dc2e128%2FCode%202%20Project%20%233.jpg?v=1583618604181"
/>
</div>
<p>
The syntax for polar coordinates then is (distance, degrees). The degree
parameter here is also known as theta, represented by the symbol θ.
</p>
<h3>
Polar to Cartesian Conversion
</h3>
<p>
When we need to animate something along the radial path, it's much
easier to think about the drawing in polar coordinates terms. However
p5.js only understands Cartesian coordinates, therefore we need to
convert polar coordinates into Cartesian coordinates using the following
equations:
</p>
<h5>x = r * cos(theta);<br />y = r * sin(theta);</h5>
<p>
r here stands for radius. And when you pair up x with cos() and y with
sin(), you're able to animate on the degree axis in the clock-wise
direction:
</p>
<iframe src="https://editor.p5js.org/xinxin/embed/pGbcPi0M"></iframe>
<div class="full-width-box">
<script src="https://gist.github.com/xinemata/3bfe39a648ecb96bbb98ce9009c13ad7.js"></script>
</div>
<a href="https://editor.p5js.org/xinxin/sketches/pGbcPi0M"
>Link to Source Code</a
>
<p>
Now that you've learned the standard equations to move something in a
circular motion, try tweaking the code example above in the following
ways and compare different results:
</p>
<ul>
<li class="bullet">
Replace cos() to sin() and sin() to cos() inside the code
</li>
<li class="bullet">
Replace all the cos() inside the code to sin()
</li>
<li class="bullet">
Replace all the sin() inside the code to cos()
</li>
</ul>
<p>
What has happened and why is it happening? What are these strange things
called sine and cosine? Let's take a deeper look into what's happening
behind the scene.
</p>
<h3>Sine and Cosine</h3>
<p>
The most difficult part of learning sine and cosine is coming to
understand that these terms are used to describe the relationship
between two sides of a triangle — they are not something directly
observerable on the canvas.
</p>
<div class="full-width-box">
<img
src="https://www.mathsisfun.com/algebra/images/sin-cos-tan.svg"
style="height: 180px"
/>
</div>
<p>
If that's already sounding extremely obscure to you, try to go through
this brilliant excercise on
<a href="https://www.mathsisfun.com/sine-graph-exercise.html"
>Math is Fun</a
>. What you should learn by the end of the excercise, is that sine wave
essentially offers a set a numbers to us that infinitely between 1 and
-1. And we could utilize this set of numbers to draw things on circular
or wavy paths.
</p>
<div class="full-width-box">
<img
src="https://upload.wikimedia.org/wikipedia/commons/3/3b/Circle_cos_sin.gif"
style="height:200px"
/>
</div>
<p>
Cosine, on the other hand also offers a set of numbers between 1 and -1
for us to use in our code. Observe the image above to see the different
wave forms and positions produced by sine and cosine under the same
theta.
</p>
<p>
In the previous example code, when x is combined with cos() and y is
combined with sin(), you get to draw things in a clock-wise, circular
motion. And when x is combined with sin() and cos() is combined with y,
you get to draw things in a counter-clock-wise, circular motion. Here's
a sketch that combines all the possible ways to plot cos() and sin()
into x and y. Comparing the similarities and differences between them
might help you gain a deeper understnding on how to use them:
</p>
<iframe src="https://editor.p5js.org/xinxin/embed/G-s5N2LG"></iframe>
<a href="https://editor.p5js.org/xinxin/sketches/G-s5N2LG"
>Link to Source Code</a
>
<h3>
Text Along the Curve
</h3>
<div class="full-width-box">
<iframe src="https://editor.p5js.org/xinxin/embed/okGMvmxM"></iframe>
<a href="https://editor.p5js.org/xinxin/sketches/okGMvmxM"
>Link to Source Code</a
>
</div>
<p>
Now that we've learned the basics of drawing things on the radial path
using sin() and cos(), let's use this knowledge to draw text along a
curve so that we can create a more surprising and engaging reading
experience for our readers.
</p>
<p>
Let's start with a simple example of placing text around a circle.
First, we need to use
<a
href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/split"
>JavaScript split()</a
>
to break the string into an array of chars.
</p>
<script src="https://gist.github.com/xinemata/2ca3329e59c0b9b39080e728861b251c.js"></script>
<p>
Next, let's use the polar - cartesian conversion equations to draw each
of the item in <i>sentenceArray</i>:
</p>
<script src="https://gist.github.com/xinemata/a2fd6ce0eb32bb7f9d794f91c96a1338.js"></script>
<p>
When you hit play, you should see all the letters from the array
overlapping on top of one another. We need to add a rotate() inside the
for Loop to rotate each letter in place:
</p>
<script src="https://gist.github.com/xinemata/d917308fa389c9eb0cd1a0fee6a150e5.js"></script>
<p>
Now, your sketch should looks like
<a href="https://editor.p5js.org/xinxin/sketches/l4qTy6fV">THIS</a>.
We're getting close, however I'd like to rotate each of the individual
letters so that the bottom of each letter would be facing towards the
center. My intuition tells me that we need to use a push() and pop() in
here in order to do that. And also it would make things a lot cleaner,
if the x and y positions for our text are (0,0). Let's do a small
reinvention of our existing code based on these guesses:
</p>
<script src="https://gist.github.com/xinemata/90cafb54b82664d4682b4b63c56a8906.js"></script>
<p>
Try to comment out individual lines in this example code to process how
each line is affecting the outcome. Here is the final output:
</p>
<div class="full-width-box">
<iframe src="https://editor.p5js.org/xinxin/embed/BrpAyJeR"></iframe>
<a href="https://editor.p5js.org/xinxin/sketches/BrpAyJeR"
>Link to Source Code</a
>
</div>
<p>
Using sin() and cos() to draw the curve in your head isn't easy and it
will take a little while to feel like you've comprehended it. The best
way to go forward is to look at the example code, try commenting some
lines out to see how they work. And try building your own through an
iterative process — start with a simple sketch and add
complexities through revisions. Here are a couple more examples that
were built off of the last example:
</p>
<div class="full-width-box">
<iframe src="https://editor.p5js.org/xinxin/embed/bRIrVRT5"></iframe>
<a href="https://editor.p5js.org/xinxin/sketches/bRIrVRT5"
>Link to Source Code</a