Creating a 3D grid-based movement system with tank controls

Godot Version

4.3 `

Question

EDIT: I’ve managed to figure out one part of the problem, but am now stuck with a different one

Hello, I’ve been trying to the replicate a grid-based movement system from a game, and have been hitting a wall with it.

For some context, I’m trying to make a 3D dungeon crawler in the style of Brandish: The Dark Revenant, which worked with a grid that allowed the player to move in it The main point is that the player could rotate in place, changing the camera’s perspective and allowing the player to move around either forward, back, strafing left or strafing right

Here is what I mean
Brandish Movement

After checking a few tutorials and adjusting, I figured out how to allow the player to move in the four directions well enough, I didn’t fully figure out how to rotate the player 90 degrees and was trying to hammer that out when I ran into the main problem I’m facing: even if I turn the player and camera the correct angle, I need to figure out how to make the movement system also account for the player rotating around.

This is the code that I was using for movement when I hit this wall

extends CharacterBody3D

const tileSize = 1
var isMoving = false
var movDir

#Inputs
func _process(delta):
	movDir = Vector3.ZERO

	#Inputs directions, then performs the movement
	if Input.is_action_pressed("movR"):
		movDir.x += 1
		moveTile()
	if Input.is_action_pressed("movL"):
		movDir.x -= 1
		moveTile()
	if Input.is_action_pressed("movU"):
		movDir.z -= 1
		moveTile()
	if Input.is_action_pressed("movD"):
		movDir.z += 1
		moveTile()
	
	if Input.is_action_pressed("RotL"):
		rotDir += 1
		rotatePly()
	
	move_and_slide()


#Movement
func moveTile():
    if movDir:
        if  isMoving == false:
            isMoving = true
            var tween = create_tween()
            tween.tween_property(self,"position", position + movDir*tileSize, 0.5)
            tween.tween_callback(stopMove)
            
#This is here to make it so if the player stops holding the button in the 
#middle of moving to the next tile, they only stop once the movement is complete

func stopMove():
    isMoving = false

#Can only rotate one way, will fix once rotation isn't instant and angle is
#exactly 90 degrees
func rotatePly():
	if isMoving == false:
		isMoving = true
		rotation.y = rotDir*90
		stopMove()

I’m not quite sure if I need to change up things a lot or if I need to take a completely different approach to the problem, but I need help to figure it out in either case.

1 Like

Ok, I’ve managed to figure out one part of the problem, because I was looking at the problem the wrong way. Turns out I did need a different approach, because all it took was to make the movement relative to the camera. I took a look at a 3rd person platformer tutorial and used that to figure out how to make the grid movement work like that.

Now my current problem is the matter of rotation. I’m tweening the player’s rotation to spin the camera around 90 degrees with each push of the relevant buttons, but it’s only letting me do it in one direction once, and when I try to spin in the opposite direction it tweens 180 degrees instead of 90

Here is the relevant part of the code I’m using for it, I can post the full thing if need be.

@onready var spatialPos: Node3D = %Spatial

var rotDir

#Inputs
func _process(delta):
	
	if Input.is_action_pressed("RotL"):
		rotDir = Vector3(0,1,0)
		rotatePly()
	if Input.is_action_pressed("RotR"):
		rotDir = Vector3(0,-1,0)
		rotatePly()
		
	move_and_slide()


#Movement
func rotatePly():
	if rotDir:
		if isMoving == false:
			isMoving = true
			var tween = create_tween()
			tween.tween_property(spatialPos,"rotation_degrees", rotation + rotDir*90, 0.35)
			tween.tween_callback(stopMove)
	
#This is here to make it so if the player stops holding the button in the 
#middle of moving to the next tile or rotating, they only stop once the movement
#is complete

func stopMove():
	isMoving = false

I’m almost sure this can work out like this, but I’m not sure what’s the part where it goes wrong. If I need to use something other than a tween, I’d be open to it, as long as it can keep the part where the player isn’t allowed to move until after the rotation is complete