In this video I show you how to use a number of realistic physics features in your python code and PyGame games! By creating a ball class with easy to change parameters we are able to see how modifying these various parameters can impact our object's movements!
Having realistic bouncing as well as friction and collision and the ability to throw objects with realistic physics is a great way to make your game feel very real and understanding the code behind it is a great way to get better at both python code in general and creating games with the PyGame module!
Don't forget to leave a like on the video, subscribe to the channel and leave a comment letting me know what you'd like to see more of in the future!
TIMESTAMPS: 00:00 Intro and Project Description. Physics in Pygame! 03:01 Setting up the PyGame framework 06:15 Draw Outer Walls for the Game 09:49 Setting up a Class in python for Balls 17:24 Applying Gravity to Python Objects with Pygame 20:05 Making Pygame Objects Bounce on Floor Collision 28:40 Selecting a Python Object and getting it to follow the Mouse! 36:40 Releasing and Throwing Objects with the Mouse in Pygame! 43:20 Handle Pygame Object Collision with Walls and Apply Friction! 50:54 Summary, Outro and Showcase! Thanks!
what's up you guys welcome back to the
channel in today's video I'm going to
show you how to incorporate some
realistic physics into your pie game
games using python code
[Music]
so I'm really excited to bring you guys
this tutorial obviously we do a lot of
Pi game content on this channel and a
lot of full uh games where we build them
out start to finish and sometimes I sort
of gloss over elements like Collision
detection or gravity in those videos and
then also sometimes I don't really uh
incorporate things like friction or
bouncing off the walls so I just want to
make this a generic tutorial on how to
incorporate several elements of
realistic uh physics into your pie game
games so we're going to start with
gravity which is probably the easiest
element here we're going to create a
class for balls so that we can create
some different uh balls like you can see
on screen that have different properties
like different amounts of lost energy
and velocity when you drop them and then
also we're going to take a look at how
to kind of grab and throw which you've
seen me do on the screen here I can grab
any of these balls and sort of throw
them in any direction I want and you'll
notice it that actually how hard I throw
the ball directly correlates with how
fast it moves in the X and Y Direction
so we're going to take a look at
throwing objects and then you can
clearly see they bounce off of the walls
they bounce off the floor I do let them
go through the ceiling but using this
tutorial you'll know how to make them
bounce off the ceiling too if you so
choose and one thing you may not have
noticed because it's a little more
subtle but they actually slow down in
both the X Direction and the y direction
and so to do this we're going to
simulate essentially an imperfect bounce
right like a minor loss of energy like
you'd get if you dropped a golf ball or
a bouncy ball on the ground you would
see the ball not bounce all the way back
to its uh original starting spot so
we're going to make that something to
play around with and then we're also
going to incorporate kind of a
coefficient of friction so that when the
balls are rolling along on the floor
they slow down because they're also
imperfect there's friction there so we
have a lot of Concepts to cover we're
going to do them one at a time and I'm
gonna make the chapters titled each
concept as we go so if you don't really
need gravity you just want to know how
to handle like throwing an object then
you can go there if you just want to
know how to handle friction you can go
there be sure to let me know in the
comments below what you think of this
video what you'd like to see more of on
the channel don't forget to leave a like
on the video and I have been doing a uh
just started a kind of silly personal
Channel that's still engineering
Concepts but less education more fun
that'll be linked below as well and of
course the code you see in this tutorial
will be at a link in the GitHub also
Below in the description section of this
video so without any further Ado let's
get right into the tutorial
so as always and it shouldn't be any uh
surprise at this point but you want to
import Pi game and do pygame dot in it
as your first two lines in any PI game
game uh import Pi game if you don't have
the package installed just run pip
install pie game and then we're going to
pick a width of one thousand one
thousand and a height of 800 we're going
to store those in variables because
we'll use them at a few points for like
Collision detection and stuff and then
let's just set up that our screen is
going to be pygame dot display dot set
mode like that and then in square
brackets our width variable and our
height variable okay so that is just the
basic defining of the outer screen
dimensions in a pi game and then let's
say that we want to run it an FPS of 60
so 60 frames per second and we're going
to initialize a pi game timer that we're
going to use to control the speed of the
game by doing
pygame.time.clock with a Capital C just
like like that and then we'll have a
section below that where when it comes
time as we're building this we'll put
like a game variables Library down here
but we're not going to fill that out
just too much because now we're going to
set up the main game Loop okay and to do
this we're just going to create a
variable called run and we're going to
set it equal to true and then we're
going to do a few basic things every
single Loop of the game so while run
while that Loop is true first thing
we're going to do is timer.tick at our
frame rate and then let's just screen
dot fill with whatever color you want
the background to be I'm going to use
black because it makes all of the
colored balls that I'll use um kind of
Pop against the black background
but you can put whatever uh whatever
um background color or image you want
right there and then a basic thing kind
of the last step in setting up the game
Loop is for event in
pygame.event dot get and so this command
is how we get everything happening with
our computer on the mouse the keyboard
anything else it's for event in
pygame.event.get and we need to check if
this specific one if event DOT type is
equal to pygame dot quit all caps like
that and that is checking to see if the
red x button in the toolbar is pressed
so if that's pressed then we want run to
be set equal to false just like that and
that's all we're going to do for game
handling now we will come back to that
when we're taking a look at like
throwing balls but so then just come
outside of your event handling and add
pygame.display.flip like this and then
outside of the while loop we want
pygame.com it so this means
as long as we haven't hit the quit
button run will not be false so we are
going to flip everything onto the screen
draw it onto the screen while run is
true but then once we press the quit
button run will be equal to false and it
will execute this line of code which
will end the program so this should be
all we need to do to get a black
rectangle of 1000 pixels wide 800 pixels
tall just like that and now we can start
building things out in our game which is
great and the first thing I want to do
it's not the most glamorous thing we're
going to do in this tutorial
but uh it's important is I just want to
draw some walls so it's really clear
where the edges are I know I use dark
mode and Pie charm um and we're so we're
going to use the walls just kind of as
visual indication when we hit things so
uh this is going to be really fast bear
with me and it's kind of important and
it honestly it's a stylistic uh
Improvement so we'll just Define draw
walls here and it's going to be a quick
easy little wall drawing function and
it's just going to be our left wall is
going to be pygame dot draw dot line and
we're going to put it on the screen and
I'm gonna make it a white line so it
really pops against a black background
and then this is going to be the left
wall so we want to start at position
zero zero so X and Y are zero and then
it's a line so we need to just give it
start and stop points and it's going to
go X so still zero along the left Edge
but all the way down to the full height
of our screen and then uh instead of
defining uh instead of typing like a 10
for wall thickness like four times for
each wall I'm going to put that in a
variable so that this is kind of the
first thing where if you want to play
around with your game settings and make
it look different you don't have to have
that B10
but I'm going to be using that you know
four times here so it's just a little
faster if I decide I want to change it
later to put it in a variable so then
we're going to have a left wall a right
wall a top wall and a bottom wall and I
got to fix that indentation there we go
and a bottom wall and you have to be
very careful about your start and stop
points for all of these because like the
top wall will be starting at
um oh did I type that wrong nope
starting at the same spot so 0 0 but
then it's going to go across the screen
to the full width of the screen and then
it's going to be
um still at the top so zero whereas like
the bottom one will start and stop at
the full height of the screen which is
at the very bottom and go across it from
zero to the full width so uh then the
right wall will be at
width the whole time so all the way on
the right edge of the screen the whole
time and I think I'm missing maybe a
closed parenthesis on one of these let's
see
um
yeah I am missing a parentheses so let's
just uh close it out I guess that should
do it
um actually I think the issue is that I
shouldn't have a starting parenthesis
over there so
I think we're okay
yeah no errors all right sorry about the
distraction I promised this was gonna be
easy while list equals
Left Right top bottom okay so
um honestly I don't think anything we're
gonna do in this tutorial will
specifically require you to go through
this entire list
um but it is nice to have somewhere
really easy to find that you're drawing
all of the walls so that if you have a
point where you want to just check for
any Collision in the game you can and
now if we boot that up you're gonna see
there's this nice white frame around the
game board and that's what we'll kind of
use for detecting if we've hit the left
or the right or the bottom or if we've
gone off screen to the Top If we decide
to do anything for that
and now we're going to get into the
absolute meat of this project which is
um we want to make code that works for
any object we drop into it so we want to
make a class essentially where we only
have to write the code once to determine
how a ball is going to interact in our
game that's sort of the essence of like
game engines and physics engines is
these laws and this code that you write
apply to any shape that you draw in and
so this class that we're going to make
is going to be a ball class so let's
come up here and it's a ball with a
capital B and then that's really just a
syntactic thing but it's the correct way
to define a class in Python and then the
first thing we're going to do is Def
underscore underscore init underscore
underscore and then we give it all of
the variables that it's going to see
um that it needs to have as part of the
class so if you think about what could
fully Define a ball it would be its X
position its y position uh it's radius
its color
um how much mass it has if we were doing
like a collision calculation for
conservation of momentum
um so then uh of retention so this is
something we're going to talk about when
we talk about loss in bounces but so
like every time a ball bounces it's not
perfectly returning to the destination
that it just was unless you want it that
way so we'll create a calculatable
retention variable that you can change
and play around with and then it'll need
a speed in the X and the y direction and
then it will give each ball a unique
ball ID you can call this whatever you
want
um but we're going to give each ball an
ID and then you have to do this
interesting thing for
um classes in Python where if you want
to use these variables that you just
passed in inside your sub functions in
the class you need to do a self dot
basically the same variable name for
every variable you can make it different
if you want like you could say self.red
equals radius if you're going to
remember what rad stands for
but it's pretty easy to just go through
and say self dot whatever is equal to
every
um variable so we're just going to do
that quickly here self.masses Mass self
dot retention is retention retention
there we go self dot y uh speed is equal
to Y speed self dot X speed equal to X
speed
and self dot cell self Dot
ID is equal to ID okay and so we're
going to use all of these things in our
subsequent functions to sort of uh
handle all of this code that we would
want so that we only need to Define it
once and if we want to make 10 balls or
50 balls we're really saving time
because we've written driver code that's
going to tell all balls how to interact
in our world here with the physics rules
we give it so first thing and easiest
thing that we'll want to do
is gonna be dry okay so we're gonna say
let's make it visible that'll kind of be
how we do all of our troubleshooting so
we're making this uh class function now
and uh essentially you'll see maybe you
saw when I did Define and then a
function called Draw uh it populates
with the parameter self that's
essentially saying let me inherit all of
these variables so that I can reference
them in here so any function in a class
is typically going to have self passed
in as well as extra parameters if you
need to pass them in we don't here so
we're going to have a new variable that
we'll call self.circle and you have to
instantiate all your variables in this
init function so it's okay to just leave
it essentially as a blank and then
overwrite it as soon as we do the Define
draw and what we'll do is self.circle
is equal to pygame dot draw dot circle
like this and then we're going to put it
on the screen and then we're going to
make it self.color so whatever color it
was passed in and then for its uh Center
Point it'll just be self.xpose comma
self dot y pause
uh y position so that's going to be it's
kind of X and Y Center and then for its
radius just self dot radius okay just
like this so that is a fully defined
Circle it's uh goes on screen this color
this position and this radius okay
so that is all we have to do to draw it
um which is great but we haven't
actually defined any instances of this
class right so let's go ahead and do
that to talk about creating an instance
of a class so let's just say we want to
make ball one and we want to be equal to
ball with a capital B that's our class
so we need to give it an X starting
position and I'll say 50 a y starting
position I'll also say 50. a radius will
say 30 so it's easy enough to see
a color will make this one blue and then
a mass we're going to make it 100 we're
not going to use that for a little while
here a retention so this is interesting
let's just go ahead and say 0.9 right so
90 of its bounce value will it retain
and that'll be useful once we get
gravity and bouncing Incorporated
okay so we have 0.9 and then we need to
give it a x speed and Y speed I believe
and then we said ID and so
this is our first ball we'll just make
it ball one okay and you'll notice I
actually instantiated it outside I
called it initialized it outside of the
main game Loop and that's because we're
going to just Define the initial ball
once but then we're going to change a
lot of those initial values with our
functions inside the game Loop so all
you need to do out there is call the
origination of the of the ball if you
actually were to do that inside your
game Loop even if you tried to change
some of those variables it would get
overwritten okay so then down here we'll
come down here and just say ball one dot
draw okay so now what I should have
because we haven't built any movement
into the game yeah I have this light
blue uh I guess regular royal blue uh
ball on the screen at position 50 50
radius 30 okay so that's kind of cool
but uh just that on its own not that
impressive because it would take uh far
less time and less lines of code than we
just put in to just
pygame.draw Circle Blue radius 30 right
there right but here's where it starts
getting a little more powerful is if we
were to make ball two and now it's going
to be at 500 500 that it starts this
will have a radius of 50 and we'll make
this one this bigger one uh green and
we'll give it a mass of 300 again just
picking a value a lower retention value
of 0.8 for this one
and then 0 0 and an ID of two okay if I
come down here and I say Ball 2 dot draw
just with basically defining the ball
here and then calling its draw function
here what you'll see is we now get a
second ball on the screen so this is
great right we have ball one and ball
two now let's take a look at
incorporating gravity into our class so
that we don't have to do some code that
we repeat for uh every single ball it's
just going to be built into the sort of
logic underlying the ball class it knows
if I'm a ball and I'm hanging in air
then I need to fall right
so let's define this function that we'll
call check gravity all right basically
check my position in space and determine
what I should do based on that and so
what we'll do is we'll start by saying
if self dot y pause so that variable we
called in the init function if self.y
pause is less than meaning uh in air
basically so the way Pi game coordinates
work is the higher numbers are closer to
the bottom of the screen so if your game
is 800 pixels tall pixel 0 in the y
direction is actually at the very top
and 800 is at the very bottom so the way
we check if our ball is in air we check
if the Y position is less than the
height of the screen but then we also
need to say minus self dot radius
because we want to check if the edges
are colliding with the bottom which
basically means that the center point so
the Y position plus the radius has to be
on top of the height but then the way
wall walls work is we also have to
incorporate that wall thickness we
defined divided by two because we
defined a line that's exactly at the
bottom of the screen but then we made it
10 wide which means that there's
actually five pixels above it and five
pixels below it so we're just going to
use wall thickness minus two but
essentially if y position is less than
all all of those combined that means we
are in air okay so that means that we
need self dot y speed and we need to
essentially increase our speed which is
actually going to be plus equals so that
means add to myself a value of what well
we need to make a game variable that
we'll call gravity okay so we'll come up
to our game variables section
and we'll define gravity here and this
is kind of the first opportunity to do
some guess and check and see what like
works for your game the way you want it
to work I think that a gravity of 0.5 is
very good for an application running at
60 FPS it feels fairly realistic fairly
similar to what you'd expect to see but
feel free to increase this decrease this
see how that kind of changes the bounces
um
but so basically moving on from that we
have this gravity variable but what do
we do if we are not in air okay so if
we've hit the ground essentially then we
want to say else and then we'll check if
self dot y speed is greater than a new
variable we're going to have to make
that'll be basically saying bounce stop
okay so
um this is a pretty important step
because
um we don't want it to do infinite tiny
little bounces forever we kind of want a
variable that's just going to say you
know what these bounces have gotten
negligible and rather than have this
silly looking infinitely bouncing and
decreasing thing on the screen we're
gonna say you know what if my total
speed is less than 0.3 I'm just gonna
stop okay and again guess and check on
all of these game variables that's why
we're putting them there so you can play
around with what makes sense for you
but what you'll see is this will
actually be nice it'll give us a point
where the ball will just stop bouncing
okay so if my y speed as I'm going down
is still great enough that I want to
continue bouncing then I want to set
self dot y speed equal to again my
previous value which was self.y speed y
speed there we go
but now times negative one so this is
flipping the direction so if it was just
falling down it's going to start going
upward but then we want to incorporate
that retention value we made right so
make sure when you generate your balls
if you're doing whatever physics
application you're doing similar to this
make sure that that retention value is
between 0 and 1. so anything more than
one and you'd actually be generating
energy on every bounce I guess you can
do that
um but so like a value of one here would
mean we're getting a perfect bounce
every time it'll take off upward with as
much speed as it was coming downward
with that's not how real life works so I
always use values between like 0.5 for a
really bad bounce or like 0.9 for a
solid bounce
um okay but so then we need to do one
more check because we just sent it
upward but we also need to check else if
and now the absolute value of self.y
speed because remember it's directional
so it could be up or down and if it's
less than or equal to bounce stop then
we want self.y speed to just be equal to
zero and this is actually really
important uh extra step because we could
have a situation here where self.y speed
is less than Bounce stop but it's less
than Bounce stop
um because it's like negative 20 right
which is is actually quite a bit of
speed it's just heading upwards
and so this will catch that scenario and
it'll only actually stop a bounce if the
absolute value of y speed has gotten
slow enough to stop a bounce okay so I
hope I didn't lose you guys there I hope
this makes sense what you should see now
is just we boot this up we get two balls
bouncing with gravity oh we didn't move
it yet you do have to call a function so
like this nice check gravity function we
just wrote we have to come down where we
do our ball dot draw and we have to call
these functions so we need to say ball
one dot check gravity and then Ball 2
dot check gravity so you when you
generate a new function you just need to
remember to call that function and I'm
going to stop forgetting things now I
promise
um if you're going to update something
inside of these functions you need to
essentially return it so that you can
remember what your previous speed was
okay so we need to return y speed from
this self.y speed from this so that we
can keep a running tally of what our
self.y speed is and we also have to
update our position based on the Y speed
so
um let's come back down here and uh so
now ball one dot y speed will be equal
to
checking gravity for ball one so ball
one dot y speed is equal to this and
ball 2
dot y speed is equal to this but it's
great we're increasing the speed but
we're not moving the ball yet so uh
that's actually something I'm very
surprised I forgot to do but we'll go
ahead and make another function that
we'll call ball one dot update
underscore position and ball 2 dot
update underscore position okay so let's
go ahead and take a look at creating the
not just the check gravity function but
the update
underscore position function okay
uh and so I promise it's actually
gravity is going to be the hardest thing
for us to do because we're setting up a
lot of initial things here that don't
specifically refer to gravity they refer
to our game writ large but uh this is
still a really important step
so for updating the position what we
want to do is say self dot y
position plus equals self dot y speed
and it's okay here to say that we're
going to do self dot X position plus
equals self.x speed as well we just
obviously haven't done anything with X
speed yet so you don't really have to
worry about that too much just yet but
now fingers crossed uh cross your
fingers for me too but when we boot this
up we should get these balls yeah you
can see them falling and bouncing and
hopefully you can see this ball will
stop bouncing unless I made the
retention too high it might be exactly
at 0.5 oh that's so frustrating all
right let's go to the green ball uh and
let's make it a 0.9 retention all right
let's check that out we may have had a
situation where that ball was going to
bounce exactly to 0.5 because of
rounding forever all right but so you
see these guys are bouncing a whole
bunch of times and there yeah the green
ball actually stopped bouncing and now
our blue one is still bouncing but very
small and now it's come to a complete
rest so this is great and you can play
around with some some of these things
like retention at this point now so if I
were to make a blue 0.5 and green point
three you'll just see two balls that
just barely bounce I mean they right
they they go upwards with 30 and 50 of
the speed they just had so this is kind
of why values of like 0.8.9 are nice for
balls
um but so that's great for gravity and
just again to reiterate the power of
what we're doing here by putting it in a
class and how you can make your games
really robust by putting your objects in
classes is you write this code once and
as long as you write a set of behaviors
that would need to be true for any of
these objects you get to just repeat it
and we can Define another ball simply by
just putting in here uh the same
instantiating like line of code so
purple
um this one I guess can make it can be
200 it doesn't really matter we'll make
it 0.8 and then this is going to be ID3
so just by doing that and then making
sure that you add in the ball 3 dot draw
okay ball three dot update
position and then ball three
dot y speed is equal to ball three dot
check gravity okay so just by those
simple lines of code I get this other
ball this pink ball now that's also
bouncing with its own set of rules and
it's still obeying gravity and all of
that jazz just because we correctly
built a class that can handle infinite
objects essentially infinite objects
okay so that is going to be the summary
on gravity now we're going to move into
I think the best next thing to do will
be essentially throwing your objects so
how do we select a ball and then how do
we essentially get the vector that the
mouse is moving in so we know what
general direction to move the ball in
okay and so to do this we're going to do
a little bit more in our event handling
so we're going to make a new if event
DOT type and this time we're going to
check if the mouse is pressed so
pygame.mouse button down all caps like
that and then what we want to do is we
basically want to check if the ball was
selected based on the balls uh collision
with a point so to do that we're going
to make a new function and we'll say if
ball 1 dot check underscore select
um
for our event dot position so we'll want
to pass into the checked select function
we're about to make the position of the
mouse when it clicked okay
um and so one thing to note that I think
is important here you can change this if
you want I just want to essentially
check this code if the event dot button
is equal to one so this is the left
keyboard click uh the left Mouse click
so you can make this for any of the
buttons if you want I just want to say
if the left mouse was clicked then I
want to check my balls so if ball 1 or
Ball 2 dot check select and this will
just be a true false to check whether or
not we have clicked on that specific
ball so we'll do it for each ball or
ball three dot check underscore
select boy I'm having a hard time typing
the word select and then pass event dot
position in for all of them okay so I
obviously have some pretty big text on
right here so that everyone can
see all of the code but hopefully uh
that doesn't confuse or throw an error
let's see it might because it doesn't
like my backslash
all right so uh there's gonna be a
little bit off screen here but it's just
an or bald three dot check select and
what we're going to do if any of those
are true then we'll make an active
selection variable equal to True okay so
just something that says hey you have
selected a ball and then we'll make a
counter to this check which is if
event.type is equal to pygame dot mouse
button up and we need some code that is
basically going to say if the event dot
button was equal to one again
then I want to release whatever I had
actively selected but also we need to
essentially set that check select
variable back equal to uh false and so
to do that we can just say 4 J in range
or for Iron Range is fine for I in range
and then the length of uh all of our
balls so this is something new that we
can use for a lot of different smart
stuff but if we come up here and we make
a balls list
um I know I'm saying balls a lot in this
video but if we make a list of all of
the balls that we've created in our game
and we have something that we want to
check for all of them we can say for I
in range the length of that list of
balls that we just created then uh why
don't we just run that check select so
balls at I dot check select that this
function let's run it with a point that
couldn't possibly be true so
um it's okay to put like a nonsense
value in here you could write another
function that's basically like release
select but since we're going to be
writing a check select function to see
if the mouse is grabbing somewhere in
collision with that ball all we might as
well just write a function that's going
to be impossible because it has negative
coordinates and so I think I need to
stop talking about the check select
function until we write the check select
function so let's go ahead and do that
it's not going to be very difficult it's
just a few lines of code to say within
the ball class hey I've just been told I
need to check and see if the mouse
selected me so Define check underscore
select we've been calling it
and then itself and here's our first
example of passing in an additional
parameter and this one is going to be
the position so the x and y coordinate
of the mouse when it just clicked the
button all right and so here we'll make
a variable called
self.selected and we'll say it's equal
to false okay so we're going to say by
default I'm going to assume that I'm not
selected and then Force this function to
prove me wrong and so obviously when we
want to make a new function a new
variable inside a class make sure you
instantiate in the beginning as well but
now what we'll say is okay self.selected
starts out false but then if self dot
Circle so the circle that I'm already
drawing if it has this dot Collide point
which is a pygame built-in Collision
detection tool with the position so the
event position that the mouse just
clicked on then we want to make self dot
select did
equal to True okay so this is uh great
this is saying now I have a way of
checking whether or not I am selected
and then we're going to return that self
dot selected value to basically tell the
outside world yes I got a ball or no I
still haven't gotten a ball okay and so
what we need to do is actually with this
um Mouse position we need to come into
our update position and say well if I am
selected so if I'm not selected then I
want to keep doing what we've already
defined so if not self dot selected
then I want to keep doing these things
but what should we do if we have been
selected
well we're still updating the X and Y
position but this means that we're
dragging the ball around with us
so
self.exposition and self.y position need
to be equal to Mouse coordinates and so
what that means is we need to go back
into the outside world and we need to
make our Mouse coordinates something
that we pass into our update uh our
update position function so that we
basically still pass in the X and Y
coordinates of the mouse and when we are
selected we want to update the position
to whatever position the mouse is
currently dragging us to and this is
actually surprisingly simple so let's go
ahead and go back into our main game
Loop and let's just say right under our
screen.fill
that will make a variable called Mouse
coords and it's going to be equal to
pygame dot mouse dot get position okay
so it really is just as simple as that
and then we come down to our update
position function and we're going to
pass in the mouse chords to all three of
those so I might be skipping some steps
I hope I'm not if I am we'll fix it but
hopefully this will let me drag a ball
around yeah with the mouse which is
awesome but what you'll see when I
release it is uh it kind of does some
funky business it doesn't really
um it doesn't really grasp uh proper
modes of movement and the reason for
this is you can take something that was
on its way down really close to about to
hit the ground and you can drag it way
up in the air so like if you can catch
something with a pretty high downward
velocity and then drag it up it's going
to fall really fast so uh to handle this
we essentially need to figure out what
to do when we release it from a
selection so
um
what we want to do now is uh make some
new code in the check gravity function
check gravity function that will handle
the difference between what to do when
selected and not selected so if not
selected then we want again everything
we already defined that's great you're
you're moving the way we want you to
move and everything else so keep it up
but if we are selected else
if we have been selected then we need to
sort of reset these and so initially
let's just say self.x speed is zero self
dot y speed is zero okay so this just
means I've grabbed the ball reset the
downward speed so that if I grab this
green ball right before it hits the
ground and I drag it up here it'll start
falling from zero again so essentially
it resets the memory of this
um which is a cool it's a cool way to
essentially drag something and drop
something which is a good start but what
you'll notice is if I like Wing
something if I like throw it really hard
it does not stop uh it does not get
momentum because I moved the mouse
really fast it does not get thrown
essentially it just gets sort of moved
um
so to do that we want to come up with a
way of figuring out what the actual push
from the mouse is so X push and Y push
are going to be these variables I want
to make next that essentially are going
to be calculated by the motion Vector of
the mouse so to do this this x push and
Y push we have to come up to our game
variables and we have to make a new
track
positions of mouse to get movement
Vector right and I say Vector because it
needs to have speed and direction so
Mouse trajectory is going to be
essentially an empty list of uh
positions all right and then what we're
going to do is once we boot up the game
right below getting the mouse
coordinates
so right underneath Mouse cords get
position we are going to get uh the
position and add it to our Mouse
trajectory list so Mouse underscore
trajectory
dot append and then the mouse
coordinates and again you can play
around this next bit if you want but
what I'm going to say is if the length
of my mouse trajectory list has gotten
above 20 so that's going to be one third
of a second right if you're running at
60 frames per second then if your list
has gotten to 20 you know what your
mouse did in the last third of a second
which is enough to know the direction it
was moving and the speed it was moving
at when you release the ball feel free
to extend this out if you want it to be
the whole previous second you could make
it a 60 but basically what I'm going to
say is I don't want this to be longer
than 20 and I want essentially a first
in first out mechanism so I'm going to
pop whatever the first position is in my
list and then I'm going to say x push
and Y push so those variables I'm
looking to get from the mouse are going
to be equal to calculate the motion uh
let's just say Vector so it's Crystal
Clear okay and this is not one that gets
done inside the ball class this is sort
of like draw walls it's just its own
free-floating uh function here so what
we'll do is we'll say Define and then
calc underscore motion underscore vector
and we're going to return we won't call
them push inside of this function we'll
call them y speed and X speed but what
we're going to do is we're going to say
x speed equals zero and Y speed equals
zero to start just because if the list
is empty like the very first time we
boot it up this won't work so what we'll
say is if the length of mouse trajectory
is greater than 10. so that means
essentially it's half populated at least
so the fastest you can throw a ball
would be in the first uh one-sixth of a
second that should be enough time but uh
you can play around with these values if
you need to what I want to do is
actually pretty simple I'm not going to
care about like all the data in the
middle I'm going to take the position
the mouse was in
at the first frame in my list
water break and then the position that
the mouse was in at the last frame in my
list I'm going to divide it by 20. so
actually I think what I'll say is
greater than 19. so that means fully
populated then what I want to do is say
that the mouse trajectory at position
minus one zero
minus the mouse trajectory at zero zero
uh and then divide it by the length of
the list so divided by length of mouse
trajectory and actually 10 is fine
because this will sort of scale if
there's only 10 in the list it'll divide
by 10 if it's uh 20 in the list it'll
divide by 20. so
let's keep it that way
and let's do the same thing for the Y
coordinates just all these second zeros
need to be ones and so Mouse trajectory
again is a list of coordinates so every
individual index in that list is going
to have an X in the zero index and then
a y in the one index
and then the first position that the
mouse uh was in so essentially a third
of a second ago will be in position zero
and then the last position our mouse got
to will be in minus one so this is one
from the back and that's all we need to
do to calculate the X and Y speed that
our mouse was moving at when we uh threw
the ball so now we should be calculating
this x push and Y push but the Savvy
viewer will remember let's see what
happens here if I grab this and throw it
upward
you'll see that Ball's not coming back
um the the Y movement actually looks
really good but we have not done
anything to essentially handle X
Collision off of the side walls so we
need to do that and the best place to do
that is going to be in our check gravity
and update function our update position
functions okay so let's go ahead and
actually we're going to leave update
position alone because that's pretty
much golden and simple right there and
check gravity is sort of a more
complicated place it should probably be
called check collisions or check
movement but I called it check gravity
so we've gone too far alrighty let's
come down below our uh else absolute
value essentially but still inside of
the if not selected and we'll say if now
self.x position and we're going to do
some checking similar to what we did for
floor Collision so if the X position is
less than the combination of my the
combination of my radius
plus the wall thickness divided by two
this means that I have collided with the
left wall okay
but to be really robust
we want to put in here an and
self.x speed is negative because if the
X speed is positive that means I'm
already going in the right direction so
I don't want to flip it again like in
the case where you get a very high speed
and then you flip Direction on collision
you might not clear that collision with
your very first scan even by flipping
the speed so you would want to make it
to where you only flip direction if
you're moving in the wrong direction in
other words if you collide with the left
wall but you're trying to move right it
doesn't make sense to invert the X
Direction here okay so then we'll say or
these are going to be the two scenarios
where we might need to
invert a x Direction it's basically
collision with the left wall or
collision with the right wall and that
would be if our X position is greater
than the way it minus self dot radius
minus half the wall thickness so wall
thickness divided by two just like that
and self dot X speed
greater than zero just like that okay
and so if either of these two things are
true then we want to set self dot X
speed
equal to its inverse so basically times
equals self.x feed come on Pete think
times
equals so it's set equal to itself times
negative one and then just a cool way to
make it slow down on collisions is that
same retention value that we already
made Let's slow it down in the X
direction as well so this is going to
handle left and right bounces it's
basically going to flip the direction
and bounce you off the left and right
walls but with a speed that is
proportional to how fast it was going
and losing a little bit of that speed
due to the retention Factor okay
now what we want to do is we want to say
unless similar to the Y direction if
self dot X speed is less than that
bounce stop variable that we said is
like hey I'm not going fast enough to
bounce off the wall then I want to set
self.x speed equal to zero okay and now
let's go ahead and take a look at what
to do with friction okay so let's say
we're still moving in the X Direction
but the Y has stopped bouncing so if
self dot y speed is equal to is equal to
zero and self.x speed is not equal to
zero so we haven't stopped moving in the
X Direction
if self Dot X speed is greater than zero
then we want to slow it down using
friction so self dot X speed minus
equals self
dot friction okay and I know I'm just
throwing friction at you but we're here
in the X Direction movement scenarios
we've just handled bouncing off the
walls so we may as well incorporate
uh how to slow the ball down if it's no
longer rolling so we have this new self
dot friction
friction equals uh friction okay so we
want to pass in something else after ID
that we'll call friction and I'm not
going to lie to you guys to get a smooth
Pleasant roll you actually want friction
to be like a very small value so I have
found when I defined my balls and again
you can
Define it however you want but I found
0.02 and 0.03 to kind of Be The Sweet
Spot for slowing down while rolling
you'll see here the purple ball
well you'll probably see here the purple
ball once it stops bouncing vertically
is going to Coast to a stop much slower
than even feels natural for like a ball
um
excuse me but so again the friction
variable is just another thing you can
play with to sort of see how it uh moves
these balls but what we're saying is if
the X speed and the Y speed are
um
are
X speed and Y speed are not zero then we
want to slow down the X speed but it's
not as simple as checking to see if the
X speed is greater than zero we also
need an else
um L if self dot X speed is less than
zero right because our velocity has
Direction it matters which way it's
moving if it's super large and negative
it still needs to get slowed down by
friction it's just now self.x speed plus
equal self dot friction so every time it
hits a wall the value of x speed is
going to change between positive and
negative and so we need to continually
decrease it and bring that value closer
to zero with friction and we do that
with these four lines of code okay
and so that was a bit of a crash course
in friction and we certainly didn't use
like the official coefficient of
friction formula but that's kind of
boring you guys would have been bored by
that anyways so let's go ahead and boot
this up and take a look at what we've
just done
because we actually haven't run this
since we had wall collision and you can
see that looks pretty good the wall
Collision looks really good actually and
what you hopefully can tell uh just from
the screen recording is the faster I
actually just chucked it off screen
there it is the faster I move my mouse
the uh faster it moves when I release it
so I can take like the blue ball here
and I can give it a really gentle toss
or I can take the purple ball and I can
just Chuck it upwards and it's gonna
come back but it's gonna take a while
all right
and now you can see this green ball is
slowing down it's still bouncing
vertically um but it is slowing down I
think it had a really good retention and
now it's going to stop bouncing
vertically and friction is going to get
to close to a stop pretty quick same
with the purple ball there okay so we
have friction which is awesome we have
bouncing which is terrific uh we have
Wall Collision we have gravity and we
have the ability to grab these balls and
throw them uh all over the screen so
this may have seemed like a little bit
of a hectic tutorial I haven't really
shown you how to build a game per se
just a lot of game mechanics but if you
fully understand every concept that
we're doing in this tutorial you're
going to be able to build some very
realistic physics movements in your
games and it also means you're getting a
pretty good grasp on what's possible
using python classes which is so
important for any object-oriented
programming language to understand the
power of classes which is basically
generating objects which is sort of the
whole point of object oriented
programming as I understand it so let's
go ahead and throw one more ball in here
let's just make a red one just to again
reiterate
how powerful this thing is
um all that code that we've written to
just immediately be able to apply it to
another ball we'll say this one's going
to be red and let's make it our largest
ball yet let's give it a pretty bad
retention point seven zero and zero for
initial X and Y speeds uh id4 and then
for friction let's say like 0.1 so the
red ball you should see going to Coast
basically to a stop as soon as uh it
stops bouncing vertically and the reason
we only apply friction while we are not
bouncing vertically is because when you
are leaving the ground there's not as
much air friction as there is between
like floor and ball so it's just a
preference thing if you really want to
figure out like an Air drag friction uh
for while it's in the air you know
totally go ahead but it sounds like you
already know a thing or two about
physics so maybe you don't need this
beginner physics tutorial
but do
just by going in every place that we
call the balls and we add our Ball Four
to all of the logic event
dot pause
event dot pause and actually you you
should probably go through and do a for
Loop similar to this for the event.pause
and essentially set active select equal
to true if it's uh true so
you could do that
um we're pretty late in this tutorial
it's been a full hour and I just wanted
to cover some basic physics Concepts
let's check out uh our red ball see if
we add everything so you can see it
actually you know what a fun experiment
would be I'm going to drop them all from
the same uh y position so why of let's
say uh 100 no let's say 50 just to get a
lot of height I'm going to drop them all
from 50 and looking at the difference
between 0.7 0.8.9 and uh I'll make the
blue 1.95 so the blue one should bounce
forever the green one probably second is
long uh red will stop quite a bit faster
so if I boot these all up you'll see
they bounce pretty much in sync but you
can see the height difference as well as
the frequency difference between when
they come up and come down so there's
really no comparison like if you start
tweaking these retention values you're
going to see sort of the physics effect
you're hoping to get and it actually it
applies for X Direction too so like even
if I throw the red ball pretty hard in
the X Direction every time it hits that
wall it slows down in the X Direction a
lot and then as soon as it stops uh
going vertically it's really done and
you see our blue ball was still bouncing
from the initial uh drop and then if I
Chuck it horizontally like that it is
going to bounce in almost that exact
same shape for a really long time
because it's maintaining so much of its
energy
so the core concept and if I were to do
a continuation of this project if at
some point in the future you guys want
to see like Advanced physics be sure to
let me know in the comments below but
what's going on with both retention and
friction as well as gravity
is essentially
conservation of energy and conservation
of momentum so if we were to put in ball
to ball Collision here as well so if any
ball were to hit any other ball we would
want it to essentially know how to react
using realistic momentum and energy
that's some pretty high level of
mathematics and physics simultaneously
solving the conservation of energy and
conservation of momentum is not a
trivial task it is actually some pretty
serious math which would require some
pretty serious programming so I'm
definitely willing to do something like
that if there's enough interest just let
me know about it and if anything in this
tutorial confused you or you have
questions or you'd like to see a
follow-up on anything let me know about
in the comments below as well I will get
back to you as soon as I can I
appreciate all the support on YouTube
please don't forget to subscribe there's
a patreon link in the description below
as well if you're feeling charitable you
want to become a super supporter of the
the channel Help Me Grow help me do new
projects thank you so much for watching
if you stuck it out to the end I don't
know why I'm still rambling but leave a
like on the video I'll see you next time
good luck with your projects thanks for
watching bye