Getting an error message in pygame - python-3.x

import pygame
import random
from os import path
img_dir = path.join(path.dirname(__file__), 'img')
snd_dir = path.join(path.dirname(__file__), 'sound')
WIDTH = 800
HEIGHT = 600
FPS = 50
WHITE=(255, 255, 255)
BLACK=(0, 0, 0)
RED=(255, 0, 0)
GREEN=(0, 255, 0)
BLUE=(0, 0, 255)
YELLOW=(255, 255, 0)
pygame.init()
pygame.mixer.init()
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("My Game")
clock = pygame.time.Clock()
font_name = pygame.font.match_font('arial')
end = True
def start_screen():
draw_text(screen, "SPACE SHOOTING", 70, WIDTH/2, HEIGHT/4)
draw_text(screen, "INSTRUCTIONS", 25, WIDTH/2, HEIGHT/2)
draw_text(screen, "Press Left arrow key to move left", 20, WIDTH/2, HEIGHT*2/3.5)
draw_text(screen, "Press Right arrow key to move right", 20, WIDTH/2, HEIGHT*2/3.3)
draw_text(screen, "Spacebar to shoot", 20, WIDTH/2, HEIGHT*2/3.1)
draw_text(screen, "Press a key to begin", 20, WIDTH/2, HEIGHT*3/4)
pygame.display.flip()
wait = True
while wait:
clock.tick(FPS)
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
if event.type == pygame.KEYUP:
if event.key == pygame.K_SPACE:
wait = False
def draw_text(surf, text, size, x, y):
font = pygame.font.Font(font_name, size)
text_surface = font.render(text, True, WHITE)
text_rect = text_surface.get_rect()
text_rect.midtop = (x, y)
surf.blit(text_surface, text_rect)
class Player(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.transform.scale(player_img, (50, 38))
self.image.set_colorkey(BLACK)
self.rect = self.image.get_rect()
self.radius = 20
self.rect.centerx = WIDTH/2
self.rect.bottom = HEIGHT - 10
self.speedx = 0
def update(self):
self.speedx = 0
keystate = pygame.key.get_pressed()
if keystate[pygame.K_LEFT]:
self.speedx = -5
if keystate[pygame.K_RIGHT]:
self.speedx = 5
self.rect.x += self.speedx
if self.rect.right > WIDTH:
self.rect.right = WIDTH
if self.rect.left < 0:
self.rect.left = 0
def shoot(self):
bullet = Bullets(self.rect.centerx, self.rect.top)
all_sprites.add(bullet)
bullets.add(bullet)
class Aliens(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = aliens_img
self.image.set_colorkey(BLACK)
self.rect = self.image.get_rect()
self.radius = int(self.rect.width*.85/2)
self.rect.x = random.randrange(WIDTH - self.rect.width)
self.rect.y = random.randrange(-100, -40)
self.speedy = random.randrange(1, 8)
def update(self):
self.rect.y += self.speedy
if self.rect.top > HEIGHT + 10 or self.rect.left < -25 or self.rect.right > WIDTH + 20:
self.rect.x = random.randrange(WIDTH - self.rect.width)
self.rect.y = random.randrange(-100, -40)
self.speedy = random.randrange(1, 8)
class SuperAliens(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = superaliens_img
self.image.set_colorkey(BLACK)
self.rect = self.image.get_rect()
self.radius = int(self.rect.width*.85/2)
self.rect.x = random.randrange(WIDTH - self.rect.width)
self.rect.y = random.randrange(-100, -40)
self.speedy = random.randrange(1, 8)
self.speedx = random.randrange(-3, 3)
def update(self):
self.rect.x += self.speedx
self.rect.y += self.speedy
if self.rect.top > HEIGHT + 10 or self.rect.left < -25 or self.rect.right > WIDTH + 20:
self.rect.x = random.randrange(WIDTH - self.rect.width)
self.rect.y = random.randrange(-100, -40)
self.speedy = random.randrange(1, 8)
def shoot1(self):
sbullet = SBullets(self.rect.centerx, self.rect.bottom)
all_sprites.add(sbullet)
bullets.add(sbullet)
class SBullets(pygame.sprite.Sprite):
def __init__(self, x, y):
pygame.sprite.Sprite.__init__(self)
self.image = sbullet_img
self.image.set_colorkey(BLACK)
self.rect = self.image.get_rect()
self.rect.bottom = y
self.rect.centerx = x
self.speedy = +10
def update(self):
self.rect.y += self.speedy
if self.rect.top < 0:
self.kill()
class Bullets(pygame.sprite.Sprite):
def __init__(self, x, y):
pygame.sprite.Sprite.__init__(self)
self.image = bullet_img
self.image.set_colorkey(BLACK)
self.rect = self.image.get_rect()
self.rect.bottom = y
self.rect.centerx = x
self.speedy = -10
def update(self):
self.rect.y += self.speedy
if self.rect.bottom < 0:
self.kill()
class Explode(pygame.sprite.Sprite):
def __init__(self, center, size):
pygame.sprite.Sprite.__init__(self)
self.size = size
self.image = explode[self.size][0]
self.rect = self.image.get_rect()
self.rect.center = center
self.frame = 0
self.last_update = pygame.time.get_ticks()
self.frame_rate = 2
def update(self):
now = pygame.time.get_ticks()
if now - self.last_update > self.frame_rate:
self.last_update = now
self.frame += 1
if self.frame == len(explode[self.size]):
self.kill()
else:
center = self.rect.center
self.image = explode[self.size][self.frame]
self.rect = self.image.get_rect()
self.rect.center = center
background = pygame.image.load(path.join(img_dir, "back.png")).convert()
background_rect = background.get_rect()
player_img = pygame.image.load(path.join(img_dir, "playerShip2_blue.png")).convert()
superaliens_img = pygame.image.load(path.join(img_dir, "enemyBlack4.png")).convert()
aliens_img = pygame.image.load(path.join(img_dir, "enemyBlack1.png")).convert()
bullet_img = pygame.image.load(path.join(img_dir, "laserRed16.png")).convert()
sbullet_img = pygame.image.load(path.join(img_dir, "laserRed11.png")).convert()
explode = {}
explode['super']=[]
explode['small']=[]
for i in range(9):
filename = 'regularExplosion02.png'.format(1)
img = pygame.image.load(path.join(img_dir, filename)).convert()
img.set_colorkey(BLACK)
img_super = pygame.transform.scale(img, (75, 75))
explode ['super'].append(img_super)
img_small = pygame.transform.scale(img, (32, 32))
explode ['small'].append(img_small)
#pygame.mixer.music.load(path.join(snd_dir, 'Orbital.mp3'))
#pygame.mixer.music.set_volume(0.4)
#pygame.mixer.music.play(loops=-1)
end_game = True
running = True
while running:
if end_game:
start_screen()
end_game = False
all_sprites = pygame.sprite.Group()
aliens = pygame.sprite.Group()
superaliens = pygame.sprite.Group()
bullets = pygame.sprite.Group()
sbullets = pygame.sprite.Group()
player = Player()
all_sprites.add(player)
for i in range(5):
m = Aliens()
all_sprites.add(m)
aliens.add(m)
for j in range(1):
n = SuperAliens()
all_sprites.add(n)
superaliens.add(n)
score = 0
clock.tick(FPS)
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
player.shoot()
all_sprites.update()
hits = pygame.sprite.groupcollide(aliens, bullets, True, True)
for hit in hits:
score += 1
m = Aliens()
expl = Explode(hit.rect.center, 'small')
all_sprites.add(expl)
all_sprites.add(m)
aliens.add(m)
hits = pygame.sprite.groupcollide(superaliens, bullets, True, True)
for hitt in hits:
score += 5
n = SuperAliens()
expl1 = Explode(hitt.rect.center, 'super')
all_sprites.add(expl1)
all_sprites.add(n)
superaliens.add(n)
hits = pygame.sprite.spritecollide(player, aliens, True)
for hit in hits:
expl = Explode(hit.rect.center, 'small')
all_sprites.add(expl)
if hits:
end_game = True
hits = pygame.sprite.spritecollide(player, superaliens, True)
for hitt in hits:
expl1 = Explode(hitt.rect.center, 'super')
all_sprites.add(expl1)
if hits:
end_game = True
screen.fill(BLACK)
screen.blit(background, background_rect)
all_sprites.draw(screen)
draw_text(screen,"SCORE" +str(score), 22, WIDTH/2, 10)
#after drwing everything flip the display
pygame.display.flip()
pygame.quit()
Sorry for the bad formatting but couldn't upload it with the proper formatting. Its my first pygame, so im not good in it. The program is working good, but every time when i close the window, its is showing me this error.
Traceback (most recent call last):
File "/Users/Documents/game.py", line 221, in
start_screen()
File "/Users/Documents/game.py", line 41, in start_screen
for event in pygame.event.get():
pygame.error: video system not initialized
I was also trying to make the super aliens shoot randomly towards the player, and that thing is not working as well.A little help would be appreciated. Thanks

After the line:
pygame.quit()
put:
exit()
Basically, pygame.quit() tells pygame that you are done with it. After you call it in your event loop, pygame no longer can draw things to the screen, but you still try to make it do so later in your program. Calling exit() makes python exit so that pygame is not told to draw anything.

Related

How to position bullet to the current directions of my Player(Gun) when the player is rotated towards another direction in Pygame Sprite [duplicate]

This question already has answers here:
How to set the pivot point (center of rotation) for pygame.transform.rotate()?
(5 answers)
Rotating and scaling an image around a pivot, while scaling width and height separately in Pygame
(1 answer)
How can you rotate an image around an off center pivot in Pygame
(1 answer)
Closed 4 months ago.
I am working on a Pygame with Sprite. Everything is working fine except that the bullet is not firing toward the position of the player(Gun)
When I position the Player (Gun) towards my target with rotation and shoot, the bullet does not get positioned towards the current position of the player(Gun)
I want the bullet to automatically position towards the same direction that my player (Gun) is currently facing when I rotate the player.
import pygame
import os
import random
BACKGROUND_IMAGE = pygame.image.load(
os.path.join("Assets", "2dforest.jpeg"))
BACKGROUND_WIDTH, BACKGROUND_HEIGHT = 1000, 550
pygame.display.set_caption("Hunting Birds")
WIN = pygame.display.set_mode((BACKGROUND_WIDTH, BACKGROUND_HEIGHT))
COLOR = (255, 200, 98)
class Birds(pygame.sprite.Sprite):
def __init__(self, image, width, height, pos_x, pos_y, speed_x, speed_y):
super().__init__()
self.width = width
self.height = height
self.pos_x = pos_x
self.pos_y = pos_y
self.image = pygame.image.load(
os.path.join("Assets", image)).convert_alpha()
self.image = pygame.transform.scale(self.image, (70, 60))
self.rect = self.image.get_rect()
self.rect.center = [self.pos_x, self.pos_y]
self.speed_x = speed_x
self.speed_y = speed_y
self.right = self.image
self.left = pygame.transform.flip(self.image, True, False)
def movement(self, thgroup):
for i in thgroup:
pos_x, pos_y = i.rect.center
pos_x += i.speed_x
pos_y += i.speed_y
i.rect.center = (pos_x, pos_y)
if(pos_x >= BACKGROUND_WIDTH - 50):
i.image = i.left
i.speed_x = - i.speed_x
elif(pos_x < 50):
i.image = i.right
i.speed_x = - i.speed_x
if(pos_y >= 300 or pos_y < 20):
i.speed_y = - i.speed_y
class HunterGun(pygame.sprite.Sprite):
def __init__(self, image, width, height, pos_x, pos_y):
super().__init__()
self.width = width
self.height = height
self.pos_x = pos_x
self.pos_y = pos_y
self.image = pygame.image.load(
os.path.join("Assets", image)).convert_alpha()
self.org_image = self.image.copy()
self.org_image = pygame.transform.scale(self.org_image, (175, 75))
self.rect = self.org_image.get_rect()
self.rect.center = (self.pos_x, self.pos_y)
self.angle = 0
def move_and_turn(self, mover):
keys_pressed = pygame.key.get_pressed()
if (keys_pressed[pygame.K_LEFT]):
pos_x, pos_y = self.rect.center
pos_x -= mover
self.rect.center = (pos_x, pos_y)
elif (keys_pressed[pygame.K_RIGHT]):
pos_x, pos_y = self.rect.center
pos_x += mover
self.rect.center = (pos_x, pos_y)
elif (keys_pressed[pygame.K_UP]):
pos_x, pos_y = self.rect.center
pos_y -= mover
self.rect.center = (pos_x, pos_y)
elif (keys_pressed[pygame.K_DOWN]):
pos_x, pos_y = self.rect.center
pos_y += mover
self.rect.center = (pos_x, pos_y)
def update(self, angle, dt):
pressed = pygame.key.get_pressed()
if pressed[pygame.K_a]:
self.angle += 3
if pressed[pygame.K_d]:
self.angle -= 3
self.direction = pygame.Vector2(1, 0).rotate(-self.angle)
self.image = pygame.transform.rotate(self.org_image, self.angle)
self.rect = self.image.get_rect(center=self.rect.center)
def create_bullect(self):
pos_x, pos_y = self.rect.center
theBullet = Bullet(pos_x, pos_y)
return theBullet
class Bullet(pygame.sprite.Sprite):
def __init__(self, pos_x, pos_y):
super().__init__()
self.pos_x = pos_x
self.pos_y = pos_y
self.image = pygame.image.load(
os.path.join("Assets", "newbullet.png")).convert_alpha()
self.image = pygame.transform.scale(self.image, (55, 60))
self.rect = self.image.get_rect(center=(pos_x, pos_y))
def update(self):
self.rect.y -= 13
self.pos_y
if(self.rect.x >= BACKGROUND_WIDTH + 200):
self.kill()
elif(self.rect.y >= BACKGROUND_HEIGHT + 200):
self.kill()
pos_x, pos_y = self.rect.center
if(pygame.sprite.spritecollide(
Bullet(pos_x, pos_y), birds_sprite, True)):
self.kill()
birds_sprite = pygame.sprite.Group()
enemyList = []
for target in range(5):
new_target = Birds("neweagle.png", 100, 100,
random.randrange(100, BACKGROUND_WIDTH - 100), random.randrange(20, BACKGROUND_HEIGHT // 3), 2, 4)
enemyList.append(new_target)
birds_sprite.add(new_target)
gunhunter = HunterGun("latestgun.png", 100, 100,
BACKGROUND_WIDTH // 2, BACKGROUND_HEIGHT//2)
gun_sprite = pygame.sprite.Group()
gun_sprite.add(gunhunter)
bullet_group = pygame.sprite.Group()
pygame.init()
clock = pygame.time.Clock()
run = True
dt = 0
while run:
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
keys_pressed = pygame.key.get_pressed()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_k:
bullet_group.add(gunhunter.create_bullect())
picture = pygame.transform.scale(BACKGROUND_IMAGE, (1000, 540))
pygame.display.flip()
WIN.blit(picture, (0, 0))
birds_sprite.draw(WIN)
bullet_group.draw(WIN)
gun_sprite.draw(WIN)
new_target.movement(enemyList)
new_target.update()
gunhunter.move_and_turn(4)
birds_sprite.update()
gun_sprite.update(event, dt)
bullet_group.update()
dt = clock.tick(60)
pygame.quit()

Alien not defined

For some reason, the python window says Alien not defined.
alien.py:
import pygame
from pygame.sprite import Sprite
class Alien(Sprite):
def __init__(self, ai_settings, screen):
super(Alien, self).__init__()
self.screen = screen
self.ai_settings = ai_settings
self.image = pygame.image.load('alien.bmp')
self.rect = self.image.get_rect()
self.rect.x = self.rect.width
self.rect.y = self.rect.height
self.x = float(self.rect.x)
def check_edges(self):
screen_rect = self.screen.get_rect()
if self.rect.right >= screen_rect.right:
return True
elif self.rect.left <= 0:
return True
def update(self):
self.x += (self.ai_settings.alien_speed_factor *
self.ai_settings.fleet_direction)
self.rect.x = self.x
def blitme(self):
self.screen.blit(self.image, self.rect)
alien_invasion.py:
import sys
import pygame
from settings import Settings
from ship import Ship
import game_functions as gf
import random
from pygame.sprite import Group
from alien import Alien
class Square(pygame.sprite.Sprite):
def __init__(self, x, y, size1, size2, colour):
super().__init__()
self.image = pygame.Surface([size1, size2])
self.image.fill(colour)
self.rect=self.image.get_rect()
self.rect.x=x
self.rect.y=y
allspriteslist = pygame.sprite.Group()
for i in range(1, 250):
num = random.randint(1,3)
stars = Square(random.randint(0, 1000), random.randint(0, 700), num, num, (255, 255, 255))
allspriteslist.add(stars)
def run_game():
pygame.init()
ai_settings = Settings()
screen = pygame.display.set_mode((ai_settings.screen_width, ai_settings.screen_height))
pygame.display.set_caption("PEWPEWPEWPOWPOW DIE YOU LITTLE ALIEN ____S ")
ship = Ship(ai_settings, screen)
bullets = Group()
aliens = Group()
gf.create_fleet(ai_settings, screen, ship, aliens)
while True:
gf.check_events(ai_settings, screen, ship, bullets)
ship.update()
gf.update_bullets(bullets)
gf.update_screen(ai_settings, screen, ship, alien, bullets)
allspriteslist.draw(screen)
pygame.display.flip()
run_game()
bullet.py:
import pygame
from pygame.sprite import Sprite
class Bullet(Sprite):
def __init__(self, ai_settings, screen, ship):
super(Bullet, self).__init__()
self.screen = screen
self.rect = pygame.Rect(0, 0, ai_settings.bullet_width,
ai_settings.bullet_height)
self.rect.centerx = ship.rect.centerx
self.rect.top = ship.rect.top
self.y = float(self.rect.y)
self.color = ai_settings.bullet_color
self.speed_factor = ai_settings.bullet_speed_factor
def update(self):
self.y -= self.speed_factor
self.rect.y = self.y
def draw_bullet(self):
pygame.draw.rect(self.screen, self.color, self.rect)
game_functions.py:
import sys
import pygame
from bullet import Bullet
def check_keydown_events(event, ai_settings, screen, ship, bullets):
if event.key == pygame.K_RIGHT:
ship.moving_right = True
elif event.key == pygame.K_LEFT:
ship.moving_left = True
elif event.key == pygame.K_SPACE:
fire_bullet(ai_settings, screen, ship, bullets)
elif event.key == pygame.K_q:
sys.exit
def check_keyup_events(event, ship):
if event.key == pygame.K_RIGHT:
ship.moving_right = False
elif event.key == pygame.K_LEFT:
ship.moving_left = False
def check_events(ai_settings, screen, ship, bullets):
for event in pygame.event.get():
if event == pygame.QUIT:
sys.exit()
elif event.type == pygame.KEYDOWN:
check_keydown_events(event, ai_settings, screen, ship, bullets)
elif event.type == pygame.KEYUP:
check_keyup_events(event, ship)
def update_screen(ai_settings, screen, ship, aliens, bullets):
screen.fill(ai_settings.bg_colour)
for bullet in bullets.sprites():
bullet.draw_bullet()
ship.blitme()
aliens.draw(screen)
def update_bullets(bullets):
bullets.update()
for bullet in bullets.copy():
if bullet.rect.bottom <= 0:
bullets.remove(bullet)
def fire_bullet(ai_settings, screen, ship, bullets):
if len(bullets) < ai_settings.bullets_allowed:
new_bullet = Bullet(ai_settings, screen, ship)
bullets.add(new_bullet)
def get_number_rows(ai_settings, ship_height, alien_height):
available_space_y = (ai_settings.screen_height -
(3 * alien_height) - ship_height)
number_rows = int(available_space_y / (2 * alien_height))
return number_rows
def create_alien(ai_settings, screen, aliens, alien_number, row_number):
alien = Alien(ai_settings, screen)
alien_width = alien.rect.width
alien.x = alien_width + 2 * alien_width * alien_number
alien.rect.x = alien.x
alien.rect.y = alien.rect.height + 2 * alien.rect.height * row_number
aliens.add(alien)
def create_fleet(ai_settings, screen, ship, aliens):
alien = Alien(ai_settings, screen)
number_aliens_x = get_number_aliens_x(ai_settings, alien.rect.width)
number_rows = get_number_rows(ai_settings, ship.rect.height,
alien.rect.height)
settings.py:
class Settings():
def __init__(self):
#screen stuff
self.screen_width = 1000
self.screen_height = 750
self.bg_colour = (0, 0, 0)
self.ship_speed_factor = 1.5
self.bullet_speed_factor = 1
self.bullet_width = 3
self.bullet_height = 15
self.bullet_color = 0, 255, 0
self.bullets_allowed = 7
ship.py:
import pygame
class Ship():
def __init__(self, ai_settings, screen):
self.screen = screen
self.ai_settings = ai_settings
self.image = pygame.image.load('ship.bmp')
self.rect = self.image.get_rect()
self.screen_rect = screen.get_rect()
self.rect.centerx = self.screen_rect.centerx
self.rect.bottom = self.screen_rect.bottom
self.moving_right = False
self.moving_left = False
self.center = float(self.rect.centerx)
def update(self):
if self.moving_right and self.rect.right < self.screen_rect.right:
self.center += self.ai_settings.ship_speed_factor
if self.moving_left and self.rect.left > 0:
self.center -= self.ai_settings.ship_speed_factor
self.rect.centerx = self.center
def blitme(self):
self.screen.blit(self.image, self.rect)
I'm getting an error message that Alien is not defined when I run this code, and I don't know why.
How is the game_functions.py file meant to know about the Alien it uses in createAlien() and createFleet()?
Python is good, but it can't read minds :-) I think you probably need to import the alien stuff into that file.

How to update score in PONG game

Something is wrong on line 54... I don't know how to fix this...
(builtins.AttributeError: 'Game' object has no attribute 'center')
Help______________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________
import pygame
def main():
pygame.init()
pygame.display.set_mode((500, 400))
pygame.display.set_caption('Pong')
w_surface = pygame.display.get_surface()
game = Game(w_surface)
game.play()
pygame.quit()
class Game:
def __init__(self, surface):
self.surface = surface
self.bg_color = pygame.Color('black')
self.fg_color = pygame.Color('white')
self.FPS = 60
self.game_Clock = pygame.time.Clock()
self.close_clicked = False
self.continue_game = True
self.small_dot = Dot('white', 10, [10, 10], [2, 2], self.surface)
self.rect1 = pygame.Rect([50,150], [10, 100])
self.rect2 = pygame.Rect([450,150], [10, 100])
self.max_frames = 100000
self.frame_counter = 0
self.score1 = 0
self.score2 = 0
def play(self):
while not self.close_clicked:
self.handle_events()
self.draw()
if self.continue_game:
self.update()
self.decide_continue()
self.game_Clock.tick(self.FPS)
def handle_events(self):
events = pygame.event.get()
for event in events:
if event.type == pygame.QUIT:
self.close_clicked = True
def draw(self):
self.surface.fill(self.bg_color)
self.small_dot.draw()
self.draw_score1()
self.draw_score2()
pygame.draw.rect(self.surface, self.fg_color, self.rect1)
pygame.draw.rect(self.surface, self.fg_color, self.rect2)
pygame.display.update()
def update(self):
self.small_dot.move()
if self.center[0] > 490:
self.score1 += self.score1
self.frame_counter = self.frame_counter + 1
def decide_continue(self):
if self.frame_counter > self.max_frames:
self.continue_game = False
def draw_score1(self):
score_string = 'Score: '+str(self.score1)
score_fg_color = pygame.Color('white')
score_font = pygame.font.SysFont('', 35)
score_image = score_font.render(score_string, True, score_fg_color)
self.surface.blit(score_image, (0, 0))
def draw_score2(self):
score_string = 'Score: '+str(self.score2)
score_fg_color = pygame.Color('white')
score_font = pygame.font.SysFont('', 35)
score_image = score_font.render(score_string, True, score_fg_color)
self.surface.blit(score_image, (400, 0))
class Dot:
def __init__(self, dot_color, dot_radius, dot_center, dot_velocity, surface):
self.color = pygame.Color(dot_color)
self.radius = dot_radius
self.center = dot_center
self.velocity = dot_velocity
self.surface = surface
def move(self):
self.center[0] += self.velocity[0]
self.center[1] += self.velocity[1]
if self.center[0] < 10:
self.velocity[0] = -self.velocity[0]
if self.center[1] < 10:
self.velocity[1] = -self.velocity[1]
if self.center[0] > 490:
self.velocity[0] = -self.velocity[0]
if self.center[1] > 390:
self.velocity[1] = -self.velocity[1]
def draw(self):
pygame.draw.circle(self.surface, self.color, self.center, self.radius)
main()
Indeed your Game class does not have a center. Your Dot does.
Add a center to your Game class in the __init__ function.
Or
Maybe you meant to call self.small_dot.center instead (in line 54)

Pygame screen gets cleared on flip, but only once

So I am trying to recreate Minesweeper in pygame. Since I am only drawing a single image over my current screen when a player clicks, I do not have frames. The problem is, when the player first clicks and I draw one image a flip the display. The first time I do that, it clears the background. After that, it doesn't clear the previous images. If I try and call flip first thing, nothing happens. I tried to flip after every image (Just trying things) and nothing changed.
Code:
import pygame, random, os, sys, math
pygame.init()
font = pygame.font.SysFont('Sans Serif 7', 15)
screenX = 1240
screenY = 720
sprites = pygame.image.load(os.path.dirname(os.path.abspath(__file__)) + "\\Minesweeper\\ImageSheet.png")
spriteList = []
#tiles = 16px, icons = 26px
class Minefield():
def __init__(self, width, height, mines, surface):
self.width = width
self.height = height
self.mine = sprites.subsurface(80, 49, 16, 16)
self.rows = []
self.surface = surface
for i in range(0, width):
self.rows.append([])
for i2 in range(0, height):
self.rows[i].append(-2)
for i in range(0, mines):
print(len(self.rows))
print(len(self.rows[1]))
x = random.randint(0, width-1)
y = random.randint(0, height-1)
print(x)
print(y)
self.rows[x][y]
self.render()
def clicked(self, rawPos):
pos = (math.floor(rawPos[0]/16), math.floor(rawPos[1]/16))
val = self.rows[pos[0]][pos[1]]
if val == -2:
mines = 1
if not pos[0] == 0 and not pos[1] == 0 and self.rows[pos[0]-1][pos[1]-1] == -1:
mines += 1
if not pos[0] == 0 and self.rows[pos[0]-1][pos[1]] == -1:
mines += 1
if not pos[0] == 0 and not pos[1] == self.height and self.rows[pos[0]-1][pos[1]+1] == -1:
mines += 1
if not pos[1] == 0 and self.rows[pos[0]][pos[1]-1] == -1:
mines += 1
if not pos[1] == self.height and self.rows[pos[0]][pos[1]+1] == -1:
mines += 1
if not pos[1] == 0 and not pos[0] == self.width and self.rows[pos[0]+1][pos[1]-1] == -1:
mines += 1
if not pos[0] == self.width and self.rows[pos[0]+1][pos[1]] == -1:
mines += 1
if not pos[1] == self.height and not pos[0] == self.width and self.rows[pos[0]+1][pos[1]+1] == -1:
mines += 1
print(mines)
self.surface.blit(spriteList[mines], (pos[0]*16, pos[1]*16))
pygame.display.flip()
elif val == -1:
playing = False
return
def render(self):
for i in range(0, self.width):
for i2 in range(0, self.height):
self.surface.blit(spriteList[0], (i*16, i2*16))
pygame.display.flip()
class Main():
def __init__(self):
self.screen = pygame.display.set_mode((screenX, screenY), pygame.RESIZABLE)
spriteList.append(sprites.subsurface(16, 49, 16, 16))
for i in range(0, 8):
print(i*16)
spriteList.append(sprites.subsurface(i*16, 65, 16, 16))
self.field = Minefield(50, 30, 30, self.screen)
def gameloop(self):
while True:
for event in pygame.event.get():
if event.type == pygame.VIDEORESIZE:
screenX = event.w
screenY = event.h
self.screen = pygame.display.set_mode((event.w, event.h), pygame.RESIZABLE)
if event.type == pygame.QUIT:
return
if event.type == pygame.MOUSEBUTTONUP:
pos = pygame.mouse.get_pos()
self.field.clicked(pos)
def stop(self):
pygame.display.quit()
pygame.quit()
sys.exit("Window Closed")
main = Main()
main.gameloop()
main.stop()
What I want:
On player click the only change is a 1 appears over the cell, but instead the background gets painted over by black.
pygame.display.set_mode() creates a new window surface. You've to render the background after recreating the window surface in the resize event. When the window was initialized, then immediately 1 resize event is pending.
def gameloop(self):
while True:
for event in pygame.event.get():
if event.type == pygame.VIDEORESIZE:
screenX = event.w
screenY = event.h
self.screen = pygame.display.set_mode((event.w, event.h), pygame.RESIZABLE)
self.field.render() # <-------------
Note, when the window was resized and the window surface is recreated then the entire scene has to be redrawn.
Probably your game will work only, if the window is not resizable. When you resize the window, then a new event occurs. The surface is recreated and the background is redrawn, but the "clicked" fields are lost. So they would have to be redrawn, too.

A moving rectangle becomes stuck after hitting the edge of the window

I created a rectangle in the middle of the window, and used key 'w', 's', 'a', 'd', to move it. My problem is every time the rectangle hits the edge of the window is becomes stuck and cannot move any more.
import pygame, sys, time
from pygame.locals import *
class Tile:
bcolor = pygame.Color('black')
rcolor = pygame.Color('white')
def __init__(self, surface):
self.surface = surface
self.size = 30
self.x = self.surface.get_width()//2 - self.size//2
self.y = self.surface.get_height()//2 - self.size//2
self.rect = pygame.Rect(self.x, self.y, self.size, self.size)
self.speed = 10
self.rcolor = Tile.rcolor
self.bcolor = Tile.bcolor
def draw(self):
pygame.draw.rect(self.surface, self.rcolor, self.rect)
def moveup(self):
if self.rect.top < self.speed:
self.speed = self.rect.top
self.rect.move_ip(0, -self.speed)
def movedown(self):
maxbottom = self.surface.get_height()
if maxbottom - self.rect.bottom < self.speed:
self.speed = maxbottom - self.rect.bottom
self.rect.move_ip(0,self.speed)
def moveleft(self):
if self.rect.left < self.speed:
self.speed = self.rect.left
self.rect.move_ip(-self.speed, 0)
def moveright(self):
maxright = self.surface.get_width()
if maxright - self.rect.right < self.speed:
self.speed = maxright - self.rect.right
self.rect.move_ip(self.speed, 0)
def handlekeydown(self, key):
if key == K_w:
self.moveup()
if key == K_s:
self.movedown()
if key == K_a:
self.moveleft()
if key == K_d:
self.moveright()
def update(self):
self.surface.fill(self.bcolor)
self.draw()
def main():
pygame.init()
pygame.key.set_repeat(20, 20)
surfacesize = (500,400)
title = 'Practice'
framedelay = 0.02
surface = pygame.display.set_mode(surfacesize, 0, 0)
pygame.display.set_caption(title)
tile = Tile(surface)
gameover = False
tile.draw()
pygame.display.update()
while True:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
if event.type == KEYDOWN and not gameover:
tile.handlekeydown(event.key)
tile.update()
pygame.display.update()
time.sleep(framedelay)
main()
Just look at this piece of code:
def moveup(self):
if self.rect.top < self.speed:
self.speed = self.rect.top
self.rect.move_ip(0, -self.speed)
Once you move to the top of the screen, self.rect.top becomes 0, which is smaller than self.speed, so the condition of the if statement is True and in the next line you set self.speed to 0, hence all your move_ip calls won't move the Rect (because self.speed is now 0).
If you want to prevent the Rect from leaving the screen, better just use clamp_ip:
...
def moveup(self):
self.rect.move_ip(0, -self.speed)
def movedown(self):
self.rect.move_ip(0,self.speed)
def moveleft(self):
self.rect.move_ip(-self.speed, 0)
def moveright(self):
self.rect.move_ip(self.speed, 0)
def handlekeydown(self, key):
if key == K_w:
self.moveup()
if key == K_s:
self.movedown()
if key == K_a:
self.moveleft()
if key == K_d:
self.moveright()
self.rect.clamp_ip(pygame.display.get_surface().get_rect())
...
(There are some other issues with your code, but that's another topic.)

Resources