如何使我的精灵向鼠标位置发射对象?

2024-06-06 13:19:48 发布

您现在位置:Python中文网/ 问答频道 /正文

对于一个学校项目,我需要完成下面的pygame程序,实现向鼠标位置射击Kunais/Shurikens的方法,以便能够击中敌人的精灵

import pygame
import math
import random
from pygame.locals import * 


pygame.init()
fenetre = pygame.display.set_mode((640,480), RESIZABLE) 
pause = False

class perso():
  def __init__(self,image,x=0,y=0,directionX=1,directionY=1):
    self.image = pygame.image.load(image).convert_alpha()
    self.x = x
    self.y = y
    self.directionX = directionX
    self.directionY = directionY

  def move(self):
      if self.x==0:
        self.directionX=1
      if self.x==640-60:
        self.directionX=-1
      if self.y==0:
        self.directionY=1
      if self.y==480-100:
        self.directionY=-1
      self.x+=self.directionX
      self.y+=self.directionY


fond = pygame.image.load("background.png").convert_alpha() 

naruto = perso("naruto.png")
tobi = perso("tobi.png", 250, 100)
kunai = perso("kunai.png")

kunai.x = naruto.x + 40
kunai.y = naruto.y + 70

continuer = True

pygame.key.set_repeat(100, 25)

myfont = pygame.font.SysFont("monospace", 40)
colorRed = (255, 0, 0)
colorBlack = (0, 0, 0)
colorWhite = (255, 255, 255)
colorBlue = (0, 0, 255)

vieNaruto = 10
vieTobi = 3
result = 0


while continuer:

  if int(naruto.x) >= int(tobi.x) and int(naruto.x) < int(tobi.x + 60) and int(naruto.y) >= int(tobi.y) and int(naruto.y) < int(tobi.y + 105):
    vieNaruto -= 1
    naruto.x = 0
    naruto.y = 0

  if int(naruto.x + 50) >= int(tobi.x) and int(naruto.x + 50) < int(tobi.x + 60) and int(naruto.y) >= int(tobi.y) and int(naruto.y) < int(tobi.y + 105):
    vieNaruto -= 1
    naruto.x = 0
    naruto.y = 0

  if int(naruto.x) >= int(tobi.x) and int(naruto.x) < int(tobi.x + 60) and int(naruto.y + 105) >= int(tobi.y) and int(naruto.y + 105) < int(tobi.y + 105):
    vieNaruto -= 1
    naruto.x = 0
    naruto.y = 0

  if int(naruto.x + 50) >= int(tobi.x) and int(naruto.x + 50) < int(tobi.x + 60) and int(naruto.y + 105) >= int(tobi.y) and int(naruto.y + 105) < int(tobi.y + 105):
    vieNaruto -= 1
    naruto.x = 0
    naruto.y = 0

  if vieNaruto <= 0:
    result = 1
    continuer = False

  if vieTobi == 0:
    result = 2
    continuer = False

  textVieNaruto = myfont.render("Vie Naruto : "+str(vieNaruto), True, colorRed)

  textVieTobi = myfont.render("Vie Tobi : "+ str(vieTobi), True, colorRed)

  for event in pygame.event.get():

    """GESTION DU CLAVIER"""

    if event.type == QUIT:
      continuer = False 
    elif event.type == KEYDOWN:
      if event.key == K_SPACE:
        pause = True
        while pause == True:
          for event in pygame.event.get():
            if event.type == KEYDOWN:
                if event.key==K_SPACE:
                    pause = False
      if event.key == K_UP and 5 <= naruto.y:
        naruto.y -= 5
      if event.key == K_DOWN and naruto.y <= 375:
        naruto.y += 5
      if event.key == K_LEFT and 5 <= naruto.x :
        naruto.x -= 5
      if event.key == K_RIGHT and naruto.x <= 575:
        naruto.x += 5



  tobi.move()
  tobi.move() 
  fenetre.blit(fond,(0,0))
  fenetre.blit(textVieNaruto, (400,0))
  fenetre.blit(textVieTobi, (400,30))
  fenetre.blit(naruto.image,(naruto.x,naruto.y))
  fenetre.blit(tobi.image,(tobi.x,tobi.y))

  pygame.time.Clock().tick(30)  
  pygame.display.update() 


