Пример #1
0
    def __init__(self):
        self.coords = (0, 0)
        self.baseColor = (0, 0, 1)
        self.selectedColor = (1, 0, 0)
        W, H = glfwGetWindowSize()
        self.entryFontScale = gameglobals.fontScale * 1.5
        self.entryLineSpacing = 3 * self.entryFontScale

        self.cursorPos = (W / 2, H / 2)
        self.cursorAngle = 0.0
        self.font_aa = GLFont(r"DATA\\FNT\\bold_aa.glf")
        self.defaultColor = (0.0, 1.0, 1.0)
        self.textureCursor = objects.loadTexture("DATA\\TEX\\cursor.png")
Пример #2
0
    def __init__(self):
        self.state = 1
        self.afterCollideTriggerBox = False
        self.beforeCollideTriggerBox = False
        self.initEvents()
        self.matchPoints = 21

        self.ball = None
        self.gameOver = False

        #faults list will contain msg text, points, and delta up px for text
        self.faultMsgList = []
        #hits list will contain combo, delta up px and coords of the collision (X HITS!)
        self.hitMsgList = []

        self.taunts = []

        self.players = {}
        self.scoreBoard = ScoreBoard(self.players)
        self.objectList = []
        self.font_aa = GLFont(r"DATA\\FNT\\bold_aa.glf")
Пример #3
0
 def __init__(self):
   self.coords = (0, 0)
   self.baseColor = (0,0,1)
   self.selectedColor = (1,0,0)
   W, H = glfwGetWindowSize()
   self.entryFontScale = gameglobals.fontScale * 1.5
   self.entryLineSpacing = 3 * self.entryFontScale
   
   self.cursorPos = (W/2, H/2)
   self.cursorAngle = 0.0
   self.font_aa = GLFont(r"DATA\\FNT\\bold_aa.glf")
   self.defaultColor = (0.0, 1.0, 1.0)
   self.textureCursor = objects.loadTexture("DATA\\TEX\\cursor.png")
Пример #4
0
 def __init__(self):
     self.objectList = []
     self.performance = 0
     ode.World.__init__(self)
     self.setGravity((0.0, -9.81 / 2, 0.0))
     self.space = ode.Space()
     self.contactgroup = ode.JointGroup()
     self.time0 = 0
     #here are menus: mainmenu, ingame
     self.entryList = [
         MainEntries(),
         InGameEntries(),
         RulesEntries(),
         AboutEntries()
     ]
     self.entryIndex = EntryIndex()
     self.font_aa = GLFont(r"DATA\\FNT\\bold_aa.glf")
     self.camera = Camera(0.0, 24.0, 0.0, -30.0, 0.0)
Пример #5
0
  def __init__(self):
    self.state = 1
    self.afterCollideTriggerBox = False
    self.beforeCollideTriggerBox = False
    self.initEvents()
    self.matchPoints = 21
    
    self.ball = None
    self.gameOver = False

    #faults list will contain msg text, points, and delta up px for text
    self.faultMsgList = []
    #hits list will contain combo, delta up px and coords of the collision (X HITS!)
    self.hitMsgList = []

    self.taunts = []

    self.players = {}
    self.scoreBoard = ScoreBoard(self.players)
    self.objectList = []
    self.font_aa = GLFont(r"DATA\\FNT\\bold_aa.glf")
