1.课设课题

1.1 基于java swing开发的魂斗罗

可实现的功能: 人物的移动射击以及跳跃
人物武器的切换
人物的死亡与重生
敌人的行为设定

1.2 UML设计图

魂斗罗游戏 java源代码 魂斗罗游戏 java源代码大全_碰撞检测

1.3 程序运行展示

uploading-image-813493.png


魂斗罗游戏 java源代码 魂斗罗游戏 java源代码大全_java_02

2.代码展示

代码地址:https://gitee.com/cai_feng_jun/contra

2.1 重点代码展示

难度选择模块

魂斗罗游戏 java源代码 魂斗罗游戏 java源代码大全_碰撞检测_03


魂斗罗游戏 java源代码 魂斗罗游戏 java源代码大全_java_04


独立一个窗口控制难度, 通过线程传参启动frame窗口

该部分代码运行结果如下:

魂斗罗游戏 java源代码 魂斗罗游戏 java源代码大全_i++_05

图像绘制模块

魂斗罗游戏 java源代码 魂斗罗游戏 java源代码大全_java_06


魂斗罗游戏 java源代码 魂斗罗游戏 java源代码大全_i++_07


绘制相关图片

键盘监听模块

魂斗罗游戏 java源代码 魂斗罗游戏 java源代码大全_java_08


根据玩家操控角色的操作, 判断是否做出相应的指令

角色的移动

