Wednesday, October 31, 2018

Midterm Update 1

After reviewing the each other's proposals I had a really good exchange with Kyle where he mentioned a site called the Library of Babel which is based on the book of the same name which does something along the line of generating every line of characters possible in theory and bookmarking it. I thought it was an interesting idea to try and wrap my project around language in that sense.

My original project was more story based an honestly I've never touched a self automated system before in coding so it's all new territory so I have little estimate on how feasible it is. As it is now I still want the program to proceed through a narrative instead of stagnating on a single scene, it's a minor but significant detail as currently I'm focusing on forming the basic functions for producing language.

This whole line of thinking is really stretching my definition of will and when a mass of conflicting goals starts producing compromises and behavior. It has me remembering the animated film Ghost in the Shell (1995) that I unfortunately lent to a friend prior to the project but the thesis of the film was how a mass of information and instructions eventually produces a conflicted self determined system.

What I have currently working in my project is dialogue class that can print itself out as well as generating words that vary consonants and vowels to at least be readable for English speakers. Part of that class allows me to generate a selection of words that the viewer can respond with. I'm currently moving onto developing an actual class to store and respond to the words.



Currently I'm still planning on using bacteria as the archetype for positive and negative responses as well as setting basic goals for the program such as constructing new strings and using words together to build context as primitive sentences. My current workflow can be seen as this:

  1. Create words and output them.
  2. Memorize words and viewer's response.
  3. Sort words based on if the response is negative or positive
  4. Attach words to the context of nouns or verbs that respond positive or negative when connected
  5. Output a new response by attaching words with connected meaning.
As of today I'm currently on step 2 however coding the next steps should not be a lot of code but simple modules of looping code that need to fit into each-other. I'm going to give myself until Monday to finish this behaviour to make sure I don't sink all my time into overdeveloping a single piece of the project. If I don't complete it I'm confident even a basic primitive function will work to complete the project. 



Wednesday, October 24, 2018

Midterm Project


Digital art has the benefit of interactivity and commercially they're labeled video games but I have my gripes for how formulaic it is. As it sits video games are more resembling of a sport or a toy, there's few of them that hold a narrative or artistic intent while they remain focused on entertainment value. There was one game director name Yoko Taro who in short is know for making mostly bad games with good stories, one of the talks he did he said that what he found was important about video games was the medium of interactivity as unique to games and the focus for giving the player an experience. I think his idea around game design  and AI is close to paralleling the reading we were given for the project where different artists end up focusing on different parts of computer generated graphics like biology, behavior, mathematics but in the end the emerging technology is always open to new inventive artistic expressions.



For my project I want to focus on building a meaningful action into what the viewer decides to do. I want to act as a short story that responds to the audience. As the viewer gets deeper into the story I want to implement more of the Artificial Life ideas in the reading to shift the tone from a prescripted story to a more organic self active system, one that can agree and disagree based on the information it gets from you.
This type of response came to me when I thought of how the reading described Artificial Life (A-Life) characters in novels are nothing more than words on paper and at most internalized personalities but in code characters function inside a the computer through the transfer of information, it made me think about what the difference is between a Roomba vacuum using walls to navigate a carpet and a bacteria chasing a tasty chemical scent. To be more specific if I built boolean that was called pleasure and one called pain is turning them on and off different than the pain and pleasure an insect feels? Sure there is evolution and life but the what we describe as self has more to do with information and navigating the best from the worst. I think even in a barebones form I would like to attempt to include this idea into my story.
What I want to do through dialogue is closer to a novel where the character is more the words I've printed being imagined as a person but I think that along with some surreal graphics I can invest the viewer into making meaningful choices even if it's just an illusion.

For this project Im very confident in utilizing classes and for loops which is what the dialogue printing in this earlier test video relies on. I've used the substring function to take slices of the string and print them out in paragraph form, the working version moves to the next line of text on a button as well it waits for me to add more text which is essential to adding events between scenes. For the meantime Im limiting myself to focus on fleshing out the story in text form before adding visuals and then more interactivity like after declaring your character has done an action it cuts to the viewer acting out that action with interactions. I've set up my workflow as such because I know the workload can become very bloated when it comes to manually writing events instead of relying solely on looping code so I want to build it in stages that prioritize the writing and then adds in additional elements with remaining time.

I havent decided entirely on the assets yet however Im currently relying on processing to produce graphics since that allows me to control more organic effects I think once I get further in I can be confident in applying them without worrying about aesthetic consistency.



