一、游戏基本功能

1、能够向左向右行走(键盘监听)

2、能够跳跃

3、能够发射×××

4、能够检测和障碍物之间的碰撞

5、背景图片的移动

二、游戏运行界面

三、游戏大致实现思路:

1.窗体

2.自己角色的添加

3.背景图片的添加

4.背景图片的移动

5.人物的移动和跳跃

6.砖头、水管等等障碍物的添加

7.任务和障碍物的碰撞

难点分析:

1.人物的多键控制

1)给人物设定方向boolean变量:向左、向右、向上、向下

2)通过键盘监听来修改方向的变量值

按下某个键的时候,我们把相应方向改为true,释放的时候改false

2.地图配置

自定义文件读取方式实现:文件流的使用和字符串String类的方法调用

3.碰撞检测

封装一个Rectangle类的对象

4.×××添加

1)先定义一个容器,这个用于封装所有的×××对象

2)按下某个键的时候,创建一个×××对象(以角色的坐标为基准初始化)

3)把×××对象添加到容器当中

4)在paint方法中,遍历容器,取出×××对象并进行绘制

5)检测×××如果超出了窗体边界,则需要把当前×××从容器当中移除掉

四、程序源代码:

代码结构图:分了三个包、敌人类包、游戏界面类包、游戏地图配置包

com.huaxin.mario包:

package com.huaxin.mario;

import java.awt.Color;

import java.awt.Graphics;

import java.awt.image.BufferedImage;

import java.util.ArrayList;

import javax.swing.ImageIcon;

import javax.swing.JFrame;

import com.huaxin.enery.Enery;

import com.huaxin.enery.Pipe;

import Util.Map;

