Pygame:子弹不会射到45度以上

时间:2013-12-12 19:28:37

标签: python math python-2.7 pygame

那么在我正在开发的游戏中,我最近允许鼠标点击鼠标所在的任何地方。但子弹只能以0度角或45度角射击。我想尝试将其设为360度。这是我的主要游戏文件的代码:

import pygame, sys
import random
import pygame.mixer
import Funk, math
from time import sleep
from player import *
from zombie import *
from level import *
from bullet import *
from constants import *
from Drops import *
from menus import *
from meteors import *
import menu as dm

class Game():

    def __init__(self):
        pygame.init()
        pygame.mixer.init()

        pygame.mixer.music.load('data/sounds/menugame.ogg')
        pygame.mixer.music.set_volume(0.5)
        pygame.mixer.music.play(-1)

        # A few variables
        self.gravity = .50
        self.red = (255, 0, 0)
        self.darkred = (200, 0, 0)
        self.darkblue = (0, 0, 200)
        self.darkgreen = (0, 200, 0)
        self.gameover = pygame.image.load('data/images/gameover.png')
        self.victory = pygame.image.load('data/images/victory.png')

        # Bullets and Drops
        self.bullets = []
        self.gameDrops = []

        # Screen
        icon = pygame.image.load('data/icons/moonsurvival.bmp')
        size = SCREEN_WIDTH, SCREEN_HEIGHT
        self.screen = pygame.display.set_mode(size)
        pygame.display.set_caption('Moon Survival!')
        pygame.display.set_icon(icon)
        self.screen_rect = self.screen.get_rect()

        # Moon / Background
        self.moon = Background()
        self.text1 = pygame.image.load('data/images/TextSlides/Text1.jpg')
        self.text2 = pygame.image.load('data/images/TextSlides/Text2.jpg')

        # Zombies and boss
        self.zombies = []
        self.bosses = []
        #for i in range(15):
        #    self.zombies.append( Zombie(random.randint(0,1280), random.randint(0,0)) )

        self.zombieskilled = 0

        # Spawn time
        self.last_spawn_time = 0

        # Meteors
        self.meteors = []

        # Menus
        self.menuStartGame = MenuStartGame(self.screen, self)
        self.menuAbout = MenuAbout(self.screen, self)
        #self.menuSettings = MenuSettings(self.screen, self)
        self.menuScene = MenuScene(self.screen, self)
        self.menuGameOver = MenuGameOver(self.screen, self)
        #self.menuGameFinish = MenuGameFinish(self.screen, self)

        # Player
        self.player = Player(25, 320, self.gravity)

        # Font for text
        self.font = pygame.font.SysFont(None, 72)

        self.point = self.player.rect.x, self.player.rect.y
        self.max_radius = math.hypot(self.screen_rect.w, self.screen_rect.h)
        self.mouse_angle = (0, 0)

        # game over
        self.gameover_text = self.font.render("The Aliens Are Too Good", -1, (255, 0, 0))
        self.gameover_rect = self.gameover_text.get_rect(center=self.screen.get_rect().center)

        # game state
        self.game_state = STATE_MENU

    def run(self):

        clock = pygame.time.Clock()

        # "state machine" 
        RUNNING   = True
        PAUSED    = False 
        GAME_OVER = False

        # Game loop
        while RUNNING:

            # (all) Events
            if self.game_state == STATE_INGAME:
                print(self.mouse_angle)

                for event in pygame.event.get():

                    if event.type == pygame.QUIT:
                        RUNNING = False

                    elif event.type == pygame.KEYDOWN:

                        if event.key == pygame.K_s:
                            if self.player.power == POWER_TRIBULLETS:
                                self.bullets.append(Bullet(self.player.rect.x + 35, self.player.rect.y + 35, self.mouse_angle))
                                self.bullets.append(Bullet(self.player.rect.x + 30, self.player.rect.y + 30, self.mouse_angle))
                                self.bullets.append(Bullet(self.player.rect.x + 35, self.player.rect.y + 25, self.mouse_angle))
                            else:
                                self.bullets.append(Bullet(self.player.rect.x + 30, self.player.rect.y + 30, self.mouse_angle))


                        if event.key == pygame.K_ESCAPE:
                            RUNNING = False

                        elif event.key == pygame.K_p:
                            # set state to paused
                            self.game_state = STATE_PAUSED

                    elif event.type == pygame.MOUSEBUTTONDOWN:

                        if event.button == 1:
                            if self.player.power == POWER_TRIBULLETS:
                                self.bullets.append(Bullet(self.player.rect.x + 35, self.player.rect.y + 35, self.mouse_angle))
                                self.bullets.append(Bullet(self.player.rect.x + 30, self.player.rect.y + 30, self.mouse_angle))
                                self.bullets.append(Bullet(self.player.rect.x + 35, self.player.rect.y + 25, self.mouse_angle))
                            else:
                                self.bullets.append(Bullet(self.player.rect.x + 30, self.player.rect.y + 30, self.mouse_angle))


                    # Player/Zombies events  
                    self.player.handle_events(event)

                # (all) Movements / Updates

                self.player_move()
                self.player.update()

                for z in self.zombies:
                    self.zombie_move(z)       
                    z.update(self.screen.get_rect())

                for boss in self.bosses:
                    self.boss_move(boss)       
                    boss.update(self.screen.get_rect())

                for b in self.bullets:
                    b.update()
                    for tile in self.moon.get_surrounding_blocks(b):
                        if tile is not None:
                            if pygame.sprite.collide_rect(b, tile):
                                # Destroy block
                                x = tile.rect.x / tile.rect.width
                                y = tile.rect.y / tile.rect.height
                                self.moon.levelStructure[x][y] = None
                                try:
                                    self.bullets.remove(b)
                                except:
                                    continue

                for m in self.meteors:
                    m.update()
                    for tile in self.moon.get_surrounding_blocks(m):
                        if tile is not None:
                            if pygame.sprite.collide_rect(m, tile):
                                # Destroy block
                                x = tile.rect.x / tile.rect.width
                                y = tile.rect.y / tile.rect.height
                                self.moon.levelStructure[x][y] = None
                                self.moon.levelStructure[x + 1][y + 1] = None
                                self.moon.levelStructure[x - 1][y - 1] = None
                                self.moon.levelStructure[x + 2][y + 2] = None
                                self.moon.levelStructure[x - 2][y - 2] = None
                                try:
                                    self.meteors.remove(m)
                                except:
                                    continue

                self.check_game_state()

                # (all) Display updating

                self.moon.render(self.screen)

                for z in self.zombies:
                    z.render(self.screen)

                for boss in self.bosses:
                    boss.render(self.screen)

                for b in self.bullets:
                    b.render(self.screen)

                for m in self.meteors:
                    m.render(self.screen)

                for drop in self.gameDrops:
                    drop.render(self.screen)

                self.player.render(self.screen)
                self.updateMousePosition(self.screen, pygame.mouse.get_pos())

                Funk.text_to_screen(self.screen, 'Level 1', 5, 675)
                Funk.text_to_screen(self.screen, 'Health: {0}'.format(self.player.health), 5, 0)
                Funk.text_to_screen(self.screen, 'Score: {0}'.format(self.player.score), 400, 0)
                Funk.text_to_screen(self.screen, 'Time: {0}'.format(self.player.alivetime), 750, 0)
                Funk.text_to_screen(self.screen, 'Kills: {0}'.format(self.zombieskilled), 5, 50)
                Funk.text_to_screen(self.screen, 'Lives: {0}'.format(self.player.lives), 300, 50)

            elif self.game_state == STATE_GAMEOVER:
                self.menuGameOver.draw()
                self.menuGameOver.update()

            elif self.game_state == STATE_SETTINGS:
                self.menuSettings.draw()
                self.menuSettings.update()

            elif self.game_state == STATE_ABOUT:
                self.menuAbout.draw()
                self.menuAbout.update()

            elif self.game_state == STATE_SCENE:
                self.menuScene.draw()
                self.menuScene.update()

            elif self.game_state == STATE_MENU:
                self.menuStartGame.draw()
                self.menuStartGame.update()

            elif self.game_state == STATE_PAUSED:
                # (all) Display updating

                if self.game_state == STATE_INGAME:
                    if event.type == pygame.QUIT:
                        RUNNING = False

                    elif event.type == pygame.KEYDOWN:
                        if event.key == pygame.K_ESCAPE:
                            RUNNING = False

                choose = dm.dumbmenu(self.screen, [
                            'Resume Game',

                            'Menu',

                            'Quit Game'], 200, 200,'orecrusherexpanded',100,0.75,self.darkred,self.red)

                if choose == 0:
                    print "You choose 'Start Game'."
                    # set state to ingame
                    self.game_state = STATE_INGAME
                elif choose == 1:
                    print "You choose 'Controls'."
                if choose == 2:
                    print "You choose 'Quit Game'."
                    pygame.quit()
                    sys.exit()

                #for event in pygame.event.get():


                self.moon.render(self.screen)

                for z in self.zombies:
                    z.render(self.screen)

                for boss in self.bosses:
                    boss.render(self.screen)

                for b in self.bullets:
                    b.render(self.screen)

                for m in self.meteors:
                    m.render(self.screen)

                self.player.render(self.screen)

            pygame.display.update()

            # FTP

            clock.tick(100)

        # --- the end ---
        pygame.quit()

    def updateMousePosition(self, surface, mouse):
        x_comp, y_comp = mouse[0] - self.point[0], mouse[1] - self.point[1]
        self.mouse_angle = math.atan2(y_comp, x_comp)
        x = self.max_radius * math.cos(self.mouse_angle) + self.point[0]
        y = self.max_radius * math.sin(self.mouse_angle) + self.point[1]
        pygame.draw.line(surface, pygame.Color("white"), self.point, (x, y))

    def check_game_state(self):
        elapsed_time = pygame.time.get_ticks()
        if elapsed_time > self.last_spawn_time + 10:
            # Spawn aliens
            if len(self.zombies) <= 10:
                self.zombies.append(Zombie(random.randint(0,1280), random.randint(0,0)))
                # Spawned! Change last spawn time!
                self.last_spawn_time = elapsed_time

        meteor_time = pygame.time.get_ticks()
        if meteor_time > self.last_spawn_time + random.randint(1000, 3000):
            # Spawn meteors
            if len(self.meteors) <= 1:
                self.meteors.append(Meteor(random.randint(0,1280), random.randint(-100,0)))
                # Spawned! Change last spawn time!
                self.last_spawn_time = meteor_time

    def player_move(self):
        # Line start
        self.point = self.player.rect.x + 30, self.player.rect.y + 30
        # add gravity
        self.player.do_jump()

        # simulate gravity
        self.player.on_ground = False
        if not self.player.on_ground and not self.player.jumping:
            self.player.velY = 4

        # Drops
        for drop in self.gameDrops:
            if pygame.sprite.collide_rect(self.player, drop):
                if type(drop) == HealthDrop:
                    self.player.health += 50
                    self.gameDrops.remove(drop)
                elif type(drop) == SuperHealthDrop:
                    self.player.health += 1000
                    self.gameDrops.remove(drop)
                elif type(drop) == TriBullets:
                    self.player.power = POWER_TRIBULLETS
                    self.gameDrops.remove(drop)
                elif type(drop) == ShieldDrop:
                    self.player.power = POWER_SHIELD
                    self.gameDrops.remove(drop)

        # Health
        for zombie in self.zombies:
            if pygame.sprite.collide_rect(self.player, zombie):
                if self.player.power == POWER_SHIELD:
                    self.player.health -= 1
                else:
                    self.player.health -= 5

                # check if we die
                if self.player.health <= 0:
                    self.player.power = POWER_NONE
                    self.player.lives -= 1
                    self.player.rect.x = 320
                    self.player.rect.y = 320
                    self.player.health += 200
                if self.player.lives <= 0:
                    self.game_state = STATE_GAMEOVER

        # move player and check for collision at the same time
        self.player.rect.x += self.player.velX
        self.check_collision(self.player, self.player.velX, 0)
        self.player.rect.y += self.player.velY
        self.check_collision(self.player, 0, self.player.velY)

    def zombie_move(self, zombie_sprite):
        # add gravity
        zombie_sprite.do_jump()
        percentage = random.randint(0, 100)

        # simualte gravity
        zombie_sprite.on_ground = False
        if not zombie_sprite.on_ground and not zombie_sprite.jumping:
            zombie_sprite.velY = 4

        # Zombie damage
        for zombie in self.zombies:
            for b in self.bullets:
                if pygame.sprite.collide_rect(b, zombie):
                    #The same bullet cannot be used to kill
                    #multiple zombies and as the bullet was 
                    #no longer in Bullet.List error was raised
                    zombie.health -= 10                
                    self.bullets.remove(b)
                    if zombie.health <= 0:
                        if (percentage >= 0) and (percentage < 40):
                            self.gameDrops.append(HealthDrop(zombie.rect.x + 10, zombie.rect.y + 30))
                        elif (percentage >= 0) and (percentage < 1):
                            self.gameDrops.append(SuperHealthDrop(zombie.rect.x + 20, zombie.rect.y + 30))
                        elif (percentage >= 1) and (percentage < 20):
                            self.gameDrops.append(TriBullets(zombie.rect.x + 30, zombie.rect.y + 30, self.player.direction))
                        elif (percentage >= 1) and (percentage < 50):
                            self.gameDrops.append(ShieldDrop(zombie.rect.x + 40, zombie.rect.y + 30))
                        self.zombieskilled += 1
                        self.player.score += 20
                        self.zombies.remove(zombie)
                    break

        # move zombie and check for collision
        zombie_sprite.rect.x += zombie_sprite.velX
        self.check_collision(zombie_sprite, zombie_sprite.velX, 0)
        zombie_sprite.rect.y += zombie_sprite.velY
        self.check_collision(zombie_sprite, 0, zombie_sprite.velY)

    def check_collision(self, sprite, x_vel, y_vel):
        # for every tile in Background.levelStructure, check for collision
        for block in self.moon.get_surrounding_blocks(sprite):
            if block is not None:
                if pygame.sprite.collide_rect(sprite, block):
                    # we've collided! now we must move the collided sprite a step back
                    if x_vel < 0:
                        sprite.rect.x = block.rect.x + block.rect.w

                        if type(sprite) is Zombie:
                            # the sprite is a zombie, let's make it jump
                            if not sprite.jumping:
                                sprite.jumping = True
                                sprite.on_ground = False

                    if x_vel > 0:
                        sprite.rect.x = block.rect.x - sprite.rect.w

                        if type(sprite) is Zombie:
                            # the sprite is a zombie, let's make it jump
                            if not sprite.jumping:
                                sprite.jumping = True
                                sprite.on_ground = False

                    if y_vel < 0:
                        sprite.rect.y = block.rect.y + block.rect.h

                    if y_vel > 0 and not sprite.on_ground:
                        sprite.on_ground = True
                        sprite.rect.y = block.rect.y - sprite.rect.h

#---------------------------------------------------------------------

Game().run() 

以下是项目符号的代码:

import pygame, math

class Bullet(pygame.sprite.Sprite):

        def __init__(self, x, y, angle):

                self.image = pygame.image.load('data/images/Sprites/laser.png')

                self.rect = self.image.get_rect()
                self.rect.x = x
                self.rect.y = y

                self.velX = math.cos(angle * math.pi / 180) * 8
                self.velY = math.sin(angle * math.pi / 180) * 8
#                self.velX = 8
#                self.velX = -8

        # Bullet updates
        def update(self):

                # Velocity
                self.rect.x += self.velX
                self.rect.y += self.velY

        def render(self, surface):
                surface.blit(self.image, self.rect)

1 个答案:

答案 0 :(得分:1)

self.mouse_angle已经是弧度。如果您再次将math.pi / 180乘以Bullet.__init__(),就像在{{1}}中那样,它将始终给出一个非常接近于零的值。