[Pygame] laggy enemy kill

[Pygame] laggy enemy kill

Postby metulburr » Thu May 09, 2013 11:18 pm

when you hit an enemy it lags for a second or so. For some reaason i think it is upon creation of the new enemy that it lags as it happens when you first run it. I am not sure why it lags though?

Code: Select all
import pygame
import sys
import math
import random

def image_from_url(url):
    try:
        from urllib2 import urlopen
        from cStringIO import StringIO as inout
    except ImportError:
        from urllib.request import urlopen
        from io import BytesIO as inout
    myurl = urlopen(url)
    return inout(myurl.read())

class Projectile:
    limit = 3
    def __init__(self, loc):
        self.surf = pygame.Surface((5,10)).convert()
        self.surf.set_colorkey((255,0,255))
        self.surf.fill((255,255,255))
        self.rect = self.surf.get_rect()
        self.rect.center = loc
        self.mask = pygame.mask.from_surface(self.surf)
        self.speed = 8

class Enemy:
    count = 3
    def __init__(self, start_loc):
        link = 'http://i1297.photobucket.com/albums/ag23/metulburr/spaceship_enemy3_zpscfeb13bf.png'
        self.orig_image = pygame.image.load(image_from_url(link)).convert()
        self.orig_image = pygame.transform.scale(self.orig_image, (40,80))
        self.orig_image.set_colorkey((255,0,255))
        self.image = pygame.transform.rotate(self.orig_image, 180)
        self.mask = pygame.mask.from_surface(self.image)
        self.rect = self.image.get_rect()
        self.rect.center = start_loc
        self.bullets = []
        self.speed = 2
        self.is_hit = False
       
    def pos_towards_player(self, player_rect):
        '''get new coords towards player'''
        c = math.sqrt((player_rect.x - self.rect[0]) ** 2 + (player_rect.y - self.rect[1]) ** 2)
        try:
            x = (player_rect.x - self.rect[0]) / c
            y = (player_rect.y - self.rect[1]) / c
        except ZeroDivisionError:
            return (self.rect.x, self.rect.y)
        return (x,y)
       
    def destroy(self):
        ...
       
    def update(self, player_rect):
       
        if self.is_hit:
            self.destroy()
        if not self.is_hit:
            #move enemy towards player
            new_pos = self.pos_towards_player(player_rect)
            self.rect.x, self.rect.y = (self.rect.x + new_pos[0] * self.speed, self.rect.y + new_pos[1] * self.speed)
           
           


class Player:
    def __init__(self, start_loc):
        self.speed = 4

        link = 'http://i1297.photobucket.com/albums/ag23/metulburr/spaceship2_zps095c332a.png'
        self.orig_image = pygame.image.load(image_from_url(link)).convert()
        self.orig_image = pygame.transform.scale(self.orig_image, (40,80))
        self.orig_image.set_colorkey((255,0,255))

        self.image = pygame.transform.rotate(self.orig_image, 180)
        self.mask = pygame.mask.from_surface(self.image)
        self.rect = self.image.get_rect()
        self.rect.center = start_loc

        self.bullets = []

    def move(self, x, y):
        self.rect[0] += x * self.speed
        self.rect[1] += y * self.speed


class Control:
    def __init__(self):
        self.screensize = (800,600)
        self.screen = pygame.display.set_mode(self.screensize)
        self.screenrect = self.screen.get_rect()
        self.clock = pygame.time.Clock()
        self.player = Player((0,600))
        #self.enemy = Enemy((800,0))
       
        self.enemies = []


        self.mainloop()

    def mainloop(self):
        run = True
        while run:
            self.screen.fill((0,0,0))

            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    run = False
                elif event.type == pygame.KEYDOWN:
                    if event.key == pygame.K_SPACE:
                        if len(self.player.bullets) <= Projectile.limit:
                            self.player.bullets.append(Projectile(self.player.rect.center))

            self.update()
            pygame.display.flip()
            self.clock.tick(60)

    def update(self):
        self.keys = pygame.key.get_pressed()
       
        for obj in self.enemies:
            obj.update(self.player.rect)
           
       
        #make new enemies
        print(len(self.enemies))
        if len(self.enemies) <= Enemy.count:
            self.enemies.append(Enemy((random.randint(1,800),-100)))

        if self.player.bullets:
            for obj in self.player.bullets:
                self.screen.blit(obj.surf, obj.rect)
                obj.rect[1] -= obj.speed

                #did obj move off screen
                if obj.rect[1] < 0:
                    self.player.bullets.remove(obj)
                #did obj hit enemy rect
                for enem in self.enemies:
                    if obj.rect.colliderect(enem.rect):
                        offset_x =  enem.rect.x - obj.rect.x
                        offset_y =  enem.rect.y - obj.rect.y
                        #did object hit enemy mask
                        if obj.mask.overlap(enem.mask, (offset_x, offset_y)):
                            self.player.bullets.remove(obj)
                            self.enemies.remove(enem)
                            enem.is_hit = True
                       

        if self.keys[pygame.K_UP]:
            self.player.move(0,-1)
        if self.keys[pygame.K_DOWN]:
            self.player.move(0,1)
        if self.keys[pygame.K_RIGHT]:
            self.player.move(1,0)
        if self.keys[pygame.K_LEFT]:
            self.player.move(-1,0)

        self.player.rect.clamp_ip(self.screenrect) #make sure rect does not go outside of screen
        for obj in self.enemies:
            if not obj.is_hit:
                self.screen.blit(obj.image, obj.rect)
        #if not self.enemy.is_hit:
         #   self.screen.blit(self.enemy.image, self.enemy.rect)
        self.screen.blit(self.player.image, self.player.rect)

