gpt4 book ai didi

python - pygame - 杀死组中的 Sprite 的问题

转载 作者:行者123 更新时间:2023-12-01 00:23:28 25 4
gpt4 key购买 nike

我正在尝试使用 pygame 为学校项目创建一个游戏。我想要阻碍玩家的障碍物(在本例中为盒子)。玩家能够摧毁盒子,这将导致另一个盒子在相同高度的随机位置产生。

我将代码分成 3 个独立的模块,分别是 Sprite 、主代码和设置(游戏变量)。

主要:

import pygame as pg 
import random
from sprites import *
from settings import *
import os
import sys
import time

class Game:
def __init__(init):#initialising the games properties(window,sound,speed,etc).
pg.init()
pg.mixer.init()
init.clock = pg.time.Clock()
init.screen = pg.display.set_mode((WIDTH,HEIGHT))
pg.display.set_caption(TITLE)
init.clock = pg.time.Clock()
init.running = True
init.font_name = pg.font.match_font(FONT_NAME)
init.data()
def data(load):
load.dir = os.path.dirname(__file__)

def new(new):#starts the game again.
new.score = 0
new.obstacles = pg.sprite.Group()
new.platforms = pg.sprite.Group()
new.bullets = pg.sprite.Group()
new.all_sprites = pg.sprite.Group()
new.player = Player(new)
new.all_sprites.add(new.player)
for plat in PLATFORM_LIST:
p = Platform(*plat)
new.all_sprites.add(p)
new.platforms.add(p)
for obs in OBSTACLE_LIST:
new.obstacle = Obstacle(*obs)
new.all_sprites.add(new.obstacle)
new.obstacles.add(new.obstacle)

new.run()
def run(run):
run.playing = True
while run.playing:
run.cooldown = 0
run.clock.tick(FPS)
run.events()
run.update()
run.draw()

def update(update):
bullet = Bullet
#game update.
update.all_sprites.update()
#spawning obstacles lower half
while len(update.obstacles) < 3:
width = random.randrange(50, 100)
update.obstacle = Obstacle(random.randrange(0, WIDTH - width),HEIGHT-100,100,50)
update.obstacles.add(update.obstacle)
update.all_sprites.add(update.obstacle)
#spawning obstacles randomly throughout the middle half
#spawning obstacles randomly throughout the map upper half
#check if bullet collides with an obstacles.
collide = pg.sprite.groupcollide(update.bullets,update.obstacles,True,False)
if collide:

update.obstacle.obs_health = update.obstacle.obs_health - bullet.damage
if update.obstacle.obs_health == 0:
update.obstacle.kill()

#check if player hits the sides of an obstacle.
if update.player.velocity.x >0:#when moving right.
collide = pg.sprite.spritecollide(update.player,update.obstacles,False)
if collide:
if update.player.pos.y >= collide[0].rect.centery+20:#if the player is above the platform.
update.player.pos.x = collide[0].rect.left - (PLAYER_WIDTH/2)
update.player.velocity.x = 0
update.player.acceleration.y = 0

if update.player.velocity.x <0:#when moving left.
collide = pg.sprite.spritecollide(update.player,update.obstacles,False)
if collide:
if update.player.pos.y >= collide[0].rect.centery:
update.player.pos.x = collide[0].rect.right + (PLAYER_WIDTH/2)
update.player.velocity.x = 0


#check if player hits side of platforms
if update.player.velocity.x >0 and (update.player.velocity.y < 0):#when moving right.
collide = pg.sprite.spritecollide(update.player,update.platforms,False)
if collide:
if update.player.pos.y < collide[0].rect.centery+50:#if the player is below the obstacle.
update.player.pos.x = collide[0].rect.left - (PLAYER_WIDTH/2)
update.player.velocity.x = 0

if update.player.velocity.x <0:#when moving left.
collide = pg.sprite.spritecollide(update.player,update.obstacles,False)
if collide:
if update.player.pos.y > collide[0].rect.centery:
update.player.pos.x = collide[0].rect.right + (PLAYER_WIDTH/2)
update.player.velocity.x = 0
#check if player hits a platform while ascending:
if update.player.velocity.y <0:#only when moving up.
collide = pg.sprite.spritecollide(update.player,update.platforms,False)
if collide:
if update.player.pos.y > collide[0].rect.bottom:
update.player.pos.y = collide[0].rect.bottom + (PLAYER_HEIGHT/2) + PLAYER_JUMP
update.player.velocity.y = 0

