I'm trying to make a basic (Mario style) game but my sprite(plumber) doesn't appear, it could be hidden behind background? i'm not exactly sure, i am not getting any errors either.
import pygame
import sys
import itertools
import pygame
from pygame.sprite import Sprite
cloud_background = pygame.image.load('clouds.bmp')
brick_tile = pygame.image.load('brick_tile.png')
pink = (255, 64, 64)
w = 640
h = 480
screen = pygame.display.set_mode((w, h))
running = 1
def setup_background():
screen.fill((pink))
screen.blit(cloud_background,(0,0))
brick_width, brick_height = brick_tile.get_width(), brick_tile.get_height()
for x,y in itertools.product(range(0,640,brick_width),
range(390,480,brick_height)):
# print(x,y)
screen.blit(brick_tile, (x, y))
pygame.display.flip()
while running:
setup_background()
event = pygame.event.poll()
if event.type == pygame.QUIT: sys.exit()
class plumber(sprite):
def __init__(
self, screen, img_filename, init_position,
init_direction, speed):
Sprite.__init__(self)
self.screen = screen
self.speed = speed
self.base_image = pygame.image.load(Mario_sideways_sprite_2xL.png).convert_alpha()
self.image = self.base_image
self.pos = 50,50
First problem found is that you must modify
pygame.image.load(Mario_sideways_sprite_2xL.png)
with something like.
pygame.image.load("Mario_sideways_sprite_2xL.png")
Besides this, the code has many problems that impedes it to work. For example,
you do not instantiate your plumber class.
class plumber(sprite) should be plumber(Sprite) (still better Plumber(Sprite))
You need something like:
myplumber = Plumber()
allsprites = pygame.sprite.RenderPlain((myplumber, ....))
clock = pygame.time.Clock()
You could see here the main parts of a simple program like yours.
Related
I recently started exploring classes and I have made my first class (sort of) but it doesn't seem to be working. I have code creating the class and function, then takes the values and blits an image to certain coordinates. for some reason It takes the values from inside the class instead of what I told it to have. I am new to classes so I'm not sure what to do, please help, thanks!
import pygame
pygame.init()
Screen = pygame.display.set_mode((800, 400))
TC = pygame.image.load("TC.png").convert_alpha()
ANUM = 0
class MTC() :
def __init__(self,) :
self.Tx = 0
self.Ty = 0
Screen.blit(TC,(self.Tx,self.Ty))
TMTC = MTC()
TMTC.Tx = 800
TMTC.Ty = 800
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
pygame.display.update()
The image is blit in the constructor. At this point the coordinates are not yet changed. You have add a method that blits the object:
class MTC() :
def __init__(self,) :
self.Tx = 0
self.Ty = 0
def dra():
Screen.blit(TC,(self.Tx,self.Ty))
Call the draw method in the application loop:
TMTC = MTC()
TMTC.Tx = 800
TMTC.Ty = 800
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
Screen.fill((0, 0, 0))
TMTC.draw()
pygame.display.update()
You are calling Screen.blit in the class constructor which is executed when your class is instantiated (TMTC = MTC()).
You are then setting the tx and ty after Screen.blit has already run
im not sure why im getting errors, as it was working perfectly fine before i started to add a button to my game. Ultimately my goal is to create a game menu with the options to start game which then moves onto the next screen, the level platform, and quit, which ultimately will close the window. Bonus, if i can get help on this, im thinking about also creating a sign up and login page, i already have one set up using tkinter but im not sure how to access the stored information using pygames, so it saves game progress from username and password. Also, what website do you guys use to get free images for your games? I can't draw that well and am having trouble finding images that match what im trying to accomplish.
# imports
import pygame, sys
import pygame.freetype
from pygame.sprite import Sprite
from pygame.rect import Rect
# colors
green = (0, 255, 0)
black = (0, 0, 0)
# buttons
def create_text(text, font_size, text_color, bg_color):
font = pygame.freetype.Sysfont("Courioer", font_size, bold=True)
surface, _ = font.render(text=text, fgcolor=text_color, bgcolor = bg_color)
return surface.convert_alpha()
class UIElement(Sprite):
def __init__(self, center_position, text, font_size, bg_color, text_color):
super().__init__()
self.mouse_over = False
default_image = create_text(text, font_size, text_color, bg_text)
highlighted_image = create_text(text, font_size * 1.2, text_color, bg_text)
self.images = [default_image, highlighted_image]
self.rects = [
default_image.get_rect(center = center_position),
highlighted_image.get_rect(center = center_position)]
super().__init__()
#property
def image(self):
return self.image[1] if self.mouse_over else self.image[0]
#property
def rect(self):
return self.rects[1] if self.mouse_over else self.rects[0]
def update(self, mouse_pos):
if self.rect.collidepoint(mouse_pos):
self.mouse_over = True
else:
self.mouse_over = False
def draw(self, surface):
surface.blit(self.image, self.rect)
# Title
pygame.display.set_caption("Zombrio")
icon = pygame.image.load("zombie.png")
pygame.display.set_icon(icon)
# character
survivorImg = pygame.image.load("frankenstein.png")
survivorx = 1
survivory = 400
def player():
screen.blit(survivorImg, (survivorx, survivory))
def main():
pygame.init()
# screen
screen = pygame.display.set_mode((800, 800))
clock = pygame.time.Clock()
uielement = UIElement(
center_position = (400, 400),
font_size = 30,
bg_color = black,
text_color = green,
text = "Start"
)
# Game Loop
while True:
screen.fill(black) # not defined error, only occurred after creating buttons
for event in pygame.event.get(): # video system not initialized
if event.type == pygame.QUIT: # indent error
pygame.quit()
sys.exit()
uielement.update(pygame.mouse.get_pos()) # says uielement is not defined
uielement.draw(screen)
pygame.display.flip()
player()
pygame.display.update()
clock.tick(120)
main()
pygame.quit()
So """Text""" is a string literal. You can use it for multi-line strings.
https://developers.google.com/edu/python/strings#:~:text=String%20literals%20inside%20triple%20quotes,go%20to%20represent%20computed%20values.
You can also use it to create a docstring.
The way you are using it here does not look correct. If you want to print those statements, then trying print("""Text""") on the next line.
If you want to use it as a comment on a line of code, then follow it with the "#"
For more examples of using tripple quotes, see here: https://www.geeksforgeeks.org/triple-quotes-in-python/
I am trying to understand the tilemaps in pygame, and to learn how to use Tiled Map Editor, but I can't succeed to load the map in the pygame.
Here is the code:
import pygame
import pytmx
pygame.init()
display = pygame.display.set_mode((600,400))
clock = pygame.time.Clock()
gameMap = pytmx.TiledMap("map.tmx")
while(True):
clock.tick(60)
keys = pygame.key.get_pressed()
for event in pygame.event.get():
if(event.type == pygame.QUIT):
quit()
if(keys[pygame.K_ESCAPE]):
quit()
for layer in gameMap.visible_layers:
for x, y, gid, in layer:
tile = gameMap.get_tile_image_by_gid(gid)
if(tile != None):
display.blit(tile, (x * gameMap.tilewidth, y * gameMap.tileheight))
pygame.display.update()
It keep giving me this error:
Traceback (most recent call last):
File "main.py", line 27, in
display.blit(tile, (x * gameMap.tilewidth, y * gameMap.tileheight))
TypeError: argument 1 must be pygame.Surface, not tuple
I know that when I print the tile in console this is what I get
(a tuple):
('img/NES - Super Mario Bros - Tileset.png', (0, 144, 16, 16), TileFlags(flipped_horizontally=False, flipped_vertically=False, flipped_diagonally=False)).
What is the simplest method to successfully load a tilemap in pygame and what am I doing wrong?
use:
gameMap = pytmx.load_pygame("map.tmx")
instead of:
gameMap = pytmx.TiledMap("map.tmx")
I think that the following covers most of the mechanics of rendering the mapSurface and drawing something on it with update and loadMap. I don't have any real TMX files to test with. ymmv. Good luck.
import time
import pygame
import pytmx
class TiledMap():
""" This is creating the surface on which you make the draw updates """
def __init__(self):
self.gameMap = pytmx.load_pygame("map.tmx", pixelalpha=True)
self.mapwidth = self.gameMap.tilewidth * self.gameMap.width
self.mapheight = self.gameMap.tileheight * self.gameMap.height
def render(self, surface):
for layer in self.gameMap.visible_layers:
if isinstance(layer, pytmx.TiledTileLayer):
for x, y, gid in layer:
tile = self.gameMap.get_tile_image_by_gid(gid)
if tile:
surface.blit(tile, (x * self.gameMap.tilewidth, y * self.gameMap.tileheight))
def make_map(self):
mapSurface = pygame.Surface((self.mapwidth, self.mapheight))
self.render(mapSurface)
return mapSurface
pygame.init()
class Display():
""" This is the class that makes the changes that you want to display. You would add most of your changes here. """
def __init__(self):
self.displayRunning = True
self.displayWindow = pygame.display.set_mode((600, 400))
self.clock = pygame.time.Clock()
def update(self):
pygame.display.set_caption("{:.2f}".format(self.clock.get_fps()))
pygame.display.update()
def loadMap(self):
self.map = TiledMap()
self.map_img = self.map.make_map()
self.map_rect = self.map_img.get_rect()
def displayLoop(self):
self.clock.tick()
self.update()
self.loadMap()
# Here is the start of the main driver
runDisplay = Display()
runDisplay.update()
runDisplay.loadMap()
time.sleep(60)
If you want it to run in a loop then you would change that bottom driver block to something like:
runDisplay = Display()
while runDisplay.displayRunning is True:
runDisplay.displayLoop()
Now below what i did is simply created a sprite as shown..
futher to do something interesting,thought of threading i added a thread which will check the cursor position, hence update global x & y resulting in change of sprite position that is trigered by display.update
I am newbie so i might me wrong in many ways ...so please bear me....
a lot thanks in advance
from pygame import *
from main import *
import threading
import sys
#lets add our sprites
(x,y) = (0, 0)
class threading1(threading.Thread):
def run(self):
global x,y
clockobj1 = pygame.time.Clock()
while (True):
clockobj1.tick(6)
(x,y)=pygame.mouse.get_pos()
display.update()
class sprites(pygame.sprite.Sprite ):
def __init__(self,color= redd, width=120, height=120):
super(sprites,self).__init__()
self.image = pygame.Surface((width,height))
self.image.fill(color)
self.rect=self.image.get_rect()
self.rect.move_ip(x,y)
display.update()
if __name__ == '__main__':
clockobj = pygame.time.Clock()
init()
mainwin = pygame.display.set_mode((720,640))
sprite1 = sprites()
spritegrp = pygame.sprite.Group()
spritegrp.add(sprite1)
spritegrp.update()
mainwin.fill(blue)
spritegrp.draw(mainwin)
threadingobj = threading1()
threadingobj.start()
x = True
while(x):
display.update()
for evt in event.get() :
if (evt.type == QUIT) :
quit()
x=False
clockobj.tick(40)
***BELOW IS MY LATEST CODE----------UPDATED AS PER ANSWERS***PLEASE CHECK
import pygame
from main import *
import threading
import sys
# lets add our sprites
class Sprites(pygame.sprite.Sprite ):
def __init__(self, color=redd, width=120, height=120):
super().__init__()
self.image = pygame.Surface((width, height))
self.image.fill(color)
self.rect = self.image.get_rect()
def updaterect(self):
print("i m in updatereact")
print(pygame.mouse.get_pos())
self.rect.center= pygame.mouse.get_pos()
pygame.display.update()
if __name__ == '__main__':
clockobj = pygame.time.Clock()
pygame.init()
mainwin = pygame.display.set_mode((720,640))
sprite1 = Sprites()
sprite1.updaterect()
spritegrp = pygame.sprite.Group()
spritegrp.add(sprite1)
spritegrp.update()
mainwin.fill(blue)
spritegrp.draw(mainwin)
x = True
while x:
sprite1.updaterect()
pygame.display.update()
for evt in pygame.event.get() :
if evt.type == pygame.QUIT :
quit()
x=False
Threading will only just complicate things. Get rid of it, and take self.rect.move_ip(x,y) and display.update() out of the __init__ for the class. Make a function in the class called update(). This function will move the rect just by saying. self.rect.center = pygame.mouse.get_pos(). Then in the main game loop, put sprite1.update() in there or update it by using the group name instead (as you did with spritegrp.update() ) and then call display.update() there too instead of in the function.
Other things:
super().__init__() doesn't need any args
if and while loops don't need parentheses
you don't need to import main (I may be wrong about this but I don't think so)
from module import * is a bad practice in general, but if you are going to do it (I don't recommend it), you can't put module.method anywhere. You did from pygame import *, but still put pygame.mouse and others like that. Maybe you meant from pygame.locals import * ?
colons don't have a space in between them and the word, i.e. for evt in event.get() : is bad
Indentation should also be the length of a tab, or four spaces. (What IDE are you using? Most do it automatically.)
variables assignments should have spaces: x = False
I have extended pygame.Rect with my Ball class. When I use nstanceOfBall.colliderect() (line 66), no errors are thrown, yet it never returns true. Any insight into why colliderect isn't working for my Ball instances?
import sys, pygame
import os
import ball
import random
import math
#from ball import Ball
###############################################################################################
class Ball(pygame.Rect):
def __init__(self, x, y, width, height, screenWidth, screenHeight):
super(pygame.Rect,self).__init__(x, y, width, height)
self.floatX=x
self.floatY=x
self.screenWidth=screenWidth
self.screenHeight=screenHeight
self.speed=[random.random()*5-2.5, random.random()*5-2.5]
def runLogic(self):
self.floatX+=self.speed[0]
self.floatY+=self.speed[1]
if self.floatX+16<0: self.floatX=self.screenWidth
if self.floatX>self.screenWidth: self.floatX=-16
if self.floatY+16<0: self.floatY=self.screenHeight
if self.floatY>self.screenHeight: self.floatY=-16
self.x=self.floatX
self.y=self.floatY
###############################################################################################
os.environ['SDL_VIDEO_WINDOW_POS'] = "%d,%d" % (700, 200)#1680,1440)
pygame.init()
size = width, height = 320, 240
white = 255, 255, 255
blue=0,0,255
screen = pygame.display.set_mode(size)
image = pygame.image.load("ball.png")
ballRect=image.get_rect()
balls = []
for x in range(0, 100):
balls.append(Ball(random.random()*width, random.random()*height, ballRect.width, ballRect.height, width, height))
lastFrameStartTime=pygame.time.get_ticks()
while 1:
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
sys.exit()
for ball in balls:
ball.runLogic()
for ball2 in balls:
if ball != ball2:
if ball.colliderect(ball2):
print("collision detected!")
balls.pop(balls.index(ball))
balls.pop(balls.index(ball2))
#balls.remove(ball2)
screen.fill(blue)
for ball in balls:
screen.blit(image, ball)
pygame.display.flip()
pygame.time.wait(33-(pygame.time.get_ticks()-lastFrameStartTime))
lastFrameStartTime=pygame.time.get_ticks()
Using super(Ball, self) instead of super(pygame.Rect, self) in Ball.init did the trick.
Thank you.
The first arument to super must be the current class, i.e. Ball instead of pygame.Rect:
class Ball(pygame.Rect):
def __init__(self, x, y, width, height, screenWidth, screenHeight):
super(Ball, self).__init__(x, y, width, height)
...
There is an example in the documentation on super.
The point of super is that it allows you to call the next method in the inheritance order without requiring you to refer to the parent class explicitly. This comes handy when using multiple inheritance, see e.g. super confusing python multiple inheritance super()