📄 prince.java
字号:
package pop2;
/**
* <p>Title: POP2</p>
* <p>Description: Prince of Persia 2</p>
* <p>Copyright: Copyright (c) 2003</p>
* <p>Company: UBI soft (Beijing)</p>
* @author Cao Heng
* @version 1.0
*/
public class Prince extends Actor
{
final static int MORE_BLOOD = 0;
final static int CAN_SWORD = 1;
final static int CAN_WALLING = 2;
final static int CAN_WALLJUMP = 3;
final static int CAN_ROLL = 4;
final static int MORE_ENERGY = 5;
final static int MORE_BLOOD1 = 6;
final static int MORE_BLOOD2 = 7;
final static int MORE_BLOOD3 = 8;
final static int MORE_BLOOD4 = 9;
final static int ABILITY_NUMBER = 10;
final static int ENERGY_WALLING = 6;
final static int ENERGY_WALLJUMP = 26;
final static int ENERGY_ROLL = 6;
final static int MSG_SHOWTIME = 1000;
final static int CAM_OFFSETX = Def.PF_WIDTH / 4;
final static int CAM_OFFSETY = -Def.PF_HEIGHT / 6;
final static int INVINCIBLE_TIMES = 30;
final static int BORN_LIMIT = 3;
final static int SHOWDIRECTION_FRAMES = 50;
// parameter
int curState, nextState;
int m_energy, m_maxEnergy;
static byte ability[] = new byte[ABILITY_NUMBER];
static int m_camOffsetX;
static int m_camOffsetY;
static boolean noJump = false;
static boolean blocked = false;
boolean noGrab = false;
boolean bornFlipX;
int m_bornTimes;
int m_showDirection;
public Prince()
{
}
void initAI()
{
Player.m_showBar = true;
m_bornTimes++;
m_start1 = m_posX;
m_start2 = m_posY;
bornFlipX = m_flag[0];
m_maxhp = Def.BLOOD_BASE + ability[MORE_BLOOD]*Def.BLOOD_MORE;
m_hp = m_maxhp;
m_maxEnergy = Def.ENERGY_BASE + ability[MORE_ENERGY]*Def.ENERGY_MORE;
m_energy = m_maxEnergy;
m_camOffsetX = CAM_OFFSETX;
m_camOffsetY = CAM_OFFSETY;
m_relativeMisc = null;
}
boolean addHp()
{
if (m_hp >= m_maxhp)
return false;
setAction(Def.PRINCE_FLASH, 1);
//GE.playSound(Def.SOUND_GETPOTION_MID, 1);
GE.resetKey();
m_hp ++;
//if(m_hp > m_maxhp) m_hp = m_maxhp;
return true;
}
boolean enableAbility(int id)
{
if (id == MORE_BLOOD)
{
m_maxhp = Def.BLOOD_BASE + ability[MORE_BLOOD] * Def.BLOOD_MORE;
m_hp = m_maxhp;
return true;
}
if (ability[id] > 0)
{
if (id >= MORE_BLOOD1 && m_hp < m_maxhp)
m_hp = m_maxhp;
else
return false;
}
else
{
if (id == MORE_ENERGY)
{
m_maxEnergy = Def.ENERGY_MAX;
m_energy = m_maxEnergy;
}
else if (id >= MORE_BLOOD1)
{
m_maxhp += Def.BLOOD_MORE;
//m_hp = m_maxhp;
if (ability[MORE_BLOOD] < 4)
ability[MORE_BLOOD]++;
}
m_hp = m_maxhp;
ability[id] = 1;
}
setAction(Def.PRINCE_FLASH2, 1);
GE.playSound(Def.SOUND_GETABILITY_MID, 1);
GE.resetKey();
return true;
}
int comsumeEnergy(int n)
{
m_energy -= n;
if(m_energy < 0)m_energy = 0;
return m_energy;
}
void followBox()
{
m_relativeMisc.m_vX = m_vX;
if (m_flag[0])
{
if (m_phbLeft < Def.PHB_SOLID)
{
m_posX = m_relativeMisc.m_posX + ((m_relativeMisc.getColBox()[2] - getColBox()[0]) << 8);
return;
}
}
else
{
if (m_phbRight < Def.PHB_SOLID)
{
m_posX = m_relativeMisc.m_posX + ((m_relativeMisc.getColBox()[0] - getColBox()[2]) << 8);
return;
}
}
postMessage(Def.MSG_BOX_AWAY, m_relativeMisc);
}
void postMessage(int msg, Actor sender)
{
switch(msg)
{
case Def.MSG_CHECKPOINT:
m_start1 = sender.m_posX;
m_start2 = sender.m_posY;
bornFlipX = m_flag[0];
Player.updateCheckPoint(true);
break;
case Def.MSG_BOX_NEAR:
if (m_relativeMisc == null || !m_relativeMisc.equals(sender))
{
m_relativeMisc = sender;
checkActorBox(m_relativeMisc);
}
if (m_flag[0] ^ (m_posX < sender.m_posX))
{
if (m_actionIDNow == Def.PRINCE_RUN && sender.m_parameters[0] > 0)
{
if (Math.abs(m_posY - sender.m_posY) < 4*256 &&
!(m_flag[0] && m_phbLeft >= Def.PHB_SOLID) &&
!(!m_flag[0] && m_phbRight >= Def.PHB_SOLID))
{
setAction(Def.PRINCE_READY_PULL_PUSH, 1);
followBox();
}
}
}
break;
case Def.MSG_BOX_AWAY:
if (m_relativeMisc != null && m_relativeMisc.equals(sender))
{
m_relativeMisc.m_vX = 0;
m_relativeMisc = null;
if(m_actionIDNow == Def.PRINCE_PUSH || m_actionIDNow == Def.PRINCE_PULL || m_actionIDNow == Def.PRINCE_READY_PULL_PUSH)
{
setAction(Def.PRINCE_NORMAL, 1);
}
else
{
checkTopBottom(CHECK_BOTTOM, true);
}
}
break;
case Def.MSG_HURT:
if (m_counter == 0 && m_actionIDNow != Def.PRINCE_HURT && m_actionIDNow != Def.PRINCE_DIE)
{
if (m_actionIDNow == Def.PRINCE_READY_PULL_PUSH || m_actionIDNow == Def.PRINCE_PULL || m_actionIDNow == Def.PRINCE_PUSH)
{
m_relativeMisc.m_vX = 0;
m_relativeMisc = null;
}
GE.m_levelPassHurt++;
if (m_actionIDNow == Def.PRINCE_HANG)
toFall();
if (--m_hp > 0)
{
if (m_actionIDNow != Def.PRINCE_FALL)
setAction(Def.PRINCE_HURT, 1);
if (sender.m_animID != Def.ID_SAW && sender.m_animID != Def.ID_RSWORD)
{
if (sender.m_animID == Def.ID_SANDMAN && sender.equals(Player.m_arrow))
{
//hard coded here for riding arrows
if (m_actionIDNow != Def.PRINCE_FALL && m_actionIDNow != Def.PRINCE_WALLFLY
&& m_actionIDNow != Def.PRINCE_JUMP_AHEAD)
setFlipX( m_posX > sender.m_posX );
}
else
setFlipX( m_posX > sender.m_posX );
}
m_counter = INVINCIBLE_TIMES;
//GE.playSound(Def.SOUND_HURT_MID, 1);
}
else
{
setAction(Def.PRINCE_DIE, 1);
stopAction(false);
GE.playSound(Def.SOUND_GAMEOVER_MID, 1);
}
}
break;
}
}
private boolean checkWallJump()
{
if ((m_flag[0] && m_phbLeft == Def.PHB_WALLJUMP) || (!m_flag[0] && m_phbRight == Def.PHB_WALLJUMP))
{
if (ability[CAN_WALLJUMP] > 0 && m_energy >= ENERGY_WALLJUMP)
{
setFlipX(!m_flag[0]);
nextState = Def.PRINCE_WALLJUMP;
comsumeEnergy(ENERGY_WALLJUMP);
}
return true;
}
return false;
}
private boolean checkClimbUp()
{
int tileX0 = ((m_posX >> 8) + (m_flag[0] ? (m_colBoxNow[0]-15) : (m_colBoxNow[2]+15))) / GE.m_tileWidth;
int tileX1 = tileX0 + (m_flag[0]?1:-1);
int tileY2 = ((m_posY >> 8) + m_colBoxNow[3]) / GE.m_tileHeight;
int tileY1 = ((m_posY >> 8) + m_colBoxNow[1]) / GE.m_tileHeight;
int tileY0 = tileY1 - (tileY2 - tileY1);
for (int y = tileY0; y <= tileY2; y++)
{
if (GE.getPhyParam(tileX1, y) == Def.PHB_SOLID)
{
return false;
}
if (GE.getPhyParam(tileX0, y) == Def.PHB_SOLID)
{
if (y < tileY2 && y >= tileY1)
{
if (m_flag[0]) // left
m_grabPosX = ((tileX0+1) * GE.m_tileWidth) << 8;
else // right
m_grabPosX = (tileX0 * GE.m_tileWidth - 1) << 8;
m_grabPosY = (y * GE.m_tileHeight - 1) << 8;
return true;
}
return false;
}
}
if (m_relativeMisc != null) // check box first
{
byte[] miscBox = m_relativeMisc.getColBox();
if (m_posY == m_relativeMisc.m_posY) // 10 is low limit
{
if (m_flag[0] && m_posX > m_relativeMisc.m_posX) // left
{
m_grabPosX = m_relativeMisc.m_posX + (miscBox[2] << 8);
m_grabPosY = m_relativeMisc.m_posY + (miscBox[1] << 8);
return true;
}
else if (!m_flag[0] && m_posX < m_relativeMisc.m_posX) // right
{
m_grabPosX = m_relativeMisc.m_posX + (miscBox[0] << 8);
m_grabPosY = m_relativeMisc.m_posY + (miscBox[1] << 8);
return true;
}
}
}
return false;
}
//scan upper-ahead for a grabbable block
private boolean scanPhb4Grab()
{
int i, j;
int tileX0, tileX, tileY, deltaX = (m_flag[0]?-1:1);
byte[] colBox = getColBox();
byte phb;
tileX0 = ((m_posX >> 8) + (m_flag[0]?colBox[0]:colBox[2])) / GE.m_tileWidth;
tileY = ((m_posY >> 8) + colBox[1]) / GE.m_tileHeight - 1;
for (i = 0; i < 2; i++, tileY--)
{
tileX = tileX0;
for (j = 0; j < 3; j++, tileX+=deltaX)
{
phb = GE.getPhyParam(tileX, tileY);
if (phb == Def.PHB_SOLID)
{
if(GE.getPhyParam(tileX, tileY - 1) != Def.PHB_SOLID && GE.getPhyParam(tileX - deltaX, tileY) != Def.PHB_SOLID)
{
if (m_flag[0])
m_grabPosX = ((tileX+1) * GE.m_tileWidth) << 8;
else
m_grabPosX = (tileX * GE.m_tileWidth - 1) << 8;
m_grabPosY = (tileY * GE.m_tileHeight - 1) << 8;
return true;
}
else break;
}
}
}
return false;
}
private boolean checkHang()
{
//int deltaX = (m_flag[0]?-1:1);
//byte phb;
int tileX = ((m_posX >> 8) + (m_flag[0] ? (m_colBoxNow[0]-7) : (m_colBoxNow[2]+7))) / GE.m_tileWidth;
int tileY = ((m_posY >> 8) + m_colBoxNow[1] + 3) / GE.m_tileHeight; // max height 5 tile
//for(i = 0; i < 1; i++, tileY++)
//{
//phb = GE.getPhyParam(tileX, tileY);
//if(phb == Def.PHB_SOLID)
//{
if (GE.getPhyParam(tileX, tileY) == Def.PHB_SOLID &&
GE.getPhyParam(tileX, tileY - 1) != Def.PHB_SOLID &&
GE.getPhyParam(tileX - (m_flag[0]?-1:1), tileY) != Def.PHB_SOLID &&
GE.getPhyParam(tileX - (m_flag[0]?-1:1), tileY - 1) != Def.PHB_SOLID)
{
if (m_flag[0])
m_grabPosX = ((tileX+1) * GE.m_tileWidth) << 8;
else
m_grabPosX = (tileX * GE.m_tileWidth + 1) << 8;
m_grabPosY = (tileY * GE.m_tileHeight - 1) << 8;
return true;
}
//}
//}
return false;
}
private boolean tryHang()
{
int oldX = m_posX, oldY = m_posY;
m_posX = m_grabPosX;
m_posY = m_grabPosY;
setAction(Def.PRINCE_HANG, 0);
// nextFrame(true);
// nextFrame(true);
// check tile phy
int tileX = ((m_posX >> 8) + (m_colBoxNow[0] + m_colBoxNow[2])/2) / GE.m_tileWidth;
int tileY = ((m_posY >> 8) + m_colBoxNow[3]) / GE.m_tileHeight;
if (GE.getPhyParam(tileX, tileY) == Def.PHB_SOLID ||
GE.getPhyParam(tileX, tileY-1) == Def.PHB_SOLID )
{
// return to old state
m_posX = oldX;
m_posY = oldY;
setAction(curState, 0);
return false;
}
//hard coded face right hang
if (!m_flag[0]) m_posX += (2<<8);
nextState = Def.PRINCE_HANG;
return true;
}
private void toFall()
{
byte[] box = getColBox();
m_posY += (box[3] - box[1]) << 8;
setAction(Def.PRINCE_FALL, 1);
curState = nextState = Def.PRINCE_FALL;
box = getColBox();
int temp = ((box[2] - box[0])/2 + 4) << 8;
m_posX += m_flag[0]?temp:-temp;//m_flag[0]?8<<8:-8<<8;
if (checkTopBottom(CHECK_BOTTOM, true))
{
setAction(Def.PRINCE_NORMAL, 1);
curState = nextState = Def.PRINCE_NORMAL;
}
else
stopAction(false);
}
private final boolean checkDragMove()
{
return !(!m_flag[0] && (m_phbLeft >= Def.PHB_SOLID || checkGround(true) > 0) ||
m_flag[0] && (m_phbRight >= Def.PHB_SOLID || checkGround(false) > 0));
}
private boolean checkRoll()
{
if (ability[CAN_ROLL] > 0 && (GE.m_input[Def.KEY_L] == Def.Dn_Continuous2 || GE.m_input[Def.KEY_R] == Def.Dn_Continuous2))
{
if (m_energy > ENERGY_ROLL * 2)
{
nextState = Def.PRINCE_ROLL_READY;
return true;
}
if (GE.m_input[Def.KEY_L] == Def.Dn_Continuous2)
GE.m_input[Def.KEY_L] = Def.Dn_Continuous;
else
GE.m_input[Def.KEY_R] = Def.Dn_Continuous;
}
nextState = Def.PRINCE_RUN;
return false;
}
public boolean updateAI(int camX, int camY)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -