CoRサンプル集: 矩形当たり判定サンプル
      回転する矩形同士の当たり判定処理を行う
サンプルスクリプトです
_/_/_/_/_/ 操作方法 _/_/_/_/_/
方向キー:画像A(ビーム)の移動
Zキー:画像A(ビーム)の回転
スクリプトの参照はこちらから
    サンプルスクリプトです
_/_/_/_/_/ 操作方法 _/_/_/_/_/
方向キー:画像A(ビーム)の移動
Zキー:画像A(ビーム)の回転
スクリプトの参照はこちらから
          プレー:39
    (人数:38)
    クリア:0
評価: 10 (1回)
    
  #-------------------
#矩形当たり判定
#-------------------
#_/_/_/_/_/ 構造体 _/_/_/_/_/
#ポインタ
S_pointer = Struct.new(:name, :x, :y)
#_/_/_/_/_/ ユーザ関数 _/_/_/_/_/
#角度をラジアンに変更
def getRad(r)
  return (r * Math::PI / 180)
end
#ラジアンを角度に変更
def getAngle(r)
  return (180 / Math::PI * r)
end
#開始座標と角度と距離から終点座標を求める
def getDistancePos(s_p, r, ren)
  wrk_r = getRad(r)
  
  wrk_p = S_pointer.new('wrk_p', nil, nil)
  wrk_p.x = s_p.x - Math.cos(wrk_r) * ren
  wrk_p.y = s_p.y - Math.sin(wrk_r) * ren
  
  return wrk_p
end
#線分同士の当たり判定
def getIntersection(a_p1, a_p2, b_p1, b_p2)
  ret = false
  
  if(((a_p1.x - a_p2.x) * (b_p1.y - a_p1.y) + (a_p1.y - a_p2.y) * (a_p1.x - b_p1.x)) * 
     ((a_p1.x - a_p2.x) * (b_p2.y - a_p1.y) + (a_p1.y - a_p2.y) * (a_p1.x - b_p2.x)) < 0)
    
    if(((b_p1.x - b_p2.x) * (a_p1.y - b_p1.y) + (b_p1.y - b_p2.y) * (b_p1.x - a_p1.x)) * 
       ((b_p1.x - b_p2.x) * (a_p2.y - b_p1.y) + (b_p1.y - b_p2.y) * (b_p1.x - a_p2.x)) < 0)
      
      ret = true
    end
  end
  
  return ret
