如何找到 Sprite 和屏幕角之间的距离(以像素为单位)?

编程入门 行业动态 更新时间:2024-10-23 20:28:55
本文介绍了如何找到 Sprite 和屏幕角之间的距离(以像素为单位)?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述

我需要找到动画 worker 对象与屏幕的 4 个角(左上、右上、左下、右下)之间的距离(以像素为单位).pygame 的哪个函数给出了这个信息?我需要在每次 update 迭代时获取此信息.

I need to find the distance (in pixels) between the animated worker objects and the 4 corners of the screen (upper left, upper right, lower left, lower right). Which function of pygame gives this information? I need to get this information at each update iteration.

import pygame, random import sys WHITE = (255, 255, 255) GREEN = (20, 255, 140) GREY = (210, 210 ,210) RED = (255, 0, 0) PURPLE = (255, 0, 255) SCREENWIDTH=1000 SCREENHEIGHT=578 IMG_BACKGROUND = "background.jpg" IMG_WORKER_RUNNING = "images/workers/worker_1.png" IMG_WORKER_IDLE = "images/workers/worker_2.png" IMG_WORKER_ACCIDENT = "images/workers/accident.png" class Background(pygame.sprite.Sprite): def __init__(self, image_file, location, *groups): # we set a _layer attribute before adding this sprite to the sprite groups # we want the background to be actually in the back self._layer = -1 pygame.sprite.Sprite.__init__(self, groups) # let's resize the background image now and only once self.image = pygame.transform.scale(pygame.image.load(image_file).convert(), (SCREENWIDTH, SCREENHEIGHT)) self.rect = self.image.get_rect(topleft=location) class GeoFenceInfluenceZone(pygame.sprite.Sprite): def __init__(self, rect, *groups): # we set a _layer attribute before adding this sprite to the sprite groups self._layer = 0 pygame.sprite.Sprite.__init__(self, groups) self.image = pygame.surface.Surface((rect.width, rect.height)) self.image.fill(GREY) self.rect = rect class GeoFence(pygame.sprite.Sprite): def __init__(self, rect, risk_level, *groups): # we set a _layer attribute before adding this sprite to the sprite groups self._layer = 1 pygame.sprite.Sprite.__init__(self, groups) self.image = pygame.surface.Surface((rect.width, rect.height)) self.image.fill(GREEN) self.rect = rect self.risk_level = risk_level self.font = pygame.font.SysFont('Arial', 20) text = self.font.render(risk_level, 1, (255,0,0), GREEN) text_rect = text.get_rect(center=(rect.width/2, rect.height/2)) self.image.blit(text, text_rect) class Worker(pygame.sprite.Sprite): # we introduce to possible states: RUNNING and IDLE RUNNING = 0 IDLE = 1 ACCIDENT = 2 NUMBER_OF_ACCIDENTS = 0 def __init__(self, image_running, image_idle, image_accident, location, *groups): self.font = pygame.font.SysFont('Arial', 10) # each state has it's own image self.images = { Worker.RUNNING: pygame.transform.scale(get_image(image_running), (45, 45)), Worker.IDLE: pygame.transform.scale(get_image(image_idle), (20, 45)), Worker.ACCIDENT: pygame.transform.scale(get_image(image_accident), (40, 40)) } # we set a _layer attribute before adding this sprite to the sprite groups # we want the workers on top self._layer = 2 pygame.sprite.Sprite.__init__(self, groups) # let's keep track of the state and how long we are in this state already self.state = Worker.IDLE self.ticks_in_state = 0 self.image = self.images[self.state] self.rect = self.image.get_rect(topleft=location) self.direction = pygame.math.Vector2(0, 0) self.speed = random.randint(1, 3) self.set_random_direction() def set_random_direction(self): # random new direction or standing still vec = pygame.math.Vector2(random.randint(-100,100), random.randint(-100,100)) if random.randint(0, 5) > 1 else pygame.math.Vector2(0, 0) # check the new vector and decide if we are running or fooling around length = vec.length() speed = sum(abs(int(v)) for v in vec.normalize() * self.speed) if length > 0 else 0 if (length == 0 or speed == 0) and (self.state != Worker.ACCIDENT): new_state = Worker.IDLE self.direction = pygame.math.Vector2(0, 0) elif self.state != Worker.ACCIDENT: new_state = Worker.RUNNING self.direction = vec.normalize() else: new_state = Worker.ACCIDENT self.ticks_in_state = 0 self.state = new_state # use the right image for the current state self.image = self.images[self.state] def update(self, screen): self.ticks_in_state += 1 # the longer we are in a certain state, the more likely is we change direction if random.randint(0, self.ticks_in_state) > 70: self.set_random_direction() # now let's multiply our direction with our speed and move the rect vec = [int(v) for v in self.direction * self.speed] self.rect.move_ip(*vec) # if we're going outside the screen, change direction if not screen.get_rect().contains(self.rect): self.direction = self.direction * -1 # spritecollide returns a list of all sprites in the group that collide with # the given sprite, but if the sprite is in this group itself, we have # to ignore a collision with itself if any(s for s in pygame.sprite.spritecollide(self, building_materials, False) if s != self): self.direction = self.direction * -1 if any(s for s in pygame.sprite.spritecollide(self, machines, False) if s != self): self.direction = self.direction * -1 # Risk handling self.handle_risks() self.rect.clamp_ip(screen.get_rect()) def handle_risks(self): for s in pygame.sprite.spritecollide(self, fences, False): if s != self: self.speed = 0 self.state = Worker.ACCIDENT self.image = self.images[self.state] Worker.NUMBER_OF_ACCIDENTS += 1 class BuildingMaterials(pygame.sprite.Sprite): def __init__(self, image_file, location, *groups): # we set a _layer attribute before adding this sprite to the sprite groups self._layer = 2 pygame.sprite.Sprite.__init__(self, groups) self.image = pygame.transform.scale(pygame.image.load(image_file).convert_alpha(), (40, 40)) self.rect = self.image.get_rect(topleft=location) class Excavator(pygame.sprite.Sprite): def __init__(self, image_file, location, *groups): # we set a _layer attribute before adding this sprite to the sprite groups self._layer = 3 pygame.sprite.Sprite.__init__(self, groups) self.image = pygame.transform.scale(pygame.image.load(image_file).convert_alpha(), (170, 170)) self.rect = self.image.get_rect(topleft=location) image_cache = {} def get_image(key): if not key in image_cache: image_cache[key] = pygame.image.load(key) return image_cache[key] pygame.init() # currently, one group would be enough # but if you want to use some collision handling in the future # it's best to group all sprites into special groups (no pun intended) all_sprites = pygame.sprite.LayeredUpdates() workers = pygame.sprite.Group() building_materials = pygame.sprite.Group() fences = pygame.sprite.Group() fences_infl_zones = pygame.sprite.Group() screen = pygame.display.set_mode((SCREENWIDTH, SCREENHEIGHT)) pygame.display.set_caption("TEST") # create multiple workers for pos in ((30,30), (50, 400), (200, 100), (700, 200)): Worker(IMG_WORKER_RUNNING, IMG_WORKER_IDLE, IMG_WORKER_ACCIDENT, pos, all_sprites, workers, building_materials, machines, fences) # create multiple building material stocks for pos in ((50,460),(50,500),(100,500),(850,30),(800,30)): BuildingMaterials("images/materials/building_blocks{}.png".format(random.randint(1,3)), pos, all_sprites, building_materials) # create multiple geo-fences risks = ["H","M","L"] for rect in (pygame.Rect(510,150,75,52), pygame.Rect(450,250,68,40), pygame.Rect(450,370,68,48), pygame.Rect(0,0,20,SCREENHEIGHT),pygame.Rect(0,0,SCREENWIDTH,20), pygame.Rect(SCREENWIDTH-20,0,20,SCREENHEIGHT),pygame.Rect(0,SCREENHEIGHT-20,SCREENWIDTH,20)): risk = risks[random.randint(0,2)] GeoFence(rect, risk, all_sprites, fences) # create influence zones for all geo-fences for rect in (pygame.Rect(495,135,105,80), pygame.Rect(435,235,98,68), pygame.Rect(435,355,98,76)): GeoFenceInfluenceZone(rect, all_sprites, fences_infl_zones) # and the background Background(IMG_BACKGROUND, [0,0], all_sprites) carryOn = True clock = pygame.time.Clock() while carryOn: for event in pygame.event.get(): if event.type==pygame.QUIT: carryOn = False pygame.display.quit() pygame.quit() quit() all_sprites.update(screen) all_sprites.draw(screen) pygame.display.flip() clock.tick(20)

