如何实施障碍以阻止玩家穿过墙壁 [英] How to implement barriers to stop the player moving through walls
问题描述
快速记录.这是我的 A-Level NEA 编程项目.有两个主要部分 - 一个是生成迷宫,用户必须在给定的时间段内通过它,该时间段当前尚未实现,第二个部分是用户必须回答教育物理问题才能获得最好的成绩.问题是从本地存储在我的系统上的文本文件中导入的.然后将用户的分数与完成日期一起导出到本地文本文件中.
Quick note. This is for my A-Level NEA Programming Project. There are two main sections - One where a maze is generated and the user must navigate through it in a given time period, the time period is not currently implemented, and a second section where the user has to answer educational physics questions in order to get the best score. Questions are imported from a text file stored locally on my system. The user's score is then exported to a local text file along with the date completed.
到目前为止,我的程序生成了迷宫,用户可以自由移动.教育方面按预期工作.
So far my program generates the maze and the user can move freely. The educational aspect works as intended.
# 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()
我该从何处着手才能使墙壁成为物理障碍,而不仅仅是视觉障碍?目前,迷宫已生成,用户可以在整个屏幕上移动.它总是停留在屏幕上,但我不确定实现墙壁的最佳方式是什么.
Where do I go from here to get to a point so that the walls act as physical barriers rather than just visual barriers? Currently, the maze is generated and the user can move throughout the screen. It always stays on the screen however I am not sure what the best way to implement the walls would be.
推荐答案
计算玩家的边界矩形并计算角点和中心点的网格索引:
Compute the bounding rectangle of the player and compute the grid indices of the corner points and and center point:
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)
根据方向和墙壁限制移动.例如:
Restrict the movement dependent on the direction and walls. For instance:
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
这篇关于如何实施障碍以阻止玩家穿过墙壁的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!