#check if a player hits a platform while falling.
if update.player.velocity.y >0:#only while falling will this apply.
collide = pg.sprite.spritecollide(update.player,update.platforms,False)#false allows you to avoid deleting the object you jump into.
if collide:
if update.player.pos.y < collide[0].rect.centery:#if the player is above the center of the platform.
update.player.pos.y = collide[0].rect.top +1
update.player.velocity.y = 0
collide = pg.sprite.spritecollide(update.player,update.obstacles,False)
if collide:
if update.player.pos.y < collide[0].rect.centery:
update.player.pos.y = collide[0].rect.top +1
update.player.velocity.y = 0
#spawning obstacles randomly throughout the map upper half

#spawning obstacles randomly throughout the middle half



def events(events):
events.cooldown += events.clock.get_time()
#processes inputs.
for event in pg.event.get():
#check for window closing.
if event.type == pg.QUIT:#if the 'x' button is clicked
if events.playing:
events.playing = False#stop the game loop.
events.running = False#stop the main loop.
if event.type == pg.KEYDOWN:
if event.key == pg.K_UP:
events.player.jump()
if event.key == pg.K_SPACE:
events.player.bullet_list.append(events.player.shoot())
#print(len(events.player.bullet_list))
def draw(draw):
draw.screen.fill(GREY)# creates a black screen.
draw.draw_text(str(draw.player.PLAYER_HEALTH),24,BLACK,WIDTH/32,HEIGHT /32)
draw.all_sprites.draw(draw.screen)#draws the sprites in the group all_sprites.

#after drawing the screen is flipped.
pg.display.flip()
def start_screen(start):#screen displayed when the game is started.
start.screen.fill(BGCOLOR)
start.draw_text(TITLE,48,WHITE,WIDTH/2,HEIGHT /4)
start.draw_text("Arrows to move,UP to jump", 22,WHITE,WIDTH/2,HEIGHT/2)
start.draw_text("Press a key to play",22,WHITE,WIDTH/2,HEIGHT*3/4)
pg.display.flip()
start.any_key()#temporary key to start system.


def any_key(wait):
waiting = True
while waiting:#a loop is used for the start screen until an action is done.
wait.clock.tick(FPS)#allows animations to
for event in pg.event.get():
if event.type == pg.QUIT:#if the 'x' button is pressed during the start screen.
waiting = False
wait.running = False#stops the main loop.
if event.type == pg.KEYUP:#if any key is released.
waiting = False
def over_screen(over):#displayed when the game ends.
if not over.running:
return#skips the over screen when 'x' button is pressed.
over.screen.fill(BGCOLOR)
over.draw_text('GAME OVER',48,WHITE,WIDTH/2,HEIGHT /4)
def draw_text(self, text, size, color, x, y):

font = pg.font.Font(self.font_name, size)#selects the chosen font.
text_surface = font.render(text, True, color)#creates the text with anti aliasing and the color chosen.
text_rect = text_surface.get_rect()
text_rect.midtop = (x, y)#position of text.
self.screen.blit(text_surface, text_rect)#renders text on screen.

g = Game()
g.start_screen()
while g.running:#the main loop.
g.new()
g.over_screen()
pg.quit()#closes the window.

Sprite :

#Sprite class
import random
import pygame as pg
from settings import *
vec = pg.math.Vector2 #creates a 2D Vector which stores the x an y cordinates for the sprites.
class Player(pg.sprite.Sprite):
def __init__(self, game):#create initialise the properties of the sprite.
self.game = game#reference to variable in game class.
pg.sprite.Sprite.__init__(self)#provides functions for the sprite in other functions.
self.image = pg.Surface((PLAYER_WIDTH,PLAYER_HEIGHT))#creates a square for the Player to be used as a hitbox.
self.image.fill(GREEN)#place holder for the player.
self.rect = self.image.get_rect()
self.rect.center = (WIDTH/2),(HEIGHT/4)# allows you to move the character.
self.pos = vec(WIDTH/2,HEIGHT/2)#the center of the sprite.
self.velocity = vec(0,0)#the speed of the player.
self.acceleration = vec(0,0)#allows for the change in speed.
self.facing = 0 #direction the player is looking.
self.current = 0#current direction facing.
self.PLAYER_HEALTH = 1000
self.bullet_list = []

