Delta3D and Ruby

Friday, May 14, 2010
Saya mengembangkan permainan menembak dalam ruang 3D (3D space shooter game). Logika internal permainan ini ditulis dalam C + +, namun, saya ingin menggunakan script Ruby.Disini saya akan menampilkan apa yang telah saya lakukan. Tutorial ini tidak begitu lengkap, tapi mudah-mudahan bisa bermanfaat dan saya berharap seseorang bisa mengedit halaman ini dan menambahkan saran / koreksi.
Saya mendapatkan banyak info dari sini.
Pertama, anda harus mengatur ruby dan delta3D. Pada Windows, one-click-installer installs dan header files beserta library-nya.
Kemudian, anda harus memilih strategi komunikasi antara Ruby dan C + +. Saya memilih kelas C + + sederhana yang mewakili sebuah pesawat ruang angkasa. Kelas ini terlihat di C + + dan Ruby.Ini adalah tahapannya:


1. C + +  memanggil Ruby
2. Ruby mengumpulkan informasi; menciptakan kelas RShipInfo dan menempatkan mereka dalam array.
3. C + +  membaca array dan mengoreksinya (menempatkan pesawat, menghancurkan pesawat, menempatkan lokasi, dsb.)
4. C + +  sebagai frame, lalu setting status ruang angkasa (jika satu pesawat hancur karena terkena rudal atau tabrakan, sets alive= 0)
5. Kembali ke langkah 1




Saat pertama kali Ruby di panggil (disebut "initmission"), maka argumen berikutnya adalah "runmission".

#ifndef _H_MISSIONCONTROL
#define _H_MISSIONCONTROL

#include
#include
#include
#include
namespace boost {}
namespace dtCore {}
namespace std {}
using namespace dtCore;
using namespace std;
using namespace boost;

//structure for communication
typedef struct tdefshipinfo
{
public:
  tdefshipinfo()
  :
  name(""),
  id(0),
  type(""),
  side(0),
  alive(1),
  command(""),
  player("")
  {  }

  string name;
  int id;
  string type;
  int side;
  int alive;
  string command;
  string player;
}
RShipInfo;

//ruby initialization
class RubyEnv
{
public:
  void static InitRuby();
  void static EndRuby();
};

//running and init mission
void InitMission();
void RunMission();


std::vector * GetRShipInfoList(); //returns the list of spaceships visible both from c++

void CopyListFromRuby(); //copy list from ruby to c++

#endif



ini file cpp nya:

#include "MissionControl.h"

#include "stdio.h"
#include "ruby.h"

std::vector Rlist;

VALUE cRShipInfo; //ruby class for ship info
VALUE objectlist; //array of ship infos

RShipInfo * GetStructure(VALUE self) //returns structure out from ruby VALUE. The ruby class is represented with c++ structure, so here
//this structure is extracted out of ruby class
{
  RShipInfo *ptr;
  Data_Get_Struct(self,RShipInfo,ptr);
  return ptr;
}

VALUE AccessorGetName(VALUE self)  //returns name of spaceship
{
  return rb_str_new2(GetStructure(self)->name.c_str());
}

VALUE AccessorSetName(VALUE self,VALUE val) //sets name of spaceship
{
  long len;
  string str=rb_str2cstr(val,&len);
  GetStructure(self)->name=str;
  return self;
}

VALUE AccessorGetType(VALUE self) //gets type of spaceship
{
  return rb_str_new2(GetStructure(self)->type.c_str());
}

VALUE AccessorSetType(VALUE self,VALUE val) //sets type of spaceship
{
  long len;
  string str=rb_str2cstr(val,&len);
  GetStructure(self)->type=str;
  return self;
}

VALUE AccessorGetID(VALUE self) //get id of spaceship
{
  return INT2NUM(GetStructure(self)->id);
}

VALUE AccessorSetID(VALUE self,VALUE val) //set id of spaceship
{
  GetStructure(self)->id=NUM2INT(val);
  return self;
}

VALUE AccessorGetSide(VALUE self) //gets side of spaceship
{
  return INT2NUM(GetStructure(self)->side);
}

VALUE AccessorSetSide(VALUE self,VALUE val) //sets side of spaceship
{
  GetStructure(self)->side=NUM2INT(val);
  return self;
}

VALUE AccessorGetAlive(VALUE self) //is alive
{
  return INT2NUM(GetStructure(self)->alive);
}

VALUE AccessorSetAlive(VALUE self,VALUE val) //sets alive
{
  GetStructure(self)->alive=NUM2INT(val);
  return self;
}

VALUE AccessorGetPlayer(VALUE self) //name of player
{
  return rb_str_new2(GetStructure(self)->player.c_str());
}

VALUE AccessorSetPlayer(VALUE self,VALUE val) //name of player
{
  long len;
  string str=rb_str2cstr(val,&len);
  GetStructure(self)->player=str;
  return self;
}

VALUE AccessorGetCommand(VALUE self) //command to do on spaceship
{
  return rb_str_new2(GetStructure(self)->command.c_str());
}

