I am trying to use the pygame.draw.arc() as a sprite, but its not displaying on the screen.
I can achieve the same effect by writing same code in the main loop, but once I try to create a sprite, the effect is not being displayed.
(One part in the main-loop can be un-commented to see the desired effect as well.)
Any pointers could be of great help.
import pygame
import random
import math
BLACK = ( 0, 0, 0)
WHITE = ( 255, 255, 255)
RED = ( 255, 0, 0)
SCREEN_WIDTH = 513
SCREEN_HEIGHT = 513
class Block(pygame.sprite.Sprite):
def __init__(self, color, width, height):
pygame.sprite.Sprite.__init__(self)
self.color = color
self.image = pygame.Surface([width, height])
self.image.fill(WHITE)
self.image.set_colorkey(WHITE)
self.center_x = SCREEN_WIDTH/2-15
self.center_y = SCREEN_HEIGHT/2-15
# Draw the ellipse, THIS WORKS PERFECTLY
#pygame.draw.ellipse(self.image, color, [0, 0, width, height])
self.i=0
#THIS DOESN'T WORK FOR SOME REASON
pygame.draw.arc(self.image, (0,255,255),(25,25,450,450),0+(self.i*math.pi)/180,math.pi/6 +(self.i*math.pi)/180,10)
self.rect = self.image.get_rect()
self.angle = 0
self.radius = 210
self.speed = 0.05
def update(self):
self.i += self.speed
pygame.init()
screen = pygame.display.set_mode([SCREEN_WIDTH, SCREEN_HEIGHT])
all_sprites_list = pygame.sprite.Group()
block = Block(BLACK, 20, 15)
all_sprites_list.add(block)
done = False
clock = pygame.time.Clock()
i=0
while not done:
for event in pygame.event.get():
if event.type == pygame.QUIT: #
done = True
screen.fill(WHITE)
all_sprites_list.update()
all_sprites_list.draw(screen)
#UNCOMMENT TO SEE THE DESIRED EFFECT
#i= i+1
#pygame.draw.arc(screen, (0,255,255),(25,25,450,450),0+(i*math.pi)/180,math.pi/6 +(i*math.pi)/180,10)
pygame.display.flip()
clock.tick(60)
pygame.quit()
You draw the arc outside of the surface.
Here you pass the values 20 and 15 to Block:
block = Block(BLACK, 20, 15)
So you create a Surface with the size 20, 15:
self.image = pygame.Surface([width, height])
Then you draw the arc in the area 25,25,450,450:
pygame.draw.arc(self.image, (0,255,255),(25,25,450,450),0+(self.i*math.pi)/180,math.pi/6 +(self.i*math.pi)/180,10)
But that area is outside the surface, because it is only 20 pixels wide and 15 pixels high.
The area you passed to pygame.draw.arc is relative to self.image.
Related
I have been trying to make a little game using Pygame. This is my first time using Pygame and I have looked at many tutorials, but my sprite still won't appear. It only shows a black line. How can I fix it?
Xcord = 0
grey = (192,192,192)
import pygame, random, time
pygame.init()
import time
Color_line=(0,0,0)
screen = pygame.display.set_mode([1000, 500])
all_sprites_list = pygame.sprite.Group()
import pygame
grey = (192,192,192)
playerWidth = 50
playerHeight = 50
all_sprites_list = pygame.sprite.Group()
class Player(pygame.sprite.Sprite):
def __init__(self, grey, playerWidth, playerHeight):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.Surface([50, 50])
self.image.fill(grey)
self.image.set_colorkey(grey)
pygame.draw.rect(self.image, grey, [0, 0, playerWidth, playerHeight])
self.rect = self.image.get_rect()
player = Player(grey, 50, 50)
player.rect.x = Xcord
player.rect.y = 400
def update(Player):
pygame.sprite.Sprite.update(Player)
player.rect.x = Xcord
player.rect.y = 400
all_sprites_list.add(player)
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
screen.fill((255, 255, 255))
all_sprites_list.update()
pygame.draw.line(screen,Color_line,(0,500),(1000,500), 75)
all_sprites_list.draw(screen)
pygame.display.flip()
Xcord =+ 50
if Xcord == 400:
Xcord == 0
pygame.quit()
I am kind of trying to make something similar to Google Chrome's no Wi-Fi dinosaur game.
You have a few mistakes.
First: you fill sprite with GRAY and you use set_key on GRAY, so the sprite is transparent and simply you can't see the sprite.
Second: the code runs very fast and the sprite leaves the window and you can't see the sprite.
Third: in the code if Xcord == 400: Xcord == 0, you need = 0 instead of == 0 - and this is why the sprite leaves the window and never go back to position (0, 400)
Another problem is the big mess in the code - you even run some code two times.
My version with many changes.
# PEP8: all imports at start.
# PEP8: every module on a separate line
import pygame
import random
import time
# --- constants --- # PEP8: `UPPER_CAS_NAMES`
GRAY = (192, 192, 192)
RED = (255, 0, 0)
# --- classes --- # PEP8: `CamelCaseName`
class Player(pygame.sprite.Sprite):
def __init__(self, color, x, y, width, weight): # you don't need prefix `player` in variables in class `Player`
super().__init__() # Python 3 method for running a function from the original class
self.color = color
self.image = pygame.Surface([width, weight])
self.image.fill(color)
#self.image.set_colorkey(color)
self.rect = self.image.get_rect()
self.rect.x = x
self.rect.y = y
def update(self):
self.rect.x += 5
if self.rect.x >= 400:
self.rect.x = 0
# --- main ---
color_line = (0,0,0) # PEP8: spaces around `=`, space after `,`
pygame.init()
screen = pygame.display.set_mode([1000, 500])
all_sprites_list = pygame.sprite.Group()
player_width = 50
player_weight = 50
player = Player(RED, 50, 400, 50, 50) # color, x, y, width, height
all_sprites_list.add(player)
clock = pygame.time.Clock()
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
# - only updates -
all_sprites_list.update()
# - only draws -
screen.fill((255, 255, 255))
pygame.draw.line(screen, color_line, (0, 500), (1000, 500), 75)
all_sprites_list.draw(screen)
pygame.display.flip()
clock.tick(30) # Slow down to 30 FPS (frames per seconds)
pygame.quit()
PEP 8 -- Style Guide for Python Code
This question already has answers here:
How do I rotate an image around its center using Pygame?
(6 answers)
How to rotate an image(player) to the mouse direction?
(2 answers)
How to turn the sprite in pygame while moving with the keys
(1 answer)
Closed 1 year ago.
I am creating a racecar game and I have decided to rewrite it because I realised I was initially writing it in a very inefficient way. I initially used image an just changed their location around the screen but I am now trying to learn how to create an object and I am running into a problem which I had initially but I don't know how to fix within a class.
What happens is when I turn the image it distorts a lot and ends up slowing down because I think pygame can't handle it maybe. In my old code, I created a copy of the original image and rotated the copy of the image which fixed the distortion problem. I now don't know how to do the same within a class.
main.py
import pygame, random
#Let's import the Car Class
from Car import Car
pygame.init()
SCREENWIDTH=800
SCREENHEIGHT=600
size = (SCREENWIDTH, SCREENHEIGHT)
screen = pygame.display.set_mode(size)
pygame.display.set_caption("Car Racing")
#This will be a list that will contain all the sprites we intend to use in our game.
all_sprites_list = pygame.sprite.Group()
playerCar = Car(60, 80, 70)
playerCar.rect.x = 160
playerCar.rect.y = 100
# Add the car to the list of objects
all_sprites_list.add(playerCar)
#Allowing the user to close the window...
carryOn = True
clock=pygame.time.Clock()
while carryOn:
for event in pygame.event.get():
if event.type==pygame.QUIT:
carryOn=False
elif event.type==pygame.KEYDOWN:
if event.key==pygame.K_x:
playerCar.moveRight(10)
keys = pygame.key.get_pressed()
if keys[pygame.K_LEFT]:
#playerCar.moveLeft(5)
playerCar.rot_center(2)
if keys[pygame.K_RIGHT]:
#playerCar.moveRight(5)
playerCar.rot_center(-2)
if keys[pygame.K_UP]:
playerCar.moveUp(5)
if keys[pygame.K_DOWN]:
playerCar.moveDown(5)
all_sprites_list.update()
#Drawing on Screen
screen.fill("white")
#Now let's draw all the sprites in one go. (For now we only have 1 sprite!)
all_sprites_list.draw(screen)
#Refresh Screen
pygame.display.flip()
#Number of frames per secong e.g. 60
clock.tick(25)
pygame.quit()
Car.py
import pygame
WHITE = (255, 255, 255)
class Car(pygame.sprite.Sprite):
#This class represents a car. It derives from the "Sprite" class in Pygame.
def __init__(self, width, height, speed):
# Call the parent class (Sprite) constructor
super().__init__()
# Instead we could load a proper picture of a car...
self.image = pygame.image.load("car.png").convert_alpha()
self.image = pygame.transform.rotate(self.image, 90)
#Initialise attributes of the car.
self.width=width
self.height=height
rect_surf = pygame.Surface((width, height), pygame.SRCALPHA)
rect_surf.fill((0, 0, 0, 0))
self.rect_surf = rect_surf
# Draw the car (a rectangle!)
pygame.draw.rect(self.image, (0, 0, 0, 0), [0, 0, self.width, self.height])
# Fetch the rectangle object that has the dimensions of the image.
self.rect = self.image.get_rect()
def moveRight(self, pixels):
self.rect.x += pixels
def moveLeft(self, pixels):
self.rect.x -= pixels
def moveUp(self, pixels):
self.rect.y -= pixels
def moveDown(self, pixels):
self.rect.y += pixels
def changeSpeed(self, speed):
self.speed = speed
def rot_center(self, angle):
rotated_image = pygame.transform.rotate(self.image, angle)
new_rect = rotated_image.get_rect(center = self.image.get_rect(center = (self.rect.x + (self.rect.width / 2), self.rect.y + (self.rect.height / 2))).center)
self.image = rotated_image
self.rect = new_rect
Any help on how to slvoe this would be much appreciated. I had questions about how to initially turn the image on another question, How do I make an object in pygame rotate.
I also don't know how to apply the rect correctly so that it is the size of the image and doesn't create a transparent spot on the image.
Any help would be much appreciated thanks. :):)
You should keep original image in separated variable with angle
self.original_image = pygame.image.load("car.png").convert_alpha()
self.angle = 90
and use it to generate rotated image at start
self.image = pygame.transform.rotate(self.original_image, self.angle)
and later you should increase self.angle and again create rotated image using original image
def rot_center(self, angle):
self.angle += angle
rotated_image = pygame.transform.rotate(self.original_image, self.angle)
new_rect = rotated_image.get_rect(center=self.rect.center)
self.image = rotated_image
self.rect = new_rect
or even shorter
def rot_center(self, angle):
self.angle += angle
self.image = pygame.transform.rotate(self.original_image, self.angle)
self.rect = self.image.get_rect(center=self.rect.center)
Full working code
I used red rectangle instead image so everyone can run it and test it.
I used pygame.math.Vector2(pixels, 0).rotate(self.angle) to move up/down using current angle - car direction - instead of moving to top/bottom of the screen.
import pygame
import random
# --- constants ---
WHITE = (255, 255, 255)
RED = (255, 0, 0)
SCREENWIDTH = 800
SCREENHEIGHT = 600
size = (SCREENWIDTH, SCREENHEIGHT)
# --- classes ---
class Car(pygame.sprite.Sprite):
#This class represents a car. It derives from the "Sprite" class in Pygame.
def __init__(self, width, height, speed):
# Call the parent class (Sprite) constructor
super().__init__()
#Initialise attributes of the car.
self.width = width
self.height = height
# Instead we could load a proper picture of a car...
#self.original_image = pygame.image.load("car.png").convert_alpha()
self.original_image = pygame.surface.Surface((width, height)).convert_alpha()
self.original_image.fill(RED)
self.angle = 90
self.image = pygame.transform.rotate(self.original_image, self.angle)
# Fetch the rectangle object that has the dimensions of the image.
self.rect = self.image.get_rect()
def moveRight(self, pixels):
self.rect.x += pixels
def moveLeft(self, pixels):
self.rect.x -= pixels
def moveUp(self, pixels):
#self.rect.y += pixels
x, y = pygame.math.Vector2(pixels, 0).rotate(self.angle)
self.rect.x += x
self.rect.y -= y
def moveDown(self, pixels):
#self.rect.y += pixels
x, y = pygame.math.Vector2(pixels, 0).rotate(self.angle)
self.rect.x -= x
self.rect.y += y
def changeSpeed(self, speed):
self.speed = speed
def rot_center(self, angle):
self.angle += angle
self.image = pygame.transform.rotate(self.original_image, self.angle)
self.rect = self.image.get_rect(center=self.rect.center)
# --- main ---
pygame.init()
screen = pygame.display.set_mode(size)
pygame.display.set_caption("Car Racing")
#This will be a list that will contain all the sprites we intend to use in our game.
all_sprites_list = pygame.sprite.Group()
playerCar = Car(60, 80, 70)
playerCar.rect.x = 160
playerCar.rect.y = 100
# Add the car to the list of objects
all_sprites_list.add(playerCar)
#Allowing the user to close the window...
carryOn = True
clock = pygame.time.Clock()
while carryOn:
for event in pygame.event.get():
if event.type == pygame.QUIT:
carryOn=False
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_x:
playerCar.moveRight(10)
keys = pygame.key.get_pressed()
if keys[pygame.K_LEFT]:
#playerCar.moveLeft(5)
playerCar.rot_center(2)
if keys[pygame.K_RIGHT]:
#playerCar.moveRight(5)
playerCar.rot_center(-2)
if keys[pygame.K_UP]:
playerCar.moveUp(5)
if keys[pygame.K_DOWN]:
playerCar.moveDown(5)
all_sprites_list.update()
#Drawing on Screen
screen.fill("white")
#Now let's draw all the sprites in one go. (For now we only have 1 sprite!)
all_sprites_list.draw(screen)
#Refresh Screen
pygame.display.flip()
#Number of frames per secong e.g. 60
clock.tick(25)
pygame.quit()
I am working on a simple game. I created a pygame sprite which and tested it by making it move forward and rotating at a consistent speed. However, it seams to be moving left and up (where sin and cos are negative) quicker than right and down (where sin and cos are positive). I tested it without moving and just rotating and it works.
Here is the code:
import pygame
import sys
from math import cos, sin, pi
from time import sleep
SCREEN_WIDTH = 800
SCREEN_HEIGHT = 800
FPS = 60
pygame.init()
DISPLAY = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
CLOCK = pygame.time.Clock()
RED = (255, 0, 0)
GREEN = (0, 255, 0)
BLUE = (0, 0, 255)
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
SHIP_BLUE_IMG = pygame.image.load('./spaceshooter/PNG/playerShip1_blue.png').convert()
SHIP_RED_IMG = pygame.image.load('./spaceshooter/PNG/playerShip1_red.png').convert()
LASER_BLUE_IMG = pygame.image.load('./spaceshooter/PNG/Lasers/laserBlue16.png').convert()
LASER_RED_IMG = pygame.image.load('./spaceshooter/PNG/Lasers/laserRed16.png').convert()
LASER_SPEED = 10
PLAYER_SHIP_SPEED = 5
all_sprites = pygame.sprite.Group()
class Player(pygame.sprite.Sprite):
def __init__(self, img, pos, angle):
super().__init__()
img.set_colorkey((0, 0, 0, 0))
self.angle = angle
self.original_img = pygame.transform.rotate(img, 180) # Becase these images come upside down
self.image = self.original_img
self.rect = self.image.get_rect()
self.rect.center = pos
self._update_image()
def _update_image(self):
x, y = self.rect.center
self.image = pygame.transform.rotate(self.original_img, self.angle)
self.rect = self.image.get_rect()
self.rect.center = (x, y)
def _get_radeons(self):
return (self.angle*pi)/180
def rotate(self, degrees):
self.angle += degrees
self._update_image()
def update(self):
self.rotate(5)
x, y = self.rect.center
nx = sin(self._get_radeons())*PLAYER_SHIP_SPEED + x
ny = cos(self._get_radeons())*PLAYER_SHIP_SPEED + y
self.rect.center = (nx, ny)
player = Player(SHIP_BLUE_IMG, (300, 300), 45)
all_sprites.add(player)
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
DISPLAY.fill(BLACK)
all_sprites.update()
all_sprites.draw(DISPLAY)
pygame.display.update()
CLOCK.tick(FPS)
To describe what it looks like when I run it, it is a ship on a black background that rotates counter-clockwise while moving forward in what should be a circle. But instead, it is creating a sort of spiral, slowly getting closer to the top left corner of the screen.
This is an accuracy issue. Since pygame.Rect is supposed to represent an area on the screen, a pygame.Rect object can only store integral data.
The coordinates for Rect objects are all integers. [...]
The fraction part of the coordinates gets lost when the new position of the player is assigned to the Rect object:
self.rect.center = (nx, ny)
Since this is done every frame, the position error will accumulate over time.
If you want to store object positions with floating point accuracy, you have to store the location of the object in separate variables respectively attributes (self.pos) and to synchronize the pygame.Rect object. round the coordinates and assign it to the location (e.g. .center) of the rectangle:
class Player(pygame.sprite.Sprite):
def __init__(self, img, pos, angle):
# [...]
self.pos = pos
# [...]
def update(self):
self.rotate(5)
nx = sin(self._get_radeons())*PLAYER_SHIP_SPEED + self.pos[0]
ny = cos(self._get_radeons())*PLAYER_SHIP_SPEED + self.pos[1]
self.pos = (nx, ny)
self.rect.center = round(nx), round(ny)
See also Move and rotate.
Minimal example:
import math
import pygame
class Player(pygame.sprite.Sprite):
def __init__(self, img, pos, angle):
super().__init__()
img.set_colorkey((0, 0, 0, 0))
self.angle = angle
self.original_img = pygame.transform.rotate(img, 180)
self.image = self.original_img
self.rect = self.image.get_rect()
self.rect.center = pos
self.pos = pos
self.speed = 5
self.angle_step = 5
self._update_image()
def _update_image(self):
x, y = self.rect.center
self.image = pygame.transform.rotate(self.original_img, self.angle)
self.rect = self.image.get_rect()
self.rect.center = (x, y)
def update(self):
self.angle += self.angle_step
self._update_image()
nx = math.sin(math.radians(self.angle)) * self.speed + self.pos[0]
ny = math.cos(math.radians(self.angle)) * self.speed + self.pos[1]
self.pos = (nx, ny)
self.rect.center = round(nx), round(ny)
pygame.init()
window = pygame.display.set_mode((300, 300))
clock = pygame.time.Clock()
background = pygame.Surface(window.get_size())
background.set_alpha(5)
all_sprites = pygame.sprite.Group()
ship_image = pygame.image.load('Rocket64.png').convert_alpha()
player = Player(ship_image, (window.get_width()//2-40, window.get_height()//2+40), 45)
all_sprites.add(player)
run = True
while run:
clock.tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
all_sprites.update()
window.blit(background, (0, 0))
all_sprites.draw(window)
pygame.display.update()
pygame.quit()
exit()
I am learning pygame by making a simple game.
Here is the code:
Main script:
import pygame
from gracz2 import SpriteGenerator
BLACK = ( 0, 0, 0)
WHITE = ( 255, 255, 255)
GREEN = ( 0, 255, 0)
RED = ( 255, 0, 0)
BLUE = ( 0, 0, 255)
pygame.init()
pygame.display.set_caption("Super Gra!")
screen_height = 720
screen_width = 1280
screen = pygame.display.set_mode((screen_width, screen_height))
all_sprites_list = pygame.sprite.Group()
playerSprite = SpriteGenerator(1,150,150)
playerSprite.rect.x = (screen_width/2 - 75)
playerSprite.rect.y = 550
all_sprites_list.add(playerSprite)
clock = pygame.time.Clock()
mainloop = True
playtime = 0
while mainloop:
for event in pygame.event.get():
# User presses QUIT-button.
if event.type == pygame.QUIT:
mainloop = False
elif event.type == pygame.KEYDOWN:
# User presses ESCAPE-Key
if event.key == pygame.K_ESCAPE:
mainloop = False
keys = pygame.key.get_pressed()
if keys[pygame.K_LEFT]:
playerSprite.moveLeft(8)
if keys[pygame.K_RIGHT]:
playerSprite.moveRight(8)
milliseconds = clock.tick(60)
playtime += milliseconds / 1000.0
all_sprites_list.update()
pygame.display.set_caption("Czas gry: " + str(round(playtime,1)) + " sekund")
# Refresh the screen
screen.fill(BLACK)
all_sprites_list.draw(screen)
screen.blit(playerSprite.image, (playerSprite.rect.x,playerSprite.rect.y))
pygame.display.flip()
print(all_sprites_list.sprites())
print(all_sprites_list)
print(playerSprite.rect.x)
print(playerSprite.rect.y)
pygame.quit()
and another file called "gracz2.py":
import pygame
WHITE = (255, 255, 255)
BLACK = ( 0, 0, 0)
class SpriteGenerator(pygame.sprite.Sprite):
#This class represents a player. It derives from the "Sprite" class in Pygame.
def __init__(self, type, width, height):
# Call the parent class (Sprite) constructor
super().__init__()
# Pass in the color of the player, and its x and y position, width and height.
# Set the background color and set it to be transparent
self.image = pygame.Surface([width, height])
self.image.fill(WHITE)
self.image.set_colorkey(WHITE)
if type == 1:
self.image = pygame.image.load("sprite-ufo.gif").convert_alpha()
elif type == 2:
self.image = pygame.image.load("sprite-bomb.jpg").convert_alpha()
# Fetch the rectangle object that has the dimensions of the image.
self.rect = self.image.get_rect()
def moveRight(self, pixels):
self.rect.x += pixels
def moveLeft(self, pixels):
self.rect.x -= pixels
It could be done in one file but the code is more readable for me this way.
around line 50 i call all_sprites_list.draw(screen)
which to my understanding should blit all the sprites contained in all_sprites_list but it does nothing.
I have to use screen.blit(playerSprite.image, (playerSprite.rect.x,playerSprite.rect.y))
to manually blit the sprite.
As i am going to add generate lots of sprites later i can't blit them all manually.
Why doesn't all_sprites_list.draw(screen) work as intended?
It's probably a stupid mistake in the code but I am trying to find for over an hour now and I am unable to locate it.
Turns out that when i restart my PC the draw() function works fine.
I don't know what caused it first, sorry for asking without following the first rule of IT troubleshooting first (restart and try again)
PS: thank you furas for your answers
I'm creating a 2D platformer type shooting game using python and pygame, and I'm trying to add in tiling mechanics so If I created a platform 100 pixels long and the tile image was only 70 pixels long, it would draw one tile and half of another, so I created a simple prototype, but I can't get it to draw the sprite. Here's my code for it:
import pygame
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
GREEN = (0, 255, 0)
RED = (255, 0, 0)
class Rec(pygame.sprite.Sprite):
def __init__(self, x, y, w, height):
super().__init__()
self.b = 0
self.image = pygame.image.load("grass.png").convert()
if w <= 70:
self.image = pygame.transform.scale(self.image, (w, height))
elif w > 70:
self.image = pygame.Surface([w, height])
while self.b < w:
self.image.blit(pygame.image.load("grass.png").convert(), (x + self.b, y))
self.b += 70
self.rect = self.image.get_rect()
self.rect.x = x
self.rect.y = y
pygame.init()
size = (700, 500)
screen = pygame.display.set_mode(size)
pygame.display.set_caption("My Game")
all_sprites_list = pygame.sprite.Group()
rec = Rec(100, 200, 140, 70)
all_sprites_list.add(rec)
done = False
clock = pygame.time.Clock()
while not done:
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
screen.fill(WHITE)
all_sprites_list.draw(screen)
pygame.display.flip()
clock.tick(60)
pygame.quit()
The line
self.image.blit(pygame.image.load("grass.png").convert(), (x + self.b, y))
should be
self.image.blit(pygame.image.load("grass.png").convert(), (self.b, 0))
since the position you pass to the blit function are relative to the Surface you blit on; but x and y are screen coordinates.
So in your example you blit the grass image with a position of x + self.b = 100, y = 200 on a Surface which has a size of (140, 70), while you should blit the it at (0, 0).