kidscancode / Godot3_dodge

"Dodge the Creeps!" Godot Engine 3.0 "getting started" game demonstrating the basics.
MIT License
90 stars 30 forks source link

StartTimer firing after game over #4

Closed KellyThomas closed 4 years ago

KellyThomas commented 6 years ago

If the player suffers an early death then StartTimer can fire after the game over.

This kicks off MobTimer and ScoreTimer which continue to fire while the menu is displayed.

This can exacerbate the problem because MobTimer will ensure that there are enemies on the screen increasing the likely-hood of an early death next time.

cbscribe commented 6 years ago

Closed. See #5

KellyThomas commented 6 years ago

@cbscribe

On second and subsequent plays the field may have enemies left still active from the previous play. This means that it is possible for a player to die before StartTimer fires its single shot.

2018-03-06_03-37-37

The two solutions that spring to mind are to either:

  1. Clear the enemies during new game or game over housekeeping, or
  2. Stop StartTimer during game over housekeeping.

The first of these options provides a more constant experience for the player in that each game will be begin in the same state, but adds a little bit more complexity to the tutorial.

The second option is a one line modification that doesn't even need to be mentioned in the explanatory text.

cbscribe commented 6 years ago

Now I understand what you're getting at. I'll reopen the issue for discussion. Stopping the start timer doesn't really fix anything, btw. I can still hit "Start" again and be playing while the leftover mobs haven't left the screen yet.

I would add there's an option 3: increase the message timer slightly, so that the leftover mobs have time to exit before the start button appears.

Making a tutorial like this is a difficult balancing act between keeping it simple and handling all the possible issues, but adding complexity. Personally, I'm OK with the current situation for two reasons:

  1. It's a minor issue and really only occurs when you are super quick to hit the start button and immediately start moving.
  2. It's good to leave minor improvements and enhancements for users like yourself to discover and attempt to fix. That is an even better learning situation than following along the tutorial was.
KellyThomas commented 6 years ago

I understand that striking the right balance for a tutorial can be tricky.

Personally I would encourage making some changes to ensure that player input is unable to break the game UI. As a core tutorial in the official docs I think it needs to serve as a robust example.

As an anecdote, I was following along but porting the code to c# as a learning exercise. When I encountered this issue I thought it was a problem with my implementation and spent an hour or so double checking everything on my end before I checked this reference implementation.


Having given it a bit more thought I think it may serve as a good case for adding groups to the tutorial. Adding a mobs group and then iterating through and clearing its members could serve as a brief introduction to a powerful godot feature.

Anyway its a minor edge case and I will defer to your judgement at the end of the day.

cbscribe commented 6 years ago

I think it may serve as a good case for adding groups to the tutorial

Not a bad idea, although I am hesitant about introducing groups for something like this, as it has the potential to promote bad habits (abusing groups for things they're not good at).

It could also work to make a parent Node to hold the mobs. The restart button could remain invisible until that node's child count is 0.

I'm going to tinker a bit with both these ideas and see how they look on the page.

rosscg commented 5 years ago

I think the most straight-forward solution is to move $Player.start($StartPosition.position) from new_game() to the end of _on_StartTimer_timeout().

This way the player can't spawn and die before the Mob and Score timers begin, thus the timers terminate correctly.

Of course the player can still die to existing mobs but unless (for e.g.) the mob speed, start timer or window size is adjusted this is unlikely to happen without the user intentionally running into a mob and they can always wait for them to clear before pressing start.

Edit: While it won't cause an issue unless the code is modified, for completeness' sake, it's worth setting the player's collision to false on instantiation as they are now vulnerable during the StartTimer countdown at (0,0).

Jonasfxh commented 5 years ago

@rosscg I solved it by adding a variable on the player's script called can_die = false and verifying if the player can die on the player_body_entered's signal so if the player can't die then it returns. Later adding on the Main's script on new_game function the $Player.can_die = false and on the _on_StartTimer_timeout signal the $player.can_die = true

func _on_Player_body_entered(body):
    if can_die == false:
        return
   # and rest of the code after the check ...

This way the player can hit and be hitted by an enemy and won't die until the StartTime timout signal is called or arised.

cbscribe commented 4 years ago

Fixed in updated version by removing all mobs at game over.