I'm creating a game on Pygame and faced with the problem that the objects are displayed incorrectly
I want the objects in a row but I wrote it diagonally
My game:
import pygame, controls
from gun import Gun
from pygame.sprite import Group
def run():
pygame.init()
screen = pygame.display.set_mode((700, 600))
pygame.display.set_caption('Game1')
bg_color = (0, 0, 0)
gun = Gun(screen)
bullets = Group()
inos = Group()
controls.create_army(screen, inos)
while True:
controls.events(screen, gun, bullets)
gun.update_gun()
controls.update(bg_color, screen, gun, inos, bullets)
controls.update_bullets(bullets)
controls.update_inos(inos)
run()
controls:
import pygame
import sys
from bullet import Bullet
from ino import Ino
def events(screen, gun, bullets):
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_d:
gun.mright = True
elif event.key == pygame.K_a:
gun.mleft = True
elif event.key == pygame.K_SPACE:
new_bullet = Bullet(screen, gun)
bullets.add(new_bullet)
elif event.type == pygame.KEYUP:
if event.key == pygame.K_d:
gun.mright = False
elif event.key == pygame.K_a:
gun.mleft = False
def update(bg_color, screen, gun, inos, bullets):
screen.fill(bg_color)
for bullet in bullets.sprites():
bullet.draw_bullet()
gun.output()
inos.draw(screen)
pygame.display.flip()
def update_bullets(bullets):
bullets.update()
for bullet in bullets.copy():
if bullet.rect.bottom <= 0:
bullets.remove(bullet)
def update_inos(inos):
inos.update()
def create_army(screen, inos):
ino = Ino(screen)
ino_width = ino.rect.width
number_ino_x = int((700 - 2 * ino_width) / ino_width)
ino_height = ino.rect.height
number_ino_y = int((800 - 100 - 2 * ino_height) / ino_height)
for row_number in range(number_ino_y - 1):
for ino_number in range(number_ino_x):
ino = Ino(screen)
ino.x = ino_width + (ino_width * ino_number)
ino.y = ino_height + (ino_height * ino_number)
ino.rect.x = ino.x
ino.rect.y = ino.rect.height + (ino.rect.height * row_number)
inos.add(ino)
soldiers:
import pygame
class Ino(pygame.sprite.Sprite):
def __init__(self, screen):
super(Ino, self).__init__()
self.screen = screen
self.image = pygame.image.load(r'C:\Users\ralph\Downloads\Python\Game\Image\r.soldier.png')
self.rect = self.image.get_rect()
self.rect.x = self.rect.width
self.rect.y = self.rect.height
self.x = float(self.rect.x)
self.y = float(self.rect.y)
def draw(self):
self.screen.blit(self.image, self.rect)
def update(self):
self.y += 0.05
self.rect.y = self.y
I got this result
But I need another
How can I fix this?
In my humble opinion the problem is in "controls" or "soldiers" update
The images are diagonal because you calculate the y-coordinate depending on the ino_number, so that the y-coordinate increases with increasing ino_number. The y-coordinate must be the same for all objects. Only the coordinated x must increase with the number ino_number:
def create_army(screen, inos):
# [...]
for row_number in range(number_ino_y - 1):
for ino_number in range(number_ino_x):
ino = Ino(screen)
ino.x = ino_width + (ino_width * ino_number)
ino.y = ino_height
ino.rect.x = ino.x
ino.rect.y = ino.y
inos.add(ino)
I'm creating a memory card game, but having difficulty updating each boxes' rect starting positions. First for loop loads each image and the second get's the starting position for each one. When I do a collision test, it only answers to <0,125,0,175> as my rect position's aren't updating. How can I update this?
import pygame, sys
from pygame.locals import *
screen_height = 800
screen_width = 800
card_x_size = 125
card_y_size = 175
marginx = 45
marginy = 25
class Box():
def __init__(self,image):
self.image = image
self.rect = image.get_rect()
def draw(self,screen):
screen.blit(self.image, self.rect)
def play_game():
pygame.init()
screen = pygame.display.set_mode((screen_width, screen_height))
back_images = ['back.jpg']*16
back_image_list = []
for back_image in back_images:
back_pic = pygame.image.load(back_image)
back_pic = pygame.transform.scale(back_pic, (card_x_size,card_y_size))
back_image_list.append(back_pic)
rect = back_pic.get_rect()
boxes = [Box(img) for img in back_image_list]
for j, box in enumerate(boxes):
pos_x = marginx + j % 4 * available_spacex
pos_y = marginy + j // 4 * available_spacey
box.rect.topleft = (pos_x, pos_y)
print(pos_x,pos_y)
while True:
mouse_clicked = False
clicked_card = False
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
elif event.type == MOUSEMOTION:
mousex, mousey = event.pos
elif event.type == MOUSEBUTTONUP:
mouse_clicked = True
print(mousex, mousey)
if rect.collidepoint(mousex,mousey):
clicked_card = True
print("hit")
for b in boxes:
b.draw(screen)
pygame.display.update()
play_game()
You have to evaluate whether the mouse click is on one of the box objects:
for box in boxes:
if box.rect.collidepoint(mousex, mousey):
clicked_card = True
print("hit")
function play_game:
def play_game():
# [...]
while True:
mouse_clicked = False
clicked_card = False
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
elif event.type == MOUSEMOTION:
mousex, mousey = event.pos
elif event.type == MOUSEBUTTONUP:
mousex, mousey = event.pos
mouse_clicked = True
print(mousex, mousey)
for box in boxes:
if box.rect.collidepoint(mousex, mousey):
clicked_card = True
print("hit")
for b in boxes:
b.draw(screen)
pygame.display.update()
import pygame, os, sys
from pygame import *
pygame.init()
RED = ( 255, 0, 0)
class WPawn():
def __init__(self, x, y):
self.x = x
self.y = y
self.image = pygame.transform.scale(pygame.image.load('wpawn.png'), (100,100))
self.move_x = 0
self.move_y = 0
def event_handler(self):
for event in pygame.event.get():
if event.type == KEYDOWN:
if event.key == K_UP:
self.move_y = -100
if event.key == K_DOWN:
self.move_y = 100
elif event.type == KEYUP:
if event.key in (K_UP, K_DOWN):
self.move_y = 0
def update(self, screen):
self.y = self.y + self.move_y
def draw(self, screen):
screen.blit(self.image, (self.x, self.y))
class Game():
def __init__(self):
screen_width = 900
screen_height = 900
self.screen = pygame.display.set_mode((screen_width,screen_height))
pygame.display.set_caption ("Chess Project")
self.pawn1 = WPawn(50,650)
self.pawn2 = WPawn(150,650)
self.pawn3 = WPawn(250,650)
self.pawn4 = WPawn(350,650)
self.pawn5 = WPawn(450,650)
self.pawn6 = WPawn(550,650)
self.pawn7 = WPawn(650,650)
self.pawn8 = WPawn(750,650)
def play(self):
clock = pygame.time.Clock()
RUNNING = True
while RUNNING:
for event in pygame.event.get():
if event.type == pygame.QUIT:
RUNNING = False
clock.tick(30)
self.pawn1.event_handler()
self.pawn2.event_handler()
self.pawn3.event_handler()
self.pawn4.event_handler()
self.pawn5.event_handler()
self.pawn6.event_handler()
self.pawn7.event_handler()
self.pawn8.event_handler()
self.pawn1.update(self.screen)
self.pawn2.update(self.screen)
self.pawn3.update(self.screen)
self.pawn4.update(self.screen)
self.pawn5.update(self.screen)
self.pawn6.update(self.screen)
self.pawn7.update(self.screen)
self.pawn8.update(self.screen)
self.screen.fill(RED)
self.pawn1.draw(self.screen)
self.pawn2.draw(self.screen)
self.pawn3.draw(self.screen)
self.pawn4.draw(self.screen)
self.pawn5.draw(self.screen)
self.pawn6.draw(self.screen)
self.pawn7.draw(self.screen)
self.pawn8.draw(self.screen)
pygame.display.update()
Game().play()
pygame.quit()
The KEY_UP event (or whatever) is consumed when you process it. So whichever WPawn class gets the event first will move.
Generally an event-driven program has only one event loop.
It may be easier to make this work by handling the event processing outside of the game objects. Have the single event loop handle record the key press, then move each WPawn that you wish to be moved.
Perhaps something like:
event = pygame.event.get()
if event.type == K_DOWN:
foreach pawn in all_pawns:
pawn.moveDown()
elif event.type == K_UP:
foreach pawn in all_pawns:
pawn.moveUp()
I'm trying to get the camera to move, but it's not having any effect when I click q w e a s or d. I tried asking the original programmer, but that came to nought, so I don't know what to do.
Code:
import pygame, sys, math
class Cam:
def __init__(self,pos=(0,0,0),rot=(0,0)):
self.pos = list(pos)
self.rot = list(rot)
def update(self,dt,key):
s = dt*10
if key[pygame.K_q]: self.pos[1]-=s
if key[pygame.K_e]: self.pos[1]+=s
if key[pygame.K_w]: self.pos[2]+=s
if key[pygame.K_s]: self.pos[2]-=s
if key[pygame.K_a]: self.pos[0]-=s
if key[pygame.K_d]: self.pos[0]+=s
pygame.init()
w,h = 400,400; cx,cy = w//2,h//2
screen = pygame.display.set_mode((w,h))
clock = pygame.time.Clock()
verts = (-1,-1,-1,),(1,-1,-1),(1,1,-1),(-1,1,-1),(-1,-1,1),(1,-1,1),(1,1,1),(-1,1,1)
edges = (0,1),(1,2),(2,3),(3,0),(4,5),(5,6),(6,7),(7,4),(0,4),(1,5),(2,6),(3,7)
cam = Cam((0,0,-5))
while True:
dt = clock.tick()/1000
for event in pygame.event.get():
if event.type == pygame.QUIT: pygame.quit(); sys.exit()
screen.fill((255,255,255))
for edge in edges:
points = []
for x,y,z in (verts[edge[0]],verts[edge[1]]):
x-=cam.pos[0]
y-=cam.pos[1]
z-=cam.pos[2]
f = 200/z
x,y = x*f,y*f
points+=[(cx+int(x),cy+int(y))]
pygame.draw.line(screen,(0,0,0),points[0],points[1],1)
pygame.display.flip()
key = pygame.key.get_pressed()
cam.update(dt,key)
You've forgotten to properly indent the last two lines.
import pygame, sys, math
class Cam:
def __init__(self,pos=(0,0,0),rot=(0,0)):
self.pos = list(pos)
self.rot = list(rot)
def update(self,dt,key):
s = dt*10
if key[pygame.K_q]: self.pos[1]-=s
if key[pygame.K_e]: self.pos[1]+=s
if key[pygame.K_w]: self.pos[2]+=s
if key[pygame.K_s]: self.pos[2]-=s
if key[pygame.K_a]: self.pos[0]-=s
if key[pygame.K_d]: self.pos[0]+=s
pygame.init()
w,h = 400,400; cx,cy = w//2,h//2
screen = pygame.display.set_mode((w,h))
clock = pygame.time.Clock()
verts = (-1,-1,-1,),(1,-1,-1),(1,1,-1),(-1,1,-1),(-1,-1,1),(1,-1,1),(1,1,1),(-1,1,1)
edges = (0,1),(1,2),(2,3),(3,0),(4,5),(5,6),(6,7),(7,4),(0,4),(1,5),(2,6),(3,7)
cam = Cam((0,0,-5))
while True:
dt = clock.tick()/1000
for event in pygame.event.get():
if event.type == pygame.QUIT: pygame.quit(); sys.exit()
screen.fill((255,255,255))
for edge in edges:
points = []
for x,y,z in (verts[edge[0]],verts[edge[1]]):
x-=cam.pos[0]
y-=cam.pos[1]
z-=cam.pos[2]
f = 200/z
x,y = x*f,y*f
points+=[(cx+int(x),cy+int(y))]
pygame.draw.line(screen,(0,0,0),points[0],points[1],1)
pygame.display.flip()
# these two lines should be inside the `while` loop
key = pygame.key.get_pressed()
cam.update(dt,key)
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.