Cocos2d-x mruby binding

17843 단어 cocos2d-x루비mruby
Cocos2d-x의 mruby bindng을 개발하고 있습니다.
iOS, Android인 어느 정도 움직이게 되었기 때문에 공개했습니다.
htps : // 기주 b. 코 m / t Kage / 여기 s2d-by

사용법



위의 github 저장소에서 clone하십시오.
$ git clone https://github.com/tkyaji/cocos2d-ruby

나머지는 일반 Cocos2d-x 사용법과 동일합니다.setup.py 스크립트를 실행하고 환경 변수를 로드합니다.
$ cd cocos2d-ruby
$ python setup.py
$ source ~/.bash_profile
cocos new 명령으로 프로젝트를 만듭니다.-l 선택적으로 ruby를 지정하면 mruby binding 프로젝트를 만들 수 있습니다.
$ cocos new MyGame -l ruby

또한 Cocos2d-x 본가의 리포지토리에서 fork하고 있으므로, C++나 Lua도 사용할 수 있습니다.

HelloWorld



생성한 프로젝트에서 그대로cocos run를 실행하면 HelloWorld 샘플이 시작됩니다.
$ cocos run -p ios
$ cocos run -p android

내용은 C++판의 HelloWorld를, ruby로 재작성한 것입니다.

main.rb
require "HelloWorld"

def main
  # size define
  resources = {
    small: {
      size: {w: 480, h: 320},
      directory: "res/iphone"
    },
    medium: {
      size: {w: 1024, h: 768},
      directory: "res/ipad"
    },
    large: {
      size: {w: 2048, h: 1536},
      directory: "res/ipadhd"
    }
  }
  design_resolution_size = resources[:small][:size]

  director = CC::Director.get_instance
  glview = director.get_open_glview
  if ! glview
    glview = CC::GLViewImpl.create("Ruby Empty Test")
    director.set_open_gl_view(glview)
  end

  glview.set_design_resolution_size(design_resolution_size[:w], design_resolution_size[:h], ResolutionPolicy.NO_BORDER)

  frame_size = glview.get_frame_size
  ssize = resources[:small][:size]
  msize = resources[:medium][:size]

  target_res = resources[:small]
  if frame_size.height > msize[:h]
    target_res = resources[:large]
  elsif frame_size.height > ssize[:h]
    target_res = resources[:medium]
  end
  target_size = target_res[:size]
  director.set_content_scale_factor([target_size[:h] / design_resolution_size[:h], target_size[:w] / design_resolution_size[:w]].min)

  futils = CC::FileUtils.get_instance
  futils.add_search_path(target_res[:directory])

  director.set_display_stats(true)
  director.set_animation_interval(1.0 / 60)

  scene = HelloWorld.scene
  director.run_with_scene(scene)
end

main

HelloWorld.rb
class HelloWorld < CC::Layer
  include CC

  TITLE_FONT_SIZE = 20;

  def self.scene
    # 'scene' is an autorelease object
    scene = Scene.create

    # 'layer' is an autorelease object
    layer = HelloWorld.create

    #add layer as a child to scene
    scene.add_child(layer)

    # return the scene
    return scene
  end

  def initialize
    init
  end

  def init

    director = Director.get_instance
    visible_size = director.get_visible_size
    visible_vec2 = Vec2.new(visible_size.width, visible_size.height)
    origin = director.get_visible_origin

    # 1. add a menu item with "X" image, which is clicked to quit the program
    #    you may modify it.

    # add a "close" icon to exit the progress. it's an autorelease object
    close_item = MenuItemImage.create("CloseNormal.png", "CloseSelected.png", Proc.new {|sender|
      p "Exit button clicked"
    })
    content_size = close_item.get_content_size
    content_vec2 = Vec2.new(content_size.width, content_size.height)
    close_item.set_position(origin + visible_vec2 - content_vec2 / 2)

    # create menu, it's an autorelease object
    menu = Menu.create(close_item)
    menu.set_position(Vec2.ZERO)
    self.add_child(menu, 1)

    # 2. add your codes below...

    # add a label shows "Hello World"
    # create and initialize a label

    label = Label::create_with_system_font("Hello World", "Arial", TITLE_FONT_SIZE)
    # position the label on the center of the screen
    label.set_position(origin.x + visible_size.width / 2, origin.y + visible_size.height - label.get_content_size.height)

    # add the label as a child to this layer
    self.add_child(label, 1)

    # add "HelloWorld" splash screen"
    sprite = Sprite.create("HelloWorld.png")

    # position the sprite on the center of the screen

    tmp_size = visible_size / 2
    sprite.set_position(Vec2.new(tmp_size.width, tmp_size.height) + origin)

    # add the sprite as a child to this layer
    self.add_child(sprite)
  end
end

main.rb에 쓰여 있는 처리는 실제로 AppDelegate.cpp에 쓰는 것이 좋다고 생각합니다만,
샘플이므로 굳이 Ruby 측에 쓰고 있습니다.

메서드 이름은 뱀 케이스로 변환되고 isXXXXXX?로 변환됩니다.
(binding-generator 런타임 설정에서이 변환을 비활성화하고 생성 할 수 있습니다)

콜백은 Proc로 구현됩니다.

메모리 관리



Lua Binding에서는 C++와 마찬가지로 상황에 따라 retain, release에서 참조 카운터를 조작해야 합니다.
mruby Binding에서는, retain, release는 불필요하고, Ruby측에서 모두 관리해 주기 위해서 구현하고 있습니다.

구체적으로는 retain, release가 불려 갔을 때에, mruby로 랩 한 인스턴스였던 경우,
C++의 레퍼런스 카운터(RC)는 늘리지 않고, 대신 Ruby측에 만든 RC를 인크리먼트 하고 있는 이미지입니다.
Ruby 측의 RC가 0이 된 타이밍에서, C++측의 RC를 감소(즉 C++의 원래의 릴리즈 처리)를 실행해,
인스턴스가 삭제되도록합니다.
이 변의 처리는, Ref.cpp , RubyEngine.cpp 로 구현하고 있습니다.

솔직히, 지금의 구현에 문제 없거나 아직 조금 걱정이므로, 이 경우에 안 되든가, 츳코미를 받을 수 있으면 기쁩니다

에디터



Lua나 JS의 경우 Cocos Code IDE를 사용한 효율적인 개발을 할 수 있지만, mruby binding은 당연히 대응하고 있지 않습니다.
그러나 그것이 불편하기 때문에, mruby binding 용 Sublime Text 플러그인을 만들었습니다.
CocosRubyEditor

이것을 사용하면 다음과 같이 자동 완성이 가능합니다.



Package Control에 등록했기 때문에, "CocosRubyEditor"로 검색하면 나올 것입니다.
정수 등, 현재 상태에서는 보완되지 않는 것이 있습니다만, 그 중 대응할 예정입니다.

TODO


  • 지원되지 않는 클래스 지원
  • cocos new로 프로젝트를 만들 때 mruby gem을 추가 할 수 있도록 허용
  • rubycompile 명령 구현 (바이트 코딩 및 암호화)
  • ruby-test 프로젝트 구현
  • 문서 생성
  • ios/Android/Mac 이외의 플랫폼 지원


  • 사용해 주시면 기쁩니다.

    이상.

    좋은 웹페이지 즐겨찾기