Пример #6
0
class Entries(list):
    def __init__(self):
        self.coords = (0, 0)
        self.baseColor = (0, 0, 1)
        self.selectedColor = (1, 0, 0)
        W, H = glfwGetWindowSize()
        self.entryFontScale = gameglobals.fontScale * 1.5
        self.entryLineSpacing = 3 * self.entryFontScale

        self.cursorPos = (W / 2, H / 2)
        self.cursorAngle = 0.0
        self.font_aa = GLFont(r"DATA\\FNT\\bold_aa.glf")
        self.defaultColor = (0.0, 1.0, 1.0)
        self.textureCursor = objects.loadTexture("DATA\\TEX\\cursor.png")

    def addEntry(self, string, state):
        #[text, active = False, state]
        self.append([string, False, state])

    def setSelectionIndex(self, selection, entryIndex):
        if selection == 'Start Game':
            entryIndex.set(1)  #set the menu index to ingame menu
        if selection == 'Restart Game':
            entryIndex.set(1)  #set the menu index to ingame menu
        if selection == 'Exit to Main Menu':
            entryIndex.set(0)  #set the menu index to main menu
        if selection == 'Rules of the game':
            entryIndex.set(2)  #set the menu index to Rules of the game menu

    def applyInputs(self, entryIndex):
        W, H = glfwGetWindowSize()

        mx, my = glfwGetMousePos()
        my = -my

        if (mx, my + H) != self.cursorPos:
            if mx <= 0: mx = 0
            if mx >= W: mx = W
            if my >= 0: my = 0
            if my <= -H: my = -H
            self.cursorPos = (mx, my + H)
            glfwSetMousePos(mx, -my)

        #if mousebutton1 is pressed, enter selected menu
        W, H = glfwGetWindowSize()
        menuY = H / 2 + 50 * self.entryFontScale
        for i in range(len(self)):
            pos = i + 1
            string = self[i][0]
            #vertical positioning will work fine only with one height for all entries
            x0 = W / 2 - self.font_aa.getSize(
                string)[0] * self.entryFontScale / 2
            y0 = menuY - pos * self.font_aa.getSize(
                string)[1] * self.entryFontScale  #+ self.entryLineSpacing
            x1 = x0 + self.font_aa.getSize(string)[0] * self.entryFontScale
            y1 = y0 + self.entryLineSpacing - self.font_aa.getSize(
                string)[1] * self.entryFontScale
            if vectormath.isPointInSquare(
                (self.cursorPos[0], 0, self.cursorPos[1]), (x0, y1), (x1, y0)):
                self[i][1] = True

                if glfwGetMouseButton(GLFW_MOUSE_BUTTON_1) == GLFW_PRESS\
                   and glfwGetMouseButton(GLFW_MOUSE_BUTTON_1) == GLFW_RELEASE:
                    sounds.playSound("Menu", (0, 0, 0))
                    selection = self[i][0]
                    gameglobals.gameState = self[i][2]
                    self.setSelectionIndex(selection, entryIndex)

    def drawCursor(self):
        x, y = self.cursorPos
        self.font_aa.begin()
        glBindTexture(GL_TEXTURE_2D, self.textureCursor)
        glTranslatef(x, y, 0.0)
        glRotatef(self.cursorAngle, 0.0, 0.0, 1.0)
        self.cursorAngle += 0.5
        glColor3f(1.0, 1.0, 1.0)
        glBegin(GL_QUADS)
        L = 10 * gameglobals.fontScale
        glTexCoord2f(0.0, 0.0)
        glVertex2i(-L, -L)
        glTexCoord2f(1.0, 0.0)
        glVertex2i(L, -L)
        glTexCoord2f(1.0, 1.0)
        glVertex2i(L, L)
        glTexCoord2f(0.0, 1.0)
        glVertex2i(-L, L)
        glEnd()
        self.font_aa.end()

    def drawDeveloper(self):
        W = glfwGetWindowSize()[0]
        glColor4f(1.0, 1.0, 1.0, 0.9)
        self.font_aa.begin()
        dScale = gameglobals.fontScale / 2
        x = W - (self.font_aa.getSize(gameinfo.developer)[0] + 5) * dScale
        y = (self.font_aa.getSize(gameinfo.developer)[1] + 5) * dScale
        self.font_aa.renderOutlined(gameinfo.developer, x, y, (0, 0, 0),
                                    dScale)
        self.font_aa.end()

    def drawTitle(self):
        W, H = glfwGetWindowSize()
        title = ["3D game", "Squares"]
        glColor4f(0.0, 0.0, 1.0, 0.9)
        self.font_aa.begin()

        #unscaled font size is 14, i believe
        titleScale = gameglobals.fontScale * 2
        y = H - H / 8
        for row in title:
            x = W / 2 - self.font_aa.getSize(row)[0] * titleScale / 2
            self.font_aa.renderOutlined(row, x, y, (0, 0, 0), titleScale)
            y -= self.font_aa.getSize(row)[1] * titleScale / 2
            titleScale = gameglobals.fontScale * 4
        self.font_aa.end()

    def draw(self):
        W, H = glfwGetWindowSize()
        menuY = H / 2 + 50 * self.entryFontScale
        for i in range(len(self)):
            pos = i + 1
            string = self[i][0]
            #vertical positioning will work fine only with one height for all entries
            x = W / 2 - self.font_aa.getSize(
                string)[0] * self.entryFontScale / 2
            y = menuY - pos * self.font_aa.getSize(
                string)[1] * self.entryFontScale + self.entryLineSpacing
            if self[i][1] == True:  #if active
                color = [1, 0, 0]
            else:
                color = self.defaultColor
            glColor3f(color[0], color[1], color[2])
            self.font_aa.begin()
            self.font_aa.render(string, x, y, self.entryFontScale)
            self.font_aa.end()
            self[i][1] = False
        self.resetColors()
        #render cursor
        self.drawDeveloper()

    def resetColors(self):
        for entry in self:
            entry[1] = self.defaultColor
