S
S
Span4ev2022-03-11 21:13:44
Python
Span4ev, 2022-03-11 21:13:44

How to pass an instance of a class from a group to event handling?

I'm learning python, trying to make a game 2048. I created a group and in a loop I create an instance of the class (new block) and add it to the group. But I want to make collision control and I can't figure out how to pass an instance of the class to the condition check function

. I'm sorry. Everything is smooth in the editor, but here some indents "floated" and the text moved out.

import pygame as pg
import time, random, sys
from pygame.sprite import Group
from pygame.sprite import Sprite

class Settings:
  def __init__(self):

    # Список цветов
    self.WHITE			= (255, 255, 255)
    self.YELLOW			= (255, 255, 102)
    self.BLACK		 	= (0, 0, 0)
    self.RED 			= (213, 50, 80)
    self.GREEN 		 	= (0, 255, 0)
    self.BLUE 			= (50, 153, 213)
    self.COLOR_LIST 		= [self.WHITE, self.YELLOW, self.BLACK, self.RED, self.GREEN, self.BLUE] 

    # Параметры шрифта
    self.FONT			= 'Tahoma'
    self.FONT_SIZE			= 40
    self.FONT_COLOR			= 'black'
    
    # Параметры экрана
    self.SCREEN_WIDTH 		= 500
    self.SCREEN_HEIGHT 		= 500
    self.DISPLAY 		= self.SCREEN_WIDTH, self.SCREEN_HEIGHT
    self.BG_COLOR 		= (230, 230, 230)
    self.FPS 			= 10

    # Параметры блока
    self.SIZE 		     = 100
    self.BLOCK_COLOR 	= 'red'
    self.BLOCK_BORDER_WIDTH 	= 6

class Block(Sprite):

  def __init__(self, screen, settings, new_number, new_color):
    super().__init__()

    self.screen 		= screen
    self.settings 		= settings
    self.screen_rect 		= self.screen.get_rect()
    self.rect 		        = pg.Rect(0, 0, settings.SIZE, settings.SIZE)
    self.border_width 		= settings.BLOCK_BORDER_WIDTH

    self.new_number 		= str(new_number)
    self.new_color 		= new_color
    self.font_style 		= pg.font.SysFont(self.settings.FONT, self.settings.FONT_SIZE)
    self.number 		= self.font_style.render(self.new_number, True, self.settings.FONT_COLOR)
    self.number_rect  		= self.number.get_rect()
    
    self.block_moving 		= False

  def print_numbers(self):

    self.number_rect.center = self.rect.center
    self.screen.blit(self.number, self.number_rect)

    if self.block_moving:
      print(1223423)

  def draw_block(self):
    """ Отрисовка каждого блока """
    pg.draw.rect(self.screen, self.new_color, self.rect, width=self.border_width)


def check_events(screen, blocks):
  for e in pg.event.get():
    if e.type == pg.QUIT or e.type == pg.KEYDOWN and e.key == pg.K_ESCAPE:
      sys.exit()
      pg.quit()

    if e.type == pg.MOUSEBUTTONDOWN and e.button == 1:
      # print(e.pos)
      block_moving = True

    if e.type == pg.MOUSEBUTTONUP and e.button == 1:
      # print(e.pos)
      block_moving = False
      # block.click = block.rect.collidepoint(e.pos)

def create_blocks(screen, settings, blocks):

  # Кол-во строк и столбцов для блоков
  rows = settings.SCREEN_WIDTH // settings.SIZE
  cols = settings.SCREEN_HEIGHT // settings.SIZE
  x = 0 # Временные переменные для координат блоков
  y = 0

  get_new_numbers = [] 		 # Список с текущими цифрами для распечатки
  positions  = [] 			         # Список с координатами для расположения блоков
  current_numbers_amount = 5  # Сколько сейчас доступно цифр. Вначале от 2 до 32
  start_numbers = 2 			 # Первая цифра это 2

  # Возвести цифры в квадрат и добавить в список
  for num in range(current_numbers_amount):
    get_new_numbers.append(start_numbers)
    start_numbers *= 2

  # Напечатать блоки
  for i in range(rows):
    for k in range(cols):
      x = i
      y = k
      x *= settings.SIZE
      y *= settings.SIZE

      # Добавление новых координат в список с координатами
      new_list = []
      new_list.append(x)
      new_list.append(y)
      positions.append(new_list)

      # Получение рандомного числа из списка
      new_number = random.choice(get_new_numbers)
      new_color  = random.choice(settings.COLOR_LIST)

      # Создать экземпляр класса, присвоить ему координаты и добавить его в группу
      block = Block(screen, settings, new_number, new_color)
      block.rect.x = x
      block.rect.y = y
      blocks.add(block)

def update_screen(screen, settings, blocks):

  screen.fill(settings.BG_COLOR)
  check_events(screen, blocks)

  # Каждый спрайт нарисовать и распечатать число
  for block in blocks.sprites():
    block.draw_block()
    block.print_numbers()

  pg.display.update()

def start():

  pg.init()

  settings = Settings()
  clock = pg.time.Clock()

  screen = pg.display.set_mode((settings.DISPLAY))
  screen_rect = screen.get_rect()

  blocks = Group()

  # Создаю один раз вне цикла
  create_blocks(screen, settings, blocks)

  while True:
    
    update_screen(screen, settings, blocks)
    clock.tick(settings.FPS)
start()


I don’t understand how to pass not the Blocks group to the def check_events function , Block is an instance of the class. I create it in a loop, in the create_blocks function , and in it I get 2 parameters that I pass to the constructor of the Block class:

# Получение рандомного числа из списка
new_number = random.choice(get_new_numbers)
new_color  = random.choice(settings.COLOR_LIST)


That is, I cannot create an instance of the class outside the function in this way (conditionally, without changing the structure of the functions), namely with the existing structure, because then from another place I will have to pass 2 parameters to it (random number and color). It was not possible to call the event check function from the loop. I sit all day, I do not understand how to implement this.
Just in case, I repeat the problem: I want to make collision control so that you can drag blocks on top of each other. Blocks are sprites in a group. I can pass a group to a function with event checking, but I cannot pass an instance of the class to work with a specific instance (block) when a mouse event occurs.

Answer the question

In order to leave comments, you need to log in

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question