如何设置障碍以阻止玩家穿墙
How to implement barriers to stop the player moving through walls
快速说明。这是我的 A-Level NEA 编程项目。有两个主要部分 - 一个是生成迷宫,用户必须在给定的时间段内导航,该时间段当前未实现,第二个部分是用户必须回答教育物理问题才能获得最好的成绩。问题是从我系统本地存储的文本文件中导入的。然后将用户的分数连同完成日期一起导出到本地文本文件。
至此我的程序生成了迷宫,用户可以自由移动。教育方面按预期工作。
# Imports
import pygame
import sys
import csv
import random
from datetime import date
# Initialising pygame
pygame.init()
# Setting parameters for commonly used colours
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
BLUE = (0, 0, 255)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
# Creating a variable set to 'False' for the generation of the maze
done = False
# Setting variables for the size of the maze, how many columns and rows there will be
cols = 10
rows = 10
# Setting variables for the size of the window and the size of each individual part of the walls
width = 600
height = 600
wr = width/cols
hr = height/rows
# Initialising the 'screen' this is the surface within pygame that everything will be displayed upon
screen = pygame.display.set_mode([width, height])
screen_rect = screen.get_rect()
pygame.display.set_caption("Maze Generator")
# Creating a clock for the pygame module to run off of
clock = pygame.time.Clock()
# This is a class for the pathfinder section of the maze, it will allow the program to spot where needs to be visited
class Spot:
def __init__(self, x, y):
self.x = x
self.y = y
self.f = 0
self.g = 0
self.h = 0
self.neighbors = []
self.visited = False
self.walls = [True, True, True, True]
def show(self, color=BLACK):
if self.walls[0]:
pygame.draw.line(screen, color, [self.x*hr, self.y*wr], [self.x*hr+hr, self.y*wr], 2)
if self.walls[1]:
pygame.draw.line(screen, color, [self.x*hr+hr, self.y*wr], [self.x*hr+hr, self.y*wr + wr], 2)
if self.walls[2]:
pygame.draw.line(screen, color, [self.x*hr+hr, self.y*wr+wr], [self.x*hr, self.y*wr+wr], 2)
if self.walls[3]:
pygame.draw.line(screen, color, [self.x*hr, self.y*wr+wr], [self.x*hr, self.y*wr], 2)
def show_block(self, color):
if self.visited:
pygame.draw.rect(screen, color, [self.x*hr+2, self.y*wr+2, hr-2, wr-2])
def add_neighbors(self):
if self.x > 0:
self.neighbors.append(grid[self.x - 1][self.y])
if self.y > 0:
self.neighbors.append(grid[self.x][self.y - 1])
if self.x < rows - 1:
self.neighbors.append(grid[self.x + 1][self.y])
if self.y < cols - 1:
self.neighbors.append(grid[self.x][self.y + 1])
grid = [[Spot(i, j) for j in range(cols)] for i in range(rows)]
for i in range(rows):
for j in range(cols):
grid[i][j].add_neighbors()
current = grid[0][0]
visited = [current]
completed = False
def breakwalls(a, b):
if a.y == b.y and a.x > b.x:
grid[b.x][b.y].walls[1] = False
grid[a.x][a.y].walls[3] = False
if a.y == b.y and a.x < b.x:
grid[a.x][a.y].walls[1] = False
grid[b.x][b.y].walls[3] = False
if a.x == b.x and a.y < b.y:
grid[b.x][b.y].walls[0] = False
grid[a.x][a.y].walls[2] = False
if a.x == b.x and a.y > b.y:
grid[a.x][a.y].walls[0] = False
grid[b.x][b.y].walls[2] = False
class Player:
def __init__(self, x, y):
self.rect = pygame.Rect(x, y, hr-2, wr-2)
self.x = int(x)
self.y = int(y)
self.colour = (255, 0, 0)
self.velX = 0
self.velY = 0
self.left_pressed = False
self.right_pressed = False
self.up_pressed = False
self.down_pressed = False
self.speed = 5
def draw(self, win):
pygame.draw.rect(win, self.colour, self.rect)
def update(self):
self.velX = 0
self.velY = 0
if self.left_pressed and not self.right_pressed:
self.velX = -self.speed
if self.right_pressed and not self.left_pressed:
self.velX = self.speed
if self.up_pressed and not self.down_pressed:
self.velY = -self.speed
if self.down_pressed and not self.up_pressed:
self.velY = self.speed
self.x += self.velX
self.y += self.velY
self.rect = pygame.Rect(self.x, self.y, hr-2, wr-2)
def readMyFiles():
questionsAndAnswers = []
correctAnswers = []
with open('questions.txt', newline='') as f:
reader = csv.reader(f, delimiter='\t')
for row in reader:
questionsAndAnswers.append(row)
return questionsAndAnswers
def game(questions, answers, correctAnswers):
score = 0
counter = 0
numberOfQuestions = len(questions)
while not counter == numberOfQuestions:
print(questions[counter])
print(answers[counter])
userAnswer = input('\nWhat is the correct answer?\n')
if userAnswer == correctAnswers[counter]:
print('Well done! That is correct.')
score += 1
else:
print('Better luck next time, that is not correct.')
counter += 1
return score
def shuffleSplit(qna):
random.shuffle(qna)
questions = []
answers = []
correctAnswers = []
for q in qna:
questions.append(q[0])
correctAnswers.append(q[1])
del q[0]
random.shuffle(q)
answers.append(q)
return (questions, answers, correctAnswers)
def exportScores(score, ):
with open('scores.txt', mode='a') as scores:
scores = csv.writer(scores, delimiter='\t')
today = date.today()
dateFormat = today.strftime("%d/%m/%Y")
scores.writerow([dateFormat, score])
player = Player(2, 2)
while not done:
clock.tick(60)
screen.fill(BLACK)
if not completed:
grid[current.x][current.y].visited = True
got_new = False
temp = 10
while not got_new and not completed:
r = random.randint(0, len(current.neighbors)-1)
Tempcurrent = current.neighbors[r]
if not Tempcurrent.visited:
visited.append(current)
current = Tempcurrent
got_new = True
if temp == 0:
temp = 10
if len(visited) == 0:
completed = True
break
else:
current = visited.pop()
temp = temp - 1
if not completed:
breakwalls(current, visited[len(visited)-1])
current.visited = True
current.show_block(WHITE)
for i in range(rows):
for j in range(cols):
grid[i][j].show(WHITE)
# grid[i][j].show_block(BLUE)
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
questionsAndAnswers = readMyFiles()
questions, answers, correctAnswers = shuffleSplit(questionsAndAnswers)
score = game(questions, answers, correctAnswers)
exportScores(score)
print('\nYour score is', str(score))
sys.exit()
if event.type == pygame.KEYDOWN and completed:
if event.key == pygame.K_LEFT:
player.left_pressed = True
if event.key == pygame.K_RIGHT:
player.right_pressed = True
if event.key == pygame.K_UP:
player.up_pressed = True
if event.key == pygame.K_DOWN:
player.down_pressed = True
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT:
player.left_pressed = False
if event.key == pygame.K_RIGHT:
player.right_pressed = False
if event.key == pygame.K_UP:
player.up_pressed = False
if event.key == pygame.K_DOWN:
player.down_pressed = False
player.rect.clamp_ip(screen_rect)
if player.x <= 2:
player.left_pressed = False
player.x = 2
if player.y <= 2:
player.up_pressed = False
player.y = 2
if player.x >= width-(wr-2):
player.right_pressed = False
player.x = width-(wr-2)
if player.y >= height-(wr-2):
player.down_pressed = False
player.y = height-(wr-2)
player.draw(screen)
player.update()
pygame.display.flip()
我从这里到哪里才能使墙壁充当物理障碍而不仅仅是视觉障碍?目前,迷宫已经生成,用户可以在整个屏幕上移动。它始终停留在屏幕上,但我不确定实现墙壁的最佳方式是什么。
计算玩家的边界矩形并计算角点和中心点的网格索引:
player_rect = pygame.Rect(player.x, player.y, wr-3, hr-3)
xC, yC = int(player_rect.centerx / wr), int(player_rect.centery / hr)
x0, y0 = int(player_rect.left / wr), int(player_rect.top / hr)
x1, y1 = int(player_rect.right / wr), int(player_rect.bottom / hr)
根据方向和墙壁限制移动。例如:
if player.left_pressed and player_rect.x < xC*wr+2:
if grid[xC][y0].walls[3] or grid[xC][y1].walls[3]:
player.x = xC*wr+2
player.left_pressed = False
完成碰撞测试:
while not done:
# [...]
player_rect = pygame.Rect(player.x, player.y, wr-3, hr-3)
xC, yC = int(player_rect.centerx / wr), int(player_rect.centery / hr)
x0, y0 = int(player_rect.left / wr), int(player_rect.top / hr)
x1, y1 = int(player_rect.right / wr), int(player_rect.bottom / hr)
if player.left_pressed and player_rect.x < xC*wr+2:
if grid[xC][y0].walls[3] or grid[xC][y1].walls[3]:
player.x = xC*wr+2
player.left_pressed = False
if player.y != yC*hr+2 and grid[x0][y0].walls[2]:
player.x = xC*wr+2
player.left_pressed = False
if player.right_pressed and player_rect.x > xC*wr+2:
if grid[xC][y0].walls[1] or grid[xC][y1].walls[1]:
player.x = xC*wr+2
player.right_pressed = False
if player.y != yC*hr+2 and grid[x0+1][y0].walls[2]:
player.x = xC*wr+2
player.right_pressed = False
if player.up_pressed and player_rect.y < yC*hr+2:
if grid[x0][yC].walls[0] or grid[x1][yC].walls[0]:
player.y = yC*hr+2
player.up_pressed = False
if player.x != xC*wr+2 and grid[x0][y0].walls[3]:
player.y = yC*hr+2
player.up_pressed = False
if player.down_pressed and player_rect.y > yC*hr+2:
if grid[x0][yC].walls[2] or grid[x1][yC].walls[2]:
player.y = yC*hr+2
player.down_pressed = False
if player.x != xC*wr+2 and grid[x0][y0+1].walls[3]:
player.y = yC*hr+2
player.down_pressed = False
快速说明。这是我的 A-Level NEA 编程项目。有两个主要部分 - 一个是生成迷宫,用户必须在给定的时间段内导航,该时间段当前未实现,第二个部分是用户必须回答教育物理问题才能获得最好的成绩。问题是从我系统本地存储的文本文件中导入的。然后将用户的分数连同完成日期一起导出到本地文本文件。
至此我的程序生成了迷宫,用户可以自由移动。教育方面按预期工作。
# Imports
import pygame
import sys
import csv
import random
from datetime import date
# Initialising pygame
pygame.init()
# Setting parameters for commonly used colours
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
BLUE = (0, 0, 255)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
# Creating a variable set to 'False' for the generation of the maze
done = False
# Setting variables for the size of the maze, how many columns and rows there will be
cols = 10
rows = 10
# Setting variables for the size of the window and the size of each individual part of the walls
width = 600
height = 600
wr = width/cols
hr = height/rows
# Initialising the 'screen' this is the surface within pygame that everything will be displayed upon
screen = pygame.display.set_mode([width, height])
screen_rect = screen.get_rect()
pygame.display.set_caption("Maze Generator")
# Creating a clock for the pygame module to run off of
clock = pygame.time.Clock()
# This is a class for the pathfinder section of the maze, it will allow the program to spot where needs to be visited
class Spot:
def __init__(self, x, y):
self.x = x
self.y = y
self.f = 0
self.g = 0
self.h = 0
self.neighbors = []
self.visited = False
self.walls = [True, True, True, True]
def show(self, color=BLACK):
if self.walls[0]:
pygame.draw.line(screen, color, [self.x*hr, self.y*wr], [self.x*hr+hr, self.y*wr], 2)
if self.walls[1]:
pygame.draw.line(screen, color, [self.x*hr+hr, self.y*wr], [self.x*hr+hr, self.y*wr + wr], 2)
if self.walls[2]:
pygame.draw.line(screen, color, [self.x*hr+hr, self.y*wr+wr], [self.x*hr, self.y*wr+wr], 2)
if self.walls[3]:
pygame.draw.line(screen, color, [self.x*hr, self.y*wr+wr], [self.x*hr, self.y*wr], 2)
def show_block(self, color):
if self.visited:
pygame.draw.rect(screen, color, [self.x*hr+2, self.y*wr+2, hr-2, wr-2])
def add_neighbors(self):
if self.x > 0:
self.neighbors.append(grid[self.x - 1][self.y])
if self.y > 0:
self.neighbors.append(grid[self.x][self.y - 1])
if self.x < rows - 1:
self.neighbors.append(grid[self.x + 1][self.y])
if self.y < cols - 1:
self.neighbors.append(grid[self.x][self.y + 1])
grid = [[Spot(i, j) for j in range(cols)] for i in range(rows)]
for i in range(rows):
for j in range(cols):
grid[i][j].add_neighbors()
current = grid[0][0]
visited = [current]
completed = False
def breakwalls(a, b):
if a.y == b.y and a.x > b.x:
grid[b.x][b.y].walls[1] = False
grid[a.x][a.y].walls[3] = False
if a.y == b.y and a.x < b.x:
grid[a.x][a.y].walls[1] = False
grid[b.x][b.y].walls[3] = False
if a.x == b.x and a.y < b.y:
grid[b.x][b.y].walls[0] = False
grid[a.x][a.y].walls[2] = False
if a.x == b.x and a.y > b.y:
grid[a.x][a.y].walls[0] = False
grid[b.x][b.y].walls[2] = False
class Player:
def __init__(self, x, y):
self.rect = pygame.Rect(x, y, hr-2, wr-2)
self.x = int(x)
self.y = int(y)
self.colour = (255, 0, 0)
self.velX = 0
self.velY = 0
self.left_pressed = False
self.right_pressed = False
self.up_pressed = False
self.down_pressed = False
self.speed = 5
def draw(self, win):
pygame.draw.rect(win, self.colour, self.rect)
def update(self):
self.velX = 0
self.velY = 0
if self.left_pressed and not self.right_pressed:
self.velX = -self.speed
if self.right_pressed and not self.left_pressed:
self.velX = self.speed
if self.up_pressed and not self.down_pressed:
self.velY = -self.speed
if self.down_pressed and not self.up_pressed:
self.velY = self.speed
self.x += self.velX
self.y += self.velY
self.rect = pygame.Rect(self.x, self.y, hr-2, wr-2)
def readMyFiles():
questionsAndAnswers = []
correctAnswers = []
with open('questions.txt', newline='') as f:
reader = csv.reader(f, delimiter='\t')
for row in reader:
questionsAndAnswers.append(row)
return questionsAndAnswers
def game(questions, answers, correctAnswers):
score = 0
counter = 0
numberOfQuestions = len(questions)
while not counter == numberOfQuestions:
print(questions[counter])
print(answers[counter])
userAnswer = input('\nWhat is the correct answer?\n')
if userAnswer == correctAnswers[counter]:
print('Well done! That is correct.')
score += 1
else:
print('Better luck next time, that is not correct.')
counter += 1
return score
def shuffleSplit(qna):
random.shuffle(qna)
questions = []
answers = []
correctAnswers = []
for q in qna:
questions.append(q[0])
correctAnswers.append(q[1])
del q[0]
random.shuffle(q)
answers.append(q)
return (questions, answers, correctAnswers)
def exportScores(score, ):
with open('scores.txt', mode='a') as scores:
scores = csv.writer(scores, delimiter='\t')
today = date.today()
dateFormat = today.strftime("%d/%m/%Y")
scores.writerow([dateFormat, score])
player = Player(2, 2)
while not done:
clock.tick(60)
screen.fill(BLACK)
if not completed:
grid[current.x][current.y].visited = True
got_new = False
temp = 10
while not got_new and not completed:
r = random.randint(0, len(current.neighbors)-1)
Tempcurrent = current.neighbors[r]
if not Tempcurrent.visited:
visited.append(current)
current = Tempcurrent
got_new = True
if temp == 0:
temp = 10
if len(visited) == 0:
completed = True
break
else:
current = visited.pop()
temp = temp - 1
if not completed:
breakwalls(current, visited[len(visited)-1])
current.visited = True
current.show_block(WHITE)
for i in range(rows):
for j in range(cols):
grid[i][j].show(WHITE)
# grid[i][j].show_block(BLUE)
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
questionsAndAnswers = readMyFiles()
questions, answers, correctAnswers = shuffleSplit(questionsAndAnswers)
score = game(questions, answers, correctAnswers)
exportScores(score)
print('\nYour score is', str(score))
sys.exit()
if event.type == pygame.KEYDOWN and completed:
if event.key == pygame.K_LEFT:
player.left_pressed = True
if event.key == pygame.K_RIGHT:
player.right_pressed = True
if event.key == pygame.K_UP:
player.up_pressed = True
if event.key == pygame.K_DOWN:
player.down_pressed = True
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT:
player.left_pressed = False
if event.key == pygame.K_RIGHT:
player.right_pressed = False
if event.key == pygame.K_UP:
player.up_pressed = False
if event.key == pygame.K_DOWN:
player.down_pressed = False
player.rect.clamp_ip(screen_rect)
if player.x <= 2:
player.left_pressed = False
player.x = 2
if player.y <= 2:
player.up_pressed = False
player.y = 2
if player.x >= width-(wr-2):
player.right_pressed = False
player.x = width-(wr-2)
if player.y >= height-(wr-2):
player.down_pressed = False
player.y = height-(wr-2)
player.draw(screen)
player.update()
pygame.display.flip()
我从这里到哪里才能使墙壁充当物理障碍而不仅仅是视觉障碍?目前,迷宫已经生成,用户可以在整个屏幕上移动。它始终停留在屏幕上,但我不确定实现墙壁的最佳方式是什么。
计算玩家的边界矩形并计算角点和中心点的网格索引:
player_rect = pygame.Rect(player.x, player.y, wr-3, hr-3)
xC, yC = int(player_rect.centerx / wr), int(player_rect.centery / hr)
x0, y0 = int(player_rect.left / wr), int(player_rect.top / hr)
x1, y1 = int(player_rect.right / wr), int(player_rect.bottom / hr)
根据方向和墙壁限制移动。例如:
if player.left_pressed and player_rect.x < xC*wr+2:
if grid[xC][y0].walls[3] or grid[xC][y1].walls[3]:
player.x = xC*wr+2
player.left_pressed = False
完成碰撞测试:
while not done:
# [...]
player_rect = pygame.Rect(player.x, player.y, wr-3, hr-3)
xC, yC = int(player_rect.centerx / wr), int(player_rect.centery / hr)
x0, y0 = int(player_rect.left / wr), int(player_rect.top / hr)
x1, y1 = int(player_rect.right / wr), int(player_rect.bottom / hr)
if player.left_pressed and player_rect.x < xC*wr+2:
if grid[xC][y0].walls[3] or grid[xC][y1].walls[3]:
player.x = xC*wr+2
player.left_pressed = False
if player.y != yC*hr+2 and grid[x0][y0].walls[2]:
player.x = xC*wr+2
player.left_pressed = False
if player.right_pressed and player_rect.x > xC*wr+2:
if grid[xC][y0].walls[1] or grid[xC][y1].walls[1]:
player.x = xC*wr+2
player.right_pressed = False
if player.y != yC*hr+2 and grid[x0+1][y0].walls[2]:
player.x = xC*wr+2
player.right_pressed = False
if player.up_pressed and player_rect.y < yC*hr+2:
if grid[x0][yC].walls[0] or grid[x1][yC].walls[0]:
player.y = yC*hr+2
player.up_pressed = False
if player.x != xC*wr+2 and grid[x0][y0].walls[3]:
player.y = yC*hr+2
player.up_pressed = False
if player.down_pressed and player_rect.y > yC*hr+2:
if grid[x0][yC].walls[2] or grid[x1][yC].walls[2]:
player.y = yC*hr+2
player.down_pressed = False
if player.x != xC*wr+2 and grid[x0][y0+1].walls[3]:
player.y = yC*hr+2
player.down_pressed = False