Пример #7
0
class Coach:
  def __init__(self):
    self.state = 1
    self.afterCollideTriggerBox = False
    self.beforeCollideTriggerBox = False
    self.initEvents()
    self.matchPoints = 21
    
    self.ball = None
    self.gameOver = False

    #faults list will contain msg text, points, and delta up px for text
    self.faultMsgList = []
    #hits list will contain combo, delta up px and coords of the collision (X HITS!)
    self.hitMsgList = []

    self.taunts = []

    self.players = {}
    self.scoreBoard = ScoreBoard(self.players)
    self.objectList = []
    self.font_aa = GLFont(r"DATA\\FNT\\bold_aa.glf")
      
  def addTaunt(self, player, msg):
    pos = [player.body.getPosition()[0], player.body.getPosition()[1], player.body.getPosition()[2]]
    self.taunts.append([msg,
                        1.0,
                        pos, player.color])

  def restart(self):
    self.gameOver = False
    self.scoreBoard.reset()
    self.resetBall()
    self.resetPlayers()

  def setGameOver(self):
    sounds.playSound("GameOver", (0,0,0))
    self.gameOver = True

  def getLoserNameColor(self):
    for name, object in self.players.items():
      if self.scoreBoard[name][0] >= self.matchPoints:
        return name, object.color
    
  def initEvents(self):
    self.events = {'lastFieldOwner':None,
                   'lastTouchedObject':None,
                   'lastTouchedPlayer':None}

  def resetBall(self, resetCoords = (0.0, 10.0, 0.0)):
    if resetCoords == (0.0, 10.0, 0.0): #a little bit misadjust centered coords
      pairs = ((-0.01, 0.0), (-0.01, -0.01), (0.0, -0.01), (0.01, -0.01), (0.01, 0.0), (0.01, 0.01), (0.0, 0.01))
      newXZ = pairs[randint(0, 6)]
      resetCoords = (newXZ[0], 10.0, newXZ[1])
      
    self.ball.geom.reset = True
    self.ball.geom.resetCoords = resetCoords

  def resetPlayers(self):
    for player in self.players.values():
      player.setInitPosition()
      player.setAngle()

  def getBallCoords(self, playerName):
    player = self.players[playerName]
    littleBit = ((player.min[0] + player.max[0]) / 5, (player.min[1] + player.max[1]) / 5)
    ballCoords = ((player.min[0] + player.max[0]) / 2 - littleBit[0],
                  3.3, (player.min[1] + player.max[1]) / 2 - littleBit[1])
    return ballCoords

  def checkIsBallInSquare(self, ball, min, max):
    min0 = min[0]
    min1 = min[1]
    max0 = max[0]
    max1 = max[1]
    #0.5 is for the middle line 
    if min0 == 0: min0 = max0 / 10 * 0.5
    if min1 == 0: min1 = max1 / 10 * 0.5
    if max0 == 0: max0 = min0 / 10 * 0.5
    if max1 == 0: max1 = min1 / 10 * 0.5
    return vectormath.isPointInSquare(ball, (min0, min1), (max0, max1))

  def registerGroundEvent(self):
    #our objects of interest:
    ball, ground = self.ball, None

    #asign objects of interest
    for object in self.objectList:
      if object.name == 'Ground':
        ground = object

    #handle events
    ballCoords = ball.geom.getPosition()
    #ball + ground

    if ball.body.getLinearVel()[1] < -0.3:
      sounds.playSound("BallGround", ballCoords)

    if not vectormath.isPointInSquare(ballCoords, (-10, -10), (10, 10)): #critical event
      #BALL HAS HIT THE FIELD OUTSIDE
      #and we handle score here

      out = False

      if self.events['lastTouchedObject'] != None: #if last touched was not middle line
        lastTouchedObject = self.events['lastTouchedObject'].name
        if 'Player' in lastTouchedObject:
          #player has kicked the ball out
          pts = self.scoreBoard.addSelfPoints(lastTouchedObject)
          resetCoords = self.getBallCoords(lastTouchedObject)
          self.faultMsgList.append(['Out from ' + lastTouchedObject + '!', str(pts), 0])

          out = lastTouchedObject
          
          getsPoints = lastTouchedObject
        elif self.events['lastFieldOwner']: #if ground was touched in one of the players field last add points to owner
          owner = self.events['lastFieldOwner'].name
          if self.events['lastTouchedPlayer']:
            #case when noone touched the ball after throwing minus
            lastPlayer = self.events['lastTouchedPlayer'].name
            if owner == lastPlayer:
              pts = self.scoreBoard.addSelfPoints(owner)
            else:
              pts = self.scoreBoard.addTotalPoints(owner)
          else:
            pts = self.scoreBoard.addPoint(owner)

          out = owner

          self.faultMsgList.append(['Out from ' + owner + '`s field!', str(pts), 0])
          resetCoords = self.getBallCoords(owner)
          getsPoints = owner
        if self.scoreBoard[getsPoints][0] >= self.matchPoints:
          self.setGameOver()
          return
      else:
        self.faultMsgList.append(['Ball out from middle line!', '', 0])
        resetCoords = (0, 10, 0)

      if out=="Player":
        pl = self.players[["Player_Red", "Player_Green", "Player_Yellow"][randint(0,2)]]
        #pl2 = self.players[["Player_Red", "Player_Green", "Player_Yellow"][randint(0,2)]]
        #while pl2==pl:
        #  pl2 = self.players[["Player_Red", "Player_Green", "Player_Yellow"][randint(0,2)]]

        sounds.playTauntMsg(pl, "GreatShot", pl.body.getPosition())
        self.addTaunt(pl, "Great shot!")

        #    sounds.playTauntMsg(pl2, "Yes", pl.body.getPosition())
        #    self.addTaunt(pl2, "Yes!")

