0

Hello I am currently working on a game in pygame and I am now trying to add a ground, gravity and jump. When I run the code I get an attribute error. Please help if you have a fix, here is the code:

import pygame, sys, time
from pygame.locals import *

pygame.init()

# A few variables
zx = 320
zy = 320
x = 25
y = 320
velX = 0
velY = 0
gravity = .50
ground = 720
clock = pygame.time.Clock()

# Screen
size = 1280, 720
screen = pygame.display.set_mode(size)
pygame.display.set_caption('Moon Survival!')

# Moon
moon = pygame.image.load('images/arena2.jpg')
pygame.display.update()

# Player
class Player(pygame.sprite.Sprite):
    global gravity

    def __init__(self, x, y):

        # Player dimensions and position
        self.x = x
        self.y = y
        self.width = 80
        self.height = 80

        # Player image and animation
        self.i0 = pygame.image.load('images/soldier.png')
        self.i1 = pygame.image.load('images/soldier2.png')
        self.timeTarget = 10
        self.timeNum = 0
        self.currentImage = 0

        # Jump and gravity
        self.vSpeed = 1
        self.jumpForce = 8
        self.maxVspeed = 3
        self.isJumping = False

    # Jump inputs
    def getInput(self):
        keys = pygame.key.get_pressed()
        if keys[pygame.K_SPACE]:
            if not self.isJumping:
                self.isJumping = True

    # PLayer updates
    def update(self):

        # Jumping
        self.getInput()
        self.vSpeed += gravity
        if self.vSpeed >  self.maxVspeed:
            self.vSpeed = self.maxVspeed
        self.y += self.vSpeed
        if self.y >= ground.y:
            self.vSpeed = 0
            self.y = ground.y
            self.isJumping = False
        if self.isJumping:
            self.vSpeed += -self.jumpForce

        # Animations
        #self.timeNum += 1
        if (self.timeNum == self.timeTarget):
            if (self.currentImage == 0):
                self.currentImage = 0
            else:
                self.currentImage = 0
            self.timeNum = 0
        self.render()

    # Player rendering
    def render(self):

        if (self.currentImage == 0):
            screen.blit(self.i0, (self.x, self.y))
        #else:
            #screen.blit(self.i1, (self.x, self.y))


# Zombies
zombie = pygame.image.load('images/zombie.png')
pygame.display.update()

# Sprite variables
player = Player(25, 320)

# Game loop
while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            sys.exit()

    # Movement
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_a:
                velX = -5
            if event.key == pygame.K_d:
                velX = +5
        if event.type == pygame.KEYUP:
            if event.key == pygame.K_a:
                velX = 0
            if event.key == pygame.K_d:
                velX = 0 

    # Image blitting
    screen.blit(moon, (0,0))
    screen.blit(zombie, (zx, zy))

    # Movement variables
    player.x += velX
    player.y += velY

    player.update()

    # Screen wrap
    if player.x >= 1240:
        player.x = 1
    if player.x <= 0:
        player.x = 1240

    # Display updating
    clock.tick(75)
    pygame.display.update()

Any help will be greatly appreciated, thank you.

1
  • Add full trackback (error message). There is number of line with problem. Mark this line in your code. Commented Nov 30, 2013 at 17:35

1 Answer 1

1

In some places you try to use int value as object:

ground = 720

self.y = ground.y # error !!!

ground is number int(integer) not object with .y

You could use pygame.Rect()

ground = pygame.Rect(0, 750, 0, 0) # (x, y, width, heigh)

and then you can use ground.x, ground.y, and others - see pygame.Rect().

.


btw: you should move #Movement code, # Movement variablescode, # Screen wrap code into Player class as functions and call that functions in main loop - to make main loop more readable.

# Movement variablescode, # Screen wrap code could be in player.update

# Movement code could be in Player class as event_handler(self, event)

def event_handler(self, event):

    if event.type == pygame.KEYDOWN:
        if event.key == pygame.K_a:
            velX = -5
        elif event.key == pygame.K_d:
            velX = +5
    elif event.type == pygame.KEYUP:
        if event.key in (pygame.K_a, pygame.K_d):
            velX = 0 

(you can use elif as above)

Now you can use this in main loop player.event_handler(event)


EDIT:

I made many modifications in your code - but I had no time to finish it.

Player still doesn't jump. But you have 10 moving zombies, pause (press P) and all in classes.

import pygame
import random

