Advertisement
Guest User

SHNAEK

a guest
Jul 8th, 2015
69
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 22.74 KB | None | 0 0
  1. from xors3d import *
  2. import time, math, random
  3.  
  4. # some constants that should not be constants actually
  5. BLOCK_SIZE = 20
  6. FIELD_SIZE = 17
  7. TOP_OFFSET = 40
  8.  
  9. # random shit
  10. def randomizePosition(pos):
  11.     pos.x = random.randint(1, FIELD_SIZE - 2) * BLOCK_SIZE
  12.     pos.y = random.randint(1, FIELD_SIZE - 2) * BLOCK_SIZE + TOP_OFFSET
  13.     # how should I detect collisions with player?
  14.  
  15. class AppClose(Exception):
  16.     pass
  17.  
  18.  
  19. class PlayerDed(Exception):
  20.     def __init__(self, score):
  21.         self.score = score
  22.  
  23.  
  24. def addSegment(tail, world):
  25.     '''Oh, dog, this whole function suck so much you have no idea'''
  26.     em = world.entityManager
  27.     entity = em.createEntity()
  28.  
  29.     if tail.numSegments > 0:
  30.         pos = world.entityManager.getComponent(tail.segments[-1], Position)
  31.     else:
  32.         pos = world.entityManager.getComponent(tail.owner, Position)
  33.  
  34.     em.addComponent(entity, Position(pos.x, pos.y))
  35.     em.addComponent(entity, Shape('square', BLOCK_SIZE, BLOCK_SIZE, 0xff00aa00))
  36.     em.addComponent(entity, Name('tail'))
  37.     em.addComponent(entity, BBox(BLOCK_SIZE, BLOCK_SIZE))
  38.  
  39.     tail.numSegments += 1
  40.     tail.segments.append(entity)
  41.  
  42.  
  43. def loadTestImage():
  44.     return xLoadImage('images/sand48.png')
  45.  
  46.  
  47. def GetDrawingColor():
  48.     return xColorRed(), xColorGreen(), xColorBlue(), xColorAlpha()
  49.  
  50.  
  51. def alpha(clr):
  52.     return (clr >> 24) & 0xff
  53.  
  54.  
  55. def red(clr):
  56.     return (clr >> 16) & 0xff
  57.  
  58.  
  59. def green(clr):
  60.     return (clr >> 8) & 0xff
  61.  
  62.  
  63. def blue(clr):
  64.     return clr & 0xff
  65.  
  66.  
  67. def mkcolor(a, r, g, b):
  68.     return ((a & 0xff) << 24 |
  69.            (r & 0xff) << 16 |
  70.            (g & 0xff) << 8 |
  71.            b & 0xff)
  72.  
  73.  
  74. # components
  75. class MouseResponce(object):
  76.     def __init__(self, btn, resp):
  77.         self.button = btn
  78.         self.action = resp
  79.  
  80.  
  81. class TextInfo(object):
  82.     def __init__(self, text, getter):
  83.         self.text = text
  84.         self.getter = getter
  85.  
  86.  
  87. class Tail(object):
  88.     def __init__(self, owner):
  89.         self.numSegments = 0
  90.         self.segments = []
  91.         self.owner = owner
  92.  
  93.  
  94. class AlphaBlink(object):
  95.     pass
  96.  
  97.  
  98. class BBox(object):
  99.     def __init__(self, width, height):
  100.         self.width = width
  101.         self.height = height
  102.  
  103.  
  104. class Physics(object):
  105.     '''Determines if object can be collided and type of collision
  106.    or smth like that'''
  107.     def __init__(self, colType):
  108.         self.colType = colType
  109.  
  110.  
  111. class Collided(object):
  112.     def __init__(self, other):
  113.         self.other = other
  114.  
  115.  
  116. class Name(object):
  117.     def __init__(self, name):
  118.         self.name = name
  119.  
  120.  
  121. class Score(object):
  122.     def __init__(self):
  123.         self.score = 0
  124.  
  125.  
  126. class Harmful(object):
  127.     pass
  128.  
  129.  
  130. class Harmless(object):
  131.     pass
  132.  
  133.  
  134. class Destructible(object):
  135.     pass
  136.  
  137.  
  138. class Shape(object):
  139.     def __init__(self, shape, width, height, color):
  140.         self.shape = shape
  141.         self.width = width
  142.         self.height = height
  143.         self.color = color
  144.  
  145.  
  146. class Image(object):
  147.     '''Unused'''
  148.     def __init__(self, img):
  149.         self.image = img
  150.  
  151.  
  152. class Position(object):
  153.     def __init__(self, x, y):
  154.         self.x = x
  155.         self.y = y
  156.  
  157.  
  158. class KeyboardController(object):
  159.     pass
  160.  
  161.  
  162. class Direction(object):
  163.     def __init__(self, dx, dy):
  164.         self.dx = dx
  165.         self.dy = dy
  166.  
  167.  
  168. class Speed(object):
  169.     def __init__(self, speed):
  170.         self.speed = speed
  171.  
  172.  
  173. # systems
  174.  
  175. # DON'T DO THIS AT HOME
  176. # THIS IS SOME QUICK WAY TO FIX SHIT
  177. can_act = False
  178.  
  179.  
  180. class TailController(object):
  181.     def __init__(self):
  182.         pass
  183.  
  184.  
  185.     def update(self, world):
  186.         if not can_act:
  187.             return
  188.  
  189.         all = world.getAll((Tail,))
  190.         # basically, do not append Tail for smth that isn't player, lol
  191.         # I can ask for Position and Direction also
  192.         for i in all:
  193.             tail = world.entityManager.getComponent(i, Tail)
  194.             pos = world.entityManager.getComponent(tail.owner, Position)
  195.             direct = world.entityManager.getComponent(tail.owner, Direction)
  196.             prevx, prevy = pos.x - BLOCK_SIZE * direct.dx, pos.y - BLOCK_SIZE * direct.dy
  197.             for j in tail.segments:
  198.                 pos = world.entityManager.getComponent(j, Position)
  199.                 pos.x, pos.y, prevx, prevy = prevx, prevy, pos.x, pos.y # WHAT?
  200.  
  201.             if (tail.numSegments > 0 and
  202.                         world.entityManager.getComponent(tail.segments[-1], Physics) is None):
  203.                 world.entityManager.addComponent(j, Physics(Harmful))
  204.                
  205.  
  206. class TextRenderer(object):
  207.     def __init__(self):
  208.         pass
  209.  
  210.  
  211.     def update(self, world):
  212.         all = world.getAll((TextInfo,))
  213.         for i in all:
  214.             pos = world.entityManager.getComponent(i, Position)
  215.             text = world.entityManager.getComponent(i, TextInfo)
  216.             if text.getter:
  217.                 xText(pos.x, pos.y, text.text + text.getter())
  218.             else:
  219.                 xText(pos.x, pos.y, text.text)
  220.  
  221.  
  222. class ArrowControls(object):
  223.     def __init__(self):
  224.         pass
  225.  
  226.  
  227.     def update(self, world):
  228.         all = world.getAll((Direction, KeyboardController))
  229.  
  230.         xd = (xKeyDown(KEY_RIGHT) - xKeyDown(KEY_LEFT))
  231.         yd = (xKeyDown(KEY_DOWN) - xKeyDown(KEY_UP))
  232.  
  233.         if xd == yd == 0:
  234.             return
  235.  
  236.         for i in all:
  237.             dir = world.entityManager.getComponent(i, Direction)
  238.             dir.dx = xd
  239.             dir.dy = yd
  240.  
  241.  
  242. class EscapeHandler(object):
  243.     def __init__(self):
  244.         pass
  245.  
  246.  
  247.     def update(self, world):
  248.         if xKeyHit(KEY_ESCAPE):
  249.             raise AppClose() # nice hack
  250.  
  251.  
  252. class XorsRenderer(object):
  253.     def __init__(self):
  254.         xGraphics3D(FIELD_SIZE * BLOCK_SIZE, TOP_OFFSET + FIELD_SIZE * BLOCK_SIZE)
  255.  
  256.  
  257.     def update(self, world):
  258.         all = world.getAll((Position, Shape))
  259.         xCls()
  260.         prevColor = GetDrawingColor()
  261.         for i in all:
  262.             pos = world.entityManager.getComponent(i, Position)
  263.             shape = world.entityManager.getComponent(i, Shape)
  264.             clr = shape.color
  265.             if shape.shape == 'square':
  266.                 xColor(red(clr), green(clr), blue(clr), alpha(clr))
  267.                 xRect(pos.x, pos.y, shape.width, shape.height, True)
  268.                 # xColor(0x77, 0x77, 0x77)
  269.                 # xRect(pos.x, pos.y, shape.width, shape.height, False)
  270.             else:
  271.                 raise ValueError('Invalid shape ' + shape)
  272.  
  273.         xColor(*prevColor)
  274.  
  275.         # xRenderWorld()
  276.         # xText(5, 5, 'Fps: ' + str(xGetFPS()))
  277.  
  278.  
  279.     def endFrame(self):
  280.         xFlip()
  281.  
  282.  
  283. class ContinuousMotion(object):
  284.     def __init__(self):
  285.         self.lastUpdate = xMillisecs()
  286.  
  287.  
  288.     def update(self, world):
  289.         global can_act
  290.         time = xMillisecs()
  291.  
  292.         if time - self.lastUpdate >= 150:
  293.             self.lastUpdate = time
  294.             can_act = True
  295.         else:
  296.             can_act = False
  297.             return
  298.  
  299.         # this is boilerplate code
  300.         # those next 4 (+/-) lines will be in every system
  301.         # so update() should receive all the entities and components somehow
  302.         all = world.getAll((Position, Direction, Speed))
  303.         for i in all:
  304.             pos = world.entityManager.getComponent(i, Position)
  305.             dir = world.entityManager.getComponent(i, Direction)
  306.  
  307.             spd = world.entityManager.getComponent(i, Speed).speed
  308.             pos.x += dir.dx * spd
  309.             pos.y += dir.dy * spd
  310.  
  311.  
  312. class CollisionDetection(object):
  313.     def __init__(self):
  314.         pass
  315.  
  316.  
  317.     def update(self, world):
  318.         if not can_act: return # FIXME: HACK
  319.         # if has Physics then can be collided
  320.         # if no then we do not care if it has BBox or not
  321.         all = world.getAll((Physics, Position, BBox))
  322.         i = 0
  323.         la = len(all)
  324.         while i < la:
  325.             p1 = world.entityManager.getComponent(all[i], Position)
  326.             b1 = world.entityManager.getComponent(all[i], BBox)
  327.             j = i + 1
  328.             while j < la:
  329.                 p2 = world.entityManager.getComponent(all[j], Position)
  330.                 b2 = world.entityManager.getComponent(all[j], BBox)
  331.                 if xRectsOverlap(p1.x, p1.y, b1.width, b1.height,
  332.                                  p2.x, p2.y, b2.width, b2.height):
  333.                     world.addComponent(all[i], Collided(all[j]))
  334.                     world.addComponent(all[j], Collided(all[i]))
  335.                 j += 1
  336.             i+=1
  337.  
  338.  
  339. class CollisionResponce(object):
  340.     def __init__(self):
  341.         pass
  342.  
  343.  
  344.     def update(self, world):
  345.         if not can_act: return # FIXME: HACK
  346.  
  347.         all = world.getAll((Collided,))
  348.         for i in all:
  349.             other = world.entityManager.getComponent(i, Collided).other
  350.             # if it's collided then it have Physics
  351.             ct = world.entityManager.getComponent(other, Physics).colType
  352.             if ct == Harmful:
  353.                 # print world.entityManager.getComponent(i, Name).name.capitalize(),\
  354.                 #     'collided hard with', world.entityManager.getComponent(other, Name).name
  355.                
  356.                 if world.entityManager.getComponent(i, KeyboardController):
  357.                     world.removeComponent(i, Collided)
  358.                     raise PlayerDed(world.entityManager.getComponent(i, Score).score)
  359.  
  360.  
  361.             elif ct == Destructible:
  362.                 # TODO: place food at random position and update user score
  363.                 pos = world.entityManager.getComponent(other, Position)
  364.                 randomizePosition(pos)
  365.  
  366.                 # this should be in some score managing system (maybe?)
  367.                 # or will events be better?
  368.                 score = world.entityManager.getComponent(i, Score)
  369.                 if score: # if object has no score component then just ignore it
  370.                     score.score += 20
  371.  
  372.                 # oh, boy...
  373.                 tail = world.entityManager.getComponent(i, Tail)
  374.                 if tail:
  375.                     addSegment(tail, world)
  376.  
  377.  
  378.             world.removeComponent(i, Collided)
  379.  
  380.  
  381. class MouseHandler(object):
  382.     def __init__(self):
  383.         pass
  384.  
  385.  
  386.     def update(self, world):
  387.         # I NEED POST UPDATE
  388.         ml, mr = xMouseDown(MOUSE_LEFT), xMouseDown(MOUSE_RIGHT)
  389.         xFlushMouse()
  390.         if ml == mr == 0: return
  391.         mx, my = xMouseX(), xMouseY()
  392.         all = world.getAll((MouseResponce, BBox, Position))
  393.         for i in all:
  394.             resp = world.entityManager.getComponent(i, MouseResponce)
  395.             bbox = world.entityManager.getComponent(i, BBox)
  396.             pos  = world.entityManager.getComponent(i, Position)
  397.  
  398.             if (((resp.button == MOUSE_LEFT and ml) or (resp.button == MOUSE_RIGHT and mr)) # this was better, but I need to flush
  399.                 and
  400.                 (pos.x <= mx <= pos.x + bbox.width and pos.y <= my <= pos.y + bbox.height)):
  401.                 resp.action()
  402.                 return
  403.  
  404.  
  405. class AlphaWave(object):
  406.     def __init__(self):
  407.         pass
  408.  
  409.  
  410.     def update(self, world):
  411.         if not can_act: return # FIXME: HACK
  412.  
  413.         all = world.getAll((Shape, AlphaBlink))
  414.         for i in all:
  415.             shape = world.entityManager.getComponent(i, Shape)
  416.             shape.color = ((int(math.cos(xMillisecs() / 100.0) * 200 + 55) << 24) |
  417.                 (shape.color & 0xffffff)) # why is this shit working weird?
  418.  
  419.  
  420. # managers
  421. class World(object):
  422.     def __init__(self):
  423.         self.systems = []
  424.         self.entityManager = None
  425.  
  426.    
  427.     # def getComponent(self, entity, component):
  428.     #     return self.entityManager.getComponent(entity, component)
  429.  
  430.  
  431.     def addComponent(self, entity, component):
  432.         self.entityManager.addComponent(entity, component)
  433.  
  434.  
  435.     def removeComponent(self, entity, component):
  436.         self.entityManager.removeComponent(entity, component)
  437.  
  438.  
  439.     def getAll(self, components):
  440.         comp = components[0]
  441.         entities = self.entityManager.get(comp)
  442.         for i in components[1:]: # this sucks
  443.             entities = self.entityManager.filter(entities, i)
  444.  
  445.         return entities
  446.  
  447.    
  448.     def registerSystem(self, info):
  449.         # info is (priority, system) pair
  450.         self.systems.append(info)
  451.         self.systems.sort(key=lambda x: x[0])
  452.  
  453.    
  454.     def setEntityManager(self, manager):
  455.         self.entityManager = manager
  456.  
  457.    
  458.     def update(self):
  459.         for _, system in self.systems:
  460.             system.update(self)
  461.  
  462.         time.sleep(1.0/120) # I'm losing 40 (80 with 30 objects) fps just because of python
  463.  
  464.  
  465. class EntityManager(object):
  466.     def __init__(self):
  467.         self.entities = set()
  468.  
  469.         # a lot of empty big arrays
  470.         # probably should use dictionaries (not lists) with entity->component mapping
  471.         self.comps = {
  472.             Position.__name__: [],
  473.             # Image.__name__: [],
  474.             KeyboardController.__name__: [],
  475.             Shape.__name__: [],
  476.             Direction.__name__: [],
  477.             Speed.__name__: [],
  478.             BBox.__name__: [],
  479.             Physics.__name__: [],
  480.             Collided.__name__: [],
  481.             Name.__name__: [],
  482.             AlphaBlink.__name__: [],
  483.             Score.__name__: [],
  484.             Tail.__name__: [],
  485.             TextInfo.__name__: [],
  486.             MouseResponce.__name__: []
  487.         }
  488.  
  489.  
  490.     # def getArray(self, component):
  491.     #     return self.comps[component.__name__]
  492.  
  493.    
  494.     def addComponent(self, entity, component):
  495.         array = self.comps[component.__class__.__name__]
  496.         while len(array) <= entity:
  497.             array.append(None)
  498.  
  499.         array[entity] = component
  500.  
  501.  
  502.     def removeComponent(self, entity, component):
  503.         # array = self.getArray(component)
  504.         array = self.comps[component.__name__]
  505.         array[entity] = None
  506.  
  507.  
  508.     def getComponent(self, entity, component):
  509.         # array = self.getArray(component)
  510.         array = self.comps[component.__name__]
  511.  
  512.         if len(array) <= entity:
  513.             return None
  514.  
  515.         return array[entity]
  516.  
  517.  
  518.     def get(self, component):
  519.         # array = self.getArray(component)
  520.         array = self.comps[component.__name__]
  521.  
  522.         return [i for i, x in enumerate(array) if not x is None] # this sucks
  523.  
  524.  
  525.     def filter(self, entities, component):
  526.         # array = self.getArray(component)
  527.         array = self.comps[component.__name__]
  528.  
  529.         length = len(array)
  530.         return [i for i in entities if length > i if not array[i] is None] # this sucks too
  531.  
  532.  
  533.     def createEntity(self):
  534.         i = 0 # yeah, itertools, but too lazy to search for docs
  535.         while True:
  536.             if i not in self.entities:
  537.                 self.entities.add(i)
  538.                 return i
  539.             i += 1
  540.    
  541.  
  542.     def destroyEntity(self, entity):
  543.         self.entities.remove(entity)
  544.         for name in self.comps:
  545.             arr = self.comps[name]
  546.             if len(arr) > entity:
  547.                 arr[entity] = None
  548.  
  549.  
  550. # main function
  551. def main():
  552.     renderer = XorsRenderer() # should be created first
  553.  
  554.     world = World()
  555.     em = EntityManager()
  556.     world.setEntityManager(em)
  557.  
  558.     # because I don't know how to bump player to the front
  559.     for i in xrange(FIELD_SIZE):
  560.         entity = em.createEntity()
  561.         em.addComponent(entity, Shape('square', BLOCK_SIZE, BLOCK_SIZE, 0xffff0000))
  562.         em.addComponent(entity, Position(i * BLOCK_SIZE, TOP_OFFSET))
  563.         em.addComponent(entity, BBox(BLOCK_SIZE, BLOCK_SIZE))
  564.         em.addComponent(entity, Physics(Harmful))
  565.         em.addComponent(entity, Name('block'))
  566.  
  567.         entity = em.createEntity()
  568.         em.addComponent(entity, Shape('square', BLOCK_SIZE, BLOCK_SIZE, 0xffff0000))
  569.         em.addComponent(entity, Position(i * BLOCK_SIZE, TOP_OFFSET + (FIELD_SIZE - 1) * BLOCK_SIZE))
  570.         em.addComponent(entity, BBox(BLOCK_SIZE, BLOCK_SIZE))
  571.         em.addComponent(entity, Physics(Harmful))
  572.         em.addComponent(entity, Name('block'))
  573.  
  574.     for i in xrange(FIELD_SIZE - 2):
  575.         entity = em.createEntity()
  576.         em.addComponent(entity, Shape('square', BLOCK_SIZE, BLOCK_SIZE, 0xffff0000))
  577.         em.addComponent(entity, Position(0, TOP_OFFSET + i * BLOCK_SIZE + BLOCK_SIZE))
  578.         em.addComponent(entity, BBox(BLOCK_SIZE, BLOCK_SIZE))
  579.         em.addComponent(entity, Physics(Harmful))
  580.         em.addComponent(entity, Name('block'))
  581.  
  582.         entity = em.createEntity()
  583.         em.addComponent(entity, Shape('square', BLOCK_SIZE, BLOCK_SIZE, 0xffff0000))
  584.         em.addComponent(entity, Position((FIELD_SIZE - 1) * BLOCK_SIZE, TOP_OFFSET + i * BLOCK_SIZE + BLOCK_SIZE))
  585.         em.addComponent(entity, BBox(BLOCK_SIZE, BLOCK_SIZE))
  586.         em.addComponent(entity, Physics(Harmful))
  587.         em.addComponent(entity, Name('block'))
  588.  
  589.  
  590.     # food
  591.     # TODO: create food after game start
  592.     entity = em.createEntity()
  593.     em.addComponent(entity, Shape('square', BLOCK_SIZE, BLOCK_SIZE, 0xff0000ff))
  594.     foodPos = Position(200, 220) # will be updated later
  595.     em.addComponent(entity, foodPos)
  596.     em.addComponent(entity, BBox(BLOCK_SIZE, BLOCK_SIZE))
  597.     em.addComponent(entity, Physics(Destructible))
  598.     em.addComponent(entity, Name('food'))
  599.     em.addComponent(entity, AlphaBlink())
  600.  
  601.     # PLAYER SHOULD BE LAST
  602.     entity = em.createEntity()
  603.     player = entity
  604.     em.addComponent(entity, Shape('square', BLOCK_SIZE, BLOCK_SIZE, 0xff00ff00))
  605.     em.addComponent(entity, Position(100, 100)) # SHOULD BE RANDOM
  606.     em.addComponent(entity, KeyboardController())
  607.     em.addComponent(entity, Direction(0, 0))
  608.     em.addComponent(entity, Speed(BLOCK_SIZE))
  609.     em.addComponent(entity, BBox(BLOCK_SIZE, BLOCK_SIZE))
  610.     em.addComponent(entity, Physics(Harmless))
  611.     em.addComponent(entity, Name('player'))
  612.     em.addComponent(entity, Score())
  613.     em.addComponent(entity, Tail(entity))
  614.  
  615.     def getScore(entity=entity):
  616.         score = world.entityManager.getComponent(entity, Score)
  617.         return str(score.score)
  618.  
  619.     entity = em.createEntity() # TODO: some UI drawing system
  620.     em.addComponent(entity, Position(5, 5)) # ?
  621.     em.addComponent(entity, TextInfo('Score: ', getScore))
  622.  
  623.     entity = em.createEntity()
  624.     em.addComponent(entity, Position(5, 18))
  625.     em.addComponent(entity, TextInfo('Fps: ', lambda: str(xGetFPS())))
  626.  
  627.     # TODO: some way to say shit like "run this system at 250 ms interval"
  628.     # and not that can_act hack
  629.     world.registerSystem((1, EscapeHandler()))
  630.     world.registerSystem((2, ArrowControls()))
  631.     world.registerSystem((16, renderer)) # oh, wow, looks like I can't postprocess, because renderer clear before rendering and flips immediately afterwards
  632.     world.registerSystem((15, AlphaWave()))
  633.     world.registerSystem((10, ContinuousMotion()))
  634.     world.registerSystem((12, CollisionDetection()))
  635.     world.registerSystem((14, CollisionResponce()))
  636.     world.registerSystem((11, TailController()))
  637.     world.registerSystem((20, TextRenderer()))
  638.     world.registerSystem((3, MouseHandler()))
  639.  
  640.     gameEntityManager = em
  641.     menuEntityManager = EntityManager()
  642.     world.setEntityManager(menuEntityManager)
  643.    
  644.     # menu
  645.     em = menuEntityManager
  646.     # label
  647.     label = [
  648.         ' ##### #  #     # #  #  #### ',
  649.         ' #     #  #    ## # #   #    ',
  650.         ' ##### ## #   # # ###   ##   ',
  651.         '     # # ##  #### #  #  #    ',
  652.         ' ##### #  # #   # #   # #### '
  653.     ]
  654.  
  655.     sx, sy = 10, 10
  656.  
  657.     for y, line in enumerate(label):
  658.         for x, char in enumerate(line):
  659.             if char == '#':
  660.                 entity = em.createEntity()
  661.                 em.addComponent(entity, Shape('square', BLOCK_SIZE / 2, BLOCK_SIZE / 2, 0xff44aa44))
  662.                 em.addComponent(entity, Position(sx + x * BLOCK_SIZE / 2, sy + y * BLOCK_SIZE / 2))
  663.  
  664.     def restartPlayer():
  665.         # oh dog, so much hacks
  666.         gameEntityManager.addComponent(player, Score())
  667.         pos = gameEntityManager.getComponent(player, Position)
  668.         dir = gameEntityManager.getComponent(player, Direction)
  669.         tail = gameEntityManager.getComponent(player, Tail)
  670.         pos.x, pos.y = FIELD_SIZE // 2 * BLOCK_SIZE, FIELD_SIZE // 2 * BLOCK_SIZE + TOP_OFFSET
  671.         dir.dx, dir.dy = 0, 0
  672.         for i in tail.segments:
  673.             gameEntityManager.destroyEntity(i)
  674.  
  675.         tail.segments = []
  676.         tail.numSegments = 0
  677.  
  678.     # new game button
  679.     entity = em.createEntity()
  680.     em.addComponent(entity, Shape('square', 120, 20, 0xff4444aa))
  681.     em.addComponent(entity, Position(20, 5 * BLOCK_SIZE / 2 + 20 + 20))
  682.     em.addComponent(entity, TextInfo('New Game', None)) # TODO: some way to center text
  683.     em.addComponent(entity, BBox(120, 20))
  684.     em.addComponent(entity, MouseResponce(MOUSE_LEFT, lambda: world.setEntityManager(gameEntityManager)))
  685.     # em.addComponent(entity, AutoCenter(HORZ, VERTICAL))
  686.  
  687.     # exit game button
  688.     entity = em.createEntity()
  689.     em.addComponent(entity, Shape('square', 120, 20, 0xff4444aa))
  690.     em.addComponent(entity, Position(20, 5 * BLOCK_SIZE / 2 + 20 + 20 + 5 + 20)) # 20 + 20 + 5))
  691.     em.addComponent(entity, TextInfo('Exit Game', None)) # TODO: some way to center text
  692.     em.addComponent(entity, BBox(120, 20))
  693.  
  694.     def lololol():
  695.         raise AppClose
  696.     em.addComponent(entity, MouseResponce(MOUSE_LEFT, lololol))
  697.     # em.addComponent(entity, AutoCenter(HORZ, VERTICAL))
  698.     # maybe not AutoCenter, but some way to make object always be at some position (in percentage, not pixels)
  699.  
  700.     # game over screen
  701.  
  702.     gameOverScoreHack = 0
  703.  
  704.     em = EntityManager()
  705.     gameOverManager = em
  706.  
  707.     entity = em.createEntity()
  708.     em.addComponent(entity, Position(20, 20))
  709.     em.addComponent(entity, Shape('square', 180, 20, 0xffaa44aa))
  710.     em.addComponent(entity, TextInfo('Final Score: ', lambda: str(gameOverScoreHack)))
  711.    
  712.     entity = em.createEntity()
  713.     em.addComponent(entity, Position(20, 80))
  714.     em.addComponent(entity, Shape('square', 120, 20, 0xff4444aa))
  715.     em.addComponent(entity, BBox(120, 20))
  716.     em.addComponent(entity, MouseResponce(MOUSE_LEFT, lambda: world.setEntityManager(menuEntityManager)))
  717.     em.addComponent(entity, TextInfo('OK', None))
  718.  
  719.  
  720.     xAppTitle('SHNAKE') # can name be passed into constructor of renderer?
  721.     restartPlayer()
  722.  
  723.     # ...
  724.     randomizePosition(foodPos)
  725.     _ = gameEntityManager.getComponent(player, Position)
  726.     px, py = _.x, _.y
  727.     while foodPos.x == px and foodPos.y == py:
  728.         randomizePosition(foodPos)
  729.    
  730.  
  731.     while not xWinMessage('WM_CLOSE'):
  732.         try: # kinda ugly
  733.             # renderer.startFrame?
  734.             world.update()
  735.             renderer.endFrame()
  736.  
  737.         except PlayerDed as pd:
  738.             gameOverScoreHack = pd.score
  739.             restartPlayer() # should check food collision here as well
  740.             world.setEntityManager(gameOverManager)
  741.  
  742.         except AppClose:
  743.             return
  744.  
  745.  
  746. if __name__ == '__main__':
  747.     main()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement