Gravity Game in R

April 8, 2010
By

(This article was first published on stotastic » R, and kindly contributed to R-bloggers)

So why should R only be used for ’serious’ stuff? No longer! I’ve written the following code in R which executes a little gravitational physics game. The goal of the game is simple. You supply a velocity and direction to a spaceship with the goal of getting the ship to the winning area without crashing into a planet.

To give you an idea of how this game works, below is a screenshot of the 3rd level.

In this screenshot, the blue dot represents the starting position of the ship. The black curve is the ships path. The red circles are the planets where the number represents the mass. Finally, the green circle is the winning area. In this example, the ship made it to the winning area safe and sound!

Gravity Game Code

Just copy and paste the code below into R and make a call to the function gravity() and enjoy! Also, you can easily add your own levels by putting your own game parameters in the ‘define level’ code blocks.

## gravity game in R
gravity <-
function(level=1){
  ## prompt user for level
  cat("Enter Level (1-3)n")
  level <- scan(n=1, quiet=T)
 
  ## simulation constants
  G <- 1000         # gravitational constant
  n <- 10000        # simulation steps
  dt <- .01         # time step size
  limit <- 50       # window limit
  m <- 1            # mass of space craft
 
  ## define level 1
  if(level==1){                 
    ## fixed mass 1
    Q1m <- 1        # mass
    Q1x <- 0        # x location
    Q1y <- -20      # y location
    Q1r <- 5        # radius
 
    ## fixed mass 2
    Q2m <- 1        # mass
    Q2x <- -10      # x location
    Q2y <- 30       # y location
    Q2r <- 5        # radius
 
    ## win zone
    winx <- 30      # x location
    winy <- 20      # y location
    winr <- 2       # radius
 
    ## start
    startx <- -40   # x location
    starty <- 20    # y location
  }
 
  ## define level 2
  if(level==2){                 
    ## fixed mass 1
    Q1m <- 10       # mass
    Q1x <- -20      # x location
    Q1y <- 20       # y location
    Q1r <- 25       # radius
 
    ## fixed mass 2
    Q2m <- 1        # mass
    Q2x <- 20       # x location
    Q2y <- -30      # y location
    Q2r <- 5        # radius
 
    ## win zone
    winx <- 30      # x location
    winy <- 20      # y location
    winr <- 2       # radius
 
    ## start
    startx <- -20   # x location
    starty <- -40   # y location
  }
 
  ## define level 3
  if(level==3){                 
    ## fixed mass 1
    Q1m <- 5        # mass
    Q1x <- 0        # x location
    Q1y <- 0        # y location
    Q1r <- 10       # radius
 
    ## fixed mass 2
    Q2m <- 1        # mass
    Q2x <- 30       # x location
    Q2y <- -0       # y location
    Q2r <- 5        # radius
 
    ## win zone
    winx <- 20      # x location
    winy <- 20      # y location
    winr <- 2       # radius
 
    ## start
    startx <- 20    # x location
    starty <- -20   # y location
  }
 
  ## plot game map
  plot(startx, starty, col="blue", main=paste("Gravity: level", level), 
       xlim=c(-limit, limit), ylim=c(-limit, limit),
       xlab="X", ylab="Y")
  circle(Q1x, Q1y, Q1r, "red")
  text(Q1x, Q1y, labels=Q1m) 
  circle(Q2x, Q2y, Q2r, "red")
  text(Q2x, Q2y, labels=Q2m)  
  circle(winx, winy, winr, "green")
  text(winx, winy, labels="w") 
 
  ## prompt user for velocity and angle
  cat("Enter Velocity (0-10, but no restrictions so don't cheat)n")
  velocity <- scan(n=1, quiet=T)
  cat("Enter Angle (in degrees, remember your trigonometry)n")  
  angle <- scan(n=1, quiet=T)
 
  ## define location paths, velocity, and distance vectors
  x <- rep(0,n)     # x location
  y <- rep(0,n)     # y location
  v <- c(0,0)       # velocity vector
  r1 <- c(0,0)      # distance vector to mass 1
  r2 <- c(0,0)      # distance vector to mass 2  
 
  ## set initial values
  x[1] <- startx
  y[1] <- starty
  v <- c(velocity*cos(angle*pi/180), velocity*sin(angle*pi/180))
 
  for(i in 2:n){
    ## calculate distance to fixed masses and win zone
    r1 <- c(x[i-1]-Q1x, y[i-1]-Q1y)         
    r2 <- c(x[i-1]-Q2x, y[i-1]-Q2y)         
    rw <- c(x[i-1]-winx, y[i-1]-winy)   
 
    ## break out of loop if ship crashed
    if(sqrt(r1 %*% r1)<Q1r | sqrt(r2 %*% r2)<Q2r){
      x[i:n] <- x[i-1]
      y[i:n] <- y[i-1]
      cat("You crashed!n")
      break
    }
 
    ## break out of loop if reach window limit
    if(abs(x[i-1])>limit*2 | abs(y[i-1])>limit*2){
      x[i:n] <- x[i-1]
      y[i:n] <- y[i-1]
      cat("Lost in space!n")
      break
    }
 
    ## break out of loop if reach win zone
    if(sqrt(rw %*% rw)<winr){
      x[i:n] <- x[i-1]
      y[i:n] <- y[i-1]
      cat("You win!n")
      break
    }
 
    ## calculate force vectors
    ## force from mass 1  
    f1 <- (r1/sqrt(r1 %*% r1))*(-G*Q1m*m)/(r1 %*% r1)
 
    ## force from mass 2
    f2 <- (r2/sqrt(r2 %*% r2))*(-G*Q2m*m)/(r2 %*% r2)
 
    ## combined forces
    f <- f1 + f2
 
    ## update velocity
    v <- v + dt*f   
 
    ## update location 
    x[i] <- x[i-1] + dt*v[1]/m 
    y[i] <- y[i-1] + dt*v[2]/m 
  }
 
  ## plot flight path
  lines(x,y)
}
 
## utlity function to draw a circle
circle <-
function(x,y,r,col){
  theta <- seq(0, 2*pi, .001)
  xv <- r*cos(theta) + x
  yv <- r*sin(theta) + y
  lines(xv,yv, col=col)
}

To leave a comment for the author, please follow the link and comment on his blog: stotastic » R.

R-bloggers.com offers daily e-mail updates about R news and tutorials on topics such as: visualization (ggplot2, Boxplots, maps, animation), programming (RStudio, Sweave, LaTeX, SQL, Eclipse, git, hadoop, Web Scraping) statistics (regression, PCA, time series, trading) and more...



If you got this far, why not subscribe for updates from the site? Choose your flavor: e-mail, twitter, RSS, or facebook...

Tags: , , ,

Comments are closed.