Skip to content

Instantly share code, notes, and snippets.

@N-Carter
Created March 8, 2023 17:51
Show Gist options
  • Save N-Carter/cd92bf0eb2c6e6dea269d70ef268138a to your computer and use it in GitHub Desktop.
Save N-Carter/cd92bf0eb2c6e6dea269d70ef268138a to your computer and use it in GitHub Desktop.
extends Area2D
@export var _walk_speed := 50.0
@export var _jump_speed := 300.0
var _gravity : float = ProjectSettings.get_setting("physics/2d/default_gravity")
@onready var _tilemap := Global.tilemap
var _velocity : Vector2
var _is_solid_left : bool
var _is_solid_right : bool
var _is_solid_above : bool
var _is_solid_below : bool
const TILE_SIZE := 16.0
const TILE_HALF_SIZE := TILE_SIZE * 0.5
func _physics_process(delta : float) -> void:
if _is_solid_below:
if Input.is_action_just_pressed("action"):
_velocity.y = -_jump_speed
else:
_velocity.y = 0.0
else:
_velocity.y += _gravity * delta
var direction := Input.get_axis("left", "right")
if direction:
_velocity.x = direction * _walk_speed
else:
_velocity.x = move_toward(_velocity.x, 0, _walk_speed)
var new_position := global_position + _velocity * delta
_is_solid_left = _is_tile_solid(new_position + Vector2(-TILE_HALF_SIZE, 0))
_is_solid_right = _is_tile_solid(new_position + Vector2(TILE_HALF_SIZE, 0))
_is_solid_above = _is_tile_solid(new_position + Vector2(0, -TILE_HALF_SIZE))
_is_solid_below = _is_tile_solid(new_position + Vector2(0, TILE_HALF_SIZE))
# var mod_y := fposmod(new_position.y, TILE_SIZE)
# if _is_solid_below and mod_y > TILE_HALF_SIZE:
# new_position.y = snappedf(new_position.y, TILE_SIZE) - TILE_HALF_SIZE
# if _is_solid_above and mod_y < TILE_HALF_SIZE:
# new_position.y = snappedf(new_position.y, TILE_SIZE) + TILE_HALF_SIZE
# These only consider tiles to the immediate left or right, but it's also important to consider
# tiles which are above or below to the left and right. I think it's necessary to test three
# tiles relative to the player's position:
#
# +-------+-------+
# |√ |√ | ∙ : tile centre
# | ∙ | ∙ | √ : tiles to check
# | | | + : player's centre in the tile is closest to the marked tiles
# +-------+-------+
# |√ | + |
# | ∙ | ∙ |
# | | |
# +-------+-------+
#
# The other thing is that you need to determine which obstruction you hit first, and that
# depends on your direction of travel.
#
# What about integer coordinates and velocity?
if _is_solid_left or _is_solid_right:
new_position.x = snappedf_round(new_position.x, TILE_SIZE) - TILE_HALF_SIZE
if _is_solid_above or _is_solid_below:
new_position.y = snappedf_round(new_position.y, TILE_SIZE) - TILE_HALF_SIZE
global_position = new_position
func _is_tile_solid(where : Vector2) -> bool:
# "where" is in global coordinates.
var tile_coordinates := _tilemap.local_to_map(_tilemap.to_local(where))
var source := _tilemap.get_cell_source_id(0, tile_coordinates)
# var atlas_coords := _tilemap.get_cell_atlas_coords(0, tile_coordinates)
# print("%s, %s, %s" % [tile_coordinates, source, atlas_coords])
return (source >= 0)
func snappedf_round(p_value : float, p_step : float) -> float:
if p_step != 0.0:
p_value = roundf(p_value / p_step + 0.5) * p_step;
return p_value
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment