It works perfectly if I do not add it in a class, but if I do it does not respond, I have tried using pygame.update, as pygame.event.pump/get and even jumbling were event should start from, still the problem persists. What am I doing wrong?Code below
.
.
class start_game:
def __init__(self,path,width = 400,height = 600):
self.width = width
self.height = height
self.head = None
self.running = False
self.path = path
pygame.init()
pygame.mixer.init()
self.background = load_img(self.path + '\AnimatedStreet.png')
self.enemy = pygame.image.load(self.path + '\Enemy.png')
self.backg0_pos = [0,0]
self.screen = pygame.display.set_mode((self.width,self.height))
def _run(self):
self.running = True
while self.running:
#pygame.event.pump()
self.screen.fill([0,0,0])
self.screen.blit(self.background, self.backg0_pos)
pygame.display.flip()
pygame.display.update()
self.backg0_pos[1] += 1
self._init_controls()
return
def _init_controls(self):
for event in pygame.event.get():
if event.type == KEYDOWN:
if event.key == K_RIGHT:
self.player_pos[0] += 5
if event.key == K_q:
pygame.quit()
return
a = start_game(path)
a._run()
The error was the return function put inside of the while loop caused it stop.
The solution was putting the return function inside of the run function.
Related
I wanted to make a simple dance game using pygame.
class Sword():
def __init__(self, image, speed, center):
self.image = pygame.image.load(image)
self.rect = self.image.get_rect()
self.rect.center = center
self.speed = speed # object speed
self.alive = True # draw object if not hit the enemey
def live(self, enemy): # check if hit the enemy
if self.rect.colliderect(enemy):
self.alive = False
mixer.music.play()
def update(self): # move object
self.rect.x += self.speed
def draw(self, surface): # draw object
if self.alive:
surface.blit(self.image, (self.rect))
I can draw and move my object on the screen.
sword = [Sword('sword.png',1,(100,420))],
[Sword('sword.png',5,(200,420))],
[Sword('sword.png',3,(300,420))]]
while (True):#Mainloop
kare = pygame.draw.rect(display,((255,0,0)), pygame.Rect(700,420,100,100))
for i, tile in sorted(enumerate(sword), reverse=True):
tile.update()
tile.live(kare)
tile.draw()
if not tile.live:
sword.pop(i)#delete object
my code works flawlessly so far;=)
but when I want to draw 4 objects on the screen every time, things don't go as I want.
def main():
extend = []
running = True
while running:
if len(extend) >= 3:
running = False
else:
for i in range(4):
extend.append(Sword('sword.png',1,(100,420)))
return extend
i have a simple function to draw 4 objects at a time to the screen but when i use this in my main loop my objects don't move
while True:
sword = main()#call function
kare = pygame.draw.rect(display,((255,0,0)), pygame.Rect(700,420,100,100))
for i, tile in sorted(enumerate(sword), reverse=True):
tile.update()
tile.live(kare)
tile.draw(display)
if not tile.alive:
sword.pop(i)
First of all, I apologize for this long post, but I wanted the topic to be clear, how do I edit my code so that there are 4 on the screen each time?
Thank you for your interest...
Here is the full code of the solution:
import pygame, sys, math, random
from pygame import mixer
from pygame.locals import *
mainClock = pygame.time.Clock()
pygame.init()
pygame.display.set_caption('game base')
WINDOW_SIZE = (980,570)
screen = pygame.display.set_mode((WINDOW_SIZE), 0, 32)
display = pygame.Surface((WINDOW_SIZE))
RIGHT_KEY,UP_KEY,LEFT_KEY,DOWN_KEY = False,False,False,False
class Sword():
def __init__(self, image, speed, center):
self.image = pygame.image.load(image)
self.rect = self.image.get_rect()
self.rect.center = center
self.speed = speed
self.alive = True
def live(self, enemy):
if self.rect.colliderect(enemy):
self.alive = False
#mixer.music.play()
def update(self):
self.rect.x += self.speed
def draw(self, surface):
if self.alive:
surface.blit(self.image, (self.rect))
def main():
extend = []
running = True
if len(extend) >= 3:
running = False
while running:
if len(extend) >= 4:
running = False
else:
for i in range(5):
extend.append(Sword('sword.png',i,(100,420)))
return extend
sword = main()
while True:
display.fill((250,198,14))
kare = pygame.draw.rect(display,((255,0,0)), pygame.Rect(700,420,100,100))
all_not_alive = True
for tile in sword:
tile.update()
tile.live(kare)
tile.draw(display)
if not tile.alive:
tile.rect.x = 100
tile.alive = True
# Buttons ------------------------------------------------ #
RIGHT_KEY,UP_KEY,LEFT_KEY,DOWN_KEY = False,False,False,False
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
pygame.quit()
sys.exit()
if event.key == pygame.K_UP:
UP_KEY = True
if event.key == pygame.K_DOWN:
DOWN_KEY = True
if event.key == pygame.K_LEFT:
LEFT_KEY = True
if event.key == pygame.K_RIGHT:
RIGHT_KEY = True
# Update -------------------------------------------------
screen.blit(display,(0,0))
pygame.display.update()
mainClock.tick(60)
The problem was that you have recreated all swords every time when the game updated. You should recreate the sword only if it is not alive.
EDIT
I have moved the code which generates the Swords out of the loop:
sword = main()
and I am moving all swords to the start after they collide:
if not tile.alive:
tile.rect.x = 100
tile.alive = True
I was following this tutorial on how to make a typing speed calculator using pygame and whenever I run the code everything renders out as it should but when I try clicking on the text field to input some text it just freezes and nothing happens. I tried to search online or watch tutorials but everything came up empty.
import sys
import time
import random
import pygame
from pygame.locals import *
"""Python Script for a typing speed test game"""
class Game(object):
def __init__(self):
self.h = 720
self.w = 1280
self.reset = True
self.active = False
self.word = ""
self.input_text = ""
self.time_start = 0
self.total_time = 0
self.accuracy = "0%"
self.wpm = 0
self.results = "Speed(WPM):0 Accuracy:0% Time:0"
self.end = False
self.head_col = (255,213,102)
self.text_col = (255,255,255)
self.result_color = (53,209,29)
pygame.init()
self.open_image = pygame.image.load("splash.jpg")
self.open_image = pygame.transform.scale(self.open_image, (self.w,self.h))
self.background = pygame.image.load("background.jpg")
self.background = pygame.transform.scale(self.background, (self.w, self.h))
self.screen = pygame.display.set_mode((self.w,self.h))
pygame.display.set_caption = "Type Speed Test"
def draw_text(self, screen, msg, y, fsize, color):
font = pygame.font.SysFont("consolas", fsize)
text = font.render(msg, 1, color)
text_rect = text.get_rect(center=(self.w/2, y))
screen.blit(text, text_rect)
pygame.display.update()
def get_sentences(self):
f = open("sentences.txt").read()
sentence = f.split("\n")
sentences = random.choice(sentence)
return sentences
def show_results(self, screen):
if(not self.end):
#Calculate Time
self.total_time = time.Time() - self.time_start
#Calcualte Accuracy
count = 0
for i,c in enumarate(self.word):
try:
if self.input_text[i] == c:
count += 1
except:
pass
self.accuracy = count/len(self.word)*100
#Calculate wpm
self.wpm = len(self.input_text)*60/(5*self.total_time)
self.end = True
print(self.total_time)
self.results = "Time:" + str(round(self.total_time))
+ " secs Accuracy: " + str(round(self.accuracy)) + "%"
+ " WPM: " + str(round(self.wpm))
#restart icon
self.time_img = pygame.image.load("icon.png")
self.time_img = pygame.transform.scale(self.time_img, (80,320))
#screen.blit(self.time_img, (80,320))
screen.blit(self.time_img, (self.w/2-75, self.h-140))
self.draw_text(screen, "Reset", self/h - 70, 26, (100,100,100))
print(self.results)
pygame.display.update()
def run(self):
self.reset_game()
self.running=True
while(self.running):
clock = pygame.time.Clock()
self.screen.fill((0,0,0), (50,250,650,50))
pygame.draw.rect(self.screen,self.head_col, (50,250,650,50), 2)
# update the text of user input
self.draw_text(self.screen, self.input_text, 274, 26,(250,250,250))
pygame.display.update()
for event in pygame.event.get():
if event.type == QUIT:
self.running = False
sys.exit()
elif event.type == pygame.MOUSEBUTTONUP:
x,y = pygame.mouse.get_pos()
# position of input box
if(x>=50 and x<=650 and y>=250 and y<=300):
self.active = True
self.input_text = ''
self.time_start = time.time()
# position of reset box
if(x>=310 and x<=510 and y>=390 and self.end):
self.reset_game()
x,y = pygame.mouse.get_pos()
elif event.type == pygame.KEYDOWN:
if self.active and not self.end:
if event.key == pygame.K_RETURN:
print(self.input_text)
self.show_results(self.screen)
print(self.results)
self.draw_text(self.screen, self.results,350, 28, self.RESULT_C)
self.end = True
elif event.key == pygame.K_BACKSPACE:
self.input_text = self.input_text[:-1]
else:
try:
self.input_text += event.unicode
except:
pass
pygame.display.update()
clock.tick(60)
def reset_game(self):
self.screen.blit(self.open_image, (0,0))
pygame.display.update()
time.sleep(1)
self.reset=False
self.end = False
self.input_text=''
self.word = ''
self.time_start = 0
self.total_time = 0
self.wpm = 0
# Get random sentence
self.word = self.get_sentences()
if (not self.word): self.reset_game()
#drawing heading
self.screen.fill((0,0,0))
self.screen.blit(self.background,(0,0))
msg = "Typing Speed Test"
self.draw_text(self.screen, msg,80, 80,self.head_col)
# draw the rectangle for input box
pygame.draw.rect(self.screen,(255,192,25), (50,250,650,50), 2)
# draw the sentence string
self.draw_text(self.screen, self.word,200, 28,self.text_col)
pygame.display.update()
Game().run()
How can this be fixed?
Your never handeling KEYDOWN Events. because the else if statement is indented to far.
You should change the following.
class Game(object):
...
def run(self):
...
while(self.running):
...
for event in pygame.event.get():
if event.type == QUIT:
...
elif event.type == pygame.MOUSEBUTTONUP:
...
elif event.type == pygame.KEYDOWN:
...
in to this:
class Game(object):
...
def run(self):
...
while(self.running):
...
for event in pygame.event.get():
if event.type == QUIT:
...
elif event.type == pygame.MOUSEBUTTONUP:
...
elif event.type == pygame.KEYDOWN:
...
In Game.reset_game you recusively call Game.reset_game() with no exit.
Remove the call to self.reset_game so the game can be reset.
You also sleep for 1 second in reset_game without listening to events. This will make the pygame window seem inresponsive.
And it lets the process take 1000 seconds or ~ 17 minutes before the RecursionError is triggerd from recursively calling reset_game. Rather then seconds.
After I paint my surface black in pygame. I get the error
pygame.error: display Surface quit.
Full error:
>
D:\Programme\Anaconda3\envs\gameDev\python.exe "C:/Users/xxx/PycharmProjects/Workspace/pygame snake/main.py"
pygame 1.9.6
Hello from the pygame community. https://www.pygame.org/contribute.html
Traceback (most recent call last):
File "C:/Users/xxx/PycharmProjects/Workspace/pygame snake/main.py", line 81, in <module>
thegame.execute()
File "C:/Users/xxx/PycharmProjects/Workspace/pygame snake/main.py", line 74, in execute
self.render(self._display_surf)
File "C:/Users/xxx/PycharmProjects/Workspace/pygame snake/main.py", line 41, in render
_display_surf.fill((0,0,0))
pygame.error: display Surface quit
<Surface(Dead Display)>
I tried instead of:
_display_surf.fill((0,0,0))
using:
_display_surf.fill(pygame.color("black"))
But that didnt work either.
Here is my full source code:
import pygame
from pygame.locals import *
class Player(object):
x = 10
y = 10
speed = 1
def moveRight(self):
self.x = self.x + self.speed
def moveLeft(self):
self.x = self.x - self.speed
def moveUp(self):
self.y = self.y - self.speed
def moveDown(self):
self.y = self.y + self.speed
class game:
def __init__(self):
self.resolution = (800, 500)
self._running = True
self._display_surf = None
self.player = Player()
def on_init(self):
pygame.init()
self._display_surf = pygame.display.set_mode(self.resolution)
pygame.display.set_caption("Snake!")
self._running = True
def on_cleanup(self):
pygame.quit()
def render(self, _display_surf):
print(_display_surf)
_display_surf.fill((0,0,0))
pygame.draw.rect(self._display_surf, (0, 128, 255), pygame.Rect(self.player.x, self.player.y, 30, 30))
pygame.display.flip()
def loop(self):
pass
def on_event(self, event):
if event.type == pygame.quit():
print("quiet")
self._running = False
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_RIGHT:
self.player.moveRight()
elif event.key == pygame.K_LEFT:
self.player.moveLeft()
elif event.key == pygame.K_UP:
self.player.moveUp()
elif event.key == pygame.K_DOWN:
self.player.moveDown()
def execute(self):
if self.on_init() == False:
self._running = False
while self._running:
for event in pygame.event.get():
self.on_event(event)
self.render(self._display_surf)
self.loop()
self.on_cleanup()
if __name__ == "__main__":
thegame = game()
thegame.execute()
I expect that I have a black surface and nothing happens. But instead, it crashes when I try to paint it black. Hope somebody can help
Solution:
For anybody who is intrested in
instead of
if event.type == pygame.quit():
print("quiet")
self._running = False
i need to to
if event.type == pygame.QUIT:
print("quiet")
self._running = False
The code
if event.type == pygame.quit():
print("quiet")
doesn't do what you expect it to do. pygame.quit() is a function call and uninitializes all pygame modules. The function returns None and so the condition fails. The code runs through and crashes at the next instruction which tries to access a pygame module.
You've to compare event.type to the event enumerator constant pygame.QUIT, which identifies the quit event instead:
if event.type == pygame.QUIT:
print("quiet")
self._running = False
See the documentation of pygame.event.
I'm trying to make a character move across the screen from the top to the bottom, where it will disappear. However, the code I have doesn't return any errors, but it won't move the character either. Here is my code:
import pygame
import sys
import random
pygame.init()
width , height = 600 , 500
display = pygame.display.set_mode((width, height ) )
pygame.display.set_caption("Class Test")
primoimage = pygame.image.load("/home/pi/Downloads/PRIMO/primo_0.png").convert()
class Enemy:
def __init__(self, name, shoot, speed, image):
self.name = name
self.shoot = shoot
self.speed = speed
self.image = image
def move(self):
enemyRack = []
if len(enemyRack) == 0:
enemyRack.append([width/2, 0])
for enemy in enemyRack:
display.blit(self.image, pygame.Rect(enemy[0], enemy[1], 0,0))
for e in range(len(enemyRack)):
enemyRack[e][1]+=2
for enemy in enemyRack:
if enemy[1] > height:
enemyRack.remove(enemy)
primo = Enemy("primo", 2, False, primoimage)
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
pass
primo.move()
pygame.display.update()
pygame.quit()
sys.exit()
The problem is in the move() function.
If you could figure it out that would be great! Thanks.
I added some indentation so things work again. (I'm assuming you just broke the indentation when posting your code). Your error was re-initializing enemyRack = [] every time move is called. That way you'll always have [300, 0] in the enemyRack.
import pygame
import sys
import random
pygame.init()
width , height = 600 , 500
display = pygame.display.set_mode((width, height ) )
pygame.display.set_caption("Class Test")
primoimage = pygame.image.load("player.png").convert()
class Enemy:
def __init__(self, name, shoot, speed, image):
self.name = name
self.shoot = shoot
self.speed = speed
self.image = image
self.enemyRack = [] # let's make this a class variable so we don't lose the contents
def move(self):
if len(self.enemyRack) == 0:
self.enemyRack.append([width/2, 0])
for enemy in self.enemyRack:
display.blit(self.image, pygame.Rect(enemy[0], enemy[1], 0,0))
for e in range(len(self.enemyRack)):
self.enemyRack[e][1]+=2
for enemy in self.enemyRack:
if enemy[1] > height:
self.enemyRack.remove(enemy)
primo = Enemy("primo", 2, False, primoimage)
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
pass
primo.move()
pygame.display.update()
pygame.quit()
sys.exit()
The following code gives me this error and I am confused. Sorry If I am asking questions wrong, I'm new here but I think this corresponds to the guidelines. The image will move
across the background as soon as I release the key it gives me this error and crashes.
Traceback (most recent call last):
File "C:\Users\Samga_000\Desktop\game\game.py", line 89, in <module>
rungame()
File "C:\Users\Samga_000\Desktop\game\game.py", line 79, in rungame
p.still()
TypeError: 'int' object is not callable
import pygame, sys
from pygame.locals import *
pygame.init()
WIDTH = 400
HEIGHT = 400
screen = pygame.display.set_mode((WIDTH, HEIGHT))
bif = "grass.png"
background = pygame.image.load(bif)
pygame.display.set_caption('RPG')
def drawEntitys():
frispri.update()
frispri.draw(screen)
def drawScreen():
screen.blit(background, (0,0))
class Player(pygame.sprite.Sprite):
image = pygame.image.load("misha.png")
image = image.convert_alpha()
def __init__(self):
pygame.sprite.Sprite.__init__(self, self.groups)
self.pos = (20, 20)
self.image = Player.image
self.rect = self.image.get_rect()
self.movepos = [0,0]
self.area = screen.get_rect()
self.still = True
def update(self):
newpos = self.rect.move(self.movepos)
if self.area.contains(newpos):
self.rect = newpos
pygame.event.pump()
def move(self, x, y):
self.still = 0
if self.still == 0:
self.movepos[0] = self.movepos[0] - x
self.movepos[1] = self.movepos[1] - y
else:
pass
def still(self):
self.still = 1
frispri = pygame.sprite.Group()
Player.groups = frispri
p = Player()
def rungame():
while True:
drawScreen()
drawEntitys()
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
elif event.type == KEYDOWN:
if event.key == K_UP:
p.move(0,1)
elif event.key == K_DOWN:
p.move(0,-1)
elif event.key == K_LEFT:
p.move(1,0)
elif event.key == K_RIGHT:
p.move(-1,0)
elif event.type == KEYUP:
if event.key == K_UP:
p.still()
elif event.key == K_DOWN:
p.still()
elif event.key == K_LEFT:
p.still()
elif event.key == K_RIGHT:
p.still()
flipgame()
def flipgame():
pygame.display.flip()
rungame()
Player.still is a boolean, assigned here:
class Player(pygame.sprite.Sprite):
def __init__(self):
# ...
self.still = True
You can't call a boolean, since it isn't a function, as you attempt here:
p = Player()
# ...
p.still()
This is essentially the same problem as discussed in this question
Your problem is that you have an instance variable, still, with the same name as your method. When you do p.still(), Python interprets the p.still as trying to access the variable not the method, and then trying to 'call' that variable.
The solution is to rename the method or the variable. To get your code to work you should only need to change one of the two. But good programming practice might say you should change both.
Since the variable is a flag that indicates if the player is still or not, you might change it's name to be is_still. This is a slightly more descriptive name, that makes it clear what the variable means.
For the method you could rename it to set_still or mark_still to indicate that it is changing the status of the player. Or combined with the above change to the variable name you could make the method name set_is_still, to make it clear exactly what variable you are setting.