Growing up is a process of losing.

The author is a post-90s generation.

As a child, everyone’s home conditions are poor, the means of entertainment is very poor. Unlike today’s children can play mobile phones, tablets and computers, at that time, a stack of small raccoons water Margin cards can play for a whole day, if there is a rare card, such as what Song Jiang, Lu Junyi, Huyanzhuo, that behind the buttocks will surely follow a long list of fans to pay tribute to.

And if there is anything in the world more enviable than this, it is absolutely can have a small overlord learning machine at home. Although the name of learning wubi coax parents to buy, but no one really buy this is used to learn, right? The head.

A learning machine, a cassette, a gamepad, a cassette (Requiem, Charo Slow Snake, Tank Wars, Teenage Mutant Ninja Turtles, Double Cut Dragon, Super Mario Bros., etc.), how to quickly cool that pile of hot black power adapters make up countless happy childhood memories. Now that the graphics are more gorgeous and the mechanics more complex, it’s hard to experience the pure joy of a simple pixel game.

Growing up is really a process of losing.

I’m going a little too far, but back to the point. So, I will take you together, hand in hand to make a small overlord learn (you) xi (XI) machine, and play games on it, recall the happy time when I was a child, didi.


To do a good job, he must sharpen his tools. — “The Analects of Confucius · Wei Ling Gong”

MCU × 1.

Here, it looks like this.

What is the single chip microcomputer?

In simple terms, SCM is a computer, but a lot of peripherals.

How to choose microcontroller?

For starters, I recommend an Arduino development board that is easy to use and has a vibrant community, even though it is derided by industry insiders as a toy. The model that the author buys is UNO R3, a cat a dog has to sell, meaning stay li edition more than 100, motherland edition dozens of pieces.

What is a development board?

The development board is suitable for study and experiment, and provides more pins: easy to implement functions, and supporting parts: such as communication serial port, program firing port, reset button and so on. The development board is fully functional, but also large in size. In actual production, all of these things may not be needed.

How does SCM work?

You’re gonna talk to me about that. I’m not sleepy. Here is only a brief introduction about, because the author is only an amateur.

Let’s start with the pins. Pins are like human senses that receive feedback. Pins can be input or output. Pin state, classified as high level and low level. , the pin level state affects the external devices it is connected to, as shown in Hello World below.

In essence, the program burned into the development board is to control the level of each pin, plus a variety of logic gates to form a more complex state, small to the light on and off, to control the aircraft, can be represented by 01.

Can not help but let a person sigh the wisdom of ancestors, quite a kind of: tao sheng one, life two, two three, three living things feeling.

Once the development board is powered up, it is programmed to repeat [input -> calculation]. The process is familiar to those who have learned computer: reading instructions, retrieving data from registers, calculating results by CPU, and finally saving the results back to registers.

FBI Warning, the above author’s ignorance, if there is a mistake, welcome to correct.

Four pin key switch x 3.

I’ll put a cute little green hat on you.

Press the one that goes “tick-tock”, same as the Overlord handle.

Male to male Dupont line several.

The thoughtful partner will ask, since there are male, that there must be female? I’m just going to show you a picture.

220 ω resistance x 3.

Is the resistance 220 ω?

For those who have not learned electrical engineering knowledge, you only need to understand that the order of the resistor color circle is: red, red, brown and yellow.

Bread board times 1.

It’s like a Lego base. We’ll talk about that later.


Hello World! – Brian Kernighan

Hardware is nothing without software. So let’s take a quick look at the syntax of Arduino.

