Quantcast
Channel: Active questions tagged python - Stack Overflow
Viewing all articles
Browse latest Browse all 23131

Pygame Platformer Collisions [duplicate]

$
0
0

I am a python beginner and have recently started watching DaFluffyPotato's pygame platformer tutorial, and attempting to code my own simple platformer. I have gotten to the collisions part of the tutorial, and attempted to model a player entity on a surface of tiles. I wanted to make the player (44x46) be able to stand on the tiles (32x32), however making it be larger than the tiles produces this weird visual effect.effect.

Physics engine:

import pygameclass Entity:    def __init__(self, game, etype, pos, size,):        self.game = game        self.type = etype        self.pos = list(pos)        self.size=size        self.velocity = [0, 0]        self.collisions = {'up': False, 'down': False, 'right': False, 'left': False}    def rect(self):        return pygame.Rect(self.pos[0], self.pos[1], self.size[0], self.size[1])    def update(self, tilemap, movement=(0, 0)):        self.collisions= {"up": False, "down": False, "right": False, "left": False}        frame_movement = (movement[0] + self.velocity[0], movement[1] + self.velocity[1])        self.pos[0] += frame_movement[0]        entity_rect = self.rect()        for rect in tilemap.physics_rects_around(self.pos):            if entity_rect.colliderect(rect):                if frame_movement[0] > 0:                    entity_rect.right = rect.left                    self.collisions["right"] = True                if frame_movement[0] < 0:                    entity_rect.left = rect.right                    self.collisions["left"] = True                self.pos[0] = entity_rect.x        self.pos[1] += frame_movement[1]        entity_rect = self.rect()        for rect in tilemap.physics_rects_around(self.pos):            if entity_rect.colliderect(rect):                if frame_movement[1] > 0:                    entity_rect.bottom= rect.top                    self.collisions["down"] = True                if frame_movement[1] < 0:                    entity_rect.top = rect.bottom                    self.collisions["up"] = True                self.pos[1] = entity_rect.y        self.velocity[1] = min(5, self.velocity[1] + 0.1)        if self.collisions["down"] or self.collisions["up"]:            self.velocity[1] = 0     def render(self, surf):        surf.blit(self.game.assets["player"], self.pos)

Tilemap:

import pygamePHYSICS_TILES={"grass"}NEIGHBOR_OFFSETS = [(-1, 0), (-1, -1), (0, -1), (1, -1), (1, 0), (0, 0), (-1, 1), (0, 1), (1, 1)]class Tilemap:    def __init__(self, game, tile_size):        self.game=game        self.tile_size = tile_size        self.tilemap = {}        self.offgrid_tiles = []        for i in range(10):            self.tilemap[str(3+i) +";10"]={"type": "grass", "pos": (3+i, 10)}    def tiles_around(self, pos):        tiles = []        tile_loc =(int(pos[0] // self.tile_size), int(pos[1] // self.tile_size))        for offset in NEIGHBOR_OFFSETS:            check_loc = str(tile_loc[0]+offset[0]) +";" + str(tile_loc[1]+offset[1])            if check_loc in self.tilemap:                tiles.append(self.tilemap[check_loc])        return tiles    def physics_rects_around(self, pos):        rects = []        for tile in self.tiles_around(pos):            if tile["type"] in PHYSICS_TILES:                rects.append(pygame.Rect(tile["pos"][0]*self.tile_size, tile["pos"][1]*self.tile_size, self.tile_size, self.tile_size))        return rects    def render(self, surf):        for tile in self.offgrid_tiles:            surf.blit(self.game.assets[tile["type"]], tile["pos"])        for loc in self.tilemap:            tile = self.tilemap[loc]            surf.blit(self.game.assets[tile["type"]],(tile["pos"][0]*self.tile_size, tile["pos"][1]*self.tile_size))

Game:

import sysimport pygamefrom Scripts.entities import Entityfrom Scripts.util import load_imagefrom Scripts.tilemap import Tilemapclass Game:    def __init__(self):        pygame.init()        self.screen = pygame.display.set_mode((640, 480))        self.clock = pygame.time.Clock()        self.movement= [False, False]        self.ymovement= [False, False]        self.assets = {"player": load_image("bonk.png"),"grass": load_image("grass.png")        }        self.tilemap = Tilemap(self, tile_size=32)        self.player=Entity(self, "player", (100,50), (44, 46))    def run(self):        while True:            self.screen.fill((0, 0, 0))            self.tilemap.render(self.screen)            self.player.update(self.tilemap, (self.movement[1] - self.movement[0], 0))            self.player.render(self.screen)            for event in pygame.event.get():                if event.type==pygame.QUIT:                    pygame.quit()                    sys.exit()                if event.type==pygame.KEYDOWN:                    if event.key==pygame.K_w:                        self.player.velocity[1] = -3                    if event.key==pygame.K_a:                        self.movement[0] = True                    if event.key==pygame.K_d:                        self.movement[1] = True                if event.type==pygame.KEYUP:                    if event.key==pygame.K_a:                        self.movement[0] = False                    if event.key==pygame.K_d:                        self.movement[1] = False            pygame.display.update()            self.clock.tick(60)Game().run()

I tested this with larger player entity sizes, and the effect is more pronounced.


Viewing all articles
Browse latest Browse all 23131

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>