private void heroMove()
	   {
	     if ((this.hero.state != 4) && (this.hero.state != 5))
	    	 
	       if ((!this.hero.jumping) && (!this.jumpDown) && (!this.leftDown) && (!this.rightDown) && (!this.upDown) && (!this.downDown)) 
	       {
	         this.hero.state = 0;
	         if (this.hero.towardsLeft) 
	         {
	           this.hero.direction = 6;
	         }
	         else if (this.hero.towardsRight) 
	         {
	           this.hero.direction = 2;
	         }
	       }
	       else if (this.hero.jumping) 
	       {
	         if (this.upDown) 
	         {
	           this.hero.direction = 0;
	           this.hero.state = 2;
	           if ((this.leftDown) && (!this.showBossScene)) 
	           {
	             this.hero.direction = 7;
	             this.hero.towardsLeft = true;
	             this.hero.towardsRight = false;
	             if (this.hero.position.x > 8.0F + this.mapPosition)
	               this.hero.position.x -= this.heroSpeed;
	           }
	           else if ((this.rightDown) && (!this.showBossScene)) {
	             this.hero.direction = 1;
	             this.hero.towardsLeft = false;
	             this.hero.towardsRight = true;
	             moveForwardToRight();
	           }
	         }
	         else if (this.downDown) 
	         {
	           this.hero.direction = 4;
	           this.hero.state = 2;
	           if (this.leftDown) 
	           {
	             this.hero.direction = 5;
	             this.hero.towardsLeft = true;
	             this.hero.towardsRight = false;
	             if (this.hero.position.x > 8.0F + this.mapPosition)
	               this.hero.position.x -= this.heroSpeed;
	           }
	           else if ((this.rightDown) && (!this.showBossScene)) 
	           {
	             this.hero.direction = 3;
	             this.hero.towardsLeft = false;
	             this.hero.towardsRight = true;
	             moveForwardToRight();
	           }
	         }
	         else if ((this.leftDown) && (!this.showBossScene)) 
	         {
	           this.hero.direction = 6;
	           this.hero.state = 2;
	           this.hero.towardsLeft = true;
	           this.hero.towardsRight = false;
	           if (this.hero.position.x > 8.0F + this.mapPosition)
	           this.hero.position.x -= this.heroSpeed;
	         }
	         else if ((this.rightDown) && (!this.showBossScene)) {
	           this.hero.direction = 2;
	           this.hero.state = 2;
	           this.hero.towardsLeft = false;
	           this.hero.towardsRight = true;
	           moveForwardToRight();
	         }
	 
	       }
	       else if ((this.leftDown) && (!this.showBossScene)) 
	       {
	         if ((this.jumpDown) && (isGrassLand(this.hero.position.x, this.hero.position.y + 1.0F)))
	         {
	           this.hero.direction = 6;
	           this.hero.state = 2;
	           this.hero.towardsLeft = true;
	           this.hero.towardsRight = false;
	           this.hero.jumping = true;
	           this.hero.jumpFinished = false;
	         }
	         else if (this.upDown) {
	           this.hero.state = 1;
	           this.hero.direction = 7;
	           this.hero.towardsLeft = true;
	           this.hero.towardsRight = false;
	           if (this.hero.position.x > 8.0F + this.mapPosition)
	             this.hero.position.x -= this.heroSpeed;
	         }
	         else if (this.downDown) {
	           this.hero.direction = 5;
	           this.hero.state = 1;
	           this.hero.towardsLeft = true;
	           this.hero.towardsRight = false;
	           if (this.hero.position.x > 8.0F + this.mapPosition)
	             this.hero.position.x -= this.heroSpeed;
	         }
	         else
	         {
	           this.hero.state = 1;
	           this.hero.direction = 6;
	           this.hero.towardsLeft = true;
	           this.hero.towardsRight = false;
	           if (this.hero.position.x > 8.0F + this.mapPosition)
	             this.hero.position.x -= this.heroSpeed;
	         }
	       }
	       else if ((this.rightDown) && (!this.showBossScene)) 
	       {
	         if ((this.jumpDown) && (isGrassLand(this.hero.position.x, this.hero.position.y + 1.0F))) {
	           this.hero.direction = 2;
	           this.hero.state = 2;
	           this.hero.towardsLeft = false;
	           this.hero.towardsRight = true;
	           this.hero.jumping = true;
	           this.hero.jumpFinished = false;
	         }
	         else if (this.upDown) {
	           this.hero.direction = 1;
	           this.hero.state = 1;
	           this.hero.towardsLeft = false;
	           this.hero.towardsRight = true;
	           moveForwardToRight();
	         }
	         else if (this.downDown) 
	         {
	           this.hero.direction = 3;
	           this.hero.state = 1;
	           this.hero.towardsLeft = false;
	           this.hero.towardsRight = true;
	           moveForwardToRight();
	         }
	         else
	         {
	           this.hero.direction = 2;
	           this.hero.state = 1;
	           this.hero.towardsLeft = false;
	           this.hero.towardsRight = true;
	           moveForwardToRight();
	         }
	       }
	       else if (this.upDown) {
	         if ((this.jumpDown) && (isGrassLand(this.hero.position.x, this.hero.position.y + 1.0F))) {
	           this.hero.direction = 0;
	           this.hero.state = 2;
	           this.hero.jumpFinished = false;
	           this.hero.jumping = true;
	         }
	         else
	         {
	           this.hero.state = 0;
	           this.hero.direction = 0;
	         }
	       }
	       else if (this.downDown) 
	       {
	         if (this.jumpDown) 
	         {
	           this.hero.state = 1;
	         }
	         else
	         {
	           this.hero.state = 3;
	           if (this.hero.direction == 3) {
	             this.hero.direction = 2;
	           }
	           else if (this.hero.direction == 5) {
	             this.hero.direction = 6;
	           }
	         }
	       }
	       else if ((this.jumpDown) && (isGrassLand(this.hero.position.x, this.hero.position.y + 1.0F)))
	       {
	         this.hero.state = 2;
	         this.hero.jumping = true;
	         this.hero.jumpFinished = false;
	       }
	   }

通过对角色当前状态的属性进行判定, 以此为依据来控制角色的移动. 以及角色是否处于可站立的位置

地图移动模块(只可向右移动)

魂斗罗游戏 java源代码 魂斗罗游戏 java源代码大全_碰撞检测_09


判定角色在屏幕中所处的位置, 当角色处于屏幕中央位置及向右移动时, 地图随之向右移动.

角色死亡后的出生点判断

魂斗罗游戏 java源代码 魂斗罗游戏 java源代码大全_java_10


