Take this into consideration while following the tutorial in Godot4: 1. Kinematicbody2d is now characterbody2d 2. Move_and_slide() doesn´t work (because is build in or something), use move_and_collide() instead and change the speed to a smaller number 3. "Invalid get index 'normal' (on base: 'KinematicCollision2D)" to fix this change .normal to .get_normal() and the ball will bounce 4. .find_node() is not going to work, use .get_node() instead (also change the speed to a smaller number like 5)
@@guyug6940 The tutorial is made for an earlier version of godot. what I did, to finish this tutorial, is to simply download godot 3 and finish it in godot 3. was worth it as I was able to learn stuff. now I am doing clears 12h godot 4 video
Asking for more contents like this would be a steal for everyone who would pay for courses, but this guy, for this guy I would keep this video in loop to make him earn everything he deserves
@@welrdo1234 it works differently as it now uses 0 argument instead of 1. "Velocity" is preexistent now and it's made specifically for movement functions, check the documentation
@@xenosunbro Is the 'documentation' on their Github? I figured this out very quickly that they already had a pre-existing velocity variable or whatever because of the errors the engine was throwing haha! Figured out my own way of solving my own issue with the character model, just wondering where I can learn more about all the preloaded stuff that comes with the engine I suppose
This tutorial/course is so great. The explanations are so clean and also the visuals too. Almost everyone said it feels like a great Godot course and it really does. Pls make more Godot course-like tutorials like this, it really helps me to learn Godot and GDscript as a Beginner.
I've wasted so much time and money on GODOT tutorials that start off strong and then hit a huge off-putting snag halfway through. "CLEAR CODE" is a perfect name for your channel! As a game design instructor trying to curate the perfect tutorial playlists, I feel I've struck gold :) I'd be a big fan of your PYGAME tutorials too if it had an IDE with graphic layout editor and easy install like GODOT does.
You are the man who taught me Pygame, all for free with AMAZING quality. I would have had to learn Pygame and the basics of Godot for $50. Thank you for producing these amazing tutorials for free, keep it up!
For anyone who is confused why only the opponent is making Score but the player is not. heres the solution to fix it. Hey, so the problem in the code is that only the opponent score is updated, not the player score. So even if the player scores a goal, the opponent would get the point. To fix it, just remove opponent_score += 1 from score_achieved() and add it to on_right_body_entered() and add player_score += 1 to on_left_body_entered() and then you should be good :)
Hmm, strange, that Work on First try? Just don't do tell the func _on_CountdownTimer_timeout(): to the _on_left _on_right func, just let it be, you already have! (But still some other Bugs are there) 😉
@@ClearCode the ai i made for the pong is impossible to beat its wayy to accurate and also sometimes it slows down its speed to improve accuracy i guess you could say that, hre is the code i used func _ready(): Ball = get_parent().get_node("Ball")
In godot 4+ the collision is func _physics_process(delta): var collision: KinematicCollision2D = move_and_collide(velocity * SPEED * delta) if collision: var reflect = collision.get_remainder().bounce(collision.get_normal()) velocity = velocity.bounce(collision.get_normal()) move_and_collide(reflect)
I think that the coordinate system in game engines is like this, because if we analyze CRT TV, the cathode rays start from the upper left corner and sweep row by row from left to right, when a row ends it goes down a scanline below and repeats the process, when it reaches the end in the lower right corner, restarts. As the Atari 2600 worked directly with this, it seems natural to choose the coordinate origin in the upper left corner and the positive y axis downwards. In 1:07:11, this is modular aritmetic, basically the clock, 15 = 3 mod (12), 15 is 3 modulo 12, if you pick the number 15 and divides by 12, the remainder is 3. If you pick any integer number a -> a = n mod (2) -> n in {0, 1}, because if a is divisible by 2, your remainder is 0, otherwise is 1.
I just finished the course and WOW!! This has got to be the BEST way to learn godot 3. Thank you so much man. I almost quit game dev because I just couldn't learn but you actually made it simple enough to where I could understand and follow. I actually at one point tried a course that was from a real game dev teacher and I got to say, You LEGIT teach better than an actual SCHOOL TEACHER!! Thank you so much. You are the best!
Amazing, I did it. your instructions were clear and easy to follow, with the comments section for updated changes, and chat gpt to debug my codes, this was a great intro to using godot. I did some html, php and java 10+ years ago and have forgotten it all, so I was basically a noob and this tutorial turned me into pretty much a God, I am now a creator of worlds. Thank You
The invertion of the Y axis is a feature that has been inherited in graphics programming from history. Back in the day computers used CRT monitors that paint the picture on the monitor from top left to bottom right (several technical reasons why that is the simplest way to go about it). Since then graphics libaries have been using this as a standard and still do till this day. Engine builders simplely inherit this since this is only a small inconvenience for the user (and will be complex to correct).
Hello everyone, if you are new here, make sure that you know this is not a Godot 4 tutorial, as this was made before it was released. But most of everything is the same except some of the code is different.
For fixing the score issue, do the following: declare your score_achieved function with it accepting a variable and then pass an apporpriate variable if the player or opponent has scored. So: func score_achieved(assignScore): $Ball.position = Vector2(640,360) if assignScore == 1: OpponentScore += 1 else: PlayerScore += 1 Now all you to do is pass 1 or something else at your instance functions: func _on_Left_Goal_body_entered(body): score_achieved(0) func _on_Right_Goal_body_entered(body): score_achieved(1)
for people who got stuck on 39:00 min something due to move_and_slide() error, its because they changed it in godot4. now move_and_slide doesnt take any args but it does take velocity by default so you cant name your variable in the 6th line as velocity. just change it to something and remove args from move_and_slide(). dont forget to match the names in the if statement
Thanks for this! The tutorial was very clear and concise and the visuals explaining some concepts were also great. Thanks for this video i sincerely appreciate it.
Nice tutorial, just one thing you missed: The function score_archived has a bug. It will always trigger to update the score of the opponent, never the player since you refact it as it will only apply the score on OpponentScore :)
I fixed it by passing a string of the winner: score_achieved("opponent") Then pass the winner back into the score_achieved function: func score_achieved(winner): if winner == "opponent": OpponentScore += 1 if winner == "player": PlayerScore += 1
The origin of the coordinates being top left instead of bottom left in computer related stuff is usually attributed on the way display (used to ?) work. Where things are drawn on the screen from top left to bottom right. I know it was the case back in the 8bit era computer, do not know if it is still the case now. (then again I might be wrong) thank you for your work and a very nice and efficient tutorial.
Thank you man for the tutorial! Really helped me out understanding godot better! I also had a lot of fun coding and your video is amazing! you teach really really well!
Anyone seeing this lately, there are some changes to the paddle input code you should be aware of: as stated be others below, the characterbody2d replaced the kinematicbody2d. Nothing crazy. However the code he used for the func _physics_process(delta) for the paddle, wont work as intended, and you should not use a "move_and_collide" as a replacement as this is not the correct function. Here is the code I implemented and works with GOD4: extends CharacterBody2D var speed = 400 func _physics_process(delta): var velocity = Vector2.ZERO if Input.is_action_pressed("ui_up"): velocity.y -= 1 if Input.is_action_pressed("ui_down"): velocity.y += 1 if velocity != Vector2.ZERO: velocity = velocity.normalized() * speed self.velocity = velocity move_and_slide() Happy coding!
Thanks, that worked nicely. Now I'm struggling getting the opponent code to work, I'll see if this fix can be applied to that script. A pity they couldn't make Godot 4 backwards compatible.
I did get the opponent working eventually, but with some additional tweaking. I started adding functionality like a variable difficulty level. One thing I never did puzzle out, is sometimes the ball would stick to the player paddle and drag it across the screen. I had to bludgeon the program into obedience by constantly setting the y value of the player paddle. I still get the ball kind of sticking to the paddle for half a second before bouncing off. Not too often, so it's still playable. Anyway, here's the code I ended up with for the opponent with Godot 4. extends CharacterBody2D var speed = 340.0 var ball var difficulty = 40 func _ready(): ball = get_parent().get_node("Ball") func _physics_process(delta): var ballvelocity = Vector2.ZERO ballvelocity.y = get_opponent_direction() ballvelocity.x = 0 velocity = ballvelocity.normalized() * speed * (1 + Global.difficulty / 2) self.velocity = velocity move_and_collide(velocity * delta) func get_opponent_direction(): # Bit of wiggle room, only move the paddle if the ball is more than 25 pixels above or below if ball.position.x > 600 - Global.difficulty * 250: if abs(ball.position.y - position.y) > 25: if ball.position.y > position.y: return 1 else: return -1 else: return 0 else: return 0
If you can't get ColorRect to work properly, I saw in another tutorial that you can just change the background color by going to Project Settings -> Rendering -> Environment -> Default Color
1:09:09 It's pretty bad to do that way. You can use Vector2.UP, rotated by random amount of degrees and multiplied by speed. Here's my code: velocity = Vector2.UP.rotated(PI * rand_range(0, 2)) * speed I think that way is better, because it is more readable and simple
hi this is the first game I ever made in Godot, and your tutorial was very helpful and great and thank you other commenters for letting us know that certain things have changed like having to use characterbody2d and not kinematicbody2d, anyways there is one complaint I have, in the finished pong game with how the opponent ai is coded, in longer matches, it feels like the opponent is just aimlessly going up and down since it is following the ball and rarely ever stops, I understand is how the opponent is suppose to work by following the ball, but I wish I could understand how to make the opponent slider stop once the ball leaves within a certain x axis, mainly when the ball is on the player's side, and would begin to move once entering the x axis threshold again which would be about the opponents side of the level.
You can edit the opponent's code by adding another if statement in the get_opponent_direction(). Let's say you want the opponent to stop after the ball is on the player's side (so its x position is below the screen length, in my case it'd be 640: if abs(ball.position.y - position.y)>25: if ball.position.y > position.y: return 1 else: return -1 else: return 0 else:return 0 the function starts with "if ball.position.x>640" , which means the code below it (basically the opponent's movement) will be run only when the ball is on the opponent's side (if the ball is on the player's side the if statement will return 0, which is equal to no movement). Hope I helped
Love the tutorial man. I have a question. When I fullscreen my color rect, it kinda just disappears instead of covering the whole screen. Any idea of what I might've done to cause this issue?
I found a wrong thing. Check your score_achieved function. In that you give the opponent 1 score. So whatever you won, the opponent will get your scores. Anyway it a nice tutorial.
If anyone has a problem with the countdown label appearing every time you start the game, what I did is go to the CountdownLabel node in level and in the inspector go to visibility -> visible and turn that off so by default it is invisible
Really great video, I learned a lot! My only question is the custom font, when I opened the asset folder I didn't see anything for the font in there. edit: I decided to grab a custom font from Google Fonts, which is a great resource! Helped me learn by searching fonts out for myself
Wow!!! Man I didn't know that there were bounce() and move_and_collide() available. Previously, I did the collision of a ball with vectors. It takes me a whole 2 days to get ball collision functionality. I wish I had seen the video earlier. 😅
first off, amazing tutorial! i love the way you explain everything. i learned more in this tutorial then any other beginners tutorial on youtube. but i have a question hopefully you will have the time to answer. im not to familiar to github, and i downloaded the assets.zip , but i dont have the fonts. do you by chance know what i did wrong? thank you
I got up to the part with the top wall but the paddle doesnt stop when it hits the collider, it just passes through as if it wasnt there :( My player code is exactly the same, the collider on the player is basically perfect, i don't know what i'm missing EDIT: I had my "main scene" set to the "player" scene, i had to change it to the "level" scene to fix this, for anyone else who may get stuck here
There's only one in my version not consistent with your version and that's pretty good for me (on the first/startup match there isn't a count down, it's a 1 and the ball starts going). Still, pretty good that I have a working pong game now. I'm going to see if I can convert it to Breakout (player paddle on x-axis) all on my own.
Thanks for this tutorial!! it's been very helpful and easy to understand. I'm now trying to improve the game by adding some more stuff to it. I understand that the final detail of resetting the Player's position is an easy way to do and explain for beginners, but I'd like to know if there's a better way to avoid the Player from moving in the first place when it hits the ball at certain angles. Thanks again!!
Thank you for this nice video. I went through all of it. I am not sure if I missed something.. :\ In the final version i found a bug. When you hit the ball with one of the edges of the pedal, it changes it's angle. That would be okay. But sometimes this leads to a very strong angle and the ball takes long time to reach the other side of the field and will be always dodged by the opponent. This is strange. Maybe a solution would be, that the pedal only reflects collisions of the x axis, but not of the y axis. What do you think? That way it would prevent a second glitch: When the opponent could not fetch the ball, but was very close to it at one of the borders, the ball slides very slowly between the player and the wall till he finally is behind the pad. I fixed this by making the Collision Rectangle for the pedals very small.
Hey, I assume you are talking about the font I am using in the text overlay? It is called Louis George Cafe and is completely free, you can get it here: www.dafont.com/louis-george-caf.font
1:38:59 followed exactly as you do until here. Mine in score starts with 2 and not 0. Here i copy paste : extends Node var PlayerScore = 0 var OpponentScore = 0 func _on_Left_body_entered(body): $Ball.position = Vector2(320.1,200) OpponentScore += 1 func _on_Right_body_entered(body): $Ball.position = Vector2(320.1,200) PlayerScore += 1 func _process(delta): $PlayerScoree.text = str(PlayerScore) $OpponentScoree.text = str(OpponentScore) Do you have any idea why score keeps starting with 2 and no 0? i set variables to 0 but because of OpponentScore += 1 and PlayerScore += 1 it makes the score to both players to start with 2. Any idea how to fix it??? Btw great job making this tutorials keep up the good work.
Im using Godot 4.0 and cant get the ai working as move and slide doesnt take arguments anymore. could someone please help Edit: I got it working by using a move and collide function which does take arguments. Its hard to find documentation for Godot 4 still
Move_and_slide arguments are now just typed into velocity for simplicity, so the code is velocity=Vector2(0,get_opponent_direction())*speed move_and_slide() Move_and_collide can work too but I think it should only really be used if something happens after a collision
An issue I did notice with this approach is that the paddle sometimes moves along the X axis if the ball pushes it at an angle. I fixed this by clamping it but I wonder what's causing it
what is the difference between .pick_random() and [randi() % 2 ] and when and how should I use each one? How can I change the results of the quantity of numbers selected in each or even specify to not repeat numbers if I want it to randomly select more than 1?
for anyone wondering: pick_random returns a random element of the array regardless of its size. [randi() % 2] returns only element of index 0 or 1. You can use [randi() % your_array.size()] to get the same result as pick_random. If you want more than one element, just repeat the procedure as many times as you need, for example in a loop. If you don't want the same index twice, you have to store those picked in some array and check against them, there are also other methods. If you're fine with modifying the array, you could always shuffle() it and just pop_back() as many times as needed. Or make a duplicate first and then shuffle and pop.
37:57 When I try to set the velocity with speed, an error like this appears, Too many arguments for "move_and_slide()" call. Expected at most 0 but received 1. I use Godot ver 4.1.1, is there anyone who can help me? Thanks
Take this into consideration while following the tutorial in Godot4:
1. Kinematicbody2d is now characterbody2d
2. Move_and_slide() doesn´t work (because is build in or something), use move_and_collide() instead and change the speed to a smaller number
3. "Invalid get index 'normal' (on base: 'KinematicCollision2D)" to fix this change .normal to .get_normal() and the ball will bounce
4. .find_node() is not going to work, use .get_node() instead (also change the speed to a smaller number like 5)
unfortunately .get_normal() ends in the preview closing after the collision with no error message
thnaks
i changed .normal to .get_normal(), but the ball doesnt bouce, it just slides very slowly, does anyone know how to fix this?
@@guyug6940
The tutorial is made for an earlier version of godot. what I did, to finish this tutorial, is to simply download godot 3 and finish it in godot 3. was worth it as I was able to learn stuff. now I am doing clears 12h godot 4 video
Not all hero's wear capes. Thank you so much!
This feels like it is premium like I paid $20 for it but it's actually free. You are amazing and your tutorials are extremely good. Keep it up!
Asking for more contents like this would be a steal for everyone who would pay for courses, but this guy, for this guy I would keep this video in loop to make him earn everything he deserves
Important Note: if you're using Godot 4 then you should now that Kinematicbody2d has been changed to Characterbody2d.
Thank you, thought I was going crazy for a moment.
Move and slide works for characterbody2d?
@@welrdo1234 it works differently as it now uses 0 argument instead of 1. "Velocity" is preexistent now and it's made specifically for movement functions, check the documentation
@@xenosunbro Is the 'documentation' on their Github? I figured this out very quickly that they already had a pre-existing velocity variable or whatever because of the errors the engine was throwing haha! Figured out my own way of solving my own issue with the character model, just wondering where I can learn more about all the preloaded stuff that comes with the engine I suppose
You are a hero
I wasted 4 hours for a pong before I came here. And you made it golden in only 2 hours. Such easy and clean within this short time. Hats off !!
some youtube videos are such a dud aren't they, but these videos are worth the price if sold.
This tutorial/course is so great. The explanations are so clean and also the visuals too. Almost everyone said it feels like a great Godot course and it really does. Pls make more Godot course-like tutorials like this, it really helps me to learn Godot and GDscript as a Beginner.
This needs to be redone for Godot 4, I went through loops trying to figure out enemy ai!
Would you care to share it? I've been stuck for a while
@@looako same here
This video is amazing. I'm a Unity developer but having some trouble understanding Godot's workflow, this video explained it very well. Thanks again!
46:00 You could set up one static body. Name it Walls, and add 2 collision shapes to it, naming them CollisionTop and CollisionBottom.
I've wasted so much time and money on GODOT tutorials that start off strong and then hit a huge off-putting snag halfway through. "CLEAR CODE" is a perfect name for your channel! As a game design instructor trying to curate the perfect tutorial playlists, I feel I've struck gold :) I'd be a big fan of your PYGAME tutorials too if it had an IDE with graphic layout editor and easy install like GODOT does.
You are the man who taught me Pygame, all for free with AMAZING quality. I would have had to learn Pygame and the basics of Godot for $50. Thank you for producing these amazing tutorials for free, keep it up!
Thanks for the video. Love the clean and clarity aspect of it. 🥰
For anyone who is confused why only the opponent is making Score but the player is not. heres the solution to fix it.
Hey, so the problem in the code is that only the opponent score is updated, not the player score. So even if the player scores a goal, the opponent would get the point.
To fix it, just remove opponent_score += 1 from score_achieved() and add it to on_right_body_entered() and add player_score += 1 to on_left_body_entered() and then you should be good :)
Yeah, I realised afterwards and felt very silly :)
Hmm, strange, that Work on First try?
Just don't do tell the
func _on_CountdownTimer_timeout():
to the
_on_left
_on_right
func, just let it be, you already have!
(But still some other Bugs are there) 😉
@@ClearCode the ai i made for the pong is impossible to beat its wayy to accurate and also sometimes it slows down its speed to improve accuracy i guess you could say that, hre is the code i used
func _ready():
Ball = get_parent().get_node("Ball")
func _physics_process(_delta):
move_and_collide(Vector2(0,get_opponent_direction()) * speed)
func get_opponent_direction():
if abs(Ball.position.y - position.y) > 25:
if Ball.position.y > position.y: return 1
else: return -1
else: return 0
i am using godot 4 pls helppp
why is this dude so good at tutorials, not just this one, literally all of his tutorials are like this
The animations and the annotations on the screen really helps us to learn!
Thanks for your effort!
In godot 4+ the collision is
func _physics_process(delta):
var collision: KinematicCollision2D = move_and_collide(velocity * SPEED * delta)
if collision:
var reflect = collision.get_remainder().bounce(collision.get_normal())
velocity = velocity.bounce(collision.get_normal())
move_and_collide(reflect)
it gives me errors any idea why? : Move functions do not work together with 'sync to physics' option.
Thank you so much
I think that the coordinate system in game engines is like this, because if we analyze CRT TV, the cathode rays start from the upper left corner and sweep row by row from left to right, when a row ends it goes down a scanline below and repeats the process, when it reaches the end in the lower right corner, restarts. As the Atari 2600 worked directly with this, it seems natural to choose the coordinate origin in the upper left corner and the positive y axis downwards. In 1:07:11, this is modular aritmetic, basically the clock, 15 = 3 mod (12), 15 is 3 modulo 12, if you pick the number 15 and divides by 12, the remainder is 3. If you pick any integer number a -> a = n mod (2) -> n in {0, 1}, because if a is divisible by 2, your remainder is 0, otherwise is 1.
I just finished the course and WOW!! This has got to be the BEST way to learn godot 3. Thank you so much man. I almost quit game dev because I just couldn't learn but you actually made it simple enough to where I could understand and follow.
I actually at one point tried a course that was from a real game dev teacher and I got to say, You LEGIT teach better than an actual SCHOOL TEACHER!!
Thank you so much. You are the best!
You are a miracle Sir in teaching.... Love the way you teach.... Stay Blessed❤❤❤❤❤❤
Amazing, I did it. your instructions were clear and easy to follow, with the comments section for updated changes, and chat gpt to debug my codes, this was a great intro to using godot. I did some html, php and java 10+ years ago and have forgotten it all, so I was basically a noob and this tutorial turned me into pretty much a God, I am now a creator of worlds. Thank You
Easing into godot, and the simplicity of this tutorial helped tremendously compared to other tutorials.
Transitioning from using C# to GD Script and your Tutorials are awesome dude!
Very high quality stuff! Glad i stumbled across this as im interested in both python and godot. Perfect!
Amazing tutorial , you did a lot of works and carefully explain simple
The invertion of the Y axis is a feature that has been inherited in graphics programming from history. Back in the day computers used CRT monitors that paint the picture on the monitor from top left to bottom right (several technical reasons why that is the simplest way to go about it). Since then graphics libaries have been using this as a standard and still do till this day. Engine builders simplely inherit this since this is only a small inconvenience for the user (and will be complex to correct).
37:07 Amazing work with that! It was confusing for me to press down and go up
Hello everyone, if you are new here, make sure that you know this is not a Godot 4 tutorial, as this was made before it was released. But most of everything is the same except some of the code is different.
You explain everything so nicely!!!!!!! Keep it up!
I didn't know pong would be complicated enough to come back to beginner tutorials 3 months later and learn this much new stuff
Thank you so much I love the feeling of accomplishment. All of the other tutorials didn’t work but this one did!
For fixing the score issue, do the following:
declare your score_achieved function with it accepting a variable and then pass an apporpriate variable if the player or opponent has scored. So:
func score_achieved(assignScore):
$Ball.position = Vector2(640,360)
if assignScore == 1:
OpponentScore += 1
else:
PlayerScore += 1
Now all you to do is pass 1 or something else at your instance functions:
func _on_Left_Goal_body_entered(body):
score_achieved(0)
func _on_Right_Goal_body_entered(body):
score_achieved(1)
still the same problem sadly always the player score is 1 at the begging
for people who got stuck on 39:00 min something due to move_and_slide() error,
its because they changed it in godot4. now move_and_slide doesnt take any args but it does take velocity by default so you cant name your variable in the 6th line as velocity. just change it to something and remove args from move_and_slide(). dont forget to match the names in the if statement
Neat tutorial. Very well explained for a total gamedev newbie.
I followed along with this on godot 4. A little frustrating but debugging from the version differences taught me a lot too.
Thanks for the tutorial. I work if Godot for 2 years and i still learned a bunch of things that will help me so much! keep the great work :)
This is an amazing tutorial. Very well explained and planned out. I will be sharing this with anyone that wants to start with Godot. Thank you!
This is the best free software Ive seen. Respect.
You are a Greater Teacher!
Better than the most Godot Tutorial or in General!
Have you more Videos like this? ☺️
And almost Finish!
But you don't tell, how to do it on a Game Icon and can Play outside the Engine, like all Games...
Still very Good!
Insane Content for only 1730 Subs.
He Does deserve more subs that is true
I guess that's why he went so quickly from 1730 to... more than 20k !
absolutely brilliant video that set a mark for how tutorials should be made
thank you very much
You're a good teacher, also you helped me to start developing in Godot.
I was looking for a good Godot video and I found one! New sub man!
It's a very good tutorial the editing is very good and you explained everything very well. Keep doing what you do.
Thanks for this! The tutorial was very clear and concise and the visuals explaining some concepts were also great. Thanks for this video i sincerely appreciate it.
Nice tutorial, just one thing you missed: The function score_archived has a bug. It will always trigger to update the score of the opponent, never the player since you refact it as it will only apply the score on OpponentScore :)
I had a problem with this as well, I had to make a copy of L and R paddles, and sadly that breaks what he was doing, better luck next time.
I fixed it by passing a string of the winner:
score_achieved("opponent")
Then pass the winner back into the score_achieved function:
func score_achieved(winner):
if winner == "opponent": OpponentScore += 1
if winner == "player": PlayerScore += 1
Hey, love your awesome tutorials, please keep it up!! :)
thank you so much :)
So good I'm going to re-watch for a second time.
man your explanations i just loved it !. keep the viedos coming and you will reach good number of subs for sure.
The origin of the coordinates being top left instead of bottom left in computer related stuff is usually attributed on the way display (used to ?) work.
Where things are drawn on the screen from top left to bottom right.
I know it was the case back in the 8bit era computer, do not know if it is still the case now.
(then again I might be wrong)
thank you for your work and a very nice and efficient tutorial.
Amazing tutorial!!!
I like the part where you say "there are a couple ways to do this"
Another Godot tutorial! Thanks for the videos you are awesome bro!!!
Man, this tutorial was perfect, in fact, it stops being a tutorial and becomes a complete Godot class, you gained a new subscriber, thank you
This truly is clear and easy to understand, Thanks a lot!
Thank you for such comprehensive lesson!
Better than ANYTHING on udemy. Thank you.
Thank you man for the tutorial! Really helped me out understanding godot better! I also had a lot of fun coding and your video is amazing! you teach really really well!
Loved the tutorial! Super Well made and easy to understand. I learned a lot, Thank you!
k-on!
Keep up the good work man!, you earned my sincerest thumbs up
Awesome tutorial thanks for sharing! Well explained and thorough. Much appreciated!
Bro it’s very intimidating! I’ve been slacking on it for a month now. The symbols are very confusing. You have to train your mind to
Anyone seeing this lately, there are some changes to the paddle input code you should be aware of: as stated be others below, the characterbody2d replaced the kinematicbody2d. Nothing crazy. However the code he used for the func _physics_process(delta) for the paddle, wont work as intended, and you should not use a "move_and_collide" as a replacement as this is not the correct function. Here is the code I implemented and works with GOD4:
extends CharacterBody2D
var speed = 400
func _physics_process(delta):
var velocity = Vector2.ZERO
if Input.is_action_pressed("ui_up"):
velocity.y -= 1
if Input.is_action_pressed("ui_down"):
velocity.y += 1
if velocity != Vector2.ZERO:
velocity = velocity.normalized() * speed
self.velocity = velocity
move_and_slide()
Happy coding!
Thanks, that worked nicely. Now I'm struggling getting the opponent code to work, I'll see if this fix can be applied to that script. A pity they couldn't make Godot 4 backwards compatible.
I did get the opponent working eventually, but with some additional tweaking. I started adding functionality like a variable difficulty level. One thing I never did puzzle out, is sometimes the ball would stick to the player paddle and drag it across the screen. I had to bludgeon the program into obedience by constantly setting the y value of the player paddle. I still get the ball kind of sticking to the paddle for half a second before bouncing off. Not too often, so it's still playable. Anyway, here's the code I ended up with for the opponent with Godot 4.
extends CharacterBody2D
var speed = 340.0
var ball
var difficulty = 40
func _ready():
ball = get_parent().get_node("Ball")
func _physics_process(delta):
var ballvelocity = Vector2.ZERO
ballvelocity.y = get_opponent_direction()
ballvelocity.x = 0
velocity = ballvelocity.normalized() * speed * (1 + Global.difficulty / 2)
self.velocity = velocity
move_and_collide(velocity * delta)
func get_opponent_direction():
# Bit of wiggle room, only move the paddle if the ball is more than 25 pixels above or below
if ball.position.x > 600 - Global.difficulty * 250:
if abs(ball.position.y - position.y) > 25:
if ball.position.y > position.y: return 1
else: return -1
else: return 0
else: return 0
1:07:16 There is also an alternative method called "[-1, 1].pick_random()" which is the same function as "[-1, 1].[randi() % 2]"
Excellency in teaching skill.
Amazing tutorial. Keep up the good work. Thank you.
note for godot 4:
velocity is an inbuilt variable, you dont need to define it
Great tutorial, thank you so much! I learned so much.
When I make my first 1$ from game making, I'm subbing to your patreon!
Thanks ❤ from India🇮🇳
If you can't get ColorRect to work properly, I saw in another tutorial that you can just change the background color by going to Project Settings -> Rendering -> Environment -> Default Color
1:09:09 It's pretty bad to do that way. You can use Vector2.UP, rotated by random amount of degrees and multiplied by speed. Here's my code: velocity = Vector2.UP.rotated(PI * rand_range(0, 2)) * speed
I think that way is better, because it is more readable and simple
Awesome tutorial!
What a great video! Could you tell me what I should do if I want to increase the speed of the ball over time?
Thanks you , for the tutorial is simple and well explained please continue doing tutorials
2 hours for a pong tutorial... Im in :D
dude, thank you very much. You helped me a lot. I have already subscribed to your channel and will see your other videos about Godot. Thank you again
Superb course! Thank you a lot! :D
hi this is the first game I ever made in Godot, and your tutorial was very helpful and great and thank you other commenters for letting us know that certain things have changed like having to use characterbody2d and not kinematicbody2d, anyways there is one complaint I have, in the finished pong game with how the opponent ai is coded, in longer matches, it feels like the opponent is just aimlessly going up and down since it is following the ball and rarely ever stops, I understand is how the opponent is suppose to work by following the ball, but I wish I could understand how to make the opponent slider stop once the ball leaves within a certain x axis, mainly when the ball is on the player's side, and would begin to move once entering the x axis threshold again which would be about the opponents side of the level.
You can edit the opponent's code by adding another if statement in the get_opponent_direction(). Let's say you want the opponent to stop after the ball is on the player's side (so its x position is below the screen length, in my case it'd be 640:
if abs(ball.position.y - position.y)>25:
if ball.position.y > position.y: return 1
else: return -1
else: return 0
else:return 0
the function starts with "if ball.position.x>640" , which means the code below it (basically the opponent's movement) will be run only when the ball is on the opponent's side (if the ball is on the player's side the if statement will return 0, which is equal to no movement). Hope I helped
A very understandable tutorial.
Love the tutorial man. I have a question. When I fullscreen my color rect, it kinda just disappears instead of covering the whole screen. Any idea of what I might've done to cause this issue?
Hey, you probably use a node2d as root node. Change it to a plain node and it should work
@@ClearCode yup I did do that. Thanks, it works now
Thank you! Great descriptive video!
Great video! Note the custom font is not in the assets zip.
I found a wrong thing. Check your score_achieved function. In that you give the opponent 1 score. So whatever you won, the opponent will get your scores. Anyway it a nice tutorial.
If anyone has a problem with the countdown label appearing every time you start the game, what I did is go to the CountdownLabel node in level and in the inspector go to visibility -> visible and turn that off so by default it is invisible
I already know how to use godot and etc, but i am here just for the quality and content
This was fantastic. Thanks for creating the first thing that I ever made in Godot!
Really great video, I learned a lot! My only question is the custom font, when I opened the asset folder I didn't see anything for the font in there.
edit: I decided to grab a custom font from Google Fonts, which is a great resource! Helped me learn by searching fonts out for myself
Wow!!! Man I didn't know that there were bounce() and move_and_collide() available. Previously, I did the collision of a ball with vectors. It takes me a whole 2 days to get ball collision functionality. I wish I had seen the video earlier. 😅
first off, amazing tutorial! i love the way you explain everything. i learned more in this tutorial then any other beginners tutorial on youtube.
but i have a question hopefully you will have the time to answer. im not to familiar to github, and i downloaded the assets.zip , but i dont have the fonts. do you by chance know what i did wrong? thank you
You can find the font file in the Pong8 - Score.zip file
I got up to the part with the top wall but the paddle doesnt stop when it hits the collider, it just passes through as if it wasnt there :( My player code is exactly the same, the collider on the player is basically perfect, i don't know what i'm missing
EDIT: I had my "main scene" set to the "player" scene, i had to change it to the "level" scene to fix this, for anyone else who may get stuck here
i iwas just stuck there
thanks!
THANK YOU BROO I WAS GETTING SO MAD THANK YOUUUU
man i love your explanation
1:58:45 - I recommend using the ceiling function, ceil(), instead.
There's only one in my version not consistent with your version and that's pretty good for me (on the first/startup match there isn't a count down, it's a 1 and the ball starts going). Still, pretty good that I have a working pong game now. I'm going to see if I can convert it to Breakout (player paddle on x-axis) all on my own.
Thanks for this tutorial!! it's been very helpful and easy to understand. I'm now trying to improve the game by adding some more stuff to it. I understand that the final detail of resetting the Player's position is an easy way to do and explain for beginners, but I'd like to know if there's a better way to avoid the Player from moving in the first place when it hits the ball at certain angles. Thanks again!!
Thank you for this nice video.
I went through all of it. I am not sure if I missed something.. :\
In the final version i found a bug. When you hit the ball with one of the edges of the pedal,
it changes it's angle. That would be okay. But sometimes this leads to a very strong angle and the ball takes long time to reach the other side of the field and will be always dodged by the opponent.
This is strange.
Maybe a solution would be, that the pedal only reflects collisions of the x axis, but not of the y axis. What do you think?
That way it would prevent a second glitch:
When the opponent could not fetch the ball,
but was very close to it at one of the borders,
the ball slides very slowly between the player and the wall till he finally is behind the pad.
I fixed this by making the Collision Rectangle for the pedals very small.
True. & thanks for the fix!
also, when the bug happens it can often get stuck for a bit and register multiple collisions, and play the sound many times.
Thank you for the tutorial!
hi!
thanks a lot for your tutorials!
what font do you use 0:45?
looks nice
Hey, I assume you are talking about the font I am using in the text overlay? It is called Louis George Cafe and is completely free, you can get it here: www.dafont.com/louis-george-caf.font
@@ClearCode thanks!
1:38:59 followed exactly as you do until here. Mine in score starts with 2 and not 0. Here i copy paste :
extends Node
var PlayerScore = 0
var OpponentScore = 0
func _on_Left_body_entered(body):
$Ball.position = Vector2(320.1,200)
OpponentScore += 1
func _on_Right_body_entered(body):
$Ball.position = Vector2(320.1,200)
PlayerScore += 1
func _process(delta):
$PlayerScoree.text = str(PlayerScore)
$OpponentScoree.text = str(OpponentScore)
Do you have any idea why score keeps starting with 2 and no 0? i set variables to 0 but because of OpponentScore += 1 and PlayerScore += 1 it makes the score to both players to start with 2. Any idea how to fix it??? Btw great job making this tutorials keep up the good work.
Im using Godot 4.0 and cant get the ai working as move and slide doesnt take arguments anymore. could someone please help
Edit: I got it working by using a move and collide function which does take arguments. Its hard to find documentation for Godot 4 still
Jesus, you saved me some time
Move_and_slide arguments are now just typed into velocity for simplicity, so the code is
velocity=Vector2(0,get_opponent_direction())*speed
move_and_slide()
Move_and_collide can work too but I think it should only really be used if something happens after a collision
An issue I did notice with this approach is that the paddle sometimes moves along the X axis if the ball pushes it at an angle. I fixed this by clamping it but I wonder what's causing it
what is the difference between .pick_random() and [randi() % 2 ] and when and how should I use each one? How can I change the results of the quantity of numbers selected in each or even specify to not repeat numbers if I want it to randomly select more than 1?
for anyone wondering: pick_random returns a random element of the array regardless of its size. [randi() % 2] returns only element of index 0 or 1. You can use [randi() % your_array.size()] to get the same result as pick_random.
If you want more than one element, just repeat the procedure as many times as you need, for example in a loop. If you don't want the same index twice, you have to store those picked in some array and check against them, there are also other methods. If you're fine with modifying the array, you could always shuffle() it and just pop_back() as many times as needed. Or make a duplicate first and then shuffle and pop.
great course
37:57 When I try to set the velocity with speed, an error like this appears,
Too many arguments for "move_and_slide()" call. Expected at most 0 but received 1.
I use Godot ver 4.1.1, is there anyone who can help me? Thanks
var direction = Input.get_axis("Move_up","Move_down")
velocity = transform.y * direction * speed
move_and_slide()
@@fallengod5305 Thanks man!