public class GameFrame extends JFrame{

public Mario mario;

public Enery pipe,cion,brick;

//背景图片

public BackgroundImage bg ;

//容器装敌人

public ArrayList<Enery> eneryList = new ArrayList<Enery>();

//×××容器

public ArrayList<Boom> boomList = new ArrayList<Boom>();

//×××的速度

public int bspeed=0;

//画地图,制定规则,是1画砖头,是2画金币,是3画水管

public int [][] map =null;

//构造函数里面初始化背景图片和马里奥对象

public GameFrame() throws Exception {

mario = new Mario(this);

mario.start();

Map mp= new Map();

bg = new BackgroundImage();

//窗体重绘线程

new Thread(){

public void run(){

while(true){

//重绘窗体

repaint();

//检查×××是否出界

checkBoom();

try {

Thread.sleep(10);

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}

}.start();

map=mp.readMap();

//读取地图,并配置地图

for (int i = 0; i < map.length; i++) {

for (int j = 0; j < map[0].length; j++) {

//读取到的是1,画砖头

if(map[i][j]==1){

brick = new Pipe(j*30,i*30,30,30,new ImageIcon("image/brick.png").getImage());

eneryList.add(brick);

}

//读到2画金币

if(map[i][j]==2){

cion = new Pipe(j*30,i*30,30,30,new ImageIcon("image/coin_brick.png").getImage());

eneryList.add(cion);

}

//读到3画水管

if(map[i][j]==3){

pipe = new Pipe(j*30,i*30,60,120,new ImageIcon("image/pipe.png").getImage());

eneryList.add(pipe);

}

}

}

//设置背景音乐

com.huaxin.music.Util.startMusic("music/bg1.wav");

}

public void initFrame(){

//设置窗体相关属性

this.setSize(800,450);

this.setTitle("山寨版超级玛丽");

this.setResizable(false);

this.setLocationRelativeTo(null);

this.setDefaultCloseOperation(3);

this.setVisible(true);

//该窗体添加键盘监听

KeyListener kl = new KeyListener(this);

this.addKeyListener(kl);

}

public void paint(Graphics g) {

//利用双缓冲画背景图片和马里奥

BufferedImage bi =(BufferedImage)this.createImage(this.getSize().width,this.getSize().height);

Graphics big =bi.getGraphics();

big.drawImage(bg.img, bg.x, bg.y, null);

for (int i = 0; i <eneryList.size(); i++) {

Enery e =eneryList.get(i);

big.drawImage(e.img, e.x, e.y, e.width, e.height,null);

}

//画×××

for (int i = 0; i < boomList.size(); i++) {

Boom b =boomList.get(i);

Color c =big.getColor();

big.setColor(Color.red);

big.fillOval(b.x+=b.speed, b.y, b.width, b.width);

big.setColor(c);

}

//画人物

big.drawImage(mario.img, mario.x, mario.y, mario.width, mario.height,null);

g.drawImage(bi,0,0,null);

}

//检查×××是否出界,出界则从容器中移除,不移除的话,内存会泄漏

public void checkBoom(){

for (int i = 0; i < boomList.size(); i++) {

Boom b = boomList.get(i);

if(b.x<0 || b.x>800){

boomList.remove(i);

}

}

}

}

package com.huaxin.mario;

import java.awt.Image;

import java.awt.Rectangle;

import javax.swing.ImageIcon;

import com.huaxin.enery.Enery;

//自己的角色类

public class Mario extends Thread{

public GameFrame gf;

public boolean jumpFlag=true;

//马里奥的坐标

public int x=0,y=358;

//马里奥的速度

public int xspeed=5,yspeed=1;

//马里奥的宽高

public int width=30,height=32;

//马里奥的图片

public Image img = new ImageIcon("image/mari1.png").getImage();

public boolean left=false,right=false,down=false,up=false;

public String Dir_Up="Up",Dir_Left="Left",Dir_Right="Right",Dir_Down="Down";

public Mario (GameFrame gf) {

this.gf=gf;

this.Gravity();

}

public void run(){

while(true){

//向左走

if(left){

//碰撞到了

if(hit(Dir_Left)){

this.xspeed=0;

}

if(this.x>=0){

this.x-=this.xspeed;

this.img=new ImageIcon("image/mari_left.gif").getImage();

}

this.xspeed=5;

}

//向右走

if(right){

if(hit(Dir_Right)){

this.xspeed=0;

}

//任人物向右移动

if(this.x<400){

this.x+=this.xspeed;

this.img=new ImageIcon("image/mari_right.gif").getImage();

}

if(this.x>=400){

//背景向左移动

gf.bg.x-=this.xspeed;

//障碍物项左移动

for (int i = 0; i <gf.eneryList.size(); i++) {

Enery enery = gf.eneryList.get(i);

enery.x-=this.xspeed;

}

this.img=new ImageIcon("image/mari_right.gif").getImage();

}

this.xspeed=5;

}

//向上跳

if(up){

if(jumpFlag && !isGravity){

jumpFlag=false;

new Thread(){

public void run(){

jump();

jumpFlag=true;

}

}.start();

}

}

try {

this.sleep(20);

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}

//向上跳的函数

public void jump(){

int jumpHeigh=0;

for (int i = 0; i < 150; i++) {

gf.mario.y-=this.yspeed;

jumpHeigh++;

if(hit(Dir_Up)){

break;

}

try {

Thread.sleep(5);

} catch (InterruptedException e) {

e.printStackTrace();

}

}

for (int i = 0; i <jumpHeigh; i++) {

gf.mario.y+=this.yspeed;

if(hit(Dir_Down)){

this.yspeed=0;

}

try {

Thread.sleep(5);

} catch (InterruptedException e) {

e.printStackTrace();

}

}

this.yspeed=1;//还原速度

}

//检测碰撞

public boolean hit(String dir){

Rectangle myrect = new Rectangle(this.x,this.y,this.width,this.height);

Rectangle rect =null;

for (int i = 0; i < gf.eneryList.size(); i++) {

Enery enery = gf.eneryList.get(i);

if(dir.equals("Left")){

rect = new Rectangle(enery.x+2,enery.y,enery.width,enery.height);

}

else if(dir.equals("Right")){

rect = new Rectangle(enery.x-2,enery.y,enery.width,enery.height);

}

else if(dir.equals("Up")){

rect = new Rectangle(enery.x,enery.y+1,enery.width,enery.height);

}else if(dir.equals("Down")){

rect = new Rectangle(enery.x,enery.y-2,enery.width,enery.height);

}

//碰撞检测

if(myrect.intersects(rect)){

return true;

}

}

return false;

}

//检查是否贴地

public boolean isGravity=false;

public void Gravity(){

new Thread(){

public void run(){

while(true){

try {

sleep(10);

} catch (InterruptedException e) {

e.printStackTrace();

}

if(!jumpFlag){

}

while(true){

if(!jumpFlag){

break;

}

if(hit(Dir_Down)){

break;

}

if(y>=358){

isGravity=false;

}

else{

isGravity=true;

y+=yspeed;

}

try {

sleep(10);

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}

}

}.start();

}

}

package com.huaxin.mario;

import java.awt.event.KeyAdapter;

import java.awt.event.KeyEvent;

import javax.swing.ImageIcon;

//键盘按下监听类

public class KeyListener extends KeyAdapter{

public GameFrame gf;

public boolean jumpFlag=true;

public KeyListener(GameFrame gf) {

this.gf=gf;

}

//键盘监听

public void keyPressed(KeyEvent e) {

int code = e.getKeyCode();

switch(code){

//向右走

case 39:

gf.mario.right=true;

break;

//向左走

case 37:

gf.mario.left=true;

break;

case 66:

addBoom();

break;

//向上跳

case 74:

gf.mario.up=true;

break;

}

}

//添加×××

public void addBoom() {

Boom b = new Boom(gf.mario.x,gf.mario.y+5,10);

if(gf.mario.left) b.speed=-2;

if(gf.mario.right) b.speed=2;

gf.boomList.add(b);

}

//键盘释放监听

public void keyReleased(KeyEvent e) {

int code=e.getKeyCode();

if(code==39){

gf.mario.right=false;

gf.mario.img=new ImageIcon("image/mari1.png").getImage();

}

if(code==37){

gf.mario.left=false;

gf.mario.img=new ImageIcon("image/mari_left1.png").getImage();

}

if(code==74){

gf.mario.up=false;

}

}

}

package com.huaxin.mario;

import java.awt.Image;

import javax.swing.ImageIcon;

public class BackgroundImage {

public int x=0,y=0;

public int ox=0,oy=0;

public Image img=new ImageIcon("image/startBack.jpg").getImage();

}

package com.huaxin.mario;

//×××类

public class Boom {

//×××的坐标,大小,速度

int x,y;

int width;

int speed=1;

public Boom(int x, int y, int width) {

super();

this.x = x;

this.y = y;

this.width = width;

}

}

主函数类,作为整个程序的入口

package com.huaxin.mario;

public class Test {

//主函数,程序入口

public static void main(String[] args) throws Exception {

GameFrame gf = new GameFrame();

gf.initFrame();

}

}

com.huaxin.enery包:

package com.huaxin.enery;

import java.awt.Image;

//障碍物的抽象父类

public abstract class Enery {

public int x,y;

public int width,height;

public Image img;

public Enery(int x, int y, int width, int height,Image img) {

this.x = x;

this.y = y;

this.width = width;

this.height = height;

this.img=img;

}

}

package com.huaxin.enery;

import java.awt.Image;

//金币类

public class Coin extends Enery{

public Coin(int x, int y, int width, int height, Image img) {

super(x, y, width, height, img);

}

}

package com.huaxin.enery;

import java.awt.Image;

//砖头类

public class Brick extends Enery {

public Brick(int x, int y, int width, int height, Image img) {

super(x, y, width, height, img);

}

}

package com.huaxin.enery;

import java.awt.Image;

//水管类

public class Pipe extends Enery {

public Pipe(int x, int y, int width, int height, Image img) {

super(x, y, width, height, img);

}

}

com.huaxin.util包:

package Util;

import java.io.BufferedReader;

import java.io.FileInputStream;

import java.io.FileNotFoundException;

import java.io.InputStreamReader;

import java.util.ArrayList;

//地图配置类

public class Map {

//数据容器

public ArrayList<String> list = new ArrayList<String>();

public int [][] map=null;

public int[][] readMap() throws Exception {

// 构造文件输入流

FileInputStream fis = new FileInputStream("map.txt");

InputStreamReader isr = new InputStreamReader(fis);

BufferedReader br = new BufferedReader(isr);

//直接读取一行数据

String value =br.readLine();

while(value!=null){

//将读取到的一行数据加入到容器中

list.add(value);

value =br.readLine();

}

br.close();

//得到多少行多少列

int row=list.size();

int cloum=0;

for (int i = 0; i < 1; i++) {

String str=list.get(i);

String [] values=str.split(",");

cloum=values.length;

}

map = new int [row][cloum];

//将读到的字符创转换成整数,并赋值给二位数组map

for (int i = 0; i < list.size(); i++) {

String str=list.get(i);

String [] values=str.split(",");

for (int j = 0; j < values.length; j++) {

map[i][j]=Integer.parseInt(values[j]);

}

}

return map;

}

}

五、项目总结:

这个小项目看起来挺简单的,其实里面也有很多功能需要仔细去思考的,以前觉得游戏人物在窗体走的时候,觉得一直是人在走,其实,人物走到中间或者走到某一位置的时候,人物已经是在原地踏步了,取而代之的是背后那张长度很长的背景的图片在移动,任务的左右移动相对而言比较简答实现,跳跃功能就不是那么简单了,需要永达线程,跟后面障碍物碰撞检测又有关系,当没有碰到的时候,人物要往下掉,一不注意就会出现各种bug,比如,可以一直跳,在跳的同时还能再跳,还有就是下降可能不会落地面的同一高度,可能会高于地面的高度,可能会低于地面的高度;障碍物的添加,我们是通过配置地图的方式,配置地图有时通过读入文件的操作,大致的原理是将后面的那张的背景图片划分成很多的小格子,将这些小格子用代码转换为二位数组,二维数组可以存入不同数字,代表不同的障碍物,通过操作文件就可以轻易配置地图;首先通过文件输入流将文件数据读入,将字符转换为数字,并存储在二维数组中,后面,通过遍历二维数组的不同位置的值,在相应的格子填充相应的障碍物;地图就这样配置好了;

觉得配地图很炫酷,因为以前有位学长在演示的时候,觉得好难,现在自己掌握了觉得也不是很难了,当然了,这里离不开老师的指导;碰撞检测类似之前小球的碰撞检测,这里主要需要处理碰撞之后的一些逻辑,如何避免一直碰撞(人物贴着障碍物不能动)等;发射×××的话,也比较简单了,利用容器装×××,不过需要注意的是要及时将容器中×××移除,不然内存会很快被吃完的;

写程序,一定要按照思路一步一步来,一点一点来实现!不要太过急于求成!

品略图书馆 http://www.pinlue.com/

转载于:https://blog.51cto.com/14325182/2407278

Java不能做游戏?快来看看这个Java版超级玛丽吧。相关推荐

  1. Java窗体小游戏开发飞机大作战Java小游戏开发源码

    Java窗体小游戏开发飞机大作战Java小游戏开发源码

  2. Java好学吗?Java能做什么?如何快速入门Java?

    Java是一门面向对象编程语言,不仅吸收了C++语言的各种优点,还摒弃了C++里难以理解的多继承.指针等概念,Java具有简单性.面向对象.分布式.健壮性.安全性.平台独立与可移植性.多线程.动态性等 ...

  3. java植物大战僵尸游戏下载安装_用 Java 写一个植物大战僵尸简易版

    植物父类.子弹父类就同理可得了. 上面说到子类共有的方法需要抽到父类中,那么部分子类共有的方法该如何处理呢?比如,豌豆射手.寒冰射手可以发射子弹,坚果墙就没有射击的这个行为.所以这里就需要用到接口(I ...

  4. java多线程做一件事_关于Java的十件事

    java多线程做一件事 那么,您从一开始就一直在使用Java? 还记得那些被称为" Oak"的日子,OO仍然是热门话题,C ++人士认为Java没有机会,Applet还是一件事吗? ...

  5. java 快速io_java 最快的input (ACM) Java高效IO

    java 最快的input 问题: Scanner 非常非常非常慢 使用Scanner来输入非常方便,但很慢. 使用 BufferedReader 和 StringTokenizer 会更快, 但是在 ...

  6. 基于Java的Minecraft游戏后端自定义插件 的Java实践项目整理

    Minecraft_Plugin 1.项目概述 2.系统设计 3.功能模块成果展示 4.个人总结 1.项目概述 1.1 项目简介 小组准备编写一个具有武器战斗,道具收集.互动社交和任务悬赏四大系统的聚 ...

  7. 基于java的五子棋游戏的设计_基于Java的五子棋游戏的设计

    摘  要 五子棋作为一个棋类竞技运动,在民间十分流行,为了熟悉五子棋规则及技巧,以及研究简单的人工智能,决定用JAVA开发五子棋游戏.主要完成了人机对战和玩家之间联网对战2个功能.网络连接部分为Soc ...

  8. 用java编写战舰 游戏吗_如何在Java中正确建模战舰游戏

    我正在尝试为我的小组在大学里做的"游戏"项目创建战舰游戏.我之前从未真正使用过GUI,几乎所有输出都在Eclipse控制台中. 首先,我创建了一个GUI类,它实际上是我的" ...

  9. java程序设计雷电游戏设计步骤_基于Java的飞机雷电射击游戏的设计任务书

    主要参考文献(资料): [1] Java 2游戏编程[M]. 清华大学出版社 , (美)ThomasPetchel著, 2005 [2] Java游戏引擎的开发与实现[J]. 何依林. 无线互联科技. ...

  10. java猜字母游戏_JAVA编程题-用java编写猜字母游戏

    原标题:JAVA编程题-用java编写猜字母游戏 问题: 猜字母游戏,其游戏规则为: 程序随机产生5个按照一定顺序排列的字符作为猜测的结果,由玩家来猜测此字符串.玩家可以猜测多次,每猜测一次,则由系统 ...

最新文章

  1. androidstudio 日历视图怎么显示农历_记事日历-记事与时间管理工具
  2. 用python将xml文件转换为txt文件_python代码xml转txt实例
  3. spring Boot打可执行的jar包
  4. JVM运行时数据区和各个区域的作用
  5. python图片显示英文字符_python如何解析字符串中出现的英文人名?
  6. 6个最好的 HTML5/CSS3 演示(PPT)框架
  7. 计算机组装内部线的整理,计算机组装与维护笔记整理.doc
  8. c++ 定时器_「正点原子Linux连载」第十九章定时器按键消抖实验
  9. HttpUtil工具类
  10. 论文降重的主要内容有什么?
  11. 公众号排版技巧:如何让你的公众号文章排版变美观?
  12. laravel pdf 加水印
  13. Shadow Defender影子卫士
  14. App 启动时如何知道 CloudKit 的 iCloud 数据同步操作已经结束了?
  15. 如何理解DeepFool算法
  16. FFplay文档解读-47-多媒体过滤器一
  17. 【无标题】sap-ecc6.0 ides 安装过程记录
  18. 格签名相似概念区分: SVP、SIS、LWE的区分
  19. 阿里面试官对面试者的忠告
  20. 谷粒商城项目搭建思路

热门文章

  1. 七个非常好用的黑科技APP,免费/小众/超实用,一次性全给你
  2. ArcMap|地理探测器(geoDetector)前在ArcGIS中的处理
  3. 一款基于易语言的搜题软件
  4. shell教你如何批量解压缩——unzip命令
  5. SQL 正则表达式 匹配方式
  6. 水面船舶雷达监视-信天翁雷达监视系统
  7. HaaS EDU场景式应用学习 - 光照信息屏
  8. Matlab图像显示
  9. 网易云爬虫系列 - 批量下载专辑图片
  10. 专业英语(电子、通信)单词集