简体   繁体   中英

pygame event key in mainloop

I've been working on key detection in my game, but an issue I get is that i get this error.

Traceback (most recent call last):

File "C:/Users/Desktop/problem.py", line 433, in <module>
    mainting()
  File "C:/Users/natha/Desktop/problem.py", line 316, in mainting
    if event.key == pygame.K_p:
AttributeError: 'Event' object has no attribute 'key''

I've tried to indent to try and solve the error but it does not make a difference. What is the solution that will resolve this error? I have also looked at other questions and tried what they have suggested but I cannot get a solution to the problem.

Here are the definitions which are used and have been cut down.

import pygame
import sys
from os import path
import math
from tkinter import *


pygame.init()
DS = pygame.display.set_mode((900, 600))
W, H = DS.get_size()
clock = pygame.time.Clock()
FPS = 60
PLAYER_IMAGE = pygame.Surface((15, 27))
PLAYER_IMAGE.fill((70, 240, 120))
IMAGE1 = pygame.Surface((20,20))
IMAGE1.fill((255,255,255))
#
ENEMY_IMAGE = pygame.Surface((20,20))
ENEMY_IMAGE.fill((255,255,255))
IMAGE2 = pygame.Surface((15,27))
IMAGE2.fill((0,0,255))
st = pygame.font.SysFont("comicsans ms", 20)
lf = pygame.font.SysFont("comicsans ms", 120)
#bolt_image = pygame.image.load('bolt power up.png')
WHITE = (255,255,255)
BLACK = (0,0,0)
BLUE = (0,0,255)
RED = (178,34,34)

class Platform(pygame.sprite.Sprite):
    def __init__(self, x, y, w, h):
        super(Platform, self).__init__()
        self.image = pygame.Surface((w, h))
        self.image.fill((90, 90, 120))
        self.rect = self.image.get_rect(topleft=(x, y))



class Level:

    def __init__(self):
        self.platforms = pygame.sprite.Group()
        for x, y, width, height in self.level:
            platform = Platform(x, y, width, height)
            self.platforms.add(platform)

    def shift_vertical(self, amount):  # Renamed this to `shift_vertical`.
            for sprite in self.platforms:
                sprite.rect.y += amount


    def shift(self, amount):
        for sprite in self.platforms:
            sprite.rect.y -= amount
        for Enemy in self.platforms:
            Enemy.rect.y -= amount

    def shift_horizontal(self, amount):
        for sprite in self.platforms:
            sprite.rect.x
class LVL_01(Level):

    def __init__(self):
        self.level = [
            (20, 20, 150, 20), (120, 200, 100, 20), (400, 440, 100, 20),
            (40, 100, 200, 20), (320, 300, 150, 20), (520, 550, 100, 20),
            (60, 100, 140, 20), (300, 200, 100, 20),(200,470,100,20),
            (40, 100, 100, 20), (350, 300, 150, 20), (95, 550, 150, 20),
            (250, 20, 150, 20), (450, 100, 150, 20), (710,20,100,20),
            (60, 20, 140, 20), (425, 200, 100, 20), (370, 350, 50, 20),
            (200, 100, 50, 20), (200, 370, 70, 20),(800,300,100,20),
            (780,130,50,20),(350,105,50,20),(310,550,100,20),
            (200, 100, 50, 20), (200, 370, 70, 20),(730,385,75,20),
            (600, -545, 50, 20), (780, -750, 50, 20), (350, -105, 50, 20),
            (40,460,75,20),(510,380,85,20),(650,450,70,20),(600,200,100,20),
            (80,305,100,20),(715,550,100,20),(460,20,100,20),
            (150,-105,150,20),(465,-105,100,20),(615,-105,100,20),(21,-195,50,20),
            (45,-60,100,20),(350,-230,75,20),(760,-239,80,20),(665,100,75,20),
            (450,-300,75,20),(118,-290,90,20),(300,-300,90,20),(100,-205,90,20),
            (765,-350,90,20),

        ]
        Level.__init__(self)