end
#矩形同士の当たり判定
def getCollision(a_pos_x, a_pos_y, a_size_w, a_size_h, a_r, 
                 b_pos_x, b_pos_y, b_size_w, b_size_h, b_r)
  
  ret = false
  
  #--- 各矩形の4点の座標を求める ---
  
  #Aの中心点
  A_C = S_pointer.new('A_C', a_pos_x, a_pos_y)
  wrk_ren = Math.sqrt((a_size_w / 2) ** 2 + (a_size_h / 2) ** 2)
  
  #Aの左上
  wrk_r     = getAngle(Math.atan2((a_size_h / 2) * (1), (a_size_w / 2) * (1)))
  wrk_pos   = getDistancePos(A_C, (a_r + wrk_r), wrk_ren)
  wrk_pos_x = wrk_pos.x;  wrk_pos_y = wrk_pos.y
  A_u_l = S_pointer.new('A_u_l', wrk_pos_x, wrk_pos_y)
  
  #Aの右上
  wrk_r     = getAngle(Math.atan2((a_size_h / 2) * (1), (a_size_w / 2) * (-1)))
  wrk_pos   = getDistancePos(A_C, (a_r + wrk_r), wrk_ren)
  wrk_pos_x = wrk_pos.x;  wrk_pos_y = wrk_pos.y
  A_u_r = S_pointer.new('A_u_r', wrk_pos_x, wrk_pos_y)
  
  #Aの左下
  wrk_r     = getAngle(Math.atan2((a_size_h / 2) * (-1), (a_size_w / 2) * (1)))
  wrk_pos   = getDistancePos(A_C, (a_r + wrk_r), wrk_ren)
  wrk_pos_x = wrk_pos.x;  wrk_pos_y = wrk_pos.y
  A_d_l = S_pointer.new('A_d_l', wrk_pos_x, wrk_pos_y)
  
  #Aの右下
  wrk_r     = getAngle(Math.atan2((a_size_h / 2) * (-1), (a_size_w / 2) * (-1)))
  wrk_pos   = getDistancePos(A_C, (a_r + wrk_r), wrk_ren)
  wrk_pos_x = wrk_pos.x;  wrk_pos_y = wrk_pos.y
  A_d_r = S_pointer.new('A_d_r', wrk_pos_x, wrk_pos_y)
  
  
  #Bの中心点
  B_C = S_pointer.new('B_C', b_pos_x, b_pos_y)
  wrk_ren = Math.sqrt((b_size_w / 2) ** 2 + (b_size_h / 2) ** 2)
  
  #Bの左上
  wrk_r     = getAngle(Math.atan2((b_size_h / 2) * (1), (b_size_w / 2) * (1)))
  wrk_pos   = getDistancePos(B_C, (b_r + wrk_r), wrk_ren)
  wrk_pos_x = wrk_pos.x;  wrk_pos_y = wrk_pos.y
  B_u_l = S_pointer.new('B_u_l', wrk_pos_x, wrk_pos_y)
  
  #Bの右上
  wrk_r     = getAngle(Math.atan2((b_size_h / 2) * (1), (b_size_w / 2) * (-1)))
  wrk_pos   = getDistancePos(B_C, (b_r + wrk_r), wrk_ren)
  wrk_pos_x = wrk_pos.x;  wrk_pos_y = wrk_pos.y
  B_u_r = S_pointer.new('B_u_r', wrk_pos_x, wrk_pos_y)
  
  #Bの左下
  wrk_r     = getAngle(Math.atan2((b_size_h / 2) * (-1), (b_size_w / 2) * (1)))
  wrk_pos   = getDistancePos(B_C, (b_r + wrk_r), wrk_ren)
  wrk_pos_x = wrk_pos.x;  wrk_pos_y = wrk_pos.y
  B_d_l = S_pointer.new('B_d_l', wrk_pos_x, wrk_pos_y)
  
  #Bの右下
  wrk_r     = getAngle(Math.atan2((b_size_h / 2) * (-1), (b_size_w / 2) * (-1)))
  wrk_pos   = getDistancePos(B_C, (b_r + wrk_r), wrk_ren)
  wrk_pos_x = wrk_pos.x;  wrk_pos_y = wrk_pos.y
  B_d_r = S_pointer.new('B_d_r', wrk_pos_x, wrk_pos_y)
  
  
  #--- 各矩形の4点の座標から線分の当たり判定を求める ---
  #--- (何れか1本でも交われば、当たっていると判定) ---
  
  #Aの上、Bの上
  wrk_flg = getIntersection(A_u_l, A_u_r, B_u_l, B_u_r)
  if wrk_flg then ret = true; end
  
  #Aの上、Bの下
  wrk_flg = getIntersection(A_u_l, A_u_r, B_d_l, B_d_r)
  if wrk_flg then ret = true; end
  
  #Aの上、Bの左
  wrk_flg = getIntersection(A_u_l, A_u_r, B_u_l, B_d_l)
  if wrk_flg then ret = true; end
  
  #Aの上、Bの右
  wrk_flg = getIntersection(A_u_l, A_u_r, B_u_r, B_d_r)
  if wrk_flg then ret = true; end
  
  
  #Aの下、Bの上
  wrk_flg = getIntersection(A_d_l, A_d_r, B_u_l, B_u_r)
  if wrk_flg then ret = true; end
  
  #Aの下、Bの下
  wrk_flg = getIntersection(A_d_l, A_d_r, B_d_l, B_d_r)
  if wrk_flg then ret = true; end
  
  #Aの下、Bの左
  wrk_flg = getIntersection(A_d_l, A_d_r, B_u_l, B_d_l)
  if wrk_flg then ret = true; end
  
  #Aの下、Bの右
  wrk_flg = getIntersection(A_d_l, A_d_r, B_u_r, B_d_r)
  if wrk_flg then ret = true; end
  
  
  #Aの左、Bの上
  wrk_flg = getIntersection(A_u_l, A_d_l, B_u_l, B_u_r)
  if wrk_flg then ret = true; end
  
  #Aの左、Bの下
  wrk_flg = getIntersection(A_u_l, A_d_l, B_d_l, B_d_r)
  if wrk_flg then ret = true; end
  
  #Aの左、Bの左
  wrk_flg = getIntersection(A_u_l, A_d_l, B_u_l, B_d_l)
  if wrk_flg then ret = true; end
  
  #Aの左、Bの右
  wrk_flg = getIntersection(A_u_l, A_d_l, B_u_r, B_d_r)
  if wrk_flg then ret = true; end
  
  
  #Aの右、Bの上
  wrk_flg = getIntersection(A_u_r, A_d_r, B_u_l, B_u_r)
  if wrk_flg then ret = true; end
  
  #Aの右、Bの下
  wrk_flg = getIntersection(A_u_r, A_d_r, B_d_l, B_d_r)
  if wrk_flg then ret = true; end
  
  #Aの右、Bの左
  wrk_flg = getIntersection(A_u_r, A_d_r, B_u_l, B_d_l)
  if wrk_flg then ret = true; end
  
  #Aの右、Bの右
  wrk_flg = getIntersection(A_u_r, A_d_r, B_u_r, B_d_r)
  if wrk_flg then ret = true; end
  
  
  return ret
