-
Notifications
You must be signed in to change notification settings - Fork 0
/
lessons.html
4868 lines (4408 loc) · 431 KB
/
lessons.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>
<!--
Massively by HTML5 UP
html5up.net | @ajlkn
Free for personal and commercial use under the CCA 3.0 license (html5up.net/license)
-->
<html>
<head>
<title>Lessons</title>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no" />
<link rel="stylesheet" href="assets/css/main.css" />
<noscript><link rel="stylesheet" href="assets/css/noscript.css" /></noscript>
</head>
<body class="is-preload">
<!-- Wrapper -->
<div id="wrapper">
<!-- Header -->
<header id="header">
<a href="index.html" class="logo">ARCADE SYSTEM PROJECT</a>
</header>
<!-- Nav -->
<nav id="nav">
<ul class="links">
<li class="active"><a href="index.html">Project homepage</a></li>
<li><a href="lessons.html">Lessons</a></li>
<li><a href="documentation.html">Documentation</a></li>
</ul>
</nav>
<!-- Main -->
<div id="main">
<!-- Post -->
<section class="post">
<header class="major">
<span class="date">October 18, 2019</span>
<h1>Project Lessons</h1>
</header>
<ul>
<li>
<a href="#Lesson0"><b>Lesson 0</b>: Environment Setup</a>
</li>
<li>
<a href="#Lesson1"><b>Lesson 1</b>: Introducing the Menu System/Designing a GUI</a>
</li>
<li>
<a href="#Lesson2"><b>Lesson 2</b>: Using Git and Implementing the Menu System</a>
</li>
<li>
<a href="#Lesson3F"><b>Lesson 3 Fall</b>: Animation and Game Design (Brick Breaker)</a>
</li>
<li>
<a href="#Lesson3W"><b>Lesson 3 Winter</b>: Animation and Game Design (Tetris)</a>
</li>
<li>
<a href="#Lesson4F"><b>Lesson 4 Fall</b>: Animation and Game Design Part 2 (Brick Breaker)</a>
</li>
<li>
<a href="#Lesson4W"><b>Lesson 4 Winter</b>: Animation and Game Design Part 2 (Tetris)</a>
</li>
<li>
<a href="#Lesson5"><b>Lesson 5</b>: Finishing the Game</a>
</li>
</ul>
<hr>
<p><b>Introduction:</b> Welcome to the lessons page of the Virtual Arcade System Software Project! This poject
is a great opportunity to apply object oriented programming in C++. If you are a beginner, don't worry! These lessons
will help guide you through the process of building this project.
</p>
<p>
<b><i>Note: This project does not assume any prior programming experience. However, this is not
an easy project and may require you to spend time reading through these lessons and other resources I have linked if you have
little to no programming experience.</i></b>
<a name="Lesson0"></a>
</br><hr><h2>Lesson 0: Environment setup (completion time: 15 min - 45min)</h2>
<i>For terms or concepts that may require additional explanation, I have provided clickable links to simple articles that provide more detail.</i>
<br></br>
<b>Overview:</b> Before we do anything, we need to set up an environment in which we can program in. This step is very important,
so please read and follow every instruction carefully. This setup can be very frustrating if you
miss a step or something goes wrong so please be patient and email me with any questions.
</p>
<h4>1. Downloading a code editor</h4>
No matter what language you use, when building a software project you need an environment where you can write code. For this project
we will be using Visual Studio Code which is a free code editor with tools and extensions that will help us build our project. Follow <a href="https://code.visualstudio.com/download" target="_blank">this link</a>
and download the according version (Windows or Mac).<br></br>
<ul>
<li>On <b>Windows</b>, an installation setup wizard should pop up (if not it will appear as something similar to "VSCodeUserSetup-x64-1.38.1.exe" in your downloads folder, double click it). Just hit next through the setup
and leave the default settings unless you want to configure the installation in a certain way.</li>
<li>On <b>Mac</b> it should show up in your downloads as a .zip. Double click on this to extract the archive. Move the Visual Studio Code application into
your applications folder and then open up the app.</li>
</ul>
<h4>2. Configuring Visual Studio Code for C++</h4>
After installing Visual Studio Code we need to configure it so that we can develop in C++. Open it up if you haven't already and click the extensions icon (under the debug icon) in the left side bar.
Search for C++, click the first extension, and install it as shown in this image. <img src="images/extensions_img.jpg" alt="" style="float: left; width: 100%; margin-right: 1%;">This extension helps us write C++ code but does not come with a C++ compiler.
A compiler is a program that takes our C++ code and translates it into lower level "object code" which we will use to make an executable program. </br><b><i>For a better explanation of a compiler <a href="https://www.coronadoenterprises.com/tutorials/cpp/cpp_ans.html" target="_blank">click here</a></i></b>. </br>Setting up Visual Studio Code with a C++
compiler will be different based on your OS so follow the steps based on your computer.
<br></br><h4>3. Setting up Visual Studio Code with a C++ compiler</h4>
<center>
</br> <a href="#Windows">Windows</a>
|
<a href="#Mac">Mac</a>
</center><hr>
<a name="Windows"></a>
<br> <h3>Windows</h3>
<p><img src="images/mingw_img.jpg" alt="" style="float: right; width: 40%; margin-left: 1%">
Unfortunately Windows does not come with a C++ compiler so we will need to download some extra tools. We will be downloading MinGW which comes with a compiler, debugger, and a make utility, which we need to build this project.
<ol>
<h4>Setting up MinGW</h4>
<li>Download it at <a href="https://sourceforge.net/projects/mingw-w64/files/Toolchains%20targetting%20Win32/Personal%20Builds/mingw-builds/installer/mingw-w64-install.exe/download" target="_blank">this link</a>. After it downloads double click on the installer which should say something like "mingw-w64-install.exe" (check your downloads folder if it doesn't pop up and double click it like before).
</li> </br>
<li>Click next through the installer setup and when you get to the <b>"Installation folder"</b> section as shown to the right, change the path to C:\MinGW. Continue through the rest of the setup and wait for it to install.
</li>
</br><li>Next we need to add the MinGW "bin" folder's path to our PATH variable so that we can access the tools from any directory.
<i><br></br><a href="https://john-dugan.com/path-variable-in-windows/" target="_blank"> What is the PATH variable?</a> </br>Note: "path" vs "path variable". "path" typically refers to a location in a file system like "C:\Users\userOne\Documents\file.txt"</i><br></br>Follow these five steps which each reference the five images below.
<ol>
<li>
search environment in the windows search bar and select "Edit the system environment variables"
</li>
<li>
Click the "Environment Variables" button
</li>
<li>
Then click the "path" row under "System Variables" and click the "edit" button
</li>
<li>
Finally click the "New" button and type "C:\MinGW\mingw32\bin". Then click "ok" on all the open tabs.
</li>
<li>To test if you configured the PATH variable correctly, open the command prompt (search cmd in the windows search bar) and type "g++". You should get something like: "g++: fatal error: no input files compilation terminated."</li>
</ol>
</li>
</ol>
<div class="row">
<div class="column">
<img src="images/env1.jpg" alt="" style="float: left; width: 50%; margin-right: 1%;margin-bottom: 3%;">
<img src="images/env2.jpg" alt="" style="float: left; width: 50%; margin-right: 1%;margin-bottom: 3%;">
<img src="images/env3.jpg" alt="" style="float: left; width: 50%; margin-right: 1%;margin-bottom: 3%;">
<img src="images/env4.jpg" alt="" style="float: left; width: 50%; margin-right: 1%;margin-bottom: 3%;">
<img src="images/env5.jpg" alt="" style="float: left; width: 50%; margin-right: 1%;margin-bottom: 3%;">
</div>
</div>
<h4>Setting up Visual Studio Code with g++ (still windows)</h4>
Now we need to configure Visual Studio Code with the C++ compiler g++ that comes with MinGW by editing a properties file. However, first we must create and open a folder where we want these
configuration settings to take effect.
<ul>
<li>create a new folder on your computer, then in VS Code go to File->Open Folder and open that folder</li>
<li>Now go to the Command pallete by clicking View -> Command Pallette or CTRL + SHIFT + P.</li>
<li>In the search bar type C++ and click the "Edit Configurations (UI)" option. A new tab will open called C/C++ Configurations.</li>
<li>Scroll down to the "Compiler Path" section and type "C:/MinGW/mingw32/bin/g++" in with the quotes.</li>
<li>Under intelliSense mode choose "gcc-x64".</li>
<img src="images/config_img.jpg" alt="" style="float: left; width: 100%; margin-right: 1%;">
</ul>
<h4>Testing if C++ works with Visual Studio Code on Windows</h4>
Our environment is finally setup for C++ so let's check it to make sure it works.
<ul>
<li>Go to File -> New File. Save with CTRL + S and it will prompt you to name it, save as test.cpp</li>
<li>Copy and paste the following code:
<pre><code>#include <iostream>
using namespace std;
int main()
{
cout << "If this prints then you have set up C++ correctly!";
return 0;
}
</pre></code></li>
<li>Go to Terminal -> New Terminal, press enter, and type the following commands:
<pre><code>g++ -o test test.cpp
.\test
</pre></code>
This image is what it should look like. If you get an error and can't figure it out please email me or come to my office hour.
<div class="row">
<div class="column">
<img src="images/test_img.jpg" alt="" style="float: left; width: 100%; margin-right: 1%;">
</div>
</div>
</li>
</ul>
<center>
</br> <a href="#Next">Next Step</a>
|
</center><hr>
</p>
<a name="Mac"></a>
<h3>MAC</h3>
<p>Fortunately, setting up C++ to compile on a Mac is much easier than Windows because Mac has an easy way to install "command line developer tools" which will provide us with utilities like clang (C++ compiler) and Make.
<h4>Downloading command line developer tools on Mac</h4>
<ol>
<li>
open the search by using Command + Space. Type in "Terminal" and press enter to open it up
</li>
<li>
In the terminal install the Command line tools with the command "xcode-select --install" Make sure you only install the tools and NOT xcode.
</li>
<li>
Now type clang and make sure you get something like "$ clang: error: no input files"
</li>
</ol>
<h4>Configuring Visual Studio Code with g++</h4>
<ol>
<li>
First we need to set up Visual Studio Code to open from the command line. In VS code use CTRL + SHIFT + P to open up the command pallete or go to View -> Command Pallete
</li>
<li>
Now type Shell and select "Shell Command: Install 'code' command in PATH." After it installs close VS code.
</li>
<li>
Now open up the terminal if you closed it and type "mkdir testFolder" to make a new folder. Enter that folder by typing "cd testFolder". Finally type "Code ." to open up this folder in VS Code.
</li>
<li>
Open the command pallette like before and type C++ and select "Edit Configurations (UI)". A new tab called C/C++ Configurations will open up. In this tab scroll down to "compiler path" and paste "/usr/bin/clang". Also make sure intellisense is "clang-x64" as shown.
<img src="images/macConfig.png" alt="" style="float: left; width: 100%; margin-right: 1%;">
</li>
<li>C++ is finally configured! Now let's test to make sure it works.</li>
</ol>
<h4>Testing C++ on MAC</h4>
Go to File -> New File. Save with CTRL + S and it will prompt you to name it, save as test.cpp</li>
<li>Copy and paste the following code:
<pre><code>#include <iostream>
using namespace std;
int main()
{
cout << "If this prints then you have set up C++ correctly!";
return 0;
}
</pre></code></li>
<li>Go to Terminal -> New Terminal, press enter, and type the following commands:
<pre><code>g++ -o test test.cpp
./test
</pre></code>
This image is what it should look like. If you get an error and can't figure it out please email me or come to my office hour.
<div class="row">
<div class="column">
<img src="images/macTest.jpg" alt="" style="float: left; width: 100%; margin-right: 1%;">
</div>
</div>
</p>
<hr>
<p>
<a name="Next"></a>
<h4>4. Managing a new project using Git and linking to the SDL2 library</h4>
Now that we have our code editor working with C++ we can start a project. When creating mid to large size
programming projects with multiple files, we want to manage our code with a tool called Git and save our code online using
a site called Github.<br></br>
<ul>
<li><b>Git</b> is known as a version control system and it is used to manage software in a container called a repository.
For example, say you make some changes to working code and break it. Using Git, you can see
every change and undo them if necessary. More on this later.
</li>
<li>
<b>Github</b> on the other hand is a service to store and manage your Git repositories online.
</li>
</ul> <a href="https://betterexplained.com/articles/a-visual-guide-to-version-control/" target="_blank">What is version control?</a> <a href="https://blog.devmountain.com/git-vs-github-whats-the-difference/" target="_blank">Git vs GitHub</a>
<br></br></br>I have created a repository (basically a directory to store a project) on github with some base code which we will build off of. This base code includes build tasks,
the SDL2 library, and a small set of classes I created to help create a simple menu system. What we will be doing is copying the base code into a local directory
on your computer and start from there. <br></br>
<ol>
<li>
first download git if you don't have it already <a href="https://git-scm.com/downloads" target="_blank">from this link.</a> In the installation
wizard just click next through all the steps and install it.
</li>
<li>
next, create an account on github if you don't have one already <a href="https://github.com/" target="_blank">from this link</a>
</li>
<li> The next thing we need to do is configure git with our information. Type these commands into the command prompt (terminal) with your name and email.
</br> git config --global user.name "firstName lastName"</br>
git config --global user.email "[email protected]"
</li>
<li>
Now that git is configured let's copy the base code to your local computer from github. Open the command prompt (terminal)
and navigate to a location where you want to save your project. This may be documents, desktop, or anywhere else you
want. Once in the location you want type this command:
<ul>
<li>
<b>Windows: </b> "git clone https://github.com/geffencooper/ArcadeSystem_windows.git"
</li>
<li>
<b>Mac: </b> "git clone https://github.com/geffencooper/ArcadeSystem_mac.git"
</li>
</ul>
<li>
Now type "cd ArcadeSystem_windows" or "cd ArcadeSystem_mac", and then type "dir" if on Windows and "ls" if on Mac.
You should see the following folders: <b>GUI_files, SDL_files, source </b>
</li>
</li>
<li>
<b>Mac</b>: If you are on Mac there is an extra step. Copy and paste the following commands ONE AT A TIME in your current directory
which should be in the ArcadeSystem_mac folder.
<pre><code>
cd SDL_files
/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
brew install SDL2 SDl2_image SDL2_ttf SDl2_mixer
cp -R /usr/local/Cellar/sdl2/2.0.10/include/SDL2/ include/
cp -R /usr/local/Cellar/sdl2/2.0.10/lib/ lib/
cp -R /usr/local/Cellar/sdl2_image/2.0.5/include/SDL2/ include/
cp -R /usr/local/Cellar/sdl2_image/2.0.5/lib/ lib/
cp -R /usr/local/Cellar/sdl2_ttf/2.0.15/include/SDL2/ include/
cp -R /usr/local/Cellar/sdl2_ttf/2.0.15/lib/ lib/
cp -R /usr/local/Cellar/sdl2_mixer/2.0.4/include/SDL2/ include/
cp -R /usr/local/Cellar/sdl2_mixer/2.0.4/lib/ lib/
</code></pre>
</li>
</ol>
</p>
<h4>5. Testing to see if SDL2 works</h4>
<ol>
<li>
Open up Visual Studio code and go to File->Open Folder and open the according folder, "ArcadeSystem_windows" or "ArcadeSystem_mac"
</li>
<li>
Now use "CTRL (CMND on Mac) + SHIFT + B" to bring up a build task drop down. It should look like the following picture
<img src="images/build.jpg" alt="" style="float: left; width: 100%; margin-right: 1%;">
</li>
<li>
select "build all". Then type "CTRL (CMND on Mac) + SHIFT + B" and select "run ArcadeSystem"
</li>
<li>
you should get a blank window that says ArcadeSystem at the top as shown
<img src="images/output.jpg" alt="" style="float: left; width: 100%; margin-right: 1%;">
</li>
<li>
That's it!
</li>
</ol>
<p>
<hr>
<h4>Congradulations! You finished the environment setup. This is one of the more difficult and frustrating parts of building
software projects so don't get discouraged, the rest of the project is much more fun. </h4>
</p>
<a name="Lesson1"></a>
<p>
</br><hr><h2>Lesson 1: Introducing the Menu System/Designing a GUI</h2>
Before getting into the design, watch this video for a demo of what the Arcade System will look like.
<video width="400" controls>
<source src="demo.mp4" type="video/mp4">
Your browser does not support HTML5 video.
</video>
</p>
<p>
<h4>Intro</h4>
For this project, the goal is to provide you with something which you can expand on so we will be building
a "base" version of the Arcade System with a simple menu system, one game (brick breaker or tetris), and some music. At the end,
you will have the knowledge and opportunity to customize your Arcade by building your own games and adding your own images and music.
</p>
<p>
<img src="images/mainMenu_img.jpg" alt="" style="float: right; width: 40%; margin-left: 1%"><h4>Designing a GUI </h4> <a href="https://www.computerhope.com/jargon/g/gui.htm" target = "blank"> What is a GUI</a></br>
A GUI is a "Graphical User Interface" and is the way we interact with a program. We will go through the steps of designing a simple GUI that will be used to interact with our
arcade system. However, due to time constraints we will not be programming this GUI from scratch. Instead we will just implement some files that I created
to help program the GUI.</br></br>
This image here on the right shows a visual of the GUI we will be making.
</p>
<p>
</br></br>
<h4>High Level Design</h4><img src="images/vision.jpg" alt="" style="float: right; width: 40%; margin-left: 1%">
How do we go about desiging a menu system from scratch? </br></br>
<ol>
<li>
When building a multi file project, you don't want to start coding right away or you will end up with a bunch of messy code with no organization.
</br></br>The first step is to start with the high level logic and design. Start with a sketch or diagram of
what you want your program to look like or how it might work. This image on the right is one of the early diagrams I made and represents a vision of what I wanted the arcade system to look like.
</li></br>
<li><img src="images/general.jpg" alt="" style="float: right; width: 40%; margin-left: 1%">
The next step is to take the specific image or vision and generalize it a bit and break it down into components
so that we can begin thinking in more of a programmatic way which makes the transition from design to implementation more fluid. Essentially,
we want to take our design and consider how we can create some structure from it.
</br></br> Consider this generalized diagram on the right. What does it resemble? It resembles
a tree-like structure right. Now using this more generic diagram let's think about the structure of a tree. A tree starts with what we call the "root" and expands
out into what we call "Nodes." Nodes are basically discrete points that hold data and are linked together to form the tree. Each box in the diagram is a node.
</ol>
<h4>Being more explicit with our design</h4>
</li></br>
<img src="images/hierarchy.jpg" alt="" style="float: right; width: 40%; margin-left: 1%">
The next step is to get more explicit with our tree structure and start to define some rules and attributes.
In our tree structure we will define something called the Node->Screen->Button hierarchy which basically are
the three tiers of our menu system.
<ul>
<li>
<b>Node</b>: The node represents an organizational unit in our menu system and does not really do anything more. Its role will become more clear but in general we
can say that a node is a collection of screens.
</li>
<li>
<b>Screen</b>: The screen represents the guts of the node and is where all the action happens. The top level user will be unaware of the nodes and will
only interact with the screens. The screen also holds a list of buttons.
</li>
<li>
<b>Button</b>: The button is what facilitates movement through the tree and is what actually links screens to screens and nodes to nodes.
</li>
<li>
<b>parent-child relationship of nodes</b>: We also need to define the connections between nodes. In this tree we are going
to keep things simple and say that every "parent" node can have multiple "child" nodes, but every "child" node can only
have one parent. Basically, every node can branch out into multiple nodes, but each node can only link to one node above itself. This way
we avoid having loops in our tree.
</li>
</ul>
This picture below shows this hierarchy in action. We have a tree made up of nodes (grey and yellow boxes), which hold screens (blue boxes), which are linked using buttons (green and red lines)
and all the nodes follow the parent-child relationship we defined.
<img src="images/tree.jpg" style="float: right; width: 100%; margin-left: 1%; margin-bottom:5%">
</p>
<p>
<h4> Transitioning from design to implementation</h4>
So now that we have a good idea of how our menu system is designed, let's go into the details of implementation because
this design needs to be described in code. So how do we do that? How do we take these attributes and rules that we used to describe our tree
structure and make them into code?
</br></br> <b>We use classes and create objects</b>
<br> We have already categorized our design into distinct parts that we can visualize (Node, Screen, Button) and described them. Now we can take all the attributes
and behaviors we associated with these parts and bundle them up into units which we call objects.
</br></br> For a quick intro about classes and objects in C++ click <a href="https://www.programiz.com/cpp-programming/object-class" target = "blank">this link</a>
</br></br>
<img src="images/classes.png" style="float: right; width: 50%; margin-left: 1%; margin-bottom:5%">For example, if we want to do something in our tree like move screens or play music how do we do that? We use the buttons. We can bundle up a set of attributes and behaviors associated with actions into a button object.
<ul>
<li>
In addition, we can bundle up the set of attributes and behaviors associated with the structure of our tree into screen and node objects
</li>
<li>
So essentially in C++, an object is a unit that bundles up a set of attributes and behaviors. It is also helpful to think about objects in C++ as real life objects, so for example take a look at these classes to the right which are blueprints to define objects.
</li>
<li>
Note how I described objects in two different ways
<ol>
<li>
We can take a real life object and describe its behaviors and attributes so that we can implement it as a construct in our program
</li>
<li>
Or we can take some high level abstract design and split it up into bundles of behaviors and attributes and form objects.
This is a more generic approach that is useful when designing classes that don't resemble tangible, real life objects.
</li>
</ol>
</li>
</ul>
<h4> Defining the Node, Screen, and Button Classes</h4>
<p>
I highly reccomend looking through "Button.h", "Screen.h", and "Node.h" in the GUI_files->headers folder inside our project folder. These files define
a generic Button, Screen, and Node class. Remember, a class is a blueprint that describes an object. A short summary of
the classes (the attributes/member variables and behaviors/functions) is shown below:
</br>
<ul>
<li>
<b>Button Attributes: </b> width, height, x position, y position
</br>
<b>Button Functions: </b> Accessors, mutators, update, render </br>
<a href="https://oop.tech-academy.co.uk/accessors-mutators/" target="blank">What are accessors and mutators</a>
</li>
<li>
<b>Screen Attributes: </b> list of ArcadeTexture objects
</br>
<b>Screen Functions: </b> Accessors, mutators, update, render </br>
</li>
<li>
<b>Node Attributes: </b> currentScreen object, list of screen objects, parent node object, renderer object
</br>
<b>Node Functions: </b> Accessors, mutators, update, render </br>
</li>
</ul>
An ArcadeTexture object is basically just an image or text that we want to put on the screen. I made a class called ArcadeTexture to simplify
the process of doing this.
You are probably wondering what update and render do. I will get into that below.
</br>But before I do it is important to note how "generic" these classes are and by that I mean I only defined the most basic
and general attributes and methods that a button, screen, or node should have without getting too specific. </br>
</br><h4>Inheritance</h4>Being generic gives us the
flexibility to create different types of buttons or screens or nodes that share the same general attributes but behave in a specific way through
<b>inheritance</b>. For a good explanation of inheritance in C++ read <a href="https://www.geeksforgeeks.org/inheritance-in-c/" target = "blank">this article</a>. For example,
we want to create different types of buttons and by using inheritance we don't
need to redefine all the button attributes and functions every time we make a new type of button. We can define a generic
button that contains the attributes and functions all buttons should have and then define a new button
that <b>inherits</b> from this generic class, giving it all these attributes and functions by default.
</br></br> So what I have done is inherited from the button class to create two different buttons (SimpleButton and OptionsButton) and inherited
from the screen class to create two different screens (MenuScreen and GameScreen). You can see these in the GUI_files->headers folder.
</br></br>
<h4> Understanding the GUI loop</h4>
So before we can start using the button, screen, and node objects to build our menu system we first have to understand how our program
runs using what I call a GUI loop (very similar to a game loop). This is where the "update" and "render" functions from above come in.
A GUI loop is just a series of three steps that our program follows (when I say GUI I basically mean the program):
<ol>
<li>
<b>Handle Input</b>: First we want our GUI to track any user events such as mouse movement or keystrokes. We want our
menu system to be able to react to these events accordingly
</li>
<li>
<b>Update</b>: Next we need our GUI to update the states or values of certain variables based on te user input. For example, if the user move their mouse over a button we want to update
the state of that button to "selected."
</li>
<li>
<b>Render</b>: Rendering just means painting to the screen. So for example, our button state was updated to selected so now when we render
that button it will be rendered with some opacity to show that it is selcted.
</li>
</ol>
This loop repeats over and over again 60 times per second for the entirety of our program.
To understand how this loop works in the context of our program take a look at this simplified main function which is where every C++ program begins.
<!-- HTML generated using hilite.me --><div style="background: #ffffff; overflow:auto;width:auto;border:solid gray;border-width:.1em .1em .1em .8em;padding:.2em .6em;"><pre style="margin: 0; line-height: 125%">
<span style="color: #888888">// we want to run the gui loop until the user quits</span>
<span style="color: #333399; font-weight: bold">bool</span> quit <span style="color: #333333">=</span> <span style="color: #007020">false</span>;
<span style="color: #888888">// here we create the first node for our menu system</span>
RootNode <span style="color: #0066BB; font-weight: bold">currentNode</span>(arcadeSystemRenderer, nullptr);
<span style="color: #888888">// ---------------THE GUI LOOP</span>
<span style="color: #008800; font-weight: bold">while</span> (<span style="color: #333333">!</span>quit)
{
<span style="color: #888888">// handle all user events until there are none left</span>
SDL_Event e;
<span style="color: #008800; font-weight: bold">while</span> (SDL_PollEvent(<span style="color: #333333">&</span>e) <span style="color: #333333">!=</span> <span style="color: #0000DD; font-weight: bold">0</span>)
{
<span style="color: #888888">// update the current node </span>
currentNode.update(<span style="color: #333333">&</span>e);
<span style="color: #888888">// user requests quit by clicking window X</span>
<span style="color: #008800; font-weight: bold">if</span> (e.type <span style="color: #333333">==</span> SDL_QUIT)
{
quit <span style="color: #333333">=</span> <span style="color: #007020">true</span>;
}
}
currentNode.update(nullptr);
<span style="color: #888888">// render the current node</span>
currentNode.render(arcadeSystemRenderer);
SDL_RenderPresent(arcadeSystemRenderer);
}
</pre></div>
<p>
The GUI works like this:
<ol>
<li>
Before going into the loop, create the first node in the menu system.
We hold it in a variable called currentNode because we only care about updating and rendering
the current node. There is no point in updating and rendering the other nodes if we aren't using them.
</li>
<li>
Now we enter the loop and run it until the user wants to quit
</li>
<li>
Next we check for user events and pass them to the current node until there are no events left.
When we update the currentNode it will call update for the currentSceen (again we only care about the current screen) which will
check if a button is selected or not.
</li>
<li>
If there are no events we still want to update the current node but just pass in no event
</li>
<li>
Finally we render the node to the screen. Node will render the current screen, which will render all its ArcadeTexture objects and all its buttons.
</li>
</ol>
</br>
More generally, we have some tree structure that has nodes, screens, and buttons.
At any moment when our program is running we will be somewhere in the tree, specifically
at the "current screen" in the "current node". For example, when the program starts out
we define the current node to be the root and the current screen to be some screen in the
root node's screen list. Below we see that by the red oval which is circling the root node denoted
by the black box which only has one screen.
<img src="images/finalTree.png" style="float: right; width: 100%; margin-left: 1%; margin-bottom:2%">
</br>
Remember that for the entire program we constantly handle events,
update, and render. So if no events occur, then we just update and render the same
screen over and over again which is why it appears that nothing is happening. Once an event
occurs we handle it at different tiers: the main function, the node level, the screen level, or
at the button level. We always check and receive events at the main function.
<br></br>
From there we pass the event down
the node -> screen -> button hierarchy calling node's update function, which calls screen's update, which calls button's update.
The button will then attempt to handle the event and return an "action" to the screen. Based on this action, the screen will
attempt to update accordingly and then return the action to the node. Based on the action, the node will attempt to
update accordingly and then return the action to the main function which will attempt to update accordingly.
<br></br>
Let's take a look at an example of this cycle. Let's say the user clicks the mouse on a button to move nodes. This click event will pass
to the node, then screen, then button. The button handle the event by checking if the click happened on a button. If so
it will return an action associated with that button, in this case to move to some other node. This action returns to the screen.
The screen cannot handle moving nodes so it returns the action to the node. The node cannot handle this action either so it returns
to the main function which updates the current node to whatever the action specified. Now when we update and render
we will update this new node and its starting screen.
</br></br>
<h4>conclusion</h4>
That was a lot of information so don't worry if a lot of it didn't make sense. Next class we will be going over
how to actually use these objects to create a menu system. </br></br><b>One important concept to remember is abstraction, it is not
critical to understand how button, screen, and node work under the hood but rather it is important to know how to use them because at the end
of the day we just want to build the menu system. For example, its good to understand how a car generally works but you don't need to understand
all the details of how it works under the hood in order to use it. In this case I have implemented the GUI classes for you and abstracted all the details away by
providing a set of methods (we will learn these next class) for you to use to build a menu.</b>
</p>
</p>
</p>
<hr>
<a name="Lesson2"></a>
<p>
<h2>Lesson 2: Using Git and implementing the menu system</h2>
<h4>Exploring the project directory</h4>
<p>
Before we start coding let's take a look at our project directory which we copied from github in lesson 0.
<img src="images/directory.png" style="float: right; width: 50%; margin-left: 1%; margin-bottom:1%">
This image on the right shows what our project directory (also our git repository) looks like.
<ul>
<li>
<b>.git</b>: This folder signfies that "ArcadeSystem_windows" is a git repository so any changes made will be identified by git. <b>We won't open or change this folder directly</b>.
<br></br>
</li>
<li>
<b>.vscode</b>: This folder stores configuration settings. It has files that specify things like the compiler path, include paths, build tasks, debugger settings.
The "build arcadeSystem" task we call to compile our code is defined here.
<b> We won't open or change this folder</b>.<br></br>
</li>
<li>
<b>GUI_files</b>: This folder has all the classes and files necessary to build the menu system. The Node, Screen, and Button classes can be found in "GUI_files->headers"
if you are curious.
We will be using these files and possibly opening them but <b> we will not change them</b>.<br></br>
</li>
<li>
<b>SDL_files</b>: This folder has files we need from the SDL2 library. These files are basically just a bunch of functions we can use to do things like detect keystrokes or put images on the screen.
<b> We will not change or open this folder</b>.<br></br>
</li>
<li>
<b>source</b>: This folder is where all our resources (images and fonts) and source code (the C++ files we will make) for our project are located.
This is really the only folder you need to interact with. You can think of all the other folders as tools we need to help us build our project and
this source folder is where all the action happens and where the tools are used.</b><br></br>
</li>
</ul>
</p>
<h4> Using Git</h4>
<p>
Next we need to learn a little bit about git. If you remember from lesson 0 and read the articles,
git is a version control system (basically a tool that helps us manage our code). We will be using it
to track our code and also to publish it to a remote repository on your github account. You can think of github as a powerful version of google drive that is specifically for software.
<h5>Seeing git in action</h5>
<p>
To understand what git does, it is useful to see it in action. These three images below show a succession of events.
<br></br>
<b> 1. Start with some code
2. Change or add to the code </b>
<div class="column">
<img src="images/git1.png" alt="" style="float: left; width: 49%; margin-right: 1%;">
<img src="images/git2.png" alt="" style="float: left; width: 49%; margin-right: 1%;margin-bottom: 3%;"> </div>
<div class="column">
</ol>
<p>
<b>3. Seeing the changes identified by git (left side is visual git interfce, right side is git command line interface)</b>
</p>
<img src="images/git3.png" alt="" style="float: left; width: 49%; margin-right: 1%; margin-bottom: 0%;">
<img src="images/git3cl.png" alt="" style="float: right; width: 49%; margin-right: 1%; margin-bottom: 1%;">
</p>
What we are seeing in the images in part three is git recognizing Main.cpp has been changed. You can interact with git through a visual interface or
a command line interface. In the command line interface we use the commands <b> git status</b> to check the current state of our repository and <b>git diff</b> to see what we changed.
<br></br><br></br>
Now that we have an idea of what git does, let's learn how it works and how to use it. Currently our files are part of a <b>git repository</b>. A repository is
just a storage space where a project sits in. What makes it a git repository is that we have the <b>.git</b> folder which tracks all our changes and builds
a history of our project that we can easily access and interact with.
<br></br>
Files in our project directory can be in different states: <b>untracked, modified, staged, and committed</b>.
<br></br>
<ul>
<li>
<img src="images/untracked.png" alt="" style="float: right; width: 50%; margin-right: 1%; margin-bottom: 3%;">
<b>Untracked:</b> files that are in our directory but are not tracked by the git repository.
<b>Note:</b> just because a file is in a directory with a .git folder does not mean it is tracked. For example, I created a new file
called test.cpp in the project directory. When I run the command <b>git status</b> it tells me the file is untracked. To start tracking it I use <b>git add <i>file</i></b>
</li><br></br>
<li>
<img src="images/modified.png" alt="" style="float: right; width: 50%; margin-right: 1%; margin-bottom: 0%;">
<b>Modified:</b> files that are being <b>tracked</b> by the git repository and have changed since the last time we "commited" (saved our changes) or since tracking them by adding them to the git repo.
<br></br>
What we see in this image are two things.
<ol>
<li> We start tracking test.cpp by adding it to the git repo with <b>git add</b>.
This is seen by <b>git status</b> showing "new file". On the left we have it in "staged changes" which
shows any changes that we "added" to the git repo.
</b></li>.
<li>
We modify test.cpp by typing a comment. When we view "Changes" in the left we see the before and after at the top. <b>git status</b>
shows the first change (adding test.cpp to the directory) is "added" and ready to be "committed" (saved) but the second change (modifying test.cpp with a comment)
has not been "added" and is not ready to be committed (saved). Changes that we want to keep must be "added" with <b>git add</b>. A change
that is "added" is ready to be commited (saved) but is not saved yet.
</li>
</ol>
</li>
<li>
<b>Staged:</b> changes that we make in our directory that we want to eventually "commit" or save. We use the <b>git add <i>file</i></b> command.
When we uses git status, these "staged" or "added" files that we changed will be green not red meaning
that they are ready to be saved.
</li>
<img src="images/commit.png" alt="" style="float: right; width: 50%; margin-right: 1%; margin-bottom: 3%;">
<li>
<b>Committed:</b> changes that are safely saved and stored in our git repository. This is shown in the image. Every time
we commit we must put a message with it. A commit is like a checkpoint in our project and signifies a series of changes.
</li>
</ul>
<img src="images/lifecycle.png" alt="" style="float: right; width: 50%; margin-right: 1%; margin-bottom: 1%;">
The whole process is summed up by this diagram which shows the different states of files. So for "test.cpp" we started as
<b>untracked</b> when we first added it to the directory. Then it became <b>tracked</b>, <b>unmodified</b>, and <b>staged</b> when
we used git add. Then it went to modified when we put a comment in the file. At this point the original empty file was staged but the
comment was not staged so if we committed the file then only the blank file would be saved. Finally, we added the change and committed it which
puts it back at the unmodified state.
<br></br> <br></br> <br></br>
<b>This may seem confusing as there are nuances between what each of these states really means. Basically all you need to worry about
is git add and git commit. The visual git interface is very useful if you don't have experience with git or want
and easy way to see what is going on without needing to use the other git commands. This interface let's you see all the changes you made to each file.</b>
</p>
<p>
<h4>setting up a remote repository</h4>
Everything we have talked about up until now regarding git has been "locally". By this I mean we have only been using git to track and save changes
on your local computer, not online or another computer (With exception to lesson 0 when did use git to clone the repo from online). What we will be talking about now
is how to link your local git repository to a repository online using GitHub.
<br></br>
In git, remote repositories are versions of our project that are hosted somewhere else, in this case on GitHub. Because we cloned our repo from my GitHub, we automatically
have this as one of our remote repos. By default this remote repo is called "origin". We will add another remote repo from your Github so you
can not only save your changes online but also copy changes from my repo if necessary.
<ol>
<div class="row">
<img src="images/create.png" alt="" style="float: right; width: 20%; margin-right: 1%; margin-bottom: 1%;">
<img src="images/create2.png" alt="" style="float: right; width: 30%; margin-right: 1%; margin-bottom: 1%;">
<img src="images/create3.png" style="float: right; width: 40%; margin-right: 1%; margin-bottom: 1%;">
</div>
<li>
First, we need make a new repository on github. Login to your github account online and click the + symbol in the top right and then "new repository." Name your repository
whatever you want like yourNameArcade and click "create repository." In the next window select HTTPS and copy the url. Look at the three images above as a reference.
</li>
<li>Next, we want to change the name of our current remote repo from "origin" to "upstream" so that we know it is the original source.
<br>In visual studio code, open the terminal and type: <code>git remote rename origin upstream</code>
</li>
<li>
Now we need to add a remote repo called origin and link it to the repo we just created in github. In the same terminal session
type this command <code>git add remote origin <i>URL to your repo</i></code> example URL: https://github.com/geffencooper/geffenArcade.git
</li>
<li>
Finally, we want to "push" or send our current git repository with all our files to this remote repo. In the same terminal window type:
<code>git push origin master</code>. <b>To check that it worked, go to your github and refresh the page, it should have our project in there.</b>
</li>
<li>
the image below shows the steps. When I type <code>git remote -v</code> it prints out the urls of each
remote repo. You can do this as a check to make sure the upstream is my repo and origin is your repo.
</li>
<img src="images/remote.png" style="float: right; width: 100%; margin-right: 1%; margin-top: 1%;">
</ol>
<h3>That's it for git we can now start coding. This setup can be confusing if it is your first time so please do not hesitate to email me with questions at any time. Please
also come to my office hour if you need help.
</h3>
</p>
<hr>
<h3>implementing the menu system</h3>
Before we do anything, I added a new build task to make things easier. To get this new build task, go to the terminal in
visual studio code as we have done before and type <code>git pull upstream master</code>
<br></br>
I am going to go through a basic example of how to use the methods and classes I provided. For the full code for the menu system
I made a repo on GitHub and have the link at the bottom of this lesson. The repo has a ReadMe with information on how to use and set up the code.
<br></br>
<img src="images/rootNode.png" style="float: right; width: 50%; margin-right: 1%; margin-top: 1%;">
<h4>Step 1: Creating a new node</h4>
The first step to implementing the menu system is creating a new node. If you recall our menu system is a tree of nodes.
To do this create a new file called "RootNode.h" in the source directory of the project. Do this by right-clicking source and
then clicking new file as shown in the image.
<br></br> <br></br>
<h5>This is the code for a basic rootNode that flips between two screens when you click a button.</h5>
Copy-paste this into your RootNode.h. Also, below this is code you need for "Main.cpp". I will dissect the code in detail below.
<p>
<!-- HTML generated using hilite.me --><div style="background: #f8f8f8; overflow:auto;width:auto;border:solid gray;border-width:.1em .1em .1em .8em;padding:.2em .6em;"><pre style="margin: 0; line-height: 125%"><span style="color: #408080; font-style: italic">// RootNode </span>
<span style="color: #408080; font-style: italic">// include the files we need</span>
<span style="color: #BC7A00">#include "Node.h"</span>
<span style="color: #BC7A00">#include "Config.h"</span>
<span style="color: #BC7A00">#include "MenuScreen.h" </span>
<span style="color: #BC7A00">#include "SimpleButton.h" </span>
<span style="color: #008000; font-weight: bold">class</span> <span style="color: #0000FF; font-weight: bold">RootNode</span> <span style="color: #666666">:</span> <span style="color: #008000; font-weight: bold">public</span> Node <span style="color: #408080; font-style: italic">// publicly inherits from Node</span>
{
<span style="color: #A0A000">public:</span>
<span style="color: #408080; font-style: italic">// Constructor // initializer list</span>
RootNode(SDL_Renderer<span style="color: #666666">*</span> renderer_in, Node<span style="color: #666666">*</span> parentNode_in)<span style="color: #666666">:</span> Node(renderer_in, parentNode_in)
{
<span style="color: #408080; font-style: italic">// first create screens for the node</span>
MenuScreen<span style="color: #666666">*</span> screen1 <span style="color: #666666">=</span> createMenuScreen();
MenuScreen<span style="color: #666666">*</span> screen2 <span style="color: #666666">=</span> createMenuScreen();
<span style="color: #408080; font-style: italic">// create images and text to put on the screen using an ArcadeTexture object</span>
ArcadeTexture<span style="color: #666666">*</span> screen1Background <span style="color: #666666">=</span> createImage(renderer_in, <span style="color: #BA2121">"rootNodeImages/rootNodeScreenBackground.png"</span>, <span style="color: #008000">true</span>);
ArcadeTexture<span style="color: #666666">*</span> screen2Background <span style="color: #666666">=</span> createImage(renderer_in, <span style="color: #BA2121">"rootNodeImages/rootNodeScreenBackground.png"</span>, <span style="color: #008000">true</span>);
ArcadeTexture<span style="color: #666666">*</span> screen1Text <span style="color: #666666">=</span> createSimpleText(renderer_in, <span style="color: #BA2121">"fonts/retro/italic.ttf"</span>, <span style="color: #666666">100</span>, <span style="color: #BA2121">"screen 1"</span>, <span style="color: #666666">255</span>, <span style="color: #666666">255</span>, <span style="color: #666666">0</span>);
screen1Text<span style="color: #666666">-></span>setPosition(windowWidth <span style="color: #666666">/</span> <span style="color: #666666">2</span> <span style="color: #666666">-</span> screen1Text<span style="color: #666666">-></span>getWidth() <span style="color: #666666">/</span> <span style="color: #666666">2</span>, <span style="color: #666666">25</span>);
ArcadeTexture<span style="color: #666666">*</span> screen2Text <span style="color: #666666">=</span> createSimpleText(renderer_in, <span style="color: #BA2121">"fonts/retro/italic.ttf"</span>, <span style="color: #666666">100</span>, <span style="color: #BA2121">"screen 2"</span>, <span style="color: #666666">255</span>, <span style="color: #666666">255</span>, <span style="color: #666666">0</span>);
screen2Text<span style="color: #666666">-></span>setPosition(windowWidth <span style="color: #666666">/</span> <span style="color: #666666">2</span> <span style="color: #666666">-</span> screen2Text<span style="color: #666666">-></span>getWidth() <span style="color: #666666">/</span> <span style="color: #666666">2</span>, <span style="color: #666666">25</span>);
<span style="color: #408080; font-style: italic">// add the images and text to the screen after creating them</span>
screen1<span style="color: #666666">-></span>addTextureToScreen(screen1Background);
screen1<span style="color: #666666">-></span>addTextureToScreen(screen1Text);
screen2<span style="color: #666666">-></span>addTextureToScreen(screen2Background);
screen2<span style="color: #666666">-></span>addTextureToScreen(screen2Text);
<span style="color: #408080; font-style: italic">// make a text button to put on the screen1</span>
SimpleButton<span style="color: #666666">*</span> button1 <span style="color: #666666">=</span> createSimpleTextButton(renderer_in, <span style="color: #BA2121">"fonts/pixel/classic.ttf"</span>, <span style="color: #666666">30</span>, <span style="color: #BA2121">"gotoscreen2"</span>, <span style="color: #666666">255</span>, <span style="color: #666666">0</span>, <span style="color: #666666">0</span>);
button1<span style="color: #666666">-></span>setButtonPosition(windowWidth <span style="color: #666666">/</span> <span style="color: #666666">2</span> <span style="color: #666666">-</span> button1<span style="color: #666666">-></span>getWidth() <span style="color: #666666">/</span> <span style="color: #666666">2</span>, screen1Text<span style="color: #666666">-></span>getY() <span style="color: #666666">+</span> screen1Text<span style="color: #666666">-></span>getHeight() <span style="color: #666666">+</span> <span style="color: #666666">50</span>);
<span style="color: #408080; font-style: italic">// give this button an action</span>
button1<span style="color: #666666">-></span>setButtonAction(createAction(MOVE_SCREENS, screen2));
<span style="color: #408080; font-style: italic">// make a text button to put on the screen2</span>
SimpleButton<span style="color: #666666">*</span> button2 <span style="color: #666666">=</span> createSimpleTextButton(renderer_in, <span style="color: #BA2121">"fonts/pixel/classic.ttf"</span>, <span style="color: #666666">30</span>, <span style="color: #BA2121">"gotoscreen1"</span>, <span style="color: #666666">255</span>, <span style="color: #666666">0</span>, <span style="color: #666666">0</span>);
button2<span style="color: #666666">-></span>setButtonPosition(windowWidth <span style="color: #666666">/</span> <span style="color: #666666">2</span> <span style="color: #666666">-</span> button2<span style="color: #666666">-></span>getWidth() <span style="color: #666666">/</span> <span style="color: #666666">2</span>, screen2Text<span style="color: #666666">-></span>getY() <span style="color: #666666">+</span> screen2Text<span style="color: #666666">-></span>getHeight() <span style="color: #666666">+</span> <span style="color: #666666">50</span>);
<span style="color: #408080; font-style: italic">// give this button an action </span>
button2<span style="color: #666666">-></span>setButtonAction(createAction(MOVE_SCREENS, screen1));
<span style="color: #408080; font-style: italic">// add the buttons to their screens</span>
screen1<span style="color: #666666">-></span>addButtonToScreen(button1);
screen2<span style="color: #666666">-></span>addButtonToScreen(button2);
<span style="color: #408080; font-style: italic">// add the screens to the node</span>
<span style="color: #008000; font-weight: bold">this</span><span style="color: #666666">-></span>addScreen(screen1);
<span style="color: #008000; font-weight: bold">this</span><span style="color: #666666">-></span>addScreen(screen2);
<span style="color: #408080; font-style: italic">// tell the node the current screen</span>
<span style="color: #008000; font-weight: bold">this</span><span style="color: #666666">-></span>setCurrentScreen(screen1);
}
};
</pre></div>
<p>
<h5>Code for Main.cpp. Copy-paste this into your Main.cpp.</h5>
<b>IMPORTANT: </b>Once you copy these files to your project and get them working, we need to add, commit, and push them with
git so that you can have a working version saved. This way when you make changes and additions you will be able to see and go back to the working
version when it breaks. See the picture at the bottom for how to do this.
<!-- HTML generated using hilite.me --><div style="background: #f8f8f8; overflow:auto;width:auto;border:solid gray;border-width:.1em .1em .1em .8em;padding:.2em .6em;"><pre style="margin: 0; line-height: 125%"><span style="color: #408080; font-style: italic">// main.cpp</span>
<span style="color: #BC7A00">#include "SDL.h"</span>
<span style="color: #BC7A00">#include "SDL_mixer.h"</span>
<span style="color: #BC7A00">#include "SDL_ttf.h"</span>
<span style="color: #BC7A00">#include "SDL_image.h"</span>
<span style="color: #BC7A00">#include "Config.h"</span>
<span style="color: #BC7A00">#include <stdio.h></span>
<span style="color: #BC7A00">#include "RootNode.h"</span>
<span style="color: #408080; font-style: italic">// declaring pointer to objects that main needs, initialize to null</span>
<span style="color: #408080; font-style: italic">// these objects are created in main because they are needed for the outermost loop</span>
SDL_Window<span style="color: #666666">*</span> arcadeSystemWindow <span style="color: #666666">=</span> nullptr;
SDL_Renderer<span style="color: #666666">*</span> arcadeSystemRenderer <span style="color: #666666">=</span> nullptr;
TTF_Font<span style="color: #666666">*</span> font <span style="color: #666666">=</span> nullptr;
<span style="color: #408080; font-style: italic">// initialization function, initializes above objects and calls some SDL initialization functions</span>
<span style="color: #B00040">bool</span> <span style="color: #0000FF">init</span>()
{
<span style="color: #408080; font-style: italic">// Initialization flag</span>
<span style="color: #B00040">bool</span> success <span style="color: #666666">=</span> <span style="color: #008000">true</span>;
<span style="color: #408080; font-style: italic">// Initialize SDL</span>
<span style="color: #008000; font-weight: bold">if</span> (SDL_Init(SDL_INIT_VIDEO <span style="color: #666666">|</span> SDL_INIT_AUDIO) <span style="color: #666666"><</span> <span style="color: #666666">0</span>)
{
printf(<span style="color: #BA2121">"SDL could not initialize! SDL Error: %s</span><span style="color: #BB6622; font-weight: bold">\n</span><span style="color: #BA2121">"</span>, SDL_GetError());
success <span style="color: #666666">=</span> <span style="color: #008000">false</span>;
}
<span style="color: #008000; font-weight: bold">else</span>
{
<span style="color: #408080; font-style: italic">// Create window in the center of the screen</span>
arcadeSystemWindow <span style="color: #666666">=</span> SDL_CreateWindow(<span style="color: #BA2121">"Arcade System"</span>, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, windowWidth, windowHeight, SDL_WINDOW_SHOWN);
<span style="color: #008000; font-weight: bold">if</span> (arcadeSystemWindow <span style="color: #666666">==</span> <span style="color: #008000">NULL</span>)
{
printf(<span style="color: #BA2121">"Window could not be created! SDL Error: %s</span><span style="color: #BB6622; font-weight: bold">\n</span><span style="color: #BA2121">"</span>, SDL_GetError());
success <span style="color: #666666">=</span> <span style="color: #008000">false</span>;
}
<span style="color: #008000; font-weight: bold">else</span>
{
<span style="color: #408080; font-style: italic">// initialize renderer, set the background as white for the wwindow, sync the renderer with the monitor refresh rate</span>
arcadeSystemRenderer <span style="color: #666666">=</span> SDL_CreateRenderer(arcadeSystemWindow, <span style="color: #666666">-1</span>, SDL_RENDERER_ACCELERATED <span style="color: #666666">|</span> SDL_RENDERER_PRESENTVSYNC);
SDL_SetRenderDrawColor(arcadeSystemRenderer, <span style="color: #666666">0xFF</span>, <span style="color: #666666">0xFF</span>, <span style="color: #666666">0xFF</span>, <span style="color: #666666">0xFF</span>);
}
<span style="color: #408080; font-style: italic">// Initialize SDL_mixer</span>
<span style="color: #008000; font-weight: bold">if</span> (Mix_OpenAudio(<span style="color: #666666">44100</span>, MIX_DEFAULT_FORMAT, <span style="color: #666666">2</span>, <span style="color: #666666">2048</span>) <span style="color: #666666"><</span> <span style="color: #666666">0</span>)
{
printf(<span style="color: #BA2121">"SDL_mixer could not initialize! SDL_mixer Error: %s</span><span style="color: #BB6622; font-weight: bold">\n</span><span style="color: #BA2121">"</span>, Mix_GetError());
success <span style="color: #666666">=</span> <span style="color: #008000">false</span>;
}
<span style="color: #408080; font-style: italic">// initialize true type font </span>
<span style="color: #008000; font-weight: bold">if</span> (TTF_Init() <span style="color: #666666">==</span> <span style="color: #666666">-1</span>)
{
printf(<span style="color: #BA2121">"SDL_ttf could not initialize! SDL_ttf Error: %s</span><span style="color: #BB6622; font-weight: bold">\n</span><span style="color: #BA2121">"</span>, TTF_GetError());
success <span style="color: #666666">=</span> <span style="color: #008000">false</span>;
}
}
<span style="color: #008000; font-weight: bold">return</span> success;
}
<span style="color: #B00040">int</span> <span style="color: #0000FF">main</span>(<span style="color: #B00040">int</span> argc, <span style="color: #B00040">char</span><span style="color: #666666">*</span> argv[])
{
<span style="color: #408080; font-style: italic">// first call initialization</span>
<span style="color: #008000; font-weight: bold">if</span> (<span style="color: #666666">!</span>init())
{
printf(<span style="color: #BA2121">"Failed to initialize!</span><span style="color: #BB6622; font-weight: bold">\n</span><span style="color: #BA2121">"</span>);
}
<span style="color: #408080; font-style: italic">// if initializes successfully then continue</span>
<span style="color: #008000; font-weight: bold">else</span>
{
<span style="color: #B00040">bool</span> quit <span style="color: #666666">=</span> <span style="color: #008000">false</span>;
RootNode currentNode(arcadeSystemRenderer, nullptr);
<span style="color: #008000; font-weight: bold">while</span> (<span style="color: #666666">!</span>quit)
{
<span style="color: #408080; font-style: italic">// handle events on queue until empty</span>
SDL_Event e;
<span style="color: #008000; font-weight: bold">while</span> (SDL_PollEvent(<span style="color: #666666">&</span>e) <span style="color: #666666">!=</span> <span style="color: #666666">0</span>)
{
currentNode.update(<span style="color: #666666">&</span>e);
<span style="color: #408080; font-style: italic">// user requests quit by clicking window X</span>
<span style="color: #008000; font-weight: bold">if</span> (e.type <span style="color: #666666">==</span> SDL_QUIT)
{
quit <span style="color: #666666">=</span> <span style="color: #008000">true</span>;
}
}
currentNode.update(nullptr);
currentNode.render(arcadeSystemRenderer);
SDL_RenderPresent(arcadeSystemRenderer);
}
}
<span style="color: #008000; font-weight: bold">return</span> <span style="color: #666666">0</span>;
}
</pre></div>
<h4>How to add, commit, and push using git</h4>
Type theses commands when you get your code working.
<code>git add .</code> then <code>git commit -m"working version"</code> then <code>git push origin master</code> You should see these additions in your GitHub account.
<img src="images/useGit.png" style="float: right; width: 100%; margin-right: 1%; margin-top: 1%; margin-bottom: 2%;">
<br>
Then type CTRL (CMDN on Mac) + SHIFT + B and run these tasks: "build arcadeSystem" then "run arcadeSystem".
<b>Note:</b> There might be some red squiggly lines saying your code has errors, try running the tasks anyways because VS code can be a bit delayed and not recognize some references.
If you change the code and want to recompile it run the tasks "recompile arcadeSystem" then "run arcadeSystem".
<h5>When running you should see this screen and be able to flip to the next screen using the button.</h5>
<div class = "row">
<img src="images/s1.jpg" style="float: right; width: 49%; margin-right: 1%; margin-top: 1%; margin-bottom: 2%;">
<img src="images/s2.jpg" style="float: right; width: 49%; margin-right: 1%; margin-top: 1%; margin-bottom: 2%;">
</div>
<h4>Dissecting the code</h4>
<h5>Main.cpp</h5>
All C++ programs start their execution from the method "main()" so let's start from the file Main.cpp
where the function "main" sits.<br></br>
<h5>This is the first chunk of code we see in the file Main.cpp</h5>
<!-- HTML generated using hilite.me --><div style="background: #f8f8f8; overflow:auto;width:auto;border:solid gray;border-width:.1em .1em .1em .8em;padding:.2em .6em;"><pre style="margin: 0; line-height: 125%"><span style="color: #408080; font-style: italic">// main.cpp</span>
<span style="color: #BC7A00">#include "SDL.h"</span>
<span style="color: #BC7A00">#include "SDL_mixer.h"</span>
<span style="color: #BC7A00">#include "SDL_ttf.h"</span>
<span style="color: #BC7A00">#include "SDL_image.h"</span>
<span style="color: #BC7A00">#include "Config.h"</span>
<span style="color: #BC7A00">#include <stdio.h></span>
<span style="color: #BC7A00">#include "RootNode.h"</span>
</pre></div>
In C++ "#include" is a special command that basically copy-pastes or "includes" a file into our code. The reason
we need to include these files is so that we can use functions and variables that they contain. If we did not include them,
then we would get errors because otherwise how would we know about these functions and variables? Our program is unaware of them unless
we include these files.<br></br>
<h5>This next chunk of code is an initialization function that we don't have to worry about</h5>
This code just calls some functions that SDL provides us to create a window, a renderer, and make sure that our resources are working.
<!-- HTML generated using hilite.me --><div style="background: #f8f8f8; overflow:auto;width:auto;border:solid gray;border-width:.1em .1em .1em .8em;padding:.2em .6em;"><pre style="margin: 0; line-height: 125%"><span style="color: #408080; font-style: italic">// declaring pointer to objects that main needs, initialize to null</span>
<span style="color: #408080; font-style: italic">// these objects are created in main because they are needed for the outermost loop</span>
SDL_Window<span style="color: #666666">*</span> arcadeSystemWindow <span style="color: #666666">=</span> nullptr;
SDL_Renderer<span style="color: #666666">*</span> arcadeSystemRenderer <span style="color: #666666">=</span> nullptr;
TTF_Font<span style="color: #666666">*</span> font <span style="color: #666666">=</span> nullptr;