if result == 1:
  while True :
    fond = pygame.image.load("Defeat.png").convert_alpha()
    fenetre.blit(fond,(0,0))
    pygame.display.update()

if result == 2:
  while True :
    fond = pygame.image.load("Victory.png").convert_alpha()
    fenetre.blit(fond,(0,0))
    pygame.display.update()

额外的png文件在以下位置可见:https://repl.it/@LeVeveysan/ISNNaruto

有人能帮我吗?我知道如何获得鼠标位置,但我无法让类正常工作

辛辣地


Tags: andkeyimageselfeventtrueifpng
1条回答
网友
1楼 · 发布于 2024-06-06 13:19:48

让我们放弃一切,从头开始,利用pygame的功能,如精灵和向量数学

我们从pygame游戏的基本框架开始,一个简单的窗口:

import pygame

def main():
    screen = pygame.display.set_mode((640, 480))
    clock = pygame.time.Clock()
    while True:
        events = pygame.event.get()
        for e in events:
            if e.type == pygame.QUIT:
                return
        screen.fill(pygame.Color('grey'))
        pygame.display.flip()
        clock.tick(60)

if __name__ == '__main__':
    main()

enter image description here

我们的游戏将有不同的场景(标题场景、游戏场景、游戏场景),所以现在让我们来实现它们:

import pygame
import pygame.freetype 

pygame.init()
FONT = pygame.freetype.SysFont(None, 32)

class SimpleScene:
    def __init__(self, text, background, next_scene):
        if background:
            self.background = pygame.image.load(background).convert()
        else:
            self.background = pygame.Surface((640, 480))
            self.background.fill(pygame.Color('white'))

        if text:
            FONT.render_to(self.background, (100, 200), text, pygame.Color('black'))
            FONT.render_to(self.background, ( 99, 199), text, pygame.Color('red'))

        self.next_scene = next_scene

    def start(self):
        pass

    def draw(self, screen):
        screen.blit(self.background, (0, 0))

    def update(self, events, dt):
        for event in events:
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_SPACE:
                    return self.next_scene

class Game:
    def __init__(self):
        self.background = pygame.image.load('background.png').convert()

    def start(self):
        pass

    def draw(self, screen):
        screen.blit(self.background, (0, 0))

    def update(self, events, dt):
        for event in events:
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_SPACE:
                    return 'VICTORY'

def main():
    screen = pygame.display.set_mode((640, 480))
    clock = pygame.time.Clock()
    scenes = {
        'TITLE': SimpleScene('PRESS SPACE TO START', 'background.png', 'GAME'),
        'GAME': Game(),
        'VICTORY': SimpleScene('YOU WIN!', None, 'TITLE'),
        'DEFEAT': SimpleScene('YOU LOSE!', None, 'TITLE'),
    }
    scene = scenes['TITLE']
    dt = 0
    while True:
        events = pygame.event.get()
        for e in events:
            if e.type == pygame.QUIT:
                return

        next_scene = scene.update(events, dt)
        if next_scene:
            scene = scenes[next_scene]
            scene.start()

        scene.draw(screen)
        pygame.display.flip()
        dt = clock.tick(60)

if __name__ == '__main__':
    main()

enter image description here

这允许我们通过按空格键循环浏览游戏场景

现在让我们实现核心游戏。首先,我们需要一些精灵,所以让我们创建一个Actor类,准备游戏场景以显示和重置精灵。我们使用pygame的一些基本功能,比如^{} class

...
class Actor(pygame.sprite.Sprite):
    def __init__(self, image, pos, direction):
       super().__init__()
       self.image = image
       self.rect = self.image.get_rect(center=pos)
       self.pos = pygame.Vector2(*pos)
       self.direction = pygame.Vector2(*direction)

class Game:
    def __init__(self):
        self.background = pygame.image.load('background.png').convert()
        self.images = {
            'tobi': pygame.image.load('tobi.png').convert_alpha(),
            'naruto': pygame.image.load('naruto.png').convert_alpha(),
            'kunai': pygame.image.load('kunai.png').convert_alpha()
        }
        self.sprites = pygame.sprite.Group()

    def start(self):
        self.sprites.empty()
        self.sprites.add(Actor(self.images['naruto'], (50, 150), (0, 0)))
        self.sprites.add(Actor(self.images['tobi'], (450, 300), (0, 0)))

    def draw(self, screen):
        screen.blit(self.background, (0, 0))
        self.sprites.draw(screen)

    def update(self, events, dt):
        for event in events:
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_SPACE:
                    return 'VICTORY'
        self.sprites.update()
...

enter image description here

该采取行动了。让我们在演员中实施一些行为。我们创造了我们想要的每一种不同行为的功能。一个是托比在屏幕上移动,一个是火影忍者通过键盘控制,还有一个是库奈人

因为我们使用Vector类来表示精灵的位置和方向,所以要使kunai移动到鼠标位置,只需进行减法运算

以下是完整的代码:

import pygame
import pygame.freetype 

pygame.init()
FONT = pygame.freetype.SysFont(None, 32)

class SimpleScene:
    def __init__(self, text, background, next_scene):
        if background:
            self.background = pygame.image.load(background).convert()
        else:
            self.background = pygame.Surface((640, 480))
            self.background.fill(pygame.Color('white'))

        if text:
            FONT.render_to(self.background, (100, 200), text, pygame.Color('black'))
            FONT.render_to(self.background, ( 99, 199), text, pygame.Color('red'))

        self.next_scene = next_scene

    def start(self):
        pass

    def draw(self, screen):
        screen.blit(self.background, (0, 0))

    def update(self, events, dt):
        for event in events:
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_SPACE:
                    return self.next_scene

def tobi_ai(self, dt):
    self._update_pos(dt)

    # change direction when hitting the edge of the screen
    display = pygame.display.get_surface().get_rect()
    if self.rect.bottom > display.bottom or self.rect.top < 0: self.direction.y *= -1
    if self.rect.right > display.right or self.rect.left < 0: self.direction.x *= -1

    self._keep_on_screen()

def player_ai(self, dt):

    # alter direction if arrow keys are pressed
    self.direction = pygame.Vector2()
    pressed = pygame.key.get_pressed()
    if pressed[pygame.K_UP] or pressed[pygame.K_w]: self.direction += (0, -1)
    if pressed[pygame.K_DOWN] or pressed[pygame.K_s]: self.direction += (0, 1)
    if pressed[pygame.K_LEFT] or pressed[pygame.K_a]: self.direction += (-1, 0)
    if pressed[pygame.K_RIGHT] or pressed[pygame.K_d]: self.direction += (1, 0)

    self._update_pos(dt)
    self._keep_on_screen()

def kunai_ai(self, dt):
    self._update_pos(dt)
    display = pygame.display.get_surface().get_rect()

    # just fly around and die if out of screen
    if not display.contains(self.rect):
        self.kill()

class Actor(pygame.sprite.Sprite):
    def __init__(self, image, pos, direction=(0, 0), speed=20, behaviour=None, rotate=False):
       super().__init__()
       self.image = image
       self.rect = self.image.get_rect(center=pos)
       # using vectors for position and direction makes it easy to calculate movement and rotation
       self.pos = pygame.Vector2(*pos)
       self.direction = pygame.Vector2(*direction)
       if rotate:
           self.image = pygame.transform.rotate(self.image, self.direction.angle_to(pygame.Vector2(1,0)))
       self.speed = speed
       self.behaviour = behaviour

    def update(self, dt):
        if self.behaviour:
            self.behaviour(self, dt)

    def _update_pos(self, dt):
        if self.direction.length() > 0:
            self.pos = self.pos + (self.direction.normalize() * self.speed * dt/100)
            self.rect.center = int(self.pos.x), int(self.pos.y)

    def _keep_on_screen(self):
        self.rect.center = self.pos
        display = pygame.display.get_surface().get_rect()
        self.rect.clamp_ip(display)
        self.pos.x, self.pos.y = self.rect.center

