1

--- FULL CODE AT BOTTOM OF QUESTION ---

my plan is to add an area of my screen occupied by an NPC to be completely unable to enter by the player. I've tried doing this method by doing this in the NPC class of my code, where the y position of the player is compared to the "self.y"/current y position of the npc:

class NPC(object):
        def __init__(self, path, x, y):
                self.image = pygame.image.load(path).convert_alpha()
                self.x = x
                self.y = y
                self.width = self.image.get_width()
                self.height = self.image.get_height()
                self.hitbox = (self.x, self.y, self.width, self.height)


        def spawn(self, surface):
                surface.blit(self.image, (self.x, self.y))
                self.hitbox = (self.x, self.y, self.width, self.height)
                pygame.draw.rect(screen, (255, 255, 255), self.hitbox, 2)

        def collide(self, x, y, width, height):
                if self.y <= y <= self.y + self.height:
                        print("collide")
                        up = True
                else:
                        up = False
                        print("not")

I am aware that I've not properly finished the code yet, I've only added in the part that should stop the player from going up at the moment for testing purposes.

For some reason however, the collision boundary is at the very top of the screen (whilst the NPC is not) and I suspect it's due to the program measuring the height of the npc from the top of the screen (i.e: npc sprite is 32 pixels tall, so collide region is first 32 pixels at top of screen)

The code that stops the player from moving (which is what the "up" boolean refers to outside of the class) also isn't working - is this due to not returning the values, possibly?

FULL CODE:

import pygame
import time

progress = 0

pygame.init()
(width, height) = (600, 400) #specify window resolution
bg_colour = (100,20,156) #specify bg colour

player_path = "downChara.png" #specifies image path

moveDown = True
moveUp = True
moveRight = True
moveLeft = True

class Player(object): #representitive of the player's overworld sprite
        def __init__(self):
            self.image = pygame.image.load(player_path).convert_alpha() #creates image, the player_path variable allowing it to be updated
            self.X = (width/2) -16; # x co-ord of player
            self.Y = (height/2)-16; # y co-ord of player
            self.width = self.image.get_width()
            self.height = self.image.get_height()
            self.hitbox = (self.X, self.Y, self.width, self.height)


        def handle_keys(self, down, up, left, right): #handling the keys/inputs
                key = pygame.key.get_pressed()
                dist = 5 #distance travelled in one frame of the program
                if key[pygame.K_DOWN] and down == True: #if down
                        self.Y += dist #move down the length of dist
                        player_path = "downChara.png" #change image to down
                        self.image = pygame.image.load(player_path).convert_alpha()
                elif key[pygame.K_UP] and up == True: #if up
                        self.Y -= dist #move up the length of dist
                        player_path = "upChara.png" #change to up
                        self.image = pygame.image.load(player_path).convert_alpha()
                if key[pygame.K_RIGHT] and right == True: #etc.
                        self.X += dist
                        player_path = "rightChara.png"
                        self.image = pygame.image.load(player_path).convert_alpha()
                elif key[pygame.K_LEFT] and left == True:
                        self.X -= dist
                        player_path = "leftChara.png"
                        self.image = pygame.image.load(player_path).convert_alpha()


        def outX(coord): #"coord" acts the same as "self"
                return (coord.X)
        def outY(coord):
                return (coord.Y)


        def draw(self, surface): #draw to the surface/screen
            surface.blit(self.image, (self.X, self.Y))
            self.hitbox = (self.X, self.Y, self.width, self.height)
            pygame.draw.rect(screen, (255, 255, 255), self.hitbox, 2)
            return self.X, self.Y, self.width, self.height


class NPC(object):
        def __init__(self, path, x, y):
                self.image = pygame.image.load(path).convert_alpha()
                self.x = x
                self.y = y
                self.width = self.image.get_width()
                self.height = self.image.get_height()
                self.hitbox = (self.x, self.y, self.width, self.height)


        def spawn(self, surface):
                surface.blit(self.image, (self.x, self.y))
                self.hitbox = (self.x, self.y, self.width, self.height)
                pygame.draw.rect(screen, (255, 255, 255), self.hitbox, 2)

        def collide(self, x, y, width, height):
                if self.y <= y <= self.y + self.height:
                        print("collide")
                        up = True
                else:
                        up = False
                        print("not")
                ##if self.y < player.hitbox[1]

