age-of-asparagus/godot3-3dgame

e06

Closed this issue · 5 comments

Allow Enemies and players to overlap

  • Name some layers: World, Player, Enemy
  • Put player on Player layer, Enemy on Enemy layer
  • Now it works, notice how they only come within 1 unit (explain this)
  • Test it (lots of enemies quickly).. now the enemies don't collide with each other (HAHAHHA cool...)
  • Mask enemies with each other (what to they recognize what to they see, what do they interact with)

Attacking

  • Add an AttackRadius as Area to enemy
  • Give it a Cylindrical CollisionShape radius about 1.5 size of enemy
  • Check if area entered
func _on_AttackRadius_body_entered(body):
#	print("Something Entered my attack radius: ", body)
  • Check for player and stop moving if attacking
func _physics_process(delta):
		
	if attacking:
		# attack
		print ("ATTACCCK!!!")
	else:
		if current_node < path.size():
			var direction: Vector3 = path[current_node] - global_transform.origin
			if direction.length() < 1:
				current_node += 1
			else:
				move_and_slide(direction.normalized() * speed)
# ...

func _on_AttackRadius_body_entered(body):
	if body == player:
                attacking = true
#		print("Something Entered my attack radius: ", body)
  • Add timer, AttackTimer (and to start moving again, Oneshot, 2 seconds
  • Rename the other timer to PathUpdateTimer (and rename _on_timer_timerout() edit the Signal connection)
  • Add reference to timer at top of script
  • Connect to timeout
func _on_AttackRadius_body_entered(body):
	if body == player:
		attacking = true
		attack_timer.start()
#		print("Something Entered my attack radius: ", body)


func _on_AttackTimer_timeout():
	attacking = false

Add the "Lunge"

First, need to consider "resting" state vs "attacking" state vs "returning" state....

var resting = false
var returning = false

State Machine?

enum state {
	ATTACKING,
	RETURNING, # after an attack
	RESTING,
	SEEKING,
}

var current_state= state.SEEKING

# ... 

func _physics_process(delta):
	
	match current_state
		state.SEEKING:
			if current_node < path.size():
				var direction: Vector3 = path[current_node] - global_transform.origin
				if direction.length() < 1:
					current_node += 1
				else:
					move_and_slide(direction.normalized() * speed)
		state.ATTACKING:
			print ("ATTACCCK!!!")
		state.RETURNING:
			pass
		state.RESTING:
			print("resting...")

Add attack motion

#...
		state.ATTACKING:
			# attack
			print ("ATTACCCK!!!")
			move_and_attack()
		state.RETURNING:
			print ("Heading back...")
		state.RESTING:
			print("resting...")

func update_path(target_position):
	path = nav.get_simple_path(global_transform.origin, target_position)
	
	
func move_and_attack():
		
	var attack_vector: Vector3 = (attack_target - global_transform.origin)
	var direction: Vector3 = attack_vector.normalized()
	var target_distance = attack_vector.length()
	
	print("I'm this far away from my target: ", target_distance)
	
	move_and_slide(direction * speed * attack_speed_multiplier)


....


func _on_AttackRadius_body_entered(body):
	if body == player:
		current_state = state.ATTACKING
		attack_target = player.global_transform.origin

  • Test... attacks the head?! Fix origin of Enemy to match height of Player
  • Test again... need to move the nave mesh up to match the player (try 0.75)
  • Check how close we are to our target ( distance of 1), and return
  • Rest after returning
func move_and_attack():
		
	var attack_vector: Vector3 = (attack_target - global_transform.origin)
	print(attack_vector)
	var direction: Vector3 = attack_vector.normalized()
	var target_distance: float = attack_vector.length()
	
	move_and_slide(direction * speed * attack_speed_multiplier)
	
	if target_distance < 1:
		
		match current_state:
			state.ATTACKING:
				current_state = state.RETURNING
				attack_target = return_position
				
			state.RETURNING:
				print("I'm back!")
				current_state = state.RESTING
				attack_timer.start()
		

func _on_Timer_timeout():
	print("Looking for Player!")
	update_path(player.global_transform.origin)
	current_node = 0


func _on_Stats_you_died_signal():
	queue_free()


func _on_AttackRadius_body_entered(body):
	if body == player:
		current_state = state.ATTACKING
		attack_target = player.global_transform.origin
		return_position = global_transform.origin
#		print("Something Entered my attack radius: ", body)


func _on_AttackTimer_timeout():
	print("I'm done resting now... where are you little bugger?")
	current_state = state.SEEKING

Change color when attacking

  • Save the base material as a resource... reorganize files in the FileSystem in Godot Editor so references are updated.
  • Create a new "Attacking" material (red?)
onready var mesh: MeshInstance = $MeshInstance

var default_material = load("res://Enemy/Enemy.tres")
var attack_material = load("res://Enemy/Enemy_Attack.tres")


func _ready():
	mesh.set_surface_material(0, default_material)
  • Delete starting material in the inspector to make sure its working
  • Change materials where needed:

			state.RETURNING:
				print("I'm back!")
				current_state = state.RESTING
				mesh.set_surface_material(0, default_material``)
				attack_timer.start()

# ...

func _on_AttackRadius_body_entered(body):
	if body == player:
		current_state = state.ATTACKING
		attack_target = player.global_transform.origin
		return_position = global_transform.origin
		mesh.set_surface_material(0, attack_material)

Allow overlap during attacks


		state.SEEKING:
			collide_with_other_enemies(true)
			move_and_slide(Vector3.ZERO)

....

func move_and_attack():
	collide_with_other_enemies(false)


... 
func collide_with_other_enemies(should_we_collide):
	set_collision_mask_bit(2, should_we_collide)
	set_collision_layer_bit(2, should_we_collide)