推荐答案

您可以为角创建点向量,然后只需减去精灵的位置(我在这里只使用鼠标位置)以获得指向角的向量角,最后调用length方法得到这些向量的长度.

You could create point vectors for the corners and then just subtract the position of the sprite (I just use the mouse pos here) to get vectors that point to the corners and finally call the length method to get the lengths of these vectors.

import pygame as pg from pygame.math import Vector2 pg.init() screen = pg.display.set_mode((640, 480)) width, height = screen.get_size() clock = pg.time.Clock() BG_COLOR = pg.Color('gray12') # Create point vectors for the corners. corners = [ Vector2(0, 0), Vector2(width, 0), Vector2(0, height), Vector2(width, height), ] done = False while not done: for event in pg.event.get(): if event.type == pg.QUIT: done = True mouse_pos = pg.mouse.get_pos() # Subtract the position from the point vectors and call the `length` # method of the resulting vectors to get the distances to the points. # Subtract the position from the point vectors and call the `length` # method of the resulting vectors to get the distances to the points. distances = [] for vec in corners: distance = (vec - mouse_pos).length() distances.append(distance) # The 4 lines above can be replaced by a list comprehension. # distances = [(vec - mouse_pos).length() for vec in corners] # I just display the distances in the window title here. pg.display.set_caption('{:.1f}, {:.1f}, {:.1f}, {:.1f}'.format(*distances)) screen.fill(BG_COLOR) pg.display.flip() clock.tick(60)

更多推荐

如何找到 Sprite 和屏幕角之间的距离(以像素为单位)?

本文发布于:2023-07-27 23:13:01,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1225204.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:像素   屏幕   距离   单位   Sprite

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!