How to create a sprite from an image - python

I have two files of code, one with the sprite classing and one. with the main background for my (basic) pygame. I am aiming to load in a png image to use in my background.
class sprite code:
class GRASS (pygame.sprite.Sprite):
def _init_(self):
super()._init_()
self.image = pygame.image.load("grass").convert()
self = self.image.set_colorkey(WHITE)
self.rect = self.image.get_rect()
main code:
from GRASS import GRASS
pygame.init()
screen = pygame.display.set_mode((800,600))
clock = pygame.time.Clock()
FPS = 60
screen.fill(WHITE)
pygame.draw.rect(screen, SKY_BLUE, [0, 0, 20000, 400],0)
pygame.draw.rect(screen, GREEN, [0, 400, 20000, 200],0)
cloud()
grassblock1 = GRASS
grassblock1.x = 10
grassblock1.y = 50
I am aiming for it to show up on the screen in the designated space but it doesn't show up at all. I am not sure if all the code I am using is needed either.

First, Rename the grass file to grass.png.
Then, add the extension .png to the image grass in
self.image = pygame.image.load("grass").convert()

Related

Is it possible to change sprite colours in Pygame?

I'm making a game in Python using Pygame that includes a small avatar maker before the game starts, but instead of creating a big sprite sheet with 88 different combinations of hairstyles and colours, is there a way that I can just use a generic .png image of each hairstyle and apply colour to it in-game?
The hairstyles are saved as .png images with alpha and anti-aliasing, so they are not just one shade of colour. I've got 8 different hairstyles and 11 different colours. It wouldn't be a problem to load them in as a sprite sheet and clip them in-game, but if there was a way to apply colour (or hue) in the game then not only would it be easier on the memory, but would open it up to more possibilities.
If the image is a "mask" image, with a transparent background and a white (255, 255, 255) mask, then you can "tint" the image with ease.
Load the image:
image = pygame.image.load(imageName)
Generate a uniform colored image with an alpha channel and the same size:
colorImage = pygame.Surface(image.get_size()).convert_alpha()
colorImage.fill(color)
Blend the image with maskImage, by using the filter BLEND_RGBA_MULT:
image.blit(colorImage, (0,0), special_flags = pygame.BLEND_RGBA_MULT)
A sprite class may look like this:
class MySprite(pygame.sprite.Sprite):
def __init__(self, imageName, color):
super().__init__()
self.image = pygame.image.load(imageName)
self.rect = self.image.get_rect()
colorImage = pygame.Surface(self.image.get_size()).convert_alpha()
colorImage.fill(color)
self.image.blit(colorImage, (0,0), special_flags = pygame.BLEND_RGBA_MULT)
Minimal example: repl.it/#Rabbid76/PyGame-ChangeColorOfSurfaceArea-4
import pygame
def changColor(image, color):
colouredImage = pygame.Surface(image.get_size())
colouredImage.fill(color)
finalImage = image.copy()
finalImage.blit(colouredImage, (0, 0), special_flags = pygame.BLEND_MULT)
return finalImage
pygame.init()
window = pygame.display.set_mode((300, 160))
image = pygame.image.load('CarWhiteDragon256.png').convert_alpha()
hue = 0
clock = pygame.time.Clock()
nextColorTime = 0
run = True
while run:
clock.tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
color = pygame.Color(0)
color.hsla = (hue, 100, 50, 100)
hue = hue + 1 if hue < 360 else 0
color_image = changColor(image, color)
window.fill((96, 96, 64))
window.blit(color_image, color_image.get_rect(center = window.get_rect().center))
pygame.display.flip()
pygame.quit()
exit()
Sprite:

python won't recognize rect as an attribute

I am currently in the process of making a 2D platformer game with procedurally generated levels in pygame, however I am getting the following error messages, which are preventing me from continuing:
Traceback (most recent call last):
File "C:\Users\Win10\Desktop\SCV v3.2.py", line 63, in <module>
main() #calls the main function
File "C:\Users\Win10\Desktop\SCV v3.2.py", line 36, in main
block_object = block_class(0, 5)
File "C:\Users\Win10\Desktop\SCV v3.2.py", line 29, in __init__
self.image.Rect = (32, 32) #block is 32*32 pixels large
AttributeError: 'pygame.Surface' object has no attribute 'Rect'
My first thought was that I had just made some of the classes and functions in the wrong order, however that didn't seem to help, I then tried renaming some of the variables, as well as making sure that I had correctly named all of my variables after this fact. I then went to youtube to see if anyone else was having a similar problem and I found that this works in python 3.4 as I had seen a very similar class work, however I have a feeling that this would only create more problems for the rest of the code as I have only used versions of python from 3.6 to the present.
Here is the code that is having the problem:
import pygame #imports pygame
import time #imports the timer so I can use the tick function to make game 60 fps
import sys #imports system
from pygame import * #imports all pygame files
win_height = 500 #height of the window is 500 pixles
win_width = 500 #width of the window is 500 pixels
red = (255, 0, 0) #makes red a preset colour using rgb
green = (0, 255, 0) #makes green a preset colour using rgb
display = (win_height, win_width) #creates the windown as 500*500 pixels
depth = 32 #prevents infinate recursion
timer = pygame.time.Clock() #creates a timer
flags = 0 #I don't really know what this does, however I have seen in many places it being used, therefore I assumed that it was important
screen = pygame.display.set_mode(display, depth, flags) #loads up a pygame window
class entity(pygame.sprite.Sprite): #makes player a sprite
def __init__(self):
pygame.sprite.Sprite.__init__(self) #sets sprite to initiate
class block_class(entity):
def __init__(self, x, y):
self.image = Surface((32, 32))
self.image.rect = (32, 32) #block is 32*32 pixels large
self.image.fill(Color ("#FF0400")) #block is red
self.image.convert()
self.rect = Rect(x, y, 32, 32)
def main(): #main game function
block_object = block_class(0, 5)
player_object = player_class(0,0)
while 1: #updates the screen so you can see changes like movement
timer.tick(60)
player_object.update()
screen.fill(red) #makes the screen red(will probably be temporary)
pygame.display.update()
class player_class(entity): #defines the player class
def __init__(self, x, y): #x is the players x coordinate, y is player y coordinate
self.xvel = 0 #how fast the player is moving to the left and right
self.yvel = 0 #how fast the player is moving up and down
self.image = Surface((32, 32))
self.image.rect = (32, 32) #player is 32*32 pixels large
self.image.fill(Color ("#00FF33")) #player is green
self.image.convert()
self.rect = Rect(x, y, 32, 32)
def update():
pass
main() #calls the main function
self.image = Surface((32, 32))
You set surface width and height there. There is no rect attr in Surface.
Surface doc

When I am trying to pass an image through pygame, it keeps saying 'pygame.Surface' has no attribute

I have tried everything I can think of to fix this, but I can't seem to find it. I know it is probably a simple fix, but I cannot find what is making this happen. This is the first part of my code :
import pygame, sys, time
from pygame.locals import *
pygame.init()
WINDOWWIDTH = 900
WINDOWHEIGHT = 400
MOVERATE = 5
screen = pygame.display.set_mode((WINDOWWIDTH, WINDOWHEIGHT))
TEXTCOLOR = (255, 255, 255)
BACKGROUNDCOLOR = (0, 0, 0)
FPS = 40
clock = pygame.time.Clock()
x = 200
y = 150
class player(pygame.sprite.Sprite):
def __init__(self, x, y):
super(player, self).__init__()
temp_image = pygame.image.load("stand_down.png").convert_alpha()
self.image_down = pygame.transform.scale(temp_image, (100, 200))
temp_image = pygame.image.load("standleft.png").convert_alpha()
self.image_left = pygame.transform.scale(temp_image, (100, 200))
temp_image = pygame.image.load("standright.png").convert_alpha()
self.image_right = pygame.transform.scale(temp_image, (100, 200))
self.image = self.image_down
# keep position and size in pygame.Rect()
# to use it in collision checking
self.rect = self.image.get_rect(x=x, y=y)
def draw(self, x, y):
screen.blit(self.image, self.rect)
def handle_event(self):#, event)
self.image = self.image_down.get_rect()
self.image = pygame.Surface((x, y))
key = pygame.key.get_pressed()
if key[K_LEFT]:
self.rect.x -= 50
self.image = self.image_left
if key[K_RIGHT]:
self.rect.x += 50
self.image = self.image_right
class room1():
#bedroom
def __init__(self):
self.x, self.y = 16, WINDOWHEIGHT/2
self.speed = 3
def draw(self):
background = pygame.image.load("bedroom.jpg").convert()
background = pygame.transform.scale(background, (WINDOWWIDTH, WINDOWHEIGHT))
screen.blit(background, (0, 0))
And this is my main function :
def main():
while True:
for event in pygame.event.get():
player.handle_event.get(event)
player.handle_event(screen)
room1.draw(screen)
player.draw(screen, x, y)
pygame.display.update()
pygame.display.flip()
clock.tick(FPS)
main()
I keep getting the same error :
File "C:\Python32\Project3\proj3pt2.py", line 220, in handle_event
self.image = self.image_down.get_rect()
AttributeError: 'pygame.Surface' object has no attribute 'image_down'
I know it's probably an easy fix, but I don't know where to look for it, and how I messed up. If someone could explain that, it would be much appreciated!
When you have an instance and call one of its methods, the instance gets automatically passed as the first argument, self. So if you have a class MyClass and an instance my_instance and you call its handle_event method, it's the same as calling MyClass.handle_event(my_instance).
In your program you never create an instance of the player class and so you're passing the screen as the self argument directly to the class (the screen is actually a pygame.Surface). That means the self in the handle_event method actually refers to the screen surface and since surfaces don't have an image_down attribute, Python raises an error when the self.image_down.get_rect() part is reached.
To fix this problem, you have to create an instance (also called object) of the player class and must not pass an argument to handle_event (unless you add more parameters to the method):
player_instance = player(x_position, y_position)
Then use the instance inside of the while and event loops:
while True:
player_instance.handle_event()
You also have to create an instance of the room1 class instead of using the class directly.
Here's a complete example with some comments about other problems:
import pygame
pygame.init()
WINDOWWIDTH = 900
WINDOWHEIGHT = 400
screen = pygame.display.set_mode((WINDOWWIDTH, WINDOWHEIGHT))
FPS = 40
clock = pygame.time.Clock()
# Load images once globally and reuse them in the program.
background = pygame.image.load("bedroom.jpg").convert()
background = pygame.transform.scale(background, (WINDOWWIDTH, WINDOWHEIGHT))
temp_image = pygame.image.load("stand_down.png").convert_alpha()
image_down = pygame.transform.scale(temp_image, (100, 200))
temp_image = pygame.image.load("standleft.png").convert_alpha()
image_left = pygame.transform.scale(temp_image, (100, 200))
temp_image = pygame.image.load("standright.png").convert_alpha()
image_right = pygame.transform.scale(temp_image, (100, 200))
class player(pygame.sprite.Sprite):
def __init__(self, x, y):
super(player, self).__init__()
self.image_down = image_down
self.image_left = image_left
self.image_right = image_right
self.image = self.image_down
# keep position and size in pygame.Rect()
# to use it in collision checking
self.rect = self.image.get_rect(x=x, y=y)
# You don't have to pass x and y, since you already
# use the `self.rect` as the blit position.
def draw(self, screen):
screen.blit(self.image, self.rect)
def handle_event(self):
# These two lines don't make sense.
#self.image = self.image_down.get_rect()
#self.image = pygame.Surface((x, y))
# I guess you want to switch back to image_down.
self.image = self.image_down
key = pygame.key.get_pressed()
if key[pygame.K_LEFT]:
self.rect.x -= 5
self.image = self.image_left
if key[pygame.K_RIGHT]:
self.rect.x += 5
self.image = self.image_right
class room1():
def __init__(self):
self.x, self.y = 16, WINDOWHEIGHT/2
# Reference to the background image.
self.background = background
def draw(self, screen): # Pass the screen.
screen.blit(self.background, (0, 0))
def main():
# Create player and room instances.
player_instance = player(200, 150)
room1_instance = room1()
while True:
for event in pygame.event.get():
# Users can press the "X" button to quit.
if event.type == pygame.QUIT:
return
player_instance.handle_event()
room1_instance.draw(screen)
player_instance.draw(screen)
# You don't need both update and flip.
# pygame.display.update()
pygame.display.flip()
clock.tick(FPS)
main()
pygame.quit()
Side note: PEP 8 recommends uppercase names for classes, so Player instead of player. Then you could call the instance player.
I suspect you do somewhere something like this
player = player.transform.scale(player.image)
player is Sprite but scale returns Surface - so you replace Sprite with Surface and later you have problems.
(BTW: I saw the same problem in some question few days ago)
If you have to rescale image then do it in __init__ as you already do with some images.
In real game you should create images with correct sizes using any Image Editor so you don't have to use scale()
BTW: in handle_event you do
self.image = self.image_down.get_rect()
self.image = pygame.Surface((x, y))
You assign Rect to Surface (self.image) and later you assing new empty Surface with size x, y. Surface doesn't keep positon, it uses only width, height.
You have self.rect to keep positiona and you already change it with
self.rect.x -= 50
and
self.rect.x += 50
BTW: use UpperCaseNames for classes to make code more readable
class Player(...)
class Room1(...)
Event Stackoverflow knows this rule and it uses light blue color for classes to make code more readable.
More: PEP 8 -- Style Guide for Python Code
BTW: in room1.draw() you read and rescale image again and again - it can slow down program. Do it in room.__init__

Pygame Collision Detection: AttributeError

