Eventos

Como o robô reage

Um evento é um aviso do jogo: "olha, aconteceu isso com você". Você escreve o que o robô deve fazer ao receber cada aviso. É aqui que um robô deixa de ser um boneco andando e vira um competidor.

Regra de ouro dos eventos

Os onze eventos precisam existir no seu robô, mesmo vazios. Se o jogo tentar avisar o seu robô de algo e não encontrar o evento (ou se o seu código der erro dentro dele), o programa inteiro fecha no meio da partida, para todas as equipes. Comece sempre do RoboMinimo, que já vem com todos.

Os três que sempre rodam

init(self)

Quando: uma única vez, no momento em que o robô entra na arena.

É o lugar de escolher cores, formato de radar, travas de arma e radar, e de guardar informações que não mudam, como o tamanho da arena.

exemplo
def init(self):
    self.setColor(66, 185, 193)
    self.arena = self.getMapSize()   # guarda para usar depois
    self.lockRadar("gun")
    self.setRadarField("thin")
    self.radarVisible(True)

run(self)

Quando: toda vez que a fila de comandos do robô esvazia.

É o cérebro. Aqui você decide para onde andar e para onde girar. Lembre que ele não roda a cada instante: se você mandar andar 200 pixels, o run() só é chamado de novo quando esses 200 pixels terminarem.

exemplo
def run(self):
    self.move(80)
    self.gunTurn(20)    # anda e varre o radar ao mesmo tempo
    self.stop()

sensors(self)

Quando: a cada quadro, o tempo todo, mesmo com a fila cheia.

Serve para observar. É o único lugar que roda de forma contínua, então é onde se acompanha algo que muda rápido, como quantos adversários restam. Evite colocar comandos de movimento aqui: como ele roda muitas vezes por segundo, a fila entope.

exemplo
def sensors(self):
    self.adversarios = len(self.getEnemiesLeft()) - 1

Quando o robô bate em alguma coisa

onHitWall(self)

Quando: o robô encosta numa das paredes da arena.

O jogo já tira 1 de vida, empurra o robô um pouco para trás e joga fora a fila de comandos. Cabe a você decidir para onde ir agora. Se não fizer nada, o robô volta ao run() e provavelmente bate de novo, e de novo.

exemplo
def onHitWall(self):
    self.reset()
    self.move(-60)     # da re
    self.turn(90)      # e vira, tudo ao mesmo tempo

onRobotHit(self, robotId, robotName)

Quando: o seu robô trombou em outro.

Recebe o número de identificação e o nome do robô em que você bateu. Os dois perdem 1 de vida.

onHitByRobot(self, robotId, robotName)

Quando: outro robô trombou no seu.

Mesmos dados, ponto de vista contrário. Numa trombada, os dois eventos acontecem, cada um no seu robô.

Como não confundir os dois

onRobotHit = eu bati. onHitByRobot = bateram em mim. O By no nome é quem indica que a ação veio de fora.

Quando envolve tiro

onTargetSpotted(self, botId, botName, botPos)

Quando: o radar do seu robô enxergou um inimigo.

É o evento mais importante do jogo. Você recebe três informações:

botId
o número de identificação do robô avistado
botName
o nome dele
botPos
onde ele está. Use botPos.x() e botPos.y().

A versão simples é atirar direto, o que funciona bem se o radar estiver travado na arma, porque aí o que o radar vê já está na mira:

versão simples
def onTargetSpotted(self, botId, botName, botPos):
    self.fire(3)

A versão caprichada calcula o ângulo exato até o inimigo antes de atirar:

versão com mira (precisa de import math no topo)
def onTargetSpotted(self, botId, botName, botPos):
    eu = self.getPosition()
    dx = botPos.x() - eu.x()
    dy = botPos.y() - eu.y()

    # angulo ate o inimigo, na bussola do jogo
    angulo_do_inimigo = math.degrees(math.atan2(dy, dx)) - 90

    erro = angulo_do_inimigo - (self.getGunHeading() % 360)
    while erro < -180:
        erro = erro + 360
    while erro > 180:
        erro = erro - 360

    self.gunTurn(erro)
    self.stop()
    self.fire(3)

onHitByBullet(self, bulletBotId, bulletBotName, bulletPower)

Quando: o seu robô levou um tiro.

Você recebe quem atirou (número e nome) e a potência do tiro. O dano que você levou é 3 × bulletPower.

Reagir aqui é uma das melhores decisões que um robô pode tomar: se você levou um tiro, alguém está mirando em você e vai atirar de novo no mesmo lugar. Sair do lugar resolve.

exemplo
def onHitByBullet(self, bulletBotId, bulletBotName, bulletPower):
    self.rPrint("Levei " + str(3 * bulletPower) + " de dano")
    self.reset()
    self.move(100)     # sai da linha de tiro
    self.turn(45)

onBulletHit(self, botId, bulletId)

Quando: um tiro seu acertou alguém.

Além do dano no adversário, você recupera vida. E se acertou uma vez, o alvo provavelmente ainda está por perto, então vale insistir na mesma direção.

onBulletMiss(self, bulletId)

Quando: um tiro seu saiu da arena sem acertar ninguém.

A energia gasta no disparo foi perdida. Um robô que recebe muitos onBulletMiss está atirando à toa e sangrando energia.

Quando acaba

onRobotDeath(self)

Quando: a vida do seu robô chegou a zero.

Não dá mais para fazer nada, porque o robô já saiu da arena. Serve para deixar uma mensagem de despedida no painel, o que às vezes ajuda a entender o que deu errado.

exemplo
def onRobotDeath(self):
    self.rPrint("Eliminei " + str(self.getKills()) + " antes de cair")

Resumo

EventoDispara quandoEfeito na vida
inito robô entra na arenanenhum
runa fila de comandos esvazianenhum
sensorsa cada quadronenhum
onHitWallbateu na parede−1
onRobotHiteu bati em outro robô−1 nos dois
onHitByRobotoutro robô bateu em mim−1 nos dois
onHitByBulletlevei um tiro−3 × potência
onBulletHitmeu tiro acertou+2 × potência
onBulletMissmeu tiro saiu da arenanenhum
onTargetSpottedo radar viu alguémnenhum
onRobotDeathminha vida zerounenhum