def jump(self):
hits = pg.sprite.spritecollide(self, self.game.platforms, False)
if hits:#only able to jump when colliding with platform.
self.velocity.y += -PLAYER_JUMP
collide = hits = pg.sprite.spritecollide(self, self.game.obstacles, False)
if collide:
self.velocity.y += -PLAYER_JUMP
def shoot(self):
#if game.cooldown > 400:
#cooldown = 0
self.bullet = Bullet(self,self.current,self.rect.centerx, self.rect.top)
self.bullet_list.append(self.bullet)
for bullet in self.bullet_list:
#self.bullet = Bullet(self.current,self.rect.centerx, self.rect.top)#creates bullet postioned in center.
self.game.all_sprites.add(self.bullet)
self.game.bullets.add(self.bullet)
#self.bullet = Bullet(self.current,self.rect.centerx, self.rect.top)#creates bullet postioned in center.
#self.game.all_sprites.add(self.bullet)
#self.game.bullets.add(self.bullet)
def update(self):
self.acceleration = vec(0,PLAYER_GRAV)#resets the position of player when not moving.
keys = pg.key.get_pressed()#inputs a pressed key.
if keys[pg.K_LEFT]:
self.acceleration.x = -PLAYER_ACC
self.facing = -1
self.current = self.facing
if keys[pg.K_RIGHT]:
self.acceleration.x = PLAYER_ACC
self.facing = 1
self.current = self.facing

if self.acceleration.x == 0:#if standing, the previous direction is saved
self.facing = self.current
#print(self.current)
#friction.
self.acceleration.x += self.velocity.x * PLAYER_FRICTION
#equation for displacment.
self.velocity += self.acceleration
self.pos += self.velocity + 0.5 * self.acceleration#moves thes players position to the new x,y co-ordinate.
#boundaries of screen.
if self.rect.right > WIDTH:
self.pos.x = WIDTH -(PLAYER_WIDTH * 0.5)#avoids overlapping the boundary.
self.velocity.x = 0 #avoids player sticking to walls by capping speed at boundaries.
self.acceleration.x = 0 #reduces the amount of 'jitter' when trying to move past boundaries.
if self.rect.left < 0 :
self.pos.x = (PLAYER_WIDTH * 0.5)#avoids overlapping the boundary.
# have to add half the player width to avoid player going into walls.
self.velocity.x = 0 #avoids player sticking to walls by stopping player at boundaries.



self.rect.midbottom = self.pos#tracks the position of the players center.
class Platform(pg.sprite.Sprite,):
def __init__(self, x, y, w, h):
pg.sprite.Sprite.__init__(self)
self.image = pg.Surface((w,h))
self.image.fill(BLACK)
self.rect = self.image.get_rect()
self.rect.x = x
self.rect.y = y
class Obstacle(pg.sprite.Sprite):
def __init__(self,x,y,w,h):
pg.sprite.Sprite.__init__(self)
self.image = pg.Surface((w,h))
self.image.fill(BLUE)
self.rect = self.image.get_rect()
self.rect.x = x
self.rect.y = y
self.obs_health = 100
class Bullet(pg.sprite.Sprite):
damage = 25
def __init__(self,player,current, x, y):
self.player = player#allows the bullet class to use player variables.
pg.sprite.Sprite.__init__(self)
self.image = pg.Surface((20,10))
self.image.fill(LBLUE)
self.rect = self.image.get_rect()
self.rect.right = x
self.rect.centery = y + (PLAYER_HEIGHT/2)
#self.damage = 25
self.velocity = vec(0,0)
if current == -1:#when looking left.
self.velocity = vec(-10,0)
if current == 1:#when looking right.
self.velocity = vec(10,0)
def update(self):
self.rect.right += self.velocity.x
#remove when moves of off screen.
if self.rect.right > WIDTH:
self.kill()
for bullet_amount in self.player.bullet_list:
self.player.bullet_list.pop(self.player.bullet_list.index(bullet_amount))
if self.rect.left <0:
self.kill()
for bullet_amount in self.player.bullet_list:
self.player.bullet_list.pop(self.player.bullet_list.index(bullet_amount))
#print(self.rect.x)