Wednesday, October 10, 2018

Processing Classes Practice


Can be played here: https://www.openprocessing.org/sketch/605087


CODE:

//MAIN

//empty vector for using Vector functions
Vector useVector = new Vector();
Entity useEntity = new Entity(0);
//empty collision for using collision functions

//player Object
Entity player;//movement input
char[] moveKeys = {'d', 'a', 'w', 's'};
//movement values
int[] moveValues = new int[4];
//movement Vector
Vector moveVector = new Vector();
//movement Velocity
Vector moveVelocity = new Vector();
float playerSpeed = 5;

//Game Timeline
boolean startGame = false;
float gameTime;

//playerAttack
//bulletList
ArrayList <Bullet> bulletStack;
Vector playerBSpawn;
boolean attackPress;
float attackPause = 8;
float attackCycle;

//Enemies
Entity dummy;
//Enemy List
ArrayList <Entity> enemyList;
//enemy bulletList
ArrayList <Bullet> EBulletStack;
//Enemy Sequence
int ESequence;

void setup()
{
  size(1080, 720);
  //all colliders will be based on radius from the center of objects
  rectMode(CENTER);
  //set bullet stack to an empty ArrayList
  bulletStack = new ArrayList();
  //start position of the player
  player = new Entity(40, new Vector(width/2, height/1.2));

  //Enemies
  EBulletStack = new ArrayList();
  //
  enemyList = new ArrayList();
  //enemyList.add(dummy);
 
  //enemy Setup
  enemyTypes();
}

void draw()
{
  //background(255, 240, 200);
  fill(255, 240, 200, 150);
  rect(width/2, height/2, width, height);
 
  movePlayer();

  drawBullet();

  damageHit();

  enemySequence();
}

//
void mousePressed()
{
  attackPress = true;
}

void mouseReleased()
{
  attackPress = false;
}

void keyPressed()
{
  for (int a = 0; a < moveKeys.length; a++)
  {
    if (key == moveKeys[a])
    {
      moveValues[a] = 1;
    }

    if (key == ' ')
    {
      attackPress = true;
    }
  }
}

void keyReleased()
{
  for (int a = 0; a < moveKeys.length; a++)
  {
    if (key == moveKeys[a])
    {
      moveValues[a] = 0;
    }

    if (key == ' ')
    {
      attackPress = false;
    }
  }
}

void movePlayer()
{
  //direction input
  moveVector = new Vector(moveValues[0]- moveValues[1], moveValues[3] - moveValues[2]);
  moveVelocity = new Vector(moveVector.x * playerSpeed, moveVector.y * playerSpeed);
  //apply movement
  player.position = useVector.addVelocity(player.position, moveVelocity);

  //playerAttack
  //attack cooldown
  if (attackCycle > 0)
  {
    attackCycle--;
  }
  //attack when the attack cooldown is back at 0
  if (attackPress && attackCycle <= 0)
  {
    playerBSpawn = new Vector(player.position.x, player.position.y-35);
    //create a new bullet
    Bullet a = new Bullet(playerBSpawn, new Vector(0, -13));
    bulletStack.add(a);
    //start attack cooldown
    attackCycle = attackPause;
  }
  //draw the player
  player.drawCirc();
}


void drawBullet()
{
  //according to google "for(class : Arraylist){}" checks for every class in a array of classes,
  //useful but not my own work.
  /*for(Bullet stack: bulletStack)
   {
   stack.drawBullet();
   stack.moveBullet();
   }*/

  //move and draw each bullet in the stack
  for (int a = 0; a < bulletStack.size(); a++)
  { 
    fill(200,100,255);
    bulletStack.get(a).moveBullet();
    bulletStack.get(a).drawBullet();

    //delete the bullet if it's out of bounds
    if (bulletStack.get(a).deleteBullet())
    {
      bulletStack.remove(a);
    }
  }

}