##      print self.scoreBoard

      #finishing handling critical branch
      self.scoreBoard.resetJoinedCombo()
      self.initEvents()
      self.resetBall(resetCoords)
      self.resetPlayers()
      if out!=False and out!="Player":
        pl = self.players[out]
        sounds.playTauntMsg(pl, "MoveIn", pl.body.getPosition())
        self.addTaunt(pl, "Move in!")


    else:
      #BALL HAS HIT THE FIELD INSIDE
      #save the touched field
      for p in self.players.values():
        if self.checkIsBallInSquare(ballCoords, p.min, p.max):
          self.events['lastFieldOwner'] = p.geom
          self.events['lastTouchedObject'] = ground
          break
        self.events['lastTouchedObject'] = None #if has hit the middle line

  def registerPlayerEvent(self):
    ball = self.ball
    for object in self.objectList:
      if 'Player' in object.name:
        player = object
    
    #ball + player
    sounds.playSound("BallPlayer", ball.geom.getPosition())
    lastTouchedObject = self.events['lastTouchedObject']
    
    if lastTouchedObject == None: #picked from middle line
      self.scoreBoard.resetJoinedCombo() #clear combo
      self.scoreBoard.incrementCombo(player, self.hitMsgList) #(+1)
    else:#picked from ground or player
      if lastTouchedObject.name == 'Ground': #picked from ground inside
        self.scoreBoard.resetJoinedCombo()
        playerName = player.name
        self.scoreBoard.incrementCombo(player, self.hitMsgList)
        if (self.events['lastFieldOwner'] == player)\
          and (self.events['lastTouchedPlayer'] == player)\
          and vectormath.isPointInSquare(ball.geom.getPosition()
                                         , self.players[playerName].min
                                         , self.players[playerName].max): #critical event. double-touched -> fault

          if playerName=="Player":
            pl = self.players[["Player_Red", "Player_Green", "Player_Yellow"][randint(0,2)]]
            #pl2 = self.players[["Player_Red", "Player_Green", "Player_Yellow"][randint(0,2)]]
            #while pl2==pl:
            #  pl2 = self.players[["Player_Red", "Player_Green", "Player_Yellow"][randint(0,2)]]

            sounds.playTauntMsg(pl, "AreYouCrazy", pl.body.getPosition())
            self.addTaunt(pl, "Are you crazy?")

            #sounds.playTauntMsg(pl2, "No", pl.body.getPosition())
            #self.addTaunt(pl2, "No!")

          resetCoords = self.getBallCoords(playerName)
          self.scoreBoard.addSelfPoints(playerName)
          self.faultMsgList.append([playerName + ' touched twice!', '1', 0])
          if self.scoreBoard[playerName][0] >= self.matchPoints:
            self.setGameOver()
            return
          self.initEvents()
          self.resetBall(resetCoords)
          self.resetPlayers()
          return 
      else: #picked from player
        if self.events['lastTouchedPlayer'] != player: #reset own combo, when picked from other
          self.scoreBoard.resetOwnCombo(player.name)
        self.scoreBoard.incrementCombo(player, self.hitMsgList)
        
    self.events['lastTouchedObject'] = player
    self.events['lastTouchedPlayer'] = player
    
  def register(self, player):
    name = player.geom.name
    self.players[name] = player
    #see scoreBoard.reset
    self.scoreBoard[name] = [0, 0]

  def msgFlowFunction(self, x, px):
    #this method is used to make the fault messages and "HITS" msg flow up and dissapear
    return 1.0 - (x/px) * (x/px)* (x/px)* (x/px)

  def draw(self, performance):
    W, H = glfwGetWindowSize()

    scale = gameglobals.fontScale
    
    nameScoreList = []

    #draw players scores
    player = self.players['Player']
    text = 'Player: ' + str(self.scoreBoard['Player'][0])
    x = 10.0
    y = self.font_aa.getSize(text)[1] * scale
    nameScoreList.append([text, x, y, player.color])

    playerName = 'Player_Red'
    player = self.players[playerName]
    text = playerName + ': ' + str(self.scoreBoard[playerName][0])
    x = 10.0
    y = H
    nameScoreList.append([text, x, y, player.color])

    playerName = 'Player_Green'    
    player = self.players[playerName]
    text = playerName + ': ' + str(self.scoreBoard[playerName][0])
    x = W - self.font_aa.getSize(text)[0] * scale - 10
    y = H
    nameScoreList.append([text, x, y, player.color])

    playerName = 'Player_Yellow'
    player = self.players[playerName]
    text = playerName + ': ' + str(self.scoreBoard[playerName][0])
    x = W - self.font_aa.getSize(text)[0] * scale - 10
    y = self.font_aa.getSize(text)[1] * scale
    nameScoreList.append([text, x, y, player.color])
    
    self.font_aa.begin()
    for nameScore in nameScoreList:
      glColor3f(nameScore[3][0], nameScore[3][1], nameScore[3][2])      
      self.font_aa.renderShadowed(nameScore[0], nameScore[1], nameScore[2], (0,0,0), scale)
    self.font_aa.end()

    #draw "hits" messages
    px = 50
    for hit in self.hitMsgList:
      if hit[1] < px:
        addend = self.msgFlowFunction(hit[1], px)
        hitText = ' HITS!'
        if hit[0] < 2:
          hitText = ' HIT!'
        text = '+' + str(hit[0]) + hitText
        pCoords = hit[2]

        x, y, _ = gluProject(pCoords[0], pCoords[1], pCoords[2])
        y = y + hit[1]
      
        glColor4f(hit[3][0], hit[3][1], hit[3][2], addend)
        self.font_aa.begin()
        self.font_aa.renderOutlined(text, x, y, (0,0,0), scale)
        self.font_aa.end()
        hit[1] += 200 * (1.2 - addend) * performance
      else:
        self.hitMsgList = self.hitMsgList[1:]

    #draw the faults messages        
    px = 80
    for fault in self.faultMsgList:
      if fault[2] < px:
        addend = self.msgFlowFunction(fault[2], px)
        text = fault[0]
        pts = fault[1]
        x, y = W / 2 - self.font_aa.getSize(text)[0] * scale / 2, H - 50 * scale
        y = y + fault[2]
      
        glColor4f(1.0, 0.8, 0.0, addend)
        self.font_aa.begin()
        self.font_aa.renderShadowed(text, x, y, (0,0,0), scale)
        if pts:
          glColor4f(0.5, 0.8, 0.1, addend)
          pts = '+' + pts
          x = W / 2 - self.font_aa.getSize(pts)[0] * scale / 2
          y -= self.font_aa.getSize(pts)[1] * scale
          self.font_aa.renderShadowed(pts, x, y, (0,0,0), scale)
        self.font_aa.end()
        fault[2] += 200 * (1.2 - addend) * performance
      else:
        self.faultMsgList = self.faultMsgList[1:]
        
    #draw the taunts
    px = 100
    for taunt in self.taunts:
      if taunt[1] < px:
        addend = self.msgFlowFunction(taunt[1], px)
        text = taunt[0]

        pCoords = taunt[2]
        x, y, _ = gluProject(pCoords[0], pCoords[1], pCoords[2])
        y = y + taunt[1]
        x = x - self.font_aa.getSize(text)[0] * scale / 2

        c = taunt[3] #players.colorNamesColors[taunt[2]]
      
        glColor4f(c[0], c[1], c[2], addend)
        self.font_aa.begin()
        self.font_aa.renderShadowed(text, x, y, (0,0,0), scale)
        self.font_aa.end()
        taunt[1] += 200 * (1.2 - addend) * performance
      else:
        self.taunts= self.taunts[1:]


    #draw current total combo
    total = self.scoreBoard.getTotalPoints()
    if total > 1:
      comboScale = scale * 1.25
      totalText = 'Combo ' + str(total) + '!'
      x = W / 2 - self.font_aa.getSize(totalText)[0] * comboScale / 2
      y = 2 * self.font_aa.getSize(totalText)[1] * comboScale
    
      glColor4f(0.0, 1.0, 1.0, 1)
      self.font_aa.begin()
      self.font_aa.renderShadowed(totalText, x, y, (0,0,0), comboScale)
      self.font_aa.end()
      
    #draw game over message
    if self.gameOver == True:
      loserMsg, loserColor = self.getLoserNameColor()
      loserMsg += ' lost!'
      msg = 'Game Over'
      loserScale = scale * 1.25
      gOverScale = scale * 2.5
      
      x0 = W / 2 - self.font_aa.getSize(loserMsg)[0] * loserScale / 2
      y0 = H / 2 + H / 4 -  self.font_aa.getSize(loserMsg)[1] * loserScale / 2

      x1 = W / 2 - self.font_aa.getSize(msg)[0] * gOverScale / 2
      y1 = H / 2 -  self.font_aa.getSize(msg)[1] * gOverScale / 2
    
      self.font_aa.begin()
      glColor4f(loserColor[0], loserColor[1], loserColor[2], 0.9)
      self.font_aa.render(loserMsg, x0, y0, loserScale)
      glColor4f(1.0, 0.0, 0.0, 0.9)
      self.font_aa.render(msg, x1, y1, gOverScale)
      self.font_aa.end()

  def manageGame(self):
    #This is the main logic function of the coach
    #Coach has 3 states to keep in mind when registering event
    #States are needed to avoid registering ball+player event when
    #the ball is standing on player not bouncing
    #This is the place where TriggerBox is used
    
    if not self.gameOver:
      objectNames = [object.name for object in self.objectList]
      beforeCollideTriggerBox = self.afterCollideTriggerBox #initvalue=False

      self.afterCollideTriggerBox = ('Trigger' in objectNames)# True if ball and TriggerBox collide else False
      afterCollidePlayer = ('Player' in ''.join(objectNames)) # True if ball and Player collide else False
      if 'Ground' in objectNames:
        self.registerGroundEvent()
     
      if self.state==1 and beforeCollideTriggerBox==False and self.afterCollideTriggerBox==True:
        self.state=2
      if self.state==2 and afterCollidePlayer==True:
        self.registerPlayerEvent()
        self.state=3
      elif self.state==2 and beforeCollideTriggerBox==True and self.afterCollideTriggerBox==False:
        self.state=1
      elif self.state==3 and self.afterCollideTriggerBox==False:
        self.state=1
