Reputation: 47
VIDEO < I'm trying to make the white rectangle curve slowly and smoothly towards the red rectangle and then stop but for some reason the white rectangle isn't curving right and its moving way to fast I want it to move smoothly and curve smoothly that the eyes can see and also alawys curve to the red rectangle is there a way i could change up my code and get it to work like that?
in my curvemove rect class I have a
self.yspeed = 0.05 self.xspeed = -0.5 self.gravity = -0.01 the x and y speed the rect will move in and the gravity effecting it
then on my redraw on the curvemove class
this is how my rect is moving if the key V is pressed then it should mave the self.move true after that it should run the code which curves the object
if keys[pygame.K_v]:
curve_move1.move = True
if self.move:
curve_move1.x += curve_move1.xspeed
curve_move1.y += curve_move1.yspeed
curve_move1.yspeed += curve_move1.gravity
# curve it towards the red rectangle
else:
curve_move1.move2 = True
class curvemove:
def __init__(self,x,y,height,width,color):
self.x = x
self.y = y
self.height = height
self.width = width
self.color = color
self.rect = pygame.Rect(x,y,height,width)
self.yspeed = 0.05
self.xspeed = -0.5
self.gravity = -0.01
self.move = False
def draw(self):
self.rect.topleft = (self.x,self.y)
pygame.draw.rect(window,self.color,self.rect)
# -------------- curve_move1 is our curving rectangle
if keys[pygame.K_v]:
curve_move1.move = True
if self.move:
curve_move1.x += curve_move1.xspeed
curve_move1.y += curve_move1.yspeed
curve_move1.yspeed += curve_move1.gravity
# curve it towards the red rectangle
else:
curve_move1.move2 = True
full code its all rectangles so you can test it out
import pygame
pygame.init()
# our window
window = pygame.display.set_mode((500,500))
pygame.display.set_caption("test map")
# our class
class curvemove:
def __init__(self,x,y,height,width,color):
self.x = x
self.y = y
self.height = height
self.width = width
self.color = color
self.rect = pygame.Rect(x,y,height,width)
self.yspeed = 0.05
self.xspeed = -0.5
self.gravity = -0.01
self.move = False
def draw(self):
self.rect.topleft = (self.x,self.y)
pygame.draw.rect(window,self.color,self.rect)
# -------------- curve_move1 is our curving rectangle
if keys[pygame.K_v]:
curve_move1.move = True
if self.move:
curve_move1.x += curve_move1.xspeed
curve_move1.y += curve_move1.yspeed
curve_move1.yspeed += curve_move1.gravity
# curve it towards the red rectangle
else:
curve_move1.move2 = True
white = 255,255,255
red = 205,0,10
curve_move1 = curvemove(250,400,50,50,white)
touched = curvemove(250,200,50,50,red)
# our game fps
fps = 60
clock = pygame.time.Clock()
# d redraw()
def redraw():
window.fill((0,0,0))
curve_move1.draw()
touched.draw()
# our main loop
run = True
while run:
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
keys = pygame.key.get_pressed()
if curve_move1.rect.colliderect(touched.rect):
curve_move1.move = False
redraw()
pygame.display.update()
pygame.quit()
I want a way to make this rect smooth curve towards the red rectangle not fast but normal this is my best try
Upvotes: 1
Views: 181
Reputation: 210909
The gravitational force must act in the direction of the target.
I recommend to use pygame.math.Vector2
for the calculations. Calculate the direction vector from the object to the target and scale it to the size of the gravitational force. Change the motion vector depending on gravity in each frame:
dir_vec = pygame.math.Vector2(target_pos) - self.rect.center
v_len_sq = dir_vec.length_squared()
if v_len_sq > 0:
dir_vec.scale_to_length(self.gravity)
self.speed = (self.speed + dir_vec) * self.friction
self.pos += self.speed
Minimal example:
import pygame
pygame.init()
class curvemove:
def __init__(self, x, y, height, width, color):
self.pos = pygame.math.Vector2(x, y)
self.color = color
self.rect = pygame.Rect(x, y, height, width)
self.speed = pygame.math.Vector2(-5.0, 0)
self.gravity = 0.5
self.friction = 0.99
def draw(self):
self.rect.center = (self.pos.x, self.pos.y)
pygame.draw.circle(window, self.color, (self.pos.x, self.pos.y), self.rect.width//2)
def update(self, target_pos):
dir_vec = pygame.math.Vector2(target_pos) - self.rect.center
v_len_sq = dir_vec.length_squared()
if v_len_sq > 0:
dir_vec.scale_to_length(self.gravity)
self.speed = (self.speed + dir_vec) * self.friction
self.pos += self.speed
window = pygame.display.set_mode((500,500))
pygame.display.set_caption("test map")
clock = pygame.time.Clock()
white = 255, 255, 255
red = 205, 0, 10
curve_move1 = curvemove(250, 400, 20, 20, white)
touched = curvemove(250, 200, 20, 20, red)
fps = 60
move = False
def redraw():
window.fill((0,0,0))
curve_move1.draw()
touched.draw()
run = True
while run:
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_v:
move = True
if event.key == pygame.K_r:
move = False
curve_move1 = curvemove(250, 400, 20, 20, white)
if (curve_move1.pos - touched.pos).length() < 10:
move = False
if move:
curve_move1.update(touched.rect.center)
redraw()
pygame.display.update()
clock.tick(fps)
pygame.quit()
exit()
Play around with the values of speed
, gravity
and friction
to get different effects.
e.g.:
self.speed = pygame.math.Vector2(-10.0, 0)
self.gravity = 1
self.friction = 0.95
e.g.:
self.speed = pygame.math.Vector2(-10.0, 0)
self.gravity = 1
self.friction = 0.91
Upvotes: 1