Различия между версиями 8 и 9
Версия 8 от 2017-08-14 18:37:53
Размер: 9489
Редактор: ArsenyMaslennikov
Комментарий:
Версия 9 от 2017-08-15 14:22:48
Размер: 9465
Редактор: FrBrGeorge
Комментарий:
Удаления помечены так. Добавления помечены так.
Строка 230: Строка 230:
   * Конец игры, когда количество бросков > количество отскоков/J    * Конец игры, когда количество бросков > количество отскоков/коэффициент
Строка 234: Строка 234:
   * Входной и выходной экран, задание J ''что имелось в виду под J?'' -- -- ArsenyMaslennikov <<DateTime(2017-07-20T20:17:34Z)>>    * Входной и Gameover экраны, повышение коэффициента при усложнении уровня

Декораторы. Полиморфизм, перегрузка операций. Наследование

Классы и перегрузка операций, повторение

{*} Класс «vector» на скорую руку

  • сложение векторов и с числом
    • выяснить тип операнда
  • умножение на вектор и на число
    • в т. ч. __rmul__

  • Не забыть делать именно вектор, type(self)(...)

  • vector.py

Декораторы

  • Преобразование списков... а функций?
  • Применяются обычно для добавления к функции (многим функциям) однотипных действий
  • {*} Пример — отладочная выдача параметров и возвращаемого значения

    • ручная реализация обёртки
    • прозрачная обёртка вида fun = wrapper(fun)

      • @wrapper

      • этот wrapper можно вешать на много разных функций

         1 """Пример декоратора, заставляющего функцию
         2 выводить свои параметры и возвращаемое значение
         3 """
         4 import sys
         5 
         6 def dumper(f):
         7     def dumpf(*ap, **an):
         8         print("", f, ap, an, file=sys.stderr)
         9         res = f(*ap, **an)
        10         print("", res, file=sys.stderr)
        11         return res
        12     return dumpf
        13 
        14 @dumper
        15 def fun(a, b, c):
        16     return a+b*2+c*3
        17 
        18 #fun = dumper(fun)    
        19     
        20 print(fun(1,2,3))
        21 print(fun("Q","W","E"))
      
  • {*} Пример: @integer (одно значение или последовательность)

    •    1 # написать декоратор, превращающий вещественные параметры
         2 # и вещественное возвращаемое значение функции в целочисленные
         3 # (также список вещественных в список целых)
         4 
         5 def integer(f):
         6     def intf(*args):
         7         newargs = (int(a) if type(a) is not int else a for a in args)
         8         res = f(*newargs)
         9         if type(res) in (list, tuple):
        10             return type(res)(int(c) if type(c) is not int else c for c in res)
        11         else:
        12             return int(res) if type(res) is not int else res 
        13     return intf
        14 
        15 @integer
        16 def newrange(a,b,n):
        17     return [a+(b-a)*i/(n-1) for i in range(n)]
        18 
        19 print(newrange(10.1000,20.111,"7"))
        20 
        21 @integer
        22 def sqsum(*args):
        23     return sum(a*a for a in args)
        24 
        25 print(sqsum(3.345, 4.4102, 5.503))
      
  • Декораторы классов и параметрические декораторы

Вывод изображений и текста в PyGame

  • surface
  • загрузка изображений, .convert()

  • Font, render()
  • Ввод текста в PyGame — ??

