Hi,
So, there is some continuation.
First of all maybe some explanation. When you call move_and_slide()
method it will move your KinematicBody2D, so having more than one method handling movement and using them the way you tried like for example:
func _physics_process(delta):
ButtonMovementLoop(delta)
MouseMovementLoop(delta)
Will actually cause your character move twice each time (because character will be moved by first method and later by second method again). Now as you noticed when you use any of button movement methods both with mouse movement method your character is moving a lot slower if you keep acceleration * delta
part. Why is that if you move your character twice? That should make it move even faster. Yes, but that is because of this part of code in MouseMovementLoop()
method:
if moving == false:
speed = 0
That code will always set speed to 0 after each update (if you don't use mouse movement at that time). That mean your character don't have time to get its maximum speed. ButtonMovementLoop()
will accelerate your character a bit each update, but MouseMovementLoop()
keep changing speed to 0, so your character is always starting movement from beginning each update. When you removed delta multiplication, probably character was able to "speed up" to max speed during one update. Max speed you used is 200 and acceleration is 750, so what happened to speed each update was:
#speed is 0 at the beginning
(...)
speed += acceleration #Now speed is 750
if speed > max_speed:
speed = max_speed #Now speed is 200
(...)
if moving == false:
speed = 0 #Speed is again 0
Delta in most cases is very small because it is time elapsed between updates, so when you multiplied acceleration by delta, value was a lot smaller and from above explanation I hope you understand why character was moving slower (it never was able to achieve max speed if it was set back to 0 each time in MouseMovementLoop()
).
Now if you used mouse movement both with button movement you wrote that player had some boost in direction you moved. That is because in that case MouseMovementLoop()
doesn't set speed back to 0 each time and it caused double movement each time as I mentioned (not only double movement, but also double acceleration).
That is why it is better idea to keep only one code handling common things like movement (of course unless you don't need to have some very specific and dedicated movement for some object). That way you can use it for many different cases withuot need to write it many times. For example you can use MovementController I created for almost any input from which you are able to calculate desired movement direction. That may be mouse input or buttons or joystick or navigation path or anything. It is also better to have that common code shared because it will keep consistency in your game and in case you want to change something in movement calculations you need to change it only once and everything using it will be updated instantly. If you would try to have different movement calculations per input type then you could make mistake when changing some code and for instance moving by buttons would be different than moving by mouse.
Ok, now lets move to another topic which is something new - rotation. You tried to use look_at()
method, but it doesn't work as you expected. That is because look_at()
only handle calculation of rotation to make some object facing some point. That would be more useful in top down game with tanks for example. You could use that to lock tank canon on some object so it will always aim correctly in its direction. In case of game you are doing it won't handle rotations as you would like to.
As I understand you have some sets of images for your character for different directions (lets say 8 directions) and you want to display proper image for any direction player is aiming with mouse. I don't know if there is maybe some method that will handle that in Godot autamatically (because I haven't worked a lot with 2D games), but that is something I guess you need to handle yourself.
Here is some exaple how it may be done:
func isometric_rotation(angle : float) -> int:
if(angle < 0):
angle += 360
return int((angle + 22.5) / 45.0) % 8
Above method will return values 0-7 depending on angle (in degrees). That values may be used as your direction to choose proper image to display. In that case it will return 0 for facing right and next numbers up to 7 for next positions counting angle clockwise.
Example how I used it to update sprite to make it "face" proper direction:
#Added that at the end of _physics_process method in KinematicBody2D
var lookDir = get_global_mouse_position() - global_position
$Sprite.frame_coords.x = (isometric_rotation(rad2deg(atan2(lookDir.y, lookDir.x))) + 6) % 8
I add 6 to value returned by isometric_rotation()
because 6th frame in my sprite sheet is facing right, so for 0 returned by isometric_rotation()
I need to use 6th frame.
Of course please notice that all these are only mathematical calculations. I assumed using atan2()
which will return values like 0 to 180 and -180 to 0, not tested if it will work for every angle you will supply (especially probably larger negative angles won't work properly, because there is only angle += 360
and not handling angle wrapping).
I hope that carified you mistakes you did in your code and with that help you will be able to experiment and find solution that suits the best for your game.