def text_objects(text, font):
        textSurface = font.render(text, True, (255, 255, 255))
        return textSurface, textSurface.get_rect()

def interact(text):
        textbox = pygame.transform.scale(pygame.image.load("bigbox.png"), (600, 111))
        textSize = pygame.font.Font("cour.ttf",28) #specify text size
        TextSurf, TextRect = text_objects(text, textSize) #allow text to be positioned
        TextRect.topleft = (12, 297) #where text will be
        screen.blit(textbox, (0, 289))
        screen.blit(TextSurf, TextRect) #display text
        pygame.display.update() #updates screen
        time.sleep(2)
        screen.fill(bg_colour, TextRect)



##def checker(array):
##  ##  check first value of each part of array (all numbers)
##  ##  compare it to progress
##  ##  if equal to or less than, cycle through rest of that part of array.
##  ##  if greater than, then ignore.
##  ##  e.g: progress = 49, NPC1 will still be on text "0", NPC2 will now be on "33" and NPC3 will be on "0"
##  
##        placeholderList = []
##  
##        for x in range(len(array)):
##                if array[x][0] <= progress:
##                        del placeholderList[0:]
##                        placeholderList.append(array[x][1:])
##        for x in range(len(placeholderList)):
##                passMe = placeholderList[x]
##                print (passMe)
##                npc.interact(passMe)


screen = pygame.display.set_mode((width, height)) #create window
pygame.display.set_caption('EduGame') #specify window name

player = Player()

playerx, playery, playerwidth, playerheight = player.draw(screen)

clock = pygame.time.Clock()

person1 = NPC("talkToThis.png",100, 200)
npc = NPC("test.png",0, 0)

def setup(text):
        for x in range(len(text)):
                passtext = text[x]
                interact(passtext)


boarderX = player.outX()
boarderY = player.outY()
##print (boarderX, boarderY) #making sure they both returned properly

pygame.display.flip() #paints screen
gameRun = True #allow game events to loop/be carried out more than once



while gameRun: #while game is running:
        person1text2 = [[0,"beginng","www","xxdqsd"],[1,"middle","aa"],[2,"end!"]]
        personText = ("hello","hi","bye")

        playerx, playery, playerwidth, playerheight = player.draw(screen)
        print(playerx, playery, playerwidth, playerheight)
        npc.collide(playerx, playery, playerwidth, playerheight)

        event = pygame.event.poll()
        if event.type == pygame.QUIT: #if the "x" is pressed
                pygame.quit() #quit game
                gameRun = False #break the loop.
                quit()
        if event.type == pygame.KEYDOWN and event.key == pygame.K_RETURN:
##                checker(person1text2)
                setup(personText)



        player.handle_keys(moveDown, moveUp, moveLeft, moveRight) #handle keys

        screen.fill(bg_colour) #draw background colour

        player.draw(screen) #draws player

        person1.spawn(screen)



        pygame.display.update()

        posX = player.outX()
        posY = player.outY()

        if posX > width - 32: #this is because the sprite's "X" is determined in the top left corner, meaning we have to subtract the width from the measurement
                moveRight = False
        else:
                moveRight = True
        if posX < 0:
                moveLeft = False
        else:
                moveLeft = True
        if posY > height - 32: #this is because the sprite's "X" is determined in the top left corner, meaning we have to subtract the width from the measurement
                moveDown = False
        else:
                moveDown = True
        if posY < 0:
                moveUp = False
        else:
                moveUp = True



        clock.tick(60)

it's very WIP, so if you happen to catch anything else whilst checking through it then feel free to bring it up.

Polybrow
  • 65
  • 1
  • 6
  • I'd just create some walls (`pygame.Rect`s or `pygame.sprite.Sprite`s) around the NPC and handle the collisions in this way: https://stackoverflow.com/a/45017561/6220679 – skrx Sep 21 '18 at 21:33

0 Answers0