Trouble with Object Orientation

Trouble with Object Orientation

Postby DavitosanX » Fri Jun 06, 2014 2:21 am

I have never truly grasped the concept of object orientation. I tend to make classes that don't make much sense, or I fail to encapsulate correctly. I think I'm getting better at it, but I'm open to suggestions. In the following code, do you think I'm being correctly object oriented? I really appreciate any help.

Code: Select all
import pygame
from pygame.locals import *



class Ball:

    def __init__(self,imageFile,position_arg):
        self.image = pygame.image.load(imageFile)
        self.position = (position_arg)



class AssetManager:

    def load_ball(self,imageFile,position):
        return Ball(imageFile,position)



class Game:

    def __init__(self,resolution,caption):

        self.screen = pygame.display.set_mode(resolution)
        pygame.display.set_caption(caption)
        self.clock = pygame.time.Clock()
        self.running = True
        self.gray = (220,220,220)

    def check_events(self):

        for event in pygame.event.get():
            if event.type == QUIT:
                self.running = False

    def draw_screen(self,ball):
        self.screen.fill(self.gray)
        self.screen.blit(ball.image,ball.position)
        pygame.display.flip()

    def main_loop(self,framerate,assets):

        ball = assets.load_ball('ball.png',(350,250))

        while self.running:

            self.clock.tick(framerate)
            self.check_events()

            self.draw_screen(ball)

        pygame.quit()



assets = AssetManager()
game = Game((800,600),"Game")
game.main_loop(60,assets)
DavitosanX
 
Posts: 9
Joined: Mon May 26, 2014 9:23 pm
Location: Pharmacist

Re: Trouble with Object Orientation

Postby metulburr » Fri Jun 06, 2014 5:08 am

Looks good to me, for the exception of AssetManager. It seems like an unnecessary layer of logic around Ball(). I removed that and modified a couple more things...

Code: Select all
import pygame

class Ball:
    def __init__(self,imageFile,position_arg):
        self.image = pygame.image.load(imageFile)
        self.position = (position_arg)
       
class Game:
    def __init__(self,resolution,caption):
        self.screen = pygame.display.set_mode(resolution)
        pygame.display.set_caption(caption)
        self.clock = pygame.time.Clock()
        self.running = True
        self.gray = (220,220,220)
        self.ball = Ball('ball.png',(350,250))

    def check_events(self):
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                self.running = False

    def draw_screen(self):
        self.screen.fill(self.gray)
        self.screen.blit(self.ball.image, self.ball.position)
        pygame.display.flip()

    def main_loop(self,framerate):
        while self.running:
            self.clock.tick(framerate)
            self.check_events()
            self.draw_screen()
        pygame.quit()

game = Game((800,600),"Game")
game.main_loop(60)


I think this may be what you were thinking of with the AssetManager...not sure
Another unique/complex approach if you really wanted to create the object outside of class Game would be to pass Game a dictionary of objects. In this example assets['ball'] becomes Game.ball (self.ball). The dictionary key becomes the class' attribute. Same thing before, but it is created outside of the class. Thist does not account for already existing attributes already named the dicts keys, so it will overwrite them.
Code: Select all
import pygame

class Ball:
    def __init__(self,imageFile,position_arg):
        self.image = pygame.image.load(imageFile)
        self.position = (position_arg)
       
class Game:
    def __init__(self,resolution,caption, **assets):
        self.__dict__.update(assets)
        self.screen = pygame.display.set_mode(resolution)
        pygame.display.set_caption(caption)
        self.clock = pygame.time.Clock()
        self.running = True
        self.gray = (220,220,220)

    def check_events(self):
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                self.running = False

    def draw_screen(self):
        self.screen.fill(self.gray)
        self.screen.blit(self.ball.image, self.ball.position)
        pygame.display.flip()

    def main_loop(self,framerate):
        while self.running:
            self.clock.tick(framerate)
            self.check_events()
            self.draw_screen()
        pygame.quit()

assets = {
    'ball': Ball('ball.png',(350,250))
}

game = Game((800,600),"Game", **assets)
game.main_loop(60)

However i have never used this as i create the objects within the class themselves.
New Users, Read This
OS Ubuntu 14.04, Arch Linux, Gentoo, Windows 7/8
https://github.com/metulburr
steam
User avatar
metulburr
 
Posts: 1476
Joined: Thu Feb 07, 2013 4:47 pm
Location: Elmira, NY

Re: Trouble with Object Orientation

Postby Mekire » Fri Jun 06, 2014 8:48 am

All looks pretty good. Couple more ideas in the interest of kicking dead horses.

No star imports (metulburr already removed it in his). Start using rects. Don't reload resources every time you make an instance of a class. Convert images when you load them (convert or convert_alpha depending)

This isn't much different but this is what I tend to do (in single module programs):
Code: Select all
import os
import sys
import pygame as pg


CAPTION = "Game"
SCREEN_SIZE = (800, 600)
BACKGROUND_COLOR = (220, 220, 220)


class Ball(pg.sprite.Sprite):
    def __init__(self, position, *groups):
        pg.sprite.Sprite.__init__(self, *groups)
        self.image = BALL_IMAGE
        self.rect = self.image.get_rect(topleft=position)

    def udpate(self):
        pass

    def draw(self, surface):
        surface.blit(self.image, self.rect)


class Game(object):
    def __init__(self):
        self.screen = pg.display.get_surface()
        self.screen_rect = self.screen.get_rect()
        self.clock = pg.time.Clock()
        self.fps = 60.0
        self.running = True
        self.ball = Ball((350,250))

    def event_loop(self):
        for event in pg.event.get():
            if event.type == pg.QUIT:
                self.running = False

    def draw(self):
        self.screen.fill(BACKGROUND_COLOR)
        self.ball.draw(self.screen)
        pg.display.update()

    def update(self):
        pass

    def main_loop(self):
        while self.running:
            self.event_loop()
            self.update()
            self.draw()
            self.clock.tick(self.fps)


def main():
    global BALL_IMAGE
    os.environ["SDL_VIDEO_CENTERED"] = "True"
    pg.init()
    pg.display.set_caption(CAPTION)
    pg.display.set_mode(SCREEN_SIZE)
    BALL_IMAGE = pg.image.load('ball.png').convert() #convert_alpha depending.
    Game().main_loop()
    pg.quit()
    sys.exit()


if __name__ == "__main__":
    main()

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

Re: Trouble with Object Orientation

Postby DavitosanX » Mon Jun 09, 2014 5:30 pm

Sorry it took me so long to reply, but I've been incredibly busy these days. I'm going to spend some time studying your posts, since they contain elements I don't fully understand. I didn't realize star imports could be that bad, but I'll follow your advice. I didn't do convert(), or inherit from Sprite, or use rects right now, simply because I wasn't aware of these tools. I'll check them out, one by one.

One thing did strike me as odd. Why did you define the fps as float?
DavitosanX
 
Posts: 9
Joined: Mon May 26, 2014 9:23 pm
Location: Pharmacist

Re: Trouble with Object Orientation

Postby Mekire » Tue Jun 10, 2014 6:45 am

DavitosanX wrote:One thing did strike me as odd. Why did you define the fps as float?

No real reason. Sometimes I do this because I want to do some float division (without converting in python 2), but here it was just a fairly arbitrary decision. I assure you, it affects nothing.

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


Return to Game Development

Who is online

Users browsing this forum: W3C [Linkcheck] and 3 guests