【解決済】spriteの移動について

八拾壱

ユーザー
お世話になります。
RGSS3で以下のようなスクリプトを作り

class Scene_Skeleton < Scene_Base
def update
super
skeleton = Sprite.new
skeleton.bitmap = Bitmap.new("Graphics/Battlers/skeleton")
skeleton.ox = skeleton.bitmap.width / 2
skeleton.oy = skeleton.bitmap.height / 2
skeleton.x = 272
skeleton.y = 208
Input.update
if Input.press?:)UP)
skeleton.y -= 20
end
if Input.press?:)DOWN)
skeleton.y += 20
end
if Input.press?:)RIGHT)
skeleton.x += 20
end
if Input.press?:)LEFT)
skeleton.x -= 20
end
return_scene if Input.trigger?:)B)
end
end

と、して

イベントコマンドスクリプトで

SceneManager.call(Scene_Skeleton)
Fiber.yield

と実行しキー入力によるスライとの移動を行ってみたのですが
初期位置から各方向に20いったところまで画像がコピーされたようになって
それ以上は移動しません。移動する前のところの画像は消去し、移動したところからはさらに20進めたいのですが
どのようにすれば良いのでしょうか?私はスクリプトの作り方が全く分かっていません。
教えていただけると助かります。よろしくお願いいたします。
 

八拾壱

ユーザー
文字化けしていますが… にっこりしてる顔は『:』。サングラスの顔は『B』です。
 

faida

ユーザー
こんばんは。

VXAceのヘルプにある「スクリプト入門」→「解読編」→「シーンの管理」→「シーンの管理」によると、
シーンは次の5つのメソッドを順番に呼び出しているそうです。
メソッド内容
start開始処理
post_start開始後処理
updateフレーム更新
pre_terminate終了前処理
terminate終了処理

八拾壱さんの書いたスクリプトはupdateを呼び出すだけですね。
つまり毎フレーム以下の部分でSpriteを作成し、
skeleton = Sprite.new
skeleton.bitmap = Bitmap.new("Graphics/Battlers/skeleton")
skeleton.ox = skeleton.bitmap.width / 2
skeleton.oy = skeleton.bitmap.height / 2
skeleton.x = 272
skeleton.y = 208
毎フレーム以下の部分で操作を受け付けているわけです。
Input.update
if Input.press?( :UP)
@skeleton.y -= 20
end
if Input.press?( : DOWN)
@skeleton.y += 20
end
if Input.press?( :RIGHT)
@skeleton.x += 20
end
if Input.press?( :LEFT)
@skeleton.x -= 20
end
return_scene if Input.trigger?( :B )

ですが、毎フレーム作成されるSpriteはすべて別のものを指しています。
そのため、毎フレームごとに1回しか操作を受け付けず、毎フレーム同じ画像が新しく表示されるようになります。

本来したいこととしては「シーン内で1回だけSpriteを作成し、毎フレーム操作を受け付ける」
ということになると思います。
そのためにはまず、上記の開始処理にSpriteを作成する処理を入れます。
コード:
def start
  super
  @skeleton = Sprite.new
  @skeleton.bitmap = Bitmap.new("Graphics/Battlers/skeleton")
  @skeleton.ox = skeleton.bitmap.width / 2
  @skeleton.oy = skeleton.bitmap.height / 2
  @skeleton.x = 272
  @skeleton.y = 208
end
変数の前に@をつけたものをインスタンス変数と呼び、「基礎編」→「クラス定義」に詳細があります。

次に、updateの処理で動かすSpriteを先程のものにしましょう。
コード:
def update
  Input.update
  if Input.press?(:UP)
    @skeleton.y -= 20
  end
  if Input.press?(:DOWN)
    @skeleton.y += 20
  end
  if Input.press?(:RIGHT)
    @skeleton.x += 20
  end
  if Input.press?(:LEFT)
    @skeleton.x -= 20
  end
  return_scene if Input.trigger?(:B)
end
あとは適当に体裁を整えれば完成です。

※ちなみに本来は終了処理にて@skeletonを解放する必要がありますが省略しました。

何か不明点等あれば遠慮なくどうぞ。
 

八拾壱

ユーザー
ありがとうございます。自分なりに体裁を整えてみて実行してみたのですがキー入力が反映されません。
教えていただいたとおりに打ち込みskeleton全てに@をつけました。PCがずっと読込中になります。
終了処理で@skeletonの開放の仕方がわかりません。教えていただけますと助かります。
 

八拾壱

ユーザー
コード:
class Scene_Skeleton < Scene_Base
def start
  super
  @skeleton = Sprite.new
  @skeleton.bitmap = Bitmap.new("Graphics/Battlers/Skeleton")
  @skeleton.ox = @skeleton.bitmap.width / 2
  @skeleton.oy = @skeleton.bitmap.height / 2
  @skeleton.x = 272
  @skeleton.y = 208
end
def update
  Input.update
  if Input.press?(:UP)
    @skeleton.y -= 20
end
if Input.press?(:DOWN)
  @skeleton.y += 20
end
    if Input.press?(:RIGHT)
   @skeleton.x += 20
end
  if Input.press?(:LEFT)
    @skeleton.x -= 20
end
return_scene if Input.trigger?(:B)
@skeleton.dispose
end
end

書いたコードはこういったものです。
 

八拾壱

ユーザー
度々ごめんなさい。
コード:
class Scene_Skeleton < Scene_Base
def start
  super
  @skeleton = Sprite.new
  @skeleton.bitmap = Bitmap.new("Graphics/Battlers/Skeleton")
  @skeleton.ox = @skeleton.bitmap.width / 2
  @skeleton.oy = @skeleton.bitmap.height / 2
  @skeleton.x = 272
  @skeleton.y = 208
end
def update
  loop do
   Graphics.update
  Input.update
    if Input.trigger?(:RIGHT)
    @skeleton.x += 20
  end
  if Input.trigger?(:LEFT)
    @skeleton.x -= 20
  end
  if Input.trigger?(:UP)
    @skeleton.y -= 20
  end
  if Input.trigger?(:DOWN)
    @skeleton.y += 20
    end
return_scene if Input.trigger?(:B)
break
end
end
end
としたら動くようになりました。ありがとうございます。
 

faida

ユーザー
解決したようなので余計かもしれませんが補足します。
コード:
def update
  super
  if Input.trigger?(:RIGHT)
    @skeleton.x += 20
  end
  if Input.trigger?(:LEFT)
    @skeleton.x -= 20
  end
  if Input.trigger?(:UP)
    @skeleton.y -= 20
  end
  if Input.trigger?(:DOWN)
    @skeleton.y += 20
    end
  return_scene if Input.trigger?(:B)
end
super忘れてました。
superとはスーパークラスの同名メソッド処理を呼び出すもので、
「基礎編」→「クラス定義」→「メソッドのオーバーライド」に記述があります。
この場合Scene_Baseのupdateを呼び出します。
Scene_Baseのupdateは「update_basic」の1行で、update_basicは以下の通りです。
コード:
  def update_basic
    Graphics.update
    Input.update
    update_all_windows
  end
ここでGraphics.updateとInput.updateが呼び出されるので、Scene_Skeletonで呼び出す必要がなくなります。
(前の書き込みだとGraphics.updateがなくて読込中になってました)
あと、実はupdateは元からループ処理なので、ループを使用する必要はありません。
これは「解読編」→「シーンの管理」→「シーンの管理」に記述があります。

終了処理で@skeletonの解放をする件ですが、
シーン遷移して元のシーンに戻る時に、Spriteが表示されたままになってしまう場合があります。
これの対策として@skeletonの解放を行う必要があるんですが、
特に影響がなければ自動的に解放する機能があるので、シーンを連続して呼び出さない限りは大丈夫かと思います。

以下そのコードです。
コード:
  def terminate
    super
    @skeleton.bitmap.dispose
    @skeleton.dispose
  end
 

八拾壱

ユーザー
ありがとうございます。
コード:
class Scene_Skeleton < Scene_Base
def start
  super
  @skeleton = Sprite.new
  @skeleton.bitmap = Bitmap.new("Graphics/Battlers/Skeleton")
  @skeleton.ox = @skeleton.bitmap.width / 2
  @skeleton.oy = @skeleton.bitmap.height / 2
  @skeleton.x = 272
  @skeleton.y = 208
end
def update
  super
  if Input.trigger?(:RIGHT)
    @skeleton.x += 20
  end
  if Input.trigger?(:LEFT)
    @skeleton.x -= 20
  end
  if Input.trigger?(:UP)
    @skeleton.y -= 20
  end
  if Input.trigger?(:DOWN)
    @skeleton.y += 20
  end
  if Input.trigger?(:C)
   @skeleton.x = 272
   @skeleton.y = 208
 end
 return_scene if Input.trigger?(:B)
end
def terminate
  super
  @skeleton.bitmap.dispose
  @skeleton.dispose
  end
end

このように打ち直ししました。とてもすっきりしたと思います。
スクリプト入門の説明を読んでもよくわからなかったので行き当たりばったりで
やっていました。本当にありがとうございました。
 
トップ