Zmob, my first (and only) own game.By the end of the course, the width and depth of our collective knowledge was much more than anyone could have expected from any high school course in any subject .
Education vs. Research
This semester, I work as an assistant teacher in an introductory course in Python, and this makes me depressed. I recall my early years of programming, when the possibilities seemed almost limitless, and adding new features to my programs was a delightful and joyful process. I was proud of every line, boasted to my friends about what amazing things I was able to do, and I felt all-powerful. The world literally changed under my fingers. I could put in flesh practically any idea that was interesting to me, and any facet of life that I wanted to explore. I have developed an insatiable thirst for programming, which remains with me to this day.
So I would look like in my youth, if there were more spaghetti in programming.The irony is that when I look back at the programs I have written today, I feel endless embarrassment. My old code was the artistic equivalent of kindergarten finger painting. Yes, the drawing
resembles a horse, but only because the child does not understand what he is doing. In the programs I wrote there were a bunch of bugs, they are difficult to read, they are poorly ordered and full of confusing spaghetti logic.
')
But I cannot deny how interesting it was, and how much I learned. I will talk about this in more detail, but first I want to contrast my own experience with how students behave this semester. Their lab work is nothing more than a meaningless data shuffle and implementation of dry, boring functions like
the Horner scheme for calculating polynomials. And (surprisingly) their independent projects are even less interesting. I think the biggest difference is that my students do not really need to solve problems by creating programs. Therefore, their experience is reduced to repeating instructions and to the fact that they pretend to be computers to follow the logic of their own programs.
Of course, I do not want to say that following instructions and simulating a computer in my head are not important for a good programmer. I try to convey that my students are not enjoying their work. Their solutions are as dry as the task itself, and I noticed that they are mostly happy when they finish the task and they don’t need to return to it anymore (even if their solution is completely wrong).
The course also has its own problems. For example, a professor teaches students C paradigms, not Python (I don’t think he learned to do anything correctly in Python at all), and they are confused when he talks about stack frames, registers and all kinds of irrelevant aspects of architecture . Do not forget, these students have never written programs before, and some have started the course barely familiar with the computer. I did not know what a frame frame is until I had been programming for three years (two of which were the years of my first experiments).
All this made me quite often think about what I would teach students in my own course if I had one. In this post, I will talk about how my own study of computer science began. I will highlight the most important aspects: what made me love programming, and what taught me deep concepts on the example of natural contexts.
My first experience was with java
Fortunately, in my high school years (at
Campolindo High , Moraga, California) there was an informatics course. From early childhood I was familiar with computers (from three years, thanks to my parents), I loved video games and knew the basics of HTML, so I inevitably had to get on this course. In retrospect, I consider him perhaps the most useful of all the courses for me, followed by in-depth English, German, and public policy. He not only gave me the aforementioned thirst for programming, but also engendered in me a mathematical grain that had grown many years later into a huge beanstalk, which I have been climbing up to now.
From the very beginning of the course was completely different. The teachers were Mr. Mathers; by the end of the first week the lectures were over. Mr. Mathers showed us the bare minimum to write a simple program that receives and outputs data, and then left us alone with our computers.
Roughly speaking, to complete the course you could choose one of two options. First: follow the progress of classes and small projects from the GUI programming tutorial in Java. Most of the students spent the first two months on assignments, and I, too, at least until I made a stupid little program for a pizzeria that allowed me to order pizza.
The second option was much more free. Students could do anything - Mr. Mathers jokingly told us: “at the end of each quarter, I will evaluate your progress, and if you deserve a five, you will get it, but otherwise you will receive a unit!”
Of course, Mr. Mathers was the nicest person I've ever met. He calmly sat at his computer at the head of the class, and helped the students who approached him with questions. He calmly and quietly listened to the student's question, and then suggested the correct way of seeing the problem. Mr. Mathers better understood the level of student success by how frequent and relevant their questions were, and most often the students standing in line solved their problems on their own before they even got to the teacher.
Most class students chose the path of “ample opportunity,” and this meant that they wanted to develop games. I'm not talking about
good games, I'm talking about games created by high school students. I wrote the ugliest mole game in the world, stupid AI for Sea Battle, a poker machine with Mr. Mathers’s face on the shirt of all cards (it also replaced the faces of all kings, queens and jacks). To create the last game, I even collaborated with other students who used a deck with Mr. Mathers’s face in their card games. The cooperation became even closer in the second year of the course (yes, I took the same course again), but before we get to it, I have to tell you some more necessary details.
First, the network in the office was designed in such a way that Mr. Mathers could remotely monitor from his computer any computer in the classroom. The observation program had the reverent name of "Vision" and the quicktrips trembled before its power. Vision allowed Mr. Mathers to view our code while we were standing in front of his desk, and helped him track students' progress. Secondly, we were allowed to use a shared disk in the school network, so we could transfer files between computers in the office. This gave direct benefits in learning, for example, we could share code examples, sprites and sound files from our programs. But more importantly, it gave the class a sense of common culture. Sometimes we held competitions in which every student of the Photoshop class Mats face into some funny scene (in fact, we used MS-Paint). It was the birth of Internet memes, and naturally, we, the youth, were at the forefront of progress.
Thirdly, we often had days of “research” in which we were freed from all training obligations. We could play games, surf the Internet, just sit and chat. Most often, everything ended up playing Unreal Tournament on LAN, but by the end of my second code I decided to use these days to work on my programs; It was more interesting for me to work on my games than to play other people.
All this gave the course a feeling of relaxation. We were not prepared for intermediate knowledge tests or in-depth exams (although over time I passed them, getting a rather high result, considering that I did not prepare for them at all). Sometimes we were not even forced to work. The course was more aimed at creating a community, and even though we were making fun of Mr. Mathers, we respected him as a teacher.
Like me, most of the students who graduated from the first year are left with one more. And then we began to appear awesome projects.
Zmob
The second year of the informatics course was entirely devoted to games. Moreover, we started thinking about real-time games, such as side-scrolling platformers, which we liked to play (yes, Super Mario Brothers and Donkey Kong Country). I tried to do something similar on my own, but quickly got lost in how to make collisions work. Creating levels, animating characters, and scrolling the screen were challenging tasks, but feasible for me.
One of my first side scrollers, inspired by the Starfox series.But when I got tired of teaching the character to jump on the blocks, I found a better project: Zmob (abbreviated from Zombie Mob). He was inspired by our collaboration. I helped a friend find a way to draw two circles in a special way: one circle was large and stationary, and the second was smaller, always touched the first, and the line between the two centers passed through the position of the mouse cursor. In other words, the smaller circle represented the “direction” of a pair of circles and was always directed towards the mouse. It was a fairly simple trigonometry, but before I understood how to do this, I decided that it would be interesting to work on a zombie shooter with a top view. Therefore, I started this project. This is how the screensaver of the early version of the game looked like (typos and errors were completely saved):
Zmob 1.0 home screenThe player controls the black circle, and the gray circle indicates the weapon. Zombies (blue circles) are regularly created in random positions and move at different speeds right in the direction of the character. The player can walk on the field, and holding Shift, for some time to run faster than they. And of course, the player shoots them until they die, and the game ends when a character dies. The number of zombies created over time increases, and ammunition is limited (however, you can get more ammunition after a certain number of murders), so that the player’s death is inevitable. The goal of the game is to score as many points as possible.
The gameplay looked more like a shepherd’s job than the shooter, and although it was difficult, I don’t think that anyone else would play the game for more than ten minutes.
It was important that I had a lot of ideas, and I needed to understand how to implement these ideas. I wanted the zombies not to pass through each other. I wanted to make a weapon that poisoned a zombie, so that when a poisoned zombie touched a healthy one, it would also poison it. I wanted a lot of things going on in the game, and the solutions naturally came in the form of Java features that I used.
Poison cannon. White zombies are poisoned, blue ones are healthy.For example, in the beginning, zombies were simply indicated by circles. There was no information that distinguished one zombie from another, so I could store them simply as a list of x, y coordinates. When I wanted to add them a strip of life, and different speeds, and learn how to poison them, I had to create
a zombie
class so that each zombie could be asked for its internal state (poisoned or not, fast or slow, etc.). Then I created a player class, item class, and bullet class.
And the bullets were the most interesting part for me. I wanted each bullet on the screen to be updated only when I called the “update ()” function. It turned out that this was similar to the transformation of a bullet into an
interface , from which each specialized class of bullets inherited. I have already seen the need and elegance of object-oriented programming. All this completely eluded me when I made these stupid “Shape” interfaces, repeating after the introductory tutorials. I solved the problem that I needed to solve, and the understanding of inheritance remained forever in my mind.
The logic of the bullets was a pleasure in itself. The first three guns I created were boring: a pistol, a machine gun, and a shotgun. As usual, they scattered small black circles. I wanted to stand out and create a cool cannon. I called my first idea a wave beam.
Wave beam: sinusoidal bullets.The idea of ​​a wave beam was that the bullets move in the direction of a shot along a sine wave. However, for me it became a huge difficulty: how can you turn a sine wave at an arbitrary angle? I had the x and y coordinates of the bullets, but all the sophisticated formulas in which I randomly tried to use sines, cosines, and tangents failed miserably. The best thing I managed to achieve was to get a sinusoid ugly stretched to the sides.
After a week of unsuccessful attempts, I approached my statistical teacher (with whom I still keep in touch) and asked him if he knew the magical mathematical formulas that I needed.
After thinking for a minute, he took out a textbook and showed me a page about the rotation matrix. For the eyes of a seventeen-year-old, this formula was as mysterious as the ancient runes:
As a result, I wrote the following code:
x += frame*Math.cos(angle) + Math.sin(frame)*Math.sin(angle) y += frame*Math.sin(angle) + Math.sin(frame)*Math.cos(angle)
When I ran the code, it worked so perfectly that I screamed with delight. After a week of torment and incompetent attempts to solve the problem, the solution turned out to be elegant, beautiful and wonderful. After that, I used analysis to make my StarFox side scroller look more natural. I experimented with other matrix operations, such as shear and stretch. By the end of that year, I began to better understand the “replacement of the basis” (although I did not even know these words yet) than most of the students who studied linear algebra in college! It was just another coordinate system for space; there were rotated coordinates, increased and stretched coordinates, narrowed and inverse coordinates. I tried all this in search of interesting gameplay.
And I overtook the training program not only in mathematics. By the end of the year I “finished” the game. I created a chain weapon that created chain reactions when it hit a zombie, improved the look by adding new graphics for the player and the zombies. I even developed a smart tile allocation system that measured the size of the screen and the window and correctly displayed the background. I’m tired of measuring dimensions manually, so I wrote a program that did this work. This seems trivial, but in fact this is the core of computer science problems.
The whole class was engaged in “beta testing” of the game, that is, we just spent a few days playing the game and finding bugs. And my classmates found a lot of bugs. Obvious (errors of dividing by zero drove the bullets crazy) and less noticeable (if you correctly calculate the time, the zombies will not be able to get close enough to the player and will just bump against each other).
Another rather important problem emerged - speed. After adding the images, I decided to use the Java library to rotate the images in each frame in the right direction. Today, some say that Java is slow, but this part was
very slow, especially when it came to hundreds and more zombies. My solution, as it happens, turned out to be a programming paradigm called
caching . I calculated in advance all the turns that would be needed in the game, and then saved them. Actually, what I implemented is called
lazy loading . This is a slightly more complicated technique used to store only calculated turns when they are necessary.
I learned the name of this technique only when I got to dynamic web programming, studied in the third year of college, and we discussed the object-relational display of Hibernate data for databases! As in the case of linear algebra, the tasks that I set for myself on my own allowed me to discover or reinvent important concepts much earlier than if I had been taught them. I developed a deep understanding of the concepts and the types of tasks that they can solve. It was completely different from the study that takes place in college: students remember the name of the concept and its meaning, but only the best students manage to understand why it is important and how to use it.
Honest analysis in retrospect
I must admit that I was more devoted to my work than the average student. A small part of the class was engaged only in nonsense. Some students had a goal in their head, but they did not pursue it with the same perseverance as I did. We did not have access to many good examples outside of our own wandering on the Internet and the mediocre quality of the books that Mr. Mathers had. The selected Java language for some probably had a too steep learning curve, but as a result, it did more good than harm.
But on the other hand, those of us who worked well studied everything independently and learned the material at our own pace. We fought with tasks that we ourselves wanted to solve, which led us to new insights. One of my classmates made a chat client and a network version of Tron, others wrote role-playing games, music applications, encryption algorithms, and more. By the end of the course, the width and depth of our collective knowledge was much more than anyone could have expected from
any high school course in any subject . I do not say this at random: I spent a lot of time analyzing the literature, discussing modern problems, memorizing a German dictionary, editing an essay and conducting biological experiments, but programming was a special case. This experience was fascinating, artistic, technical, logical and
intuitive . Moreover, this skill has proven useful to me in the labor market. Today, I can graduate from the master's program and find a good job as a software engineer in any major city and probably in any of the industries in which they are engaged in software. It was this course that set me on the path that I am taking now.
Worst of all,
my heart breaks when my students say, “I didn’t think programming would be like
this .” I'm not ready for this. Best of all, I can answer them: “Do not judge programming in this course. In fact, it can be fun. ”
What do they need
For me, it is absolutely clear - to interest students in programming, they need a couple of things:
1. Instant rewardMy students spend too much time figuring out their own code. Something needs to be changed so that they see the effect right away. They need training tools designed by
Brett Victor (to understand what I'm talking about, rewind the video at 10:30, but it's worth it to watch the whole thing). And they need to work on visual programs. Programs for drawing, games and music. Programs, whose effect can be felt in a non-intellectual way, and not boring checking that they correctly consider derivatives of polynomials.
2. Projects must be meaningful, or at least interesting.As when I was studying myself, students need the opportunity to study. Let them work on their own projects and, as a teacher, have enough knowledge to help them when they reach a dead end (or better yet, brainstorm with them). If creating a project that is unique for each student is impossible, then at least let them work on something meaningful. Alas, in the last two projects of the course, which I teach, students were engaged in the input / output of files and the addition of matrices. Why not let them work on a video game or a search engine (this may seem complicated, but here’s an introductory course on
udacity ), or on drawing / animation, on a chat client, on a sudoku solution? Yes, at least show how to get data from Facebook through the Graph API. All these things can be largely abstract, so that a student of any level can cope with them, and at the same time, each of them requires the ability to work with certain concepts (basics of working with the network for a chat client, sudoku matrix, input-output files in parts of the search engine, etc.). Despite the abundance of interesting things that students can work on, teachers, it seems, simply do not want to give them interesting projects, so again and again they force students to calculate the sums of matrices.
3. The ability to read someone else's code.This is an integral part of learning. Students should not only be able to write their own code, but also read someone else's. They should be able to look at examples and select important parts from them for use in their own work. They must learn to collaborate with their classmates, work on a common project, and brainstorm when discussing bugs. They must learn to
criticize the code, how they can criticize a movie or a cafe. Students should have their own judgments about the software and strive for the correct implementation, openly ridiculing the bloated or chaotic code (well, maybe not so hard, but they still need to be consciously prepared for this).
These three principles underlie computer science and software development, and the rest of the stuff (stack frames, lazy booting and Linux shells) can wait until students are interested and start striving for more. Moreover, it can wait until they have the opportunity to
choose an area that requires knowledge of Linux shells, or web frameworks, or network security, or graphics processing. I learned all the basics and something else without touching the Linux terminal and not even knowing about its existence. And I have no doubt that my current students are also capable of that.
And when students are completely immersed in the code (like me, having spent a year or two writing spaghetti code), they can learn to see the beauty of the elegant ways of organizing programs, and the expressive power that you can have for writing useful programs. In a sense, programming is similar to architecture: a good program has the beauty of form and functionality. At this point, they should start thinking about system and network programming, because then they can compare the new paradigms with their own. They can criticize, discuss and make innovations, or at least appreciate them, and apply ideas to the “zombie projects” they are working on.
I am of the opinion that in every computer science curriculum there should be several courses used as a blank sheet of paper, and in the learning process one of them should be given as early as possible (maybe even as part of the very first course). I think that students are not taught this way for the same reason that in teaching math: proper teaching is
hard work ! No matter how sad it may sound, professors (especially in research educational institutions) do not have time to develop carefully designed student projects.
And while I'm in the training system, I will work to make a difference. I will develop courses so that they are interesting, and help my future employees who do not succeed. Even in highly structured courses, I will allow students to work on free projects.
Therefore, I will add to my wish list of a high school teacher a course called “Programming as drawing with fingers”. (Or "Programming on a clean sheet"? Or "How to kill zombies"?) I am open to suggestions.