# defines the player, what it will look like and attributes that will help it to move
class Player(pygame.sprite.Sprite):

    def __init__(self, pos, level):
        super(Player, self).__init__()
        self.image = PLAYER_IMAGE
        self.image1 = IMAGE1
        self.rect = self.image.get_rect(center=pos)
        self._vx = 0
        self._vy = 0
        self._spritex = pos[0]
        self._spritey = pos[1]
        self.level = level
        self._gravity = .9
        # A vector as a camera.
        self.camera = pygame.math.Vector2()
    # Shows the movement
    def update(self):
        self.grav()
        self.dead()
        self.HighScore()
        self._spritex += self._vx
        self.rect.centerx = self._spritex
        # collision detection
        block_hit_list = pygame.sprite.spritecollide(self, self.level, False)
        for block in block_hit_list:
            if self._vx > 0:
                self.rect.right = block.rect.left
            elif self._vx < 0:
                self.rect.left = block.rect.right
            self._spritex = self.rect.centerx

        self._vy += self._gravity
        self._spritey += self._vy
        self.rect.centery = self._spritey
        # collision detection when player jumps
        block_hit_list = pygame.sprite.spritecollide(self, self.level, False)
        for block in block_hit_list:
            if self._vy > 0:
                self.rect.bottom = block.rect.top
            elif self._vy < 0:
                self.rect.top = block.rect.bottom
            self._spritey = self.rect.centery
            self._vy = 0
            if self.rect.y >= H - self.rect.height and self._vy >= 0:
                self._vy = 0
                self.rect.y = H - self.rect.height


    # defines the jumping
    def jump(self):
        self.rect.y += 2
        platform_hit_list = pygame.sprite.spritecollide(self, self.level, False)
        self.rect.y -= 2

        # if its okay to jump the speed shall be set upwards.
        if len(platform_hit_list) > 0 or self.rect.bottom >= H:
            self._vy = -19
    # Applies the gravity
    def grav(self):

        if self._vy == 0:
            self._vy = 1
        else:
            self._vy += .35

    # checks if the sprite is dead
    def dead(self):
        # See if we are on the ground.
        if self.rect.y >= H - self.rect.height and self._vy >= 0:
            self._vy = 0
            self.rect.bottom = H
            # You have to update the _spritey pos as well.
            self._spritey = self.rect.centerx
            Player.kill(self)
    # creates a highscore for the player which will be saved onto the textfile
    def HighScore(self):
        pygame.font.init()
        # self.st = pygame.font.SysFont("comicsans ms", 20)
        # self.text_rect,self.text_rect = text_objects('score :',(W/4,H/4),self.st)

        self.dir = path.dirname(__file__)


        with open(path.join(self.dir, 'highscore.txt'), 'w') as f:
            try:
                self.highscore = int(f.read())

            except:
                self.highscore =0

class Powerup(pygame.sprite.Sprite):
     def __init__(self):
         super(Powerup, self).__init__()
         self.bolt = bolt
         self._vy = 5
         self._vx = 5
         self.player = player
         pygame.Rect = (rect)

     def update(self):
         self.player.rect.y += 2
         if self.bolt.rect.colliderect(self.player.rect):
             shift = (self._vx, self._vy)
             # Move the player's rect.
             self.player.rect.x += self._vx
             self.player.rect.y += self._vy
             # Adjust the actual position as well.
             self.player._spritex = self.player.rect.centerx
             self.player._spritey = self.player.rect.centery
             # And the camera.
             self.player.camera.x -= self._vx
             self.player.camera.y -= self._vy
             # Move the platform.
             self.player.rect =+ shift