设置:

#settings
TITLE = "downpour"
WIDTH = 900
HEIGHT = 500
FPS = 60
FONT_NAME = 'Ariel'
#platforms
PLATFORM_LIST = [(0, HEIGHT - 50, WIDTH, 50),
(WIDTH -225 ,HEIGHT * 3/4 -50,200, 40),#(x,y,width,height)of the platforms.
(0 +25 ,HEIGHT * 3/4 -50,200, 40),
(0 +350,HEIGHT * 3/4 -150,200, 40)]
OBSTACLE_LIST = [(WIDTH/2,HEIGHT -50-50,100,50),(WIDTH/3,HEIGHT -50-50,100,50),(WIDTH/2,HEIGHT -50-50,100,50)]
#player properties
PLAYER_WIDTH = 50
PLAYER_HEIGHT = 50
PLAYER_ACC = 0.55
PLAYER_FRICTION = -0.05
PLAYER_GRAV = 0.8
PLAYER_JUMP = 15
#colors defines
WHITE = (255,255,255)
BLACK = (0,0,0)
GREY = (211,211,211)
RED = (255,0,0)
GREEN = (0,255,0)
BLUE = (0,0,255)
LBLUE = (132,112,255)
BGCOLOR = LBLUE

我遇到的问题是在摧毁多个盒子之一后生成一个新盒子。射击盒子会耗尽其生命值,从而将其摧毁。

假设我有 3 个盒子:A、B 和 C。当我尝试摧毁 B 或 C 时,盒子 A 会被摧毁并重生。

我觉得这是一个显而易见的答案......

与障碍物相关的代码:

创建类:

class Obstacle(pg.sprite.Sprite):
def __init__(self,x,y,w,h):
pg.sprite.Sprite.__init__(self)
self.image = pg.Surface((w,h))
self.image.fill(BLUE)
self.rect = self.image.get_rect()
self.rect.x = x
self.rect.y = y
self.obs_health = 100

将其添加到 Sprite 组:

for obs in OBSTACLE_LIST:
new.obstacle = Obstacle(*obs)
new.all_sprites.add(new.obstacle)
new.obstacles.add(new.obstacle)

碰撞:

collide = pg.sprite.groupcollide(update.bullets,update.obstacles,True,False)
if collide:

update.obstacle.obs_health = update.obstacle.obs_health - bullet.damage
if update.obstacle.obs_health == 0:
update.obstacle.kill()

产生新的障碍:

while len(update.obstacles) < 3:
width = random.randrange(50, 100)
update.obstacle = Obstacle(random.randrange(0, WIDTH - width),HEIGHT-100,100,50)
update.obstacles.add(update.obstacle)
update.all_sprites.add(update.obstacle)

最佳答案

首先,对于所有实例方法,如果您使用名称 self 而不是您正在使用的所有自定义名称(例如 new),这将对读者有所帮助或更新第一个参数。

重写后,您的代码将如下所示:

        collide = pg.sprite.groupcollide(self.bullets,self.obstacles,True,False)
if collide:
self.obstacle.obs_health = self.obstacle.obs_health - bullet.damage
if self.obstacle.obs_health == 0:
self.obstacle.kill()

现在问问自己,为什么程序知道 self.obstacle 是发生碰撞的那个? self.obstacle 是否应该存在?看起来 self.obstacle 只是在创建 Game 类时使用了临时局部变量来将 Obstacle 添加到 self.obstacles 中。

如果是这样,只需使用局部变量,如下所示:

        for obs in OBSTACLE_LIST:
obstacle = Obstacle(*obs)
self.all_sprites.add(obstacle)
self.obstacles.add(obstacle)

此时,希望错误消息能够清楚地表明引用 self.obstacle 不起作用。 pg.sprite.groupcollide 返回一个 Sprite_dict,因此您需要从 collide 中提取障碍物以找出发生碰撞的内容。

关于python - pygame - 杀死组中的 Sprite 的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58793929/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com