app = Control()
pygame.quit();sys.exit()
New Users, Read This
version Python 3.3.2 and 2.7.5, tkinter 8.5, pyqt 4.8.4, pygame 1.9.2 pre
OS Ubuntu 14.04, Arch Linux, Gentoo, Windows 7/8
https://github.com/metulburr
User avatar
metulburr
 
Posts: 1130
Joined: Thu Feb 07, 2013 4:47 pm
Location: Elmira, NY

Re: [Pygame] laggy enemy kill

Postby Mekire » Thu May 09, 2013 11:30 pm

Well first off I can see that you are loading your Enemy image every time you create a new Enemy inside its __init__, rather than loading the image once and just using a reference to that loaded image every new enemy. I'm not sure if this is the cause of your delay, but it certainly isn't helping. I'll take a closer look and get back to you.

-Mek
User avatar
Mekire
 
Posts: 830
Joined: Thu Feb 07, 2013 11:33 pm
Location: Amakusa, Japan

Re: [Pygame] laggy enemy kill

Postby metulburr » Thu May 09, 2013 11:41 pm

ok i again figured it out. I was loading them from the url upon each creation which is obviously bad, i was doing it the same as with the player, but since the player only gets loaded once and its just testing, then whatever.

Code: Select all
import pygame
import sys
import math
import random

def image_from_url(url):
    try:
        from urllib2 import urlopen
        from cStringIO import StringIO as inout
    except ImportError:
        from urllib.request import urlopen
        from io import BytesIO as inout
    myurl = urlopen(url)
    return inout(myurl.read())

class Projectile:
    limit = 3
    def __init__(self, loc):
        self.surf = pygame.Surface((5,10)).convert()
        self.surf.set_colorkey((255,0,255))
        self.surf.fill((255,255,255))
        self.rect = self.surf.get_rect()
        self.rect.center = loc
        self.mask = pygame.mask.from_surface(self.surf)
        self.speed = 8

class Enemy:
    count = 3
    def __init__(self, start_loc, orig_image):
        self.orig_image = orig_image
        #link = 'http://i1297.photobucket.com/albums/ag23/metulburr/spaceship_enemy3_zpscfeb13bf.png'
        #self.orig_image = pygame.image.load(image_from_url(link)).convert()
        self.orig_image = pygame.transform.scale(self.orig_image, (40,80))
        self.orig_image.set_colorkey((255,0,255))
        self.image = pygame.transform.rotate(self.orig_image, 180)
        self.mask = pygame.mask.from_surface(self.image)
        self.rect = self.image.get_rect()
        self.rect.center = start_loc
        self.bullets = []
        self.speed = 2
        self.is_hit = False
       
    def pos_towards_player(self, player_rect):
        '''get new coords towards player'''
        c = math.sqrt((player_rect.x - self.rect[0]) ** 2 + (player_rect.y - self.rect[1]) ** 2)
        try:
            x = (player_rect.x - self.rect[0]) / c
            y = (player_rect.y - self.rect[1]) / c
        except ZeroDivisionError:
            return (self.rect.x, self.rect.y)
        return (x,y)
       
    def destroy(self):
        ...
       
    def update(self, player_rect):
        if not self.is_hit:
            #move enemy towards player
            new_pos = self.pos_towards_player(player_rect)
            self.rect.x, self.rect.y = (self.rect.x + new_pos[0] * self.speed, self.rect.y + new_pos[1] * self.speed)
           
           


