mirror of
https://github.com/JHDev2006/Super-Mario-Bros.-Remastered-Public.git
synced 2025-10-22 23:48:11 +00:00
added the game
This commit is contained in:
35
Scripts/Classes/Entities/Objects/BobOmbHeld.gd
Normal file
35
Scripts/Classes/Entities/Objects/BobOmbHeld.gd
Normal file
@@ -0,0 +1,35 @@
|
||||
extends Enemy
|
||||
const EXPLOSION = preload("uid://clbvyne1cr8gp")
|
||||
@export var timer := 5.0
|
||||
|
||||
var can_move := true
|
||||
|
||||
func _ready() -> void:
|
||||
$Movement.auto_call = can_move
|
||||
|
||||
func _physics_process(delta: float) -> void:
|
||||
timer -= delta
|
||||
if timer <= 2.0:
|
||||
%FlashAnimation.play("Flash")
|
||||
if timer <= 0:
|
||||
explode()
|
||||
timer = 99
|
||||
%Sprite.scale.x = direction
|
||||
|
||||
func explode() -> void:
|
||||
$AnimationPlayer.play("Explode")
|
||||
await $AnimationPlayer.animation_finished
|
||||
summon_explosion()
|
||||
queue_free()
|
||||
|
||||
func kick(object: Node2D) -> void:
|
||||
AudioManager.play_sfx("kick", global_position)
|
||||
var kick_dir = sign(global_position.x - object.global_position.x)
|
||||
velocity.x = 150 * kick_dir
|
||||
direction = kick_dir
|
||||
velocity.y = -100
|
||||
|
||||
func summon_explosion() -> void:
|
||||
var node = EXPLOSION.instantiate()
|
||||
node.global_position = global_position + Vector2(0, -8)
|
||||
add_sibling(node)
|
1
Scripts/Classes/Entities/Objects/BobOmbHeld.gd.uid
Executable file
1
Scripts/Classes/Entities/Objects/BobOmbHeld.gd.uid
Executable file
@@ -0,0 +1 @@
|
||||
uid://baie518kyfenr
|
38
Scripts/Classes/Entities/Objects/Bumper.gd
Normal file
38
Scripts/Classes/Entities/Objects/Bumper.gd
Normal file
@@ -0,0 +1,38 @@
|
||||
extends Node2D
|
||||
|
||||
const LOW_STRENGTH := -300
|
||||
const HIGH_STRENGTH := -450
|
||||
|
||||
func bounce_player(player: Player) -> void:
|
||||
$Sprite.play("Bounce")
|
||||
$AnimationPlayer.stop()
|
||||
if player.global_position.y + 8 < global_position.y:
|
||||
player.velocity.x *= 0.8
|
||||
if Global.player_action_pressed("jump", player.player_id):
|
||||
player.gravity = player.JUMP_GRAVITY
|
||||
player.jump_cancelled = false
|
||||
player.velocity.y = HIGH_STRENGTH
|
||||
player.has_jumped = true
|
||||
AudioManager.play_sfx("bumper_high", global_position)
|
||||
else:
|
||||
AudioManager.play_sfx("bumper", global_position)
|
||||
player.velocity.y = LOW_STRENGTH
|
||||
else:
|
||||
player.velocity = global_position.direction_to(player.global_position) * 200
|
||||
if Global.player_action_pressed("jump", player.player_id):
|
||||
player.gravity = player.JUMP_GRAVITY
|
||||
player.velocity.y = LOW_STRENGTH
|
||||
player.has_jumped = true
|
||||
AudioManager.play_sfx("bumper_high", global_position)
|
||||
else:
|
||||
AudioManager.play_sfx("bumper", global_position)
|
||||
refresh_hitbox()
|
||||
$AnimationPlayer.play("Bounce")
|
||||
await $AnimationPlayer.animation_finished
|
||||
$Sprite.play("Idle")
|
||||
|
||||
func refresh_hitbox() -> void:
|
||||
$Hitbox/CollisionShape2D.set_deferred("disabled", true)
|
||||
await get_tree().physics_frame
|
||||
$Hitbox/CollisionShape2D.set_deferred("disabled", false)
|
||||
|
1
Scripts/Classes/Entities/Objects/Bumper.gd.uid
Normal file
1
Scripts/Classes/Entities/Objects/Bumper.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://biu4x75tbkfk3
|
29
Scripts/Classes/Entities/Objects/Burner.gd
Normal file
29
Scripts/Classes/Entities/Objects/Burner.gd
Normal file
@@ -0,0 +1,29 @@
|
||||
extends AnimatableBody2D
|
||||
|
||||
@export_enum("Up", "Down", "Left", "Right") var direction := 0
|
||||
|
||||
func _ready() -> void:
|
||||
$Timer.start()
|
||||
|
||||
func do_cycle() -> void:
|
||||
if BooRaceHandler.countdown_active == false:
|
||||
AudioManager.play_sfx("burner", global_position)
|
||||
do_animation()
|
||||
await get_tree().create_timer(0.25, false).timeout
|
||||
%Hitbox.set_deferred("disabled", false)
|
||||
await get_tree().create_timer(1.5, false).timeout
|
||||
%Hitbox.set_deferred("disabled", true)
|
||||
$Timer.start()
|
||||
|
||||
func do_animation() -> void:
|
||||
%Flame.show()
|
||||
%Flame.play("Rise")
|
||||
await %Flame.animation_finished
|
||||
%Flame.play("Loop")
|
||||
await get_tree().create_timer(1, false).timeout
|
||||
%Flame.play("Fall")
|
||||
await %Flame.animation_finished
|
||||
%Flame.hide()
|
||||
|
||||
func damage_player(player: Player) -> void:
|
||||
player.damage()
|
1
Scripts/Classes/Entities/Objects/Burner.gd.uid
Normal file
1
Scripts/Classes/Entities/Objects/Burner.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://clareynx710qb
|
28
Scripts/Classes/Entities/Objects/Cannon.gd
Normal file
28
Scripts/Classes/Entities/Objects/Cannon.gd
Normal file
@@ -0,0 +1,28 @@
|
||||
extends Node2D
|
||||
|
||||
@export var item: PackedScene = preload("uid://bumvqjhs2xxka")
|
||||
|
||||
@export_range(0, 8, 1) var head_angle := 0
|
||||
@export_range(0, 4, 1) var stand_angle := 0
|
||||
|
||||
var amount := 0
|
||||
|
||||
func _ready() -> void:
|
||||
$Timer.start()
|
||||
|
||||
func shoot() -> void:
|
||||
if amount >= 3 or $Head/Raycast.is_colliding():
|
||||
return
|
||||
var node = item.instantiate()
|
||||
var direction_vector = [Vector2.UP, Vector2(1, -1), Vector2.RIGHT, Vector2(1, 1), Vector2.DOWN, Vector2(-1, 1), Vector2.LEFT, Vector2(-1, -1), Vector2.UP][head_angle]
|
||||
node.set("direction_vector", direction_vector)
|
||||
node.set("velocity", 100 * direction_vector)
|
||||
if direction_vector.x != 0:
|
||||
node.set("direction", sign(direction_vector.x))
|
||||
node.global_position = global_position
|
||||
if item.resource_path != "res://Scenes/Prefabs/Entities/Objects/CannonBall.tscn":
|
||||
node.global_position += direction_vector * 4
|
||||
node.tree_exited.connect(func(): amount -= 1)
|
||||
amount += 1
|
||||
AudioManager.play_sfx("cannon", global_position)
|
||||
add_sibling(node)
|
1
Scripts/Classes/Entities/Objects/Cannon.gd.uid
Normal file
1
Scripts/Classes/Entities/Objects/Cannon.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://bxfr63s2j3ts7
|
30
Scripts/Classes/Entities/Objects/CheckpointFlag.gd
Normal file
30
Scripts/Classes/Entities/Objects/CheckpointFlag.gd
Normal file
@@ -0,0 +1,30 @@
|
||||
extends Node2D
|
||||
@onready var sprite: AnimatedSprite2D = $"../Sprite"
|
||||
@onready var activated: AnimatedSprite2D = $"../Activated"
|
||||
|
||||
static var character_save := "Mario"
|
||||
|
||||
func _ready() -> void:
|
||||
activated.get_node("ResourceSetterNew").resource_json = load(get_character_sprite_path(0))
|
||||
if Settings.file.difficulty.checkpoint_style == 0 and (Global.current_game_mode != Global.GameMode.LEVEL_EDITOR and Global.current_game_mode != Global.GameMode.CUSTOM_LEVEL) or Global.current_campaign == "SMBANN":
|
||||
owner.queue_free()
|
||||
return
|
||||
owner.show()
|
||||
if Checkpoint.passed:
|
||||
sprite.hide()
|
||||
activated.show()
|
||||
|
||||
func get_character_sprite_path(player_id := 0) -> String:
|
||||
var character = Player.CHARACTERS[int(Global.player_characters[player_id])]
|
||||
var path = "res://Assets/Sprites/Players/" + character + "/CheckpointFlag.json"
|
||||
if int(Global.player_characters[player_id]) > 3:
|
||||
path = path.replace("res://Assets/Sprites/Players", "user://custom_characters")
|
||||
return path
|
||||
|
||||
func activate(player: Player) -> void:
|
||||
character_save = player.character
|
||||
sprite.play("Hit")
|
||||
await get_tree().physics_frame
|
||||
await sprite.animation_finished
|
||||
sprite.hide()
|
||||
activated.show()
|
1
Scripts/Classes/Entities/Objects/CheckpointFlag.gd.uid
Executable file
1
Scripts/Classes/Entities/Objects/CheckpointFlag.gd.uid
Executable file
@@ -0,0 +1 @@
|
||||
uid://hk6ml16axmcc
|
18
Scripts/Classes/Entities/Objects/CloudPlatform.gd
Executable file
18
Scripts/Classes/Entities/Objects/CloudPlatform.gd
Executable file
@@ -0,0 +1,18 @@
|
||||
extends AnimatableBody2D
|
||||
|
||||
var active := false
|
||||
|
||||
@onready var starting_position := global_position
|
||||
|
||||
func _physics_process(delta: float) -> void:
|
||||
if active:
|
||||
global_position.x += 48 * delta
|
||||
|
||||
func on_player_entered(player: Player) -> void:
|
||||
if player.velocity.y > -player.FALL_GRAVITY:
|
||||
active = true
|
||||
|
||||
func reset() -> void:
|
||||
global_position = starting_position
|
||||
reset_physics_interpolation()
|
||||
active = false
|
1
Scripts/Classes/Entities/Objects/CloudPlatform.gd.uid
Executable file
1
Scripts/Classes/Entities/Objects/CloudPlatform.gd.uid
Executable file
@@ -0,0 +1 @@
|
||||
uid://bosxtidiegjv0
|
122
Scripts/Classes/Entities/Objects/Door.gd
Normal file
122
Scripts/Classes/Entities/Objects/Door.gd
Normal file
@@ -0,0 +1,122 @@
|
||||
class_name Door
|
||||
extends Node2D
|
||||
|
||||
@export_range(0, 99) var door_id := 0
|
||||
|
||||
@export_enum("0", "1", "2", "3", "4") var sublevel_id := 0
|
||||
|
||||
@export var locked := false
|
||||
@export var start_locked := false
|
||||
|
||||
signal updated
|
||||
|
||||
static var exiting_door_id := -1
|
||||
|
||||
var can_enter := true
|
||||
|
||||
static var door_found := false
|
||||
|
||||
static var unlocked_doors := []
|
||||
|
||||
static var same_scene_exiting_door: Door = null
|
||||
|
||||
func _ready() -> void:
|
||||
if start_locked:
|
||||
locked = true
|
||||
if locked:
|
||||
check_if_unlocked(false)
|
||||
|
||||
func _physics_process(_delta: float) -> void:
|
||||
for i in $PlayerDetection.get_overlapping_areas():
|
||||
if i.owner is Player and can_enter:
|
||||
if Global.player_action_just_pressed("move_up", i.owner.player_id) and i.owner.is_on_floor():
|
||||
if locked:
|
||||
if KeyItem.total_collected > 0:
|
||||
unlock_door(i.owner)
|
||||
else:
|
||||
AudioManager.play_sfx("door_locked", global_position)
|
||||
$Sprite.play("Locked")
|
||||
$AnimationPlayer.play("Locked")
|
||||
else:
|
||||
player_enter(i.owner)
|
||||
|
||||
func check_if_unlocked(do_animation := true) -> void:
|
||||
if locked:
|
||||
if unlocked_doors.has(door_id):
|
||||
locked = false
|
||||
$Sprite.play("Idle")
|
||||
if do_animation:
|
||||
$AnimationPlayer.play("Unlock")
|
||||
|
||||
func run_door_check() -> void:
|
||||
if same_scene_exiting_door != null:
|
||||
if same_scene_exiting_door != self and exiting_door_id == door_id:
|
||||
door_found = true
|
||||
for i in get_tree().get_nodes_in_group("Players"):
|
||||
player_exit(i)
|
||||
return
|
||||
else:
|
||||
if exiting_door_id == door_id:
|
||||
door_found = true
|
||||
for i in get_tree().get_nodes_in_group("Players"):
|
||||
player_exit(i)
|
||||
return
|
||||
await get_tree().physics_frame
|
||||
if door_found == false:
|
||||
for i in get_tree().get_nodes_in_group("Players"):
|
||||
player_exit(i)
|
||||
|
||||
func unlock_door(player: Player) -> void:
|
||||
AudioManager.play_sfx("door_unlock", global_position)
|
||||
Global.p_switch_timer_paused = true
|
||||
KeyItem.total_collected -= 1
|
||||
freeze_player(player)
|
||||
$Sprite.play("Idle")
|
||||
unlocked_doors.append(door_id)
|
||||
get_tree().call_group("Doors", "check_if_unlocked", true)
|
||||
$AnimationPlayer.play("Unlock")
|
||||
await get_tree().create_timer(0.5, false).timeout
|
||||
player_enter(player)
|
||||
|
||||
func player_exit(player: Player) -> void:
|
||||
exiting_door_id = -1
|
||||
can_enter = false
|
||||
LevelEditor.play_door_transition = false
|
||||
same_scene_exiting_door = null
|
||||
player.global_position = global_position
|
||||
player.recenter_camera()
|
||||
$Sprite.play("Close")
|
||||
await get_tree().create_timer(0.2, false).timeout
|
||||
$Sprite.play("Close")
|
||||
player.state_machine.transition_to("Normal")
|
||||
AudioManager.play_sfx("door_close", global_position)
|
||||
can_enter = true
|
||||
Global.p_switch_timer_paused = false
|
||||
|
||||
func player_enter(player: Player) -> void:
|
||||
Global.p_switch_timer_paused = true
|
||||
can_enter = false
|
||||
door_found = false
|
||||
exiting_door_id = door_id
|
||||
freeze_player(player)
|
||||
$Sprite.play("Open")
|
||||
LevelEditor.play_door_transition = true
|
||||
AudioManager.play_sfx("door_open", global_position)
|
||||
await get_tree().create_timer(0.5, false).timeout
|
||||
if Global.level_editor.sub_level_id == sublevel_id:
|
||||
Global.do_fake_transition()
|
||||
if Global.fade_transition:
|
||||
await get_tree().create_timer(0.25, false).timeout
|
||||
same_scene_exiting_door = self
|
||||
for i in get_tree().get_nodes_in_group("Doors"):
|
||||
i.run_door_check()
|
||||
else:
|
||||
same_scene_exiting_door = null
|
||||
Global.level_editor.transition_to_sublevel(sublevel_id)
|
||||
$Sprite.play("Idle")
|
||||
can_enter = true
|
||||
|
||||
func freeze_player(player: Player) -> void:
|
||||
player.state_machine.transition_to("Freeze")
|
||||
player.sprite.play("Idle")
|
||||
player.velocity = Vector2.ZERO
|
1
Scripts/Classes/Entities/Objects/Door.gd.uid
Normal file
1
Scripts/Classes/Entities/Objects/Door.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://cy8cncadvevvt
|
5
Scripts/Classes/Entities/Objects/EditorLinkedElevator.gd
Normal file
5
Scripts/Classes/Entities/Objects/EditorLinkedElevator.gd
Normal file
@@ -0,0 +1,5 @@
|
||||
extends Node2D
|
||||
|
||||
@export_range(1, 8) var width := 1
|
||||
@export_range(1, 8) var left_height := 1
|
||||
@export_range(1, 8) var right_height := 2
|
@@ -0,0 +1 @@
|
||||
uid://duxduhxe8vqdo
|
9
Scripts/Classes/Entities/Objects/ElevatorPlatform.gd
Executable file
9
Scripts/Classes/Entities/Objects/ElevatorPlatform.gd
Executable file
@@ -0,0 +1,9 @@
|
||||
extends StaticBody2D
|
||||
|
||||
@export var vertical_direction := 1
|
||||
const MOVE_SPEED := 50
|
||||
@export var top := -244
|
||||
|
||||
func _physics_process(delta: float) -> void:
|
||||
global_position.y += (MOVE_SPEED * delta) * vertical_direction
|
||||
global_position.y = wrap(global_position.y, top, 64)
|
1
Scripts/Classes/Entities/Objects/ElevatorPlatform.gd.uid
Executable file
1
Scripts/Classes/Entities/Objects/ElevatorPlatform.gd.uid
Executable file
@@ -0,0 +1 @@
|
||||
uid://bosinwppqswdr
|
18
Scripts/Classes/Entities/Objects/Explosion.gd
Executable file
18
Scripts/Classes/Entities/Objects/Explosion.gd
Executable file
@@ -0,0 +1,18 @@
|
||||
class_name Explosion
|
||||
extends Node2D
|
||||
|
||||
const destructable_tiles := {Vector2i(4, 0): Rect2(32, 160, 16, 16), Vector2i(4, 2): Rect2(48, 160, 16, 16)}
|
||||
const BLOCK_DESTRUCTION_PARTICLES = preload("uid://cyw7kk1em8h16")
|
||||
|
||||
|
||||
func on_body_entered(body: Node2D) -> void:
|
||||
if body is Block:
|
||||
if body.destructable: body.destroy()
|
||||
if body is Player:
|
||||
body.damage()
|
||||
|
||||
|
||||
|
||||
func on_area_entered(area: Area2D) -> void:
|
||||
if area.owner is Player:
|
||||
area.owner.damage()
|
1
Scripts/Classes/Entities/Objects/Explosion.gd.uid
Executable file
1
Scripts/Classes/Entities/Objects/Explosion.gd.uid
Executable file
@@ -0,0 +1 @@
|
||||
uid://ritdlvkpyjd4
|
10
Scripts/Classes/Entities/Objects/FallingPlatform.gd
Normal file
10
Scripts/Classes/Entities/Objects/FallingPlatform.gd
Normal file
@@ -0,0 +1,10 @@
|
||||
extends AnimatableBody2D
|
||||
|
||||
func _physics_process(delta: float) -> void:
|
||||
if $PlayerDetect.get_overlapping_areas().any(is_player):
|
||||
global_position.y += 96 * delta
|
||||
|
||||
func is_player(area: Area2D) -> bool:
|
||||
if area.owner is Player:
|
||||
return area.owner.is_on_floor() and area.owner.global_position.y - 4 <= global_position.y
|
||||
return false
|
1
Scripts/Classes/Entities/Objects/FallingPlatform.gd.uid
Executable file
1
Scripts/Classes/Entities/Objects/FallingPlatform.gd.uid
Executable file
@@ -0,0 +1 @@
|
||||
uid://c4m157i8p54cf
|
27
Scripts/Classes/Entities/Objects/OnOffFanRed.gd
Normal file
27
Scripts/Classes/Entities/Objects/OnOffFanRed.gd
Normal file
@@ -0,0 +1,27 @@
|
||||
extends AnimatableBody2D
|
||||
|
||||
@export var active := false
|
||||
@export_enum("Right", "Left", "Up", "Down") var direction := 0
|
||||
@export_range(1, 4, 1) var strength := 1
|
||||
|
||||
func on_switch_hit() -> void:
|
||||
active = not active
|
||||
|
||||
func _physics_process(_delta: float) -> void:
|
||||
$Particles.amount = strength * 2
|
||||
$Particles.speed_scale = strength / 2.0
|
||||
$Sprite.speed_scale = strength / 2.0
|
||||
if active:
|
||||
for i in $Hitbox.get_overlapping_areas():
|
||||
if i.owner is CharacterBody2D:
|
||||
var wind_velocity = Vector2.RIGHT.rotated(global_rotation) * (strength * 2)
|
||||
var modifier = Vector2.ONE
|
||||
if i.owner is Player:
|
||||
if Global.player_action_pressed("jump", i.owner.player_id):
|
||||
modifier.y = 2
|
||||
if Global.player_action_pressed("move_down", i.owner.player_id):
|
||||
modifier.y = 0.5
|
||||
var distance = (((i.owner.global_position - global_position) / modifier).length() / 250)
|
||||
i.owner.velocity += (wind_velocity / distance / Vector2(2, 1))
|
||||
$Particles.emitting = active
|
||||
$Sprite.play("On" if active else "Off")
|
1
Scripts/Classes/Entities/Objects/OnOffFanRed.gd.uid
Normal file
1
Scripts/Classes/Entities/Objects/OnOffFanRed.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://bvplls3ae0oqr
|
17
Scripts/Classes/Entities/Objects/PSwitch.gd
Normal file
17
Scripts/Classes/Entities/Objects/PSwitch.gd
Normal file
@@ -0,0 +1,17 @@
|
||||
extends CharacterBody2D
|
||||
|
||||
var is_pressed := false
|
||||
|
||||
func on_player_entered(player: Player) -> void:
|
||||
if player.velocity.y >= 0:
|
||||
pressed()
|
||||
|
||||
func pressed() -> void:
|
||||
if is_pressed:
|
||||
return
|
||||
is_pressed = true
|
||||
$Sprite.play("Pressed")
|
||||
AudioManager.play_global_sfx("switch")
|
||||
AudioManager.play_global_sfx("cannon")
|
||||
$AnimationPlayer.play("Pressed")
|
||||
Global.activate_p_switch()
|
1
Scripts/Classes/Entities/Objects/PSwitch.gd.uid
Executable file
1
Scripts/Classes/Entities/Objects/PSwitch.gd.uid
Executable file
@@ -0,0 +1 @@
|
||||
uid://df20kjawaoqcl
|
50
Scripts/Classes/Entities/Objects/RopeElevatorPlatform.gd
Normal file
50
Scripts/Classes/Entities/Objects/RopeElevatorPlatform.gd
Normal file
@@ -0,0 +1,50 @@
|
||||
class_name RopeElevatorPlatform
|
||||
extends Node2D
|
||||
|
||||
|
||||
@export var linked_platform: Node2D = null
|
||||
|
||||
@onready var platform: AnimatableBody2D = $Platform
|
||||
@onready var player_detection: Area2D = $Platform/PlayerDetection
|
||||
|
||||
@export var rope_top := -160
|
||||
var velocity := 0.0
|
||||
|
||||
var dropped := false
|
||||
|
||||
var player_stood_on := false
|
||||
|
||||
var sample_colour: Texture = null
|
||||
|
||||
func _ready() -> void:
|
||||
$Platform/ScoreNoteSpawner.owner = $Platform
|
||||
|
||||
func _process(_delta: float) -> void:
|
||||
if not dropped:
|
||||
$Rope.size.y = platform.global_position.y - rope_top
|
||||
$Rope.global_position.y = rope_top
|
||||
|
||||
func _physics_process(delta: float) -> void:
|
||||
player_stood_on = player_detection.get_overlapping_areas().any(is_player)
|
||||
if dropped:
|
||||
velocity += (5 / delta) * delta
|
||||
platform.position.y += velocity * delta
|
||||
return
|
||||
else:
|
||||
if platform.global_position.y <= rope_top or linked_platform.dropped:
|
||||
dropped = true
|
||||
if linked_platform.dropped:
|
||||
if Settings.file.audio.extra_sfx == 1:
|
||||
AudioManager.play_sfx("lift_fall", global_position)
|
||||
$Platform/ScoreNoteSpawner.spawn_note(1000)
|
||||
if player_stood_on:
|
||||
velocity += (2 / delta) * delta
|
||||
else:
|
||||
velocity = lerpf(velocity, 0, delta * 2)
|
||||
linked_platform.velocity = -velocity
|
||||
platform.position.y += velocity * delta
|
||||
|
||||
func is_player(area: Area2D) -> bool:
|
||||
if area.owner is Player:
|
||||
return area.owner.is_on_floor()
|
||||
return false
|
1
Scripts/Classes/Entities/Objects/RopeElevatorPlatform.gd.uid
Executable file
1
Scripts/Classes/Entities/Objects/RopeElevatorPlatform.gd.uid
Executable file
@@ -0,0 +1 @@
|
||||
uid://brl0yede1msau
|
49
Scripts/Classes/Entities/Objects/SpikeBall.gd
Normal file
49
Scripts/Classes/Entities/Objects/SpikeBall.gd
Normal file
@@ -0,0 +1,49 @@
|
||||
class_name SpikeBall
|
||||
extends CharacterBody2D
|
||||
|
||||
var can_gravity := false
|
||||
const SPIKE_BALL_DESTRUCTION_PARTICLES = preload("uid://bk0arhpyyila6")
|
||||
func _physics_process(delta: float) -> void:
|
||||
handle_movement(delta)
|
||||
$Sprite.rotation_degrees += velocity.x * delta * 8
|
||||
handle_block_collision()
|
||||
|
||||
func handle_movement(delta: float) -> void:
|
||||
if can_gravity:
|
||||
velocity.y += (Global.entity_gravity / delta) * delta
|
||||
if is_on_floor():
|
||||
can_gravity = true
|
||||
velocity.x += get_floor_normal().x * 4
|
||||
if is_on_wall():
|
||||
destroy()
|
||||
if sign(get_floor_normal().x) != sign(velocity.x) and abs(get_floor_normal().x) > 0.2 and is_on_floor():
|
||||
velocity.y = (velocity.length() * get_floor_normal().y) + Global.entity_gravity
|
||||
move_and_slide()
|
||||
|
||||
func destroy() -> void:
|
||||
summon_particles()
|
||||
AudioManager.play_sfx("block_break", global_position)
|
||||
queue_free()
|
||||
|
||||
func handle_block_collision() -> void:
|
||||
for i in $Hitbox.get_overlapping_bodies():
|
||||
if i is Block:
|
||||
if global_position.y - 8 < i.global_position.y:
|
||||
i.shell_block_hit.emit(null)
|
||||
|
||||
func summon_particles() -> void:
|
||||
var particles = SPIKE_BALL_DESTRUCTION_PARTICLES.instantiate()
|
||||
particles.global_position = global_position
|
||||
add_sibling(particles)
|
||||
|
||||
func on_area_entered(area: Area2D) -> void:
|
||||
if area.owner is SpikeBall and area.owner != self:
|
||||
destroy()
|
||||
if area.owner is Enemy:
|
||||
if area.owner.has_node("ShellDetection"):
|
||||
area.owner.die_from_object(self)
|
||||
elif area.owner is Player:
|
||||
if area.owner.is_invincible:
|
||||
destroy()
|
||||
else:
|
||||
area.owner.damage()
|
1
Scripts/Classes/Entities/Objects/SpikeBall.gd.uid
Executable file
1
Scripts/Classes/Entities/Objects/SpikeBall.gd.uid
Executable file
@@ -0,0 +1 @@
|
||||
uid://dlq222ogmfken
|
81
Scripts/Classes/Entities/Objects/Track.gd
Normal file
81
Scripts/Classes/Entities/Objects/Track.gd
Normal file
@@ -0,0 +1,81 @@
|
||||
class_name Track
|
||||
extends Node2D
|
||||
const TRACK_PIECE = preload("uid://4gxhnql5bjk6")
|
||||
|
||||
@export var path := []
|
||||
var pieces := []
|
||||
var length := 0
|
||||
|
||||
@export_enum("Closed", "Open") var start_point := 0
|
||||
@export_enum("Closed", "Open") var end_point := 0
|
||||
@export var invisible := false:
|
||||
set(value):
|
||||
invisible = value
|
||||
update_pieces()
|
||||
|
||||
var editing := false
|
||||
|
||||
const DIRECTIONS := [
|
||||
Vector2i(-1, -1), # 0
|
||||
Vector2i.UP, # 1
|
||||
Vector2i(1, -1), # 2
|
||||
Vector2i.RIGHT, # 3
|
||||
Vector2i(1, 1), # 4
|
||||
Vector2i.DOWN, # 5
|
||||
Vector2i(-1, 1), # 6
|
||||
Vector2i.LEFT # 7
|
||||
]
|
||||
|
||||
func _process(_delta: float) -> void:
|
||||
$Point.frame = int(start_point == 0)
|
||||
visible = not (invisible and LevelEditor.playing_level)
|
||||
if editing and Global.current_game_mode == Global.GameMode.LEVEL_EDITOR:
|
||||
if Input.is_action_just_pressed("editor_open_menu") or Input.is_action_just_pressed("ui_cancel"):
|
||||
editing = false
|
||||
Global.level_editor.current_state = LevelEditor.EditorState.IDLE
|
||||
update_pieces()
|
||||
|
||||
func _ready() -> void:
|
||||
for i in path:
|
||||
add_piece(i, false)
|
||||
update_pieces()
|
||||
|
||||
func update_pieces() -> void:
|
||||
var idx := 0
|
||||
for i in $Pieces.get_children():
|
||||
i.idx = idx
|
||||
i.editing = idx >= path.size() and editing
|
||||
if idx > 0:
|
||||
i.starting_direction = -path[idx - 1]
|
||||
else:
|
||||
i.starting_direction = Vector2i.ZERO
|
||||
if idx <= path.size() - 1:
|
||||
i.connecting_direction = path[idx]
|
||||
else:
|
||||
i.connecting_direction = Vector2i.ZERO
|
||||
i.update_direction_textures()
|
||||
idx += 1
|
||||
|
||||
func add_piece(new_direction := Vector2i.ZERO, add_to_arr := true) -> void:
|
||||
var piece = TRACK_PIECE.instantiate()
|
||||
var next_position := new_direction * 16
|
||||
for i in length:
|
||||
next_position += path[i] * 16
|
||||
piece.position = next_position
|
||||
$Pieces.add_child(piece)
|
||||
piece.owner = self
|
||||
pieces.append(piece)
|
||||
piece.idx = length
|
||||
piece.reset_physics_interpolation()
|
||||
if add_to_arr:
|
||||
path.append(new_direction)
|
||||
length += 1
|
||||
update_pieces()
|
||||
|
||||
func remove_last_piece() -> void:
|
||||
$Pieces.get_child($Pieces.get_child_count() - 1).queue_free()
|
||||
await get_tree().process_frame
|
||||
path.pop_back()
|
||||
pieces.pop_back()
|
||||
length -= 1
|
||||
update_pieces()
|
1
Scripts/Classes/Entities/Objects/Track.gd.uid
Normal file
1
Scripts/Classes/Entities/Objects/Track.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://3heyyx506fnu
|
62
Scripts/Classes/Entities/Objects/TrackPiece.gd
Normal file
62
Scripts/Classes/Entities/Objects/TrackPiece.gd
Normal file
@@ -0,0 +1,62 @@
|
||||
class_name TrackPiece
|
||||
extends Node2D
|
||||
|
||||
var editing := false
|
||||
|
||||
var mouse_in_areas := 0
|
||||
|
||||
var pieces := []
|
||||
|
||||
var idx := 0
|
||||
|
||||
var starting_direction := Vector2i.ZERO
|
||||
var connecting_direction := Vector2i.UP
|
||||
|
||||
const SPRITE_COORDS := {
|
||||
Vector2i.ZERO: Vector2(112, 16),
|
||||
Vector2i.RIGHT: Vector2(0, 0),
|
||||
Vector2i.LEFT: Vector2(16, 0),
|
||||
Vector2i.DOWN: Vector2(32, 0),
|
||||
Vector2i.UP: Vector2(48, 0),
|
||||
Vector2i(1, 1): Vector2(64, 0),
|
||||
Vector2i(-1, 1): Vector2(80, 0),
|
||||
Vector2i(-1, -1): Vector2(96, 0),
|
||||
Vector2i(1, -1): Vector2(112, 0),
|
||||
}
|
||||
|
||||
const TRACKS = preload("uid://50hm4xgnw8ks")
|
||||
const INVISIBLE_TRACKS = preload("uid://barofu3g8jf00")
|
||||
|
||||
func _process(_delta: float) -> void:
|
||||
$PlacePreview.visible = editing
|
||||
$Start.region_rect.position = SPRITE_COORDS[starting_direction]
|
||||
$Connect.region_rect.position = SPRITE_COORDS[connecting_direction]
|
||||
$End.visible = idx == owner.length
|
||||
$End.frame = int(owner.end_point == 0)
|
||||
if Input.is_action_pressed("mb_left") and editing and mouse_in_areas > 0:
|
||||
for i in 8:
|
||||
if is_mouse_in_area(i):
|
||||
if Track.DIRECTIONS[i] == starting_direction:
|
||||
owner.remove_last_piece()
|
||||
else:
|
||||
owner.add_piece(Track.DIRECTIONS[i])
|
||||
|
||||
func update_direction_textures() -> void:
|
||||
var texture = TRACKS
|
||||
if owner.invisible:
|
||||
texture = INVISIBLE_TRACKS
|
||||
for i in $PlacePreview.get_children():
|
||||
i.frame = int(Track.DIRECTIONS[i.get_index()] == starting_direction)
|
||||
for i in [$Start, $Connect, $End]:
|
||||
i.texture = texture
|
||||
|
||||
func on_mouse_entered(area_idx := 0) -> void:
|
||||
mouse_in_areas |= (1 << area_idx)
|
||||
print(mouse_in_areas)
|
||||
|
||||
func on_mouse_exited(area_idx := 0) -> void:
|
||||
mouse_in_areas &= ~(1 << area_idx)
|
||||
print(mouse_in_areas)
|
||||
|
||||
func is_mouse_in_area(area_idx := 0) -> bool:
|
||||
return mouse_in_areas & (1 << area_idx) != 0
|
1
Scripts/Classes/Entities/Objects/TrackPiece.gd.uid
Normal file
1
Scripts/Classes/Entities/Objects/TrackPiece.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://chhr6kgvstkod
|
114
Scripts/Classes/Entities/Objects/TrackRider.gd
Normal file
114
Scripts/Classes/Entities/Objects/TrackRider.gd
Normal file
@@ -0,0 +1,114 @@
|
||||
class_name TrackRider
|
||||
extends Node2D
|
||||
|
||||
@export var attached_entity: Node2D = null
|
||||
|
||||
@export_range(1, 8, 1) var speed := 2
|
||||
@export_enum("Forward", "Backward") var direction := 0
|
||||
|
||||
var velocity := Vector2.ZERO
|
||||
var last_position := Vector2.ZERO
|
||||
var direction_vector := Vector2i.ZERO
|
||||
|
||||
var current_track: Track = null
|
||||
var track_idx := -1
|
||||
var can_attach := true
|
||||
var travelling_on_rail := false
|
||||
|
||||
func _ready() -> void:
|
||||
start()
|
||||
await get_tree().physics_frame
|
||||
if attached_entity != null:
|
||||
attach_to_joint(attached_entity)
|
||||
|
||||
func start() -> void:
|
||||
current_track = null
|
||||
track_idx = -1
|
||||
|
||||
func check_for_entities() -> void:
|
||||
for i in $Hitbox.get_overlapping_bodies():
|
||||
print(i)
|
||||
if i.has_node("TrackJoint"):
|
||||
attach_to_joint(i)
|
||||
return
|
||||
for i in $Hitbox.get_overlapping_areas():
|
||||
print(i)
|
||||
if i.owner.has_node("TrackJoint"):
|
||||
attach_to_joint(i.owner)
|
||||
return
|
||||
|
||||
func _physics_process(delta: float) -> void:
|
||||
if attached_entity == null:
|
||||
check_for_entities()
|
||||
return
|
||||
if travelling_on_rail == false:
|
||||
velocity.y += 10
|
||||
global_position += velocity * delta
|
||||
check_for_rail()
|
||||
last_position = global_position
|
||||
|
||||
func attach_to_joint(node: Node2D) -> void:
|
||||
var joint = node.get_node("TrackJoint")
|
||||
joint.is_attached = true
|
||||
if joint.movement_node != null:
|
||||
joint.movement_node.active = false
|
||||
joint.attached.emit()
|
||||
elif joint.disable_physics:
|
||||
node.set_physics_process(false)
|
||||
joint.rider = self
|
||||
node.physics_interpolation_mode = Node.PHYSICS_INTERPOLATION_MODE_OFF
|
||||
node.reparent($Joint, false)
|
||||
node.position = joint.offset
|
||||
attached_entity = node
|
||||
|
||||
func check_for_rail() -> void:
|
||||
if travelling_on_rail == false and can_attach:
|
||||
for i in $Hitbox.get_overlapping_areas():
|
||||
if i.get_parent() is TrackPiece and i.get_parent().owner != current_track:
|
||||
var piece: TrackPiece = i.get_parent()
|
||||
if piece.owner.length <= 0:
|
||||
continue
|
||||
global_position = piece.global_position
|
||||
travelling_on_rail = true
|
||||
current_track = piece.owner
|
||||
track_idx = piece.idx
|
||||
if track_idx >= current_track.path.size():
|
||||
direction = 1
|
||||
if direction == 1:
|
||||
track_idx -= 1
|
||||
track_idx = clamp(track_idx, 0, current_track.path.size() - 1)
|
||||
if travelling_on_rail:
|
||||
direction_vector = current_track.path[track_idx] * [1, -1][direction]
|
||||
if current_track != null:
|
||||
move_tween(Vector2(direction_vector))
|
||||
|
||||
func move_tween(new_direction := Vector2.ZERO) -> void:
|
||||
var tween = create_tween()
|
||||
tween.tween_property(self, "global_position", global_position + (new_direction * 16), float(1.0 if new_direction.is_normalized() else 1.414) / (speed * 2))
|
||||
await tween.finished
|
||||
track_idx += [1, -1][direction]
|
||||
|
||||
|
||||
if track_idx >= current_track.length and direction == 0:
|
||||
track_idx = current_track.length - 1
|
||||
if current_track.end_point == 0:
|
||||
direction = 1
|
||||
else:
|
||||
detach_from_rail()
|
||||
return
|
||||
if track_idx < 0 and direction == 1:
|
||||
track_idx = 0
|
||||
if current_track.start_point == 0:
|
||||
direction = 0
|
||||
else:
|
||||
detach_from_rail()
|
||||
return
|
||||
check_for_rail()
|
||||
|
||||
func detach_from_rail() -> void:
|
||||
can_attach = false
|
||||
travelling_on_rail = false
|
||||
track_idx = -1
|
||||
velocity = direction_vector * speed * 48
|
||||
await get_tree().create_timer(0.1, false).timeout
|
||||
can_attach = true
|
1
Scripts/Classes/Entities/Objects/TrackRider.gd.uid
Normal file
1
Scripts/Classes/Entities/Objects/TrackRider.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://dg16ltpjq1r4r
|
41
Scripts/Classes/Entities/Objects/Trampoline.gd
Normal file
41
Scripts/Classes/Entities/Objects/Trampoline.gd
Normal file
@@ -0,0 +1,41 @@
|
||||
extends AnimatableBody2D
|
||||
|
||||
@export var bounce_height := -500
|
||||
|
||||
var players := []
|
||||
|
||||
func on_area_entered(area: Area2D) -> void:
|
||||
pass
|
||||
|
||||
func _physics_process(_delta: float) -> void:
|
||||
for i in $Hitbox.get_overlapping_areas():
|
||||
if i.owner is Player and i.owner.is_on_floor():
|
||||
if i.owner.spring_bouncing or i.owner.velocity.y < 0:
|
||||
continue
|
||||
i.owner.velocity.x = 0
|
||||
if players.has(i.owner) == false:
|
||||
players.append(i.owner)
|
||||
$Animation.play("Bounce")
|
||||
i.owner.spring_bouncing = true
|
||||
for i in players:
|
||||
i.global_position.y = $PlayerCollision/PlayerJoint.global_position.y
|
||||
|
||||
func bounce_players() -> void:
|
||||
var high_bounce := false
|
||||
for player in players:
|
||||
if Global.player_action_pressed("jump", player.player_id):
|
||||
high_bounce = true
|
||||
player.velocity.y = bounce_height
|
||||
player.gravity = player.JUMP_GRAVITY
|
||||
player.has_jumped = true
|
||||
else:
|
||||
player.velocity.y = -300
|
||||
if high_bounce:
|
||||
AudioManager.play_sfx("spring", global_position)
|
||||
else:
|
||||
AudioManager.play_sfx("bump", global_position)
|
||||
players.clear()
|
||||
|
||||
func on_area_exited(area: Area2D) -> void:
|
||||
if area.owner is Player:
|
||||
area.owner.spring_bouncing = false
|
1
Scripts/Classes/Entities/Objects/Trampoline.gd.uid
Executable file
1
Scripts/Classes/Entities/Objects/Trampoline.gd.uid
Executable file
@@ -0,0 +1 @@
|
||||
uid://bof8ieprith1d
|
19
Scripts/Classes/Entities/Objects/WindArea.gd
Normal file
19
Scripts/Classes/Entities/Objects/WindArea.gd
Normal file
@@ -0,0 +1,19 @@
|
||||
extends Area2D
|
||||
|
||||
@export var wind_force := 30
|
||||
|
||||
func _ready() -> void:
|
||||
await get_tree().create_timer(0.1, false).timeout
|
||||
get_parent().move_child(self, 0)
|
||||
|
||||
func _physics_process(delta: float) -> void:
|
||||
for i in get_overlapping_areas():
|
||||
if i.owner is Player:
|
||||
if i.owner.spring_bouncing == false and i.owner.is_on_wall() == false and i.owner.state_machine.state.name == "Normal":
|
||||
i.owner.global_position.x += wind_force * delta
|
||||
var active := get_overlapping_areas().any(func(area: Area2D) -> bool: return area.owner is Player)
|
||||
$CanvasLayer/Control/Particles.emitting = active
|
||||
if active and $SFX.is_playing() == false:
|
||||
$SFX.play()
|
||||
elif not active:
|
||||
$SFX.stop()
|
1
Scripts/Classes/Entities/Objects/WindArea.gd.uid
Executable file
1
Scripts/Classes/Entities/Objects/WindArea.gd.uid
Executable file
@@ -0,0 +1 @@
|
||||
uid://d3kftxro4bfnv
|
Reference in New Issue
Block a user