Пример #8
0
class Entries(list):
  def __init__(self):
    self.coords = (0, 0)
    self.baseColor = (0,0,1)
    self.selectedColor = (1,0,0)
    W, H = glfwGetWindowSize()
    self.entryFontScale = gameglobals.fontScale * 1.5
    self.entryLineSpacing = 3 * self.entryFontScale
    
    self.cursorPos = (W/2, H/2)
    self.cursorAngle = 0.0
    self.font_aa = GLFont(r"DATA\\FNT\\bold_aa.glf")
    self.defaultColor = (0.0, 1.0, 1.0)
    self.textureCursor = objects.loadTexture("DATA\\TEX\\cursor.png")

  def addEntry(self, string, state):
    #[text, active = False, state]
    self.append([string, False, state])

  def setSelectionIndex(self, selection, entryIndex):
    if selection == 'Start Game':
      entryIndex.set(1) #set the menu index to ingame menu
    if selection == 'Restart Game':
      entryIndex.set(1) #set the menu index to ingame menu
    if selection == 'Exit to Main Menu':
      entryIndex.set(0) #set the menu index to main menu
    if selection == 'Rules of the game':
      entryIndex.set(2) #set the menu index to Rules of the game menu

  def applyInputs(self, entryIndex):
    W, H = glfwGetWindowSize()

    mx, my = glfwGetMousePos()
    my = -my
    
    if (mx, my + H) != self.cursorPos:
      if mx <= 0: mx = 0
      if mx >= W: mx = W
      if my >= 0: my = 0
      if my <= -H: my = -H
      self.cursorPos = (mx, my + H)
      glfwSetMousePos(mx, -my)

    #if mousebutton1 is pressed, enter selected menu
    W, H = glfwGetWindowSize()
    menuY = H / 2 + 50 * self.entryFontScale
    for i in range(len(self)):
      pos = i + 1
      string = self[i][0]
      #vertical positioning will work fine only with one height for all entries
      x0 = W / 2 - self.font_aa.getSize(string)[0] * self.entryFontScale / 2
      y0 = menuY - pos * self.font_aa.getSize(string)[1] * self.entryFontScale #+ self.entryLineSpacing
      x1 = x0 + self.font_aa.getSize(string)[0] * self.entryFontScale
      y1 = y0 + self.entryLineSpacing - self.font_aa.getSize(string)[1] * self.entryFontScale
      if vectormath.isPointInSquare((self.cursorPos[0], 0, self.cursorPos[1]), (x0, y1), (x1, y0)):
        self[i][1] = True
        
        if glfwGetMouseButton(GLFW_MOUSE_BUTTON_1) == GLFW_PRESS\
           and glfwGetMouseButton(GLFW_MOUSE_BUTTON_1) == GLFW_RELEASE:
          sounds.playSound("Menu", (0,0,0))
          selection = self[i][0]
          gameglobals.gameState = self[i][2]
          self.setSelectionIndex(selection, entryIndex)

  def drawCursor(self):
    x, y = self.cursorPos
    self.font_aa.begin()
    glBindTexture(GL_TEXTURE_2D, self.textureCursor)
    glTranslatef(x, y, 0.0)
    glRotatef(self.cursorAngle, 0.0, 0.0, 1.0)
    self.cursorAngle += 0.5
    glColor3f(1.0, 1.0, 1.0)
    glBegin(GL_QUADS)
    L = 10 * gameglobals.fontScale
    glTexCoord2f(0.0, 0.0); glVertex2i(-L, -L)
    glTexCoord2f(1.0, 0.0); glVertex2i( L, -L)
    glTexCoord2f(1.0, 1.0); glVertex2i( L,  L)
    glTexCoord2f(0.0, 1.0); glVertex2i(-L,  L)
    glEnd()
    self.font_aa.end()

  def drawDeveloper(self):
    W = glfwGetWindowSize()[0]
    glColor4f(1.0, 1.0, 1.0, 0.9)
    self.font_aa.begin()
    dScale = gameglobals.fontScale / 2
    x = W - (self.font_aa.getSize(gameinfo.developer)[0] + 5) * dScale
    y = (self.font_aa.getSize(gameinfo.developer)[1] + 5) * dScale
    self.font_aa.renderOutlined(gameinfo.developer, x, y, (0,0,0), dScale)
    self.font_aa.end()

  def drawTitle(self):
    W, H = glfwGetWindowSize()
    title = ["3D game", "Squares"]
    glColor4f(0.0, 0.0, 1.0, 0.9)
    self.font_aa.begin()

    #unscaled font size is 14, i believe
    titleScale = gameglobals.fontScale * 2
    y = H - H / 8
    for row in title:
      x = W / 2 - self.font_aa.getSize(row)[0] * titleScale / 2
      self.font_aa.renderOutlined(row, x, y, (0,0,0), titleScale)
      y -= self.font_aa.getSize(row)[1] * titleScale / 2
      titleScale = gameglobals.fontScale * 4
    self.font_aa.end()        

  def draw(self):
    W, H = glfwGetWindowSize()
    menuY = H / 2 + 50 * self.entryFontScale
    for i in range(len(self)):
      pos = i + 1
      string = self[i][0]
      #vertical positioning will work fine only with one height for all entries
      x = W / 2 - self.font_aa.getSize(string)[0] * self.entryFontScale / 2
      y = menuY - pos * self.font_aa.getSize(string)[1] * self.entryFontScale + self.entryLineSpacing
      if self[i][1] == True: #if active
        color = [1,0,0]
      else:
        color = self.defaultColor
      glColor3f(color[0], color[1], color[2])
      self.font_aa.begin()
      self.font_aa.render(string, x, y, self.entryFontScale)
      self.font_aa.end()
      self[i][1] = False
    self.resetColors()
    #render cursor
    self.drawDeveloper()
    
  def resetColors(self):
    for entry in self:
      entry[1] = self.defaultColor