class Player:
    def __init__(self, start_loc):
        self.speed = 4

        link = 'http://i1297.photobucket.com/albums/ag23/metulburr/spaceship2_zps095c332a.png'
        self.orig_image = pygame.image.load(image_from_url(link)).convert()
        self.orig_image = pygame.transform.scale(self.orig_image, (40,80))
        self.orig_image.set_colorkey((255,0,255))

        self.image = pygame.transform.rotate(self.orig_image, 180)
        self.mask = pygame.mask.from_surface(self.image)
        self.rect = self.image.get_rect()
        self.rect.center = start_loc

        self.bullets = []

    def move(self, x, y):
        self.rect[0] += x * self.speed
        self.rect[1] += y * self.speed


class Control:
    def __init__(self):
        self.screensize = (800,600)
        self.screen = pygame.display.set_mode(self.screensize)
        self.screenrect = self.screen.get_rect()
        self.clock = pygame.time.Clock()
        self.player = Player((0,600))
        #self.enemy = Enemy((800,0))
        link = 'http://i1297.photobucket.com/albums/ag23/metulburr/spaceship_enemy3_zpscfeb13bf.png'
        self.enemy_image = pygame.image.load(image_from_url(link)).convert()
       
        self.enemies = []


        self.mainloop()

    def mainloop(self):
        run = True
        while run:
            self.screen.fill((0,0,0))

            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    run = False
                elif event.type == pygame.KEYDOWN:
                    if event.key == pygame.K_SPACE:
                        if len(self.player.bullets) <= Projectile.limit:
                            self.player.bullets.append(Projectile(self.player.rect.center))

            self.update()
            pygame.display.flip()
            self.clock.tick(60)

    def update(self):
        self.keys = pygame.key.get_pressed()
       
        #for obj in self.enemies:
        #    obj.update(self.player.rect)
           
       
        #make new enemies
        #print(len(self.enemies))
       
        if len(self.enemies) <= Enemy.count:
            self.enemies.append(Enemy((random.randint(1,800),-100), self.enemy_image))
           

        if self.player.bullets:
            for obj in self.player.bullets:
                self.screen.blit(obj.surf, obj.rect)
                obj.rect[1] -= obj.speed

                #did obj move off screen
                if obj.rect[1] < 0:
                    self.player.bullets.remove(obj)
                #did obj hit enemy rect
                for enem in self.enemies:
                    if obj.rect.colliderect(enem.rect):
                        offset_x =  enem.rect.x - obj.rect.x
                        offset_y =  enem.rect.y - obj.rect.y
                        #did object hit enemy mask
                        if obj.mask.overlap(enem.mask, (offset_x, offset_y)):
                            self.player.bullets.remove(obj)
                            self.enemies.remove(enem)
                            enem.is_hit = True
   
                       

        if self.keys[pygame.K_UP]:
            self.player.move(0,-1)
        if self.keys[pygame.K_DOWN]:
            self.player.move(0,1)
        if self.keys[pygame.K_RIGHT]:
            self.player.move(1,0)
        if self.keys[pygame.K_LEFT]:
            self.player.move(-1,0)

        self.player.rect.clamp_ip(self.screenrect) #make sure rect does not go outside of screen
        for obj in self.enemies:
            obj.update(self.player.rect)
            if not obj.is_hit:
                self.screen.blit(obj.image, obj.rect)
        #if not self.enemy.is_hit:
         #   self.screen.blit(self.enemy.image, self.enemy.rect)
        self.screen.blit(self.player.image, self.player.rect)

app = Control()
pygame.quit();sys.exit()
New Users, Read This
version Python 3.3.2 and 2.7.5, tkinter 8.5, pyqt 4.8.4, pygame 1.9.2 pre
OS Ubuntu 14.04, Arch Linux, Gentoo, Windows 7/8
https://github.com/metulburr
User avatar
metulburr
 
Posts: 1130
Joined: Thu Feb 07, 2013 4:47 pm
Location: Elmira, NY

Re: [Pygame] laggy enemy kill

Postby metulburr » Thu May 09, 2013 11:42 pm

oh didnt even see you post, Mekire. Yeah that was the problem. Forgot i was loading it from the url every time
New Users, Read This
version Python 3.3.2 and 2.7.5, tkinter 8.5, pyqt 4.8.4, pygame 1.9.2 pre
OS Ubuntu 14.04, Arch Linux, Gentoo, Windows 7/8
https://github.com/metulburr
User avatar
metulburr
 
Posts: 1130
Joined: Thu Feb 07, 2013 4:47 pm
Location: Elmira, NY


Return to Game Development

Who is online

Users browsing this forum: No registered users and 1 guest