Инкапсуляция, наследование и полиморфизм

  • Инкапсуляция — иерархизация пространств имён
  • Наследование
  • {*} пример теоретический

       1 ndir = lambda obj: [l for l in dir(obj) if not l.startswith("_")]
       2 
       3 class C:
       4     value = None
       5     def __init__(self, arg):
       6         self.value = arg
       7         self.doux = arg*2
       8     def __str__(self):
       9         return "C: {}/{}".format(self.value, self.doux)
      10     def __add__(self, other): 
      11         return type(self)(self.value+other.value)
      12 
      13 class D(C):
      14     def __init__(self, arg):
      15         C.__init__(self, arg)
      16         self.another = arg
      17 
      18     def newfun(self):
      19         return self.doux
      20     
      21     def __str__(self):
      22         return "D: {}/{}/{}".format(self.value, self.doux, self.another)
      23 
      24 class Fake:
      25     value = 100500
      26     doux = 500100
      27     def __init__(self, *args):
      28         pass
      29 
      30 a = C(123) + C(567)
      31 print(type(a),a)
      32 
      33 b = D(432) + D(123)
      34 print(type(b),b)
      35 
      36 f = Fake()
      37 print(C(100)+f)
      38 print(C.__add__(f,f))
    
  • {*} перепишем последнюю программу с классом Square так, чтобы он был унаследован от pygame.Rect

  • Полиморфизм — в питоне сам собой по причине duck typing
  • {*} Оконная система

    • Класс «окно» — Rect + bg + show() (надо ли? + resize())
    • Класс «окно с рамочкой»
    • Класс «окно с заголовком»
    • Класс «окно с рамочкой и заголовком» (двойное наследование)
    • как их таскать или ресайзить
         1 # Класс «окно» — size + bg + show(pos)
         2 # Класс «окно с рамочкой»
         3 # Класс «окно с заголовком»
         4 # Класс «окно с рамочкой и заголовкам» (двойное наследование)
         5 # как их таскать
         6     
         7 import pygame
         8     
         9 class BaseWindow:
        10     '''Просто окно''' 
        11     def __init__(self, size, bgcolor):
        12         self.size = size
        13         self.color = pygame.Color(*bgcolor)
        14     
        15     def collide(self, coords, pos):
        16         return pygame.Rect(coords, self.size).collidepoint(pos)
        17 
        18     def show(self, surface, pos):
        19         '''Нарисовать окно на экране surface
        20         по координатам pos'''
        21         pygame.draw.rect(surface, self.color, (pos, self.size))
        22         
        23 class FramedWindow(BaseWindow):
        24     BSIZE = 4
        25     BCOLOR = (200,0,0)
        26     
        27     def show(self, surface, pos):
        28         BaseWindow.show(self, surface, pos)
        29         pygame.draw.rect(surface, self.BCOLOR, (pos, self.size), self.BSIZE)
        30 
        31 class DotWindow(BaseWindow):
        32     CCOLOR = (0,0,200)
        33     
        34     def show(self, surface, pos):
        35         BaseWindow.show(self, surface, pos)
        36         pygame.draw.ellipse(surface, self.CCOLOR, pygame.Rect(pos, self.size))
        37 
        38 class FDotWindow(FramedWindow, DotWindow):
        39     def show(self, surface, pos):
        40         FramedWindow.show(self, surface, pos)
        41         DotWindow.show(self, surface, pos)
        42 
        43 W, H = 640, 480
        44 pygame.init()
        45 screen = pygame.display.set_mode((W,H))
        46 
        47 Windows = [ [(10,10),BaseWindow((100,100),(0,0,100))],
        48             [(40,110),FramedWindow((100,100),(0,100,100))],
        49             [(110,20),BaseWindow((100,100),(100,0,100))],
        50             [(210,220),DotWindow((100,100),(100,0,100))],
        51             [(310,320),FDotWindow((100,100),(100,0,100))],            
        52 ]
        53 Drag, NDrag = None, 0
        54 
        55 while True:
        56     e = pygame.event.wait()
        57     if e.type == pygame.QUIT:
        58         break
        59     if e.type == pygame.MOUSEBUTTONDOWN:
        60         for num,(pos,w) in enumerate(Windows):
        61             if w.collide(pos, e.pos):
        62                 Drag, NDrag = w, num
        63     if e.type == pygame.MOUSEMOTION and e.buttons[0]:
        64         if Drag:
        65             Windows[NDrag][0]=e.pos
        66     if e.type == pygame.MOUSEBUTTONUP:
        67         Drag = None
        68 
        69     screen.fill((0,0,0))
        70     for pos,w in Windows:
        71         w.show(screen, pos)
        72     pygame.display.flip()
      

Структура аркадной (real-time) игровой программы

  • Игровой мир
    • Актёры
    • События с ними и миром
    • Свои единицы измерения
    • Часы (как минимум одни), понятие такта
  • Отображение мира
    • Низкоуровневые события (мышь, клавиатура, таймер и т. п.)
    • Координаты на экране
    • Отрисовка
  • Один такт работы:
    • Аккумуляция низкоуровневых событий (иногда с некоторой непосредственной реакцией)
    • Превращение их в события мира (в т. ч. выбор актёров, которым они предназначаются)
    • Обработка событий актёрами
    • Самостоятельная активность актёров и мира
    • Отрисовка результата
  • Режимы работы игры (например, intro, gameplay и gameover) — такт выглядит так же, а обработчики разные, => общие названия методов

  • {i} Игра в шары (к зачёту),

    • минимум:
      • Несколько шаров
      • Замедление скорости
      • Разлёт при соударении (массы одинаковы, а вот углы!)
      • Бросаем любой (но не несём, т. е. несём не больше 1/5 сек, дальше отпускаем со скоростью, вычисляемой из event.rel)
      • Считаем отскоки до полного останова
      • Конец игры, когда количество бросков > количество отскоков/коэффициент

    • Дополнения
      • Крутящиеся шары
      • гравитация
      • Входной и Gameover экраны, повышение коэффициента при усложнении уровня

Python/Summer2017/2017-07-13 (последним исправлял пользователь FrBrGeorge 2017-08-15 14:22:48)