Python은 접근제어를 하기 위해서 키워드를 제공하지 않는 대신에 명명법(Naming)에 의한 방법으로 설정 가능.


<Public>

    • _(Single underscore)를 접두사로 사용하지 않음.(ex: name)
    • Python의 모든 속성 및 메소드는 기본적으로 public.
    • 외부 클래스에서 접근 가능.

<Protected>

    • _를 접두사로 사용. (ex: _name)
    • 해당 및 하위 클래스에서만 접근 가능.

<Private>

    • __(Double underscore)를 접두사로 사용.(ex: __name)
    • 해당 클래스 이외에는 접근 불가능.(단, Property Get, Set을 이용하면 접근가능)

※Protected와 Private에서 _를 접미사로 사용할 경우, 한개는 허용하지만, 두개 이상이면 Public으로 간주함.

    • _name_은 Protected, _name__은 Public으로 간주.


extends Spatial

var camera_distance = 2

func _ready():
	set_process(true)

	$Spatial/Spatial/Camera.translation = camera_distance * Vector3(0, 5, 5)
	$Spatial/Spatial/Camera.rotation_degrees = Vector3(-35, 0, 0)
	
func _process(delta):
	# Left & Right Rotation
	if Input.is_key_pressed(KEY_Q):
		$Spatial.rotate_y(5 * delta)
	elif Input.is_key_pressed(KEY_E):
		$Spatial.rotate_y(-5 * delta)

	# Up & Down Rotation
	if Input.is_key_pressed(KEY_W):
		$Spatial/Spatial.rotate_x(5 * delta)
	elif Input.is_key_pressed(KEY_S):
		$Spatial/Spatial.rotate_x(-5 * delta)

	# Zoomin & Zoomout
	if Input.is_key_pressed(KEY_EQUAL):
		$Spatial.set_scale($Spatial.get_scale() - Vector3(0.8, 0.8, 0.8) * delta)
	elif Input.is_key_pressed(KEY_MINUS):
		$Spatial.set_scale($Spatial.get_scale() + Vector3(0.8, 0.8, 0.8) * delta)

 

<참고>
http://www.bitoutsidethebox.com/godot-tutorial-5-2-axis-gimbal-camera-for-3d-games/

extends Node
...
signal my_signal


func _ready():
    connect("my_signal", self, "signal_handler")
    ...
    var otherNode = get_node("someNode")
    otherNode.connect("my_signal", self, "signal_handler")

func SomeFunc():
    ...
    # causes self.signal_handler() to be called
    emit_signal("my_signal")
    ...

func signal_handler():
    ...

 

[참고] https://godotengine.org/qa/3218/how-to-create-a-custom-signal-in-gdscript

Scene 편집 도구를 이용해도 되지만, GD Script만으로 코딩을 하고 싶을 경우(?)에는 아래 예제를 참고하여 작성하면 된다.

extends Node

func _ready():
	
	var timer = Timer.new()
	add_child(timer)

	timer.connect("timeout", self, "_on_timeout")

	timer.set_wait_time(10)
	timer.start()
	
func _on_timeout():
	
	print("Time out!")

 

[참고] http://docs.godotengine.org/en/3.0/classes/class_timer.html

RigidBody2D에서 총알(Bullet)을 발사하여 벽(Block)에 충돌하였을 경우, 충돌한 객체의 정보를 얻어내기 위해서는 func _ready() 안에 다음 code를 추가한다.

func _ready():
    set_contact_monitor(true)
    set_max_contacts_reported(5) # 0보다 큰 정수를 지정해주면 된다.

그다음 편집기에서 signals에서 함수를 연결하면 되지만, 직접 Gdscript에서 code를 추가하여보자. 그렇기 위해선 _ready() 함수 루틴에 다음과 같이 signal을 연결하는 code를 추가한다.

func _ready():
    set_contact_monitor(true)
    set_max_contacts_reported(5)
    connect("body_entered", self, "collision_detected")

그리고 collision_detected() 함수를 작성한다.

func collision_detected(obj):
    print(self.get_name(), " is colliding with ", obj.get_name())

