我对编码还很陌生,我想构建一个人工智能。我在这个项目中使用 pygame 和 pytorch。有关解决方案或代码格式的任何提示都会有所帮助!
当我运行测试时,只需一次更新即可完全正常工作。然而,当我让 AI 进行输入时,立方体就会从屏幕上掉下来,玩家的位置迅速正向增加,而玩家位置的速度和 y 则负向增加。我被困住了,因为我不认为是与地板的碰撞导致试运行成功。也许是AI的快速输入?这是该项目的 GitHub - https://github.com/hprymak07/physicals-ai-game
import pygame
from math import dist
pygame.init()
w, h = 1250, 720
class Direction:
@staticmethod
def update(left=0, right=0, jump=0):
return left, right, jump
class Player:
def __init__(self, x, y):
self.rect = pygame.Rect(x, y, 10, 10)
self.vel_x = 0
self.vel_y = 0
self.gravity = 0.2
self.ground = False
self.collision_tol = 5
def update_velo(self, left, right, jump):
self.vel_x = 300 if right == 1 else 0 if left == 1 else 0
self.vel_y += self.gravity
self.vel_y = -10 if jump == 1 else self.vel_y
print("Velocity X:", self.vel_x)
print("Velocity Y:", self.vel_y)
def move(self):
self.rect.x += self.vel_x
self.rect.y += self.vel_y
print("Player Position:", self.rect.x, self.rect.y)
def collisions(self, objects, walls):
for object in objects:
if self.rect.colliderect(object):
print("Collision detected with object:", object)
if abs(self.rect.right - object.left) <= self.collision_tol:
self.rect.right = object.left
self.ground = True
elif abs(self.rect.left - object.right) <= self.collision_tol:
self.rect.left = object.right
self.ground = True
elif self.rect.bottom >= object.top:
self.rect.bottom = object.top
self.ground = True
self.vel_y = 0
elif self.rect.top <= object.bottom:
self.rect.top = object.bottom
self.ground = False
else:
self.ground = False
for wall in walls:
if self.rect.colliderect(wall):
print("Collision detected with wall:", wall)
if self.vel_x > 0:
self.rect.right = wall.left
elif self.vel_x < 0:
self.rect.left = wall.right
if self.vel_y > 0:
self.rect.bottom = wall.top
self.vel_y = 0
self.ground = True
elif self.vel_y < 0:
self.rect.top = wall.bottom
self.vel_y = 0
def update(self, left, right, jump, objects, walls):
self.update_velo(left, right, jump)
self.move()
self.collisions(objects, walls)
print("Player position:", self.rect.x, self.rect.y)
class Game:
def __init__(self):
self.display = pygame.display.set_mode((w, h))
pygame.display.set_caption("AI Game")
self.clock = pygame.time.Clock()
self.endpt = pygame.Rect(1200, h - 250, 20, 20)
self.floor = pygame.Rect(0, h - 20, w, 200)
self.left_wall = pygame.Rect(0, 0, 20, h)
self.right_wall = pygame.Rect(w - 20, 0, 20, h)
self.objects_for_lvl = [
pygame.Rect(100, h - 100, 100, 80),
pygame.Rect(250, h - 140, 100, 25),
pygame.Rect(400, h - 170, 100, 25),
pygame.Rect(535, h - 170, 75, 25),
pygame.Rect(735, h - 170, 75, 25),
pygame.Rect(900, h - 200, 150, 25),
pygame.Rect(1150, h - 230, 200, 25)
]
self.player = Player(30, 600)
self.running = True
self.reset()
def reset(self):
self.score = 0
self.frame_iteration = 0
def step(self, action):
self.frame_iteration += 1
for ev in pygame.event.get():
if ev.type == pygame.QUIT:
pygame.quit()
quit()
left, right, jump = action
self.player.update(left, right, jump, self.objects_for_lvl, [self.floor, self.left_wall, self.right_wall])
reward, game_over = self.calculate_score()
self._update()
return reward, game_over, self.score
def calculate_score(self):
reward = 0
game_over = False
if self.player.rect.colliderect(self.endpt):
reward += 10
elif self.player.rect.colliderect(self.floor):
reward -= 5
self.score += reward
game_over = self.player.rect.colliderect(self.left_wall) or self.player.rect.colliderect(self.right_wall)
return reward, game_over
def _update(self):
self.display.fill('white')
for obj in self.objects_for_lvl:
pygame.draw.rect(self.display, (128, 128, 128), obj)
pygame.draw.rect(self.display, (128, 128, 128), self.floor)
pygame.draw.rect(self.display, (128, 128, 128), self.left_wall)
pygame.draw.rect(self.display, (128, 128, 128), self.right_wall)
pygame.draw.rect(self.display, (255, 0, 0), self.player.rect) # Draw player object
pygame.draw.rect(self.display, (0, 255, 0), self.endpt)
pygame.display.update()
if __name__ == "__main__":
game = Game()
while game.running:
action = Direction.update(1, 0, 0) # move left once
print("Action:", action)
reward, game_over, score = game.step(action)
if game_over:
print("Game Over")
game.running = False
这似乎是一项相当困难的任务。我认为问题出在碰撞上。我对代码做了一些小改动,它仍然不起作用,但现在你可以使用 SPACE 来进行一步。像这样你可以看到,红色矩形向上移动,然后向下移动,一旦接触地面,它就会停止。它似乎处于无限循环中。现在可能更容易找到错误。
import pygame
pygame.init()
w, h = 1250, 720
class Direction:
@staticmethod
def update(left=0, right=0, jump=0):
return left, right, jump
class Player:
def __init__(self, x, y):
self.rect = pygame.Rect(x, y + 1, 10, 10)
self.vel_x = 0
self.vel_y = 0
self.gravity = 0.8
self.ground = False
self.collision_tol = 10
def __repr__(self):
return f"Player(x={self.rect.x}, y={self.rect.y}, vel_x={self.vel_x}, vel_y={self.vel_y}, ground={self.ground})"
def update_velo(self, left, right, jump, objects, walls):
self.vel_x = 10 if right == 1 else 0 if left == 1 else 0
self.vel_y += self.gravity
self.ground = self.rect.colliderect(walls[0]) or any(self.rect.colliderect(obj) for obj in objects)
if jump == 1 and self.ground:
self.vel_y = -10
# print("Velocity X:", self.vel_x)
# print("Velocity Y:", self.vel_y)
# print(f"self.ground:{self.ground}")
def move(self):
self.rect.x += self.vel_x
self.rect.y += self.vel_y
# print("Player Position:", self.rect.x, self.rect.y)
def collisions(self, objects, walls):
for object in objects:
if self.rect.colliderect(object):
print("Collision detected with object:", object)
if abs(self.rect.right - object.left) <= self.collision_tol:
self.rect.right = object.left
self.ground = True
elif abs(self.rect.left - object.right) <= self.collision_tol:
self.rect.left = object.right
self.ground = True
elif self.rect.bottom >= object.top:
self.rect.bottom = object.top
self.ground = True
self.vel_y = 0
elif self.rect.top <= object.bottom:
self.rect.top = object.bottom
self.ground = False
else:
self.ground = False
for wall in walls:
if self.rect.colliderect(wall):
print("Collision detected with wall:", wall)
if self.vel_x > 0:
self.rect.right = wall.left
elif self.vel_x < 0:
self.rect.left = wall.right
if self.vel_y > 0:
self.rect.bottom = wall.top
self.vel_y = 0
self.ground = True
elif self.vel_y < 0:
self.rect.top = wall.bottom
self.vel_y = 0
def update(self, left, right, jump, objects, walls):
self.update_velo(left, right, jump, objects, walls)
self.move()
self.collisions(objects, walls)
# print("Player position:", self.rect.x, self.rect.y)
print(self)
class Game:
def __init__(self, display):
self.display = display
self.clock = pygame.time.Clock()
self.endpt = pygame.Rect(1200, h - 250, 20, 20)
self.floor = pygame.Rect(0, h - 20, w, 200)
self.left_wall = pygame.Rect(0, 0, 20, h)
self.right_wall = pygame.Rect(w - 20, 0, 20, h)
self.objects_for_lvl = [
pygame.Rect(100, h - 100, 100, 80),
pygame.Rect(250, h - 140, 100, 25),
pygame.Rect(400, h - 170, 100, 25),
pygame.Rect(535, h - 170, 75, 25),
pygame.Rect(735, h - 170, 75, 25),
pygame.Rect(900, h - 200, 150, 25),
pygame.Rect(1150, h - 230, 200, 25)
]
self.player = Player(30, 600)
self.running = True
self.reset()
def reset(self):
self.score = 0
self.frame_iteration = 0
def step(self, action):
self.frame_iteration += 1
for ev in pygame.event.get():
if ev.type == pygame.QUIT:
pygame.quit()
quit()
left, right, jump = action
self.player.update(left, right, jump, self.objects_for_lvl, [self.floor, self.left_wall, self.right_wall])
reward, game_over = self.calculate_score()
# self._update()
return reward, game_over, self.score
def calculate_score(self):
reward = 0
game_over = False
if self.player.rect.colliderect(self.endpt):
reward += 10
elif self.player.rect.colliderect(self.floor) and self.player.rect.x >= 100:
reward -= 5
self.score += reward
game_over = self.player.rect.colliderect(self.left_wall) or self.player.rect.colliderect(self.floor) and self.player.rect.x >= 100
return reward, game_over
def draw(self):
for obj in self.objects_for_lvl:
pygame.draw.rect(self.display, (128, 128, 128), obj)
pygame.draw.rect(self.display, (128, 128, 128), self.floor)
pygame.draw.rect(self.display, (128, 128, 128), self.left_wall)
pygame.draw.rect(self.display, (128, 128, 128), self.right_wall)
pygame.draw.rect(self.display, (255, 0, 0), self.player.rect) # Draw player object
pygame.draw.rect(self.display, (0, 255, 0), self.endpt)
if __name__ == "__main__":
display = pygame.display.set_mode((w, h))
pygame.display.set_caption("AI Game")
game = Game(display)
while game.running:
# reset screen
display.fill('white')
# use SPACE for every step
events = pygame.event.get()
for event in events:
if event.type == pygame.KEYDOWN:
action = Direction.update(0, 0, 1) # move up once
print("Action:", action)
reward, game_over, score = game.step(action)
if game_over:
print("Game Over")
game.running = False
# draw the stuff
game.draw()
pygame.display.update()