Pygame bullet movement from point A to point B
I am trying to create a game with a library python
called " Pygame
" (v1.9.2) and I have made a character for the player. This character has to "shoot" "bullets" or "spells" at the point mouse_pos
, and I need help getting the "bullet" to have a constant velocity set to 1 self.speed = 1
, if I try to increase the velocity it will have a flickering effect when the bullet reaches mouse_pos. because self.pos will be either above or below mouse_pos.
How can I make this bullet fast and smooth like a bullet and get to the point where mouse_pos is set?
Example with self.speed = 1
Example with self.speed = 2
http://4.1m.yt/d_TmNNq.gif
the related code is inside the update ()
function of Sprites.py (spell / bullet class)
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()
source to share
If your bullet is traveling so fast that it goes through the target, you may need to check if the line between the current points crosses the marker and the last point intersects with your target.
More information is available here: https://gamedev.stackexchange.com/questions/18604/how-do-i-handle-collision-detection-so-fast-objects-are-not-allowed-to-pass-thro
source to share
The Pythagorean theorem says the distance between points in n-dimensional space. For your case
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
This is not a great solution, because the bullet will move unrealistically, at different speeds at different angles. In fact, it will move at a speed of sqrt (2) at an angle of 45 feet and at a speed of 1 at 90 Β°.
But I suppose you don't need a trigonometry lecture.
EDIT: Here's a lecture on trigonometry. Your program will move the bullet realistically because it moves it at full speed in both the x and y directions. You need to make the speed slower in both directions, so the hypotenuse of the triangle is that the shape of the x speed and the y-speed (vectors) are 1. Since the speed is always 1, this triangle just turns out to be a unit circle.
m
|\
| \
sin(A) | \ This speed is 1
| \
| A\
------p
cos(A)
If your character is at point p and your mouse is at point m, then you will find the angle between them, denoted here as A. Then the x-speed will be the cosine of A, and the y-speed will be the sine of a.
How do you find the angle? you're using arctangent ... actually, here's the code to use.
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)
or something similar. Perhaps my symbols are confused.
source to share