Advertisement
boris-vlasenko

Платформер.Столкновение. Работает

Feb 25th, 2018
193
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 16.84 KB | None | 0 0
  1. from tkinter import *
  2. from random import randrange as rnd, choice
  3. from PIL import ImageTk, Image
  4. import os, sys
  5. import time
  6.  
  7.  
  8. #~ столкновение с блоками:
  9.     #~ если блок слева, тогда:
  10.         #~ если левая координата зашла за правую координату блока, то подвинуть
  11.     #~ если блок справа, тогда:
  12.         #~ если правая координата зашла за правую координату блока, то подвинуть
  13.     #~ если блок снизу, тогда:
  14.         #~ если нижняя координата зашла за верхнюю координату блока, то подвинуть (поставить на блок)
  15.     #~ ....
  16.    
  17.  
  18.    
  19.  
  20.  
  21. root = Tk()
  22. width = 900
  23. hight = 600
  24. padding = 50
  25. m = 40
  26. root.geometry(str(width)+'x'+str(hight)+'+100+100')
  27. canv = Canvas(bg='lightblue')
  28. canv.pack(fill=BOTH,expand=1)
  29.  
  30. '''
  31. прокручивается с миром или центр камеры
  32. останавливает игрока/врагов/пули
  33. можно разрушать (блоки и врагов)
  34. можно толкать (только блоки)
  35. враг (наносит урон)
  36. предмет (можно взять)
  37.  
  38. выносить свойства в отдельный класс только в том случае, если ими обладают и Блоки и Враги
  39. класс Разрушаемый
  40. класс НаносящийУрон поражает прикосновением любой стороны: шипы или враг
  41. класс Анимированный
  42.  
  43. класс Предмет можно взять
  44. класс Предмет2 (нельзя брать)
  45.  
  46. класс Враг(НаносящийУрон, Разрушаемый, Анимированный)
  47.     класс Черепаха, ЛетающаяЧерепаха, Череп и т.д. (виды врагов)
  48. класс Предмет()
  49. класс Монета(Предмет)
  50. класс Ключ(Предмет)
  51. класс Портал(Предмет2)
  52. класс Дверь(Предмет2) (перегородка)
  53. класс Лампа(Предмет2)
  54.  
  55. класс Блок() ограничивает движение
  56. класс РазрушаемыйБлок(Блок, Разрушаемый)
  57. класс ПадающийБлок(Блок)
  58. класс Платформа(Блок)
  59. класс РазрушаемаяПлатформа(Платформа,Разрушаемый)
  60. класс ТолкаемыйБлок(Блок)
  61. '''
  62.  
  63. '''
  64. 1. Блоки неподвижные
  65. 2. Блоки перемещаемые (могут падать)
  66. 3. Блоки разрушаемые
  67. 4. Блоки падающие
  68. 5. Блоки-платформы
  69. 6. Предметы, которые можно собирать (ключи, монеты)
  70. 7. Предметы, с которыми можно взаимодействовать (двери, кнопки)
  71. 8. Враги стоящие на месте
  72. 9. Враги ходящие туда-сюда
  73. 10. Враги летающие туда-сюда
  74.  
  75.  
  76. Объект:
  77.     1. Перемещается вместе с миром
  78.     2. Отрисовывать себя на экране
  79.     3. Пересечение с другими объектами (список)
  80.    
  81. Анимированный объект
  82.  
  83. '''
  84.  
  85. def pointInSegment(x,x1,x2):
  86.     return x1 <= x <= x2
  87.  
  88. def segmentInSegment(x1,x2,xx1,xx2):
  89.     return pointInSegment(x1,xx1,xx2) or pointInSegment(x2,xx1,xx2) or \
  90.     pointInSegment(xx1,x1,x2) or pointInSegment(xx2,x1,x2)
  91.  
  92. def rectInRect(x1,y1,x2,y2,xx1,yy1,xx2,yy2):
  93.     if segmentInSegment(x1,x2,xx1,xx2) and segmentInSegment(y1,y2,yy1,yy2):
  94.         return True
  95.     if segmentInSegment(xx1,xx2,x1,x2) and segmentInSegment(yy1,yy2,y1,y2):
  96.         return True
  97.     return False
  98.  
  99. class Base():
  100.     def __init__(self,*args,**kwargs):
  101.         pass
  102.        
  103.  
  104. class Object():
  105.     def __init__(self,x,y,**kwargs):
  106.         self.centerx = x
  107.         self.centery = y
  108.         imagePil = kwargs['images'][0]
  109.         self.w = imagePil.width()
  110.         self.h = imagePil.height()
  111.         self.x1 = x - self.w/2
  112.         self.y1 = y - self.h/2
  113.         self.x2 = self.x1 + self.w
  114.         self.y2 = self.y1 + self.h
  115.         self.imagePil = imagePil
  116.         self.vx = 0
  117.         self.vy = 0
  118.         self.image = canv.create_image(self.centerx,self.centery,image=self.imagePil)
  119.         super().__init__(**kwargs)
  120.         self.update()
  121.    
  122.     def paint(self):
  123.         canv.coords(self.image,self.centerx,self.centery)
  124.        
  125.     def update(self):
  126.         root.after(30,self.update)
  127.         self.x1 = self.centerx - self.w/2
  128.         self.y1 = self.centery - self.h/2
  129.         self.x2 = self.x1 + self.w
  130.         self.y2 = self.y1 + self.h
  131.  
  132.         self.paint()
  133.  
  134.  
  135. class MovableObject(Object,Base):
  136.     def __init__(self,x,y,**kwargs):
  137.         self.g = 1
  138.         self.onGround = False
  139.         self.active = True
  140.         self.left_stop = 10000
  141.         self.right_stop = 0
  142.         self.up_stop = 10000
  143.         self.down_stop = 0
  144.         super().__init__(x,y,**kwargs)
  145.        
  146.  
  147.     def collide(self,objects):
  148.         res = []
  149.         for item in objects:
  150.             nx1 = item.x1+item.vx
  151.             nx2 = item.x2+item.vx
  152.             ny1 = item.y1+item.vy
  153.             ny2 = item.y2+item.vy
  154.  
  155.             nxx1 = self.x1+self.vx
  156.             nxx2 = self.x2+self.vx
  157.             nyy1 = self.y1+self.vy
  158.             nyy2 = self.y2+self.vy
  159.  
  160.             if rectInRect(nx1,ny1,nx2,ny2,nxx1,nyy1,nxx2,nyy2):
  161.                 res.append(item)
  162.         return res
  163.  
  164.     def collide_first(self,objects):
  165.         for item in objects:
  166.             nx1 = item.x1+item.vx
  167.             nx2 = item.x2+item.vx
  168.             ny1 = item.y1+item.vy
  169.             ny2 = item.y2+item.vy
  170.  
  171.             nxx1 = self.x1+self.vx
  172.             nxx2 = self.x2+self.vx
  173.             nyy1 = self.y1+self.vy
  174.             nyy2 = self.y2+self.vy
  175.  
  176.             if rectInRect(nx1,ny1,nx2,ny2,nxx1,nyy1,nxx2,nyy2):
  177.                 return item
  178.    
  179.     def hitstop_(self,objects):
  180.         items =  self.collide(objects)
  181.         #self.onGround = False
  182.         #print(self.onGround)
  183.         if not items:
  184.             self.onGround = False
  185.            
  186.         for item in items:
  187.                 if self.vx > 0:
  188.                     self.vx = 0
  189.                     self.centerx = item.x1 - self.w/2
  190.                 elif self.vx < 0:
  191.                     self.vx = 0
  192.                     self.centerx = item.x2 + self.w/2
  193.                        
  194.                 if self.vy > 0:
  195.                     self.vy = 0
  196.                     self.onGround= True
  197.                     self.can_jump = True
  198.                     self.centery = item.y1 - self.h/2
  199.                      
  200.                 elif self.vy < 0:
  201.                     self.vy = 1
  202.                     self.centery = item.y2 + self.h/2
  203.                    
  204.                    
  205.     def hitstop__(self,objects):
  206.         #self.onGround = False
  207.         for item in objects:
  208.             nx1 = item.x1+item.vx
  209.             nx2 = item.x2+item.vx
  210.             ny1 = item.y1+item.vy
  211.             ny2 = item.y2+item.vy
  212.  
  213.             nxx1 = self.x1+self.vx
  214.             nxx2 = self.x2+self.vx
  215.             nyy1 = self.y1+self.vy
  216.             nyy2 = self.y2+self.vy
  217.  
  218.             if rectInRect(nx1,ny1,nx2,ny2,nxx1,nyy1,nxx2,nyy2):
  219.                 item.r = (item.centery-padding)//m
  220.                 item.c = (item.centerx-padding)//m
  221.                 self.r = (self.centery-padding)//m
  222.                 self.c = (self.centerx-padding)//m
  223.                 dr = item.r - self.r
  224.                 dc = item.c - self.c
  225.                 if dr == 0:
  226.                     if dc == 0:
  227.                         dx = item.centerx - self.centerx
  228.                         dy = item.centery - self.centery
  229.                         if dx > dy:
  230.                             if dx > 0:
  231.                                 dc = 1
  232.                             else:
  233.                                 dc = -1
  234.                         else:
  235.                             if dy > 0:
  236.                                 dr = 1
  237.                             else:
  238.                                 dr = -1
  239.                         #print(self.vx,self.vy)
  240.                         canv.create_rectangle(item.x1,item.y1,item.x2,item.y2, outline = 'red', width = 5, tag = 'temp')
  241.  
  242.                     if dc > 0:
  243.                         self.centerx = item.x1 - self.w/2-1
  244.                         self.vx = 0
  245.                     elif dc < 0:
  246.                         self.centerx = item.x2 + self.w/2+1
  247.                         self.vx = 0
  248.  
  249.                 if dr > 0:
  250.                     self.vy = 0
  251.                     self.centery = item.y1 - self.h/2-1
  252.                     self.can_jump = True
  253.                    
  254.                 elif dr < 0:
  255.                     self.vy = 0
  256.                     self.centery = item.y2 + self.h/2+1
  257.                    
  258.     def hitstop(self,objects):
  259.         for item in objects:
  260.             item.r = (item.centery-padding)//m
  261.             item.c = (item.centerx-padding)//m
  262.             self.r = (self.centery-padding)//m
  263.             self.c = (self.centerx-padding)//m
  264.             dr = item.r - self.r
  265.             dc = item.c - self.c
  266.             canv.create_rectangle(self.x1+self.vx,self.y1+self.vy,self.x2+self.vx,self.y2+self.vy, outline = 'orange', width = 1, tag = 'temp')
  267.             if segmentInSegment(self.y1+2,self.y2-2,item.y1+2,item.y2-2) and -1 <= dc <= 0 : # блок слева
  268.                 canv.create_rectangle(item.x1,item.y1,item.x2,item.y2, outline = 'green', width = 5, tag = 'temp')
  269.                 if self.x1+self.vx < item.x2:
  270.                     canv.create_rectangle(item.x1,item.y1,item.x2,item.y2, fill = 'green', tag = 'temp')
  271.                     if self.vx < 0:
  272.                         self.vx = 0
  273.                     self.centerx = item.x2 + self.w/2 + 1
  274.                    
  275.             if segmentInSegment(self.y1+2,self.y2-2,item.y1+2,item.y2-2) and dc == 1: # блок справа
  276.                 canv.create_rectangle(item.x1,item.y1,item.x2,item.y2, outline = 'yellow', width = 5, tag = 'temp')
  277.                 if self.x2+self.vx > item.x1:
  278.                     canv.create_rectangle(item.x1,item.y1,item.x2,item.y2, fill = 'yellow', tag = 'temp')
  279.                     if self.vx > 0:
  280.                         self.vx = 0
  281.                     self.centerx = item.x1 - self.w/2 - 1
  282.                    
  283.             if -1 <= dr <= 0 and segmentInSegment(self.x1+2,self.x2-2,item.x1+2,item.x2-2): # блок сверху
  284.                 canv.create_rectangle(item.x1,item.y1,item.x2,item.y2, outline = 'red', width = 5, tag = 'temp')
  285.                 if self.y1+self.vy < item.y2:
  286.                     canv.create_rectangle(item.x1,item.y1,item.x2,item.y2, fill = 'red', tag = 'temp')
  287.                     if self.vy < 0:
  288.                         self.vy = 0
  289.                     self.centery = item.y2 + self.h/2 + 1
  290.    
  291.             if dr == 1 and segmentInSegment(self.x1+2,self.x2-2,item.x1+2,item.x2-2): # блок снизу
  292.                 canv.create_rectangle(item.x1,item.y1,item.x2,item.y2, outline = 'blue', width = 5, tag = 'temp')
  293.                 if self.y2+self.vy > item.y1:
  294.                     canv.create_rectangle(item.x1,item.y1,item.x2,item.y2, fill = 'blue', tag = 'temp')
  295.                     self.can_jump = True
  296.                     if self.vy > 0:
  297.                         self.vy = 0
  298.                     self.centery = item.y1 - self.h/2
  299.        
  300.     def update(self):
  301.         if self.active:
  302.  
  303.             self.vy += self.g
  304.             self.centerx += self.vx
  305.             self.centery += self.vy
  306.  
  307.             self.hitstop(blocks)
  308.            
  309.             self.x1 = self.centerx - self.w/2
  310.             self.y1 = self.centery - self.h/2
  311.             self.x2 = self.x1 + self.w
  312.             self.y2 = self.y1 + self.h
  313.            
  314.         super().update()
  315.  
  316. class Animation():
  317.     def __init__(self,**kwargs):
  318.         super().__init__(**kwargs)
  319.         self.images = kwargs['images']
  320.         self.frame = 0
  321.         self.pause = kwargs['pause']
  322.         self.active_animation = True
  323.         self.update_animation()
  324.    
  325.     def update_animation(self):
  326.         if self.active_animation:
  327.             self.frame += 1
  328.             if self.frame >= len(self.images):
  329.                 self.frame = 0
  330.             canv.itemconfig(self.image,image=self.images[self.frame])
  331.             self.paint()
  332.         root.after(self.pause,self.update_animation)
  333.        
  334. class Player(MovableObject,Animation,Base):
  335.     def __init__(self,x,y,**kwargs):
  336.         self.keys = set()
  337.         self.id_vx = canv.create_text(100,100,text = '', font ='Arial 40')
  338.         self.id_vy = canv.create_text(100,145,text = '', font ='Arial 40')
  339.         super().__init__(x,y,**kwargs)
  340.         self.bullets = []
  341.         self.points = 0
  342.         self.can_jump = True
  343.         #self.id_vx = canv.create_text(100,100,text = self.vx, font ='Arial 40')
  344.    
  345.     def pickup_coin(self,coin):
  346.         self.points += coin.value
  347.        
  348.     def shot(self,vx,vy):  
  349.         self.bullets.append(Bullet(self.x,self.y,vx,vy))
  350.    
  351.     def update_info(self):
  352.         canv.itemconfig(self.id_vx,text = self.vx)
  353.         canv.itemconfig(self.id_vy,text = self.vy)
  354.    
  355.     def update(self):
  356.         self.vx = 0
  357.         if 'left' in self.keys:
  358.             self.vx = -5
  359.         if 'right' in self.keys:
  360.             self.vx = +5
  361.         if 'down' in self.keys:
  362.             self.vy = +5
  363.         if 'up' in self.keys:
  364.             self.vy = -5
  365.         if 'jump' in self.keys:
  366.             if self.can_jump:
  367.                 self.can_jump = False
  368.                 self.vy = -25
  369.         super().update()
  370.        
  371.         self.update_info()
  372.        
  373.         #~ if self.centerx > 600:
  374.             #~ dx = 600 - self.centerx
  375.             #~ self.centerx = 600
  376.             #~ for item in world:
  377.                 #~ item.centerx += dx
  378.                 #~ item.paint()
  379.         #~ if self.centerx < 300:
  380.             #~ dx = 300 - self.centerx
  381.             #~ self.centerx = 300
  382.             #~ for item in world:
  383.                 #~ item.centerx += dx
  384.                 #~ item.paint()
  385.         #~ if self.centery > 500:
  386.             #~ dy = 500 - self.centery
  387.             #~ self.centery = 500
  388.             #~ for item in world:
  389.                 #~ item.centery += dy
  390.                 #~ item.paint()
  391.         #~ if self.centery < 200:
  392.             #~ dy = 200 - self.centery
  393.             #~ self.centery = 200
  394.             #~ for item in world:
  395.                 #~ item.centery += dy
  396.                 #~ item.paint()
  397.         #self.active = False
  398.  
  399. class Bullet():
  400.     def __init__(self,x,y,vx,vy):
  401.         self.x = x
  402.         self.y = y
  403.         self.r = 3
  404.         self.w = self.r
  405.         self.h = self.r
  406.         self.vx = vx
  407.         self.vy = vy   
  408.         self.g = 1
  409.         self.active = True
  410.         self.id = canv.create_oval(self.x-self.r,self.y-self.r,self.x+self.r,self.y+self.r,fill='gray')
  411.         self.update()
  412.    
  413.     def update(self):
  414.         self.vy += 0.8
  415.         self.y += self.vy
  416.         self.x += self.vx
  417.         canv.coords(self.id,self.x-self.r,self.y-self.r,self.x+self.r,self.y+self.r)   
  418.         for enemy in enemies:
  419.             if self.x-enemy.r <= enemy.x <= self.x+self.w+enemy.r and self.y-enemy.r <= enemy.y <= self.y + self.h + enemy.r:  
  420.                 enemy.kill()
  421.                 self.kill()
  422.         if self.active:
  423.             root.after(30,self.update)
  424.        
  425.     def kill(self):
  426.         canv.delete(self.id)
  427.         self.active = False
  428.         if self in player.bullets:
  429.             player.bullets.remove(self)
  430.  
  431. class Enemy(MovableObject,Animation,Base):
  432.     def __init__(self,x,y,**kwargs):
  433.         super().__init__(x,y,**kwargs)
  434.         self.vx = -3
  435.        
  436.     def kill(self):
  437.         canv.delete(self.id)
  438.         world.remove(self)
  439.         enemies.remove(self)
  440.         self.active = False
  441.  
  442. class Block(Object,Base):
  443.     def __init__(self,x,y,**kwargs):
  444.         super().__init__(x,y,**kwargs)
  445.        
  446.     #~ def update(self):
  447.         #~ for unit in enemies + [player]:
  448.             #~ hitside = self.hittest([unit])
  449.             #~ dx = 5
  450.             #~ dy = 1
  451.             #~ # ~ if hitside:
  452.                 #~ # ~ print(hitside)
  453.             #~ if hitside == 'up':
  454.                 #~ unit.vy = 0
  455.                 #~ unit.centery = self.y1-unit.h/2-dy
  456.                 #~ unit.can_jump = True
  457.             #~ if hitside == 'down':
  458.                 #~ unit.vy = 0
  459.                 #~ unit.centery = self.y2 + unit.h/2 + dy
  460.             #~ if hitside == 'left':
  461.                 #~ unit.vx = 0
  462.                 #~ unit.centerx = self.x1 - unit.w/2 - dx
  463.                 #~ # ~ canv.create_rectangle(self.x1,self.y1,self.x2,self.y2)
  464.                 #~ # ~ canv.create_rectangle(unit.x1,unit.y1,unit.x2,unit.y2,outline='orange')
  465.                 #~ # ~ unit.active = False
  466.             #~ if hitside == 'right':
  467.                 #~ unit.vx = 0
  468.                 #~ unit.centerx = self.x2 + unit.w/2 + dx
  469.         #~ super().update()
  470.    
  471. class Coin(Object,Animation,Base):
  472.     def __init__(self,x,y,**kwargs):
  473.         self.value = 1
  474.         super().__init__(x,y,**kwargs)
  475.         self.update()
  476.  
  477.     # ~ def update(self):
  478.         # ~ if self.hittest([player]):
  479.             # ~ player.pickup_coin(self)
  480.             # ~ self.kill()
  481.         # ~ else:
  482.             # ~ root.after(30,self.update)     
  483.            
  484.     def kill(self):
  485.         pass
  486.         #canv.delete(self.image)
  487.         #world.remove(self)
  488.        
  489. blocks = []    
  490. coin_images = []
  491.  
  492. for i in range(1,7):
  493.     coin_image = Image.open('coin'+str(i)+'.png').resize((m,m),Image.ANTIALIAS)
  494.     coin_images.append(ImageTk.PhotoImage(image=coin_image))
  495.     #canv.create_image(100+i*50,100,image=coin_images[-1])
  496.  
  497. enemy_images = []
  498. for i in range(1,2):
  499.     enemy_image = Image.open('enemy.png').resize((m,m),Image.ANTIALIAS)
  500.     enemy_images.append(ImageTk.PhotoImage(image=enemy_image))
  501.  
  502.    
  503. player_images = []
  504. player_image = Image.open('enemy.png').resize((30,30),Image.ANTIALIAS)
  505. player_images.append(ImageTk.PhotoImage(image=player_image))
  506.  
  507.  
  508. block_image = Image.open('block.png').resize((m,m),Image.ANTIALIAS)
  509. block_image = ImageTk.PhotoImage(image=block_image)
  510.        
  511. player = Player(300,300,images=player_images,pause=150)
  512. f = open('map1.py','r')
  513. r = 0
  514. x0 = 10
  515. y0 = 10
  516.  
  517.  
  518. world = []
  519. enemies =  []
  520. blocks = []
  521.  
  522. for line in f.readlines():
  523.     c = 0
  524.     for block in line.strip():
  525.         x = x0 + c*m
  526.         y = y0 + r*m
  527.         if block == '1':
  528.             block = Block(x,y,images=[block_image])
  529.             world.append(block)
  530.             blocks.append(block)
  531.         elif block == 'c':
  532.             world.append(Coin(x,y,images=coin_images,pause=100))
  533.         #~ elif block == 'e':
  534.             #~ en = Enemy(x,y,images=enemy_images,pause=100)
  535.             #~ enemies.append(en)
  536.             #~ world.append(en)
  537.         c += 1
  538.     r += 1
  539.  
  540. f.close()
  541.  
  542. def clearTemp():
  543.     canv.delete('temp')
  544.     root.after(3000,clearTemp)
  545. clearTemp()
  546.  
  547. def keyDown(event):
  548.     if event.keycode == 37  or event.keycode == 113:
  549.         player.keys.add('left')
  550.     if event.keycode == 39  or event.keycode == 114:
  551.         player.keys.add('right')
  552.     if event.keycode == 38  or event.keycode == 111:
  553.         player.keys.add('jump')
  554.     if event.keycode == 40  or event.keycode == 116:
  555.         player.keys.add('down')
  556.  
  557. def keyUp(event):
  558.     if event.keycode == 37 or event.keycode == 113:
  559.         if 'left' in player.keys:
  560.             player.keys.remove('left')
  561.     if event.keycode == 39  or event.keycode == 114:
  562.         if 'right' in player.keys:
  563.             player.keys.remove('right')
  564.     if event.keycode == 38  or event.keycode == 111:
  565.         if 'jump' in player.keys:
  566.             player.keys.remove('jump')
  567.         if 'up' in player.keys:
  568.             player.keys.remove('up')
  569.     if event.keycode == 40  or event.keycode == 116:
  570.         if 'down' in player.keys:
  571.             player.keys.remove('down')
  572.            
  573. def mm(event):
  574.     player.active = True
  575.    
  576. def click(event):  
  577.     #~ vx = (event.x - player.x)/10
  578.     #~ vy = (event.y - player.y)/10
  579.     #~ player.shot(vx,vy)
  580.     player.active = True
  581.  
  582.  
  583. canv.bind('<1>',click)
  584. canv.bind('<Motion>',mm)
  585. root.bind('<Key>',keyDown)
  586. root.bind('<KeyRelease>',keyUp)
  587.  
  588. mainloop()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement