pygame add object with mouse click - python

Trying to add more boids by using mouse click ingame.
elif event.type == pygame.MOUSEBUTTONUP:
self.boids_group.add(boids.Boids(rect=pygame.Rect(random()*self.width, random()*self.height, 40, 40)))
I get an error msg that there is no object Boids in Boids, however this is the method i am adding boids to the game at start.
self.boids_group = pygame.sprite.Group()
for i in range(cfg.boidNum):
self.boids_group.add(boids.Boids(rect=pygame.Rect(random()*self.width, random()*self.height, 40, 40)))
And the cfg.boidNum is set to 19 at start, and its adding 19 boids, but not adding more when i push the mousebutton.
If anyone can guide me in the right direction....

The error msg i get when i try running is: line 69, there is no object Boids in Boids, line 69 ref to the mouse input line.
#!/usr/bin/env python
from random import random
from pygame.locals import *
import boids, predator, diver, pygame, sys
import config as cfg
bgimage = pygame.image.load("ramfjord.png")
class Ramfjorden:
def __init__(self, width=1024, height=760):
pygame.init()
self.width = width
self.height = height
self.screen = pygame.display.set_mode((self.width, self.height))
pygame.display.set_caption('Ramfjorden')
def loadSprites(self):
self.predator_group = pygame.sprite.Group()
for i in range(cfg.predatorNum):
self.predator_group.add(predator.Predator(rect=pygame.Rect(random()*self.width, random()*self.height, 70, 70)))
self.boids_group = pygame.sprite.Group()
for i in range(cfg.boidNum):
self.boids_group.add(boids.Boids(rect=pygame.Rect(random()*self.width, random()*self.height, 40, 40)))
self.diver_group = pygame.sprite.Group()
self.diver_group.add(diver.Diver(rect=pygame.Rect(300, 300, 150, 231)))
def collision(self, sprite1, sprite2):
if sprite1 == sprite2:
return False
else:
return pygame.sprite.collide_circle(sprite1, sprite2)
def mainLoop(self):
fps = pygame.time.Clock()
self.loadSprites()
while True:
self.screen.blit(bgimage, (0,0))
self.predator_group.draw(self.screen)
self.boids_group.draw(self.screen)
self.diver_group.draw(self.screen)
for predator in self.predator_group.sprites():
predator.update(ramfjord=self)
for boids in self.boids_group.sprites():
boids.update(ramfjord=self)
for predator in self.predator_group.sprites():
predator.swim(ramfjord=self)
for boids in self.boids_group.sprites():
boids.swim(ramfjord=self)
spriteHitList = pygame.sprite.groupcollide(self.predator_group, self.boids_group, False, True, collided=self.collision)
for event in pygame.event.get():
if event.type == pygame.QUIT:
exit()
sys.exit()
elif event.type == KEYDOWN:
if event.key == K_ESCAPE:
pygame.event.post(pygame.event.Event(QUIT))
elif event.type == pygame.MOUSEBUTTONUP:
self.boids_group.add(boids.Boids(rect=pygame.Rect(random()*self.width, random()*self.height, 40, 40)))
pygame.display.update()
fps.tick(30)
def main():
ramfjord = Ramfjorden()
ramfjord.mainLoop()
if __name__ == "__main__":
main()

Related

Problem when using keyboard commands in pygame

