📄 actor.java
字号:
package pop2;
import javax.microedition.lcdui.*;
import java.io.*;
/**
* <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 Actor
{
final static int FLAG_FLIPX = 0x01;
final static int FLAG_FLIPY = 0x02;
final static int FLAG_IGNORE = 0x04;
final static int FLAG_ACTIVE = 0x08;
// class
Animation m_anim;
int m_animID;
// these varibles have low 8 bits as fraction
int m_posX; // X position
int m_posY; // Y position
int m_vX; // X velocity
int m_vY; // Y velocity
int m_aX; // X acceleration
int m_aY; // Y acceleration
int m_grabPosX; // X position of grab tile point
int m_grabPosY; // Y position of grab tile point
//boolean m_inActiveZone; // actor is in active zone
//short[] m_activeZone = new short[4]; // left, top, right, bottom
boolean m_flag[] = new boolean[4]; // flipX, flipY, ignore active zone, active
byte[] m_parameters; // parameters
byte m_phbLeft; // left phb of player
byte m_phbTop; // top phb of player
byte m_phbRight; // right phb of player
byte m_phbBottom; // bottom phb of player
int m_frameIndex;
int m_actionIDNow;
int m_frameIDNow;
byte m_durNow;
boolean m_actionNoCycle;
boolean m_actionOver;
byte[] m_colBoxNow;
Actor m_relativeMisc;
// parameter
int m_hp, m_maxhp;
int m_start1/*bornx*/, m_start2/*borny*/;
int m_counter; // HM: 0-strike 1-trust BM: 0-fire1 1-fire2 PRINCE:invincible
final int RECOVER_TIME = 45;
//static Random rand = new Random(System.currentTimeMillis());
public Actor()
{
}
public void loadActor(byte[] data, int offset)
{
offset += 2; // actor data size
m_animID = data[offset++];
m_anim = Player.m_anims[m_animID];
m_actionIDNow = data[offset++];
int flag = data[offset++];
m_flag[0] = (flag & FLAG_FLIPX) != 0;
m_flag[1] = (flag & FLAG_FLIPY) != 0;
m_flag[2] = (flag & FLAG_IGNORE) != 0;
m_flag[3] = (flag & FLAG_ACTIVE) != 0;
int nPara = data[offset++];
m_posX = GE.readUnsignedShort(data, offset) << 8;
offset+=2;
m_posY = GE.readUnsignedShort(data, offset) << 8;
offset+=2;
offset+=8; // activeZone
if (nPara > 0)
{
m_parameters = new byte[nPara];
System.arraycopy(data, offset, m_parameters, 0, nPara);
}
setAction(m_actionIDNow, 1);
initAI();
}
public void packActor(byte[] data, int offset)
{
offset+=3; // actor data size & actor anim ID
if (m_animID != Def.ID_SAW && m_animID != Def.ID_NAIL)
{
if (m_animID == Def.ID_SANDMAN)
{
if (m_actionIDNow == Def.SANDMAN_BM_DEAD)
{
if (m_start1 != 0 && m_start2 != 0)
m_actionIDNow = Def.SANDMAN_HM_GUARD;
else
m_actionIDNow = Def.SANDMAN_HM_WALK;
}
else if(m_actionIDNow == Def.SANDMAN_HM_DEAD)
m_actionIDNow = Def.SANDMAN_BM_GUARD;
else if(m_actionIDNow == Def.SANDMAN_SMOKE)
m_flag[3] = false;
data[offset] = (byte)m_actionIDNow;
}
else if(m_animID == Def.ID_GHOST)
data[offset] = Def.GHOST_SLEEP;
else
data[offset] = (byte)m_actionIDNow;
}
offset++;
byte flag = 0;
if (m_flag[0]) flag += FLAG_FLIPX;
if (m_flag[1]) flag += FLAG_FLIPY;
if (m_flag[2]) flag += FLAG_IGNORE;
if (m_flag[3]) flag += FLAG_ACTIVE;
data[offset++] = flag;
if (m_animID == Def.ID_SAW || m_animID == Def.ID_NAIL || m_animID == Def.ID_GHOST)
return;
offset++; // npara
int temp = m_posX >> 8;
data[offset++] = (byte)(temp >> 8);
data[offset++] = (byte)temp;
temp = m_posY >> 8;
data[offset++] = (byte)(temp >> 8);
data[offset++] = (byte)temp;
}
// update actor state for each frame ---------------------------------------
// if the actor is not been update, return false.
boolean updateAI(int camX, int camY)
{
if (m_flag[3] == false)
return false;
if (m_frameIndex == -1)
return false;
switch (m_animID)
{
case Def.ID_SAW:
m_posX += m_vX;
m_posY += m_vY;
break;
case Def.ID_NAIL:
case Def.ID_PRINCE:
case Def.ID_SANDMAN:
case Def.ID_BOX:
// position & velocity, these must have some limitions.
checkEnvironment(false);
break;
}
m_vX += m_aX;
m_vY += m_aY;
if (m_vY > 0x1000) m_vY = 0x1000; // 16 pixel per frame
// Enemy AI
switch(m_animID)
{
case Def.ID_NAIL: aiNail(); break;
case Def.ID_GHOST: aiGhost(); break;
case Def.ID_SANDMAN: aiSandman(); break;
case Def.ID_SAW: aiSaw(); break;
case Def.ID_BOX: aiBox(); break;
case Def.ID_RSWORD: aiRSword(); break;
case Def.ID_TREADLE: aiTreadle(); break;
case Def.ID_BONUS: aiBonus(); break;
}
return true;
}
// set the next action ---------------------------------
void setAction(int actionID, int init)
{
m_actionOver = false;
m_actionIDNow = actionID;//m_anim.getAction(actionID);
if (m_actionIDNow == -1)
{
m_frameIndex = -1;
m_frameIDNow = -1;
getNewColBox();
}
else
{
m_frameIDNow = 0;
m_durNow = 0;
m_frameIndex = m_anim.getFrame(m_actionIDNow, m_frameIDNow);
m_actionNoCycle = false;
getNewColBox();
if ((init & 0x01) > 0)
{
byte mechModelID = m_anim.mechModelID[m_actionIDNow];
if ((mechModelID & 0x01) != 0)
{
m_vX = m_anim.mechModel[m_actionIDNow*4+0];
if (m_flag[0]) m_vX = -m_vX;
}
if ((mechModelID & 0x02) != 0)
{
m_vY = m_anim.mechModel[m_actionIDNow*4+1];
if (m_flag[1]) m_vY = -m_vY;
}
if ((mechModelID & 0x04) != 0)
{
m_aX = m_anim.mechModel[m_actionIDNow*4+2];
if (m_flag[0]) m_aX = -m_aX;
}
if ((mechModelID & 0x08) != 0)
{
m_aY = m_anim.mechModel[m_actionIDNow*4+3];
if (m_flag[1]) m_aY = -m_aY;
}
}
}
//return m_actionIDNow;
}
//------------------------------------------------------
// now : true for stop immediately
// false for stop when action is over
void stopAction(boolean now)
{
if (now)
m_durNow = -1;
else
m_actionNoCycle = true;
}
// calculate which frame is drawing ----------------------------------------
int nextFrame(boolean pass)
{
if (m_frameIndex == -1)
return -1;
if (m_durNow < 0)
return -1;
if (pass == false)
{
m_durNow++;
if (m_durNow < m_anim.getDuration(m_actionIDNow, m_frameIDNow))
return m_frameIndex;
}
m_frameIDNow++;
if (m_frameIDNow >= m_anim.nFrame[m_actionIDNow])
{
if (m_actionNoCycle)
m_frameIDNow--;
else
m_frameIDNow = 0;
m_actionOver = true;
}
m_frameIndex = m_anim.getFrame(m_actionIDNow, m_frameIDNow);
getNewColBox();
m_durNow = 0;
return m_frameIndex;
}
//------------------------------------------------------
public void draw(int camX, int camY)
{
camX = (m_posX >> 8) - camX;
camY = (m_posY >> 8) - camY;
m_anim.draw(camX, camY, m_flag[0], m_flag[1], m_frameIndex);
/* Lyman DEBUG, show col box & att box
if (GE.m_Debug2 == 1)
{
GE.m_g.setClip(0, 0, Def.PF_WIDTH, Def.PF_HEIGHT);
byte[] box = getColBox();
GE.m_g.setColor(0xFFFF00);
GE.m_g.drawRect(camX + box[0], camY + box[1], box[2] - box[0], box[3] - box[1]);
box = getAttBox();
if (box[0] != box[2])
{
GE.m_g.setColor(0xFF0000);
GE.m_g.drawRect(camX + box[0], camY + box[1], box[2] - box[0], box[3] - box[1]);
}
}
*/
if (GE.m_msgIndex < 0 && GE.m_gameState == Def.STATE_RUN) // stop action when draw message
nextFrame(false);
}
byte[] getNewColBox()
{
m_colBoxNow = new byte[4];
byte[] colBox = m_anim.frameData;
if (m_frameIndex != -1 && colBox != null)
{
m_colBoxNow[1] = colBox[m_frameIndex*8+1];
m_colBoxNow[3] = colBox[m_frameIndex*8+3];
if (m_flag[0]) // flipX
{
m_colBoxNow[0] = (byte)-colBox[m_frameIndex*8+2];
m_colBoxNow[2] = (byte)-colBox[m_frameIndex*8+0];
}
else
{
m_colBoxNow[0] = colBox[m_frameIndex*8+0];
m_colBoxNow[2] = colBox[m_frameIndex*8+2];
}
}
return m_colBoxNow;
}
byte[] getColBox()
{
if (m_colBoxNow == null)
getNewColBox();
return m_colBoxNow;
}
byte[] getAttBox()
{
byte[] attBox = m_anim.frameData;
byte[] box = new byte[4];
if (m_frameIndex != -1 && attBox != null)
{
box[1] = (byte)(attBox[m_frameIndex*8+4+1]);
box[3] = (byte)(attBox[m_frameIndex*8+4+3]);
if (m_flag[0]) // flipX
{
box[0] = (byte)-(attBox[m_frameIndex*8+4+2]);
box[2] = (byte)-(attBox[m_frameIndex*8+4+0]);
}
else
{
box[0] = (byte)(attBox[m_frameIndex*8+4+0]);
box[2] = (byte)(attBox[m_frameIndex*8+4+2]);
}
if (m_animID != Def.ID_PRINCE && m_animID != Def.ID_SANDMAN)
{
box[0] <<= 1;
box[1] <<= 1;
box[2] <<= 1;
box[3] <<= 1;
}
}
return box;
}
void setFlipX(boolean flipX)
{
if (m_flag[0] == flipX)
return;
m_flag[0] = flipX;
m_vX = -m_vX;
m_aX = -m_aX;
getNewColBox();
}
/*
void activeActor(boolean active)
{
m_flag[3] = active;
}//*/
// judge if the box is intersect with this actor's attack box
boolean intersectAttackBox(Actor actor)
{
return intersectBox(actor.m_posX, actor.m_posY, actor.getAttBox(), 0);
}
// judge if the box is intersect with this actor's box
boolean intersectColBox(Actor actor)
{
return intersectBox(actor.m_posX, actor.m_posY, actor.getColBox(), 0);
}
// judge if the box is intersect with this actor's box
boolean intersectBox(int x, int y, byte[] box, int extra)
{
if (box[0] == box[2]) return false;
byte[] colBox = getColBox();
//if (colBox == null) return false;
x = (x - m_posX) >> 8;
y = (y - m_posY) >> 8;
if (x + box[0] > colBox[2] + extra || y + box[1] > colBox[3] + extra)
return false;
if (x + box[2] < colBox[0] - extra || y + box[3] < colBox[1] - extra)
return false;
return true;
}
// check the left, top , right, bottom of player, give the right position and speed
boolean checkEnvironment(boolean v)
{
if (!v && m_vX == 0 && m_vY == 0)
return false;
boolean checkX = (m_vX == 0);
boolean checkY = (m_vY == 0);
// get deltaX & deltaY
int times = Math.max(Math.abs(m_vX / GE.m_tileWidth) >> 8, Math.abs(m_vY / GE.m_tileHeight) >> 8) + 1;
int deltaX = m_vX / times, deltaY = m_vY / times;
// init phb
m_phbLeft = Def.PHB_NONE;
m_phbRight = Def.PHB_NONE;
m_phbTop = Def.PHB_NONE;
m_phbBottom = Def.PHB_NONE;
// check tile by tile
if (checkY)
checkLeftRight(CHECK_CENTER, false);
if (m_flag[0]) // prince face left, then check left first
{
if (checkLeftRight(CHECK_LEFT, false))
if (deltaX < 0) deltaX = 0;
if (checkLeftRight(CHECK_RIGHT, false))
if (deltaX > 0) deltaX = 0;
}
else
{
if (checkLeftRight(CHECK_RIGHT, false))
if (deltaX > 0) deltaX = 0;
if (checkLeftRight(CHECK_LEFT, false))
if (deltaX < 0) deltaX = 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -