2015-06-30 55 views
2

我正在寫一個相對複雜的一些平臺遊戲,其中玩家使用wasd移動並用鼠標拍攝。目標是在點擊鼠標時讓子彈前往鼠標的位置。我有這樣的代碼,但隨着角度從0或90(直向左/右或直上/下)變得更遠,子彈的最終位置離光標更遠。我相當確定這個問題很簡單,因爲x和y的變化是浮點和x,y項目符號的位置不能是浮點,所以會出現舍入問題。我已經嘗試了許多基於論壇搜索的不同方法,並且它們都有相同的問題。我附上了最相關的文件(特別注意init class)。任何意見或幫助,將不勝感激。對於記錄來說,這只是玩家級別不是主要的。使用pygame製作子彈移動到您的光標

import pygame 
import level 
import platform 
##import enemies 
import math 
pygame.init() 

## sets up colors that need to be used in every part of the program 
black=(0,0,0) 
white=(255,255,255) 
red=(255,0,0) 
green=(0,255,0) 
blue=(0,0,255) 


class Player(pygame.sprite.Sprite): 
    ## This class represents the player. It is inhariting from the Sprite class in Pygame 
    window=None 
    screen_width=0 
    screen_height=0 
    width=None 
    height=None 
    x_velocity=0 
    y_velocity=0 
    chrono_level=500 
    ball_damage=0 
    bomb_damage=0 
    blast_radius=0 
    gravity=0 
    isjumping=False 
    isducking=False 
    level=None 
    direction=None 

    def __init__(self,argwindow,argsheight,argswidth,argcolor=white,argwidth=40,argheight=60,argx=0,argy=0,argball_damage=5,argbomb_damage=15,argbomb_radius=10,argchrono_level=500): 
     ## Constructor. Pass in the color, width, and height 
     pygame.sprite.Sprite.__init__(self) 
     self.image = pygame.Surface([argwidth,argheight]) 
     self.image.fill(argcolor) 
     self.rect=self.image.get_rect() 
     ## sets up the variables inital variables 
     self.window=argwindow 
     self.width=argwidth 
     self.height=argheight 
     self.screen_height=argsheight 
     self.screen_width=argswidth 
     self.rect.x=argx 
     self.rect.y=argy 
     self.x_velocity=0 
     self.y_velocity=0 
     self.ball_damage=argball_damage 
     self.bomb_damage=argbomb_damage 
     self.bomb_radius=argbomb_radius 
     self.chrono_level=argchrono_level 
     self.isjumping=False 
     self.isducking=False 

    def update(self): 
     ## check gravity 
     self.calc_grav() 
     ## move left or right 
     self.rect.x+=self.x_velocity 
     ## check for any collisions 
     platform_hit_list=pygame.sprite.spritecollide(self,self.level.platform_list,False)## this is the pygame generatred collision detection builtin to the sprite class 
     for platform in platform_hit_list: 
      if self.x_velocity > 0:##i.e sprite was moving right 
       self.rect.right = platform.rect.left ##puts the right side of the sprite flush with the left side of the platform 
      elif self.x_velocity < 0: 
       self.rect.left = platform.rect.right 
      self.x_velocity=0   
     ## move sprite up or down 
     self.rect.y+=self.y_velocity 
     ## check for any collisions 
     platform_hit_list=pygame.sprite.spritecollide(self,self.level.platform_list,False)## this is the pygame generatred collision detection builtin to the sprite class 
     for platform in platform_hit_list: 
      if self.y_velocity > 0:## i.e. sprite is falling 
       self.rect.bottom = platform.rect.top ## puts bottom of player flush with top of platform 
       self.isjumping=False 
      elif self.y_velocity < 0: 
       self.rect.top = platform.rect.bottom 
      self.y_velocity=0 
     ## check direction 
     pos = pygame.mouse.get_pos() 
     if pos[0] > (self.rect.x+(self.width/2)): ##i.e. cursor is farther to the right then the middle of the sprite 
      self.direction="Right" 
     else: ##pos[0] < (self.rect.x+(self.width/2)) 
      self.direction="Left" 
    def jump(self): 
     if not self.isjumping: 
      self.y_velocity=-15 
      self.isjumping=True 

    def calc_grav(self): 
     if self.y_velocity ==0: 
      self.y_velocity=1 
     else: 
      self.y_velocity+=self.gravity 

     if self.rect.y >= self.screen_height - self.rect.height and self.y_velocity >= 0: 
      self.y_velocity = 0 
      self.rect.y = self.screen_height - self.rect.height 
      self.isjumping=False 

    def move_left(self):## called if the player hits the left arrow key or the a key 
     self.x_velocity=-5 

    def move_right(self):## called is the player hits the right arrow key or the d key 
     self.x_velocity=5 

    def stop(self):## called if the player lets up on either arrow key or the a or d key 
     self.x_velocity=0 

    def shoot(self,argmouse_position): 
     if self.direction=="Left": 
      bullet_start_x=self.rect.x 
      bullet_start_y=(self.rect.y+(self.height/2)) 
     elif self.direction=="Right": 
      bullet_start_x=(self.rect.x+self.width) 
      bullet_start_y=(self.rect.y+(self.height/2)) 
     bullet=player_bullet(bullet_start_x,bullet_start_y,argmouse_position) 
     return (bullet) 


class player_bullet(pygame.sprite.Sprite): 

    bullet_x=None 
    bullet_y=None 
    bullet_x_velocity=None 
    bullet_y_velocity=None 
    target_x=None 
    target_y=None 
    speed=10 

    def __init__(self,argx,argy,argmouse_positon): 
     pygame.sprite.Sprite.__init__(self) 
     print "it inited" 
     self.image = pygame.Surface([4, 10]) 
     self.image.fill(black) 
     self.rect=self.image.get_rect() 
     self.rect.x=argx 
     self.rect.y=argy 
     self.bullet_x=argx 
     self.bullet_y=argy 
     self.target_x=argmouse_positon[0] 
     self.target_y=argmouse_positon[1] 
     dx=self.target_x-self.bullet_x 
     dy=self.target_y-self.bullet_y 
     angle=math.atan2(dy,dx) 
     print angle 
     self.bullet_x_velocity=self.speed*math.cos(angle) 
     self.bullet_y_velocity=self.speed*math.sin(angle) 
    def update(self): 
     print self.rect.x 
     print self.bullet_x_velocity 
     self.rect.x+=self.bullet_x_velocity 
     print self.rect.x 
     self.rect.y+=self.bullet_y_velocity 
    def collide(self,argdisplay_width,argdisplay_height,argplatform_list): 
     Platform_hit_list=pygame.sprite.spritecollide(self, argplatform_list, False) 
     if len(Platform_hit_list) > 0: 
      return True 
     elif self.rect.x > argdisplay_width or self.rect.x < 0: 
      return True 
     elif self.rect.y > argdisplay_height or self.rect.y < 0: 
      return True 
     else: 
      return False 
+0

子彈的位置。看看他的回答:[使精靈移動到鼠標單擊位置一步一步](http://stackoverflow.com/a/16294710/142637) – sloth

+0

非常感謝你的幫助 –

回答

1

我已經寫了一個類似的遊戲機制,而不是子彈我可以射擊任何尺寸的任何子彈的任何子彈。我所做的是將我當前的位置添加到我必須移動的像素數量(定義爲vx,vy)。我發現我需要移動的像素的數量除以軸的差異,距離,乘以速度(通常爲10)。這裏是下面的彈丸類(掩碼的東西是如此的子彈沒有進入建築物):你必須創建代表你的子彈有前進的方向向量,並使用該矢量來更新

class projectile: 
    """an image goes towards the target from starting location""" 

    def __init__(self, xorg, yorg, x, y, sprite, speed): 
     self.x = xorg 
     self.y = yorg 
     self.gotox = x 
     self.gotoy = y 
     self.sprite = sprite 
     self.xsize = self.sprite.get_width() 
     self.ysize = self.sprite.get_height() 
     self.rect = Rect(self.x, self.y, self.xsize, self.ysize) 

     # divided by 2, because we want the middle of the projectile to goto the destination, not the edge 
     self.gotox -= self.xsize/2 
     self.gotoy -= self.ysize/2 

     self.speed = speed 

     #differance in the x and y axis of destination to current position 
     self.dx = self.gotox - self.x 
     self.dy = self.gotoy - self.y 

     self.slope = (self.dy/max(1, self.dx)) 
     self.gotox += self.gotox * self.slope 
     self.gotoy += self.gotoy * self.slope 
     self.dist = max(1, hypot(self.dx, self.dy)) 
     self.state = "alive" 
     self.rect = Rect(self.x, self.y, self.xsize, self.ysize) 

    def move(self): 
     """moves based on where the target was during time of shooting 
     untill it hits targer, or hits a wall""" 
     global currentMask 
     dist = max(1, hypot(self.dx, self.dy)) 

     # found the num of pixels I have to move (speed is usually 10) 
     self.vx = self.speed * (self.dx/self.dist) 
     self.vy = self.speed * (self.dy/self.dist) 

     if currentMask.get_at((int(self.x + self.vx), int(self.y + self.vy))) != (0, 0, 0) and currentMask.get_at(
       (int(self.x + self.vx + self.xsize), int(self.y + self.vy + self.ysize))) != (0, 0, 0) and int(
          self.y + self.vy + self.ysize) <= 800 - self.ysize and int(
        self.y + self.vy) >= 0 + self.ysize and int(self.x + self.vx) >= self.xsize and int(
          self.x + self.vx + self.xsize) <= 1200 - self.xsize: 
      # added the num of pixels i have to move, to my current postition 
      self.x += self.vx 
      self.y += self.vy 
     else: 
      self.state = "dead" 
     self.rect = Rect(self.x, self.y, self.xsize, self.ysize) 
     screen.blit(self.sprite, (self.x, self.y))