魂斗罗游戏 java源代码 魂斗罗游戏 java源代码大全_碰撞检测_11


魂斗罗游戏 java源代码 魂斗罗游戏 java源代码大全_碰撞检测_12

角色死亡后将会出生在屏幕最左端的可站立的方块上
需要对角色位置进行判定的是是否通过移动方块, 若未通过, 佳能复活在移动方块左端的方块之上

角色的死亡判定(碰撞检测)

private void heroDeathCheck()
    {
      if ((this.hero.state != 4) && (this.hero.state != 5)) 
      {
        for (int i = 0; i < this.enemyBullets.size(); i++) 
        {
          Bullet b = (Bullet)this.enemyBullets.get(i);
          if ((b.position.x > this.hero.position.x - this.hero.width / 2 / 3) && (b.position.x < this.hero.position.x + this.hero.width / 2 / 3) && 
            (b.position.y > this.hero.position.y - this.hero.height / 3) && (b.position.y < this.hero.position.y) && 
            (this.hero.visible)) 
          {
            this.hero.state = 4;
            this.hero.deathEventType = 0;
            this.enemyBullets.remove(i);
          }
        }
  
        for (int i = 0; i < this.enemys.size(); i++) 
        {
          SimpleEnemy e = (SimpleEnemy)this.enemys.get(i);
          if ((e.state != 4) && (e.state != 5) && 
            (this.hero.position.x > e.position.x - this.hero.width / 2 / 3 - 11.0F) && (this.hero.position.x < e.position.x + 11.0F + this.hero.width / 2 / 3) && 
            (this.hero.position.y > e.position.y - 26.0F) && (this.hero.position.y < e.position.y + this.hero.height / 3)) {
            if (this.hero.visible) {
              this.hero.state = 4;
              this.hero.deathEventType = 2;
            }
            else {
              e.state = 4;
            }
          }
        }
  
        for (int i = 0; i < this.bossChildren.size(); i++) 
        {
          BossChild e = (BossChild)this.bossChildren.get(i);
          if ((e.state != 4) && (e.state != 5) && 
            (this.hero.position.x > e.position.x - this.hero.width / 2 / 3 - 15.0F) && (this.hero.position.x < e.position.x + 15.0F + this.hero.width / 2 / 3) && 
            (this.hero.position.y > e.position.y - 10.0F) && (this.hero.position.y < e.position.y + this.hero.height / 3) && 
            (this.hero.visible)) {
            this.hero.state = 4;
            this.hero.deathEventType = 2;
          }
        }
      }
    }

判断角色是否与子弹或敌人相撞, 或判定角色是否出界

可站立方块的设定