# Player
class Player(pygame.sprite.Sprite):

    def __init__(self, x, y, gravity):

        # Player dimensions and position

        self.gravity = gravity

        # Player image and animation
        self.images = []
        self.images.append(pygame.image.load('images/soldier.png'))
        self.images.append(pygame.image.load('images/soldier2.png'))
        #~ self.images.append(pygame.image.load('ball1.png'))
        #~ self.images.append(pygame.image.load('ball2.png'))
        self.maxImage = len(self.images)
        self.currentImage = 0

        #~ self.rect = pygame.Rect(x, y, 80, 80)
        self.rect = self.images[0].get_rect()
        self.rect.x = x
        self.rect.y = y

        self.timeTarget = 10
        self.timeNum = 0

        self.velX = 0
        self.velY = 0

        # Jump and gravity
        self.vSpeed = 1
        self.jumpForce = 8
        self.maxVspeed = 3
        self.isJumping = False

    # Jump inputs
    def handle_events(self, event):

        if event.type == pygame.KEYDOWN:

            if event.key == pygame.K_SPACE:
                if not self.isJumping:
                    self.isJumping = True

            elif event.key == pygame.K_a:
                self.velX = -5

            elif event.key == pygame.K_d:
                self.velX = +5

        elif event.type == pygame.KEYUP:
            if event.key in (pygame.K_a, pygame.K_d):
                self.velX = 0 

        print "isJumping:", self.isJumping

    # PLayer updates
    def update(self, ground):

        # Jumping

        self.vSpeed -= self.gravity

        if self.vSpeed > self.maxVspeed:
            self.vSpeed = self.maxVspeed

        self.rect.y -= self.vSpeed

        if self.isJumping:
            self.vSpeed -= self.jumpForce

        if self.rect.bottom >= ground.y:
            self.vSpeed = 0
            self.rect.bottom = ground.y
            self.isJumping = False


        # Animations

        if self.timeNum == self.timeTarget:
            self.currentImage += 1
            if self.currentImage >= self.maxImage:
                self.currentImage = 0
            self.timeNum = 0

        self.rect.centerx += self.velX
        self.rect.centery += self.velY

        # Screen wrap
        if self.rect.right > 1280:
            self.rect.left = 0

        elif self.rect.left < 0:
            self.rect.right = 1280

    # Player rendering
    def render(self, surface):
        surface.blit(self.images[self.currentImage], self.rect)

#----------------------------------------------------------------------

class Zombie():

    def __init__(self, x, y):

        self.image = pygame.image.load('images/zombie.png')
        #~ self.image = pygame.image.load('ball2.png')
        self.rect = self.image.get_rect()

        self.rect.x = x
        self.rect.y = y

        self.direction_left = True

    def update(self, surface_rect):
        if self.direction_left:
            self.rect.x -= 1
            if self.rect.left <= surface_rect.left:
                self.direction_left = not self.direction_left
        else:
            self.rect.x += 1
            if self.rect.right >= surface_rect.right:
                self.direction_left = not self.direction_left

    def render(self, surface):
        surface.blit(self.image, self.rect)

#----------------------------------------------------------------------

class Background():

    def __init__(self):

        self.image = pygame.image.load('images/arena2.jpg')
        #~ self.image = pygame.image.load('background.jpg')
        self.rect = self.image.get_rect()

    def render(self, surface):
        surface.blit(self.image, self.rect)

#----------------------------------------------------------------------

class Game():

    def __init__(self):
        pygame.init()

        # A few variables
        self.gravity = .50
        self.ground = pygame.Rect(0, 720, 0, 0)

        # Screen
        size = (1280, 720)
        self.screen = pygame.display.set_mode(size)
        pygame.display.set_caption('Moon Survival!')

        # Moon / Background
        self.moon = Background()

        # Zombies
        self.zombies = []
        for i in range(10):
            self.zombies.append( Zombie(random.randint(0,1280), random.randint(0,720)) )

        # Player
        self.player = Player(25, 320, self.gravity)

        # Font for text
        self.font = pygame.font.SysFont(None, 72)

        # Pause - center on screen
        self.pause_text = self.font.render("PAUSE", -1, (255,0,0))
        self.pause_rect = self.pause_text.get_rect(center = self.screen.get_rect().center)

    def run(self):

        clock = pygame.time.Clock()

        # "state machine" 
        RUNNING   = True
        PAUSED    = False 
        GAME_OVER = False

        # Game loop
        while RUNNING:

            # (all) Events

            for event in pygame.event.get():

                if event.type == pygame.QUIT:
                    RUNNING = False

                elif event.type == pygame.KEYDOWN:

                    if event.key == pygame.K_ESCAPE:
                        RUNNING = False

                    elif event.key == pygame.K_p:
                        PAUSED = not PAUSED

                # Player/Zomies events  

                if not PAUSED and not GAME_OVER:
                    self.player.handle_events(event)

            # (all) Movements / Updates

            if not PAUSED and not GAME_OVER:
                self.player.update(self.ground)
                for z in self.zombies:
                    z.update(self.screen.get_rect())

            # (all) Display updating

            self.moon.render(self.screen)

            for z in self.zombies:
                z.render(self.screen)

            self.player.render(self.screen)

            if PAUSED:
                self.screen.blit(self.pause_text, self.pause_rect)

            pygame.display.update()

            # FTP

            clock.tick(75)

        # --- the end ---
        pygame.quit()

#---------------------------------------------------------------------

Game().run()
Sign up to request clarification or add additional context in comments.

8 Comments

Hello the part with ground fixes the error but now my player is falling through the floor and a few other errors like when I jump my player doesn't stop, he just flies off screen, also when I move all of the movement code the movement stops working. Any suggestions?
Use print self.y, ground.y and you see that player is stopping but below bottom window border. self.y is top of player so all player is below self.y. With pygame.Rect() you could test self.rect.bottom >= ground.y. You could also use self.rect.top, self.rect.centerx, etc. See: pygame.Rect(). You can use self.rect with screen.blit - screen.blit(self.i0, self.rect) - and with collision detect ([pygame.Rect.colliderect](pygame.Rect.colliderect), etc., pygame.sprite.collide_rect, etc. ).
You can detect collision with enemies and grounds.
@GhostFrag1 I made some modifications in your code and I put it in answer.
Thank you I actually found out recently why my jumping wasn't working also why I fell through the floor. Thank you for the help. Will try your modifications and add in jumping myself :)
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.