void FighterFightTask::updateState() { if (m_state != State::IDLE && m_targets.empty()) { setState(State::IDLE); } switch (m_state) { case State::IDLE: if (m_targets.empty()) { return; } else { setState(State::APPROACH); } break; case State::APPROACH: if (targetDistance() < componentsInfo().maxBulletRange()) { setState(State::ENGAGE); } break; case State::ENGAGE: if (targetDistance() < m_minEnemyDistance) { setState(State::EVADE); m_positionBehindTarget = findRandomEvasionPoint(); } break; case State::EVADE: if (pointDistance(m_positionBehindTarget) < 20 && targetDistance() < m_minEnemyDistance) { m_positionBehindTarget = findRandomEvasionPoint(); } if (pointDistance(m_positionBehindTarget) > 20) break; if (targetDistance() < m_minEnemyDistance) { break; } if (targetDistance() < componentsInfo().maxBulletRange()) { setState(State::ENGAGE); } else { setState(State::APPROACH); } break; default: assert(false); return; } if (m_stateChanged) { m_stateChanged = false; updateState(); } }
void FighterFightTask::update(float deltaSec) { updateTargets(); updateState(); WorldObject* worldObject = boardComputer()->worldObject(); switch (m_state) { case State::IDLE: return; case State::APPROACH: if (angleToTarget() > 45.0f) { boardComputer()->rotateTo(m_primaryTarget->transform().position()); } else { boardComputer()->rotateTo(m_primaryTarget->transform().position()); boardComputer()->moveTo(m_primaryTarget->transform().position()); } if (targetDistance() < componentsInfo().maxBulletRange()) { boardComputer()->shootBullet(m_targets); } break; case State::ENGAGE: if (angleToTarget() > 45.0f) { boardComputer()->moveTo(worldObject->transform().position() + glm::vec3(0, 0, -1) * worldObject->transform().orientation()); boardComputer()->rotateTo(m_primaryTarget->transform().position()); } else { boardComputer()->rotateTo(m_primaryTarget->transform().position()); boardComputer()->moveTo(m_primaryTarget->transform().position()); if (angleToTarget() < 15.0f && targetDistance() < componentsInfo().maxRocketRange()) { boardComputer()->shootRockets(m_primaryTarget); } } if (targetDistance() < componentsInfo().maxBulletRange()) { boardComputer()->shootBullet(m_targets); } break; case State::EVADE: boardComputer()->rotateTo(m_positionBehindTarget); boardComputer()->moveTo(m_positionBehindTarget); break; } }
void moveGhost(Location *ghost,int xtl,int ytl,int boardHeight,int boardWidth,int target[]){ /* Moves all active ghosts */ int i=ghost->y, j=ghost->x; int move[4],movement=0; //array of viable moves (each index applies to different move) double distance[4]={1000,1000,1000,1000}; //either set to distance or 1000 (arbitrary high value) if(board[i+1][j]!=1 && board[i+1][j]!=8 && (i+1)<rows && (i+1)!=ghost->prevY){ //down move[down]=1; distance[down]=targetDistance(target[1],target[0],j,i+1); } else{ move[down]=0; distance[down]=1000;} if(board[i-1][j]!=1 && board[i-1][j]!=8 && (i-1)>=0 && (i-1)!=ghost->prevY){ //up move[up]=1; distance[up]=targetDistance(target[1],target[0],j,i-1); } else{ move[up]=0; distance[up]=1000;} if(board[i][j+1]!=1 && board[i][j+1]!=8 && (j+1)<columns && (j+1)!=ghost->prevX){ //right move[right]=1; distance[right]=targetDistance(target[1],target[0],j+1,i); } else{ move[right]=0; distance[right]=1000;} if(board[i][j-1]!=1 && board[i][j-1]!=8 && (j-1)>=0 && (j-1)!=ghost->prevX){ //left move[left]=1; distance[left]=targetDistance(target[1],target[0],j-1,i); } else{ move[left]=0; distance[left]=1000;} /* Now that we know which moves are viable and the distances from each, * determine which is the closest to target */ movement=minLocation(distance); if (i==7 && j==0 && ghost->prevX==1){//this is for the spot on the left to flip sides of the board ghost->prevX=columns; ghost->x=columns-1; ghost->orientation=left; } else if (i==7 && j==columns-1 && ghost->prevX==columns-2){//this is for the spot on the rght to flip sides of the board ghost->prevX=-1; ghost->x=0; ghost->orientation=left; } else { switch(movement){ case up: ghost->prevY=ghost->y; ghost->prevX=ghost->x; ghost->y--; //move up ghost->orientation=up; //set orientation upward break; case down: ghost->prevY=ghost->y; ghost->prevX=ghost->x; ghost->y++; //move down ghost->orientation=down; //set orientation downward break; case left: ghost->prevX=ghost->x; ghost->prevY=ghost->y; ghost->x--; //move left ghost->orientation=left; //set orientation left break; case right: ghost->prevX=ghost->x; ghost->prevY=ghost->y; ghost->x++; //move right ghost->orientation=right; //set orientation right break; } } }
void targetGhosts(Location ghosts[],Location *pacman,int xtl,int ytl,int boardHeight,int boardWidth,int active,int state[]){ int i,j,k=blinky,move,a; static int loop=0; double dist[4]; /* This loop will update the locations of each individual ghost */ /* Assumptions: ghosts cannot turn around * Each ghost tries to get to its specified target that turn */ int target[2];//target[0]=ytarget target[1]=xtarget for(k=blinky;k<=active;k++){ if(state[k]==frighten && loop%2){//if a ghost is frightened, they slow down to one space every two loops target[0]=ghosts[k].y; target[1]=ghosts[k].x; continue; } switch(state[k]){ case chase: //this is the chase state, all ghosts go for pacman switch(k){ /* Blinky's movement targets pacman directly. His target is pacman's current position */ case blinky: target[0]=pacman->y; target[1]=pacman->x; break; /* Pinky's target is 3 spaces in front of pacman's current position, toward his orientation */ case pinky: switch(pacman->orientation){ case left: target[0]=pacman->y; target[1]=pacman->x - 3; break; case right: target[0]=pacman->y; target[1]=pacman->x + 3; break; case up: target[0]=pacman->y - 3; target[1]=pacman->x; break; case down: target[0]=pacman->y + 3; target[1]=pacman->x; break; } break; /* Inky's movement uses blinky's location and pacman's location. His target is blinky's target +2 in direction of pacman's orientation times two */ case inky: switch(pacman->orientation){ case left: target[0]=2*(pacman->y - ghosts[blinky].y)+ghosts[blinky].y; target[1]=2*(pacman->x - 2 - ghosts[blinky].x)+ghosts[blinky].x; break; case right: target[0]=2*(pacman->y - ghosts[blinky].y)+ghosts[blinky].y; target[1]=2*(pacman->x + 2 - ghosts[blinky].x)+ghosts[blinky].x; break; case up: target[0]=2*(pacman->y - 2 - ghosts[blinky].y)+ghosts[blinky].y; target[1]=2*(pacman->x - ghosts[blinky].x)+ghosts[blinky].x; break; case down: target[0]=2*(pacman->y + 2 - ghosts[blinky].y)+ghosts[blinky].y; target[1]=2*(pacman->x - ghosts[blinky].x)+ghosts[blinky].x; break; } break; /* If distance greater than 5, target pacman, otherwise, target random target on board */ case clyde: if(targetDistance(ghosts[clyde].x,ghosts[clyde].y,pacman->x,pacman->y)>=5){ target[0]=pacman->y; target[1]=pacman->x; } else { target[0]=rows-1; target[1]=0; } break; } break; case scatter: //This is when the ghosts go to their respective target corners switch(k){ //each has its own designated corner case blinky://top right target[0]=0; target[1]=columns-1; break; case pinky://top left target[0]=0; target[1]=0; break; case inky://bottom right target[0]=rows-1; target[1]=columns-1; break; case clyde://bottom left target[0]=rows-1; target[1]=0; break; } break; case frighten: //This is randomized chaotic movement, usually slower target[0]=rand()%rows; target[1]=rand()%columns; break; case dead: target[0]=6; target[1]=7; break; } /* This next block makes sure the target is on the board */ if(target[0]>=rows) target[0]=rows-1; else if(target[0]<0) target[0]=0; if(target[1]>=columns) target[1]=columns-1; else if(target[1]<0) target[1]=0; /* This block of code decides where to move the ghost in this loop */ if(state[k]==dead && ghosts[k].x==target[1] && ghosts[k].y==target[0]){ //This means they are at their designated target /* Put them into the ghost house */ ghosts[k].y++; //at top of house, move into house and change state state[k]=housed; } else if(state[k]==housed){ ghosts[k].y--; state[k]=chase; } else { moveGhost(&ghosts[k],xtl,ytl,boardHeight,boardWidth,target); } } loop++; }