Пример #9
0
class Coach:
    def __init__(self):
        self.state = 1
        self.afterCollideTriggerBox = False
        self.beforeCollideTriggerBox = False
        self.initEvents()
        self.matchPoints = 21

        self.ball = None
        self.gameOver = False

        #faults list will contain msg text, points, and delta up px for text
        self.faultMsgList = []
        #hits list will contain combo, delta up px and coords of the collision (X HITS!)
        self.hitMsgList = []

        self.taunts = []

        self.players = {}
        self.scoreBoard = ScoreBoard(self.players)
        self.objectList = []
        self.font_aa = GLFont(r"DATA\\FNT\\bold_aa.glf")

    def addTaunt(self, player, msg):
        pos = [
            player.body.getPosition()[0],
            player.body.getPosition()[1],
            player.body.getPosition()[2]
        ]
        self.taunts.append([msg, 1.0, pos, player.color])

    def restart(self):
        self.gameOver = False
        self.scoreBoard.reset()
        self.resetBall()
        self.resetPlayers()

    def setGameOver(self):
        sounds.playSound("GameOver", (0, 0, 0))
        self.gameOver = True

    def getLoserNameColor(self):
        for name, object in self.players.items():
            if self.scoreBoard[name][0] >= self.matchPoints:
                return name, object.color

    def initEvents(self):
        self.events = {
            'lastFieldOwner': None,
            'lastTouchedObject': None,
            'lastTouchedPlayer': None
        }

    def resetBall(self, resetCoords=(0.0, 10.0, 0.0)):
        if resetCoords == (0.0, 10.0,
                           0.0):  #a little bit misadjust centered coords
            pairs = ((-0.01, 0.0), (-0.01, -0.01), (0.0, -0.01), (0.01, -0.01),
                     (0.01, 0.0), (0.01, 0.01), (0.0, 0.01))
            newXZ = pairs[randint(0, 6)]
            resetCoords = (newXZ[0], 10.0, newXZ[1])

        self.ball.geom.reset = True
        self.ball.geom.resetCoords = resetCoords

    def resetPlayers(self):
        for player in self.players.values():
            player.setInitPosition()
            player.setAngle()

    def getBallCoords(self, playerName):
        player = self.players[playerName]
        littleBit = ((player.min[0] + player.max[0]) / 5,
                     (player.min[1] + player.max[1]) / 5)
        ballCoords = ((player.min[0] + player.max[0]) / 2 - littleBit[0], 3.3,
                      (player.min[1] + player.max[1]) / 2 - littleBit[1])
        return ballCoords

    def checkIsBallInSquare(self, ball, min, max):
        min0 = min[0]
        min1 = min[1]
        max0 = max[0]
        max1 = max[1]
        #0.5 is for the middle line
        if min0 == 0: min0 = max0 / 10 * 0.5
        if min1 == 0: min1 = max1 / 10 * 0.5
        if max0 == 0: max0 = min0 / 10 * 0.5
        if max1 == 0: max1 = min1 / 10 * 0.5
        return vectormath.isPointInSquare(ball, (min0, min1), (max0, max1))

    def registerGroundEvent(self):
        #our objects of interest:
        ball, ground = self.ball, None

        #asign objects of interest
        for object in self.objectList:
            if object.name == 'Ground':
                ground = object

        #handle events
        ballCoords = ball.geom.getPosition()
        #ball + ground

        if ball.body.getLinearVel()[1] < -0.3:
            sounds.playSound("BallGround", ballCoords)

        if not vectormath.isPointInSquare(ballCoords, (-10, -10),
                                          (10, 10)):  #critical event
            #BALL HAS HIT THE FIELD OUTSIDE
            #and we handle score here

            out = False

            if self.events[
                    'lastTouchedObject'] != None:  #if last touched was not middle line
                lastTouchedObject = self.events['lastTouchedObject'].name
                if 'Player' in lastTouchedObject:
                    #player has kicked the ball out
                    pts = self.scoreBoard.addSelfPoints(lastTouchedObject)
                    resetCoords = self.getBallCoords(lastTouchedObject)
                    self.faultMsgList.append(
                        ['Out from ' + lastTouchedObject + '!',
                         str(pts), 0])

                    out = lastTouchedObject

                    getsPoints = lastTouchedObject
                elif self.events[
                        'lastFieldOwner']:  #if ground was touched in one of the players field last add points to owner
                    owner = self.events['lastFieldOwner'].name
                    if self.events['lastTouchedPlayer']:
                        #case when noone touched the ball after throwing minus
                        lastPlayer = self.events['lastTouchedPlayer'].name
                        if owner == lastPlayer:
                            pts = self.scoreBoard.addSelfPoints(owner)
                        else:
                            pts = self.scoreBoard.addTotalPoints(owner)
                    else:
                        pts = self.scoreBoard.addPoint(owner)

                    out = owner

                    self.faultMsgList.append(
                        ['Out from ' + owner + '`s field!',
                         str(pts), 0])
                    resetCoords = self.getBallCoords(owner)
                    getsPoints = owner
                if self.scoreBoard[getsPoints][0] >= self.matchPoints:
                    self.setGameOver()
                    return
            else:
                self.faultMsgList.append(['Ball out from middle line!', '', 0])
                resetCoords = (0, 10, 0)

            if out == "Player":
                pl = self.players[[
                    "Player_Red", "Player_Green", "Player_Yellow"
                ][randint(0, 2)]]
                #pl2 = self.players[["Player_Red", "Player_Green", "Player_Yellow"][randint(0,2)]]
                #while pl2==pl:
                #  pl2 = self.players[["Player_Red", "Player_Green", "Player_Yellow"][randint(0,2)]]

                sounds.playTauntMsg(pl, "GreatShot", pl.body.getPosition())
                self.addTaunt(pl, "Great shot!")

                #    sounds.playTauntMsg(pl2, "Yes", pl.body.getPosition())
                #    self.addTaunt(pl2, "Yes!")


