当前位置: 首页 > 知识库问答 >
问题:

如何设置障碍来阻止玩家穿墙

平庆
2023-03-14

快速笔记。这是我的高级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()

我该从哪里开始,让墙壁充当物理屏障,而不仅仅是视觉屏障?目前,迷宫已经生成,用户可以在整个屏幕上移动。它总是停留在屏幕上,但是我不确定实现墙壁的最佳方式是什么。

共有1个答案

田仲卿
2023-03-14

计算玩家的边界矩形,并计算角点和中心点的网格索引:

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

另请参阅如何防止玩家在迷宫中穿过墙壁?

 类似资料:
  • 我正在编程我的第一个实际2D游戏(吃豆人)。我认为比赛看起来不错,但我有一个大问题--碰撞。对象仍然存在,我被困住了,所以我决定寻求有丰富经验的真正程序员的帮助。(我当然做了一些研究,但我不想做复制粘贴之类的事情,因为我没搞懂)。就像我说的,游戏差不多完成了,我所需要做的就是让帕克曼继续前进。像例子一样,我画大的白色矩形作为平台。我希望有人能帮助我。在这个项目中,我学到了很多东西,碰撞是我理解的东

  • 无障碍设计 无障碍设计是指产品, 设备, 服务, 或者环境是为残疾人设计的. 无障碍设计的概念意味着与一个人的辅助技术(例如, 电脑屏幕阅读器)相兼容, 确保直接访问(即独立)和"间接访问". 无障碍设计可以理解为 "能够访问", 并对一个系统或实体是有利的, 其侧重于使身体残障, 或有特殊需要, 或要依赖辅助技术的人群能够访问 Web. 然后, 研究和开发无障碍设计对每个人都带来了好处. 无障碍

  • 我正在制作的网站可以在德语和英语之间切换显示语言。Shaka player似乎支持本地化切换,但我无法用英语以外的任何语言显示该播放器。尝试在新沙卡上使用changeLocale。用户界面。本地化实例,但它似乎对玩家没有影响。 如果能在不同地区之间切换,我将不胜感激。

  • 在我创建的游戏中,我只希望僵尸能够每分钟击中玩家2次,而不是拿走洞健康条,因为它会让玩家快速受伤。 这是检查玩家和僵尸碰撞的代码。我这样做是为了让玩家只受到10点伤害,但这样玩家就再也不会受到伤害了。我尝试使用if语句来检查玩家是否无敌,并且在if语句中有一个for循环,当int达到30000时,该循环会使玩家死亡,但僵尸仍然会以如此快的速度伤害玩家,以至于洞健康条被拿走。

  • 引子 这篇教程旨在帮助开发者快速上手 Rax iOS 上的无障碍开发。 无障碍,即「accessibility」(常常缩写成「a11y」),是相对有障碍访问而言的,常见的有障碍访问场景有两类。 一种是用户因为生理缺陷,没有能力按正常的交互方式访问,举几个例子: 视障人士看不见或看不清,无法感受手淘上的信息,动效,氛围; 听障人士听不见或听不清,无法听到音乐以及视频的语音部分; 老年人视力和听力的退

  • 无障碍性(a11y) 当你设计一款扩展,需要让扩展对于诸如视觉缺陷,失聪,行动不便的残疾人没有使用障碍。 所有人 — 不仅仅是有特殊需求的人 — 都应该能从那些无障碍扩展所提供的相应模式中获益。例如,键盘的快捷键对于盲人,灵敏度较差的那些人非常重要,然而他们也能提高高级用户在无鼠标状态下的工作效率。 字幕和手抄本提供了聋人获取影音内容的通道,然而他们对语言学习者也非常有用。 人们可以通过各种方式和