Python 使用pygame减少对象之间的距离
我正在研究太空入侵者的变异。现在所有的敌人都在水平移动,当第一个或最后一个敌人击中窗口边界时,所有的敌人都开始向相反的方向移动 我的问题是,当敌人在窗口右边界击中几次时,最后一个敌人和前一个敌人之间的距离正在减小。下面的gif显示了一个问题 我认为问题出在Python 使用pygame减少对象之间的距离,python,pygame,Python,Pygame,我正在研究太空入侵者的变异。现在所有的敌人都在水平移动,当第一个或最后一个敌人击中窗口边界时,所有的敌人都开始向相反的方向移动 我的问题是,当敌人在窗口右边界击中几次时,最后一个敌人和前一个敌人之间的距离正在减小。下面的gif显示了一个问题 我认为问题出在敌方类中的移动方法中,但我不确定这一点 我的代码: import pygame import os import random # CONST WIDTH, HEIGHT = 800, 800 WIN = pygame.display.se
敌方
类中的移动
方法中,但我不确定这一点
我的代码:
import pygame
import os
import random
# CONST
WIDTH, HEIGHT = 800, 800
WIN = pygame.display.set_mode((WIDTH, HEIGHT))
FPS = 60
BACKGROUND = pygame.image.load(os.path.join("assets", "background.png"))
PLAYER_IMG = pygame.image.load(os.path.join("assets", "player-space-ship.png"))
PLAYER_VELOCITY = 7
PLAYER_LIVES = 3
ENEMY_IMG = pygame.image.load(os.path.join("assets", "Enemy1.png"))
ENEMY_VELOCITY = 1
ENEMY_ROWS = 3
ENEMY_COOLDOWN_MIN, ENEMY_COOLDOWN_MAX = 60, 60 * 4
ENEMIES_NUM = 10
LASER_IMG = pygame.image.load(os.path.join("assets", "laser-bullet.png"))
LASER_VELOCITY = 10
pygame.init()
pygame.display.set_caption("Galaxian")
font = pygame.font.SysFont("Comic Sans MS", 20)
class Ship:
def __init__(self, x, y):
self.x = x
self.y = y
self.ship_img = None
self.laser = None
def draw(self, surface):
if self.laser:
self.laser.draw(surface)
surface.blit(self.ship_img, (self.x, self.y))
def get_width(self):
return self.ship_img.get_width()
def get_height(self):
return self.ship_img.get_height()
def get_rect(self):
return self.ship_img.get_rect(topleft=(self.x, self.y))
def move_laser(self, vel, obj):
if self.laser:
self.laser.move(vel)
if self.laser.is_offscreen():
self.laser = None
elif self.laser.collision(obj):
self.laser = None
obj.kill()
def fire(self):
if not self.laser:
x = int(self.get_width() / 2 + self.x - 4)
y = self.y - 9
self.laser = Laser(x, y)
class Player(Ship):
def __init__(self, x, y):
super().__init__(x, y)
self.ship_img = PLAYER_IMG
self.mask = pygame.mask.from_surface(self.ship_img)
self.score = 0
self.lives = PLAYER_LIVES
def move_laser(self, vel, objs):
if self.laser:
self.laser.move(vel)
if self.laser.is_offscreen():
self.laser = None
else:
for obj in objs:
if self.laser and self.laser.collision(obj):
self.score += 1
objs.remove(obj)
self.laser = None
def get_lives(self):
return self.lives
def get_score(self):
return self.score
def kill(self):
self.lives -= 1
def collision(self, obj):
return is_collide(self, obj)
class Enemy(Ship):
y_offset = 0
rect = None
def __init__(self, x, y):
super().__init__(x, y)
self.ship_img = ENEMY_IMG
self.mask = pygame.mask.from_surface(self.ship_img)
self.vel = ENEMY_VELOCITY
self.cooldown = random.randint(ENEMY_COOLDOWN_MIN, ENEMY_COOLDOWN_MAX)
def move(self, objs):
if self.x + self.vel + self.get_width() > WIDTH or self.x + self.vel < 0:
for obj in objs:
obj.vel *= -1
self.x += self.vel
def can_fire(self, enemies):
if self.cooldown > 0:
self.cooldown -= 1
return False
self.cooldown = random.randint(ENEMY_COOLDOWN_MIN, ENEMY_COOLDOWN_MAX)
self.rect = pygame.Rect((self.x, self.y), (self.get_width(), HEIGHT))
for enemy in enemies:
if self.rect.contains(enemy.get_rect()) and enemy != self:
return False
return True
def collision(self, obj):
return is_collide(self, obj)
class Laser:
def __init__(self, x, y):
self.x = x
self.y = y
self.img = LASER_IMG
self.mask = pygame.mask.from_surface(self.img)
def draw(self, surface):
surface.blit(self.img, (self.x, self.y))
def move(self, vel):
self.y += vel
def is_offscreen(self):
return self.y + self.get_height() < 0 or self.y > HEIGHT
def get_width(self):
return self.img.get_width()
def get_height(self):
return self.img.get_height()
def collision(self, obj):
return is_collide(self, obj)
def is_collide(obj1, obj2):
offset_x = obj2.x - obj1.x
offset_y = obj2.y - obj1.y
return obj1.mask.overlap(obj2.mask, (offset_x, offset_y)) != None
def spawn_enemies(count):
distance = int(WIDTH / (count + 1))
enemies = []
enemy_width = ENEMY_IMG.get_width()
enemy_height = ENEMY_IMG.get_height()
if distance >= enemy_width * 2:
for i in range(count):
x = distance * (i + 1) - enemy_width
for row in range(ENEMY_ROWS):
enemies.append(Enemy(x, (row + 1) * enemy_height * 2))
return enemies
def game():
is_running = True
clock = pygame.time.Clock()
player = Player(int(WIDTH / 2), int(HEIGHT - PLAYER_IMG.get_height() - 20))
enemies = spawn_enemies(ENEMIES_NUM)
background = pygame.transform.scale(BACKGROUND, (WIDTH, HEIGHT))
bg_y = 0
def redraw():
WIN.blits(((background, (0, bg_y - HEIGHT)), (background, (0, bg_y)),))
score = font.render(f"Punktacja: {player.get_score()}", True, (255, 255, 255))
lives_text = font.render(f"Życia: {player.get_lives()}", True, (255, 255, 255))
WIN.blit(score, (20, 20))
WIN.blit(lives_text, (WIDTH - lives_text.get_width() - 20, 20))
player.draw(WIN)
for enemy in enemies:
enemy.draw(WIN)
while is_running:
clock.tick(FPS)
redraw()
# Move backgrounds
if bg_y < HEIGHT:
bg_y += 1
else:
bg_y = 0
for event in pygame.event.get():
if event.type == pygame.QUIT:
is_running = False
break
key = pygame.key.get_pressed()
if key[pygame.K_LEFT] and (player.x - PLAYER_VELOCITY) >= 0:
player.x -= PLAYER_VELOCITY
if (
key[pygame.K_RIGHT]
and (player.x + player.get_width() + PLAYER_VELOCITY) <= WIDTH
):
player.x += PLAYER_VELOCITY
if key[pygame.K_SPACE]:
player.fire()
player.move_laser(-LASER_VELOCITY, enemies)
for enemy in enemies:
if enemy.can_fire(enemies):
enemy.fire()
enemy.move(enemies)
enemy.move_laser(LASER_VELOCITY, player)
pygame.display.update()
pygame.quit()
game()
导入pygame
导入操作系统
随机输入
#常数
宽度,高度=800800
WIN=pygame.display.set_模式((宽度、高度))
FPS=60
BACKGROUND=pygame.image.load(os.path.join(“assets”,“BACKGROUND.png”))
PLAYER\u IMG=pygame.image.load(os.path.join(“assets”,“PLAYER space ship.png”))
玩家速度=7
玩家_寿命=3
敌人\u IMG=pygame.image.load(os.path.join(“资产”,“Enemy1.png”))
敌方速度=1
敌方排=3
敌人冷却时间最小值,敌人冷却时间最大值=60,60*4
敌人数量=10
LASER\u IMG=pygame.image.load(os.path.join(“资产”,“激光子弹.png”))
激光速度=10
pygame.init()
pygame.display.set_标题(“Galaxian”)
font=pygame.font.SysFont(“Comic Sans MS”,20)
船舶等级:
定义初始化(self,x,y):
self.x=x
self.y=y
self.ship\u img=无
self.laser=无
def绘图(自、表面):
如果是自动激光:
自动激光绘图(表面)
表面blit(self.ship\u img,(self.x,self.y))
def get_宽度(自身):
返回self.ship\u img.get\u width()
def get_高度(自身):
返回self.ship\u img.get\u height()
def get(自我):
返回self.ship\u img.get\u rect(左上方=(self.x,self.y))
def move_激光器(自身、vel、obj):
如果是自动激光:
自动激光移动(vel)
如果self.laser.is_屏幕外():
self.laser=无
elif自激光碰撞(obj):
self.laser=无
对象kill()
def火灾(自):
如果不是自动激光器:
x=int(self.get_uwidth()/2+self.x-4)
y=self.y-9
自激光=激光(x,y)
职业球员(船):
定义初始化(self,x,y):
super().\uuuu init\uuuu(x,y)
self.ship\u img=玩家\u img
self.mask=pygame.mask.from_surface(self.ship_img)
self.score=0
self.lifes=玩家生命
def move_激光器(自身、vel、objs):
如果是自动激光:
自动激光移动(vel)
如果self.laser.is_屏幕外():
self.laser=无
其他:
对于objs中的obj:
如果自激光和自激光碰撞(obj):
self.score+=1
objs.remove(obj)
self.laser=无
def获取_生命(自我):
回归自我
def get_分数(自我):
返回自我评分
def杀死(自我):
self.lifes-=1
def碰撞(自身、obj):
返回是碰撞(自身,obj)
敌舰级:
y_偏移=0
rect=None
定义初始化(self,x,y):
super().\uuuu init\uuuu(x,y)
self.ship\u img=敌人\u img
self.mask=pygame.mask.from_surface(self.ship_img)
self.vel=敌方速度
self.cooldown=random.randint(敌方最低冷却时间,敌方最高冷却时间)
def移动(自身、objs):
如果self.x+self.vel+self.get_width()>width或self.x+self.vel<0:
对于objs中的obj:
对象级别*=-1
self.x+=self.vel
def can_火力(自身、敌人):
如果自冷却时间>0:
自我冷却时间-=1
返回错误
self.cooldown=random.randint(敌方最低冷却时间,敌方最高冷却时间)
self.rect=pygame.rect((self.x,self.y),(self.get_width(),HEIGHT))
对于敌人中的敌人:
如果self.rect.contains(敌方.get_rect())和敌方!=自我:
返回错误
返回真值
def碰撞(自身、obj):
返回是碰撞(自身,obj)
激光等级:
定义初始化(self,x,y):
self.x=x
self.y=y
self.img=激光
self.mask=pygame.mask.from_surface(self.img)
def绘图(自、表面):
表面blit(self.img,(self.x,self.y))
def移动(自身、水平):
self.y+=vel
def在屏幕外(自身):
返回self.y+self.get_height()<0或self.y>height
def get_宽度(自身):
返回self.img.get_width()
def get_高度(自身):
返回self.img.get_height()
def碰撞(自身、obj):
返回是碰撞(自身,obj)
def发生碰撞(obj1、obj2):
偏移量_x=obj2.x-obj1.x
偏移量_y=obj2.y-obj1.y
返回obj1.mask.overlap(obj2.mask,(偏移量x,偏移量y))!=没有一个
def繁殖敌人(计数):
距离=整数(宽度/(计数+1))
敌人=[]
敌人宽度=敌人图像。获取宽度()
敌方高度=敌方高度。获取高度()
如果距离>=敌方宽度*2:
对于范围内的i(计数):
x=距离*(i+1)-敌方宽度
对于范围内的行(敌人行):
敌人。附加(敌人(x,(行+1)*敌人高度*2))
还敌
def game():
_正在运行=正确吗
clock=pygame.time.clock()
player=player(int(宽度/2),int(高度-player\u IMG.get\u HEIGHT()-20))
敌人=繁殖敌人(敌人数量)
背景=pygame.transform.scale(背景,(宽度,高度))
bg_y=0
def redraw():
WIN.blits(((背景,(0,背景y-高度)),(背景,(0,背景y)),)
score=font.render(f“Punktacja:{player.get_score()}”,真,(255,255,255))
lives_text=font.render(f“Życia:{player.get_lifes()}),True,(255,255))
赢。布利特(得分,(20,20))
blit(lives\u text,(WIDTH-lives\u text.get\u WIDTH()-20,20))
球员。平局(获胜)
对于敌人中的敌人:
敌人。平局(胜利)
当_正在运行时:
时钟滴答声(FPS)
重画
#向后移动
class Enemy(Ship):
# ...
def move(self, objs):
last_obj = objs[-1]
if (
last_obj.x + last_obj.vel + last_obj.get_width() > WIDTH
or self.x + self.vel < 0
):
for obj in objs:
obj.vel *= -1
self.x += self.vel