//Damage
void damageHit()
{
  //HIT ENEMIES
  if (enemyList.size()>0)
  {
    for (int b = 0; b < enemyList.size(); b++)
    {
      //fix out of bounds bug
      if (bulletStack.size()>0)
      {
        for (int a = 0; a < bulletStack.size(); a++)
        {
          //attack test

          //use collision boolean method on bullets and target
          if (useEntity.attackCollision(bulletStack.get(a), enemyList.get(b)))
          {
            bulletStack.remove(a);
          }
        }
      }
      //if enemy has health
      if (enemyList.get(b).health > 0)
      {
        enemyList.get(b).drawCirc();
      } else
      {
        enemyList.remove(b);
      }
    }
  }

  //PLAYER damage
  if (EBulletStack.size() > 0)
  {
    for (int a = 0; a < EBulletStack.size(); a++)
    {
      //use collision boolean method on bullets and test dummy
      if (useEntity.attackCollision(EBulletStack.get(a), player))
      {
        EBulletStack.remove(a);
      }
    }
  }
}

boolean onEnemy;

//bugger type enemy
Entity bugger;

Entity skimmer;

Entity rusher;

Entity doozers;

void enemyTypes()
  {
    //
    dummy = new Entity(100, new Vector (width/2, 100));
    dummy.health = 25;
    dummy.lifeSpan = -10;
    dummy.moveSetup(new Vector(), 50, 20, .05);
   
    //
    bugger = new Entity(50, new Vector());
    bugger.lifeSpan = 600;
    //bugger.attackSetup(new Vector(0,3), 1);
    bugger.attackSetup(new Vector(1,2), 1);
    bugger.attackSetup(new Vector(-1,2), 1);
    bugger.moveSetup(new Vector(0,1), 70,0, .05);
    //
    skimmer = new Entity(70, new Vector());
    skimmer.health = 20;
    skimmer.lifeSpan = 600;
    skimmer.attackSetup(new Vector(2,2), 1);
    skimmer.moveSetup(new Vector(2,0), 0,0,1);
    //
    rusher = new Entity(60, new Vector());
    rusher.health = 5;
    rusher.lifeSpan = 600;
    rusher.attackSetup(new Vector(2,1), .5);
    rusher.attackSetup(new Vector(-2,1), .5);
    rusher.moveSetup(new Vector(0,3), 0,0,1);
    //
    doozers = new Entity(30, new Vector());
    doozers.health = 3;
    doozers.lifeSpan = 1200;
    doozers.attackSetup(new Vector(1,1), 1.25);
    doozers.attackSetup(new Vector(-1,1), 1.25);
    doozers.attackSetup(new Vector(-1,-1), 1.25);
    doozers.attackSetup(new Vector(1,-1), 1.25);
    doozers.moveSetup(new Vector(0,.5),20,20,.1);
  }

//the timeline for all enemy spawns
void enemySequence()
{
  //a bool to stop if conditions from crashing if the enemy list is empty/null.
  //must be first condition or array list will crash
  if (enemyList.size() >0)
  {
    onEnemy = true;
  } else
  {
    onEnemy = false;
  }

  //add enemies to the game on time when the game starts
 
  switch(int(gameTime))
  {
    //create the starting enemy
   
    /*case:
        //add enemy
        List.add(enemyObject);
        //starting position
        List.get(int).position = new Vector();
    */
   
  case 0:
    enemyList.add(dummy);
    gameTime++;
    break;
    //start the game once starting enemy is destroyed
  case 1:
    if (!onEnemy)
      startGame = true;
    break;
  case 2:
    bugger.position = new Vector(width/2, -60);
    enemyList.add(bugger);
    gameTime++;
    break;
  case 6:
  //must reset the classes to a new class(); to avoid double feedback
    enemyTypes();
    bugger.position = new Vector(width/2 + 100, -60);
    enemyList.add(bugger);
  //
    enemyTypes();
    bugger.position = new Vector(width/2 -100, -60);
    enemyList.add(bugger);
    gameTime++;
    break;
  case 15:
    enemyTypes();
    skimmer.position = new Vector(-50, 200);
    enemyList.add(skimmer);
    gameTime++;
    break;
  case 18:
    enemyTypes();
    skimmer.moveSetup(new Vector(-2,0), 0,0,-1);
    skimmer.position = new Vector(width+50, 200);
    skimmer.attackSetup(new Vector(-2,2), 1);
    enemyList.add(skimmer);
    gameTime++;
    break;
  case 25:
    enemyTypes();
    rusher.position = new Vector(width/2 - 300,-50);
    enemyList.add(rusher);
    //
    enemyTypes();
    rusher.position = new Vector(width/2 + 300,-50);
    enemyList.add(rusher);
    gameTime++;
    break;
  case 28:
    enemyTypes();
    doozers.position = new Vector(width/2 + 200, - 50);
    enemyList.add(doozers);
    //
    enemyTypes();
    doozers.position = new Vector(width/2, - 50);
    enemyList.add(doozers);
    //
    enemyTypes();
    doozers.position = new Vector(width/2 - 200, - 50);
    enemyList.add(doozers);
    //
    enemyTypes();
    doozers.position = new Vector(width/2 - 400, - 50);
    enemyList.add(doozers);
    //
    enemyTypes();
    doozers.position = new Vector(width/2 + 400, - 50);
    enemyList.add(doozers);
    gameTime++;
    break;
  }

  //out of bounds check
  if (onEnemy)
  {
    //all enemies
    for (int a = 0; a < enemyList.size(); a++)
    {
      //move all enemies
      enemyList.get(a).moveType();
      enemyList.get(a).attackCycle();
     
     
      //if the enemy has run out of time delete them
      if(!enemyList.get(a).lifeTime())
      {
        enemyList.remove(a);
      }
    }
  }
 
  //keep bullet stack below limit by removing the last one in the stack
  if (EBulletStack.size() > 200)
  {
    EBulletStack.remove(0);
  }
 
  //move and draw each bullet in the stack
  for (int a = 0; a < EBulletStack.size(); a++)
  { 
    fill(255,100,200);
    EBulletStack.get(a).moveBullet();
    EBulletStack.get(a).drawBullet();

    //delete the bullet if it's out of bounds
    if (EBulletStack.get(a).deleteBullet())
    {
      EBulletStack.remove(a);
    }
  }

  //start game time
  if (startGame)
  {
    //real seconds timer
    gameTime += 1/frameRate;
    //println(int(gameTime)+ "   " + ESequence);
  }
}

