So basically I’ve been tryng to create a small RPG for a school project and have struck a wall when trying to use attacks. I wanted the hitbox for the attack to be bigger than the characters usual hitbox, so I looked around and found rect.inflate() which seems to work. But it only extened in the bottom right corner. So now what I want to do is center it around my character so it has equal distance on all sides. I did try rect.center with another rect which I gave the variables of the first rect before inflatiing it (when it was centered on the character) but that doesn’t seem to work. So what I’d like is either a solution to center it, or maybe a better way to do my attacks because for now I just put another animation on top of the non-attacking one.
Any help at all will be appreciated!
P.S The problem most likely lies in the ATK function which is in the end of the sprites code.
Code down below
Main
import pygame
from sprite import *
from config import *
import sys
class Game:
def __init__(self):
pygame.init()
self.screen = pygame.display.set_mode((WIN_WIDTH, WIN_HEIGHT))
self.clock = pygame.time.Clock()
self.running = True
self.font = pygame.font.Font('ARCADECLASSIC.TTF', 32)
self.character_spritesheet = Spritesheet('img/Crusader.png')
self.terrain_spritesheet = Spritesheet('img/Full.png')
self.enemy_spritesheet = Spritesheet('img/Goblin1.png')
self.void_spritesheet = Spritesheet('img/void.png')
self.intro_background = pygame.image.load('./img/Castle2.jpg')
self.gameover_background = pygame.image.load('./img/gameover.jpg')
def createTilemap(self):
for i, row in enumerate(tilemap):
for j, column in enumerate(row):
Ground(self, j, i)
if column == "B":
Block(self, j, i)
if column == "P":
self.player = Player(self, j, i)
if column == "E":
Enemy(self, j, i)
if column == "V":
Void(self, j, i)
def new(self):
self.playing = True
self.all_sprites = pygame.sprite.LayeredUpdates()
self.blocks = pygame.sprite.LayeredUpdates()
self.player = pygame.sprite.LayeredUpdates()
self.enemies = pygame.sprite.LayeredUpdates()
self.attacks = pygame.sprite.LayeredUpdates()
self.createTilemap()
def update(self):
self.all_sprites.update()
def draw(self):
self.screen.fill(BLACK)
self.all_sprites.draw(self.screen)
self.clock.tick(FPS)
pygame.display.update()
def events(self):
for event in pygame.event.get():
if event.type == pygame.QUIT:
self.playing = False
self.running = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
Atk(self, self.player.rect.x, self.player.rect.y)
def main(self):
while self.playing:
self.events()
self.update()
self.draw()
def gameover(self):
text = self.font.render('Quest Failed', True, RED)
text_rect = text.get_rect(center=(WIN_WIDTH/2, WIN_HEIGHT/2))
restart_button = Button(560, 200, 100, 50, WHITE, BLACK, 'Retry', 32)
for sprite in self.all_sprites:
sprite.kill()
while self.running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
self.running = False
mouse_pos = pygame.mouse.get_pos()
mouse_pressed = pygame.mouse.get_pressed()
if restart_button.is_pressed(mouse_pos, mouse_pressed):
self.new()
self.main()
self.screen.blit(self.gameover_background, (0,0))
self.screen.blit(text, text_rect)
self.screen.blit(restart_button.image, restart_button.rect)
self.clock.tick(FPS)
pygame.display.update
def intro_screen(self):
intro = True
title = self.font.render('Knights Quest', True, BLACK)
title_rect = title.get_rect(x=10, y=10)
play_button = Button(560, 200, 100, 50, WHITE, BLACK, 'Play', 32)
while intro:
for event in pygame.event.get():
if event.type == pygame.QUIT:
intro = False
self.running = False
mouse_pos = pygame.mouse.get_pos()
mouse_pressed = pygame.mouse.get_pressed()
if play_button.is_pressed(mouse_pos, mouse_pressed):
intro = False
self.screen.blit(self.intro_background, (0,0))
self.screen.blit(title, title_rect)
self.screen.blit(play_button.image, play_button.rect)
self.clock.tick(FPS)
pygame.display.update()
g = Game()
g.intro_screen()
g.new()
while g.running:
g.main()
g.gameover()
pygame.quit()
sys.exit()
sprites
`import pygame
from config import *
import math
import random
class Spritesheet:
def __init__(self, file):
self.sheet = pygame.image.load(file).convert()
def get_sprite(self, x, y, width, height):
sprite = pygame.Surface([width, height])
sprite.blit(self.sheet, (0,0), (x, y, width, height))
sprite.set_colorkey(BLACK)
return sprite
def get_sprite_void(self, x, y, width, height):
sprite = pygame.Surface([width, height])
sprite.blit(self.sheet, (0,0), (x, y, width, height))
return sprite
class Player(pygame.sprite.Sprite):
def __init__(self, game, x, y):
self.game = game
self._layer = PLAYER_LAYER
self.groups = self.game.all_sprites
pygame.sprite.Sprite.__init__(self, self.groups)
self.x = x * SPRITESIZE
self.y = y * SPRITESIZE
self.width = SPRITESIZE
self.height = SPRITESIZE
self.x_change = 0
self.y_change = 0
self.facing = 'down'
self.animation_loop = 1
self.image = self.game.character_spritesheet.get_sprite(0, 0, self.width, self.height)
self.image = pygame.transform.scale(self.image, (32, 32))
self.rect = self.image.get_rect()
self.rect.x = self.x
self.rect.y = self.y
def update(self):
self.movement()
self.animate()
self.collide_enemy()
self.rect.x += self.x_change
self.collide_blocks('x')
self.rect.y += self.y_change
self.collide_blocks('y')
self.x_change = 0
self.y_change = 0
def movement(self):
keys = pygame.key.get_pressed()
if keys[pygame.K_LEFT]:
for sprite in self.game.all_sprites:
sprite.rect.x += PLAYER_SPEED
self.x_change -= PLAYER_SPEED
self.facing = 'left'
if keys[pygame.K_RIGHT]:
for sprite in self.game.all_sprites:
sprite.rect.x -= PLAYER_SPEED
self.x_change += PLAYER_SPEED
self.facing = 'right'
if keys[pygame.K_UP]:
for sprite in self.game.all_sprites:
sprite.rect.y += PLAYER_SPEED
self.y_change -= PLAYER_SPEED
self.facing = 'up'
if keys[pygame.K_DOWN]:
for sprite in self.game.all_sprites:
sprite.rect.y -= PLAYER_SPEED
self.y_change += PLAYER_SPEED
self.facing = 'down'
if keys[pygame.K_a]:
for sprite in self.game.all_sprites:
sprite.rect.x += PLAYER_SPEED
self.x_change -= PLAYER_SPEED
self.facing = 'left'
if keys[pygame.K_d]:
for sprite in self.game.all_sprites:
sprite.rect.x -= PLAYER_SPEED
self.x_change += PLAYER_SPEED
self.facing = 'right'
if keys[pygame.K_w]:
for sprite in self.game.all_sprites:
sprite.rect.y += PLAYER_SPEED
self.y_change -= PLAYER_SPEED
self.facing = 'up'
if keys[pygame.K_s]:
for sprite in self.game.all_sprites:
sprite.rect.y -= PLAYER_SPEED
self.y_change += PLAYER_SPEED
self.facing = 'down'
def collide_enemy(self):
hits = pygame.sprite.spritecollide(self, self.game.enemies, False)
if hits:
self.kill()
self.game.playing = False
def collide_blocks(self, direction):
if direction == "x":
hits = pygame.sprite.spritecollide(self, self.game.blocks, False)
if hits:
if self.x_change > 0:
for sprite in self.game.all_sprites:
sprite.rect.x += PLAYER_SPEED
self.rect.x = hits[0].rect.left - self.rect.width
if self.x_change < 0:
for sprite in self.game.all_sprites:
sprite.rect.x -= PLAYER_SPEED
self.rect.x = hits[0].rect.right
if direction == "y":
hits = pygame.sprite.spritecollide(self, self.game.blocks, False)
if hits:
if self.y_change > 0:
for sprite in self.game.all_sprites:
sprite.rect.y += PLAYER_SPEED
self.rect.y = hits[0].rect.top - self.rect.height
if self.y_change < 0:
for sprite in self.game.all_sprites:
sprite.rect.y -= PLAYER_SPEED
self.rect.y = hits[0].rect.bottom
def animate(self):
up_animations = [self.game.character_spritesheet.get_sprite(0, 512, self.width, self.height),
self.game.character_spritesheet.get_sprite(64, 512, self.width, self.height),
self.game.character_spritesheet.get_sprite(128, 512, self.width, self.height),
self.game.character_spritesheet.get_sprite(192, 512, self.width, self.height),
self.game.character_spritesheet.get_sprite(256, 512, self.width, self.height),
self.game.character_spritesheet.get_sprite(320, 512, self.width, self.height),
self.game.character_spritesheet.get_sprite(384, 512, self.width, self.height),
self.game.character_spritesheet.get_sprite(448, 512, self.width, self.height),
self.game.character_spritesheet.get_sprite(512, 512, self.width, self.height)]
left_animations=[self.game.character_spritesheet.get_sprite(0, 576, self.width, self.height),
self.game.character_spritesheet.get_sprite(64, 576, self.width, self.height),
self.game.character_spritesheet.get_sprite(128, 576, self.width, self.height),
self.game.character_spritesheet.get_sprite(192, 576, self.width, self.height),
self.game.character_spritesheet.get_sprite(256, 576, self.width, self.height),
self.game.character_spritesheet.get_sprite(320, 576, self.width, self.height),
self.game.character_spritesheet.get_sprite(384, 576, self.width, self.height),
self.game.character_spritesheet.get_sprite(448, 576, self.width, self.height),
self.game.character_spritesheet.get_sprite(512, 576, self.width, self.height)]
down_animations = [self.game.character_spritesheet.get_sprite(0, 640, self.width, self.height),
self.game.character_spritesheet.get_sprite(64, 640, self.width, self.height),
self.game.character_spritesheet.get_sprite(128, 640, self.width, self.height),
self.game.character_spritesheet.get_sprite(192, 640, self.width, self.height),
self.game.character_spritesheet.get_sprite(256, 640, self.width, self.height),
self.game.character_spritesheet.get_sprite(320, 640, self.width, self.height),
self.game.character_spritesheet.get_sprite(384, 640, self.width, self.height),
self.game.character_spritesheet.get_sprite(448, 640, self.width, self.height),
self.game.character_spritesheet.get_sprite(512, 640, self.width, self.height)]
right_animations =[self.game.character_spritesheet.get_sprite(0, 704, self.width, self.height),
self.game.character_spritesheet.get_sprite(64, 704, self.width, self.height),
self.game.character_spritesheet.get_sprite(128, 704, self.width, self.height),
self.game.character_spritesheet.get_sprite(192, 704, self.width, self.height),
self.game.character_spritesheet.get_sprite(256, 704, self.width, self.height),
self.game.character_spritesheet.get_sprite(320, 704, self.width, self.height),
self.game.character_spritesheet.get_sprite(384, 704, self.width, self.height),
self.game.character_spritesheet.get_sprite(448, 704, self.width, self.height),
self.game.character_spritesheet.get_sprite(512, 704, self.width, self.height),]
if self.facing == 'down':
if self.y_change == 0:
self.image = self.game.character_spritesheet.get_sprite(0, 640, self.width, self.height)
else:
self.image = down_animations[math.floor(self.animation_loop)]
self.animation_loop += 0.2
if self.animation_loop >= 9:
self.animation_loop = 1
if self.facing == 'up':
if self.y_change == 0:
self.image = self.game.character_spritesheet.get_sprite(0, 512, self.width, self.height)
else:
self.image = up_animations[math.floor(self.animation_loop)]
self.animation_loop += 0.2
if self.animation_loop >= 9:
self.animation_loop = 1
if self.facing == 'right':
if self.x_change == 0:
self.image = self.game.character_spritesheet.get_sprite(0, 704, self.width, self.height)
else:
self.image = right_animations[math.floor(self.animation_loop)]
self.animation_loop += 0.2
if self.animation_loop >= 9:
self.animation_loop = 1
if self.facing == 'left':
if self.x_change == 0:
self.image = self.game.character_spritesheet.get_sprite(0, 576, self.width, self.height)
else:
self.image = left_animations[math.floor(self.animation_loop)]
self.animation_loop += 0.2
if self.animation_loop >= 9:
self.animation_loop = 1
class Enemy(pygame.sprite.Sprite):
def __init__(self, game, x, y):
self.game = game
self._layer = ENEMY_LAYER
self.groups = self.game.all_sprites, self.game.enemies
pygame.sprite.Sprite.__init__(self, self.groups)
self.x = x * SPRITESIZE
self.y = y * SPRITESIZE
self.width = SPRITESIZE
self.height = SPRITESIZE
self.x_change = 0
self.y_change = 0
self.facing = random.choice(['left', 'right', 'up', 'down'])
self.animation_loop = 1
self.movement_loop = 0
self.max_travel = random.randint(30, 34)
self.image = self.game.enemy_spritesheet.get_sprite(38, 1640, self.width, self.height)
self.image = pygame.transform.scale(self.image, (32, 32))
self.image.set_colorkey(BLACK)
self.rect = self.image.get_rect()
self.rect.x = self.x
self.rect.y = self.y
def update(self):
self.movement()
self.animate()
self.rect.x += self.x_change
self.collide_blocks('x')
self.rect.y += self.y_change
self.collide_blocks('y')
self.x_change = 0
self.y_change = 0
def collide_blocks(self, direction):
if direction == "x":
hits = pygame.sprite.spritecollide(self, self.game.blocks, False)
if hits:
if self.x_change > 0:
self.rect.x = hits[0].rect.left - self.rect.width
if self.x_change < 0:
self.rect.x = hits[0].rect.right
if direction == "y":
hits = pygame.sprite.spritecollide(self, self.game.blocks, False)
if hits:
if self.y_change > 0:
self.rect.y = hits[0].rect.top - self.rect.height
if self.y_change < 0:
self.rect.y = hits[0].rect.bottom
def movement(self):
if self.facing == 'left':
self.x_change -= ENEMY_SPEED
self.movement_loop -= 1
if self.movement_loop <= -self.max_travel:
self.facing = random.choice(['right', 'up', 'down'])
if self.facing == 'right':
self.x_change += ENEMY_SPEED
self.movement_loop += 1
if self.movement_loop >= self.max_travel:
self.facing = random.choice(['left', 'up', 'down'])
if self.facing == 'down':
self.y_change += ENEMY_SPEED
self.movement_loop -= 1
if self.movement_loop <= -self.max_travel:
self.facing = random.choice(['left', 'up', 'right'])
if self.facing == 'up':
self.y_change -= ENEMY_SPEED
self.movement_loop += 1
if self.movement_loop >= self.max_travel:
self.facing = random.choice(['right', 'left', 'down'])
def animate(self):
up_animations = [self.game.enemy_spritesheet.get_sprite(32, 1376, self.width, self.height),
self.game.enemy_spritesheet.get_sprite(160, 1376, self.width, self.height),
self.game.enemy_spritesheet.get_sprite(288, 1376, self.width, self.height),
self.game.enemy_spritesheet.get_sprite(416, 1376, self.width, self.height),
self.game.enemy_spritesheet.get_sprite(544, 1376, self.width, self.height),
self.game.enemy_spritesheet.get_sprite(672, 1376, self.width, self.height),
self.game.enemy_spritesheet.get_sprite(800, 1376, self.width, self.height),
self.game.enemy_spritesheet.get_sprite(928, 1376, self.width, self.height),
self.game.enemy_spritesheet.get_sprite(1056, 1376, self.width, self.height)]
left_animations=[self.game.enemy_spritesheet.get_sprite(32, 1504, self.width, self.height),
self.game.enemy_spritesheet.get_sprite(160, 1504, self.width, self.height),
self.game.enemy_spritesheet.get_sprite(288, 1504, self.width, self.height),
self.game.enemy_spritesheet.get_sprite(416, 1504, self.width, self.height),
self.game.enemy_spritesheet.get_sprite(544, 1504, self.width, self.height),
self.game.enemy_spritesheet.get_sprite(672, 1504, self.width, self.height),
self.game.enemy_spritesheet.get_sprite(800, 1504, self.width, self.height),
self.game.enemy_spritesheet.get_sprite(928, 1504, self.width, self.height),
self.game.enemy_spritesheet.get_sprite(1056, 1504, self.width, self.height)]
down_animations = [self.game.enemy_spritesheet.get_sprite(32, 1632, self.width, self.height),
self.game.enemy_spritesheet.get_sprite(160, 1632, self.width, self.height),
self.game.enemy_spritesheet.get_sprite(288, 1632, self.width, self.height),
self.game.enemy_spritesheet.get_sprite(416, 1632, self.width, self.height),
self.game.enemy_spritesheet.get_sprite(544, 1632, self.width, self.height),
self.game.enemy_spritesheet.get_sprite(672, 1632, self.width, self.height),
self.game.enemy_spritesheet.get_sprite(800, 1632, self.width, self.height),
self.game.enemy_spritesheet.get_sprite(928, 1632, self.width, self.height),
self.game.enemy_spritesheet.get_sprite(1056, 1632, self.width, self.height)]
right_animations =[self.game.enemy_spritesheet.get_sprite(32, 1760, self.width, self.height),
self.game.enemy_spritesheet.get_sprite(160, 1760, self.width, self.height),
self.game.enemy_spritesheet.get_sprite(288, 1760, self.width, self.height),
self.game.enemy_spritesheet.get_sprite(416, 1760, self.width, self.height),
self.game.enemy_spritesheet.get_sprite(544, 1760, self.width, self.height),
self.game.enemy_spritesheet.get_sprite(672, 1760, self.width, self.height),
self.game.enemy_spritesheet.get_sprite(800, 1760, self.width, self.height),
self.game.enemy_spritesheet.get_sprite(928, 1760, self.width, self.height),
self.game.enemy_spritesheet.get_sprite(1056, 1760, self.width, self.height)]
if self.facing == 'down':
if self.y_change == 0:
self.image = self.game.enemy_spritesheet.get_sprite(32, 1632, self.width, self.height)
else:
self.image = down_animations[math.floor(self.animation_loop)]
self.animation_loop += 0.2
if self.animation_loop >= 9:
self.animation_loop = 1
if self.facing == 'up':
if self.y_change == 0:
self.image = self.game.enemy_spritesheet.get_sprite(32, 1376, self.width, self.height)
else:
self.image = up_animations[math.floor(self.animation_loop)]
self.animation_loop += 0.2
if self.animation_loop >= 9:
self.animation_loop = 1
if self.facing == 'right':
if self.x_change == 0:
self.image = self.game.enemy_spritesheet.get_sprite(32, 1760, self.width, self.height)
else:
self.image = right_animations[math.floor(self.animation_loop)]
self.animation_loop += 0.2
if self.animation_loop >= 9:
self.animation_loop = 1
if self.facing == 'left':
if self.x_change == 0:
self.image = self.game.enemy_spritesheet.get_sprite(32, 1504, self.width, self.height)
else:
self.image = left_animations[math.floor(self.animation_loop)]
self.animation_loop += 0.2
if self.animation_loop >= 9:
self.animation_loop = 1
class Block(pygame.sprite.Sprite):
def __init__(self, game, x, y):
self.game = game
self._layer = BLOCK_LAYER
self.groups = self.game.all_sprites, self.game.blocks
pygame.sprite.Sprite.__init__(self, self.groups)
self.x = x * TILESIZE
self.y = y * TILESIZE
self.width = TILESIZE
self.height = TILESIZE
self.image = self.game.terrain_spritesheet.get_sprite_void(32, 32, self.width, self.height)
self.rect = self.image.get_rect()
self.rect.x = self.x
self.rect.y = self.y
class Void(pygame.sprite.Sprite):
def __init__(self, game, x, y):
self.game = game
self._layer = BLOCK_LAYER
self.groups = self.game.all_sprites, self.game.blocks
pygame.sprite.Sprite.__init__(self, self.groups)
self.x = x * TILESIZE
self.y = y * TILESIZE
self.width = TILESIZE
self.height = TILESIZE
self.image = self.game.void_spritesheet.get_sprite(190, 120, self.width, self.height)
self.rect = self.image.get_rect()
self.rect.x = self.x
self.rect.y = self.y
class Ground(pygame.sprite.Sprite):
def __init__(self, game, x, y):
self.game = game
self._layer = GROUND_LAYER
self.groups = self.game.all_sprites
pygame.sprite.Sprite.__init__(self, self.groups)
self.x = x * TILESIZE
self.y = y * TILESIZE
self.width = TILESIZE
self.height = TILESIZE
self.image = self.game.terrain_spritesheet.get_sprite(64, 64, self.width, self.height)
self.rect = self.image.get_rect()
self.rect.x = self.x
self.rect.y = self.y
class Button:
def __init__(self, x, y, width, height, fg, bg, content, fontsize):
self.font = pygame.font.Font('ARCADECLASSIC.TTF', fontsize)
self.content = content
self.x = x
self.y = y
self.width = width
self.height = height
self.fg = fg
self.bg = bg
self.image = pygame.Surface((self.width, self.height))
self.image.fill(self.bg)
self.rect = self.image.get_rect()
self.rect.x = self.x
self.rect.y = self.y
self.text = self.font.render(self.content, True, self.fg)
self.text_rect = self.text.get_rect(center = (self.width/2, self.height/2))
self.image.blit(self.text, self.text_rect)
def is_pressed(self, pos, pressed):
if self.rect.collidepoint(pos):
if pressed[0]:
return True
return False
return False
class Atk(pygame.sprite.Sprite):
def __init__(self, game, x, y):
self.game = game
self._layer = ATK_LAYER
self.groups = self.game.all_sprites, self.game.attacks
pygame.sprite.Sprite.__init__(self, self.groups)
self.x = x
self.y = y
self.width = SPRITESIZE
self.height = SPRITESIZE
self.animation_loop = 0
self.image = self.game.character_spritesheet.get_sprite(38, 1640, self.width, self.height)
self.rect = self.image.get_rect()
self.rect2 = self.rect
self.rect = self.rect.inflate(256, 256)
self.rect.center = self.rect2.center
self.rect.x = self.x
self.rect.y = self.y
def update(self):
self.animate()
self.collide()
def collide(self):
hits = pygame.sprite.spritecollide(self, self.game.enemies, True)
#animate function that i had to remove bc to many characters
if direction == 'up':
self.image = up_animations[math.floor(self.animation_loop)]
self.animation_loop += 0.2
if self.animation_loop >= 6:
self.kill()
if direction == 'down':
self.image = down_animations[math.floor(self.animation_loop)]
self.animation_loop += 0.2
if self.animation_loop >= 6:
self.kill()
if direction == 'left':
self.image = left_animations[math.floor(self.animation_loop)]
self.animation_loop += 0.2
if self.animation_loop >= 6:
self.kill()
if direction == 'right':
self.image = right_animations[math.floor(self.animation_loop)]
self.animation_loop += 0.2
if self.animation_loop >= 6:
self.kill()`
``
I have tried this:
self.rect = self.image.get_rect() self.rect2 = self.rect self.rect = self.rect.inflate(256, 256) self.rect.center = self.rect2.center
Which didn't seem to work, but there might have been some sort of trouble by giving both rect the same variables
Arvin is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.