ä»åã®èšäºã§ã¯ã2Dã²ãŒã ã§ã®ç»é¢æºãã®å®è£ æ¹æ³ã玹ä»ãããã²ãŒã ã«çµ¶å¯Ÿã«å¿ èŠãªèŠçŽ ã§ã¯ãªãããããŸã䜿ãã°ãã¬ã€ã€ãŒã®ã²ãŒã äœéšãããã€ã³ã¿ã©ã¯ãã£ãã«ã§ãããŠãŒã¶ãšã¯ã¹ããªãšã³ã¹ã«çŽæ¥åœ±é¿ãäžããããšãã§ãããäŸãã°ãéãæã£ãæãæµãããã¡ãŒãžãåããæãé«ããšããããèœã¡ãæãªã©ã䜿ããããªå Žé¢ã¯å±±ã»ã©ãããã¡ãªã¿ã«ããã®ãããªå¿ èŠã§ã¯ãªããã®ã®è¿œå ããããšã§ã²ãŒã ãããé¢çœãããèŠçŽ ããè±èªåã§ã¯ã²ãŒã ã»ãžã¥ãŒã¹[Game Juice]ãšããããŸãããããããšããžã¥ãŒã·ã³ã°[Juicing]ãšããããã ã
ç»é¢æºãã®å®è£ æ¹æ³ã«ã€ããŠè§£èª¬ãããªãœãŒã¹ã¯ Web äžã«ããããååšããä»å玹ä»ãã以å€ã®æ¹æ³ããã¡ããååšãããä»åã¯ãã®äžã§ãç¹ã«ä»¥äžã®åç»ãšèšäºãåèã«ããŠããã®ã§ã䜵ããŠç¢ºèªããã ããšããç解ãæ·±ãŸãã ããã
Reference
YouTube: GDC - Math for Game Programmers: Juicing Your Cameras With Math
KidsCanCode: SCREEN SHAKE
ãã®ãã¥ãŒããªã¢ã«ã§æåŸã«ã§ãããããããžã§ã¯ãã®ãã¡ã€ã«ã¯GitHubãªããžããª
ã«çœ®ããŠããã.zipãã¡ã€ã«ãããŠã³ããŒãããŠããã ãããEndããã©ã«ãå
ã®ãproject.godotããã¡ã€ã«ã Godot Engine ã§ã€ã³ããŒãããŠããã ããã°ãçŽæ¥ãããžã§ã¯ãã確èªããŠããã ãããšãå¯èœã ã
Environment
Godot ã®ããŒãžã§ã³: 3.4.4
ã³ã³ãã¥ãŒã¿ã®OS: macOS 11.6.5
æºå
æ°èŠãããžã§ã¯ããäœæãã
ããã§ã¯ Godot Engine ãç«ã¡äžããŠãæ°èŠãããžã§ã¯ããäœæãããããããžã§ã¯ãã®ååã¯ããªãã®ã奜ã¿ã§æ±ºããŠããã ããŠOKã ãããæãã€ããªããã°ãScreen ShakeããšããŠãããã
ãããžã§ã¯ãèšå®ãæŽæ°ãã
ãšãã£ã¿ã衚瀺ããããããããžã§ã¯ãå šäœã«é¢ããèšå®ãæŽæ°ããŠããã
ãŸãã¯ã²ãŒã ã®ãã£ã¹ãã¬ã€ãµã€ãºãèšå®ãããä»å㯠16 px ãåºæºå€ãšããŠçžŠæšª 9:16 ã®æ¯çãšããã
ããããžã§ã¯ããã¡ãã¥ãŒïŒããããžã§ã¯ãèšå®ããéãã
ãäžè¬ãã¿ãã§ãwindowãã§æ€çŽ¢ããŠããµã€ãããŒã®ãDisplayãïŒãWindowããéžæããã
ãSizeãã»ã¯ã·ã§ã³ã§ä»¥äžã®é ç®ã®å€ãå€æŽããã
- Width: 256
- Height: 144
- Test Width: 512
- Test Height: 288
ãStretchãã»ã¯ã·ã§ã³ã§ä»¥äžã®é ç®ã®å€ãå€æŽããã
- Mode: 2d
- Aspect: keep
ãã€ã³ãããããããã¿ãã«åãæ¿ããã¢ã¯ã·ã§ã³ã«ãshakeããè¿œå ããã
ãshakeãã®æäœã«ãspaceãããŒãå²ãåœãŠãã
ã¢ã»ãããããŠã³ããŒãããŠã€ã³ããŒããã
次ã«ãKENNEYã®ãµã€ãããã¢ã»ãããããŠã³ããŒãããŠå©çšãããŠãããããä»åå©çšããã®ã¯ãTiny Dungeon ããšããã¢ã»ããããã¯ã ããã®ã¢ã»ããã«å«ãŸããã¿ã€ã«ã»ããã䜿çšããããã®çŽ æŽãããããç¡æã®çŽ æã«æè¬ããã«ã¯ããããªãã
ããŠã³ããŒããããã/kenney_tinydungeon/Tilemap/tilemap_packed.pngãããã¡ã€ã«ã·ã¹ãã ããã¯ãžãã©ãã°ããŠãããžã§ã¯ãã«ã€ã³ããŒãããã
ãã¡ã€ã«ãã€ã³ããŒãããçŽåŸã¯ç»åããŒãããæãã«ãªã£ãŠããã®ã§ãããã以äžã®æé ã§ä¿®æ£ããŠããã
- ãã¡ã€ã«ã·ã¹ãã ããã¯ã§ã€ã³ããŒãããã¢ã»ãããã¡ã€ã«ãéžæããç¶æ ã«ãã
- ã€ã³ããŒãããã¯ã§ãããªã»ãããïŒã2D Pixelããéžæãã
- äžçªäžã«ãããåã€ã³ããŒãããã¿ã³ãã¯ãªãã¯ããã
ããã§ãã¯ã»ã«ã¢ãŒãç¹æã®ãšããžã®å¹ããç»åã«ãªã£ãã¯ãã ãã€ã³ããŒãããã¿ã€ã«ã»ããã¯ãåŸã»ã©ã¿ã€ã«ãããäœææã«å©çšããã
Camera ã·ãŒã³ãäœã
Camera ã·ãŒã³ãæ°èŠäœæãã
ãŸã㯠Camera ã·ãŒã³ãäœæãããã
- ãã·ãŒã³ãã¡ãã¥ãŒïŒãæ°èŠã·ãŒã³ããéžæããã
- ãCamera2Dãã¯ã©ã¹ã®ããŒããã«ãŒãããŒããšããŠéžæããããååããCameraãã«å€æŽããã
- äžæŠããã§ã·ãŒã³ãä¿åããããã©ã«ããäœæããŠããã¡ã€ã«ãã¹ããres://Camera/Camera.tscnããšããŠã·ãŒã³ãä¿åããã
ã·ãŒã³ããªãŒã¯åããŒãããªããããã·ãŒã³ããã¯ã¯ä»¥äžã®ããã«ãCameraãããŒãã®ã¿ã«ãªã£ãŠããã¯ãã ã
Camera ããŒãã®ããããã£ãç·šéãã
ç¶ããŠã€ã³ã¹ãã¯ã¿ãŒã§ä»¥äžã®ç·šéãããã
- ãCurrentãããããã£ã On ã«ããã
- ãLimitãããããã£ããã£ã¹ãã¬ã€ãµã€ãºã«åãããã
Camera ããŒãã«ã¹ã¯ãªãããã¢ã¿ããããŠç·šéãã
Camera ããŒãã«æ°èŠã§ã¹ã¯ãªãããã¢ã¿ããããããã¡ã€ã«ãã¹ããres://Camera/Camera.tscnããšããŠã¹ã¯ãªãããã¡ã€ã«ãäœæããã
ä»åããèãç»é¢æºãããšãæ»ãããªç»é¢æºããã®2çš®é¡ã®æºããå®è£ ããŠããããŸãå ã«ã³ãŒãã®å 容ãæ¯èŒçã·ã³ãã«ãªãèãç»é¢æºããããã
ã¹ã¯ãªããã«ã¯ä»¥äžã®ã³ãŒããèšè¿°ããã
###Camera.gd###
extends Camera2D
# æºãã®åŒ·ãïŒ0.0ãã1.0ãŸã§ïŒ
var trauma = 0.0
# æºãã®åŒ·ãã环ä¹ããéã®ææ°
var trauma_power = 2
# æºãã®åŒ·ã trauma ãææ° trauma_power ã§çŽ¯ä¹ããå€ãå
¥ãã
var amount = 0.0
# 1ç§ã§æžè¡°ããæºãã®åŒ·ãïŒ0.0以äžã ãšæ°žé ã«æºããã®ã§æ³šæïŒ
var decay = 0.8
# æ倧ã®æºãå¹
ïŒx軞æ¹åãy軞æ¹åããããã®å€ãVector2åã§äžã€ã®ããŒã¿ãšããŠä¿æïŒ
var max_offset = Vector2(36, 64) # display ratio is 16 : 9
# æ倧ã®å転è§åºŠïŒã©ãžã¢ã³)
var max_roll = 0.1
# ããŒããèªã¿èŸŒãŸãããæåã«åŒã°ããçµã¿èŸŒã¿é¢æ°
func _ready():
# ã©ã³ãã å€ãè¿ãé¢æ°ã®ããã«ã·ãŒãå€ãã©ã³ãã åãã
# ã·ãŒãå€ãåãã ãšåŸãããæ°ãåãã«ãªãããå¿
é
randomize()
# æ¯ãã¬ãŒã åŒã°ããçµã¿èŸŒã¿ã®ããã»ã¹é¢æ°
func _process(delta):
# ãã trauma ã®æ°å€ã0ãã倧ãããã°
if trauma:
# æºãã®åŒ·ããæžè¡°ããã
trauma = max(trauma - decay * delta, 0)
# èãç»é¢æºãã®æºãå¹
ãšå転è§åºŠãèšå®ããã¡ãœãããåŒã¶
# ãããæ¯ãã¬ãŒã åŒã¶ããšã§ç»é¢æºããè¡šçŸãã
rough_shake() # ãã®ããšå®çŸ©
# èãç»é¢æºãã®æºãå¹
ãšå転è§åºŠãèšå®ããã¡ãœãã
func rough_shake():
# amount ã¯æºãã®åŒ·ãã环ä¹ããå€
# pow() é¢æ°ã¯ç¬¬äžåŒæ°ã第äºåŒæ°ãææ°ãšããŠçŽ¯ä¹ãã
# æºãã®åŒ·ãã 0 ã«è¿ã¥ãã»ã©ã环ä¹ãããšãã®å€ã¯ããå°ãããªã
# äŸ: 1.0 * 1.0 = 1.0, 0.5 * 0.5 = 0.25, 0.1 * 0.1 = 0.01
amount = pow(trauma, trauma_power)
# å転è§åºŠ = æ倧å転è§åºŠ * æºãã®åŒ·ãã环ä¹ããå€ * -1 ~ 1 ã®ã©ã³ãã å€
rotation = max_roll * amount * rand_range(-1, 1)
# x軞æ¹åã®æºãå¹
= x軞æ¹åã®æ倧æºãå¹
* æºãã®åŒ·ãã环ä¹ããå€ * -1 ~ 1 ã®ã©ã³ãã å€
offset.x = max_offset.x * amount * rand_range(-1, 1)
# y軞æ¹åã®æºãå¹
= y軞æ¹åã®æ倧æºãå¹
* æºãã®åŒ·ãã环ä¹ããå€ * -1 ~ 1 ã®ã©ã³ãã å€
offset.y = max_offset.y * amount * rand_range(-1, 1)
# æºãã®åŒ·ããã»ããããã¡ãœãã
func set_shake(add_trauma = 0.5):
# åŒæ° add_trauma ã®å€ãçŸåšã® trauma ã®å€ã«å ç®ãã
# 1.0 以äžã«ãªãå Žå㯠trauma ã 1.0 ãšãã
trauma = min(trauma + add_trauma, 1.0)
# å
¥åãåŠçããçµã¿èŸŒã¿ã®é¢æ°
func _unhandled_input(event):
# ããã€ã³ããããããã®ã¢ã¯ã·ã§ã³ãshakeãã®ããŒãæŒããã
if event.is_action_pressed("shake"):
# æºãã®åŒ·ããã»ããããã¡ãœãããåŒã¶
set_shake()
ããã§ãèãç»é¢æºããã®ã¹ã¯ãªããã¯å®æã ã
World ã·ãŒã³ãäœã
World ã·ãŒã³ãæ°èŠäœæããŠå¿ èŠãªããŒããè¿œå ãã
Camera ã·ãŒã³ã ãã§ã¯ç»åããªãã®ã§æºããããããªããæºãã確èªããããã«ãWorld ã·ãŒã³ãäœæããããã« Camera ã·ãŒã³ã®ã€ã³ã¹ã¿ã³ã¹ãšãèæ¯ãšãªãããŒããçšæããŠããã
- ãã·ãŒã³ãã¡ãã¥ãŒïŒãæ°èŠã·ãŒã³ããéžæããã
- ã«ãŒãããŒããšããŠãNode2DããéžæããååããWorldãã«å€æŽããã
- ãã¡ã€ã«ãã¹ããres://World/World.tscnããšããŠã·ãŒã³ãä¿åããã
ç¶ããŠãWorld ã·ãŒã³ã以äžã®ã·ãŒã³ããªãŒã«ãªãããã«ããŒããè¿œå ããã
- World (Node2D)
- Camera (Camera2DãCameraã·ãŒã³ã®ã€ã³ã¹ã¿ã³ã¹)
- TileMap
TileMap ããŒããç·šéãã
èæ¯çšã«ææ©ãã¿ã€ã«ããããäœæãããã
- ãTileMapãããŒãã®ãTile Setãããããã£ã«æ°èŠã¿ã€ã«ã»ãããªãœãŒã¹ãé©çšããã
- ã¿ã€ã«ã»ããããã«ãéããå·ŠåŽã« KENNEY ããããŠã³ããŒããããres://Assets/tilemap_packed.pngããªãœãŒã¹ãã¡ã€ã«ããã©ãã°ããã·ã³ã°ã«ã¿ã€ã«ãã¢ãã©ã¹ã§ã¿ã€ã«ãé©åœã«èšå®ããã
- ã·ãŒã³ããã¯ã§ãTileMapããéžæããŠã¿ã€ã«ããããäœæãããç¯å²ã¯ãã£ã¹ãã¬ã€ãµã€ãºãå°ãã¯ã¿åºãçšåºŠã«ã
ãèãç»é¢æºããããã¹ããã
ãããããããžã§ã¯ããå®è¡ããŠãèãç»é¢æºããããã¹ãã ãåããŠå®è¡ããå Žåã¯ãããžã§ã¯ãã®ã¡ã€ã³ã·ãŒã³ã«ãWorld.tscnããéžæããã
ã¹ããŒã¹ããŒãæŒããŠç»é¢ãæºãããŠã¿ãããå°ãåŸ ã£ãŠããæŒããŠã¿ãããéã空ããã«é£ç¶çã«æŒãããããŠãæåã確èªããŠã¿ãã
éåæã¯ç¹ã«ãªãããããªãã«è¯ãæãã ããããããã®åŸå®è£ ããæ»ãããªç»é¢æºããšæ¯èŒãããšãããèãå°è±¡ãåããã¯ãã ã
Camera ããŒãã®ã¹ã¯ãªããã«ãæ»ãããªç»é¢æºããã®ã³ãŒããè¿œå ãã
ããããã¯ãæ»ãããªç»é¢æºãããå®è£ ããŠãããCamera ã·ãŒã³ã«æ»ããã¢ã¿ããããŠãããCamera.gdãã¹ã¯ãªããã«ã³ãŒããè¿œå ããã
æ»ãããªç»é¢æºãã¯ããã€ãºãšåŒã°ãã以äžã®ãããªç»åãå©çšããã
ãã€ãºç»åã«ã¯çœãã°ã¬ãŒãé»ãã©ã³ãã ã«ååžããŠãããé»ã -1 çœã 1 ãäžéã®ã°ã¬ãŒã 0 ãšããŠããã€ãºã®å€ã¯ -1 ~ 1 ãŸã§å€åããããã€ãºäžã®åº§æšãæå®ããŠããã®ãã¯ã»ã«ã®ãã€ãºã®å€ãååŸãããããç»é¢æºãã«å¿çšããããšããããã ã
Godot ã§ã¯ OpenSimplexNoiseãšããã¯ã©ã¹ïŒãªãœãŒã¹ïŒãçšæãããŠããããããã¹ã¯ãªããäžã§æ°èŠçæãããã®ãªãœãŒã¹ã®ã¯ã©ã¹ã«çµã¿èŸŒãŸããŠããget_noise_2d
ã¡ãœããã§ãåŒæ°ã«x座æšãy座æšãæž¡ããŠããããšãæå®ãã座æšã®ãã€ãºå€ãååŸã§ãããä»åã¯åŒæ°ã«æž¡ã x座æšãã©ã³ãã ã§æå®ããy座æšã 1 pixel ãã€ããããªãããã€ãºå€ãååŸãããããæºãå¹
ã®èšç®ã«ä¹ããããšã§ãæ»ãããªç»é¢æºããåçŸããã
ã¡ãªã¿ã«ããã€ãºãæ§æããããã€ãã®ãã©ã¡ãŒã¿ãå€åããããšããã€ãºãã©ã®ããã«å€ããã®ãã¯ãGodot ã® OpenSimplexNoise ãå©çšãã以äžã®ãã¢ããŒãžã§è²ã ãšè©ŠããŠã¿ããšçŽæçã«ç解ã§ãããããããªãã
Reference
OpenSimplexNoise Viewer
ãã€ãºã«ã€ããŠã¯ã¡ãã£ãšãããããæãããããããããªãããã²ãšãŸãã¹ã¯ãªãããèšè¿°ããŠã¿ãããã€ãã§ã«ãèãç»é¢æºãããšãæ»ãããªç»é¢æºãããåãæ¿ããããããã«ããŠããã
###Camera.gd###
extends Camera2D
# ç»é¢æºãã®çš®é¡ãenumã§å®çŸ©
enum {
ROUGH, # èãæºãã®å Žå
SMOOTH # æ»ãããªæºãã®å Žå
}
## å
±éã®ããããã£
var type = ROUGH # ç»é¢æºãã®çš®é¡ïŒããã©ã«ãã¯èãæºãïŒ
var trauma = 0.0
var trauma_power = 2
var amount = 0.0
## èãç»é¢æºãã®ããããã£
var decay = 0.8
var max_offset = Vector2(36, 64)
var max_roll = 0.1
## æ»ãããªç»é¢æºãã®ããããã£
var noise_y = 0 # ãã€ãºã® y 座æš
onready var noise = OpenSimplexNoise.new() # ãã€ãºã®ã€ã³ã¹ã¿ã³ã¹
func _ready():
randomize()
## æ»ãããªç»é¢æºãã®å Žåã«äœ¿çš
# ã·ãŒãïŒãã€ãºç¹æã®ã©ã³ãã ãªèŠãç®ã決ããå€ïŒã©ã³ãã ãªæŽæ°ãå²ãåœãŠãïŒ
# ã·ãŒãå€ãå€ããã°ãã€ãºã®çœããé»ã®ãããã®é
眮ãå€ãã
noise.seed = randi()
# ãªã¯ã¿ãŒãïŒãã€ãºãäœãã¬ã€ã€ãŒæ°ïŒããã§ã¯ 2 ãšããïŒ
# å€ã倧ããã»ã©çœãšé»ã®éã®ã°ã¬ãŒã®éå±€ãå¢ããŠè©³çŽ°ãªãã€ãºã«ãªã
noise.octaves = 2
# ããªãªãïŒãã€ãºã®åšæïŒããã§ã¯ 4 ãšããïŒ
# å€ãå°ããã»ã©é«åšæ³¢ãã€ãºã«ãªã
noise.period = 4
func _process(delta):
if trauma:
trauma = max(trauma - decay * delta, 0)
# ããç»é¢æºãã®çš®é¡ã ROUGH ã®å Žå
if type == ROUGH:
# èãç»é¢æºãã®æºãå¹
ãšå転è§åºŠãèšå®ããã¡ãœãããåŒã¶
rough_shake()
# ããç»é¢æºãã®çš®é¡ã SMOOTH ã®å Žå
elif type == SMOOTH:
# æ»ãããªç»é¢æºãã®æºãå¹
ãšè§åºŠãèšå®ããã¡ãœãããåŒã¶
smooth_shake()
func rough_shake():
amount = pow(trauma, trauma_power)
rotation = max_roll * amount * rand_range(-1, 1)
offset.x = max_offset.x * amount * rand_range(-1, 1)
offset.y = max_offset.y * amount * rand_range(-1, 1)
# æ»ãããªç»é¢æºãã®æºãå¹
ãšå転è§åºŠãèšå®ããã¡ãœãã
func smooth_shake():
# amount ã¯æºãã®åŒ·ãã环ä¹ããå€
amount = pow(trauma, trauma_power)
# ãã€ãºã® y 座æšã 1 ãã¯ã»ã«å¢ãã
noise_y += 1
# å転è§åºŠ = æ倧å転è§åºŠ * æºãã®åŒ·ãã环ä¹ããå€ * æå®ãã座æšã®ãã€ãºå€(-1 ~ 1)
rotation = max_roll * amount * noise.get_noise_2d(noise.seed, noise_y)
# x軞æ¹åã®æºãå¹
= x軞æ¹åã®æ倧æºãå¹
* æºãã®åŒ·ãã环ä¹ããå€ * æå®ãã座æšã®ãã€ãºå€(-1 ~ 1)
# noise.seed ã«ä¹ããŠãã 2 ã¯å転è§åºŠãšy軞æ¹åã®æºãå¹
ãšã¯ç°ãªããã€ãºå€ãååŸããããã®é©åœãªæ°å€
offset.x = max_offset.x * amount * noise.get_noise_2d(noise.seed * 2, noise_y)
# y軞æ¹åã®æºãå¹
= y軞æ¹åã®æ倧æºãå¹
* æºãã®åŒ·ãã环ä¹ããå€ * æå®ãã座æšã®ãã€ãºå€(-1 ~ 1)
# noise.seed ã«ä¹ããŠãã 3 ã¯å転è§åºŠãšx軞æ¹åã®æºãå¹
ãšã¯ç°ãªããã€ãºå€ãååŸããããã®é©åœãªæ°å€
offset.y = max_offset.y * amount * noise.get_noise_2d(noise.seed * 3, noise_y)
func set_shake(add_trauma = 0.5):
trauma = min(trauma + add_trauma, 1.0)
func _unhandled_input(event):
if event.is_action_pressed("shake"):
set_shake()
# å³ç¢å°ããŒãŸãã¯å·Šç¢å°ããŒãæŒãããç»é¢æºãã®çš®é¡ãåãæ¿ã
if event.is_action_pressed("ui_right")\
or event.is_action_pressed("ui_left"):
# çŸåšèãç»é¢æºãã®èšå®ã«ãªã£ãŠããã
if type == ROUGH:
# æ»ãããªç»é¢æºãã®èšå®ã«ãã
type = SMOOTH
# æ»ãããªç»é¢æºãã®èšå®ã«ãªã£ãŠããã
else:
# èãç»é¢æºãã®èšå®ã«ãã
type = ROUGH
World ã·ãŒã³ã«ããŒããè¿œå ãã
ç»é¢äžã©ã¡ãã®çš®é¡ã®ç»é¢æºãã«ãªã£ãŠãããåãããããããããã·ãŒã³ããªãŒã«ãCanvasLayerãããŒããšãã®åãšããŠãLabelãããŒããè¿œå ãããããŒãã®ååã¯ãTypeLabelããšããŠããã
ã€ã³ã¹ãã¯ã¿ãŒã§ãTextãããããã£ã«ãROUGHããšåæå€ãå
¥åããŠããã
ãTheme OverridesãïŒãColorãïŒãFont Colorãããããã£ã§ããã©ã³ãã®è²ã #000000ïŒé»ïŒãšããã
2D ã¯ãŒã¯ã¹ããŒã¹ã®ããŒã«ããŒã®ãLayoutããããäžå€®ããéžæãããTypeLabelãããŒãã®äœçœ®ãäžå€®ã«é
眮ããã
ãWorldãã«ãŒãããŒãã«ã¹ã¯ãªãããã¢ã¿ããããŠããã¡ã€ã«ãã¹ããres://World/World.gdããšããŠä¿åãããã¹ã¯ãªããã«ã¯ãç»é¢æºãã®çš®é¡ãåãæ¿ããæäœã®ããã«ä»¥äžã®ã³ãŒããèšè¿°ããã
###World.gd###
onready var type_label = $CanvasLayer/TypeLabel
func _unhandled_input(event):
if event.is_action_pressed("ui_right")\
or event.is_action_pressed("ui_left"):
if type_label.text == "ROUGH":
type_label.text = "SMOOTH"
else:
type_label.text = "ROUGH"
ããã§å·Šå³ç¢å°ããŒã§ç»é¢æºãã®çš®é¡ã ROUGHïŒèãç»é¢æºãïŒãš SMOOTHïŒæ»ãããªç»é¢æºãïŒãšã§åãæ¿ããããããã«ãªã£ãã
ãæ»ãããªç»é¢æºããããã¹ãããèãç»é¢æºãããšæ¯èŒãã
ããã§ã¯æåŸã«å床ãããžã§ã¯ããå®è¡ããæºãã®çš®é¡ãåãæ¿ãã€ã€ããæ»ãããªç»é¢æºããã®æåã確èªãããèãç»é¢æºãããšæ¯èŒããŠã¿ããã
以äžã§ãç»é¢æºãã®å®è£ ã¯å®äºã ãéããæããŠããã ããã ããããå ããªéããªæ°ãããããã²ãŒã ã®æŒåºã«ãã ãããªããã®å Žé¢ã«ãµããããæºããæ¡çšããããã®ã ã
ãµã³ãã«ãããžã§ã¯ã
ããã«èŠèŠçã«ç»é¢æºãã®ç¶æ ãåããããããããããžã§ã¯ããå¥ã§çšæããããããã°è§Šã£ãŠã¿ãŠã»ããã
ãµã³ãã«ã²ãŒã ã®ãããžã§ã¯ããã¡ã€ã«ã¯ãGitHubãªããžããª
ã«çœ®ããŠããã®ã§ããããã .zip ãã¡ã€ã«ãããŠã³ããŒãããŠããã ãããSampleããã©ã«ãå
ã®ãproject.godotããã¡ã€ã«ã Godot Engine ã§ã€ã³ããŒãããã°ç¢ºèªããŠããã ããã¯ãã ã
ãµã³ãã«ãããžã§ã¯ãã®ä»æ§ã¯ãããã以äžã®éãã ã
amount
ããããã£ãštrauma
ããããã£ãã²ãŒãžã§è¡šç€º- ããŒããŒãæäœã§äžäžå·Šå³ã«ç§»åã§ãããã£ã©ã¯ã¿ãŒãè¿œå
- D ããŒ: å³
- A ããŒ: å·Š
- W ããŒ: äž
- S ããŒ: äž
- ãã£ã©ã¯ã¿ãŒãèžãã ãç»é¢æºããçºçããè€æ°ã®ã¹ãã€ã¯ãå°é¢ã«è¿œå
trauma
ã«è¿œå ããå€ãäžç¢å°ããŒã§ 0.1 å¢å ãäžç¢å°ããŒã§ 0.1 æžå°ïŒæ倧 1.0ãæå° 0.0ïŒ- ãROUGHããšãSMOOTHãã®æºãã®çš®é¡ãå·Šäžã«è¡šç€º
- å·Šå³ç¢å°ããŒã§ãROUGHããšãSMOOTHãã®æºãã®çš®é¡ãåãæ¿ã
- ã¹ããŒã¹ããŒã§ãç»é¢æºããçºç
ãããã«
ä»åã¯2Dã§ã®ç»é¢æºãã®å®è£ ã«ã€ããŠçŽ¹ä»ãããã²ãŒã ã®ãžã£ã³ã«ãå Žé¢ã¯éžã¶ããç»é¢æºããé©çšã§ããæ©äŒã¯ãã£ãšå€ãã ããããŸããç»é¢æºããæ§æãããã©ã¡ãŒã¿ãã©ãå€åãããã°æºããã©ãå€ããã®ããç解ããã°ãå©çšç®çã«æé©ãªç»é¢æºããè¡šçŸããããšãã§ããã¯ãã ã
åè
- KENNEY - Assets
- Godot demo projects - OpenSimplexNoise
- KidsCanCode: SCREEN SHAKE
- YouTube: Math for Game Programmers: Juicing Your Cameras With Math
- YouTube: Godot Game Juice Tutorial 1: Camera Shake and Frame Freeze
- Coding Kaiju - Screen Shake in Godot: The Best Way
UPDATE:
2022/08/01 ã¿ã€ãä¿®æ£