From 4bfb6eff6b4834e7e626dd3356ff00913c22fc84 Mon Sep 17 00:00:00 2001 From: vlad Date: Fri, 2 Jun 2023 13:58:32 +0300 Subject: [PATCH] Finally, rotation centre! --- costume.py | 2 +- sb3Unpacker.py | 2 +- targetSprite.py | 14 +++--- tests.py | 111 +++++++++++++++++++++++++++--------------------- 4 files changed, 71 insertions(+), 58 deletions(-) diff --git a/costume.py b/costume.py index d9b1353..9d0ccbd 100644 --- a/costume.py +++ b/costume.py @@ -13,7 +13,7 @@ def __init__(self): self.dataFormat = "svg" self.rotationCenterX = 0 self.rotationCenterY = 0 - self.currentRotationCenter = (0, 0) + self.offset = None self.bitmapResolution = 1 self.file = None self.name = "" # display name diff --git a/sb3Unpacker.py b/sb3Unpacker.py index 29abed7..18afae0 100644 --- a/sb3Unpacker.py +++ b/sb3Unpacker.py @@ -61,8 +61,8 @@ def sb3Unpack(sb3): if "md5ext" in costumeObj: c.md5ext = costumeObj["md5ext"] c.rotationCenterX, c.rotationCenterY = costumeObj["rotationCenterX"], costumeObj["rotationCenterY"] - c.currentRotationCenter = (c.rotationCenterX, c.rotationCenterY) c.dataFormat = costumeObj["dataFormat"] + c.offset = pygame.math.Vector2(c.rotationCenterX, c.rotationCenterY) c.file = project.read(costumeObj["assetId"] + "." + costumeObj["dataFormat"]) c.name = costumeObj["name"] if costumeObj["dataFormat"] != "svg": diff --git a/targetSprite.py b/targetSprite.py index 9e94d56..fbfde4d 100644 --- a/targetSprite.py +++ b/targetSprite.py @@ -81,20 +81,18 @@ def setXy(self, x, y): y = scratch.HEIGHT / 2 + self.rect.height / 2 - 16 elif y < scratch.HEIGHT / -2 - self.rect.height / 2 + 16: y = scratch.HEIGHT / -2 - self.rect.height / 2 + 16 - # Set X and Y self.x = x self.y = y - print("aici") # print(_("debug-prefix"), _("new-sprite-position", x=x, y=y, name=self.name), file=sys.stderr) #rect = self.sprite.get_rect(topleft=(self.x - self.target.costumes[self.target.currentCostume].rotationCenterX, self.y - self.target.costumes[self.target.currentCostume].rotationCenterY)) - offset = pygame.Vector2(self.target.costumes[self.target.currentCostume].rotationCenterX - self.sprite.get_rect().width / 2, self.target.costumes[self.target.currentCostume].rotationCenterY - self.sprite.get_rect().height / 2) + offset = self.target.costumes[self.target.currentCostume].offset - pygame.math.Vector2(self.sprite.get_width() / 2, self.sprite.get_height() / 2) offset.rotate_ip(90 + self.direction) - self.image = pygame.transform.rotozoom(self.sprite, 90 - self.direction, 1) + self.image = pygame.transform.rotate(self.sprite, 90 - self.direction) # offset = pygame.Vector2(0, 0) - self.rect.centerx = scratch.WIDTH // 2 + self.x + offset.x - self.rect.centery = scratch.HEIGHT // 2 - self.y + offset.y - print(self.rect.x, self.rect.y, "/", self.x, self.y, "/", offset.x, offset.y) - # TODO update current rotation centre to correct sprite position + relativePosition = pygame.math.Vector2(self.spriteRect.centerx, self.spriteRect.centery) + position = pygame.math.Vector2(self.x - self.sprite.get_width() / 2 + scratch.WIDTH / 2, self.y - self.sprite.get_height() / 2 + scratch.HEIGHT / 2) + + self.rect = self.image.get_rect(center=position+relativePosition+offset) # Relatively set self position def setXyDelta(self, dx, dy): diff --git a/tests.py b/tests.py index 7d5d4cb..d6c00f0 100644 --- a/tests.py +++ b/tests.py @@ -1,48 +1,63 @@ -import pygame - -pygame.init() - -# Set up the window -screen = pygame.display.set_mode((640, 480)) - -# Load the sprite image -sprite_image = pygame.image.load("sprite.png") - -# Define the rotation center offset relative to the sprite's origin -rotation_center_offset = (20, 10) - -# Define the initial angle of the sprite -angle = 0 - -while True: - for event in pygame.event.get(): - if event.type == pygame.QUIT: - pygame.quit() - quit() - - # Calculate the rotation center position relative to the sprite's origin - rotation_center = ( - rotation_center_offset[0], - rotation_center_offset[1] - ) - - # Rotate the sprite image around the rotation center - rotated_image = pygame.transform.rotate(sprite_image, angle) - - # Get the rect of the rotated image - rect = rotated_image.get_rect() - - # Calculate the position of the sprite based on the rotation center and rect dimensions - position = ( - rotation_center[0] - rect.width / 2, - rotation_center[1] - rect.height / 2 - ) - - # Draw the rotated image to the screen at the calculated position - screen.blit(rotated_image, position) - - # Increment the angle - angle += 0.125 - - # Update the screen - pygame.display.update() +import pygame as pg +from pygame.math import Vector2 + + +class Entity(pg.sprite.Sprite): + + def __init__(self, pos): + super().__init__() + self.image = pg.Surface((122, 70), pg.SRCALPHA) + pg.draw.polygon(self.image, pg.Color('dodgerblue1'), + ((1, 0), (120, 35), (1, 70))) + # A reference to the original image to preserve the quality. + self.orig_image = self.image + self.rect = self.image.get_rect(center=pos) + self.pos = Vector2(pos) # The original center position/pivot point. + self.offset = Vector2(50, 0) # We shift the sprite 50 px to the right. + self.angle = 0 + + def update(self): + self.angle += 2 + self.rotate() + + def rotate(self): + """Rotate the image of the sprite around a pivot point.""" + # Rotate the image. + self.image = pg.transform.rotozoom(self.orig_image, -self.angle, 1) + # Rotate the offset vector. + offset_rotated = self.offset.rotate(self.angle) + # Create a new rect with the center of the sprite + the offset. + self.rect = self.image.get_rect(center=self.pos+offset_rotated) + + +def main(): + screen = pg.display.set_mode((640, 480)) + clock = pg.time.Clock() + entity = Entity((320, 240)) + all_sprites = pg.sprite.Group(entity) + + while True: + for event in pg.event.get(): + if event.type == pg.QUIT: + return + + keys = pg.key.get_pressed() + if keys[pg.K_d]: + entity.pos.x += 5 + elif keys[pg.K_a]: + entity.pos.x -= 5 + + all_sprites.update() + screen.fill((30, 30, 30)) + all_sprites.draw(screen) + pg.draw.circle(screen, (255, 128, 0), [int(i) for i in entity.pos], 3) + pg.draw.rect(screen, (255, 128, 0), entity.rect, 2) + pg.draw.line(screen, (100, 200, 255), (0, 240), (640, 240), 1) + pg.display.flip() + clock.tick(30) + + +if __name__ == '__main__': + pg.init() + main() + pg.quit()