Python Forum
[PyGame] How to make collisions in isometrick game?
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
[PyGame] How to make collisions in isometrick game?
#1
Brick 
Win 10
Python 3.9.5

I need to make collisions for my isometric game and for player
Can someone help me?
Sorry for bad english, i from Ukraine.

here is code:
import pygame
import sys
import time
import random

WIDTH = 700
HEIGHT = 700
from pygame.constants import QUIT



clock = pygame.time.Clock()


pygame.init()
screen = pygame.display.set_mode((WIDTH, HEIGHT), 0, 32)
pygame.display.set_caption("game base")
display = pygame.Surface((300, 300))

ground_img = pygame.image.load('ground3.png')
ground_img.set_colorkey((0, 0, 0))
stone_img = pygame.image.load("stone2.png").convert()
stone_img.set_colorkey((0, 0, 0))


ground_dict = {}  # словарь {ряд-номер клетки-номер слоя: название картинки}

# читаем данные карты из файла и заполняем ими словарь
with open('map.txt') as f:
    map_data = [[int(c) for c in row.strip()] for row in f]
    for y, row in enumerate(map_data):
        for x, tile in enumerate(row):              
            if tile:
                ground_dict[f'{y}-{x}-1'] = 'stone'
                # для второго слоя
                if random.randint(0, 1):
                    ground_dict[f'{y}-{x}-2'] = 'ground'                       

while True:
    display.fill((0, 0, 0))
    clock.tick(60)
    # проходим в цикле по словарю
    for key, value in ground_dict.items():
        # получаем ряд, номер клетки и номер слоя
        y, x, n = list(map(int, key.split('-')))
        # определяем нужную картинку для клетки
        z = stone_img if value == 'stone' else ground_img 
        # отрисовываем в зависимости от номера слоя
        if n == 1:
            display.blit(z, (150 + x * 10 - y * 10, 100 + x * 5 + y * 5))
        elif n == 2:
            display.blit(z, (150 + x * 10 - y * 10, 100 + x * 5 + y * 5 - 14))   
    
    for event in pygame.event.get():
        if event.type == QUIT:
            pygame.quit()
            sys.exit()
    
    screen.blit(pygame.transform.scale(display, screen.get_size()), (55, 55))
    pygame.display.update()
    time.sleep(1)
Reply
#2
I couldn't get internet formula to work. So I made my own. Still working on it.
Something I been playing around with. No real purpose. Just testing.
import pygame
import itertools
from types import SimpleNamespace

color = SimpleNamespace(**dict([(k, pygame.Color(v)) for k, v in pygame.color.THECOLORS.items()]))

def create_box_image(color, size):
    size = size, size
    surface = pygame.Surface(size, pygame.SRCALPHA)
    surface.fill((0, 0, 0, 0))
    pygame.draw.rect(surface, color, (0, 0, *size), 1)
    return surface

def shift_image(image):
    w, h = image.get_size()
    size = w + h, h
    surface = pygame.Surface(size, pygame.SRCALPHA)
    for x in range(w):
        for y in range(h):
            color = image.get_at((x, y))
            surface.set_at((x + y, y), color)

    return surface

class TileMap:
    def __init__(self, tilemap, tilekey):
        self.tilemap = tilemap
        self.tilekey = tilekey
        self.hover = None
        self.hover2 = None

    def draw(self, camera, surface):
        for y, row in enumerate(self.tilemap):
            for x, key in enumerate(row):
                if key != 0:
                    image = self.tilekey[key]

                    if self.hover == self.hover2 and self.hover != None:
                        if self.hover[0] == x and self.hover[1] == y:
                            image = self.tilekey["hover3"]
                    else:
                        if self.hover:
                            if self.hover[0] == x and self.hover[1] == y:
                                image = self.tilekey["hover"]

                        if self.hover2:
                            if self.hover2[0] == x and self.hover2[1] == y:
                                image = self.tilekey["hover2"]

                    surface.blit(image, camera.map_to_screen((x, y)))

class TileCamera:
    def __init__(self, worldsize, position, view, tilesize, map):
        self.map = map
        self.view = view
        self.position = position
        self.tile = pygame.Rect(0, 0, tilesize, tilesize)
        self.surface = pygame.Surface(worldsize, pygame.SRCALPHA)

    def draw(self, surface):
        self.surface.fill(color.gray40)
        self.map.draw(self, self.surface)

        surface.blit(self.surface, self.position)

    def map_to_screen(self, position):
        return self.view[0] + position[0] * self.tile.w, self.view[1] + position[1] * self.tile.h

    def iso_hover(self, position):
        self.map.hover = position[0] // self.tile.w, position[1] // self.tile.h

class IsoCamera:
    def __init__(self, worldsize, position, view, tilesize, map):
        self.map = map
        self.view = view
        self.position = position
        self.tile = pygame.Rect(0, 0, tilesize * 2, tilesize)
        self.surface = pygame.Surface(worldsize, pygame.SRCALPHA)

    def draw(self, surface):
        self.surface.fill(color.gray30)
        self.map.draw(self, self.surface)

        surface.blit(self.surface, self.position)

    def get_position(self, mpos):
        return mpos[0] - self.view[0] - self.position[0], mpos[1] - self.view[1] - self.position[1]

    # Formula found on the net
    def real_screen_to_map(self, position):
        x = (position[0] - self.view[0] - self.position[0]) / self.tile.width
        y = (position[1] - self.view[1] - self.position[1]) / self.tile.height
        return int(x + y), int(y - x)

    # Formula I came up with
    def screen_to_map(self, position):
        # Remove all offset
        posx = position[0] - self.position[0] - self.view[0]
        posy = position[1] - self.position[1] - self.view[1]
        # Change to map position
        y = (posy - posx * 0.5 + self.tile.centery)
        x = (posx + y - self.tile.height) // self.tile.height
        y /= self.tile.height
        if y < 0:
            y -= 1
        return int(x), int(y)

    # Formula found on the net
    def map_to_screen(self, position):
        x, y = position
        return (self.view[0] + (x - y) * self.tile.centerx,
                self.view[1] + (x + y) * self.tile.centery)