private void initGrassLands()
	   {
	     FloatPoint[] points = 
	    { 
	       new FloatPoint(1.0F, 110.0F), new FloatPoint(5.0F, 142.0F), new FloatPoint(8.0F, 174.0F), 
	       new FloatPoint(9.0F, 206.0F), new FloatPoint(11.0F, 174.0F), new FloatPoint(13.0F, 142.0F), new FloatPoint(18.0F, 206.0F), 
	       new FloatPoint(19.0F, 158.0F), new FloatPoint(27.0F, 110.0F), new FloatPoint(36.0F, 110.0F), new FloatPoint(42.0F, 78.0F), 
	       new FloatPoint(43.0F, 206.0F), new FloatPoint(46.0F, 160.0F), new FloatPoint(49.0F, 142.0F), new FloatPoint(53.0F, 206.0F), 
	       new FloatPoint(57.0F, 110.0F), new FloatPoint(59.0F, 174.0F), new FloatPoint(62.0F, 174.0F), new FloatPoint(63.0F, 78.0F), 
	       new FloatPoint(65.0F, 158.0F), new FloatPoint(67.0F, 142.0F), new FloatPoint(69.0F, 110.0F), new FloatPoint(72.0F, 142.0F), 
	       new FloatPoint(72.0F, 206.0F), new FloatPoint(73.0F, 174.0F), new FloatPoint(76.0F, 110.0F), new FloatPoint(77.0F, 78.0F), 
	       new FloatPoint(77.0F, 206.0F), new FloatPoint(78.0F, 158.0F), new FloatPoint(80.0F, 110.0F), new FloatPoint(81.0F, 142.0F), 
	       new FloatPoint(84.0F, 206.0F), new FloatPoint(88.0F, 174.0F), new FloatPoint(91.0F, 142.0F), new FloatPoint(93.0F, 110.0F), 
	       new FloatPoint(93.0F, 206.0F), new FloatPoint(94.0F, 158.0F), new FloatPoint(98.0F, 142.0F), new FloatPoint(99.0F, 174.0F), 
	       new FloatPoint(24.0F, 110.0F), new FloatPoint(33.0F, 110.0F) 
	    };
	     int[] lengths = { 22, 3, 1, 2, 1, 2, 2, 3, 5, 8, 16, 3, 2, 7, 6, 7, 2, 2, 5, 1, 3, 2, 2, 1, 3, 2, 2, 1, 1, 2, 5, 3, 2, 2, 5, 22, 4, 1, 1, 1, 1 };
	     for (int i = 0; i < points.length - 2; i++) {
	       GrassLand gl = new GrassLand(points[i], lengths[i]);
	       this.grassLands[i] = gl;
	     }
	     GrassLand movingGrassLand1 = new GrassLand(new FloatPoint(24.0F, 110.0F), 1);
	     GrassLand movingGrassLand2 = new GrassLand(new FloatPoint(33.0F, 110.0F), 1);
	     movingGrassLand1.movingDirection = 3;
	     movingGrassLand2.movingDirection = 3;
	     this.grassLands[(this.grassLands.length - 2)] = movingGrassLand1;
	     this.grassLands[(this.grassLands.length - 1)] = movingGrassLand2;
	   }
	private void drawNPC(Graphics2D g)
	{
	     this.grassLands[(this.grassLands.length - 2)].drawMovingGrassLand(this.hero, 23.4F, 25.799999F, (int)this.mapPosition, this.backgroundSizeOfWidth, this, g);
	     this.grassLands[(this.grassLands.length - 1)].drawMovingGrassLand(this.hero, 32.400002F, 34.799999F, (int)this.mapPosition, this.backgroundSizeOfWidth, this, g);
	}
	private boolean isGrassLand(float x, float y) {
	     if (this.hero.towardsRight) {
	       for (int i = 0; i < this.grassLands.length; i++) {
	         if ((x > this.grassLands[i].position.x * 32.0F - 7.0F) && (x < (this.grassLands[i].position.x + this.grassLands[i].length) * 32.0F + 3.0F) && 
	           (y > this.grassLands[i].position.y) && (y < this.grassLands[i].position.y + 5.0F))
	           return true;
	       }
	     }
	     else if (this.hero.towardsLeft) {
	       for (int i = 0; i < this.grassLands.length; i++) {
	         if ((x > this.grassLands[i].position.x * 32.0F - 7.0F) && (x < (this.grassLands[i].position.x + this.grassLands[i].length) * 32.0F + 1.0F) && 
	           (y > this.grassLands[i].position.y) && (y < this.grassLands[i].position.y + 5.0F))
	           return true;
	       }
	     }
	     else if ((!this.hero.towardsLeft) && (!this.hero.towardsRight)) {
	       for (int i = 0; i < this.grassLands.length; i++) {
	         if ((x > this.grassLands[i].position.x * 32.0F) && (x < (this.grassLands[i].position.x + this.grassLands[i].length) * 32.0F) && 
	           (y > this.grassLands[i].position.y) && (y < this.grassLands[i].position.y + 5.0F))
	           return true;
	       }
	     }
	     return false;
	   }

规定角色可以站立而不死亡的位置

3.代码改进及任务的分配

3.1

在学习了借鉴的代码之后, 我们对其进行了一定程度的优化, 增加了一些原来没有的功能
1.增加了难度的设置, 让玩家有了更多的选择
2.使用了缓存的技术, 解决了闪屏的问题
3.增加了角色的死亡位置判定, 使其能在移动方块左方出生