I've been banging my head against this for a while. I am trying to make a game with PyGame and I got up to the collision segment and have been stuck for a while and have checked a few threads.
This is the code I have (removed other methods and conditional statements in between, but left the relevant parts). I am a little confused by the error because I do a self.imageRect = self.image.get_rect() in both classes init, yet I have this error. The error was specifically:
"AttributeError: 'Pebble' object has no attribute 'rect'" when the program attempts to carry out the collision detection part in the dog class. What have I been doing wrong?
import random
import pygame, sys
pygame.init()
clock = pygame.time.Clock() # fps clock
screenSize = WIDTH, HEIGHT = [800, 600]
screen = pygame.display.set_mode(screenSize)
background = pygame.Surface(screen.get_size())
bgColorRGB = [153, 204, 255]
background.fill(bgColorRGB)
pebbleGroup = pygame.sprite.Group()
pebbleSingle = pygame.sprite.GroupSingle()
dogSingle = pygame.sprite.GroupSingle()
#----------------------------------------------------------------------
class Dog(pygame.sprite.Sprite):
def __init__(self, path, speed):
pygame.sprite.Sprite.__init__(self) #call Sprite initializer
self.image = pygame.image.load(path) # load sprite from path/file loc.
self.imageRect = self.image.get_rect() # get bounds of image
self.imageWidth = self.image.get_width()
self.imageHeight = self.image.get_height()
self.speed = speed
# sets location of the image, gets the start location of object
# sets the start location as the image's left and top location
def setLocation(self, location):
self.imageRect.left, self.imageRect.top = location
def checkCollision(self, pebble, dogGroup):
if pygame.sprite.spritecollide(pebble, dogGroup, False):
print "collided"
#---------------------------------------------------------------------
class Pebble(pygame.sprite.Sprite):
def __init__(self, path, speed, location):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load(path)
self.imageRect = self.image.get_rect()
self.imageWidth = self.image.get_width()
self.imageHeight = self.image.get_height()
self.imageRect.left, self.imageRect.top = location
self.speed = speed # initialize speed
self.isDragged = False
#----------------------------------------------------------------------
def startGame():
pebblePaths = ['images/pebble/pebble1.jpg', 'images/pebble/pebble2.jpg']
for i in range(3):
pebblePath = pebblePaths[random.randrange(0, len(pebblePaths))]
pebbleSpeed = [random.randrange(1, 7), 0]
pebbleLocation = [0, random.randrange(20, HEIGHT - 75)]
pebble = Pebble(pebblePath, pebbleSpeed, pebbleLocation)
pebbleGroup.add(pebble)
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
for pebble in pebbleGroup:
dog.checkCollision(pebble, dogSingle)
pygame.display.flip()
clock.tick(30) # wait a little before starting again
startGame()
It's expecting Sprite.rect, so change from
self.imageRect = self.image.get_rect()
#to
self.rect = self.image.get_rect()
Note
self.imageWidth = self.image.get_width()
self.imageHeight = self.image.get_height()
self.imageRect.left, self.imageRect.top = location
These are not necessary, since rect's have many properties, like self.rect.width or self.rect.topleft = location . Another useful one is centerx.
full list at: pygame Rect docs

making sprites randomly appear

I am trying to have sprites randomly appear on the screen with out using OOP principles
this code is from a ants demo for AI
if randint(1, 10) == 1:
leaf = Leaf(world, leaf_image)
leaf.location = Vector2(randint(0, w), randint(0, h))
world.add_entity(leaf)
world.process(time_passed)
world.render(screen)
pygame.display.update()
Question:
How do I get Sprites on the screen randomly?
I know to blit them
but how without using Object-Oriented
this is the only part my code is missing a way for sprites to randomly appear
this the code to the antstate.py where im getting the code:
http://www.mediafire.com/?5tjswcyl9xt5huj
A sprite is an object. So you need to use some OOP to work with a sprite. Here's an example:
# Sample Python/Pygame Programs
# Simpson College Computer Science
# http://cs.simpson.edu/?q=python_pygame_examples
import pygame
import random
# Define some colors
black = ( 0, 0, 0)
white = ( 255, 255, 255)
# This class represents the ball
# It derives from the "Sprite" class in Pygame
class Block(pygame.sprite.Sprite):
# Constructor. Pass in the color of the block,
# and its x and y position
def __init__(self, color, width, height):
# Call the parent class (Sprite) constructor
pygame.sprite.Sprite.__init__(self)
# Create an image of the block, and fill it with a color.
# This could also be an image loaded from the disk.
self.image = pygame.Surface([width, height])
self.image.fill(color)
# Fetch the rectangle object that has the dimensions of the image
# image.
# Update the position of this object by setting the values
# of rect.x and rect.y
self.rect = self.image.get_rect()
# Initialize Pygame
pygame.init()
# Set the height and width of the screen
screen_width=700
screen_height=400
screen=pygame.display.set_mode([screen_width,screen_height])
# This is a list of 'sprites.' Each block in the program is
# added to this list. The list is managed by a class called 'RenderPlain.'
block_list = pygame.sprite.RenderPlain()
for i in range(50):
# This represents a block
block = Block(black, 20, 15)
# Set a random location for the block
block.rect.x = random.randrange(screen_width)
block.rect.y = random.randrange(screen_height)
# Add the block to the list of objects
block_list.add(block)

Categories

Resources