1

I am using Pygame and I have to adapt the following code thus the animation is also showing when the mouse is not moved (so there is no event). Can someone maybe help me please?

The "DDR.png" is attached below. I tried out several things, also by including the updates in the for loop of the main while-running-loop, but it didn't work yet. (You can also in-/decrease the velocity of the robot by pressing t or g).

import pygame
import math

class Envir:
    def __init__(self,dimentions):
        # colors
        self.black = (0, 0, 0)
        self.white = (255, 255, 255)
        self.green = (0, 255, 0)
        self.blue = (0, 0, 255)
        self.red = (255, 0, 0)
        self.yel = (255, 255, 0)
        # map dims
        self.height=dimentions[0]
        self.width=dimentions[1]
        # window settings
        pygame.display.set_caption("Differential drive robot")
        self.map=pygame.display.set_mode((self.width,self.height))
        # text variables
        self.font=pygame.font.Font('freesansbold.ttf',50)
        self.text=self.font.render('default',True,self.white,self.black)
        self.textRect=self.text.get_rect()
        self.textRect.center=(dimentions[1]-600,dimentions[0]-100)
        # trail
        self.trail_set=[]

    def write_info(self,Vl,Vr,theta):
        txt=f"Vl = {Vl} Vr = {Vr} theta = {int(math.degrees(theta))}"
        self.text=self.font.render(txt,True,self.white,self.black)
        self.map.blit(self.text,self.textRect)

    def trail(self,pos):
        for i in range(0,len(self.trail_set)-1):
            pygame.draw.line(self.map,self.yel,(self.trail_set[i][0],self.trail_set[i][1]),(self.trail_set[i+1][0],self.trail_set[i+1][1]))
        if self.trail_set.__sizeof__()>30000:
            self.trail_set.pop(0)
        self.trail_set.append(pos)

    def robot_frame(self,pos,rotation):
        n=30

        centerx,centery=pos
        x_axis=(centerx + n*math.cos(-rotation),centery + n*math.sin(-rotation))
        y_axis=(centerx + n*math.cos(-rotation+math.pi/2),centery + n*math.sin(-rotation+math.pi/2))
        pygame.draw.line(self.map,self.red,(centerx,centery),x_axis,3)
        pygame.draw.line(self.map,self.green,(centerx,centery),y_axis, 3)

class Robot:
    def __init__(self,startpos,robotImg,width):
        self.m2p=3779.52 # meters 2 pixels
        #robot dims
        self.w=width
        self.x=startpos[0]
        self.y=startpos[1]
        self.theta=0
        self.vl=0.05*self.m2p # meters/2
        self.vr=0.05*self.m2p
        self.maxspeed=0.02*self.m2p
        self.minspeed=0.02*self.m2p
        # graphics
        self.img=pygame.image.load(robotImg)
        self.rotated=self.img
        self.rect=self.rotated.get_rect(center=(self.x,self.y))
    def draw(self,map):
        map.blit(self.rotated,self.rect)

    def move(self,event=None):

        if event is not None:
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_w:
                    self.vl += 0.001 * self.m2p
                elif event.key == pygame.K_s:
                    self.vl -= 0.001 * self.m2p
                elif event.key == pygame.K_o:
                    self.vr += 0.001 * self.m2p
                elif event.key == pygame.K_l:
                    self.vr -= 0.001 * self.m2p
                elif event.key == pygame.K_t:
                    self.vr += 0.001 * self.m2p
                    self.vl += 0.001 * self.m2p
                elif event.key == pygame.K_g:
                    self.vr -= 0.001 * self.m2p
                    self.vl -= 0.001 * self.m2p
                elif event.key == pygame.K_x:
                    self.vr = 0
                    self.vl = 0

            self.x+=((self.vl+self.vr)/2)*math.cos(self.theta)*dt
            self.y-=((self.vl+self.vr)/2)*math.sin(self.theta)*dt
            self.theta+=(self.vr-self.vl)/self.w*dt

            self.rotated=pygame.transform.rotozoom(self.img,math.degrees(self.theta),1)
            self.rect=self.rotated.get_rect(center=(self.x,self.y))


# initialisation
pygame.init()

# start position
start=(200,200)

#dimentions
dims=(600,1200)

#running or not
running=True

# the envir
environment=Envir(dims)

# the robot
robot=Robot(start,"DDR.png",80)#0.01*3779.52
# dt
dt=0
lasttime=pygame.time.get_ticks()
# simulation loop
while running:
    # activate the quit button
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running=False
        robot.move(event)
    dt = (pygame.time.get_ticks() - lasttime) / 1000
    lasttime=pygame.time.get_ticks()
    pygame.display.update()
    environment.map.fill(environment.black)
    robot.move()
    environment.write_info(int(robot.vl), int(robot.vr), robot.theta)
    robot.draw(environment.map)
    environment.robot_frame((robot.x,robot.y),robot.theta)
    environment.trail((robot.x,robot.y))

The image "DDR.png":

enter image description here

Mark Rotteveel
  • 100,966
  • 191
  • 140
  • 197

1 Answers1

2

You have to split the move method. You need one method that handles the events and changes the motion vector and another method that moves the robot:

class Robot:
    # [...]

    def update(self,event=None):

        if event is not None:
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_w:
                    self.vl += 0.001 * self.m2p
                elif event.key == pygame.K_s:
                    self.vl -= 0.001 * self.m2p
                elif event.key == pygame.K_o:
                    self.vr += 0.001 * self.m2p
                elif event.key == pygame.K_l:
                    self.vr -= 0.001 * self.m2p
                elif event.key == pygame.K_t:
                    self.vr += 0.001 * self.m2p
                    self.vl += 0.001 * self.m2p
                elif event.key == pygame.K_g:
                    self.vr -= 0.001 * self.m2p
                    self.vl -= 0.001 * self.m2p
                elif event.key == pygame.K_x:
                    self.vr = 0
                    self.vl = 0

    def move(self, dt):

        self.x+=((self.vl+self.vr)/2)*math.cos(self.theta)*dt
        self.y-=((self.vl+self.vr)/2)*math.sin(self.theta)*dt
        self.theta+=(self.vr-self.vl)/self.w*dt

        self.rotated=pygame.transform.rotozoom(self.img,math.degrees(self.theta),1)
        self.rect=self.rotated.get_rect(center=(self.x,self.y))

Call update in the event loop and move in the application loop:

while running:
    # activate the quit button
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running=False
        robot.update(event)

    dt = (pygame.time.get_ticks() - lasttime) / 1000
    robot.move(dt)

    # [...]

I recommend reading How can I make a sprite move when key is held down.

Rabbid76
  • 202,892
  • 27
  • 131
  • 174