📄 planecanvas.java
字号:
// 保存游戏设置(速度)
dos.writeInt(sleepTime);
// 保存当前地图数据
dos.writeInt(mapX);
dos.writeInt(mapY);
// 将数据存入byte数组
byte[] data = baos.toByteArray();
// 将数据存入记录集中
int RMSIndex = rs.getNumRecords();
if (RMSIndex == 0) {
rs.addRecord(data, 0, data.length);
} else {
rs.setRecord(1, data, 0, data.length);
}
// 关闭流
dos.close();
baos.close();
// 关闭记录集
rs.closeRecordStore();
// 设置存档是否存在标志
record = true;
} catch (Exception e) {
record = false;
}
}
/** 加载游戏 */
private void loadingGame() {
// 打开记录集,异常时界面提示
try {
RecordStore rs = RecordStore.openRecordStore("saving", false);
int RMSIndex = rs.getNumRecords();
if (RMSIndex == 1) {
byte[] data = rs.getRecord(1);
// 创建输入流对象
ByteArrayInputStream bais = new ByteArrayInputStream(data);
DataInputStream dis = new DataInputStream(bais);
// 恢复pp数组数据
for (int i = 0; i < pp.length; i++) {
pp[i] = dis.readInt();
}
// 恢复ep数组数据
for (int i = 0; i < ep.length; i++) {
for (int j = 0; j < ep[0].length; j++) {
ep[i][j] = dis.readInt();
}
}
// 恢复pb数组数据
for (int i = 0; i < pb.length; i++) {
for (int j = 0; j < pb[0].length; j++) {
pb[i][j] = dis.readInt();
}
}
// 恢复increaseDelay数组数据
for (int i = 0; i < increaseDelay.length; i++) {
for (int j = 0; j < increaseDelay[0].length; j++) {
increaseDelay[i][j] = dis.readInt();
}
}
// 恢复eb数组数据
for (int i = 0; i < eb.length; i++) {
for (int j = 0; j < eb[0].length; j++) {
eb[i][j] = dis.readInt();
}
}
// 恢复ppBlast数组数据
for (int i = 0; i < ppBlast.length; i++) {
for (int j = 0; j < ppBlast[0].length; j++) {
ppBlast[i][j] = dis.readInt();
}
}
// 恢复blastArray数组数据
for (int i = 0; i < blastArray.length; i++) {
for (int j = 0; j < blastArray[0].length; j++) {
blastArray[i][j] = dis.readInt();
}
}
// 恢复计时器
delay = dis.readInt();
times = dis.readInt();
shotDelay = dis.readInt();
// 恢复游戏关卡状态
// gameState = dis.readInt();//该状态会影响加载界面显示
gate = dis.readInt();
gateState = dis.readInt();
// 恢复游戏设置(速度)
sleepTime = dis.readInt();
// 恢复当前地图数据
mapX = dis.readInt();
mapY = dis.readInt();
// 关闭流
dis.close();
bais.close();
// 关闭记录集
rs.closeRecordStore();
}
} catch (Exception e) {
record = false;
}
}
/** 绘制关卡地图 */
private void drawGateMap(Graphics g) {
switch (gameState) {
case GAME_CONTINUE:
switch (gate) {
case 1:
switch (gateState) {
case GATE_OPEN:
// 绘制关卡logo
g.setFont(font);
g.setColor(0);
g.fillRect(0, 0, width, height);
g.setColor(0, 255, 0);
g.drawString("第一关", width / 2, 110, Graphics.TOP
| Graphics.HCENTER);
g.drawString("城市上空的鹰", width / 2, 170, Graphics.TOP
| Graphics.HCENTER);
break;
case GATE_CONTINUE:
// 绘制场景
g.drawImage(map1Img, mapX, mapY, Graphics.TOP
| Graphics.LEFT);
break;
}
break;
case 2:
switch (gateState) {
case GATE_OPEN:
g.setFont(font);
g.setColor(0);
g.fillRect(0, 0, width, height);
g.setColor(0, 255, 0);
g.drawString("第二关", width / 2, 110, Graphics.TOP
| Graphics.HCENTER);
g.drawString("鹰击千岛长空", width / 2, 170, Graphics.TOP
| Graphics.HCENTER);
break;
case GATE_CONTINUE:
// 绘制场景
drawMapImg(g);
break;
}
break;
}
break;
}
}
/** 绘制关卡块地图场景(从第二关开始) */
private void drawMapImg(Graphics g) {
for (int row = 0; row < 16; row++) {
for (int col = 0; col < 12; col++) {
if (mapY + SCREENSPEED < height) {
// 设置下面绘制的剪切区域
g.setClip(col * 20, row * 20 + mapY, 20, 20);
// 画场景图层
g.drawImage(map2Img, col * 20
- ((mapArray[row][col] - 1) % 4) * 20, row * 20
- ((mapArray[row][col] - 1) / 4) * 20 + mapY,
Graphics.TOP | Graphics.LEFT);
}
if (mapY + SCREENSPEED >= 0) {
// 设置上面绘制的剪切区域
g.setClip(col * 20, row * 20 + mapY - MAP2_HEIGHT, 20, 20);
// 画场景图层
g.drawImage(map2Img, col * 20
- ((mapArray[row][col] - 1) % 4) * 20, row * 20
- ((mapArray[row][col] - 1) / 4) * 20 + mapY
- MAP2_HEIGHT, Graphics.TOP | Graphics.LEFT);
}
}
}
// 剪切区域恢复默认
g.setClip(0, 0, width, height);
}
/** 创建玩家飞机 */
public void createPP() {
// 类别
pp[0] = PP;
// 可见性
pp[1] = 1;
// 动画帧索引
pp[2] = 1;
// HP初始值
pp[5] = 68;
// 宽
pp[6] = 34;
// 高
pp[7] = 26;
// 移动速度(移动时要加成屏幕移动速度)
pp[8] = 9;
// 左上x坐标
pp[3] = width / 2 - pp[6] / 2;
// 左上y坐标
pp[4] = height;
// 初始状态:新生
pp[9] = 0;
// 闪烁状态:闪烁
pp[10] = 1;
// pp[12]复活次数,为防止复活次数改写,新生时不赋值(初值0正好)
if (pp[12] == 0) { // 玩家未曾复活过
// 初始为无敌状态,
pp[13] = 1;
// 得分
pp[11] = 0;
// 级别为0
pp[14] = 0;
}
}
/** 玩家初始闪烁动画 */
public void playerState() {
// 如果处于新生状态
if (pp[9] == 0 & gateState == GATE_CONTINUE
& gameState == GAME_CONTINUE) {
delay++;
// 开启无敌
pp[13] = 1;
if (pp[10] == 1) {
// 不绘制
pp[10] = 0;
} else {
// 绘制
pp[10] = 1;
}
// 移动飞机
pp[4] -= 3;
// 正常状态
if (delay > 14) {
pp[9] = 1;
pp[10] = 1;
// 关闭无敌
pp[13] = 0;
delay = 0;
}
}
}
/**
* 玩家无敌效果(生命值满,能连续使用必杀技)
*/
private void invincibility() {
// 开启无敌,则锁定生命,解除必杀技限制
if (unlock) {
pp[13] = 1;
if (pp[14] == 0) {
pp[5] = 68;
} else if (pp[14] == 1) {
pp[5] = 136;
} else {
pp[5] = 204;
}
}
}
/** *玩家升级(级别与炮弹类别对应) */
private void upgrade() {
if (pp[11] < UPGREAD_01) {
pp[14] = 0;
} else if (pp[11] < UPGREAD_02) {
pp[14] = 1;
} else {
pp[14] = 2;
if (!unlock) {
if (pp[11] > INVINCIBILITY_SCORE) {
pp[13] = 1;
} else {
pp[13] = 0;
}
}
}
}
/**
* 必杀技(衍生弹添加)逻辑(Fire键激发)
*
* @param x参考点(取生成衍生炮弹区域的中点)左上坐标x
* @param y参考点(取生成衍生炮弹区域的中点)左上坐标y
* @param n衍生代标识,初始为0,次为1,再为2
*/
private void Invincibility_Logicol(int x, int y, int n) {
for (int i = 0; i < (n * n + 2 * n - n / 2 + 1); i++) { // 1,4,8
for (int j = 0; j < pb.length; j++) {
// 添加炮弹
if (pb[j][1] == 0) {
// 炮弹类别
pb[j][0] = 3;
// 可见
pb[j][1] = 1;
// 炮弹图片宽
pb[j][4] = 10;
// 炮弹图片高
pb[j][5] = 10;
// 炮弹伤害值(4,8,12,16)
pb[j][6] = 16;
// 炮弹x向速度
pb[j][7] = 6;
// 炮弹y向速度
pb[j][8] = 10;
// 炮弹衍生代标识
pb[j][9] = n;
// 炮弹生成序号
pb[j][10] = i;
// 定位出现坐标
switch (pb[j][10]) {
case 0:// 上
// 炮弹左上x坐标
pb[j][2] = x;
// 炮弹左上y坐标
pb[j][3] = y - 22;
break;
case 1:// 下
// 炮弹左上x坐标
pb[j][2] = x;
// 炮弹左上y坐标
pb[j][3] = y + 22;
break;
case 2:// 左
// 炮弹左上x坐标
pb[j][2] = x - 22;
// 炮弹左上y坐标
pb[j][3] = y;
break;
case 3:// 右
// 炮弹左上x坐标
pb[j][2] = x + 22;
// 炮弹左上y坐标
pb[j][3] = y;
break;
case 4:// 左上
// 炮弹左上x坐标
pb[j][2] = x - 17;
// 炮弹左上y坐标
pb[j][3] = y - 17;
break;
case 5:// 左下
// 炮弹左上x坐标
pb[j][2] = x - 17;
// 炮弹左上y坐标
pb[j][3] = y + 17;
break;
case 6:// 右上
// 炮弹左上x坐标
pb[j][2] = x + 17;
// 炮弹左上y坐标
pb[j][3] = y - 17;
break;
case 7:// 右下
// 炮弹左上x坐标
pb[j][2] = x + 17;
// 炮弹左上y坐标
pb[j][3] = y + 17;
break;
}
break;
}
}
}
}
/**
* 玩家飞机连续移动
*
* @param repeat连续按键状态(对应方向)
*/
private void PPMove(int repeat) {
if (pp[1] == 0 || gameState != GAME_CONTINUE
|| gateState != GATE_CONTINUE) {
return;
}
// 玩家飞机动画
if (pp[2] == 1) {
pp[2] = 2;
} else if (pp[2] == 2) {
pp[2] = 3;
} else {
pp[2] = 1;
}
switch (repeat) {
case MOVE_UP: //加成屏移速度,再微调1,不变算了
pp[4] -= pp[8];
// 边界检测(防止玩家飞机躲到最上面通关的bug)
if (pp[4] < pp[6] + 30) {
pp[4] = pp[6] + 30;
}
break;
case MOVE_DOWN:
pp[4] += pp[8];
// 边界检测
if (pp[4] > height - pp[7]) {
pp[4] = height - pp[7];
}
break;
case MOVE_LEFT:
pp[3] -= pp[8];
// 边界检测
if (pp[3] < 0) {
pp[3] = 0;
}
break;
case MOVE_RIGHT:
pp[3] += pp[8];
// 边界检测
if (pp[3] > width - pp[6]) {
pp[3] = width - pp[6];
}
break;
}
}
/** 绘制玩家飞机及其生命条 */
private void drawPP(Graphics g) {
// 可见时绘制飞机
if (pp[1] == 1 && pp[10] == 1) {
// 设置剪切区域
g.setClip(pp[3], pp[4], pp[6], pp[7]);
g.drawImage(planeImg[PP], pp[3] - (pp[2] - 1) % 3 * pp[6], pp[4],
Graphics.TOP | Graphics.LEFT);
// 恢复剪切区域
g.setClip(0, 0, width, height);
// HP
g.setColor(255, 0, 0);
g.fillRect(pp[3], pp[4] + 27, pp[5] / ((pp[14] + 1) * 2), 3);
// HP边框
g.setColor(5, 253, 238);
g.drawRect(pp[3], pp[4] + 27, 34, 3);
}
}
/** 玩家飞机开火(添加炮弹到pb[][]数组) */
private void PPFire() {
// 处于新生或不可见状态时,不添加炮弹
if (pp[9] == 0 || pp[1] == 0) {
return;
}
shotDelay++;
if (shotDelay % 3 == 2) { // 防止计数器失控bug,改为取余
for (int i = 0; i < pb.length; i++) {
// 找到不可见的下标,添加、初始化
if (pb[i][1] == 0) {
// 可见
pb[i][1] = 1;
// 炮弹类别取等玩家级别
pb[i][0] = pp[14];
// 炮弹图片宽、高
switch (pp[14]) {
case 0:
pb[i][4] = 3;
pb[i][5] = 11;
break;
case 1:
pb[i][4] = 9;
pb[i][5] = 11;
break;
case 2:
pb[i][4] = 17;
pb[i][5] = 14;
break;
}
// 炮弹左上x坐标(调整1)
pb[i][2] = pp[3] + 1 + (pp[6] - pb[i][4]) / 2;
// 炮弹左上y坐标
pb[i][3] = pp[4] + pb[i][5];
// 炮弹伤害值(4,7,12,19)
pb[i][6] = pb[i][0] * (pb[i][0] + 2) + 4;
// 炮弹x向速度
pb[i][7] = 8;
// 炮弹y向速度
pb[i][8] = 10;
shotDelay = 0;
break;
}
}
}
}
/** 玩家炮弹移动 */
private void PbMove() {
if (gameState != GAME_CONTINUE || gateState != GATE_CONTINUE) {
return;
}
for (int i = 0; i < pb.length; i++) {
if (pb[i][1] == 1) {
if (pb[i][0] == 3) {
// 0代的移动
if (pb[i][9] == 0) {
// 先绝对向上移动,冲减卷屏速度
pb[i][3] -= 4;
int distance = 540;
for (int j = 0; j < ep.length; j++) { // 敌人飞机
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -