gdquest-demos / godot-3-beginner-2d-platformer

Learn to create a 2d platform game with the Godot game engine. This is a beginner programming tutorial.
MIT License
364 stars 96 forks source link

Add Mario Stomp #4

Closed henriiquecampos closed 5 years ago

henriiquecampos commented 5 years ago

When the Player jumps on enemies' heads, they should die.

These Area2Ds will be both One way collisions, Player's will be rotated 180 degrees to make sure the collision only happens from a Vector2(0, -1) collision normal

henriiquecampos commented 5 years ago

@razcore-art Can you help me with a decision? I'm not sure if I should add the stomp logic on the Player's script or on the StompArea2D script. The reason being: I need to get and modify the Player's linear velocity, which is private. But I also use a threshold and a force that are relative to the StompArea2d.

If I go with the logic being on the Player.gd it would be something like this:

extends KinematicBody2D

const SNAP_DIRECTION: = Vector2.DOWN
const FLOOR_NORMAL: = Vector2.UP

export var movement_speed: = 400.0
export var gravity: = 4000.0
export var jump_impulse: = 500.0

export var stomp_threshold: = 400.0
export var stomp_hop_impulse: = 600.0

var _linear_velocity: = Vector2.ZERO

func _physics_process(delta: float) -> void:
    move_and_slide_with_snap(_linear_velocity, SNAP_DIRECTION, FLOOR_NORMAL)

    if not is_on_floor():
        _linear_velocity.y += gravity * delta
    else:
        _linear_velocity.y = 0.0

func _on_StompArea2D_area_entered(area: Area2D) -> void:
    if _linear_velocity.y >= stomp_threshold:
        area.get_stomped()
        _linear_velocity.y = -stomp_hop_impulse

If I go with the logic being put on StompArea2D it would be something like this:

extends Area2D

onready var player: = get_node(player_path) as Player

const Player: = preload("res://actors/Player.gd")

export var player_path: = NodePath("..")
export var stomp_threshold: = 400.0
export var stomp_hop_impulse: = 600.0

func _on_area_entered(area: Area2D) -> void:
    if player._linear_velocity.y >= stomp_threshold:
        area.get_stomped()
        player._linear_velocity.y = -stomp_hop_impulse

The major problem is that Player._linear_velocity should ideally be private, we can make it public tho, I dunno if this is relevant for the sake of teaching. What do you think @NathanLovato ? Is private vs public relevant for the project's goal?

razcore-rad commented 5 years ago

I have a couple of questions and comments:

  1. why do we need a stomp_threshold? Isn't it enough that the one way collision gets triggered?
  2. let's go for now with the Player approach, it's simpler (less parts to worry about)
  3. I'm not entirely sure about area.get_stomped() call, what I'd probably do is have _on_StompableArea2D_entered where I check for the Player area and trigger the stomp/death sequence within the Enemy itself
  4. I personally think a small section on the pseudo-private/public topic is fine, this is by now a well established coding standard

Could you start uploading some of the code? it would be much easier if you created some PRs so I can explore them on my PC instead of responding through comments in abstract ways. You can mark the PRs as draft if they're not ready to merge.

henriiquecampos commented 5 years ago
  1. No, it isn't enough, for some reason the One Way Collision is detecting collisions...on every direction for this specific situation, that's the reason I had to create this threshold. ezgif com-video-to-gif
  2. Agree, each one does its own detection and handle it proper
henriiquecampos commented 5 years ago

This is very strange tbh, I am testing this in other Area2Ds with One Way Collision, and they all trigger collisions on every direction

henriiquecampos commented 5 years ago

I just opened an issue about this. https://github.com/godotengine/godot/issues/31564