end
#画像オブジェクトの透明度を設定
def setAlpha(obj, a)
  wrk_obj = obj.instance_variable_get('@js_sprite')
  wrk_obj.alpha = a
end
scene 'start' do
  #_/_/_/ ローカル変数の定義 _/_/_/
  
  #キー入力
  key_flg_up_st    = nil;  key_flg_up_do    = nil;  key_flg_up_en    = nil
  key_flg_down_st  = nil;  key_flg_down_do  = nil;  key_flg_down_en  = nil
  key_flg_left_st  = nil;  key_flg_left_do  = nil;  key_flg_left_en  = nil
  key_flg_right_st = nil;  key_flg_right_do = nil;  key_flg_right_en = nil
  
  key_flg_z_st = nil;      key_flg_z_do = nil;      key_flg_z_en = nil
  
  
  #画像オブジェクト
  obj_image_A_key_up    = nil
  obj_image_A_key_down  = nil
  obj_image_A_key_left  = nil
  obj_image_A_key_right = nil
  
  obj_image_A_key_z     = nil
  
  
  obj_image_A_spr = nil
  
  obj_image_A_pos_x = nil
  obj_image_A_pos_y = nil
  
  obj_image_A_size_w = nil
  obj_image_A_size_h = nil
  
  obj_image_A_r = nil
  
  obj_image_A_pos_x_old = nil
  obj_image_A_pos_y_old = nil
  
  obj_image_A_r_old = nil
  
  
  obj_image_B_spr = nil
  
  obj_image_B_pos_x = nil
  obj_image_B_pos_y = nil
  
  obj_image_B_size_w = nil
  obj_image_B_size_h = nil
  
  obj_image_B_r = nil
  
  obj_image_B_alpha = nil
  
  obj_image_B_alpha_old = nil
  
  
  preload do 
    #_/_/_/ 素材のロード _/_/_/
    
    #画像A
    image 'img_image_A', id: 77342
    
    #画像B
    image 'img_image_B', id: 79094
  end
  
  create do
    #_/_/_/ 変数の初期化 _/_/_/
    
    #--- キー入力 ---
    key_flg_up_st    = false;  key_flg_up_do    = false;  key_flg_up_en    = false
    key_flg_down_st  = false;  key_flg_down_do  = false;  key_flg_down_en  = false
    key_flg_left_st  = false;  key_flg_left_do  = false;  key_flg_left_en  = false
    key_flg_right_st = false;  key_flg_right_do = false;  key_flg_right_en = false
    
    key_flg_z_st = false;      key_flg_z_do = false;      key_flg_z_en = false
    
    
    #--- 画像オブジェクト ---
    obj_image_A_key_up    = false
    obj_image_A_key_down  = false
    obj_image_A_key_left  = false
    obj_image_A_key_right = false
    
    obj_image_A_key_z     = nil
    
    
    obj_image_A_pos_x = (800 / 2)
    obj_image_A_pos_y = (600 - 128)
    
    obj_image_A_size_w = (14 * 2)
    obj_image_A_size_h = (64 * 2)
    
    obj_image_A_r = 0
    
    obj_image_A_pos_x_old = obj_image_A_pos_x
    obj_image_A_pos_y_old = obj_image_A_pos_y
    
    obj_image_A_r_old = obj_image_A_r
    
    
    obj_image_B_pos_x = (800 / 2)
    obj_image_B_pos_y = (600 / 2)
    
    obj_image_B_size_w = (32 * 2)
    obj_image_B_size_h = (32 * 2)
    
    obj_image_B_r = 0
    
    obj_image_B_alpha = 1
    
    obj_image_B_alpha_old = obj_image_B_alpha
    
    
    #_/_/_/ 素材の初期化 _/_/_/
    
    #画像A
    obj_image_A_spr = put_sprite 'spr_image_A' do
      position obj_image_A_pos_x, obj_image_A_pos_y
      src_rect 0, 0, 16, 64
    end
    obj_image_A_spr.scale 2, 2
    
    #画像B
    obj_image_B_spr = put_sprite 'spr_image_B' do
      position obj_image_B_pos_x, obj_image_B_pos_y
      src_rect (32 * 7), (32 * 5), 32, 32
    end
    obj_image_B_spr.scale 2, 2
    
  end
  
  update do
    #_/_/_/ 入力の判定 _/_/_/
    #キー入力判定
    if keyboard.down?('UP')
      key_flg_up_st = true
    else
      key_flg_up_st = false
      key_flg_up_do = false
    end
    
    if keyboard.down?('DOWN')
      key_flg_down_st = true
    else
      key_flg_down_st = false
      key_flg_down_do = false
    end
    
    if keyboard.down?('LEFT')
      key_flg_left_st = true
    else
      key_flg_left_st = false
      key_flg_left_do = false
    end
    
    if keyboard.down?('RIGHT')
      key_flg_right_st = true
    else
      key_flg_right_st = false
      key_flg_right_do = false
    end
    
    if keyboard.down?('Z')
      key_flg_z_st = true
    else
      key_flg_z_st = false
      key_flg_z_do = false
    end
    
    
    #_/_/_/ メイン処理 _/_/_/
    #キー入力処理
    if (key_flg_up_st && !key_flg_up_do)
      key_flg_up_do = true
      obj_image_A_key_up = true
    elsif key_flg_up_do
      key_flg_up_en = true
      obj_image_A_key_up = true
    elsif key_flg_up_en
      key_flg_up_en = false
      obj_image_A_key_up = false
    end
    
    if (key_flg_down_st && !key_flg_down_do)
      key_flg_down_do = true
      obj_image_A_key_down = true
    elsif key_flg_down_do
      key_flg_down_en = true
      obj_image_A_key_down = true
    elsif key_flg_down_en
      key_flg_down_en = false
      obj_image_A_key_down = false
    end
    
    if (key_flg_left_st && !key_flg_left_do)
      key_flg_left_do = true
      obj_image_A_key_left = true
    elsif key_flg_left_do
      key_flg_left_en = true
      obj_image_A_key_left = true
    elsif key_flg_left_en
      key_flg_left_en = false
      obj_image_A_key_left = false
    end
    
    if (key_flg_right_st && !key_flg_right_do)
      key_flg_right_do = true
      obj_image_A_key_right = true
    elsif key_flg_right_do
      key_flg_right_en = true
      obj_image_A_key_right = true
    elsif key_flg_right_en
      key_flg_right_en = false
      obj_image_A_key_right = false
    end
    
    if (key_flg_z_st && !key_flg_z_do)
      key_flg_z_do = true
      obj_image_A_key_z = true
    elsif key_flg_z_do
      key_flg_z_en = true
      obj_image_A_key_z = true
    elsif key_flg_z_en
      key_flg_z_en = false
      obj_image_A_key_z = false
    end
    
    
    #画像Aの操作
    #移動
    if obj_image_A_key_up
      obj_image_A_pos_y -= 2
    end
    
    if obj_image_A_key_down
      obj_image_A_pos_y += 2
    end
    
    if obj_image_A_key_left
      obj_image_A_pos_x -= 2
    end
    
    if obj_image_A_key_right
      obj_image_A_pos_x += 2
    end
    
    #回転
    if obj_image_A_key_z
      obj_image_A_r += 1
    end
    
    
    #画像Bをゆっくりと回転させる
    obj_image_B_r += 1
    if obj_image_B_r > 360
      obj_image_B_r -= 360
    end
    
    
    #********************
    #画像Aと画像Bの当たり判定を求める
    wrk_flg = getCollision(obj_image_A_pos_x,  obj_image_A_pos_y, 
                           obj_image_A_size_w, obj_image_A_size_h, 
                           obj_image_A_r,
                           obj_image_B_pos_x,  obj_image_B_pos_y, 
                           obj_image_B_size_w, obj_image_B_size_h, 
                           obj_image_B_r)
    #********************
    
    
    #当たっていた場合、画像Bの透明度を変更する
    if wrk_flg
      obj_image_B_alpha = 0.5
    else
      obj_image_B_alpha = 1
    end
    
  end
  
  render do
    #画像Aの移動
    if (obj_image_A_pos_x != obj_image_A_pos_x_old) ||
       (obj_image_A_pos_y != obj_image_A_pos_y_old)
      
      obj_image_A_pos_x_old = obj_image_A_pos_x
      obj_image_A_pos_y_old = obj_image_A_pos_y
      
      obj_image_A_spr.position obj_image_A_pos_x, obj_image_A_pos_y
    end
    
    #画像Aの回転
    if obj_image_A_r != obj_image_A_r_old
      obj_image_A_r_old != obj_image_A_r
      
      wrk_r = getRad(obj_image_A_r)
      obj_image_A_spr.rotation wrk_r
    end
    
    
    #画像Bの回転
    wrk_r = getRad(obj_image_B_r)
    obj_image_B_spr.rotation wrk_r
    
    #画像Bの透明度
    if obj_image_B_alpha != obj_image_B_alpha_old
      obj_image_B_alpha_old = obj_image_B_alpha
      
      setAlpha(obj_image_B_spr, obj_image_B_alpha)
    end
    
  end
end
#_/_/_/_/_/ 素材の定義 _/_/_/_/_/
#画像A
sprite 'spr_image_A' do
  image 'img_image_A'
  origin :center
end
#画像B
sprite 'spr_image_B' do
  image 'img_image_B'
  origin :center
end
#_/_/_/_/_/ シーンの開始 _/_/_/_/_/
start_scene 'start'
  コード一覧
- start.rb
プレー内容を公開する
    コメントする
コメントするには、ログインする必要があります。
コメント一覧
 なとおとき(投稿日:2022/08/28 20:06,
                                               履歴)
 なとおとき(投稿日:2022/08/28 20:06,
                                               履歴)
    
      2線分の交点を求める論理に感動しました。「ABをs:(1-s)に内分する」のsを、Aから見てもBから見ても同符号(正)になれば内分されている、とするのは初めて見た気がします。衝撃です。
  プレー履歴
    プレー履歴はありません。
新着レビュー
      レビューはまだ投稿されていません。 作品の感想を作者に伝えるためにレビューを投稿してみませんか?
フォロー/シェア
    
    
    
    
  