# creates the enemy class, what it will look like and the attributes it will have
class enemy(pygame.sprite.Sprite):

    def __init__(self, pos, level):
        super(enemy, self).__init__()
        self.image = ENEMY_IMAGE
        self.image1 = IMAGE2
        self.rect = self.image.get_rect(center=pos)
        self._x = 0
        self._y = 0
        self._enemyx = pos[0]
        self._enemyy = pos[1]
        self.level = level
        self._gravity = .9
        # A vector as a camera.


    def update(self):
        self.grav()
        self.dead()

        self._enemyx += self._x
        self.rect.centerx = self._enemyx
        # collision detection for enemy
        block_hit_list = pygame.sprite.spritecollide(self, self.level, False)
        for block in block_hit_list:
            if self._x > 0:
                self.rect.right = block.rect.left
            elif self._x < 0:
                self.rect.left = block.rect.right
            self._enemyx = self.rect.centerx

        self._y += self._gravity
        self._enemyy += self._y
        self.rect.centery = self._enemyy
        # collision detection when enemy jumps
        block_hit_list = pygame.sprite.spritecollide(self, self.level, False)
        for block in block_hit_list:
            if self._y > 0:
                self.rect.bottom = block.rect.top
            elif self._y < 0:
                self.rect.top = block.rect.bottom
            self._enemyy = self.rect.centery
            self._y = 0
            if self.rect.y >= H - self.rect.height and self._y >= 0:
                self._y = 0
                self.rect.y = H - self.rect.height

        # for block in block_hit_list:
             # block.rect.x += self.force
    # this will make the enemy jump
    def jump(self):
        self.rect.y += 2
        platform_hit_list = pygame.sprite.spritecollide(self, self.level, False)
        self.rect.y -= 2

        # If the enemy can jump the speed shall be set upwards.
        if len(platform_hit_list) > 0 or self.rect.bottom >= H:
            self._y = -19
    # calculates the effect of gravity
    def grav(self):

        if self._y == 0:
            self._y = 1
        else:
            self._y += .35

    # checks if the enemy is dead
    def dead(self):
        # See if the enemy on the ground.
        if self.rect.y >= H - self.rect.height and self._y >= 0:
            self._y = 0
            self.rect.bottom = H
            # spritey's position has to be updated as well.
            self._spritey = self.rect.centerx
            enemy.kill(self)

This is the part where the issue occurs

def mainting():
        active_sprite_group = pygame.sprite.Group()
        level_list = [LVL_01()]
        current_level_index = 0
        current_level = level_list[current_level_index]

        player = Player([131, 557], current_level.platforms)
        Enemy = enemy([600, 540], current_level.platforms)
        DS = pygame.display.set_mode((900, 600))
        W, H = DS.get_size()
        clock = pygame.time.Clock()
        FPS = 60

        # definitions of classes made into variables so that they can be used later on
        active_sprite_group = pygame.sprite.Group()
        level_list = [LVL_01()]
        current_level_index = 0
        current_level = level_list[current_level_index]

        # score = HighScore()
        player = Player([131, 557], current_level.platforms)
        Enemy = enemy([600, 540], current_level.platforms)
        # image = bolt_image([350,400])


        intro = True

        while intro:
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    pygame.quit()
                    quit()



                elif event.type == pygame.KEYDOWN:
                    if event.key == pygame.K_LEFT:
                          player._vx = -3

                if event.key == pygame.K_p:



                    print('paused')
                    pygame.display.update()

                if event.key == pygame.K_r or not player.alive():

                    print('gameover')
                    pygame.display.flip()

                    elif event.key == pygame.K_RIGHT:
                    player._vx = 3
                    Enemy.go_left()
                elif event.key == pygame.K_UP:
                    player.jump()



            if event.type == pygame.KEYUP:
                if event.key == pygame.K_LEFT and player._vx < 0:
                    player._vx = 0
            elif event.key == pygame.K_RIGHT and player._vx > 0:
                player._vx = 0

        active_sprite_group.update()

        # Shift the platforms vertically.
        if player.rect.y <= 100:
            diff = player.rect.y - 100
            player.rect.y = 100
            # You have to update the _spritex pos as well.
            player._spritey = player.rect.centery
            current_level.shift_vertical(-diff)

        active_sprite_group.draw(DS)

        # We have to iterate with a for loop because the camera offset
        # has to be added to the rect coords.

        pygame.display.flip()

        clock.tick(FPS)
    mainting()
    pygame.quit()

All your tests involving event.key should be inside the block started by elif event.type == pygame.KEYDOWN: - otherwise it just tries to fetch the attribute key for all events - and any event that is not keyboard related, such as mouse movement, or timer, don't have a key attribute.

Simply re-indent your program so that the tests for "keys" are only executed when the event type is "KEYDOWN" and it should work.

Its because your indentation is wrong.

Heres the correct code:

            elif event.type == pygame.KEYDOWN:
                if event.key == pygame.K_LEFT:
                      player._vx = -3

                if event.key == pygame.K_p:



                    print('paused')
                    pygame.display.update()

                if event.key == pygame.K_r or not player.alive():

                    print('gameover')
                    pygame.display.flip()

                    elif event.key == pygame.K_RIGHT:
                        player._vx = 3
                        Enemy.go_left()
                    elif event.key == pygame.K_UP:
                        player.jump()

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM