Godot Version
Godot_v4.2.2
Question
Hi, so i have a problem with my projectile
Sometimes when i hit part of tilemap it does not destroy that part of the tile map, especially on the edges.
Also i need to set the speed of the bullet to extremely low values to even destroy the block that the bullet hit first and not 4 tiles behind it
Here is the code for the projectile2.gd:
extends Area2D
@export var speed: float = 300.0
@export var lifetime: float = 10.0 # Time until bullet is destroyed
var velocity: Vector2 = Vector2.ZERO # Default position
var hit_registered: bool = false # Hit flag
@onready var tile_map = $TileMap # Reference to the TileMap
@onready var sprite = $Sprite2D # Reference to the sprite
@onready var collision_shape = $CollisionShape2D # Reference to the collision shape
const DEATH_PARTICLE_SCENE = preload("res://scenes/DeathParticle.tscn") # Death particle effect
func _ready():
# Set up the timer to destroy the bullet after lifetime expires
var timer = Timer.new()
timer.wait_time = lifetime
timer.one_shot = true
timer.timeout.connect(_on_timeout)
add_child(timer)
timer.start()
# Connect the body_entered signal for collision detection
connect("body_entered", _on_body_entered)
func _process(delta):
# Move the bullet according to its velocity
position += velocity * delta # Manual movement of the bullet
func destroy_tile(tilemap: TileMap):
var tile_position = tilemap.local_to_map(position.round()) # Zaokrąglij pozycję pocisku
var tile_source_id = tilemap.get_cell_source_id(0, tile_position) # Pobierz źródło kafelka w warstwie 0
if tile_source_id != -1: # check if it is actually a part of tilemap
tilemap.set_cell(0, tile_position, -1) # est to -1, to delete tile
func _on_body_entered(body):
if hit_registered:
return # Ignore further collisions if already hit
if body.is_class("TileMap"):
# Call tile destruction method
destroy_tile(body) # Pass the TileMap as an argument
queue_free() # Remove the bullet
elif body.name == "CharacterBody2D":
# Ignore collision with CharacterBody2D and continue the bullet's path
return
else:
# Bullet hit an enemy or other object
hit_registered = true # Register the hit
sprite.visible = false # Hide bullet sprite
collision_shape.disabled = true # Disable bullet collision
# Check if the object has apply_damage method
if body.has_method("apply_damage"):
body.apply_damage(20) # Deal 20 damage
# Add death particle effect if bullet hits an enemy
var death_particle = DEATH_PARTICLE_SCENE.instantiate()
add_child(death_particle)
death_particle.global_position = body.global_position
death_particle.emitting = true
# Wait 0.2 seconds before removing the bullet
await get_tree().create_timer(0.2).timeout
queue_free() # Remove the bullet
func _on_timeout():
# Remove the bullet after lifetime expires
queue_free()
and here is code for the player(main_character):
extends CharacterBody2D
var double_jump = 0
var max_jumps = 2
const SPEED = 375.0
const RUN_SPEED = 500.0
const JUMP_VELOCITY = -760.0
var current_speed = SPEED
var last_direction = 1
var is_weapon_active = false
var shooting = false
var shoot_timer = 0.0
var shoot_interval = 0.05
var fire_mode = "single" # Fire mode: 'single' or 'auto'
var initial_visibility = {} # Map to store visibility state
@onready var sprite_2d_3 = $Sprite2D3
@onready var sprite_2d_4 = $Sprite2D4
@onready var sprite_2d_5 = $Sprite2D5
@onready var sprite_2d_6 = $Sprite2D6 # New sprite
@export var death_particle: PackedScene
@onready var sprite_2d = $Sprite2D
@onready var kalach_sprite = $Sprite2D2
@onready var collectable = $"../coll/Collectable"
@onready var jump_sound = $jump
@onready var bieganie = $bieganie
@onready var bljaaaaa = $bljaaaaa
@onready var kill1 = $kill1
@onready var randomk = $randomk
@export var particle: PackedScene
@export var projectile_scene: PackedScene
# Magazine
var magazine_size = 30 # Magazine capacity
var current_ammo: int = magazine_size # Current ammo in the magazine
var reload_time: float = 5.0 # Reload time in seconds
var is_reloading: bool = false # Flag to control if the weapon is reloading
var gravity = ProjectSettings.get_setting("physics/2d/default_gravity")
func _ready():
kalach_sprite.visible = false
set_weapon_sprites_visibility()
func jump():
velocity.y = JUMP_VELOCITY
spawn_particle()
func spawn_particle():
var particle_node = particle.instantiate()
particle_node.position = position
get_parent().add_child(particle_node)
await get_tree().create_timer(0.3).timeout
particle_node.queue_free()
func _physics_process(delta):
var speed = SPEED
# Check if weapon is active and aiming with the weapon
if is_weapon_active:
aim_weapon()
# Adding gravity
if not is_on_floor():
velocity.y += gravity * delta
if double_jump == 2:
sprite_2d.animation = "test"
else:
sprite_2d.animation = "jumping"
else:
double_jump = 0
if velocity.x == 0:
sprite_2d.animation = "default"
else:
sprite_2d.animation = "running"
# Jump input handling
if Input.is_action_just_pressed("jump") and double_jump < max_jumps:
jump_sound.play()
jump()
double_jump += 1
if double_jump == 2:
spawn_particle()
# Direction handling
var direction = Input.get_axis("left", "right")
# Running handling
if Input.is_action_pressed("run") and is_on_floor():
current_speed = RUN_SPEED
speed = RUN_SPEED
if direction != 0:
sprite_2d.animation = "running"
else:
sprite_2d.animation = "default"
elif is_on_floor():
current_speed = SPEED
# Character movement
if direction != 0:
velocity.x = direction * current_speed
last_direction = direction
else:
velocity.x = move_toward(velocity.x, 0, 70)
move_and_slide()
# Flip the sprite depending on the last movement direction
if last_direction < 0:
sprite_2d.flip_h = true
elif last_direction > 0:
sprite_2d.flip_h = false
# Toggle weapon activation
if Input.is_action_just_pressed("weapon_toggle"):
toggle_weapon()
# Toggle fire mode
if Input.is_action_just_pressed("toggle_fire_mode"):
toggle_fire_mode()
set_weapon_sprites_visibility() # Set weapon sprites visibility after switching fire mode
# Shooting logic
if is_weapon_active:
if is_reloading:
shooting = false
else:
if fire_mode == "auto" and Input.is_action_pressed("shoot"):
if current_ammo > 0:
shooting = true
else:
start_reloading() # Start reloading if no ammo
elif fire_mode == "single" and Input.is_action_just_pressed("shoot"):
if current_ammo > 0:
shoot_projectile() # Single shot
current_ammo -= 1 # Decrease ammo count
else:
start_reloading() # Start reloading if no ammo
else:
shooting = false
shoot_timer = shoot_interval # Reset shoot timer after shooting ends
# Continuous shooting in auto mode
if shooting and fire_mode == "auto":
shoot_timer -= delta
if shoot_timer <= 0:
shoot_projectile()
current_ammo -= 1 # Decrease ammo count
shoot_timer = shoot_interval
# Set weapon sprites visibility based on the kalach_sprite state
set_weapon_sprites_visibility()
# Function to toggle fire mode
func toggle_fire_mode():
if fire_mode == "single":
fire_mode = "auto"
print("Fire mode switched to automatic.")
else:
fire_mode = "single"
print("Fire mode switched to single shot.")
# Function to toggle weapon visibility (kalach)
func toggle_weapon():
is_weapon_active = not is_weapon_active
kalach_sprite.visible = is_weapon_active
set_weapon_sprites_visibility() # Set weapon sprites visibility
# Function to set weapon sprites visibility
func set_weapon_sprites_visibility():
var is_kalach_visible = kalach_sprite.visible
if is_kalach_visible: # Only if the weapon is visible
sprite_2d_3.visible = is_weapon_active && fire_mode == "single" # Visible only in single mode
sprite_2d_4.visible = is_weapon_active && fire_mode == "auto" # Visible in auto mode
sprite_2d_5.visible = is_weapon_active && fire_mode == "auto" # Visible in auto mode
sprite_2d_6.visible = is_weapon_active && fire_mode == "auto" # Visible in auto mode
else:
sprite_2d_3.visible = false
sprite_2d_4.visible = false
sprite_2d_5.visible = false
sprite_2d_6.visible = false
# Function to make the weapon follow the player's cursor
func aim_weapon():
var mouse_position = get_global_mouse_position()
var weapon_position = kalach_sprite.global_position
var angle = (mouse_position - weapon_position).angle()
kalach_sprite.rotation = angle
if abs(angle) > PI / 2:
kalach_sprite.flip_v = true
else:
kalach_sprite.flip_v = false
# Function to shoot a projectile
func shoot_projectile():
if projectile_scene == null:
print("projectile_scene is null! Please assign it in the inspector.")
return
var projectile = projectile_scene.instantiate()
var mouse_position = get_global_mouse_position()
projectile.position = kalach_sprite.global_position
var direction = (mouse_position - projectile.position).normalized()
projectile.velocity = direction * projectile.speed
var angle = direction.angle()
projectile.rotation = angle
get_parent().add_child(projectile)
# Function to start reloading
func start_reloading():
if not is_reloading: # Only if it's not already reloading
is_reloading = true
print("Reloading...")
await get_tree().create_timer(reload_time).timeout # Wait for reload to finish
current_ammo = magazine_size # Refill the ammo
is_reloading = false
print("Reloading complete.")
Thank you in advance!!!