Amey-K27
Amey-K27

Reputation: 1

function not working as expected in pygame

I'm working on simple snake game in pygame. Issue I'm facing is when commented lines below are interchanged in Game class under play function. This lines suppose to draw snake (using for loop over array) and draw apple at certain location. As per my understanding order of this calls should not affect program in any way but when self.apple.draw() is called before self.snake.walk() suddenly apple images keeps wiping out of screen whenever it's coming back to main function after completing it's draw function. If I reverse order for this calls everything works. (Apology in advance if this is very basic question, but new to coding)

import pygame,time,random
from pygame.locals import *
SIZE=40

class Apple():
    def __init__(self,surface) -> None:
        self.parent_screen=surface
        self.image=pygame.image.load("resources/apple.jpg").convert()
        self.x=0
        self.y=0
    
    def draw(self):
        self.parent_screen.blit(self.image, (self.x, self.y))
    
    def move(self):
        self.x=random.randint(1,9)*SIZE
        self.y=random.randint(1,9)*SIZE

class Snake():
    def __init__(self,surface,length) -> None:
        self.parent_screen=surface
        self.block=pygame.image.load("resources/block.jpg").convert()   #size of block is 40*40
        self.x,self.y=0,0
        self.direction="down" 
        self.length=length
        self.x=[40]*length
        self.y=[40]*length

    def move_left(self):
        self.direction="left"
    
    def move_right(self):
        self.direction="right"
    
    def move_up(self):
        self.direction="up"
    
    def move_down(self):
        self.direction="down"
    
    def walk(self):
        for i in range(self.length-1,0,-1):
            self.x[i]=self.x[i-1]
            self.y[i]=self.y[i-1]

        if self.direction=="left":
            self.x[0]-=SIZE
        if self.direction=="right":
            self.x[0]+=SIZE
        if self.direction=="up":
            self.y[0]-=SIZE
        if self.direction=="down":
            self.y[0]+=SIZE
        self.draw()

    def draw(self):
        self.parent_screen.fill((110, 110, 5))
        for i in range(self.length):
            self.parent_screen.blit(self.block, (self.x[i], self.y[i]))
    
    def increase_length(self):
        self.length += 1
        self.x.append(-1)
        self.y.append(-1)

class Game():
    def __init__(self) -> None:
        pygame.init()
        self.surface=pygame.display.set_mode((400,400))
        self.snake=Snake(self.surface,5)
        self.apple=Apple(self.surface)
    
    def is_collision(self,x1,y1,x2,y2):
        if (x1==x2 and y1==y2):
            return True
        return False

    def display_score(self):
        font = pygame.font.SysFont('arial',30)
        score = font.render(f"Score: {self.snake.length}",True,(200,200,200))
        self.surface.blit(score,(100,100))
        pygame.display.flip()


    def play(self):
        self.snake.walk()       #This is the first line
        self.apple.draw()       #This is the second line
        pygame.display.flip()
        

        if self.is_collision(self.snake.x[0],self.snake.y[0],self.apple.x,self.apple.y):
            self.snake.increase_length()
            self.apple.move()

        for i in range(2, self.snake.length):
            if self.is_collision(self.snake.x[0], self.snake.y[0], self.snake.x[i], self.snake.y[i]):
                return False
        
        return True

    def run(self):
        running =True

        while running:
            for event in pygame.event.get():
                if event.type == KEYDOWN:
                    if event.key == K_ESCAPE:
                        running = False
                    if event.key == K_LEFT:
                        self.snake.move_left()

                    if event.key == K_RIGHT:
                        self.snake.move_right()

                    if event.key == K_UP:
                        self.snake.move_up()

                    if event.key == K_DOWN:
                        self.snake.move_down()

            if self.play()==False:
                break
            else:
                time.sleep(.5)
        self.display_score()
        #time.sleep(5)
if __name__=="__main__":
    game=Game()
    game.run()

Upvotes: 0

Views: 73

Answers (1)

Rabbid76
Rabbid76

Reputation: 210890

You must clear the screen before drawing any object, but not in the draw method of an object:

class Snake():
    # [...]

    def draw(self):

        # self.parent_screen.fill((110, 110, 5))   <--- DELETE

        for i in range(self.length):
            self.parent_screen.blit(self.block, (self.x[i], self.y[i]))
class Game():
    # [...]

    def play(self):
        
        self.surface.fill((110, 110, 5))         # <-- INSERT

        self.apple.draw()
        self.snake.walk()
        pygame.display.flip()

Upvotes: 1

Related Questions