//BULLET CLASS

class Bullet
{
  //empty Vector class for using class functions
  Vector useVector = new Vector();
 
  //bullet position
  Vector bPos;
  //bullet Size
  float radius = 25;
  //bullet Velocity
  Vector bVelocity = new Vector();
  //bullet lifeTime
  float lifeTime = 1200;
 
  //constructor for spawning the bullet in canvas space
  Bullet(Vector position, Vector velocity)
  {
    bPos = position;
    bVelocity = velocity;
  }
 
  //draw the bullet
  void drawBullet()
  {
    noStroke();
    ellipse(bPos.x, bPos.y,radius, radius);
  }
 
  //translate the bullet via it's velocity
  void moveBullet()
  {
    bPos = useVector.addVelocity(bPos, bVelocity);
    lifeTime -= 1; 
  }
 
  //return true to delete bullet from arrayList
  boolean deleteBullet()
  {
    if(lifeTime <= 0)
    {
      return true;
    }
   
    return false;
  }

}

//ENTITY

class Entity
{
  Bullet useBullet = new Bullet(new Vector(), new Vector());
 
  float shape = 10;
  Vector position = new Vector(0, 0);
  //
  float healthChange;
  float health = 10;
  //
  float lifeSpan = 600;

  //empty box with a shape
  Entity(float a)
  {
    shape = a;
    attackVectors = new ArrayList();
  }

  //shape and position
  Entity(float a, Vector b)
  {
    shape = a;
    position = b;
    attackVectors = new ArrayList();
  }

  //
  void drawCirc()
  {
    noStroke();
    fill(200, 100, 100);
    ellipse(position.x, position.y, shape+health, shape+health);

    if (healthChange != health)
    {
      fill(255, 100, 100);
      healthChange = health;
    } else
    {
      fill(100, 100, 100);
    }

    stroke(0);
    ellipse(position.x, position.y, shape, shape);
  }

  boolean attackCollision(Bullet bullet, Entity target)
  {
    if (dist(bullet.bPos.x, bullet.bPos.y, target.position.x, target.position.y) < bullet.radius/2 + target.shape/2)
    {
      //remove health from target on collision
      target.health --;
      return true;
    }
    return false;
  }

  boolean lifeTime()
  {
    //return true if object has time left
    if (lifeSpan > 0)
    {
      return true;
    }
    //if lifespan is below 0 return false to delete enemy unless set below -10 for infinite lifetime;
    if (lifeSpan > -10 && lifeSpan <=0)
    {
      return false;
    }
    //return true for infinite life
    return true;
  }

  boolean mSetupOnce = false;

  Vector velocity = new Vector();
  float xMove;
  float yMove;
  float wSpeed;