To the website (www.arduino.cc/en/software… IDE (web version, in order to facilitate the upload procedures, or download the client). The IDE is already very simple and supports Chinese, so I won’t go into details.

A simple LED lamp experiment.

Hardware connection: development board pin N -> 220 ω resistance yellow end -> LED positive pole (foot long end); LED negative -> Development board GND (can be understood as power negative). Resistance is added to reduce the current flowing into the LED and prevent it from burning out the device. Considering that some friends may not be able to see the schematic diagram, so directly on the photo.

Start writing programs (Arduino is a C-like language) :

// This function is executed only once
void setup(a) {
   // Set pin 6 as output, N above
   pinMode(6, OUTPUT);
}

// This guy will execute in a loop
void loop(a) {
   digitalWrite(6, HIGH); // High level on
   delay(1000);
   digitalWrite(6, LOW); // The low level is off
   delay(1000);
}
Copy the code

Click the button in the red box below to upload the application to the development board.

IF the upload fails, click Tools -> Port to check whether the correct COM (Windows) or device (Linux) is selected. IF correct, you need to install the driver (www.arduino.cn/thread-1008…

If all is well, you can see the yellow light flashing on the development board, indicating data transmission. Upload after completion, your small light bulb on repeat a second, extinguish a second of the process, sprinkle flowers.


Let the game begin. – medivh

Let’s assemble this first. Not the author hypocritical ah, the word is not the author P, the original picture has!

Because the author does not have enough four corner keys, so only 3, each in addition to connect the board pin is not the same, the rest of the connection method are consistent. Turn the button over, you can see the label 1234 next to the pin. Note that 12 can be energized, 34 can be energized (direction is not important), but 13,24,14,23 can not be connected.

Connection: pin N -> key pin 1, key pin 2 -> 220 ω resistance yellow end, 220 ω resistance red end -> development board 5V; Button pin 3 -> Development board GND.

It is normal to find that the button has a leg that is not used. Do the same for the rest.

If you are careful, you will find that the development board has only two GND buttons, so it is not enough to connect one BUTTON to one GND.

This is when you need to insert dupont wire into a special area of the bread board. As shown in the figure, the part between the red and blue lines on both sides of the bread board is connected horizontally, and all the feet of this row are considered to be connected to 5V or GND. And the middle of the loaf is vertically connected, so notice that.

Then write a program to read the key signal, not to say much, everything is in the code:

 // Here is the pin number
const byte left = 7;
const byte right = 8;
const byte act = 9;

 // Here is the pin state
byte leftHit;
byte rightHit;
byte actHit;

void setup(a) {
  pinMode(7, INPUT);
  pinMode(8, INPUT);
  pinMode(9, INPUT);
  // The new guy, here in the serial port initialization, used to receive, send data
  Serial.begin(9600);
}

void loop(a) {
  // Read the level of the four-pin key
  leftHit = digitalRead(left);
  rightHit = digitalRead(right);
  actHit = digitalRead(act);
  // When pressed, the level is LOW
  if (leftHit == LOW) {
    sendSerial(0);
  }
  if (rightHit == LOW) {
    sendSerial(1);
  }
  if (actHit == LOW) {
    sendSerial(2);
  }
  // Because the release time is a long time for the program
  // There is a delay to reduce the frequency of sending data
  // In the case of games, you can't hold it all the time.
  delay(100);
}

void sendSerial(byte data) {
  // When sending data, interrupt to ensure timing
  delayMicroseconds(2);
  Serial.print(data);
  delayMicroseconds(2);
}
Copy the code

So far, So good, come and test it. After uploading the program, open the IDE tools -> Serial port monitor (uploading the program will take up the serial port, so wait until the program is uploaded), adjust the baud rate to 9600 in the lower right corner, IF the hardware connection is correct, every time you press a button, the monitor will display the corresponding value.

Now that we have the controller, it’s time to write the game.


Hello World! Again!!! – Brian Kernighan

As I am a layman in game development, I choose the relatively simple Processing language for development. Processing was originally used for image design, and here it is used to do a more partial thing. Given that most of you have probably never heard of this guy, let’s take an example of how Processing works.

As usual, go to the official website (processing.org/download/) free… IDE. The interface is very similar to Arduino, so I won’t talk about it much.

Demo:

// Same as Arduino, a setup function, a loop function
void setup(a) {
  // Set the canvas size
  size(200.200);
}

// Just like Arduino, you can check the frame count of the game through endless loops
void draw(a) {
  // Set the background to black. For details, see the official website
  background(0);
  // Fill the following elements with white
  fill(255);
  // Draw a circle with a radius of 80 pixels centered around the mouse coordinates
  ellipse(mouseX, mouseY, 80.80);
}
Copy the code

Click “Run” in the upper left corner. IF the code is correct, a black box will pop up. After the mouse enters, a white circle will follow the mouse movement.

For a slight change, define an int x = 0 before setup, and then increment it x++ at the end of draw. Change the ellipse parameter to Ellipse (x, 40, 80, 80), and the circle will move from left to right.

Similarly, any function provided by Processing can use variables to control the attributes or behavior of elements.

IF you comment out the background, everything that the circle moves will leave a circle behind.

Why emphasize this single point? Of course, some elements will be retained or removed later using this feature.

At this point, you have the basics of Processing for writing games.


Everything is ready except the east wind. – the various ge is bright

Many foreshadowing in front, finally ushered in the final yan moment. Start writing the masturbating game now. In general, normal programming, the actual coding time ratio is 8 to 2. So don’t worry. Get your head together.

I refer to the classic game Bee.

Game type: Flying shooting

Victory condition: eliminate all enemy aircraft

Failure condition: Player is shot

Human-computer Interface (HMI) :

  • At the top of the screen are three rows, each with six enemy planes. Enemy behavior is: side to side, shooting.

  • At the bottom of the screen is the player, 1 plane. The instructions were: move left and right, shoot.

  • Game process: Press any key to start the game; The player is shot or enemy aircraft all out, the middle of the screen prompts the corresponding text, the game is interrupted; When interrupted, press any key to start a new game.

Here’s what the player sees, and here’s what’s inside:

Movement: Very simple, changing the x and y positions of player and enemy aircraft.

Shooting: Creates a bullet, enemy bullet moves down, fixes x axis, changes Y axis, player bullet moves in opposite direction.

Collision determination: The hardest part, determining whether the bullet hit an object. Because every frame, every bullet has to be counted, when there are a lot of bullets on the screen, the count increases exponentially, and if not optimized properly, the cycle of violence can get stuck and lead to a poor player experience.

We’re almost done. Work it out. Processing provides multiple language schemas, and the one I chose was Java (upper right corner of the IDE).

// Start with the main character
class Ship {
  // The current position
  int sx;
  int sy;
  // Move speed
  int speed = 6;

  Ship(int initX, int initY) { 
    sx = initX;
    sy = initY;
  }

  void display(a) {
    // Player's plane is a 40x26 picture, you can change it to your own image
    image(shipShape, sx, sy, 40.26);
  }

  void drive(int direct) {
    // Move left
    if (0 == direct) {
      sx = sx - speed;
      // Can't fly off the screen
      if (sx <= 0) {
        sx = 0;
      }
      return;
    }
    sx += speed;
    int right = width - 40;
    if (sx >= right) {
      sx = right;
    }
  }
}

PImage shipShape;
Ship ship;

void setup(a) {
  size(600.360);
  // The file path is the same level as the Process file
  shipShape = loadImage("resource/ship.png");
  ship = new Ship(280.324);
}

void draw(a) {
  / / turn to fly
  // ship.drive(1);
  ship.display();
}
Copy the code

Now you can control the plane by calling ship’s Drive method. Enemy aircraft class is about the same, here will not repeat the code.

Wait, how do you respond to Arduino buttons? Actually already answered this question before, serial communication!

import processing.serial.*;

Serial port;

void setup(a) {...// The break rate should be the same as Arduino
  port = new Serial(this.{your serial port/device}.9600);
}

void draw(a) {
  if (port.available() <= 0) {
    return;
  }
  // The output data of Arduino needs to be changed to its own definition
  int coming = port.read();
  switch(coming) {
  case 48:
    ship.drive(0);
    break;
  case 49:
    ship.drive(1);
    break;
  case 50:
    // The attack method of aircraft is not defined yet
    ship.attack();
    break; }}Copy the code

The logical thing to do now is to write the attack logic, but you need bullets to hit, so write the bullet object code first.

class Bullet {
  int bx = 0;
  int by = 0;
  int speed = 5;
  // Public bullet class, call different methods to fly up, or down
  boolean up(a) {
    by -= speed;
    image(bulletUp, bx, by, 2.14);
  }

  boolean down(a) {
    by += speed;
    image(bulletDown, bx, by, 2.14); }}// Use different images to distinguish enemy bullets
PImage bulletUp;
PImage bulletDown;
// New bullet here for demonstration purposes
Bullet bullet = new Bullet();

void setup(a) {... bulletUp = loadImage("resource/bullet_up.png");
  bulletDown = loadImage("resource/bullet_down.png");
}

void draw(a) {... bullet.up(); }Copy the code

Next, the attack.

// Add attributes and methods to the bullet class
// Whether to display
boolean alive = false;

/ / cop
void trigger(int initX, int initY, int initSpeed) {
    alive = true;
    bx = initX;
    by = initY;
    speed = initSpeed;
}

// Bullets don't need to be displayed when they fly off the screen
void clean(a) {
    alive = false;
    bx = 0;
    by = 0;
}

// Change the up down method
boolean up(a) {
  by -= speed;
  // The reason this is negative is because it is removed after the bullet has completely flown off the screen
  if (by <= -14) {
    return false;
  }
  image(bulletUp, bx, by, 2.14);
  return true;
}

boolean down(a) {
  by += speed;
  if (by >= height + 14) {
    return false;
  }
  image(bulletDown, bx, by, 2.14);
  return true;
}

// Add attack methods for aircraft
void attack(a) {
  // Sorry, we only take dormant bullets
  if(! bullet.alive) {// The bullet's initial X-axis position, 5 is the bullet's speed
    bullet.trigger(sx + 20, sy, 5);
    break; }}void draw(a) {...// Only live bullets are displayed
  if (bullet.alive) {
    if(! bullet.up()) {// Goodbye, bullets flying off screenbullet.clean(); }}}Copy the code

To control the number of bullets on the screen, I didn’t just press the attack button to create a new bullet. Instead, you create a container, and you put some in beforehand. When the container runs out of bullets, it no longer responds to attacks, and when bullets fly off the screen, it wakes them up for later use.

And finally, the hardest part, the crash test.

The author’s idea is the simplest violent way, fake code is as follows:

intLen = number of enemies leftfor (int i = 0; i < len; i++) {
    // Calculate the upper, lower, left, and right boundaries of the enemy. The enemy is 28 x 38 square
    // int top = enemy.pool[i].ey;
    int bottom = enemy.pool[i].ey + 28;
    // int left = enemy.pool[i].ex;
    int right = enemy.pool[i].ex + 38;
    intLen2 = Number of live bulletsfor (int j = 0; j < len2; j++) {
      Bullet tmp = bullet[j];
      // Although the bullet has width, I am lazy to treat it as a dot
      if (tmp.bx > enemy.pool[i].ex && tmp.bx < right && tmp.by < bottom && tmp.by > enemy.pool[i].ey) {
        // If this point overlaps with the enemy block, then the enemy is hit
        enemy[i].alive = false;
        // The bullet hits the object and disappearstmp.clean(); }}}}Copy the code

It’s functional, but it’s still too crude. So the author of a small optimization, ugly.

Because the y axis of the player and the enemy is fixed, I created two containers. Each time a bullet refreshes, load the bullets that enter the enemy’s Y-axis movement area and the player’s Y-axis movement area, and then modify the code above to only iterate through the bullets in these two containers. This greatly reduces the number of iterations. The next time you refresh the screen, empty the container again. Of course, the more mature approach is to use the algorithm to speed up the calculation, but the author has limited ability, no practice.

The rest of the work is easy.

Loop to instantiate enemies and players. Enemies are set to attack with a random number each time they move. The draw loop determines whether the game should continue by determining whether the player has been hit or whether enemies have been wiped out. By the time I finished, I had less than 400 lines of code. The final effect is as follows:

The complete code can be found in the repository (gitee.com/kyzx/mutali…

With these skeletons, you can go crazy with your imagination. Things like moving planes up, down, left, and right, adding health bars for players and enemies, bullet trajectories, bullet cancelling bullets, score mechanics, etc.


I’ve written so much before I know it.

As I recall, this process was fraught with difficulties and there was no expert guidance around me. However, relying on the powerful tool of the Internet, THE author still managed to complete it with stumbling difficulties. The sense of accomplishment is self-evident.

This game is really easy to play, even compared to those games on yellow cartridges. But from 0 to 1, the process of groping is the same as when I was a child playing the game, pain and happiness.

May you always be a teenager.