더 자세한 정보를 얻고 싶을때는 get_colliding_bodies()를 이용하면 된다.

 

<참고>
 https://www.reddit.com/r/godot/comments/3ofhwj/how_can_i_use_body_enter_function/

일반적인 resource들은 load() 혹은 preload()를 이용하여 불러올 수 있다.

예)

var res1 = load("res://sample1.png")

var res2 = preload("res://sample2.png")

 

scene을 불러올 때는 PackedScene.instance()를 이용하면 된다.

예)

var bullet = preload("res://bullet.tscn").instance()

add_child(bullet)

인스턴스(혹은 노드)를 생성할 때 관리를 위해서 그룹화를 하는 경우가 생기는데, 그러한 경우 그룹 안에 몇개의 인스턴스가 생성되어 있는지 확인하고자 할 경우 다음과 같이 하면 된다.

 

get_tree().get_nodes_in_group("그룹명").size()

 

보다 자세한 것은 SceneTree.get_nodes_in_group을 참조하면 된다.

<조건>

-CA(Cellular Automata)를 이용하여 동굴형태의 던전맵을 생성.

-0세대(랜덤생성맵) Wall의 생성 비율은 45%, 5세대까지 Loop.

-경계면도 Rule 적용.

-Rule은 B5678/S45678

-Moore neighborhood 검색방식.

 

<결과 예제: 40x20 크기로 5세대까지 Loop>

 

<소스코드>

# -*- coding: utf-8 -*-
#
#	cave_map_generator.py
#
#	http://codememo.tistory.com
#
#	# - Wall / Space - Empty, CA Rule - B5678/S45678
#

import sys
import os
import random

class Map:
	
	wall_ratio = 45
	
	def __init__(self, column, row):
		self.column, self.row = column, row
		self.wall, self.empty = 0, 0
		self.map = [["#"] * self.row for m in range(self.column)]
		self.new_map = [["#"] * self.row for m in range(self.column)]

		for column in range(self.column):
			for row in range(self.row):
				if (0< row < self.row - 1) and (0 < column < self.column - 1):
					if (random.random() * 100) < self.wall_ratio:
						self.map[column][row] = "#"
					else:
						self.map[column][row] = " "
					
					self.new_map[column][row] = " "
		
		print("0 Generation")
		self.result()
		
	def generate(self, count):
		for i in range(1, count + 1):
			for column in range(1, self.column - 1):
				for row in range(1, self.row -1):
					self.check(column, row)

			print("%d Generation" % (i))
			self.map = self.new_map
			self.result()
			
			self.new_map = [["#"] * self.row for m in range(self.column)]

			for m in range(1, self.column - 1):
				for n in range(1, self.row - 1):
					self.new_map[m][n] = " "

	def check(self, column, row):

		neighborhood_empty, neighborhood_wall = 0, 0
		
		for m in range(-1, 2):
			for n in range(-1, 2):
				if m != 0 or n != 0:
					if self.map[column + m][row + n] == "#":
						neighborhood_wall += 1
					elif self.map[column + m][row + n] == " ":
						neighborhood_empty += 1					

		if ((self.map[column][row] == "#" and neighborhood_wall >= 4) or
				(self.map[column][row] == " " and neighborhood_wall >= 5)):
			self.new_map[column][row] = "#"
		else:
			self.new_map[column][row] = " "

	def result(self):
		dungeon = ""
		self.wall, self.empty = 0, 0
		
		for column in range(self.column):
			for row in range(self.row):
				dungeon += self.map[column][row]
				if self.map[column][row] == "#":
					self.wall += 1
				else:
					self.empty += 1
			
			if column < (self.column - 1):
				dungeon += "\n"
		
		print("Wall : %d Empty: %d" % (self.wall, self.empty))
		print(dungeon)

def main():
	map = Map(20, 40)
	map.generate(5)
	
	sys.exit()
	
if __name__ == "__main__":
	main()

 

<참고>

http://www.roguebasin.com/index.php?title=Cellular_Automata_Method_for_Generating_Random_Cave-Like_Levels

+ Recent posts