goralph
goralph

Reputation: 1086

Have a simple in-browser JS game need it to work with a Ruby script on the 'backend'

My 'frontend' is a JS script that loads a HTML5 canvas and draws a X * Y grid, it then draws an alien at some default (X,Y) coordinate in the grid.

I have some ruby classes that define how this alien moves. For now, it's just +- on the X,Y plane. I want to be able to click on a 'move forward' button in the browser, and for that to send a request to the ruby script which will then calculate the new position and send a response with the coordinates.

Could somebody point me in the right direction? I can't get the logic around doing this. I've read into Sinatra, AJAX, templates, and so on but nothing is helping.

Edit

app.rb

require 'sinatra'
require_relative 'alien'

get '/' do
  haml :home
end

get '/new_alien' do
  @alien = Alien.new 1,1,:N       # create a new alien
  @x = @alien.x                  # set the x coordinate
  @y = @alien.y                  # set the y coordinate
  %Q|{ "x":#{@x}, "y":#{@y} }|  # return a string with the coordinates
end

home.haml

!!!
%html
  %head
    %link{:rel => :stylesheet, :type => :"text/css", :href => "/css/main.css"}
  %body
    .wrapper
%script(src="http://code.jquery.com/jquery-2.1.1.min.js")
%script(src="/js/grid.js")

When the / path is loaded, home.haml should load and I would like for the x and y values to be passed to a JS script which uses these coordinates to draw an image. I'm not sure how to do this exactly.

Upvotes: 1

Views: 147

Answers (1)

7stud
7stud

Reputation: 48599

1) Use javascript to intercept the button click by installing an onclick event handler on the button.

2) The onclick event handler function should use javascript(or jquery) to send an AJAX request to the server. The AJAX request should include any relevant data that your server side ruby script needs to produce its calculation. Your AJAX request will specify a certain url, e.g.

"/calculate_new_position?x=10&y=20"

3) Your Sinatra app, which is located on the server, can be as simple as this:

 require 'sinatra'

 get '/calculate_new_positon' do

    x_coord = params[:x]  #=> 10
    y_coord = params[:y]  #=> 20

    #Do calculation here:
    new_x = x_coord * 20  
    new_y = y_coord - 3

    #The following string is the response:
    %Q|{ "new_x":#{new_x}, "new_y":#{new_y} }| 

 end

When your server receives a GET request for the url /calculate_new_position?x=10&y=20, it will cause the code above to execute. Sinatra will automatically insert any GET (or POST) variables in a Hash called params. The return value of the block will be the response that is sent back to the browser.

4) Your javascript AJAX code will include a function that is called when the response from the server is received. The function will contain something like this:

obj = JSON.parse(json_str);  //--> obj = {"new_x":22, "new_y":-3};
new_x = obj["new_x"];
new_y = obj["new_y"];

#Use javascript to move figures to new coordinates.

Here is an example:

~/ruby_programs/sinatra_4app$ tree
.
├── models
│   └── alien.rb
├── public
│   └── js
│       └── grid.js
├── routes.rb
└── views
    └── home.haml

4 directories, 4 files

home.haml:

!!! 5
%html
  %body
    %button#forward_button Move forward

    %script{:type => "text/javascript",
      :src  => "http://code.jquery.com/jquery-2.1.1.min.js"}

    %script{:type => "text/javascript",
      :src  => "/js/grid.js"}

The result after sinatra executes home.haml:

<!DOCTYPE html>
<html>
  <body>
    <button id='forward_button'>Move forward</button>
    <script src='http://code.jquery.com/jquery-2.1.1.min.js' type='text/javascript'></script>
    <script src='/js/grid.js' type='text/javascript'></script>
  </body>
</html>

routes.rb:

require 'sinatra'
require_relative 'models/alien'

get '/' do
  haml :home, :format => :html5
  #Sinatra automatically looks for templates in a 'views' directory, so the line above looks for the file: views/home.haml
end

get '/new_alien' do
  alien = Alien.new 1,1,:N       
  alien.calculate_new_position
  new_x = alien.x
  new_y = alien.y

  %Q|{ "new_x":#{new_x}, "new_y":#{new_y} }|  #return a string in json format containing the new coordinates
end

alien.rb:

class Alien
  attr_accessor :x, :y, :direction

  def initialize(x, y, direction)
    @x = x
    @y = y
    @direction = direction
  end

  def calculate_new_position
    self.x += 2  #Changes @x using the accessor method rather than changing @x directly, which is considered good practice.
    self.y -= 2
  end
end

grid.js:

$(document).ready(function() {
                  #This function executes when all the html elements exist, i.e. when
                  #the document is 'ready'--you can't search for an element until it exists.

  #Search for an element whose id="forward_button" and install an event handler function 
  #for its onclick event:
  $("#forward_button").click(function() {
                             #This function executes when the button is clicked
    #Get current x, y coords somehow....
    var x = 10;
    var y = 20;

    var url = "/new_alien?x=" + x + "&y=" + y;

    $.getJSON(url, function(js_obj) {  #This is a specialized version of $.ajax()
                   #This function is called when the browser
                   #receives the response returned by the server

      new_x = js_obj["new_x"];
      new_y = js_obj["new_y"];
      #Do something with new_x and new_y...

      console.log( "Response received!" );
      console.log( "new_x= " + new_x);
      console.log( "new_y= " + new_y);
    });

  });

});

Note that js comments start with //, so the code above will cause errors if you don't replace the # with //. I'm using the # to get the light gray shading, which makes the code easier to read.

1) Start the server:

~/ruby_programs/sinatra_4app$ ruby routes.rb 

2) Then enter the following url in your browser:

http://localhost:4567/

3) Then open the Console window for whatever browser you are using. In Firefox, the console window is under:

Tools>Web Developer>Web Console

In Chrome, it's:

View>Developer>Javascript Console

4) Click on the "Move forward" button; then check the output in the Console window.

Upvotes: 2

Related Questions