class Game:
    def __init__(self):
        self.background = pygame.image.load('background.png').convert()
        self.images = {
            'tobi': pygame.image.load('tobi.png').convert_alpha(),
            'naruto': pygame.image.load('naruto.png').convert_alpha(),
            'kunai': pygame.image.load('kunai.png').convert_alpha()
        }
        self.sprites = pygame.sprite.Group()
        self.kunais = pygame.sprite.Group()

    def start(self):
        self.sprites.empty()
        self.kunais.empty()
        self.naruto = Actor(self.images['naruto'], (50, 150), behaviour=player_ai)
        self.tobi = Actor(self.images['tobi'], (450, 300), (1, 1), behaviour=tobi_ai)
        self.sprites.add(self.naruto)
        self.sprites.add(self.tobi)
        self.player_lives = 10
        self.enemy_lives = 3

    def draw(self, screen):
        screen.blit(self.background, (0, 0))
        self.sprites.draw(screen)
        FONT.render_to(screen, (430, 10), 'Naruto:' , pygame.Color('red'))
        FONT.render_to(screen, (550, 10), str(self.player_lives), pygame.Color('red'))
        FONT.render_to(screen, (430, 50), 'Tobi:', pygame.Color('red'))
        FONT.render_to(screen, (550, 50), str(self.enemy_lives), pygame.Color('red'))

    def update(self, events, dt):
        for event in events:
            if event.type == pygame.MOUSEBUTTONDOWN:
                kunai = Actor(self.images['kunai'], 
                               self.naruto.pos, 
                               event.pos-self.naruto.pos, 
                               speed=35, 
                               behaviour=kunai_ai,
                               rotate=True)
                self.sprites.add(kunai)
                self.kunais.add(kunai)

        self.sprites.update(dt)

        # kunai hits tobi
        # we use https://www.pygame.org/docs/ref/sprite.html#pygame.sprite.spritecollide 
        # for collition detection
        for sprite in pygame.sprite.spritecollide(self.tobi, self.kunais, True):
            self.enemy_lives -= 1
            if self.enemy_lives <= 0:
                return 'VICTORY'

        # tobi hits naruto
        if self.tobi.rect.colliderect(self.naruto.rect):
            self.player_lives -= 1
            if self.player_lives <= 0:
                return 'DEFEAT'
            self.naruto.pos = pygame.Vector2(50, 150)
            self.tobi.pos.x = max(self.tobi.pos.x, 400)

def main():
    screen = pygame.display.set_mode((640, 480))
    clock = pygame.time.Clock()
    scenes = {
        'TITLE': SimpleScene('PRESS SPACE TO START', 'background.png', 'GAME'),
        'GAME': Game(),
        'VICTORY': SimpleScene('YOU WIN!', None, 'TITLE'),
        'DEFEAT': SimpleScene('YOU LOSE!', None, 'TITLE'),
    }
    scene = scenes['TITLE']
    dt = 0
    while True:
        events = pygame.event.get()
        for e in events:
            if e.type == pygame.QUIT:
                return

        next_scene = scene.update(events, dt)
        if next_scene:
            scene = scenes[next_scene]
            scene.start()

        scene.draw(screen)

        pygame.display.flip()
        dt = clock.tick(60)

if __name__ == '__main__':
    main()

enter image description here

现在我们有了一个简单的游戏,它可以重复播放,并且很容易扩展。您可以随意使用此代码

相关问题 更多 >