class TileLabels:
    def __init__(self):
        pen = Pen(pygame.font.Font(None, 24), color.white)
        iso_ypos = itertools.count(10, 30)
        ypos = itertools.count(10, 30)
        self.labels = {
            "Mouse" : Label(pen, "Mouse Pos: ({}, {})", (0, 0), (10, next(iso_ypos)), "topleft"),
            "ISO Position" : Label(pen, "ISO Position: ({}, {})", (0, 0), (10, next(iso_ypos)), "topleft"),

            "Position" : Label(pen, "Position: ({}, {})", (0, 0), (410, next(ypos)), "topleft"),
            "Position2" : Label(pen, "Position: ({}, {})", (0, 0), (410, next(ypos)), "topleft"),
            }

    def draw(self, surface):
        for value in self.labels.values():
            value.draw(surface)

    # Formula I came up with
    def update(self, mpos, iso_cam):
        self.labels["Mouse"].render(*mpos)
        ix, iy = iso_cam.get_position(mpos)
        self.labels["ISO Position"].render(ix, iy)
        y = iy - ix * 0.5 + iso_cam.tile.centery
        x = ix + y - iso_cam.tile.h
        self.labels["Position"].render(x, y)
        self.labels["Position2"].render(*iso_cam.screen_to_map(mpos))
        return x, y

class Pen:
    def __init__(self, font, color):
        self.font = font
        self.color = color

    def render(self, string):
        return self.font.render(string, 1, self.color)

class Label:
    def __init__(self, pen, fstring, data, position, anchor):
        self.pen = pen
        self.fstring = fstring
        self.position = position
        self.anchor = anchor
        self.render(*data)

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

    def render(self, *data):
        text = self.fstring.format(*data)
        self.image = self.pen.render(text)
        self.rect = self.image.get_rect(**{self.anchor: self.position})

class Main:
    def __init__(self, caption, width, height, flags=0):
        pygame.display.set_caption(caption)
        self.surface = pygame.display.set_mode((width, height), flags)
        self.rect = self.surface.get_rect()
        self.clock = pygame.time.Clock()
        self.running = False
        self.delta = 0
        self.fps = 60

        self.tile_labels = TileLabels()

        tilesize = 32
        worldsize = 400, 400
        view = 150, 100
        self.maptile = [[1, 1, 1, 1, 1],
                        [1, 1, 1, 1, 1],
                        [1, 1, 1, 1, 1],
                        [1, 1, 1, 1, 1]]

        self.tilekey = {
            "hover" : create_box_image(color.lawngreen, tilesize),
            "hover2" : create_box_image(color.firebrick, tilesize),
            "hover3" : create_box_image(color.dodgerblue, tilesize),
            1 : create_box_image(color.snow, tilesize)
        }

        rotate = pygame.transform.rotate
        scale = pygame.transform.smoothscale
        self.isokey = {
            "hover" : scale(rotate(self.tilekey["hover"], 45), (64, 32)),
            "hover2" : scale(rotate(self.tilekey["hover2"], 45), (64, 32)),
            "hover3" : scale(rotate(self.tilekey["hover3"], 45), (64, 32)),
            1 : scale(pygame.transform.rotate(self.tilekey[1], 45), (64, 32))
        }

        self.tile_map = TileMap(self.maptile, self.tilekey)
        self.iso_map = TileMap(self.maptile, self.isokey)
        self.tile_camera = TileCamera(worldsize, (400, 100), view, tilesize, self.tile_map)
        self.iso_camera = IsoCamera(worldsize, (0, 100), view, tilesize, self.iso_map)

        self.inverse_mouse = None

    def draw(self):
        self.iso_camera.draw(self.surface)
        self.tile_camera.draw(self.surface)
        self.tile_labels.draw(self.surface)

    def mainloop(self):
        self.running = True
        while self.running:
            for event in pygame.event.get():
                if event.type == pygame.MOUSEMOTION:
                    self.iso_camera.map.hover2 = self.iso_camera.screen_to_map(event.pos)
                    pos = self.tile_labels.update(event.pos, self.iso_camera)
                    self.tile_camera.iso_hover(pos)
                    self.iso_camera.map.hover = self.tile_camera.map.hover
                elif event.type == pygame.QUIT:
                    self.running = False

            self.surface.fill(color.black)
            self.draw()
            pygame.display.flip()
            self.delta = self.clock.tick(self.fps) * 0.001

def main():
    pygame.init()
    app = Main("IsoMetric", 800, 500)
    app.mainloop()
    pygame.quit()

main()
99 percent of computer problems exists between chair and keyboard.
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  Collisions in Arrays Prithak 2 3,012 Mar-19-2021, 03:17 AM
Last Post: Prithak
  Can someone help me with collisions ? CUKEMAN 2 1,969 Jun-22-2020, 09:54 AM
Last Post: JudyLarose
  Trying to make a simple pong game. kevindadmun 1 3,870 Aug-05-2019, 06:39 AM
Last Post: kevindadmun
  Help with collisions. ghost0fkarma 5 5,978 Mar-11-2019, 12:09 AM
Last Post: Windspar
  [PyGame] How do you make a quiz game in Python? SteampunkMaverick12 1 4,523 May-20-2018, 09:34 PM
Last Post: Larz60+

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020