2021-08-07 Godot Engine > 猫とiconの衝突判定 > (キャラクタをカーソルで移動, キャラクタをマウスで移動, 衝突判定)

### 動作環境

```
Windows 10 Pro v21H1
Godot Engine v3.3.2.stable.official
```

### 処理概要

- キャラクタをカーソルで移動
    - Spaceキー押しながらで加速
- キャラクタをマウスで移動
- 衝突判定
    - 衝突した後も残るノード
    - 衝突した後に消えるノード

## 実装

### キャラクタ

[EDGE](https://takabosoft.com/edge)を使って描画。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/32870/0ee344c1-dea3-5274-ed41-faa4b70b8280.png)

### ノード階層

(左は名前、右はノードの種類)

- Node2D: Node2D
    - Player : KinematicBody2D > Player.gdをアタッチ
        - Sprite
        - CollisionShape2D
    - Enemy_always : KinematicBody2D
        - Enemy_sprite : Sprite
        - Collision_enemy : CollisionShape2D
    - Enemy_fadeAway : KinematicBody2D
        - Enemy_sprite : Sprite
        - Collision_enemy : CollisionShape2D

### 備考

二つのEnemyオブジェクトのどちらと衝突したかは距離で判定することにした。


### Collisionレイヤー設定

以下のレイヤーを用意して割り当てた

- Player
    - PlayerのCollision.Layer
    - Enemy_alwaysのCollision.Mask
    - Enemy_fadeAwayのCollision.Mask
- Enemy
    - Enemy_alwaysのCollision.Layer
    - Enemy_fadeAwayのCollision.Layer

### コード

```python:Player.gd
extends KinematicBody2D

var shift_right =  Vector2(32, 0) * 4
var shift_left  = -Vector2(32, 0) * 4
var shift_up    = -Vector2(0, 32) * 4
var shift_down  =  Vector2(0, 32) * 4

onready var enemyNode_always   = get_node("../Enemy_always")
onready var enemyColl_always   = get_node("../Enemy_always/Collision_enemy")
onready var enemyNode_fadeaway = get_node("../Enemy_fadeAway")
onready var enemyColl_fadeaway = get_node("../Enemy_fadeAway/Collision_enemy")

const CHARACTER_SIZE = 64  # 64 x 64
const DISP_WIDTH = 1024
const DISP_HEIGHT = 600

func myMoveAndCollide(delta):
	if position.x < CHARACTER_SIZE / 2:
		position.x = CHARACTER_SIZE / 2
		return false
	if position.x > DISP_WIDTH:
		position.x = DISP_WIDTH
		return false
	if position.y < CHARACTER_SIZE / 2:
		position.y = CHARACTER_SIZE / 2
		return false
	if position.y > DISP_HEIGHT:
		position.y = DISP_HEIGHT
		return false
	return move_and_collide(delta)
	
func hideEnemy():
	var dist = enemyNode_fadeaway.transform.origin.distance_to(position)
	print(dist)
	if dist > 100:  # not fadeaway Node
		return
	enemyNode_fadeaway.visible = false  # hide
	enemyColl_fadeaway.disabled = true  # disable collision

func _process(delta):
	# acceleration
	var accel = 1.0
	var collide
	if Input.is_action_pressed("ui_accept"):
		accel = 2.0
	# movement
	if Input.is_action_pressed("ui_right"):
		collide = myMoveAndCollide(shift_right * delta * accel)
	if Input.is_action_pressed("ui_left"):
		collide = myMoveAndCollide(shift_left * delta * accel)
	if Input.is_action_pressed("ui_up"):
		collide = myMoveAndCollide(shift_up * delta * accel)
	if Input.is_action_pressed("ui_down"):
		collide = myMoveAndCollide(shift_down * delta * accel)

	if collide:
		hideEnemy()
		# for debug
		print("collide1,", collide)
		
func _input(event):
	var collide
	if event is InputEventMouseButton:
		var moveShift = event.position - position
		moveShift = moveShift.normalized() * CHARACTER_SIZE / 2
		collide = myMoveAndCollide(moveShift)
	if collide:
		hideEnemy()
		# for debug
		print("collide2,", collide)

```

### 実行例

起動時:
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/32870/006a2077-ecbe-11d0-1f2c-0ecdcc66ad31.png)

右側のiconに衝突後:
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/32870/ed6e1df0-819b-a665-3a64-5ce96ce2f662.png)


### 参考

- [How to get the distance between a Kinematic and a Rigid body in 3D](https://godotengine.org/qa/83644/how-to-get-the-distance-between-kinematic-and-rigid-body-in-3d)
- [Understanding node paths](https://kidscancode.org/godot_recipes/basics/getting_nodes/)
- [【Godot】コリジョンレイヤーとマスクについて](https://qiita.com/2dgames_jp/items/062ab83ea1fcdb2c7f5e)