Python Forum
[split] image VS drawing - Printable Version

+- Python Forum (https://python-forum.io)
+-- Forum: Python Coding (https://python-forum.io/forum-7.html)
+--- Forum: Game Development (https://python-forum.io/forum-11.html)
+--- Thread: [split] image VS drawing (/thread-14714.html)

Pages: 1 2


[split] image VS drawing - Windspar - Dec-09-2018

Simple improvement would to put images in a list or dict.
This would stop if block. When more image are added.
DISPLAYSURF.blit(tileImage[tile], (centered_x, centered_y)) #display the actual tile
My example. My math could be improve.
import pygame

class Square:
    def __init__(self, color):
        self.surface = pygame.Surface((64, 64))
        self.surface = self.surface.convert_alpha()
        self.surface.fill((0,0,0,0))

        pygame.draw.polygon(self.surface, color, [(32,32), (64,48), (32,64), (0,48)])

    def draw(self, surface, pos):
        surface.blit(self.surface, pos)

class Block:
    def __init__(self, color):
        self.surface = pygame.Surface((64, 64)).convert_alpha()
        self.surface.fill((0,0,0,0))

        pygame.draw.polygon(self.surface, color, [(32,32), (0,16), (32,0), (64,16)])

        c = color.hsla
        color.hsla = c[0], c[1], c[2] * 0.75, c[3]
        pygame.draw.polygon(self.surface, color, [(0,16), (32,32), (32,64), (0,48)])

        c = color.hsla
        color.hsla = c[0], c[1], c[2] * 0.75, c[3]
        pygame.draw.polygon(self.surface, color, [(32,32), (64,16), (64,48), (32,64)])

    def draw(self, surface, pos):
        surface.blit(self.surface, pos)

class Scene:
    def __init__(self):
        self.rect = pygame.Rect(0, 0, 800, 600)
        pygame.display.set_caption('Example')
        self.surface = pygame.display.set_mode(self.rect.size)
        self.clock = pygame.time.Clock()

        self.images = [Square(pygame.Color('lawngreen')),
                       Block(pygame.Color('cyan')),
                       Block(pygame.Color('firebrick'))
        ]

        self.map = [[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
                    [0, 1, 0, 0, 1, 0, 2, 2, 2, 0],
                    [0, 1, 0, 0, 1, 0, 0, 2, 0, 0],
                    [0, 1, 1, 1, 1, 0, 0, 2, 0, 0],
                    [0, 1, 0, 0, 1, 0, 0, 2, 0, 0],
                    [0, 1, 0, 0, 1, 0, 2, 2, 2, 0],
                    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]

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

            self.surface.fill((0,0,0))

            cx = self.rect.centerx // 2 + len(self.map) * 32
            cy = self.rect.centery // 2 - len(self.map[0]) * 4
            w, h = self.rect.size
            for row, line in enumerate(self.map):
                for col, tile in enumerate(line):
                    pos = w - (row * 32 + cx) + col * 32, (col + row) * 16 + cy
                    self.images[tile].draw(self.surface, pos)

            pygame.display.flip()
            self.clock.tick(30)

        pygame.quit()

scene = Scene()
scene.loop()



RE: Simple code for isometric 2D games - ThePhi - Dec-10-2018

What you're proposing is probably faster in term of CPU (I didn't time it though) but the usual way in a 2d game is to use 2d assets, not drawing them in the program.
You can use free 2d assets like here: https://devilsworkshop.itch.io/big-pixel-isometric-block-pack-free-2d-sprites


RE: Simple code for isometric 2D games - metulburr - Dec-10-2018

(Dec-10-2018, 07:25 AM)ThePhi Wrote: the usual way in a 2d game is to use 2d assets, not drawing them in the program.
I would do this as well. I think its easier and when you need top-down assets something like Tiled makes it really easy to place positions and edit them in the future being able to see them. Not to mention you can make minute details in image software that would be horrific trying to replicate them.


RE: Simple code for isometric 2D games - Windspar - Dec-10-2018

Creating image in game and/or loading image is just a personal preference.
Loading image have higher quality. If you are going that way.
Creating image I can program to have different colors quickly.
So I can test out different task quickly.
Then if I want higher quality images. I can just replace it.


RE: Simple code for isometric 2D games - ThePhi - Dec-11-2018

(Dec-10-2018, 03:19 PM)Windspar Wrote: Creating image in game and/or loading image is just a personal preference.
A bit more than that... Even you didn't manage to create the same image as in my example (see the red line around each face of the cube? Not so easy drawing that by the program isn't it?).
[Image: Screenshot-2018-12-11-08-24-35.png]

(Dec-10-2018, 03:19 PM)Windspar Wrote: Loading image have higher quality. If you are going that way. Creating image I can program to have different colors quickly. So I can test out different task quickly. Then if I want higher quality images. I can just replace it.
To get the same result with image assets, you can still use vertex images in pygame. Even if I didn't try it, it seems to work (https://stackoverflow.com/questions/4001340/can-pygame-use-vector-art)


RE: Simple code for isometric 2D games - Windspar - Dec-11-2018

(Dec-11-2018, 07:34 AM)ThePhi Wrote: A bit more than that... Even you didn't manage to create the same image as in my example (see the red line around each face of the cube? Not so easy drawing that by the program isn't it?).
Confused

Example with my poor quality red lines.
import pygame

BRED = pygame.Color(200, 110, 110)

class Square:
    def __init__(self, color):
        self.surface = pygame.Surface((64, 64))
        self.surface = self.surface.convert_alpha()
        self.surface.fill((0,0,0,0))

        pygame.draw.polygon(self.surface, color, [(32,32), (64,48), (32,64), (0,48)])
        pygame.draw.polygon(self.surface, BRED, [(32,32), (64,48), (32,64), (0,48)], 1)

    def draw(self, surface, pos):
        surface.blit(self.surface, pos)

class Block:
    def __init__(self, color):
        self.surface = pygame.Surface((64, 64)).convert_alpha()
        self.surface.fill((0,0,0,0))

        pygame.draw.polygon(self.surface, color, [(32,32), (0,16), (32,0), (64,16)])

        c = color.hsla
        color.hsla = c[0], c[1], c[2] * 0.75, c[3]
        pygame.draw.polygon(self.surface, color, [(0,16), (32,32), (32,64), (0,48)])

        c = color.hsla
        color.hsla = c[0], c[1], c[2] * 0.75, c[3]
        pygame.draw.polygon(self.surface, color, [(32,32), (64,16), (64,48), (32,64)])
        pygame.draw.polygon(self.surface, BRED, [(32,32), (0,16), (32,0), (64,16)], 1)
        pygame.draw.polygon(self.surface, BRED, [(0,16), (32,32), (32,64), (0,48)], 1)
        pygame.draw.polygon(self.surface, BRED, [(32,32), (64,16), (64,48), (32,64)], 1)

    def draw(self, surface, pos):
        surface.blit(self.surface, pos)

class BlockHalf:
    def __init__(self, color):
        self.surface = pygame.Surface((64, 64)).convert_alpha()
        self.surface.fill((0,0,0,0))

        # top
        pygame.draw.polygon(self.surface, color, [(32,48), (0,32), (32,16), (64,32)])

        # left
        c = color.hsla
        color.hsla = c[0], c[1], c[2] * 0.75, c[3]
        pygame.draw.polygon(self.surface, color, [(0,32), (32,48), (32,64), (0,56)])

        # right
        c = color.hsla
        color.hsla = c[0], c[1], c[2] * 0.75, c[3]
        pygame.draw.polygon(self.surface, color, [(32,48), (64,32), (64,56), (32,64)])

    def draw(self, surface, pos):
        surface.blit(self.surface, pos)

class Scene:
    def __init__(self):
        self.rect = pygame.Rect(0, 0, 800, 600)
        pygame.display.set_caption('Example')
        self.surface = pygame.display.set_mode(self.rect.size)
        self.clock = pygame.time.Clock()

        self.images = [Square(pygame.Color('lawngreen')),
                       Block(pygame.Color('cyan')),
                       Block(pygame.Color('firebrick'))
        ]

        self.map = [[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
                    [0, 1, 0, 0, 1, 0, 2, 2, 2, 0],
                    [0, 1, 0, 0, 1, 0, 0, 2, 0, 0],
                    [0, 1, 1, 1, 1, 0, 0, 2, 0, 0],
                    [0, 1, 0, 0, 1, 0, 0, 2, 0, 0],
                    [0, 1, 0, 0, 1, 0, 2, 2, 2, 0],
                    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]

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

            self.surface.fill((0,0,0))

            cx = self.rect.centerx // 2 + len(self.map) * 32 + 16
            cy = self.rect.centery // 2 - len(self.map[0]) * 4
            w, h = self.rect.size
            for row, line in enumerate(self.map):
                for col, tile in enumerate(line):
                    pos = w - (row * 32 + cx) + col * 32, (col + row) * 16 + cy
                    self.images[tile].draw(self.surface, pos)

            pygame.display.flip()
            self.clock.tick(30)

        pygame.quit()

scene = Scene()
scene.loop()
One good thing about low quality images. You can see how fast it program runs. Then see how much slow down with high quality images. In programming everything has it cost.


RE: Simple code for isometric 2D games - ThePhi - Dec-11-2018

You gave yourself a lot of work. Try with a sprite of an hospital, a tree now Rolleyes


RE: Simple code for isometric 2D games - Windspar - Dec-12-2018

(Dec-11-2018, 06:28 PM)ThePhi Wrote: You gave yourself a lot of work.
Confused

Example with a trees
import pygame

BRED = pygame.Color(200, 110, 110)

def darken_color(color, darken=0.75):
    c = color.hsla
    color.hsla = c[0], c[1], c[2] * darken, c[3]

def lower_points(points, by=32):
    return tuple([(p[0], p[1] + by) for p in points])

def top_points(x=0, y=0, w=64, h=32):
    if w < 0:
        w = 64 + w

    if h < 0:
        h = 32 + h

    w -= x
    h -= y

    topleft     = x,            y + h * 0.5
    topright    = x + w * 0.5,  y + x * 0.5
    bottomleft  = x + w * 0.5,  y + h - x * 0.5
    bottomright = x + w,        y + h * 0.5
    return topleft, topright, bottomright, bottomleft

def side_points(top_points, height=32):
    return ((top_points[0],
             top_points[3],
            (top_points[3][0],  top_points[3][1] + height),
            (top_points[0][0],  top_points[0][1] + height)),

            (top_points[3],
             top_points[2],
            (top_points[2][0],  top_points[2][1] + height),
            (top_points[3][0],  top_points[3][1] + height)))

class Square:
    def __init__(self, color):
        self.surface = pygame.Surface((64, 64)).convert_alpha()
        self.surface.fill((0,0,0,0))

        pygame.draw.polygon(self.surface, color, [(0,48), (32,32), (64,48), (32,64)])
        pygame.draw.polygon(self.surface, BRED, [(0,48), (32,32), (66,48), (32,64)], 1)

    def draw(self, surface, pos):
        surface.blit(self.surface, pos)

class Block:
    def __init__(self, color):
        self.surface = pygame.Surface((64, 64)).convert_alpha()
        self.surface.fill((0,0,0,0))
        self.create_image(color)

    def create_image(self, color):
        top = top_points()
        left, right = side_points(top)
        # top
        pygame.draw.polygon(self.surface, color, top)

        # left
        darken_color(color)
        pygame.draw.polygon(self.surface, color, left)

        # right
        darken_color(color)
        pygame.draw.polygon(self.surface, color, right)
        #pygame.draw.polygon(self.surface, BRED, [(32,32), (0,16), (32,0), (64,16)], 1)
        #pygame.draw.polygon(self.surface, BRED, [(0,16), (32,32), (32,64), (0,48)], 1)
        #pygame.draw.polygon(self.surface, BRED, [(32,32), (64,16), (64,48), (32,64)], 1)

    def draw(self, surface, pos):
        surface.blit(self.surface, pos)

class Tree:
    def __init__(self, color, trunk_color, ground_color):
        self.tree_top = pygame.Surface((64, 64)).convert_alpha()
        self.tree_top.fill((0,0,0,0))
        self.trunk = pygame.Surface((64, 64)).convert_alpha()
        self.trunk.fill((0,0,0,0))
        self.create_image(color, trunk_color, ground_color)

    def create_image(self, color, trunk_color, ground_color):
        # Tree Top
        top, left, right = self.layer(top_points(), 24, 8)
        self.draw_polygons(self.tree_top, top, left, right, pygame.Color(*color))
        top, left, right = self.layer(top_points(8, w=-8), 16, 8)
        self.draw_polygons(self.tree_top, top, left, right, pygame.Color(*color))
        top, left, right = self.layer(top_points(16, w=-16), 8, 8)
        self.draw_polygons(self.tree_top, top, left, right, pygame.Color(*color))
        top, left, right = self.layer(top_points(24, w=-24), 0, 8)
        self.draw_polygons(self.tree_top, top, left, right, pygame.Color(*color))
        # Trunk
        top = lower_points(top_points())
        pygame.draw.polygon(self.trunk, ground_color, top)
        top, left, right = self.layer(top_points(20, w=-20), 0, 32)
        self.draw_polygons(self.trunk, top, left, right, trunk_color)

    def draw_polygons(self, surface, top, left, right, color):
        # top
        pygame.draw.polygon(surface, color, top)

        # left
        darken_color(color)
        pygame.draw.polygon(surface, color, left)

        # right
        darken_color(color)
        pygame.draw.polygon(surface, color, right)

    def layer(self, toptop, height, diff):
        top = lower_points(toptop, height)
        left, right = side_points(top, diff)
        return top, left, right

    def draw(self, surface, pos):
        surface.blit(self.trunk, pos)
        position = pos[0], pos[1] - 16
        surface.blit(self.tree_top, position)

class Scene:
    def __init__(self):
        self.rect = pygame.Rect(0, 0, 800, 600)
        pygame.display.set_caption('Example')
        self.surface = pygame.display.set_mode(self.rect.size)
        self.clock = pygame.time.Clock()

        self.images = [Square(pygame.Color('lawngreen')),
                       Block(pygame.Color('cyan')),
                       Block(pygame.Color('firebrick')),
                       Tree(pygame.Color('forestgreen'), pygame.Color('brown'), pygame.Color('lawngreen'))
        ]

        self.map = [[3, 0, 0, 0, 0, 0, 0, 0, 0, 0],
                    [0, 1, 0, 0, 1, 0, 2, 2, 2, 0],
                    [0, 1, 0, 0, 1, 0, 0, 2, 0, 0],
                    [0, 1, 1, 1, 1, 0, 0, 2, 0, 0],
                    [0, 1, 0, 0, 1, 0, 0, 2, 0, 3],
                    [0, 1, 0, 0, 1, 0, 2, 2, 2, 0],
                    [3, 0, 0, 0, 0, 0, 0, 0, 0, 0]]

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

            self.surface.fill((0,0,0))

            cx = self.rect.centerx // 2 + len(self.map) * 32 + 16
            cy = self.rect.centery // 2 - len(self.map[0]) * 4
            w, h = self.rect.size
            for row, line in enumerate(self.map):
                for col, tile in enumerate(line):
                    pos = w - (row * 32 + cx) + col * 32, (col + row) * 16 + cy
                    self.images[tile].draw(self.surface, pos)

            pygame.display.flip()
            self.clock.tick(30)

        pygame.quit()

scene = Scene()
scene.loop()



RE: Simple code for isometric 2D games - metulburr - Dec-13-2018

(Dec-10-2018, 03:19 PM)Windspar Wrote: Creating image in game and/or loading image is just a personal preference.
Loading image have higher quality. If you are going that way.
Creating image I can program to have different colors quickly.
So I can test out different task quickly.
Then if I want higher quality images. I can just replace it.
In my opinion the opposite is true. I think it is much more faster to throw an image in GIMP (or PhotoShop Tongue ) to change it than to program it. If your planning on replacing your placeholder images anyways, then it was a complete waste of time writing the code to make trees, rather than just using the actual image you would be using in the first place.


RE: Simple code for isometric 2D games - Windspar - Dec-13-2018

It's probably just me, but I like programming image code. I always use blender over gimp when I can. I can do some math in blender. I like dealing objects over layers. I use gimp for normals and diffuse maps.

I believe I can have 50 colors of every image before you can do it gimp.

It all comes down to how fancy you want your images.
Since I not very good at make fancy images.