Major Frog AI improvments, Cam Fix

This commit is contained in:
Jakob Feldmann 2023-02-07 16:15:52 +01:00
parent b83804b0c3
commit 28fd3a9ba9
16 changed files with 221 additions and 419 deletions

View File

@ -44,13 +44,12 @@ func _physics_process(delta: float) -> void:
if(!GlobalState.is_dead): if(!GlobalState.is_dead):
var player_vel = (blobby.position - prev_pos)/delta var player_vel = (blobby.position - prev_pos)/delta
# TODO Take average of velocity here # TODO Take average of velocity here
if(abs(player_vel.x) >= blobby.max_velocity["walk"] * 0.97): if(abs(player_vel.x) >= blobby.max_velocity["walk"] * 0.97
&& (sign(player_vel.x) == sign(target_offset.x) || target_offset.x == 0)):
move_time += delta move_time += delta
slow_time = 0
elif(abs(player_vel.x) <= blobby.max_velocity["walk"] * 0.05 elif(abs(player_vel.x) <= blobby.max_velocity["walk"] * 0.05
|| sign(player_vel.x) != sign(target_offset.x) ): || sign(player_vel.x) != sign(target_offset.x) || target_offset.x == 0):
slow_time += delta slow_time += delta
move_time = 0
else: else:
move_time = max(0, move_time - delta) move_time = max(0, move_time - delta)
@ -100,6 +99,7 @@ func _adapt_to_movement(velocity: Vector2) -> void:
# TODO: Blobby can go off screen, when shifting camera at level edge and returning i # TODO: Blobby can go off screen, when shifting camera at level edge and returning i
# n the opposite direction slowly # n the opposite direction slowly
if(move_time >= offset_adapt_seconds && !anim_player.is_playing()): if(move_time >= offset_adapt_seconds && !anim_player.is_playing()):
move_time = 0
target_offset.x = camera_horizontal_shift * sign(velocity.x) target_offset.x = camera_horizontal_shift * sign(velocity.x)
if(offset == target_offset || if(offset == target_offset ||
left_edge_pos + target_offset.x - 24 < limit_left || left_edge_pos + target_offset.x - 24 < limit_left ||
@ -126,6 +126,7 @@ func _adapt_to_movement(velocity: Vector2) -> void:
shiftRight.track_set_key_value(limit_right_track, 1, new_limit_right) shiftRight.track_set_key_value(limit_right_track, 1, new_limit_right)
anim_player.play("shiftingRight") anim_player.play("shiftingRight")
elif(slow_time >= offset_reset_seconds): elif(slow_time >= offset_reset_seconds):
slow_time = 0
target_offset.x = 0 target_offset.x = 0
if(offset == target_offset): if(offset == target_offset):
return return

View File

@ -38,7 +38,7 @@
[ext_resource path="res://assets/environment/decor/screen/Screen1.png" type="Texture" id=36] [ext_resource path="res://assets/environment/decor/screen/Screen1.png" type="Texture" id=36]
[ext_resource path="res://assets/environment/decor/screen/Screen12.png" type="Texture" id=37] [ext_resource path="res://assets/environment/decor/screen/Screen12.png" type="Texture" id=37]
[ext_resource path="res://src/Environment/LightingShaderMaterial.tres" type="Material" id=38] [ext_resource path="res://src/Environment/LightingShaderMaterial.tres" type="Material" id=38]
[ext_resource path="res://src/Levels/Emitter.gd" type="Script" id=39] [ext_resource path="res://src/Actors/Emitter.gd" type="Script" id=39]
[ext_resource path="res://assets/blobby/idle/blobby1.png" type="Texture" id=40] [ext_resource path="res://assets/blobby/idle/blobby1.png" type="Texture" id=40]
[sub_resource type="Animation" id=5] [sub_resource type="Animation" id=5]
@ -378,7 +378,7 @@ tracks/0/imported = false
tracks/0/enabled = true tracks/0/enabled = true
tracks/0/keys = { tracks/0/keys = {
"times": PoolRealArray( 0, 0.6 ), "times": PoolRealArray( 0, 0.6 ),
"transitions": PoolRealArray( 1, 0.5 ), "transitions": PoolRealArray( 1, 1 ),
"update": 0, "update": 0,
"values": [ Vector2( 0, 0 ), Vector2( 0, 0 ) ] "values": [ Vector2( 0, 0 ), Vector2( 0, 0 ) ]
} }
@ -390,7 +390,7 @@ tracks/1/imported = false
tracks/1/enabled = true tracks/1/enabled = true
tracks/1/keys = { tracks/1/keys = {
"times": PoolRealArray( 0, 0.6 ), "times": PoolRealArray( 0, 0.6 ),
"transitions": PoolRealArray( 1, 0.8 ), "transitions": PoolRealArray( 1, 1 ),
"update": 0, "update": 0,
"values": [ -10000000, -10000000 ] "values": [ -10000000, -10000000 ]
} }
@ -406,7 +406,7 @@ tracks/0/imported = false
tracks/0/enabled = true tracks/0/enabled = true
tracks/0/keys = { tracks/0/keys = {
"times": PoolRealArray( 0, 0.6 ), "times": PoolRealArray( 0, 0.6 ),
"transitions": PoolRealArray( 1, 0.5 ), "transitions": PoolRealArray( 1, 1 ),
"update": 0, "update": 0,
"values": [ Vector2( 0, 0 ), Vector2( 0, 0 ) ] "values": [ Vector2( 0, 0 ), Vector2( 0, 0 ) ]
} }
@ -418,7 +418,7 @@ tracks/1/imported = false
tracks/1/enabled = true tracks/1/enabled = true
tracks/1/keys = { tracks/1/keys = {
"times": PoolRealArray( 0, 0.6 ), "times": PoolRealArray( 0, 0.6 ),
"transitions": PoolRealArray( 1, 0.8 ), "transitions": PoolRealArray( 1, 1 ),
"update": 0, "update": 0,
"values": [ 10000000, 10000000 ] "values": [ 10000000, 10000000 ]
} }
@ -532,7 +532,7 @@ drag_margin_v_enabled = true
drag_margin_left = 0.05 drag_margin_left = 0.05
drag_margin_top = 0.0 drag_margin_top = 0.0
drag_margin_right = 0.05 drag_margin_right = 0.05
drag_margin_bottom = 0.33 drag_margin_bottom = 0.01
editor_draw_drag_margin = true editor_draw_drag_margin = true
script = ExtResource( 1 ) script = ExtResource( 1 )
@ -632,10 +632,10 @@ texture = ExtResource( 8 )
[node name="AnimatedSprite" type="AnimatedSprite" parent="ParallaxBackground/ParallaxLayer5"] [node name="AnimatedSprite" type="AnimatedSprite" parent="ParallaxBackground/ParallaxLayer5"]
visible = false visible = false
frames = SubResource( 7 ) frames = SubResource( 7 )
frame = 5 frame = 6
playing = true playing = true
[node name="AnimatedSprite2" type="AnimatedSprite" parent="ParallaxBackground/ParallaxLayer5"] [node name="AnimatedSprite2" type="AnimatedSprite" parent="ParallaxBackground/ParallaxLayer5"]
frames = SubResource( 8 ) frames = SubResource( 8 )
frame = 10 frame = 11
playing = true playing = true

View File

@ -2,6 +2,7 @@ extends Node2D
# Is given in blocks # Is given in blocks
export var movement_radius = 6 export var movement_radius = 6
onready var tilemap: TileMap = $"%TileMap"
var Rope = preload("res://src/Contraptions/Rope/Rope.tscn") var Rope = preload("res://src/Contraptions/Rope/Rope.tscn")
var RopeAnchor = preload("res://src/Contraptions/Rope/RopeAnchor.tscn") var RopeAnchor = preload("res://src/Contraptions/Rope/RopeAnchor.tscn")
@ -18,7 +19,7 @@ func _on_LevelTemplate_ready() -> void:
rope.rope_end_joint = get_node("RopeAnchor/cshape/pjoint") rope.rope_end_joint = get_node("RopeAnchor/cshape/pjoint")
rope.rope_start_joint = get_node("WhatAreFrog/cshape/pjoint") rope.rope_start_joint = get_node("WhatAreFrog/cshape/pjoint")
rope.spawn_rope($WhatAreFrog.global_position, $RopeAnchor.global_position, movement_radius, false) rope.spawn_rope($WhatAreFrog.global_position, $RopeAnchor.global_position, movement_radius, false)
$WhatAreFrog.tilemap = tilemap
$WhatAreFrog.bind_to_anchor($RopeAnchor, movement_radius) $WhatAreFrog.bind_to_anchor($RopeAnchor, movement_radius)
# Executes on frog death # Executes on frog death

View File

@ -5,17 +5,28 @@ onready var players = get_tree().get_nodes_in_group("player")
onready var vision_raycast: RayCast2D = $VisionRayCast onready var vision_raycast: RayCast2D = $VisionRayCast
onready var orientation: RayCast2D = $Orientation onready var orientation: RayCast2D = $Orientation
onready var feeler_raycast: RayCast2D = $FeelerRayCast
onready var tilemap: TileMap = $"../%TileMap"
onready var jump_timer: Timer onready var jump_timer: Timer
onready var target_lost_timer: Timer onready var target_lost_timer: Timer
onready var rng = RandomNumberGenerator.new()
export var score := 100 export var score := 100
# Is given in blocks # Is given in blocks
export var vision_distance := 6.0 export var vision_distance := 6.0
# Jump distance in blocks
export var default_jump_distance := 3.0
export var default_jump_angle := 70.0
export var jump_time_search := 0.7
export var jump_time_hunt := 0.3
export var jump_time_standard_deviation := 0.1
# Also in blocks # Also in blocks
var movement_radius: float var movement_radius: float
var anchor: Node2D var anchor: Node2D
var is_bound := false var is_bound := false
var was_restricted := false
var has_reversed := false var has_reversed := false
var target: Object = null var target: Object = null
@ -29,11 +40,14 @@ var current_delta = 0.0
var reversing_possible_searching := true var reversing_possible_searching := true
# TODO Make parameters tunable!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!1111!!
func _ready(): func _ready():
default_jump_distance = default_jump_distance * tilemap.cell_size.x
jump_timer = Timer.new() jump_timer = Timer.new()
jump_timer.set_one_shot(true) jump_timer.set_one_shot(true)
jump_timer.connect("timeout", self, "jump") jump_timer.connect("timeout", self, "jump")
target_lost_timer = Timer.new() target_lost_timer = Timer.new()
target_lost_timer.set_one_shot(true)
target_lost_timer.connect("timeout", self, "lose_target") target_lost_timer.connect("timeout", self, "lose_target")
add_child(jump_timer) add_child(jump_timer)
add_child(target_lost_timer) add_child(target_lost_timer)
@ -60,8 +74,12 @@ func execute_movement(delta: float) -> void:
var next_position = global_position + velocity * current_delta var next_position = global_position + velocity * current_delta
var current_distance = global_position.distance_to(anchor.global_position) var current_distance = global_position.distance_to(anchor.global_position)
var new_distance = next_position.distance_to(anchor.global_position) var new_distance = next_position.distance_to(anchor.global_position)
# TODO Fix this in respects to x and y distances and movement dampening
# Maybe use mathemathematics or something idfc
if(current_distance >= movement_radius && new_distance > current_distance): if(current_distance >= movement_radius && new_distance > current_distance):
velocity.x = velocity.x * 0.8 velocity.x = velocity.x * 0.8
velocity.y = velocity.y * 0.8
was_restricted = true
velocity = move_and_slide(velocity, FLOOR_NORMAL, false, 4, 0.785398,false) velocity = move_and_slide(velocity, FLOOR_NORMAL, false, 4, 0.785398,false)
if(is_on_floor()): if(is_on_floor()):
velocity = Vector2(0,0) velocity = Vector2(0,0)
@ -84,10 +102,9 @@ func searching() -> Vector2:
if(is_on_floor()): if(is_on_floor()):
if(jump_timer.is_stopped()): if(jump_timer.is_stopped()):
jump_timer.start(rand_range(0.3,1.666)) jump_timer.start(rng.randfn(jump_time_search, jump_time_standard_deviation))
if(in_air): if(in_air):
in_air = false in_air = false
#print("Jump distance: ",global_position.x - start_x)
else: else:
if(!in_air): if(!in_air):
start_x = global_position.x start_x = global_position.x
@ -97,16 +114,15 @@ func searching() -> Vector2:
return velocity return velocity
func hunting() -> Vector2: func hunting() -> Vector2:
detect_player() detect_player()
if(is_on_floor()): if(is_on_floor()):
if(jump_timer.is_stopped()): if(jump_timer.is_stopped()):
#TODO Make normal distribution jump_timer.start(rng.randfn(jump_time_hunt, jump_time_standard_deviation))
jump_timer.start(rand_range(0.3,0.7))
if(in_air): if(in_air):
in_air = false in_air = false
#print("Jump distance: ",global_position.x - start_x)
else: else:
if(!in_air): if(!in_air):
start_x = global_position.x start_x = global_position.x
@ -116,6 +132,7 @@ func hunting() -> Vector2:
return velocity return velocity
func detect_player() -> void: func detect_player() -> void:
var player var player
if(players.empty()): if(players.empty()):
@ -124,6 +141,7 @@ func detect_player() -> void:
player = players[0] player = players[0]
vision_raycast.cast_to = (player.global_position - global_position).normalized() * 24 * vision_distance vision_raycast.cast_to = (player.global_position - global_position).normalized() * 24 * vision_distance
var ray_angle_to_facing = vision_raycast.cast_to.angle_to(orientation.cast_to) var ray_angle_to_facing = vision_raycast.cast_to.angle_to(orientation.cast_to)
vision_raycast.force_raycast_update()
var collider = vision_raycast.get_collider() var collider = vision_raycast.get_collider()
if(target == null && abs(ray_angle_to_facing) < PI/4 && collider != null && collider.is_in_group("player")): if(target == null && abs(ray_angle_to_facing) < PI/4 && collider != null && collider.is_in_group("player")):
target_lost_timer.stop() target_lost_timer.stop()
@ -145,40 +163,53 @@ func lose_target() -> void:
func jump(): func jump():
# Calculate jump velocity with distance and angle # print("jump calculation initiated")
# Check if is bound # Can only reverse once per jump calculation
# Reverse the calculated x velocity if rope is short or there is a wall
print("jump")
has_reversed = false has_reversed = false
var v: Vector2 = velocity_for_jump_distance(2 * 24, deg2rad(70)) var zero_vector = Vector2(0,0)
var v: Vector2 = velocity_for_jump_distance(default_jump_distance, deg2rad(default_jump_angle))
v = correct_jump_direction(v)
if(is_bound): if(is_bound):
var next_position = global_position + v * get_facing_direction() * current_delta var next_position = global_position + v * current_delta
var current_distance = global_position.distance_to(anchor.global_position) var current_distance = global_position.distance_to(anchor.global_position)
var new_distance = next_position.distance_to(anchor.global_position) var new_distance = next_position.distance_to(anchor.global_position)
#print(current_distance) print(current_distance)
#print(new_distance) print(new_distance)
if(new_distance >= movement_radius && new_distance > current_distance): if((new_distance >= movement_radius && new_distance > current_distance) || (new_distance > current_distance && was_restricted)):
if can_reverse_facing_direction(): if can_reverse_facing_direction():
reverse_facing_direction() reverse_facing_direction()
elif (($Left_Wallcast.is_colliding() || $Right_Wallcast.is_colliding()) && can_reverse_facing_direction()): was_restricted = false
reverse_facing_direction()
elif (($Left_Wallcast.is_colliding() || $Right_Wallcast.is_colliding()) && can_reverse_facing_direction()): if (get_facing_direction() < 0 && $Left_Wallcast.is_colliding()):
reverse_facing_direction() v = zero_vector
if (get_facing_direction() > 0 && $Right_Wallcast.is_colliding()):
v = zero_vector
if ($Right_Wallcast.is_colliding() && $Left_Wallcast.is_colliding()):
print("help this is a really tight space :(")
return velocity
v = correct_jump_direction(v) v = correct_jump_direction(v)
#TODO Consider distance to wall if(v != zero_vector):
# Will jump on top? If not, is spike under?
v = consider_jump_landing_space(v)
v = consider_jump_headspace(v) v = consider_jump_headspace(v)
#TODO Consider distance to wall, measure height of wall and seek angle for jumping on top if(v != zero_vector):
v = consider_jump_landing_space(v)
if(v == zero_vector):
# TODO fix that you could call jump from jumping on top
# and let it fail if the top is dangerous for jump height or not safe
v = consider_jumping_on_top()
if(v == zero_vector && can_reverse_facing_direction()):
reverse_facing_direction()
jump()
velocity = v velocity = v
func correct_jump_direction(v: Vector2) -> Vector2: func correct_jump_direction(v: Vector2) -> Vector2:
if sign(v.x) != get_facing_direction(): if sign(v.x) != get_facing_direction():
v.x *= -1 v.x *= -1
return v return v
# Cast a ray to the highest point of the jump # Cast a ray to the highest point of the jump
# Check the highest point for collision # Check the highest point for collision
# Calculate safe jump height and then a safe jump velocity # Calculate safe jump height and then a safe jump velocity
@ -186,46 +217,50 @@ func consider_jump_headspace(v: Vector2) -> Vector2:
var height = calculate_jump_height(v) var height = calculate_jump_height(v)
var distance = calculate_jump_distance(v) var distance = calculate_jump_distance(v)
# Half distance is an estimate of the jumps apex() # Half distance is an estimate of the jumps apex()
$CeilingRayCast.cast_to = Vector2(get_facing_direction()*(distance/2), - height) var height_collider = check_feeler(Vector2(get_facing_direction()*(distance/2), (-height)), Vector2(0,-9))
$CeilingRayCast.force_raycast_update()
var height_collider = $CeilingRayCast.get_collider()
if(height_collider != null): if(height_collider != null):
# check half jump height # check half jump height
var half_height_v = jump_height_to_velocity(height/2, v) var half_height_v = jump_height_to_velocity(height/3, v)
var half_height = calculate_jump_height(half_height_v) var half_height = calculate_jump_height(half_height_v)
$CeilingRayCast.cast_to = Vector2(get_facing_direction()*(distance/2), - half_height) height_collider = check_feeler(Vector2(get_facing_direction()*(distance/2), (-half_height)), Vector2(0,-9))
$CeilingRayCast.force_raycast_update()
height_collider = $CeilingRayCast.get_collider()
if(height_collider != null && can_reverse_facing_direction()): if(height_collider != null && can_reverse_facing_direction()):
print("no safe height for frog jump") print("no safe height for frog jump")
#TODO Consider jumping ontop of target
reverse_facing_direction()
return Vector2(0,0) return Vector2(0,0)
else: else:
var collision_point = $CeilingRayCast.get_collision_point() var collision_point = feeler_raycast.get_collision_point()
#TODO Consider sprite size for height #TODO Consider sprite size for height
var target_height = collision_point.y - $CeilingRayCast.global_position.y var target_height = collision_point.y - (feeler_raycast.global_position.y - 9)
v = jump_height_to_velocity(abs(target_height), v) v = jump_height_to_velocity(abs(target_height), v)
return v return v
# Check the block in jump distance for danger or height # Check the block in jump distance for danger or height
# If danger check neighboring blocks: if still danger, then jump closer (or jump over) # If danger check neighboring blocks: if still danger, then jump closer (or jump over)
# If height move to distance which allows 1 block high jump # If height move to distance which allows 1 block high jump
# TODO See if jump would land on ground before spike
func consider_jump_landing_space(v: Vector2) -> Vector2: func consider_jump_landing_space(v: Vector2) -> Vector2:
v = jump_to_tile_center(v) var jump_distance = calculate_jump_distance(v)
if(!is_jump_path_safe(v, global_position)): var jump_height = calculate_jump_height(v)
# print("would land in spikes") var collider = check_feeler(Vector2(jump_distance * get_facing_direction(), - jump_height/2))
v = jump_distance_to_velocity(calculate_jump_distance(v) - 24, v) # TODO Unpacked loop, make function or something?
# Shortens the jump in steps to make it more safe
if(!is_jump_path_safe(v, global_position) || collider != null):
jump_distance = calculate_jump_distance(v) - 24
v = change_jump_distance(jump_distance, v)
jump_height = calculate_jump_height(v)
v = correct_jump_direction(v) v = correct_jump_direction(v)
# print("next best distance") collider = check_feeler(Vector2(jump_distance * get_facing_direction(), - jump_height/2))
# print(calculate_jump_distance(v)) if(!is_jump_path_safe(v, global_position) || collider != null):
if(!is_jump_path_safe(v, global_position) && can_reverse_facing_direction()): jump_distance = calculate_jump_distance(v) - 12
print("cant jump over spikes") v = change_jump_distance(jump_distance, v)
reverse_facing_direction() jump_height = calculate_jump_height(v)
v = correct_jump_direction(v)
collider = check_feeler(Vector2(jump_distance * get_facing_direction(), - jump_height/2))
if((!is_jump_path_safe(v, global_position) || collider != null) && can_reverse_facing_direction()):
return Vector2(0,0) return Vector2(0,0)
return v return v
# Tries to shorten the jump, so that it lands in a tiles center
func jump_to_tile_center(v: Vector2) -> Vector2: func jump_to_tile_center(v: Vector2) -> Vector2:
var distance = stepify(calculate_jump_distance(v), 0.01) var distance = stepify(calculate_jump_distance(v), 0.01)
if !is_equal_approx(fmod(abs(global_position.x + distance * get_facing_direction()), 24), 12): if !is_equal_approx(fmod(abs(global_position.x + distance * get_facing_direction()), 24), 12):
@ -239,28 +274,32 @@ func jump_to_tile_center(v: Vector2) -> Vector2:
new_distance = distance + 12 - fmod((global_position.x + distance), 24) new_distance = distance + 12 - fmod((global_position.x + distance), 24)
print("centering distance") print("centering distance")
print(new_distance) print(new_distance)
v = jump_distance_to_velocity(abs(new_distance), v) v = change_jump_distance(abs(new_distance), v)
v = correct_jump_direction(v) v = correct_jump_direction(v)
return v return v
# TODO Depends on Frog Shape and Tile Shape
func is_jump_path_safe(v: Vector2, pos: Vector2) -> bool: func is_jump_path_safe(v: Vector2, pos: Vector2) -> bool:
var v0 = v.length() var v0 = v.length()
var angle = v.angle() var angle = v.angle()
var jump_distance = calculate_jump_distance(v) var jump_distance = calculate_jump_distance(v)
var harmful_nodes = get_tree().get_nodes_in_group("harmful") var harmful_nodes = get_tree().get_nodes_in_group("harmful")
# print("calculate landing spot safety")
for node in harmful_nodes: for node in harmful_nodes:
var node_pos = node.global_position var node_pos = node.global_position
if abs(node_pos.x - pos.x) > abs(jump_distance) * 3 || abs(node_pos.x - pos.x) < 1: if abs(node_pos.x - pos.x) > abs(jump_distance) * 3 || abs(node_pos.x - pos.x) < 1:
continue continue
var node_y = node_pos.y - 12 var node_y = node_pos.y - 12
var initial_throw_height = node_y - global_position.y - 9 var initial_throw_height = node_y - (global_position.y + 9)
var term1 = (pow(v0, 2) * sin(2 * angle)) / (2 * _gravity) var term1 = (pow(v0, 2) * sin(2 * angle)) / (2 * _gravity)
var term2 = ((v0 * cos(angle))/_gravity) * sqrt(pow(v0, 2) * pow(sin(angle), 2) + 2 * _gravity * initial_throw_height) var term2 = ((v0 * cos(angle))/_gravity) * sqrt(pow(v0, 2) * pow(sin(angle), 2) + 2 * _gravity * initial_throw_height)
var distance = abs(term1) + abs(term2) var distance = abs(term1) + abs(term2)
# print("distance to next spike") # print("distance to next spike")
# print(pos.x + sign(v.x) * distance - node_pos.x) # print(pos.x + sign(v.x) * distance - node_pos.x)
if(abs(pos.x + sign(v.x) * distance - node_pos.x) < 12): var safe_distance = 12
if (sign(initial_throw_height) < 0):
safe_distance = 24
if(abs(pos.x + sign(v.x) * distance - node_pos.x) < safe_distance):
return false return false
return true return true
@ -268,29 +307,88 @@ func is_jump_path_safe(v: Vector2, pos: Vector2) -> bool:
func calculate_jump_height(v: Vector2) -> float: func calculate_jump_height(v: Vector2) -> float:
return abs((pow(v.length(), 2) * pow(sin(v.angle()), 2))/(2*_gravity)) return abs((pow(v.length(), 2) * pow(sin(v.angle()), 2))/(2*_gravity))
func consider_jumping_on_top() -> Vector2:
var collider = check_feeler(Vector2(36 * get_facing_direction(),0))
var facing = 0 if get_facing_direction() >= 0 else - 1
if (collider == null):
return Vector2(0,0)
var local_position = tilemap.to_local(feeler_raycast.get_collision_point())
var map_position = tilemap.world_to_map(local_position)
var tile_position = Vector2(map_position.x + facing, map_position.y)
print(tile_position)
# TODO Here the climb height of frog is limited to one constantly
if (tilemap.get_cell(tile_position.x, tile_position.y - 1) != -1):
print("wall is more than one high")
return Vector2(0,0)
print("wall is only one high")
var tile_upper_left_corner = tilemap.to_global(tilemap.map_to_world(tile_position))
var tile_upper_right_corner = Vector2(tile_upper_left_corner.x + tilemap.cell_size.x, tile_upper_left_corner.y)
var jump_angle = 0
if(facing < 0):
var frog_bottom_left_corner = Vector2($EnemyBody.global_position.x - $EnemyBody.shape.extents.x,
$EnemyBody.global_position.y + $EnemyBody.shape.extents.y)
jump_angle = frog_bottom_left_corner.angle_to_point(tile_upper_right_corner)
else:
var frog_bottom_right_corner = Vector2($EnemyBody.global_position.x + $EnemyBody.shape.extents.x,
$EnemyBody.global_position.y + $EnemyBody.shape.extents.y)
jump_angle = frog_bottom_right_corner.angle_to_point(tile_upper_left_corner) - PI
print(rad2deg(jump_angle))
# if(abs(rad2deg(jump_angle)) < default_jump_angle):
# return correct_jump_direction(velocity_for_jump_distance(default_jump_distance/2, abs(deg2rad(default_jump_angle))))
if(abs(rad2deg(jump_angle)) < 78):
return correct_jump_direction(velocity_for_jump_distance(default_jump_distance/2, abs(deg2rad(80))))
else:
return velocity_for_jump_distance(8, abs(deg2rad(45))) * -1 * facing
return Vector2(0,0)
# Check if there is another obstacle above the block or do a regular jump with adjusted parameters instead(for checking)
# Cast from bottom corner to upper tile corner
# Check the angle of the raycast
# Return small jump backwards if the angle is too steep
# Make the angle 1 deg steeper
# Return a jump along the angled raycast
# Only works for jumps on straight ground # Only works for jumps on straight ground
func calculate_jump_distance(v: Vector2) -> float: func calculate_jump_distance(v: Vector2) -> float:
return abs((pow(v.length(), 2) * sin(-1 * 2 * v.angle()))/(_gravity)) return abs((pow(v.length(), 2) * sin(-1 * 2 * v.angle()))/(_gravity))
func jump_height_to_velocity(target_height: float, v: Vector2) -> Vector2: func jump_height_to_velocity(target_height: float, v: Vector2) -> Vector2:
var initial_height = calculate_jump_height(v) var initial_height = calculate_jump_height(v)
return v.normalized() * sqrt(pow(v.length(),2)/(initial_height/target_height)) return v.normalized() * sqrt(pow(v.length(),2)/(initial_height/target_height))
#TODO Ähh Öhh das ist iwie doppelt ne
func jump_distance_to_velocity(target_distance: float, v: Vector2) -> Vector2: # Changes a Vector for a jump to the targeted distance, keeping the angle
func change_jump_distance(target_distance: float, v: Vector2) -> Vector2:
var initial_distance = calculate_jump_distance(v) var initial_distance = calculate_jump_distance(v)
return v.normalized() * sqrt(pow(v.length(),2)/(initial_distance/target_distance)) return v.normalized() * sqrt(pow(v.length(),2)/(initial_distance/target_distance))
# Takes an angle and a distance to calculate a jump launching at that angle and covering the distance
func velocity_for_jump_distance(distance: float = 3*24, angle: float = deg2rad(65)) -> Vector2: func velocity_for_jump_distance(distance: float = 3*24, angle: float = deg2rad(65)) -> Vector2:
var abs_velocity = sqrt((distance * _gravity)/sin(2*angle)) var abs_velocity = sqrt((distance * _gravity)/sin(2*angle))
return Vector2(abs_velocity,0).rotated(-1*angle) return Vector2(abs_velocity,0).rotated(-1*angle)
func can_reverse_facing_direction() -> bool: func can_reverse_facing_direction() -> bool:
if(is_on_floor() && !has_reversed): if(is_on_floor() && !has_reversed):
return true return true
return false return false
# Checks the feeler ray for collisions and returns collision or null
func check_feeler(v: Vector2, _offset = Vector2(0,0)) -> Object:
var prev_position = feeler_raycast.position
feeler_raycast.position += _offset
feeler_raycast.cast_to = v
feeler_raycast.force_raycast_update()
feeler_raycast.position = prev_position
return feeler_raycast.get_collider()
func reverse_facing_direction() -> void: func reverse_facing_direction() -> void:
has_reversed = true has_reversed = true
print("reversing direction") print("reversing direction")

View File

@ -49,8 +49,7 @@ rect = Rect2( -89, -10, 2, 20 )
process_parent = true process_parent = true
physics_process_parent = true physics_process_parent = true
[node name="CeilingRayCast" type="RayCast2D" parent="."] [node name="FeelerRayCast" type="RayCast2D" parent="."]
position = Vector2( 0, -9 )
enabled = true enabled = true
cast_to = Vector2( 0, -1 ) cast_to = Vector2( 0, -1 )
collision_mask = 56 collision_mask = 56

View File

@ -26,11 +26,8 @@ wait_time = 20.0
[node name="BlobbyCam" parent="." instance=ExtResource( 12 )] [node name="BlobbyCam" parent="." instance=ExtResource( 12 )]
[node name="AnimatedSprite" parent="BlobbyCam/ParallaxBackground/ParallaxLayer5" index="4"]
frame = 9
[node name="AnimatedSprite2" parent="BlobbyCam/ParallaxBackground/ParallaxLayer5" index="5"] [node name="AnimatedSprite2" parent="BlobbyCam/ParallaxBackground/ParallaxLayer5" index="5"]
frame = 4 frame = 12
[node name="Blobby" parent="." instance=ExtResource( 2 )] [node name="Blobby" parent="." instance=ExtResource( 2 )]
unique_name_in_owner = true unique_name_in_owner = true

View File

@ -80,10 +80,10 @@ wait_time = 20.0
[node name="BlobbyCam" parent="." instance=ExtResource( 12 )] [node name="BlobbyCam" parent="." instance=ExtResource( 12 )]
[node name="AnimatedSprite" parent="BlobbyCam/ParallaxBackground/ParallaxLayer5" index="4"] [node name="AnimatedSprite" parent="BlobbyCam/ParallaxBackground/ParallaxLayer5" index="4"]
frame = 10 frame = 0
[node name="AnimatedSprite2" parent="BlobbyCam/ParallaxBackground/ParallaxLayer5" index="5"] [node name="AnimatedSprite2" parent="BlobbyCam/ParallaxBackground/ParallaxLayer5" index="5"]
frame = 1 frame = 5
[node name="Blobby" parent="." instance=ExtResource( 2 )] [node name="Blobby" parent="." instance=ExtResource( 2 )]
unique_name_in_owner = true unique_name_in_owner = true

View File

@ -127,7 +127,7 @@ shape = SubResource( 3 )
position = Vector2( 0, 1.5 ) position = Vector2( 0, 1.5 )
z_index = -1 z_index = -1
frames = SubResource( 5 ) frames = SubResource( 5 )
frame = 9 frame = 21
playing = true playing = true
[node name="TileMap" type="TileMap" parent="."] [node name="TileMap" type="TileMap" parent="."]

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,82 +0,0 @@
[gd_scene load_steps=11 format=2]
[ext_resource path="res://src/Actors/Blobby/Blobby.tscn" type="PackedScene" id=1]
[ext_resource path="res://assets/environment/blocks/Basic stone block.png" type="Texture" id=2]
[ext_resource path="res://src/Contraptions/Platform/SpringPlatform.tscn" type="PackedScene" id=3]
[ext_resource path="res://src/Environment/Background.tscn" type="PackedScene" id=4]
[ext_resource path="res://src/Contraptions/Platform/FlyingPlatform.tscn" type="PackedScene" id=5]
[ext_resource path="res://src/UserInterface/UserInterface.tscn" type="PackedScene" id=7]
[sub_resource type="NavigationPolygon" id=1]
vertices = PoolVector2Array( 16, 16, 0, 16, 0, 0, 16, 0 )
polygons = [ PoolIntArray( 0, 1, 2, 3 ) ]
[sub_resource type="OccluderPolygon2D" id=2]
polygon = PoolVector2Array( 16, 16, 0, 16, 0, 0, 16, 0 )
[sub_resource type="ConvexPolygonShape2D" id=3]
points = PoolVector2Array( 16, 16, 0, 16, 0, 0, 16, 0 )
[sub_resource type="TileSet" id=4]
0/name = "Basic stone block.png 0"
0/texture = ExtResource( 2 )
0/tex_offset = Vector2( 0, 0 )
0/modulate = Color( 1, 1, 1, 1 )
0/region = Rect2( 0, 0, 16, 16 )
0/tile_mode = 0
0/occluder_offset = Vector2( 0, 0 )
0/occluder = SubResource( 2 )
0/navigation_offset = Vector2( 0, 0 )
0/navigation = SubResource( 1 )
0/shape_offset = Vector2( 0, 0 )
0/shape_transform = Transform2D( 1, 0, 0, 1, 0, 0 )
0/shape = SubResource( 3 )
0/shape_one_way = false
0/shape_one_way_margin = 1.0
0/shapes = [ {
"autotile_coord": Vector2( 0, 0 ),
"one_way": false,
"one_way_margin": 1.0,
"shape": SubResource( 3 ),
"shape_transform": Transform2D( 1, 0, 0, 1, 0, 0 )
} ]
0/z_index = 0
[node name="PlattformsLevel" type="Node2D"]
__meta__ = {
"_edit_horizontal_guides_": [ 464.0 ],
"_edit_vertical_guides_": [ 2880.0 ]
}
[node name="UserInterface" parent="." instance=ExtResource( 7 )]
[node name="Simple Background" parent="." instance=ExtResource( 4 )]
layer = -1
[node name="TileMap" type="TileMap" parent="."]
tile_set = SubResource( 4 )
cell_size = Vector2( 16, 16 )
cell_quadrant_size = 32
cell_custom_transform = Transform2D( 16, 0, 0, 16, 0, 0 )
collision_layer = 8
collision_mask = 2147483648
format = 1
tile_data = PoolIntArray( 1900544, 0, 0, 1900545, 0, 0, 1900546, 0, 0, 1900547, 0, 0, 1900548, 0, 0, 1900549, 0, 0, 1900550, 0, 0, 1900551, 0, 0, 1900552, 0, 0, 1900553, 0, 0, 1900554, 0, 0, 1900555, 0, 0, 1900556, 0, 0, 1900557, 0, 0, 1900558, 0, 0, 1900559, 0, 0, 1900560, 0, 0, 1900561, 0, 0, 1900562, 0, 0, 1900563, 0, 0, 1900564, 0, 0, 1900565, 0, 0, 1900566, 0, 0, 1900567, 0, 0, 1900568, 0, 0, 1900569, 0, 0, 1966080, 0, 0, 1966105, 0, 0, 2031616, 0, 0, 2031641, 0, 0, 2097152, 0, 0, 2097177, 0, 0, 2162688, 0, 0, 2162713, 0, 0, 2228224, 0, 0, 2228249, 0, 0, 2293760, 0, 0, 2293785, 0, 0, 2359296, 0, 0, 2359321, 0, 0, 2424832, 0, 0, 2424857, 0, 0, 2490368, 0, 0, 2490393, 0, 0, 2555904, 0, 0, 2555905, 0, 0, 2555906, 0, 0, 2555907, 0, 0, 2555908, 0, 0, 2555909, 0, 0, 2555910, 0, 0, 2555911, 0, 0, 2555912, 0, 0, 2555913, 0, 0, 2555914, 0, 0, 2555915, 0, 0, 2555916, 0, 0, 2555917, 0, 0, 2555918, 0, 0, 2555919, 0, 0, 2555920, 0, 0, 2555921, 0, 0, 2555922, 0, 0, 2555923, 0, 0, 2555924, 0, 0, 2555925, 0, 0, 2555926, 0, 0, 2555927, 0, 0, 2555928, 0, 0, 2555929, 0, 0 )
[node name="Blobby" parent="." instance=ExtResource( 1 )]
position = Vector2( 50.7867, 604.063 )
[node name="Track" parent="." instance=ExtResource( 5 )]
position = Vector2( 34.7867, 501.525 )
scale = Vector2( 2.83999, 0.56 )
[node name="KinematicBody2D" parent="Track" index="0"]
position = Vector2( 25.0812, 0 )
[node name="CollisionShape2D" parent="Track/KinematicBody2D" index="1"]
position = Vector2( -0.00534821, 0.0656128 )
[node name="Spring" parent="." instance=ExtResource( 3 )]
position = Vector2( 170, 603.063 )
[editable path="Track"]

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,34 +0,0 @@
extends Node2D
var Rope = preload("res://src/Contraptions/Rope/Rope.tscn")
var start_pos := Vector2.ZERO
var end_pos := Vector2.ZERO
onready var rope: Node2D = null
func _ready() -> void:
pass
# rope = Rope.instance()
# add_child(rope)
# rope.rope_start = get_node("BoundFrog/RopeAnchor")
# rope.rope_end = get_node("BoundFrog/WhatAreFrog")
# rope.rope_start_joint = get_node("BoundFrog/RopeAnchor/cshape/pjoint")
# rope.rope_end_joint = get_node("BoundFrog/WhatAreFrog/cshape/pjoint")
# rope.spawn_rope($BoundFrog/RopeAnchor.global_position, $BoundFrog.global_position, false)
# func _input(event):
# if event is InputEventMouseButton && !event.is_pressed():
# if start_pos == Vector2.ZERO:
# start_pos = get_global_mouse_position()
# elif end_pos == Vector2.ZERO:
# end_pos = get_global_mouse_position()
# rope = Rope.instance()
# add_child(rope)
# rope.spawn_rope(start_pos, end_pos)
# start_pos = Vector2.ZERO
# end_pos = Vector2.ZERO
# if rope != null && event.is_action_pressed("click"):
# rope.mouse_follow = true
# if event.is_action_released("click"):
# if rope != null:
# rope.mouse_follow = false

View File

@ -48,5 +48,5 @@ animations = [ {
[node name="AnimatedSprite" type="AnimatedSprite" parent="."] [node name="AnimatedSprite" type="AnimatedSprite" parent="."]
frames = SubResource( 1 ) frames = SubResource( 1 )
frame = 22 frame = 28
playing = true playing = true