Game development on Processing with control via Arduino Uno board, part 2

    Introduction


    In a previous article , an example of creating the simplest one-dimensional game - “a la avoid collisions” was considered. With such a set of abilities SHG clearly does not live up to its name. In fact, a dodging ball is obtained, which does not sound proud. So why not expand the capabilities of the "gameplay" and add an element of interactivity to the game?
    To begin with, it is proposed to transfer the action of the game to the plane. Introduce the victory condition into the game - an account, upon reaching which, the cherished “You won” cherished message will appear. Issue the ShG a pacifist tool for faster points and interaction with the ShP , if possible change the visual design of the project to a more attractive one.
    Actually, I took up the solution of these problems as part of my next “weekend” project. What happened, read on.

    Step 1 “Development Task”


    -ShG must have 2 degrees of freedom.
    -SHG has the ability to quickly score points and slow down the speed of movement of the silos by means of hitting the last special beam.
    -Implement new rules - the game is played up to 1000 points. For a simple avoidance of a collision, 1 point is awarded. For keeping the beam on the ball, +1 point for every 50 * 10 ^ -3 s (a delay of 50 ms is set in the Arduino program)

    Step 2 “Description of connecting an analog stick”


    The stick has 5 pins for connection: VCC pin connects to + 5V power, GND - to ground on the Arduino Uno board, X - to analog input A0, Y - to A1, D - to digital input D2.

    Step 3 “Transferring Multiple Coordinates over a Serial Connection”


    The position data of the stick is transmitted together in order to ensure their processing as quickly as possible without a time delay. To describe the current position of the analog stick, 7 bits XXXYYYB are enough - 3 for the X coordinate, 3 more for the Y coordinate, 1 bit for controlling the button on the stick. I enclose the code below:
    Code for Arduino Uno Board
    #include 
    int xPin = A0, yPin = A1, buttonPin = 2;
    int xPosition = 0, yPosition = 0, buttonState = 0;
    char strbuf[20]; //
    void setup() {
      // initialize serial communications at 9600 bps:
      Serial.begin(9600); 
      pinMode(xPin, INPUT);
      pinMode(yPin, INPUT);
      //activate pull-up resistor on the push-button pin
      pinMode(buttonPin, INPUT_PULLUP);   }
    void loop() {
      xPosition = map(analogRead(xPin),0,1023,0,639);
      yPosition = map(analogRead(yPin),0,1023,0,639);
      buttonState = digitalRead(buttonPin);
      sprintf(strbuf,"%03d%03d%1d",xPosition,yPosition,buttonState);
      Serial.println(strbuf); 
      delay(50); }// add some delay between reads
    

    After connecting the stick and Arduino Uno firmware, you can see something like the following in the Serial port monitor.

    This is the stick state vector in the format we defined. By the way, sometimes artifacts “slip” - degenerate vectors from 2 3 bits. Extremely unpleasant phenomenon. Because of them, the game at Processing "crashes." Perhaps this is due to a defect on my stick board, maybe not. In any case, I did not begin to deal with artifacts at the Arduino level. For this, a special condition is provided in the game code for Processing (see Step 4). Its task is to verify the integrity of the transmitted data over the Serial connection.

    Step 4 “Encoding the game”


    I will not comment in detail on the code. I tried to make it understandable. Evaluate whether or not you can under the spoiler. Just in case, I bring a table of variables:
    radiusOfHero-radius of the SH;
    radiusOfEnemy - ShP radius;
    radiusOfBullet - bullet radius; produced SHG;
    Counter - point counter;
    speedOfEnemy - coefficient directly proportional to the speed of falling of the silos;
    DeltaPositionOfHeroX - increment of the position of the SH along the X axis, obtained from the stick;
    positionOfHeroX1 - the final coordinate of the movement of the SH along the X axis (at the end of the read clock);
    positionOfHeroX0 - the initial coordinate along the X axis (at the beginning of the measure);
    DeltapositionOfHeroY, positionOfHeroY1, positionOfHeroY0 - the same along the Y axis;
    strbuf is the line into which readings of the status of the analog stick transmitted from Arduino Uno are read.
    Processing Game Code
    import processing.serial.*;//I/O library
    Serial port;
    PShape bot;
    PFont font;
    PImage img;
    int radiusOfHero=100, radiusOfEnemy, radiusOfBullet=5, Counter=0, Fire;
    float speedOfEnemy=1, DeltaPositionOfHeroX, positionOfHeroX1, positionOfHeroX0=640.0,
    DeltapositionOfHeroY, positionOfHeroY1, positionOfHeroY0=640.0,
    positionOfEnemyY = 0.0 ,positionOfEnemyX=0.0, positionOfBulletX=0.0,positionOfBulletY=0.0;
    String strbuf="3223220";
    void setup()
    {
      size(640, 640);
      port = new Serial(this, "COM4", 9600);
      port.bufferUntil('\n');
      bot = loadShape("2.svg");
      font = loadFont("AgencyFB-Bold-200.vlw");
      img = loadImage("img.png");  // Load the image into the program  
      textFont(font,200);
    }
    void draw() {
        background(0);
        image(img, 0, 0);
        fill(255);
        text(Counter, 400,170);
    //==========definiton of hero==========
    fill(0, 200, 102);
    positionOfHeroX1=positionOfHeroX0+(0.05*(DeltaPositionOfHeroX-width/2));
    if (positionOfHeroX1<0){positionOfHeroX1=0.0;}
    if (positionOfHeroX1>width){positionOfHeroX1=width;}
    positionOfHeroY1=positionOfHeroY0+(0.05*(DeltapositionOfHeroY-height/2));
    if (positionOfHeroY1<0){positionOfHeroY1=0.0;}
    if (positionOfHeroY1>height){positionOfHeroY1=height;}
    ellipse(positionOfHeroX1, positionOfHeroY1, radiusOfHero, radiusOfHero);
    positionOfHeroX0=positionOfHeroX1;
    positionOfHeroY0=positionOfHeroY1;
    fill(244);
           positionOfBulletY= positionOfHeroY1-radiusOfHero/2;
          if (Fire==0){
                for(int i = 0; i < (positionOfHeroY1); i++){
                          positionOfBulletX = positionOfHeroX1; 
                          positionOfBulletY= positionOfBulletY-height/100;
                          ellipse(positionOfBulletX, positionOfBulletY, radiusOfBullet, radiusOfBullet);           }
                           }
    //===============definition of enemy===============
    fill(255,0,0);
    radiusOfEnemy=round(random(60));{
       for(int i = 0; i < height; i++) 
         positionOfEnemyY=positionOfEnemyY+0.02*speedOfEnemy;
         ellipse(positionOfEnemyX, positionOfEnemyY, radiusOfEnemy*2, radiusOfEnemy*2); }
            if (positionOfEnemyY>height) {
            positionOfEnemyY=0.0;
            positionOfEnemyX = round(random(width)); 
            Counter++;}
    //==========definition of counter==========        
            if (Counter>1000){
            text("YOU WON!", 50,height/2);
    }
    //==========clash==========
    if (abs(positionOfHeroX1-positionOfEnemyX) < (radiusOfHero+radiusOfEnemy)/2 & 
       (abs(positionOfHeroY1-positionOfEnemyY) < (radiusOfHero+radiusOfEnemy)/2)){
    background(255,0,0);
    shape(bot, positionOfHeroX1-radiusOfHero/2,positionOfHeroY1-radiusOfHero, 100, 100);  
    Counter=-1;
    fill(255);
    textFont(font,150);
    text("TURN AWAY!", 0,height/2);}
    //==========Checking of target hit==========
        if (((abs(positionOfBulletX-positionOfEnemyX) < (radiusOfBullet+radiusOfEnemy)/2))& (Fire==0))
          {speedOfEnemy=0.05;// decreasing of enemy speed
          Counter++;}
        else speedOfEnemy=0.2;}
    void serialEvent (Serial port) {
      if(port.available()>0){
       strbuf=port.readStringUntil('\n'); 
    if (strbuf.length()<7) {//condition to prevent artefacts
    strbuf="3223220";
      }
    DeltaPositionOfHeroX=float(strbuf.substring(0, 3)); 
    DeltapositionOfHeroY=float(strbuf.substring(3, 6)); 
    Fire=int(strbuf.substring(6, 7));
    }
    }
    

    Step 5 “Demonstration”




    Also popular now: