【问题标题】:making a bullet move to your cursor using pygame使用 pygame 使子弹移动到光标
【发布时间】:2015-06-30 21:21:38
【问题描述】:

我正在编写一个相对复杂的平台游戏,其中玩家使用 wasd 移动并用鼠标射击。目标是让子弹在被点击时移动到鼠标的位置。我有这样的代码,但随着角度远离 0 或 90(直线左/右或直线上/下),子弹最终位置离光标更远。我相当肯定这个问题很简单,因为 x 和 y 的变化是浮点数,并且子弹的 x,y 位置不能是浮点数,所以会出现舍入问题。我根据论坛搜索尝试了许多不同的方法,所有方法都有相同的问题。我附上了最相关的文件(特别注意项目符号 init 类)。任何建议或帮助将不胜感激。为了记录,这只是播放器类而不是主要的。

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

【问题讨论】:

标签: python pygame sprite


【解决方案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))

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-24
    相关资源
    最近更新 更多