While doing some game programming, I ran into a problem with the keyboard commands. In my code, I have a food bar and a money bank variable named money_bar. The food bar in my game would increase when I press a key, say f, in my game, and also the game deduct say $10 from my money_bar when I press f.
The food bar shows the current amount of food I have, which is supposed to decrease every second. However, it appears that none of my keyboard commands in the event() are working. May I know what is the problem in my code?
This is my food_bar and `money_bar initialisation:
def __init__(self):
pygame.init()
self.clock = pygame.time.Clock()
self.living = 1
self.screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption(TITLE)
self.time = pygame.time.get_ticks()
pygame.key.set_repeat(500, 100)
self.all_sprites = pygame.sprite.Group()
self.console = Console(self, 0)
self.player = Player(self, 390, 595)
self.work = Work(self, 450, 250)
self.food_station = Food_Station(self, 750, 200)
self.food = Food(self, 25, 20)
self.education = Education(self, 300, 10)
self.school = School(self, 100, 200)
self.family = Family(self, 600, 10)
self.money = Money(self, 800, 15)
initial_food = 100
self.food_bar = initial_food
initial_money = 0
self.money_bar = initial_money
initial_education = "Student"
self.education_level = initial_education
initial_family = 3
self.family_member = 3
This is where i run the main algorithm:
def run(self):
self.playing = True
self.hunger()
while self.playing:
self.dt = self.clock.tick(FPS) / 1000
self.events()
self.draw()
self.update()
and here's how i check for events(including keyboard commands)
def events(self):
for event in pygame.event.get():
if event.type == pygame.QUIT:
self.quit()
if event.type == self.HUNGEREVENT:
self.food_bar = self.food_bar - 10
self.all_sprites.update()
pygame.display.flip()
if event.type == pygame.K_f:
self.money_bar = self.money_bar - 10
self.food_bar = self.food_bar + 15
self.all_sprites.update()
pygame.display.flip()
if event.type == pygame.K_ESCAPE:
self.quit()
Thanks in advance
While pygame.K_f is a key enumerator constant (see pygame.key) the content of event.type is event enumerator constant (see pygame.event).
If you want to determine if a certain key is pressed, the you've to verify if the event type is pygame.KEYDOWN (or pygame.KEYUP for button release) and if the .key attribute of the event is equal the key enumerator. e.g.:
for event in pygame.event.get():
if event.type == pygame.QUIT:
self.quit()
# [...]
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_f:
# [...]

pygame.error: display Surface quit after filling the surface black

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.

Enemy Object wont move in Pygame

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()

Insert score in a button game function

I have this code for a button that is pressable:
def button(msg,xloc,yloc,xlong,ylong,b1,b2,action=None):
hover = pygame.mouse.get_pos()
click = pygame.mouse.get_pressed()
if xloc < hover [0] < xloc+xlong and yloc< hover [1] < yloc+ylong:
pygame.draw.rect(display, b1, (xloc ,yloc ,xlong,ylong))
if click [0]==1 and action != None:
action()
else:
pygame.draw.rect(gameDisplay, inactiveButton, (xloc ,yloc ,xlong,ylong))
label = pygame.font.SysFont("arial",16)
textSurf, textBox = textMsg(msg, label)
textBox.center = ((xloc +(300)),((yloc +(150))
gameDisplay.blit(textSurf,textBox)
and the code for the scoring is:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
if event.type == pygame.MOUSEBUTTONDOWN:
score+=1
print (score)
I would like have a score that – upon pressing the correct button in the choices in order to answer in a quiz game – will be displayed and incremented by 1. How can I do that?
Here's the simplest way to implement a button that I know. Create a rect for the button and draw it with pygame.draw.rect (or blit an image). For the collision detection, check if the event.pos of a pygame.MOUSEBUTTONDOWN event collides with the rect and then just increment the score variable.
import pygame as pg
pg.init()
screen = pg.display.set_mode((640, 480))
GRAY = pg.Color('gray15')
BLUE = pg.Color('dodgerblue1')
def main():
clock = pg.time.Clock()
font = pg.font.Font(None, 30)
button_rect = pg.Rect(200, 200, 50, 30)
score = 0
done = False
while not done:
for event in pg.event.get():
if event.type == pg.QUIT:
done = True
if event.type == pg.MOUSEBUTTONDOWN:
if event.button == 1:
if button_rect.collidepoint(event.pos):
print('Button pressed.')
score += 1
screen.fill(GRAY)
pg.draw.rect(screen, BLUE, button_rect)
txt = font.render(str(score), True, BLUE)
screen.blit(txt, (260, 206))
pg.display.flip()
clock.tick(30)
if __name__ == '__main__':
main()
pg.quit()
Addendum: Actually, I would implement a button with the help of classes, sprites and sprite groups. If you don't know how classes and sprites work, I'd recommend to check out Program Arcade Games (chapter 12 and 13).
import pygame as pg
pg.init()
GRAY= pg.Color('gray12')
BLUE = pg.Color('dodgerblue1')
FONT = pg.font.Font(None, 30)
# The Button is a pygame sprite, that means we can add the
# instances to a sprite group and then update and render them
# by calling `sprite_group.update()` and `sprite_group.draw(screen)`.
class Button(pg.sprite.Sprite):
def __init__(self, pos, callback):
pg.sprite.Sprite.__init__(self)
self.image = pg.Surface((50, 30))
self.image.fill(BLUE)
self.rect = self.image.get_rect(topleft=pos)
self.callback = callback
def handle_event(self, event):
"""Handle events that get passed from the event loop."""
if event.type == pg.MOUSEBUTTONDOWN:
if self.rect.collidepoint(event.pos):
print('Button pressed.')
# Call the function that we passed during the
# instantiation. (In this case just `increase_x`.)
self.callback()
class Game:
def __init__(self):
self.screen = pg.display.set_mode((800, 600))
self.clock = pg.time.Clock()
self.x = 0
self.button = Button((200, 200), callback=self.increase_x)
self.buttons = pg.sprite.Group(self.button)
self.done = False
# A callback function that we pass to the button instance.
# It gets called if a collision in the handle_event method
# is detected.
def increase_x(self):
"""Increase self.x if button is pressed."""
self.x += 1
def run(self):
while not self.done:
self.handle_events()
self.run_logic()
self.draw()
self.clock.tick(30)
def handle_events(self):
for event in pg.event.get():
if event.type == pg.QUIT:
self.done = True
for button in self.buttons:
button.handle_event(event)
def run_logic(self):
self.buttons.update()
def draw(self):
self.screen.fill(GRAY)
self.buttons.draw(self.screen)
txt = FONT.render(str(self.x), True, BLUE)
self.screen.blit(txt, (260, 206))
pg.display.flip()
if __name__ == "__main__":
Game().run()
pg.quit()

How to get coordinates of image in pygame

I just started learning Pygame and I'm doing a little game (school project), where using mouse I can click on the image and drag it. There are a lot of images, so my question is how I can identify what image is chosen. Thank you!
Here are some code:
def Transformation(element):
element = pygame.transform.scale(element,(50,75))
fire = pygame.image.load("ElementIcon/fire.png").convert_alpha()
Transformation(fire)
fire.set_colorkey(BLACK)
fire_rect = fire.get_rect()
earth = pygame.image.load("ElementIcon/earth.png").convert_alpha()
Transformation(earth)
earth.set_colorkey(BLACK)
earth_rect = earth.get_rect()
while not done:
screen.fill(WHITE)
#Update the screen with drawings
screen.blit(fire,(408,450))
screen.blit(earth,(419, 350))
mouse_pos = pygame.mouse.get_pos()
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
print("User quits the game :(")
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
done = True
print("Game stopped early by user :( ")
if event.type == pygame.MOUSEBUTTONDOWN:
print mouse_pos
print fire_rect
if fire_rect.collidepoint(mouse_pos):
print "over fire"
if earth_rect.collidepoint(mouse_pos):
print "mama"
When I try to print fire_rect I get <0,0,62,75>
Have a play with this code:
import pygame
from pygame.locals import *
pygame.init()
screen = pygame.display.set_mode((600,600))
clock = pygame.time.Clock()
FPS = 60
class MovableImage(pygame.Surface):
def __init__(self, image, xpos=0, ypos=0):
self.image = image
self.xpos = xpos
self.ypos = ypos
self.width = image.get_width()
self.height = image.get_height()
self.selected = False
self.rect = pygame.Rect(xpos, ypos, image.get_width(), image.get_height())
def move(self, move):
self.xpos += move[0]
self.ypos += move[1]
self.rect = pygame.Rect(self.xpos, self.ypos, self.width, self.height)
def Transformation(element):
element = pygame.transform.scale(element,(50,75))
def init():
global ImageList
fire = pygame.Surface((50,50))
fire.fill((255,0,0))
#fire = pygame.image.load("ElementIcon/fire.png").convert_alpha()
#Transformation(fire)
#fire.set_colorkey(BLACK)
#fire_rect = fire.get_rect()
earth = pygame.Surface((50,50))
earth.fill((255,255,0))
#earth = pygame.image.load("ElementIcon/earth.png").convert_alpha()
#Transformation(earth)
#earth.set_colorkey(BLACK)
#earth_rect = earth.get_rect()
fire_obj = MovableImage(fire, 408, 450)
earth_obj = MovableImage(earth, 419,350)
ImageList =[]
ImageList.append(fire_obj)
ImageList.append(earth_obj)
def run():
global done
done = False
while not done:
check_events()
update()
clock.tick(60)
def check_events():
global done
global ImageList
mouse_pos = pygame.mouse.get_pos()
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
print("User quits the game :(")
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
done = True
print("Game stopped early by user :( ")
if event.type == pygame.MOUSEBUTTONDOWN:
for im in ImageList:
if im.rect.collidepoint(mouse_pos):
im.selected = not im.selected
if event.type == pygame.MOUSEBUTTONUP:
for im in ImageList:
if im.rect.collidepoint(mouse_pos):
im.selected = False
if event.type == pygame.MOUSEMOTION:
for im in ImageList:
if im.rect.collidepoint(mouse_pos) and im.selected:
xmv = event.rel[0]
ymv = event.rel[1]
if event.buttons[0]:
if xmv < 0:
if im.xpos > 0:
im.move((xmv,0))
elif event.rel[0] > 0:
if im.xpos < screen.get_width():
im.move((xmv,0))
elif event.rel[1] < 0:
if im.ypos > 0:
im.move((0,ymv))
elif event.rel[1] > 0:
if im.ypos < screen.get_height():
im.move((0,ymv))
def update():
global ImageList
screen.fill((255, 255, 255)) #WHITE)
#Update the screen with drawings
for im in ImageList:
screen.blit(im.image, (im.xpos, im.ypos))
pygame.display.update()
if __name__=="__main__":
init()
run()
You can get the mouse pos and the image rect and check for collision:
pos = pygame.mouse.get_pos()
if image.rect.collidepoint(pos)
# move it
If you want to move the image with the mouse you can get the relative x/y movement with pygame.mouse.get_rel() and use that to change the image location.

Categories

Resources