##      print self.scoreBoard

#finishing handling critical branch
            self.scoreBoard.resetJoinedCombo()
            self.initEvents()
            self.resetBall(resetCoords)
            self.resetPlayers()
            if out != False and out != "Player":
                pl = self.players[out]
                sounds.playTauntMsg(pl, "MoveIn", pl.body.getPosition())
                self.addTaunt(pl, "Move in!")

        else:
            #BALL HAS HIT THE FIELD INSIDE
            #save the touched field
            for p in self.players.values():
                if self.checkIsBallInSquare(ballCoords, p.min, p.max):
                    self.events['lastFieldOwner'] = p.geom
                    self.events['lastTouchedObject'] = ground
                    break
                self.events[
                    'lastTouchedObject'] = None  #if has hit the middle line

    def registerPlayerEvent(self):
        ball = self.ball
        for object in self.objectList:
            if 'Player' in object.name:
                player = object

        #ball + player
        sounds.playSound("BallPlayer", ball.geom.getPosition())
        lastTouchedObject = self.events['lastTouchedObject']

        if lastTouchedObject == None:  #picked from middle line
            self.scoreBoard.resetJoinedCombo()  #clear combo
            self.scoreBoard.incrementCombo(player, self.hitMsgList)  #(+1)
        else:  #picked from ground or player
            if lastTouchedObject.name == 'Ground':  #picked from ground inside
                self.scoreBoard.resetJoinedCombo()
                playerName = player.name
                self.scoreBoard.incrementCombo(player, self.hitMsgList)
                if (self.events['lastFieldOwner'] == player)\
                  and (self.events['lastTouchedPlayer'] == player)\
                  and vectormath.isPointInSquare(ball.geom.getPosition()
                                                 , self.players[playerName].min
                                                 , self.players[playerName].max): #critical event. double-touched -> fault

                    if playerName == "Player":
                        pl = self.players[[
                            "Player_Red", "Player_Green", "Player_Yellow"
                        ][randint(0, 2)]]
                        #pl2 = self.players[["Player_Red", "Player_Green", "Player_Yellow"][randint(0,2)]]
                        #while pl2==pl:
                        #  pl2 = self.players[["Player_Red", "Player_Green", "Player_Yellow"][randint(0,2)]]

                        sounds.playTauntMsg(pl, "AreYouCrazy",
                                            pl.body.getPosition())
                        self.addTaunt(pl, "Are you crazy?")

                        #sounds.playTauntMsg(pl2, "No", pl.body.getPosition())
                        #self.addTaunt(pl2, "No!")

                    resetCoords = self.getBallCoords(playerName)
                    self.scoreBoard.addSelfPoints(playerName)
                    self.faultMsgList.append(
                        [playerName + ' touched twice!', '1', 0])
                    if self.scoreBoard[playerName][0] >= self.matchPoints:
                        self.setGameOver()
                        return
                    self.initEvents()
                    self.resetBall(resetCoords)
                    self.resetPlayers()
                    return
            else:  #picked from player
                if self.events[
                        'lastTouchedPlayer'] != player:  #reset own combo, when picked from other
                    self.scoreBoard.resetOwnCombo(player.name)
                self.scoreBoard.incrementCombo(player, self.hitMsgList)

        self.events['lastTouchedObject'] = player
        self.events['lastTouchedPlayer'] = player

    def register(self, player):
        name = player.geom.name
        self.players[name] = player
        #see scoreBoard.reset
        self.scoreBoard[name] = [0, 0]

    def msgFlowFunction(self, x, px):
        #this method is used to make the fault messages and "HITS" msg flow up and dissapear
        return 1.0 - (x / px) * (x / px) * (x / px) * (x / px)

    def draw(self, performance):
        W, H = glfwGetWindowSize()

        scale = gameglobals.fontScale

        nameScoreList = []

        #draw players scores
        player = self.players['Player']
        text = 'Player: ' + str(self.scoreBoard['Player'][0])
        x = 10.0
        y = self.font_aa.getSize(text)[1] * scale
        nameScoreList.append([text, x, y, player.color])

        playerName = 'Player_Red'
        player = self.players[playerName]
        text = playerName + ': ' + str(self.scoreBoard[playerName][0])
        x = 10.0
        y = H
        nameScoreList.append([text, x, y, player.color])

        playerName = 'Player_Green'
        player = self.players[playerName]
        text = playerName + ': ' + str(self.scoreBoard[playerName][0])
        x = W - self.font_aa.getSize(text)[0] * scale - 10
        y = H
        nameScoreList.append([text, x, y, player.color])

        playerName = 'Player_Yellow'
        player = self.players[playerName]
        text = playerName + ': ' + str(self.scoreBoard[playerName][0])
        x = W - self.font_aa.getSize(text)[0] * scale - 10
        y = self.font_aa.getSize(text)[1] * scale
        nameScoreList.append([text, x, y, player.color])

        self.font_aa.begin()
        for nameScore in nameScoreList:
            glColor3f(nameScore[3][0], nameScore[3][1], nameScore[3][2])
            self.font_aa.renderShadowed(nameScore[0], nameScore[1],
                                        nameScore[2], (0, 0, 0), scale)
        self.font_aa.end()

        #draw "hits" messages
        px = 50
        for hit in self.hitMsgList:
            if hit[1] < px:
                addend = self.msgFlowFunction(hit[1], px)
                hitText = ' HITS!'
                if hit[0] < 2:
                    hitText = ' HIT!'
                text = '+' + str(hit[0]) + hitText
                pCoords = hit[2]

                x, y, _ = gluProject(pCoords[0], pCoords[1], pCoords[2])
                y = y + hit[1]

                glColor4f(hit[3][0], hit[3][1], hit[3][2], addend)
                self.font_aa.begin()
                self.font_aa.renderOutlined(text, x, y, (0, 0, 0), scale)
                self.font_aa.end()
                hit[1] += 200 * (1.2 - addend) * performance
            else:
                self.hitMsgList = self.hitMsgList[1:]

        #draw the faults messages
        px = 80
        for fault in self.faultMsgList:
            if fault[2] < px:
                addend = self.msgFlowFunction(fault[2], px)
                text = fault[0]
                pts = fault[1]
                x, y = W / 2 - self.font_aa.getSize(
                    text)[0] * scale / 2, H - 50 * scale
                y = y + fault[2]

                glColor4f(1.0, 0.8, 0.0, addend)
                self.font_aa.begin()
                self.font_aa.renderShadowed(text, x, y, (0, 0, 0), scale)
                if pts:
                    glColor4f(0.5, 0.8, 0.1, addend)
                    pts = '+' + pts
                    x = W / 2 - self.font_aa.getSize(pts)[0] * scale / 2
                    y -= self.font_aa.getSize(pts)[1] * scale
                    self.font_aa.renderShadowed(pts, x, y, (0, 0, 0), scale)
                self.font_aa.end()
                fault[2] += 200 * (1.2 - addend) * performance
            else:
                self.faultMsgList = self.faultMsgList[1:]

        #draw the taunts
        px = 100
        for taunt in self.taunts:
            if taunt[1] < px:
                addend = self.msgFlowFunction(taunt[1], px)
                text = taunt[0]

                pCoords = taunt[2]
                x, y, _ = gluProject(pCoords[0], pCoords[1], pCoords[2])
                y = y + taunt[1]
                x = x - self.font_aa.getSize(text)[0] * scale / 2

                c = taunt[3]  #players.colorNamesColors[taunt[2]]

                glColor4f(c[0], c[1], c[2], addend)
                self.font_aa.begin()
                self.font_aa.renderShadowed(text, x, y, (0, 0, 0), scale)
                self.font_aa.end()
                taunt[1] += 200 * (1.2 - addend) * performance
            else:
                self.taunts = self.taunts[1:]

        #draw current total combo
        total = self.scoreBoard.getTotalPoints()
        if total > 1:
            comboScale = scale * 1.25
            totalText = 'Combo ' + str(total) + '!'
            x = W / 2 - self.font_aa.getSize(totalText)[0] * comboScale / 2
            y = 2 * self.font_aa.getSize(totalText)[1] * comboScale

            glColor4f(0.0, 1.0, 1.0, 1)
            self.font_aa.begin()
            self.font_aa.renderShadowed(totalText, x, y, (0, 0, 0), comboScale)
            self.font_aa.end()

        #draw game over message
        if self.gameOver == True:
            loserMsg, loserColor = self.getLoserNameColor()
            loserMsg += ' lost!'
            msg = 'Game Over'
            loserScale = scale * 1.25
            gOverScale = scale * 2.5

            x0 = W / 2 - self.font_aa.getSize(loserMsg)[0] * loserScale / 2
            y0 = H / 2 + H / 4 - self.font_aa.getSize(
                loserMsg)[1] * loserScale / 2

            x1 = W / 2 - self.font_aa.getSize(msg)[0] * gOverScale / 2
            y1 = H / 2 - self.font_aa.getSize(msg)[1] * gOverScale / 2

            self.font_aa.begin()
            glColor4f(loserColor[0], loserColor[1], loserColor[2], 0.9)
            self.font_aa.render(loserMsg, x0, y0, loserScale)
            glColor4f(1.0, 0.0, 0.0, 0.9)
            self.font_aa.render(msg, x1, y1, gOverScale)
            self.font_aa.end()

    def manageGame(self):
        #This is the main logic function of the coach
        #Coach has 3 states to keep in mind when registering event
        #States are needed to avoid registering ball+player event when
        #the ball is standing on player not bouncing
        #This is the place where TriggerBox is used

        if not self.gameOver:
            objectNames = [object.name for object in self.objectList]
            beforeCollideTriggerBox = self.afterCollideTriggerBox  #initvalue=False

            self.afterCollideTriggerBox = (
                'Trigger' in objectNames
            )  # True if ball and TriggerBox collide else False
            afterCollidePlayer = (
                'Player' in ''.join(objectNames)
            )  # True if ball and Player collide else False
            if 'Ground' in objectNames:
                self.registerGroundEvent()

            if self.state == 1 and beforeCollideTriggerBox == False and self.afterCollideTriggerBox == True:
                self.state = 2
            if self.state == 2 and afterCollidePlayer == True:
                self.registerPlayerEvent()
                self.state = 3
            elif self.state == 2 and beforeCollideTriggerBox == True and self.afterCollideTriggerBox == False:
                self.state = 1
            elif self.state == 3 and self.afterCollideTriggerBox == False:
                self.state = 1