  //setup all entity movement on initiation;
  void moveSetup(Vector lineMove, float xWave, float yWave, float waveSpeed)
  {
    //if (!mSetupOnce)
    {
      velocity = lineMove;
      xMove = xWave;
      yMove = yWave;
      wSpeed= waveSpeed;
      //mSetupOnce = true;
    }
  }

  void moveType()
  {
    //if (xMove !=0 || yMove !=0 || wSpeed !=0)
    {
      sinMove(xMove, yMove, wSpeed);
    }

    ///if (velocity.x != 0 || velocity.y != 0)
    {
      anchorPoint = useVector.addVelocity(anchorPoint, velocity);
    }
  }

  float wave;
  boolean anchorStop = true;
  Vector anchorPoint = new Vector();
  Vector waveMovement = new Vector();

  //adds a wave motion to the object
  void sinMove(float xWave, float yWave, float speed)
  {
    //find the anchor of the Object before wave movement starts
    if (anchorStop)
    {
      anchorPoint = position;
      anchorStop = false;
    }
    //create vector with wave motion
    waveMovement = new Vector(sin(wave) * xWave, cos(wave) * yWave);
    //apply motion
    position = useVector.addVelocity(anchorPoint, waveMovement);
    wave += speed;
  }

  ArrayList <Vector> attackVectors;

  float fireRate;
  float coolDown;

  void attackSetup(Vector direction, float rate)
  {
   
    attackVectors.add(direction);
    fireRate = rate;
  }

  Vector bulletSpawn;



  void attackCycle()
  {
    //check for out of bounds
    if (attackVectors.size()>0)
    {
      //if cycle is reset
      if (coolDown <= 0)
      {
        //use all attacks
        for (int a = 0; a < attackVectors.size(); a++)
        {
          bulletSpawn = useVector.addVelocity(position, attackVectors.get(a));
          EBulletStack.add(new Bullet(position, attackVectors.get(a)));
        }
        coolDown = fireRate;
      }

      //cycle interval
      if (coolDown>0)
      {
        coolDown -= 1/frameRate;
      }
    }
  }
}


//VECTORS

//physics class
class Vector
{
  //x and y values
  float x;
  float y;

  //empty new Vector(0,0)
  Vector()
  {
    x = 0;
    y = 0;
  }

  //new Vector(x,y)
  Vector(float a, float b)
  {
    x = a;
    y = b;
  }

  //function for adding movement using a velocity Vector
  Vector addVelocity(Vector position, Vector velocity)
  {
    return new Vector(position.x + velocity.x, position.y + velocity.y);
  }

}

Wednesday, October 3, 2018

Processing - Procedural Motion



Code:

MAIN:

//useClass functions
//Vector class stores and manipulates floats x and y for horizontal and vertical
Vector useVector = new Vector();

//Player
//player size x and y
Vector playerSize = new Vector(20, 20);

//Vectors
//player position x and y
Vector playerPos = new Vector();
//player speed and direction as x and y
Vector playerVelocity = new Vector();
//input direction of the player x and y
Vector inputVector = new Vector();

//Input
//movement keys
char[] moveKeys = {'d', 'a', ' ', 's'};
//input axis for the movement
int[] moveValues = new int[4];

//Movement
//horizontal velocity
float moveSpeed = 5;

//Jump
//input for jumping
boolean jumpPress;
//locks the input so it only applies once per press
boolean singleJump;
//magnitude of jump velocity
float jumpForce = 7.5;
//is on the floor
boolean floorTouch;


//amount of platform to be drawn
int platformCount = 15;
//position of each platform
Vector[] platformStart;
//size of eachplatform
Vector[] platformEnd;


void setup()

  size(500, 700);
  //center the player
  playerPos = new Vector(width/2, 0);
  //build the platforms
  platformSetup();
}

void draw()
{
  background(240, 200, 200);
  //get player input
  moveInput();
  //get jump input
  jump();
  //apply physics
  playerPhysics();
  //draw platforms
  platform();
  //platform collisions
  collide();
  //draw player
  drawPlayer();

  saveFrame("output/gp_####.png");
}

void drawPlayer()
{
  fill(200, 200, 200);
  rect(playerPos.x, playerPos.y, playerSize.x, playerSize.y);
}

void moveInput()
{
  //set a directional vector based on the keyboard input directions pressed
  inputVector = new Vector(moveValues[0] - moveValues[1], moveValues[2] - moveValues[3]);
}

void keyPressed()
{
  //add input value on key input
  for (int a = 0; a < moveKeys.length; a ++)
    if (key == moveKeys[a])
    {
      moveValues[a] = 1;
    }
}

void keyReleased()
{
  //remove input value on key input
  for (int a = 0; a < moveKeys.length; a ++)
    if (key == moveKeys[a])
    {
      moveValues[a] = 0;
    }
}

//gravity, drag, and movement
void playerPhysics()
{
  //gravity
  playerVelocity = useVector.gravity(playerVelocity);
  //drag
  playerVelocity = useVector.drag(playerVelocity);
  //movement
  playerVelocity.x = inputVector.x * moveSpeed;
  //add velocity
  playerPos = new Vector(playerPos.x + playerVelocity.x, playerPos.y+playerVelocity.y);
}

//jumping mechanics
void jump()
{
  //Jump Input when vertical input vector is positive
  if (inputVector.y > 0)
  {
    jumpPress = true;
  }
  else
  //turn off jump input and
  {
    jumpPress = false;
    singleJump = true;
  }

  //Add jump velocity
  //check if touching floor
  if (floorTouch)
  {
    //jump input
    if (jumpPress && singleJump)
    {
      //add velocity
      playerVelocity.y = -jumpForce;
      //fire once boolean
      singleJump = false;
    }
  }

  //accelerate faster if player releases jump input
  if (!jumpPress && playerVelocity.y < 0)
  {
    playerVelocity.y += 0.2;
  }
  //
  if (playerVelocity.y > 0)//!jumpPress && playerVelocity.y > 0)
  {
    playerVelocity.y += 0.1;
  }
}

void collide()
{
  //reset floor trigger;
  floorTouch = false;

  for (int a = 0; a < platformCount; a ++)
  {
    //only run if there is a platform
    if (platformStart[a] != null)
    {
      //check if the player is contacting floor collider;
      if (playerPos.y + playerSize.y >= platformStart[a].y)
      {
        //check if the player is on the platform from the left
        if (playerPos.x + playerSize.x >= platformStart[a].x)
        {
          //check if the player is on the collider from the right
          if (playerPos.x <= platformStart[a].x + platformEnd[a].x)
          {
            //check if the player is above the collider
            if (playerPos.y <= platformStart[a].y + platformEnd[a].y)
            {
              //enable jumping
              floorTouch = true;
              //stop downward velocity
              if(playerVelocity.y > 0)
              {
                playerVelocity.y = 0;
              }
              //keep the player above the platform
              playerPos.y = platformStart[a].y - (playerSize.y);
            }
          }
        }
      }
    }
  }
}

//create platforms
void platformSetup()
{
  //platform positions and dimensions
  platformStart = new Vector[platformCount];
  platformEnd = new Vector[platformCount];

  //first platform for the ground
  platformStart[0] = new Vector(0, height - 100);
  platformEnd[0] = new Vector(width, height);

  //make a bunch of random positions for platforms
  for (int a = 1; a < platformCount; a ++)
  {
    //random positions
    platformStart[a] = new Vector(random(0, width), random(0, height -100));
    //platforms with some random width
    platformEnd[a] = new Vector(random(50, 100), 10);
  }
}

//draw the platforms
void platform()
{
  fill(100, 100, 200);
  //draw each platform
  for (int a = 0; a < platformCount; a ++)
  {
    rect(platformStart[a].x, platformStart[a].y, platformEnd[a].x, platformEnd[a].y);
  }
}


VECTOR CLASS

//Vector class stores x and y positions but can also be used for manipulating velocity using the same Vector type;
//aka it handles basic 2D physics

class Vector
{
  //horizontal and vertical;
  float x;
  float y;
  
  //forces
  float gravity = 9.11/60;
  float drag = 0.01;
  
  //if empty statement make new Vectors(0,0)
  Vector()
  {
    x=0;
    y=0;
  }
  
  //declare a new vector with new values;
  Vector(float a, float b)
  {
    x = a;
    y = b;
  }
  
  //returns a velocity with gravity acceleration
  Vector gravity(Vector velocity)
  {
    return new Vector(velocity.x, velocity.y + gravity); 
  }
  
  //returns a velocity with drag deceleration
  Vector drag(Vector velocity)
  {
    return new Vector(velocity.x - velocity.x * drag, velocity.y - velocity.y * drag);
  }

}