Flappy Bot for Flappy Bird

    image
    Crazy game. What lad did not hear about Flappy Bird? About $ 50,000 of income per day? The game is devoted to financial reports, funny songs, yellow articles and scientific research. The Chinese guys even invented a mechanical robot chasing a bird .
    Ah, and I installed the app on my favorite 2007 iPhone. At my age, you look at the download slider and think: Isn't it the last application in your life that you download?
    Yes. I drove the bird for about 20 minutes. I couldn’t go further than the 10th tower. Played another ten minutes. Oh, 22 towers - my ceiling. Nerves to hell.
    And my friend Kirill and I decided to create our own ro-bot. To beat the Chinese tanks, as Ostap said.

    Read how it was and see what happened.
    Under the button is three kilobyte text and a minute video.


    Half franc coin


    First of all, our robot is not mechanical. Pressing the screen can be simulated not with a mechanical stick, but with an electric charge. Glue a coin to the iPad screen. We attach a wire to the coin with a blue electrical tape. You send current to the coin through the wire - iPad is triggered by pressing. In this place you need to say smart words Capacitive screen and it is important to shake your head.
    image
    Of course, there is no photographer from me.

    To control the current you need an iPhone. He shoots a video game running on the iPad, recognizes the point in time when you need to click on the game screen and sends a signal to a coin. How? On the audio wire. We generate a signal with a frequency of 20 KHz and a duration of 20 milliseconds. You can play the wav file, but it is better to simulate the signal programmatically, more precisely. However, the delay from the start of the Pi-and-and-and-and-and-i teamuntil simulated pressing is 100-110 milliseconds. Remember this number.

    Code example? God, this is more boring than ORT news, today without a code, ok?

    So the signal from the iPhone through the audio output runs to the capacitor, the capacitor is connected by a wire to our coin - voila, the circuit works.

    image

    Repeat our plan

    • On the iPad, launch the Flappy Bird game.
    • Glue a coin to the iPad screen
    • Coin connects to capacitor
    • Capacitor connects to iPhone audio input
    • On the iPhone, we write a program that, through a video camera, monitors the game on the iPad and sends a sound signal-command Press, Maleshkin!
    • The capacitor sends current to the coin, the coin simulates a click on the iPad
    • Bird obediently jumping


    According to the scheme, according to the specifications of semiconductors and other electro-technical trinkets, Cyril can answer. But he will not answer, he is modest. There are not many trinkets on the board, sometimes they are weakly shocked if you want to touch them.
    For those who fumble in electrical engineering
    Of course, this is not a capacitor.

    image
    When an audio signal with a level> = 1V pnp is applied, the transistor opens and supplies a logical “1” to the input of the first inverter, causing a change in the polarity of the double-gate FET transistor.

    Opening the FET connects the coin hanging “in the air” with the ground, increasing the capacity measured by the screen to the level that is taken as a touch. The capacity of the gate-drain channel in the closed state is 5pF. The transistor is mounted directly on a coin to reduce the stray capacitance of the connecting wires.
    Prior to this solution, attempts to connect the coin to the transistor with a shielded cable were unsuccessful.

    Not shown in the diagram: the ground of the board is connected to the ground of the tablet with an audio cable.


    Xerox Box


    The mini-studio for the robot was made from a used box. They halved the box, put it on its side, carefully laid the gaming iPad with a pre-glued coin at the bottom. In the ceiling of the box, they made a hole for the iPhone’s camcorder and laid the phone on top so that the camera could see the game screen of the lower iPad. Phew, wait, it's over soon.

    I had to put Bakhvalov’s Numerical Modeling book under the iPad so that the game screen completely fills the video frame.
    All.

    Recognition of the playing field, birds and poles


    It's simple here.
    To begin with, I took a screenshot of the game and in Photoshop measured the color intensity of the blue background, the red beak of the bird and the green pillars as absinthe.

    Since the angles of the field are almost straight, it is not difficult to catch the black frame. It is not necessary to run the entire 1280 array at 720 points of the video buffer. I start diagonals from four corners to finding the first point of the game screen. This is approximately 5,000 comparison operations for each angle. Pennies.

    Yes! I completely forgot.

    What video mode to choose on our iPhone? good frequency required.

    I tried Low-video mode. 192 by 144 pixels. The frequency is 20 frames per second. Not good.
    Standard video capture of 480 by 360 pixels. It gives a frequency of 30 frames per second. Better, but not enough.
    But direct enumeration of video modes finds 60 frames per second with a video resolution of 1280 by 720. The enumeration method is taken from stackoverflow.com.

    P-paradoxically it turns out - the higher the resolution, the more often the frames. What did you want from Steve Jobs? He also presented such surprises.

    For those who rummage in iOS
    @implementation ViewController
    static AVCaptureDevice *cam;
    static AVCaptureSession *sess;
    const float requiredFps = 60.0f;
    - (void)viewDidLoad
    {
        [super viewDidLoad];
    	// Do any additional setup after loading the view, typically from a nib.
        sess = [AVCaptureSession new];
        cam = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
        NSError *err = nil;
        AVCaptureDeviceInput *input = [[AVCaptureDeviceInput alloc] initWithDevice:cam error:&err];
        if (err) {
            NSLog(@"Failed to create AVCaptureDeviceInput: %@", err.description);
        }
        [sess addInput:input];
        AVCaptureDeviceFormat *bestFmt = nil;
        int64_t bestDim = 0;
        CMTime tfps = CMTimeMake(10, 10 * requiredFps);
        for (AVCaptureDeviceFormat *fmt in cam.formats) {
            NSLog(@"Format: %@", fmt);
            for (AVFrameRateRange *fps in fmt.videoSupportedFrameRateRanges) {
                if (fps.maxFrameRate >= requiredFps) {
                    if (CMFormatDescriptionGetMediaSubType(fmt.formatDescription) ==
                        kCVPixelFormatType_420YpCbCr8BiPlanarFullRange)
                    {
                        CMVideoDimensions dimensions = CMVideoFormatDescriptionGetDimensions(fmt.formatDescription);
                        int64_t sq = dimensions.height * dimensions.width;
                        if (sq > bestDim) {
                            bestDim = sq;
                            bestFmt = fmt;
                        }
                    }
                }
            }
        }
        if (bestFmt) {
            if ( [cam lockForConfiguration:&err] ) {
                NSLog(@"Selected format: %@", bestFmt);
                cam.activeFormat = bestFmt;
                cam.activeVideoMaxFrameDuration = tfps;
                [cam unlockForConfiguration];
            } else {
                NSLog(@"Failed to lock camera config: %@", err.description);
            }
        } else {
            NSLog(@"Failed to find a %f FPS format", requiredFps);
        }
        AVCaptureVideoDataOutput *output = [AVCaptureVideoDataOutput new];
        [sess addOutput:output];
        dispatch_queue_t queue;
        queue = dispatch_queue_create("cameraQueue", NULL);
        [output setSampleBufferDelegate:self queue:queue];
        [output setVideoSettings:[NSDictionary dictionaryWithObject:[NSNumber numberWithInt:kCVPixelFormatType_32BGRA] forKey:(id)kCVPixelBufferPixelFormatTypeKey]];
        [self.view bringSubviewToFront:cameraReal];
        cameraReal.transform =CGAffineTransformMakeRotation(M_PI_2);
       //   [sess startRunning]; turn on/off when view appear/disappear
    }
    - (void)viewWillDisappear:(BOOL)animated
    {
         [sess stopRunning];
        [super viewWillDisappear:animated];
    }
    - (void)viewWillAppear:(BOOL)animated
    {
        [sess startRunning];
        [super viewWillAppear:animated];
    }
    



    I conclude. White crosses on the video mark the corners of the boundary of the playing field. I calculate every time, although this is not necessary. A bird is marked with a red cross, I must calculate these parameters every measure. Knowing the time, knowing the coordinates of the bird, it is easy to calculate its speed. It is also easy to calculate the bird's jump speed after clicking and the acceleration of gravity. 2000 pixels per second per second, Vietnamese like round numbers))

    Why know the speed? Due to a delay in the click command of 110 milliseconds. We have to calculate the parabola of the bird's movement in order to pickle in advance.

    The algorithm is not yet perfect, because it was created during today's Friday.
    But our bird takes 100 pillars quite often. Once or twice a night she could, gold, not a bird.

    I think it is easy to bring this matter to 1000 and calm down.

    Everyone enjoy watching.



    Attention Advertising


    Of course, I wrote my clone of this game. Nobody downloads the game, it is secret, but especially for you, dear readers, I give a link to the Winter Jumping application .
    In honor of her birthday, she is free and without ads.

    thanks


    Thanks for attention.

    Also popular now: