注:游戏开发样式借鉴原“保卫萝卜3”
运用技术
1:java 继承 封装 多肽 以及绘图工具 文件的输入流
开发工具 Eclipse ps。
界面效果
1:游戏启动窗口
2:冒险模式
3:关卡内效果
部分代码展示
1:角色工厂
package game;
import java.util.ArrayList;
import org.omg.CORBA.PUBLIC_MEMBER;
import game.Attack.Attacks;
import game.Attack.Attacks;
import game.Explod.Explod_T;
import game.FormArea.*;
import game.MaoxianWindow.*;
import game.MaoxianWindow.ChangJing1.*;
import game.MaoxianWindow.GuanKa.GuanKa;
import game.MaoxianWindow.GuanKa.GuanKa1;
import game.Monsters.*;
import game.Obstacles.*;
import game.Paota.*;
import game.StartWindow.*;
import game.Themes.*;
public class Factory {
// 游戏中最开始被默认隐藏的角色
// 窗口选择(初始都为不显示)
// 游戏主窗口
public static StartWindow startWindow = null;
// 关卡窗口
public static ThemesWindow ThemesWindow = null;
// 冒险窗口
public static MaoxianWindow maoxianWindow = null;
// 选择关卡窗口
public static ChangeGuanKaWindow changethemeswindow = null;
// 金币
public static FormArea formarer = new FormArea(198,30);
// 菜单按钮
public static Form form = new Form(760, 30);
// 暂停
public static Stop stop = new Stop(700, 32);
public static GameStop gamestop = new GameStop(430, 34);
// 初始游戏窗口选项按钮
public static Maoxian maoxian = new Maoxian(100, 420);
public static Boss boss = new Boss(410, 420);
public static Guaiwu guaiwu = new Guaiwu(720, 420);
// 关卡的选择
public static Getback getback = new Getback(50, 33);
public static Return ret = new Return(200, 415);
public static ChangJing1 changjing1 = new ChangJing1(50, 100);
public static ChangJing2 changjing2 = new ChangJing2(400, 100);
public static ChangJing3 changjing3 = new ChangJing3(750, 100);
public static ChangJing4 changjing4 = new ChangJing4(50, 300);
public static ChangJing5 changjing5 = new ChangJing5(400, 300);
public static More more = new More(750, 300);
public static GuanKa guanka = null;
//大关卡
public static int DaGuanKa = 0;
// 障碍物
public static ArrayList<Obstacles> obstacle = new ArrayList<Obstacles>();
// 菜单
public static GameMenue gamemenue = new GameMenue(312, 126);
// 萝卜
public static Luobu luobu = new Luobu();
// 游戏中怪物的行走路径
public static RoadWay roadWay = new RoadWay();
// 把场景创建进角色工厂
public static Theme theme = null;
// 炮塔动态数组
public static ArrayList<Paota> paotas = new ArrayList<Paota>();
//选地
public static Location change =new Location();
//建塔
public static PaotaCard paotacards=new PaotaCard();
//升级
public static Upup up=new Upup();
//加载中。。。
public static boolean Loading = false;
//倒数
public static boolean Daoshu=false;
// 测试monster
public static ArrayList<Monster> monsters = new ArrayList<Monster>();
// 测试爆炸效果
public static ArrayList<Explod_T> e_t = new ArrayList<Explod_T>();
// 测试子弹
public static ArrayList<Attacks> T_A = new ArrayList<Attacks>();
//游戏暂停
public static boolean Stop =false;
//重新开始
public static void NewGame(){
roadWay.TackNum();
paotas = new ArrayList<Paota>();
monsters = new ArrayList<Monster>();
T_A = new ArrayList<Attacks>();
e_t = new ArrayList<Explod_T>();
Stop =false;
up=new Upup();
paotacards=new PaotaCard();
change =new Location();
luobu.hp=7;
theme.monsterCount=7;
Factory.formarer.money=1000;
Loading=true;
Daoshu=true;
}
}
2:记分版
package game.FormArea;
import java.awt.Color;
import java.awt.Font;
import game.Factory;
import game.resources.Res;
import net.zj.game.Pen;
public class FormArea {
public int x;
public int y;
public int money=1000;
public FormArea(int x,int y){
this.x=x;
this.y=y;
}
/**
* 绘制
*/
public void draw(){
Pen.drawImage(Res.Pic.formArea, x,y,null);//计分板
Factory.roadWay.grid[0][2]='3';Factory.roadWay.grid[0][3]='3';Factory.roadWay.grid[0][4]='3';
Factory.roadWay.grid[0][5]='3';Factory.roadWay.grid[0][6]='3';Factory.roadWay.grid[0][7]='3';
Factory.roadWay.grid[0][8]='3';Factory.roadWay.grid[0][9]='3';
Pen.setColor(Color.YELLOW);
Pen.setFont(new Font("Tohoma",Font.BOLD,24));
Pen.drawString(money+"", 250, 60);
}
}
3:启动窗口
package game.StartWindow;
import java.awt.Toolkit;
import java.awt.event.MouseEvent;
import game.Factory;
import game.resources.Res;
import net.zj.game.GameFrame;
import net.zj.game.Pen;
public class StartWindow extends GameFrame {
public int x;
public int y;
public StartWindow(){
setSize(1024,512);//窗口大小 (正常显示的窗口大小为1000)
setTitle("保卫萝卜");//标题
setVisible(false);//是否显示
setCenter();//窗口居中
setbackImage(Res.Pic.backImg);
Res.Music.BGmusic.play();//添加游戏住背景音乐
Res.Music.BGmusic.loop();//背景音乐循环播放
}
@Override
public void mouseClicked(MouseEvent e) {
Factory.maoxian.ByCklick(e.getX(), e.getY());
}
@Override
public void animate() {
Pen.drawImage(Res.Pic.name, 380, 130, null);
Pen.drawGif(Res.Pic.a, 300, 100, null);
Factory.maoxian.draw();
Factory.boss.draw();
Factory.guaiwu.draw();
}
/**
* 居中 让游戏窗口居中
*/
public void setCenter(){
int width=Toolkit.getDefaultToolkit().getScreenSize().width;
int height=Toolkit.getDefaultToolkit().getScreenSize().height;
this.setLocation((width-1024)/2,(height-512)/2);
}
}
4:怪物类(抽象)
package game.Monsters;
import java.awt.Color;
import game.Factory;
import game.Luobu;
import game.resources.Res;
import net.zj.game.Pen;
import net.zj.game.TimerTicker;
import net.zj.game.gifutil.GIF;
/**
* 怪物抽象类
*
*/
public abstract class Monster {
public int x, y;// x,y坐标
public int dir;// 方向,(0为上,1为右,2为下,3为左)
public int lbDir;// 萝卜在怪物的哪个方向,用以控制怪物吃掉萝卜(0为上,1为右,2为下,3为左)
public boolean isBeAttack = false;// 是否被攻击,用以控制显示血条,默认为false(即没被攻击)
public int hp;// 血量
public int row, col;// 行,列
public int speed;// 怪物速度
public int control;// 控制,用以控制速度
public GIF gif;// 用以加载怪物图片
/**
* 构造器
*
* @param x
* 初始化x
* @param y
* 初始化y
*/
Monster(int x, int y, int dir, int lbDir) {
this.x = x;
this.y = y;
this.dir = dir;
this.lbDir = lbDir;
}
/**
* 绘制怪物方法
*
* @param pen
*/
public void draw() {
Pen.drawGif(gif, x, y, null);
if (isBeAttack == true) {
Pen.setColor(Color.GREEN);
Pen.fillRect(x, y, hp * 10, 3);
}
}
/**
* 怪物移动方法
*/
public void move() {
getRowCol(x, y);
Luobu lb = Factory.luobu;
if (this.row == lb.row && this.col == lb.col) {// 如果怪物所在行列与萝卜相同
switch (lbDir) {// 根据萝卜方向和行列判断怪物是否吃掉萝卜
case 0:// 如果萝卜最终在怪物上方
case 2:
if (this.y >= lb.y && this.y <= lb.y + 50) {// 如果y坐标位于萝卜图片位置以内
lb.beAttack();// 调用萝卜被攻击方法
Factory.monsters.remove(this);// 删除这只怪物
}
break;// 跳出switch
case 1:// 如果萝卜最终在怪物右方或左方
case 3:
if (this.x >= lb.x || this.x <= lb.x + 50) {// 如果x坐标位于萝卜图片位置以内
lb.beAttack();// 调用萝卜被攻击方法
Factory.monsters.remove(this);// 删除这只怪物
}
break;// 跳出switch
}
}
dir = getDir();// 获得方向
switch (dir) {// 根据方向移动
case 0:// 向上
y -= speed * control;
break;
case 1:// 向右
x += speed * control;
break;
case 2:// 向下
y += speed * control;
break;
case 3:// 向左
x -= speed * control;
break;
}
}
/**
* 计算行列
*/
public void getRowCol(int dx, int dy) {
row = (dy - 15) / 78;
col = (dx - 40) / 78;
}
/**
* 怪物被攻击方法
*/
public void beAttack() {
isBeAttack = true;// 变更是否被攻击状态为“是被攻击”
hp -= 2;
if (this.hp <= 0) {// 如果怪物血量小于0
Factory.formarer.money+=79;
Factory.theme.xx=this.x+20;
Factory.theme.yy=this.y-40;
Factory.monsters.remove(this);// 删除怪物
return;// 后续代码不执行
}
int oldHp = hp;// 获得目前血量
if (new TimerTicker(3).tickOver() && oldHp == hp)// 如果3秒后血量未曾发生变化
isBeAttack = false;// 变更是否被攻击状态为“未被攻击”
}
/**
* 方向探测器
*
* @return
*/
public int getDir() {
if (dir == 4)
return dir;
int dx = -1, dy = -1;
switch (dir) {
case 0:
dx = x;
dy = y - 20;
break;
case 1:
dx = x + 50 + 15;
dy = y;
break;
case 2:
dx = x;
dy = y + 50 + 22;
break;
case 3:
dx = x - 22;
dy = y;
break;
}
getRowCol(dx, dy);
if (row >= 0 && row < Factory.roadWay.grid.length && col >= 0 && col < Factory.roadWay.grid[0].length
&& Factory.roadWay.grid[row][col] == '1') {
return dir;
} else {
int d;
for (d = 0; d < 4; d++) {
if (dir - d == 2 || dir - d == -2)
continue;
dx = -1;
dy = -1;
switch (d) {
case 0:
dx = x;
dy = y - 20;
break;
case 1:
dx = x + 50 + 15;
dy = y;
break;
case 2:
dx = x;
dy = y + 50 + 22;
break;
case 3:
dx = x - 22;
dy = y;
break;
}
getRowCol(dx, dy);
if (row >= 0 && row < Factory.roadWay.grid.length && col >= 0 && col < Factory.roadWay.grid[0].length
&& Factory.roadWay.grid[row][col] == '1') {
break;
}
}
return d;
}
}
}
5:场景障碍物
package game.Obstacles;
import java.awt.image.BufferedImage;
import game.Factory;
import net.zj.game.Pen;
/**
* 场景障碍物的父类
* @author
* 后续在写子类的时候 给images赋值 赋值根据障碍物图片的颜色不同来进行分类
*/
public abstract class Obstacles {
public int x,y;
public int hp;
public int addMoney;
public int col,row;
//变量控制 数组中的第几章图片 (赋值改变选择图片)
public int state = 0;
//创建游戏障碍物图片数组 图片后续再子类中给予值 不在父类中写
public BufferedImage[] images;
//构造器
Obstacles(int row,int col,int state){
this.row = row;
this.col = col;
this.state = state;//初始化障碍物种类
}
/**
* 绘制方法
*/
public void draw(){
Pen.drawImage(images[state],x,y,null);//绘制方法 根据state改变绘制的图片 图片后续再子类中给予值 不在父类中写
}
/**
* 被攻击方法 (未调用)
*/
public void beAttack(){
hp--;
}
/**
* 获取行列 (后续子类如果需要占用多个格子的重写方法来改变 根据情况来定)
*/
public void getColRow(){
this.x=Factory.roadWay.getX(col)+10;//获取列
this.y=Factory.roadWay.getY(row);//获取行
// System.out.println(x+" "+y);
}
/**
* 种植进小院抽象方法需要后续子类进行修改
*/
public abstract void takeObstacles();
}
6:资源文件的处理
package game.resources;
import java.applet.AudioClip;
import java.awt.image.BufferedImage;
import net.zj.game.ImageUtil;
import net.zj.game.MusicUtil;
import net.zj.game.gifutil.GIF;
/**
* 资源加载
* @autho
* 2017.11.28
*/
public class Res {
//加载图片
public static class Pic{
//背景图片
public static BufferedImage backImg=ImageUtil.load("/images/main/main.png");
public static BufferedImage name=ImageUtil.load("/images/main/name.png");
public static BufferedImage maoxian=ImageUtil.load("/images/main/maoxian.png");
public static BufferedImage boss=ImageUtil.load("/images/main/boss.png");
public static BufferedImage guaiwu=ImageUtil.load("/images/main/guaiwu.png");
public static BufferedImage formArea=ImageUtil.load("/images/continue/formArea.png");
public static BufferedImage form=ImageUtil.load("/images/continue/form.png");
public static BufferedImage Stopgame=ImageUtil.load("/images/continue/stopgame.png");
//冒险关卡
public static BufferedImage back=ImageUtil.load("/images/Guanka/back.png");
public static BufferedImage getback=ImageUtil.load("/images/Guanka/getback.png");
public static BufferedImage ret=ImageUtil.load("/images/Guanka/return.png");
public static BufferedImage change=ImageUtil.load("/images/Guanka/change.png");
public static BufferedImage Guanka1=ImageUtil.load("/images/Guanka/Guanka-1.png");
public static BufferedImage Guanka2=ImageUtil.load("/images/Guanka/Guanka-2.png");
public static BufferedImage Guanka3=ImageUtil.load("/images/Guanka/Guanka-3.png");
public static BufferedImage Guanka4=ImageUtil.load("/images/Guanka/Guanka-4.png");
public static BufferedImage Guanka5=ImageUtil.load("/images/Guanka/Guanka-5.png");
public static BufferedImage more=ImageUtil.load("/images/Guanka/more.png");
public static BufferedImage monsterout=ImageUtil.load("/images/Monsters/Monster-out.png");
public static GIF a=ImageUtil.loadGif("/images/main/2.gif");
//游戏中菜单
public static BufferedImage gamemenue=ImageUtil.load("/images/continue/GameMenue.png");
public static BufferedImage cont=ImageUtil.load("/images/continue/continue.png");
public static BufferedImage xuanzhe=ImageUtil.load("/images/continue/change.png");
public static BufferedImage remove=ImageUtil.load("/images/continue/remove.png");
//游戏结束
public static BufferedImage GameOver=ImageUtil.load("/images/continue/GameOver.png");
public static BufferedImage Ko=ImageUtil.load("/images/continue/Ko.png");
//怪物时空门
public static BufferedImage monsterSpace = ImageUtil.load("/images/Change/out.png");
//游戏倒数
public static GIF Daoso = ImageUtil.loadGif("/images/Change/Daoshu.gif");
//增加金币
public static BufferedImage Money4 = ImageUtil.load("/images/Change/Money+4.png");
}
//加载音乐
public static class Music{
public static AudioClip BGmusic=MusicUtil.getMusic("/Music/BGmusic.wav");
public static AudioClip Accomplish=MusicUtil.getMusic("/Music/Accomplish.wav");
}
}
7:炮台
package game.Paota;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import game.Factory;
import game.Attack.Attacks;
import game.Attack.TArrowAttack;
import game.Attack.TRocktAttack;
import game.Monsters.*;
import game.Obstacles.Obstacles;
import net.zj.game.ImageUtil;
import net.zj.game.Pen;
import net.zj.game.TimerTicker;
public class TArrow extends Paota{
public TimerTicker ticker = new TimerTicker(2);
int degree = 0;
public Monster Monster[];
public boolean state1=true;
public boolean isRotate = false;// 是否可以旋转
BufferedImage img_rotate;
BufferedImage img_rotate_2;
BufferedImage img_rotate_3;
public Monster m;
public Obstacles o;
//public BufferedImage imgs[] = new BufferedImage[2];
public TArrow(int row, int col) {
super(row, col);
//底座
imgs[0]=ImageUtil.load("/images/Paota/TArrow/botton.png");
//炮塔小 中 大
imgs[1]=ImageUtil.load("/images/Paota/TArrow/TArrow-b.png");
imgs[2]=ImageUtil.load("/images/Paota/TArrow/TArrow-m.png");
imgs[3]=ImageUtil.load("/images/Paota/TArrow/TArrow-s.png");
}
public void draw() {
img_rotate = ImageUtil.rotateImage(imgs[3], degree);
img_rotate_2 = ImageUtil.rotateImage(imgs[2], degree);
img_rotate_3 = ImageUtil.rotateImage(imgs[1], degree);
Pen.drawImage(imgs[0], x, y, null);
//Pen.drawImage(imgs[1], x, y, null);Pen.drawImage(imgs[0], x, y, null);
switch (state) {
case 0:
Pen.drawImage(img_rotate, x, y-3, null);
break;
case 1:
Pen.drawImage(img_rotate_2, x, y-3, null);
break;
case 2:
Pen.drawImage(img_rotate_3, x, y-5, null);
break;
default:
break;
}
//Pen.drawImage(img_rotate, x, y - 5, null);
// if(degree<360)degree+=1;
// else degree=0;
}
public void Attack() {// 攻击方法
if (state1 == true) {// 判断状态是否为空闲状态,是则攻击
for (int i = 0; i < Factory.monsters.size(); i++) {
if (Factory.monsters.get(i) == null)
return;// 判断monster是有没有怪物
if (Factory.monsters.get(i).hp <= 0)
return;// 判断monster是否是活的
m = Factory.monsters.get(i);
// 判断自己的攻击范围
move(m);// 调用自己的转动方法
// 如果在则攻击
if (ticker.tickOver()) {
// System.out.println(22222);
if(Math.abs(this.y - m.y) < 200 && Math.abs(this.x - m.x) < 200) {
Attacks T = new TArrowAttack(x + 5, y + 5, degree);
Factory.T_A.add(T);
T.Attack(m);// 子弹攻击
ticker.reset();
state1 = false;
}
}
}
}
if (state1 == false) {
if (ticker.tickOver()) {
if(Math.abs(this.y - m.y) < 200 && Math.abs(this.x - m.x) < 200) {
Attacks T = new TArrowAttack(x + 5, y + 5, degree);
Factory.T_A.add(T);
T.Attack(m);// 子弹攻击
ticker.reset();
}
}
if (m.hp <= 0) {
state1 = true;
}
}
}
public void attack_obstacle(int x, int y) {
if (state1 == true) {// 判断状态是否为空闲状态,是则攻击
for (int i = 0; i < Factory.obstacle.size(); i++) {
if (Factory.obstacle.get(i) == null)
return;// 判断obstacle
if (Factory.obstacle.get(i).hp <= 0)
return;
o = Factory.obstacle.get(i);
// 判断自己的攻击范围
move_obstacles(o);// 调用自己的转动方法
// 如果在则攻击
if (ticker.tickOver()) {
// System.out.println(22222);
if (Math.abs(this.y - y) < 200 && Math.abs(this.x - x) < 200) {
Attacks T = new TArrowAttack(x + 5, y + 5, degree);
Factory.T_A.add(T);
// T_a=T;
T.Attack_obstacle(x,y);// 子弹攻击
ticker.reset();
state1 = false;
}
}
}
}
if (state1 == false) {
if (ticker.tickOver()) {
if (Math.abs(this.y - y) < 200 && Math.abs(this.x - x) < 200) {
Attacks T = new TArrowAttack(x + 5, y + 5, degree);
Factory.T_A.add(T);
T.Attack_obstacle(x,y);// 子弹攻击
ticker.reset();
}
}
if (m.hp <= 0) {
state1 = true;
}
}
}
public void move(Monster enemy) {// 自己的转动方法
if (Math.abs(this.y - enemy.y) < 200 && Math.abs(this.x - enemy.x) < 200) {
// isRotate=true;
// double a=(double)(enemy.y-this.y)/(double)(enemy.x-this.x);
// double d=Math.atan(a);
// degree=(int)(d*180/Math.PI)+90;
if (this.x > enemy.x) {
double a = (double) (enemy.y - this.y) / (double) (enemy.x - this.x);
double d = Math.atan(a);
degree = (int) (d * 180 / Math.PI) - 90;
}
if (this.x < enemy.x) {
double a = (double) (enemy.y - this.y) / (double) (enemy.x - this.x);
double d = Math.atan(a);
degree = (int) (d * 180 / Math.PI) + 90;
}
}
}
@Override
public void adjustment() {
x+=78/4;
y+=78/4;
}
public void move_obstacles (Obstacles o){
if (Math.abs(this.y - o.y) < 50 && Math.abs(this.x - o.x) < 50) {
// isRotate=true;
// double a=(double)(enemy.y-this.y)/(double)(enemy.x-this.x);
// double d=Math.atan(a);
// degree=(int)(d*180/Math.PI)+90;
if (this.x > o.x) {
double a = (double) (o.y - this.y) / (double) (o.x - this.x);
double d = Math.atan(a);
degree = (int) (d * 180 / Math.PI) - 90;
}
if (this.x < o.x) {
double a = (double) (o.y - this.y) / (double) (o.x - this.x);
double d = Math.atan(a);
degree = (int) (d * 180 / Math.PI) + 90;
}
}
}
}
项目描述
1:本项目只针对于学习 提升对java语言基础知识的认识
项目下载地址
https://download.csdn.net/download/qq_41193701/11190924