Topic was automatically imported from the old Question2Answer platform.
Asked By
PokeJosh
Old Version
Published before Godot 3 was released.
Hello friends!
My question is in two parts. Allow me to explain what I have so far, and the big picture.
I have attached a Camera2D of a certain size to a KineticBody2D that the user controls as the player. It is currently centered. The idea is to structure the world in a Zelda-like grid pattern, where the player can roam within one grid space until he reaches the edge, when the world will shift to the next grid space, and the player can continue seamlessly where he left off.
However, I would like the camera to be smaller than each grid space, so that the user cannot see the entire space on the grid all at once. When the player has moved so that an edge of the centered camera comes in contact with the edge of a grid space, the camera will stop moving even as the player approaches the edge of the space.
How can I create a grid with bounds that can affect the camera movement but Not the player movement?
How can I keep the camera centered on the player only when the conditions of the grid allow the camera to be centered?
I am still learning what functions that the godot 3.0 nodes are capable of, any assistance is greatly appreciated!
-PokeJosh
I know it’s a litle bit late. But I have done such a camera in one of my projects. If there is still need for it I can try to cleanup my code and post it here.
RoniPerson | 2021-01-03 14:09
I would love to learn how to do this! I had forgotten about this problem and was pleasantly surprised to see an email with a response, haha. I never did solve this issue.
This script is on a node 2D which has a camera 2d as child.
Each screen is a Node2D whith a tilemap. If you don’t use tilemaps you have to find another weay to get the size of the objects. The screens are added to the screen_objects array. Set your player as target and the script should work.
Note that there may be better ways performance wise as checking for a screen transition every frame.
extends Node2D
const CHANGE_TIME = 0.1 # active screen can not change faster as this (to prevent flickering)
var change_timer = 0
var screen_size
onready var cam = $Camera2D
var screens = []
export(Array) var screen_objects = []
export var active_screen = 0
export(NodePath) var target
# Called when the node enters the scene tree for the first time.
func _ready():
for screen_object in screen_objects:
var rects = []
var children = get_node(screen_object).get_children()
for child in children:
# this only works to get the size off the children when they are tilemaps
if child.has_method("get_used_rect"):
var t_rect = child.get_used_rect()
rects.append(Rect2(t_rect.position.x*8, t_rect.position.y*8, t_rect.size.x*8, t_rect.size.y*8))
if len(rects) > 0:
var f_rect = rects[0]
for i in range(1, rects.size()):
f_rect = f_rect.merge(rects[i])
screens.append(f_rect)
target = get_node(target)
screen_size = get_viewport_rect().size
func _process(delta):
change_timer -= delta
change_timer = 0 if change_timer < 0 else change_timer
if change_timer == 0:
screen_change()
# you can implement more advanced camera controlls here. Like smoothing or view direction. Important is to leave the clamp statements at the end.
cam.position = target.get_center()
var screen = screens[active_screen]
cam.position.x = clamp(cam.position.x, screen.position.x+screen_size.x/2, screen.position.x + screen.size.x-screen_size.x/2)
cam.position.y = clamp(cam.position.y, screen.position.y+screen_size.y/2, screen.position.y + screen.size.y-screen_size.y/2)
func screen_change():
var i = 0
for screen in screens:
if screen.has_point(target.get_center()):
if active_screen != i:
print("change (RoomController)")
active_screen = i
change_timer = CHANGE_TIME
break
i += 1