Estoy tratando de hacer un juego con una biblioteca python llamada 'Pygame' (v1.9.2) y he creado un personaje para el jugador. Se supone que este personaje "dispara" "balas" o "hechizos" hasta el punto de mouse_pos y con lo que necesito ayuda es que la "bala" tiene una velocidad constante asignada a 1 self.speed = 1, si Intento aumentar la velocidad, causará un efecto de parpadeo cuando la bala llegue a mouse_pos porque self.pos será mayor o menor que mouse_pos.

¿Cómo puedo hacer que esta viñeta sea rápida y suave como una viñeta y aún así llegar al punto exacto donde se establece mouse_pos?

Ejemplo con self.speed = 1
https://media.giphy.com/media/AAifrctxHHQbe/giphy.gif

Ejemplo con self.speed = 2
http://4.1m.yt/d_TmNNq.gif

El código relacionado está dentro de la función update ()
Sprites.py (clase de hechizo / viñeta)

class Spell(pygame.sprite.Sprite):
    def __init__(self,game,x,y,spelltype,mouse_pos):
        pygame.sprite.Sprite.__init__(self)
        self.game = game
        self.width = TILESIZE
        self.height = TILESIZE
        self.type = spelltype
        self.effects = [
                'effect_'+self.type+'_00',
                'effect_'+self.type+'_01',
                'effect_'+self.type+'_02'
        ]
        self.image = pygame.image.load(path.join(IMG_DIR,"attack/attack_"+self.type+".png")).convert_alpha()
        self.image = pygame.transform.scale(self.image,(self.width,self.height))
        self.rect = self.image.get_rect()
        self.rect.x = x+self.width
        self.rect.y = y+self.height
        self.speed = 1
        self.mouse_pos = mouse_pos
        self.idx = 0

    def update(self):
        if not self.rect.collidepoint(self.mouse_pos):
            if self.mouse_pos[0] < self.rect.x:
                self.rect.x -= self.speed
            elif self.mouse_pos[0] > self.rect.x:
                self.rect.x += self.speed

            if self.mouse_pos[1] < self.rect.y:
                self.rect.y -= self.speed
            elif self.mouse_pos[1] > self.rect.y:
                self.rect.y += self.speed
        else:
            self.image = pygame.image.load(path.join(IMG_DIR,"effects/"+self.effects[self.idx]+".png"))
            self.idx += 1
            if self.idx >= len(self.effects):
                self.kill()
3
Feelsbadman 13 may. 2017 a las 12:22

2 respuestas

La mejor respuesta

Si su bala pasa tan rápido que atraviesa el objetivo, es posible que desee probar si la línea entre el punto actual de las balas y su último punto se cruzan con su objetivo.

Un poco más de detalle está disponible aquí: https://gamedev.stackexchange.com/questions/18604/how-do-i-handle-collision-detection-so-fast-objects-are-not-allowed-to-pass- thro

2
Lanting 19 may. 2017 a las 12:18

El teorema de Pitágoras dice la distancia entre puntos en el espacio n-dimensional. Para su caso

distance = math.sqrt(sum[ (self.mouse_pos[0] - self.rect.x) ** 2 
                        , (self.mouse_pos[1] - self.rect.y) ** 2
                        ]))
if distance < self.speed: 
    #remove the bullet from the scene

Esta no es una gran solución, porque la bala se moverá de manera poco realista, con diferentes velocidades en diferentes ángulos. De hecho, se moverá a una velocidad de sqrt (2) en un ángulo de 45 'y con una velocidad de 1 a 90'.

Pero, supongo que no quieres una conferencia de trigonometría.

EDITAR: Aquí está la conferencia de trigonometría. Su programa moverá la bala de manera realista porque lo mueve a toda velocidad en las direcciones x e y. Lo que debe hacer es que la velocidad sea más lenta en ambas direcciones, de modo que la hipotenusa del triángulo que forman la velocidad xy la velocidad y (vectores) sea igual a 1. Dado que la velocidad es siempre 1, este triángulo , resulta ser el círculo unitario.

       m
       |\
       | \
sin(A) |  \ This speed is 1
       |   \
       |   A\
       ------p
        cos(A)

Si su personaje está en p, y el mouse está en m, entonces encontrará el ángulo entre ellos etiquetado aquí como A. Entonces, la velocidad x será el coseno de A y la velocidad y será el seno de A.

¿Cómo encuentras el ángulo? usa el arcotangente ... de hecho, aquí está el código para usar.

import math
if not self.rect.collidepoint(self.mouse_pos):
        angle = math.atan2( (self.mouse_pos[1] - self.rect.y)
                          , (self.mouse_pos[0] - self.rect.x)
        self.rect.x += self.speed * math.cos(angle)
        self.rect.y += self.speed * math.sin(angle)

O algo más como eso. Puedo tener mis símbolos mezclados.

2
VoNWooDSoN 24 may. 2017 a las 17:24