VALUE AccessorSetCommand(VALUE self,VALUE val) //command to do on spaceship
{
  long len;
  string str=rb_str2cstr(val,&len);
  GetStructure(self)->command=str;
  return self;
}

void FreeRubyShipInfo(void *p) //deletes object
{
  RShipInfo *pp=(RShipInfo*) p;
  delete pp;
}

VALUE InitRubyShipInfo(VALUE first,...) //ruby constructor
{
  return first;
}

VALUE NewRubyShipInfo(VALUE first, ...) //c++ constructor called from ruby
{
  RShipInfo * ptr=new RShipInfo();
  VALUE tdata=Data_Wrap_Struct(cRShipInfo,0,0,ptr);
  rb_obj_call_init(tdata,0,0);
  return tdata;
}

void CreateRubyClass_ShipInfo() //dynamically register new class with ruby
{
  cRShipInfo=rb_define_class("RShipInfo",rb_cObject);
  rb_define_singleton_method(cRShipInfo,"new",(VALUE (*) (...))NewRubyShipInfo,0);
  rb_define_method(cRShipInfo,"initialize",(VALUE (*) (...))InitRubyShipInfo,0);
  rb_define_method(cRShipInfo,"getname",(VALUE (*) (...))AccessorGetName,0);
  rb_define_method(cRShipInfo,"setname",(VALUE (*) (...))AccessorSetName,1);
  rb_define_method(cRShipInfo,"getid",(VALUE (*) (...))AccessorGetID,0);
  rb_define_method(cRShipInfo,"setid",(VALUE (*) (...))AccessorSetID,1);
  rb_define_method(cRShipInfo,"gettype",(VALUE (*) (...))AccessorGetType,0);
  rb_define_method(cRShipInfo,"settype",(VALUE (*) (...))AccessorSetType,1);
  rb_define_method(cRShipInfo,"getside",(VALUE (*) (...))AccessorGetSide,0);
  rb_define_method(cRShipInfo,"setside",(VALUE (*) (...))AccessorSetSide,1);
  rb_define_method(cRShipInfo,"getalive",(VALUE (*) (...))AccessorGetAlive,0);
  rb_define_method(cRShipInfo,"setalive",(VALUE (*) (...))AccessorSetAlive,1);
  rb_define_method(cRShipInfo,"getplayer",(VALUE (*) (...))AccessorGetPlayer,0);
  rb_define_method(cRShipInfo,"setplayer",(VALUE (*) (...))AccessorSetPlayer,1);
  rb_define_method(cRShipInfo,"getcommand",(VALUE (*) (...))AccessorGetCommand,0);
  rb_define_method(cRShipInfo,"setcommand",(VALUE (*) (...))AccessorSetCommand,1);
}

void RubyEnv::InitRuby() //this is how to init ruby environment
{
  ruby_init();
  ruby_init_loadpath();
  ruby_incpush("scripts");

  objectlist=rb_ary_new();
  rb_define_variable("$sslist",&objectlist);
  CreateRubyClass_ShipInfo();
}

void RubyEnv::EndRuby() //and finalize ruby environment
{
  ruby_finalize();
}

void InitMission() //init mission
{
  ruby_script("init");
  int status;
  rb_load_protect(rb_str_new2("start.rb"), 0, &status);

  ruby_script("initmission");
  int state = ruby_exec();
  CopyListFromRuby();
}

void RunMission() //run mission, once a second
{
  ruby_script("runmission");
  int state = ruby_exec();
  CopyListFromRuby();
}

std::vector * GetRShipInfoList() //list of spaceships
{
  return &Rlist;
}

void CopyListFromRuby() //copies list from ruby to c++
{
  Rlist.clear();
  VALUE curr;
  int len=(RARRAY(objectlist)->len);
  for (int i=0;i
  {
    curr=rb_ary_entry(objectlist,i);
    RShipInfo *ptr;
    Data_Get_Struct(curr,RShipInfo,ptr);
    Rlist.push_back(ptr);
  }
}


Ruby scriptnya :

def initmission
  puts "start of mission"
  r=RShipInfo.new
  r.setid 1
  r.setname("moja ladja")
  r.setside 1
  r.settype("tip1")
  r.setalive 1
  r.setplayer "human"
  r.setcommand "create"
  $sslist << r

  puts "id=" + r.getid.to_s
  puts "name=" + r.getname
  puts "side=" + r.getside.to_s
  puts "tip=" + r.gettype
  puts "alive=" +r.getalive.to_s
  puts "player=" +r.getplayer
  puts "command="+r.getcommand

  for i in 2..20 do
    r=RShipInfo.new
    r.setid i
    r.setname("enemy 1")
    r.setside 2
    r.settype("tip1")
    r.setalive 1
    r.setplayer "computer"
    r.setcommand "create"
    $sslist << r
  end

  puts $sslist.length
end

def runmission
  puts "just idle running"
end

if $0 == "init"
  puts "init"
end

if $0 == "runmission"
  puts "runmission"
  runmission
end

if $0 == "initmission"
  puts "initmission"
  initmission
end

Sumber : http//sourceforge.net/apps/mediawiki/delta3d/index.php?title=Delta3D_and_Ruby


Photobucket

0 komentar:

Post a Comment