用Java写解谜Rpg-4.加载界面,RPG界面与Player

根据我们之前的工作,StartObject已经被成功构建出来,那么,其余的GameObject只要照猫画虎,继承或重写几个方法,其他东西很快就能完成。

 

另外对于Player,我们采用解谜游戏比较经典的画法,让人物处于屏幕中心,让地图在屏幕上滚动,而人物只需要在原地做出走动的动画就好。

 

首先是加载界面LoadingObject


package model.start;

import java.awt.Graphics;
import java.awt.Image;
import java.io.IOException;

import javax.imageio.ImageIO;

import model.GameObject;
import model.over.GameOverObject;
import model.rpg.RpgObject;
import model.rpg.SaveData;
import model.rpg.map.MapObjects.auto.Story2;
/**
 * 缓冲功能,在加载RpgObject类之前使用此类,避免游戏看上去变卡的现象。
 * */
public class LoadingObject extends GameObject {
	private int wait = 0;
	private static Image gameover;
	private SaveData save;

	static {
		try {
			gameover = ImageIO.read(GameOverObject.class.getClassLoader().getResourceAsStream("source/loading.png"));
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * 构造方法。
	 * 当传入null时即认为是新的开始,没有存档
	 * */
	public LoadingObject(SaveData save) {
		this.save = save;
	}

	@Override
	protected void keyResponse() {
	}
	
	/**
	 * 设置int变量,当变量达到条件时,
	 * 说明Load经过了足够时间,
	 * 将new出RpgObject
	 * */
	@Override
	public void draw(Graphics g) {
		wait++;
		if (wait == 20) {
			die();
		}
		g.drawImage(gameover, 0, 0, null);
	}
	
	/**
	 * 判断目前是读档还是新的游戏,然后执行不同操作
	 * */
	@Override
	public void die() {
		if(save == null)
			new RpgObject();
		else
			new RpgObject(save);
	}
}

其中,SaveData是一种存档的方式,读者暂时不用深究。当Loading传入了存档时,游戏即加载存档,开始RPG界面;否则开始新的游戏,从零开始启动RpgObject

 

其次是RPG界面。我们知道,解谜游戏,或者说RPG游戏中很重要的两个部分:地图和人物。对于这两个玩意,我们可以类似GameObject的道理,不替换现有的GameObject,而是在GameObject中画图,即RpgObject的主要职能即执行地图和Playerpaint方法。

 

由于地图是个复杂的东西,我们现在先只尝试构造Player类。

先放上目前的RpgObject,其中含有一个ImageSets类,这个类用于读取所有的图片文件,只需要传入一个数字,就可以根据数字返回一个图片对象。

package model.rpg;

import java.awt.Graphics;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.util.ArrayList;

import model.Game;
import model.GameObject;
import model.start.ItemObject;
import view.Control;
import view.ImageSets;
import view.Lib;
/**
 * 游戏运行时主要重画此类即内部的地图和人物,
 * 这个类中应存在一个saveData类,
 * 里面设置ArrayList Map 、 Item 和currentMap,还应该存在一个ObjectWriter负责生成saveData的文件,即存档,
 * 为此,此类应拥有一个带有saveData形参的构造方法,负责传入LoadObject传入的saveData
 * */
public class RpgObject extends GameObject{
	
	//记录目前状态
	private boolean isRunning = false,isStanding = true;
	protected Direction direction = Direction.R;
	
	public RpgObject(){
		super.musicStart("钟声.wav");
	}
	
	@Override
	protected void keyResponse() {
		//走、跑和静止操作,默认人物为走动
		isStanding = false;
		if(Control.UP){
			direction = Direction.U;
		}
		else if(Control.DOWN){
			direction = Direction.D;
		}
		else if(Control.LEFT){
			direction = Direction.L;
		}
		else if(Control.RIGHT){
			direction = Direction.R;
		}
		else {
			isStanding = true;
		}
		if(Control.Z){
			isRunning = true;
		}
		else{
			isRunning = false;
		}
	}
	
	/**
	 * 重画操作。
	 * 检查各种东西,包括:
	 * 镜子的反光,是否达成条件、调查物品、门的检查、Auto模块的检查。(之后会加上,现在还没有)
	 * */
	public void paint(Graphics g){
		//清屏操作
		g.clearRect(0, 0, Lib.gameWIDTH, Lib.gameHEIGHT);
		//站立不动时调用
		if(isStanding){
			Player.getInstance().draw(g,direction);
			//最后加上阴影
			g.drawImage(ImageSets.getImg(52), 0, 0, null);
		}
		
		//走动时调用
		else{
			Player.getInstance().draw(g,isRunning,direction);
			g.drawImage(ImageSets.getImg(52), 0, 0, null);
		}
	}
	
	@Override
	public void draw(Graphics g) {
		try{
			isStanding = true;
			paint(g);
		}catch(Exception e){
			e.getStackTrace();
		}	
	}
	
	@Override
	public void die() {
		super.musicStop();
	}

}

这样一来,RpgObjectPlayer的调用基本完成,接下来需要构建Player

 

仔细想想,Player也没什么很必要的属性,几个图片,一个物品栏,四个方向,还有走动状态就差不多了。对于方向,我们简单构建一个Direction的枚举。

package model.rpg;
/**
 * 人物以及事件触发的方向
 * */
public enum Direction {
	U,D,L,R
}


然后开始编写Player。对于Player的物品栏目前暂且不提,首先读取Player需要的图片



两张图片,读取后使用BufferedImagesubImage方法可以获得整个图片的一部分,我们把它放进图片数组中。

//图片数组,读入两张图,分成32个小图
	private BufferedImage walk,run;
	private BufferedImage[] walku = new BufferedImage[4];
	private BufferedImage[] walkd = new BufferedImage[4];
	private BufferedImage[] walkl = new BufferedImage[4];
	private BufferedImage[] walkr = new BufferedImage[4];
	private BufferedImage[] runu = new BufferedImage[4];
	private BufferedImage[] rund = new BufferedImage[4];
	private BufferedImage[] runl = new BufferedImage[4];
	private BufferedImage[] runr = new BufferedImage[4];
/**
	 * 构造方法,
	 * 读取图片,同时意味着这个对象不能被存档写入文件。(Image没有序列化,不能跟随写入文件)
	 * */
	public Player(){
		try {
			walk = ImageIO.read(Player.class.getClassLoader().getResourceAsStream("source/rpg/player/walk.png"));
			run = ImageIO.read(Player.class.getClassLoader().getResourceAsStream("source/rpg/player/run.png"));
		} catch (IOException e) {
			e.printStackTrace();
		}
		for(int i = 0;i<walku.length;i++){
			walku[i] = walk.getSubimage(i*(walk.getWidth()/4), 3*(walk.getHeight()/4), walk.getWidth()/4, walk.getHeight()/4);
		}
		for(int i = 0;i<walkd.length;i++){
			walkd[i] = walk.getSubimage(i*(walk.getWidth()/4), 0, walk.getWidth()/4, walk.getHeight()/4);
		}
		for(int i = 0;i<walkl.length;i++){
			walkl[i] = walk.getSubimage(i*(walk.getWidth()/4), walk.getHeight()/4, walk.getWidth()/4, walk.getHeight()/4);
		}
		for(int i = 0;i<walkr.length;i++){
			walkr[i] = walk.getSubimage(i*(walk.getWidth()/4), walk.getHeight()/2, walk.getWidth()/4, walk.getHeight()/4);
		}
		
		for(int i = 0;i<runu.length;i++){
			runu[i] = run.getSubimage(i*(run.getWidth()/4), 3*(run.getHeight()/4), run.getWidth()/4, run.getHeight()/4);
		}
		for(int i = 0;i<rund.length;i++){
			rund[i] = run.getSubimage(i*(run.getWidth()/4), 0, run.getWidth()/4, run.getHeight()/4);
		}
		for(int i = 0;i<runl.length;i++){
			runl[i] = run.getSubimage(i*(run.getWidth()/4), run.getHeight()/4, run.getWidth()/4, run.getHeight()/4);
		}
		for(int i = 0;i<runr.length;i++){
			runr[i] = run.getSubimage(i*(run.getWidth()/4), run.getHeight()/2, run.getWidth()/4, run.getHeight()/4);
		}
		x = Lib.gameWIDTH/2-walk.getWidth()/8;
		y = Lib.gameHEIGHT/2-walk.getHeight()/8;
	}


图片读取完成后,剩下的就是把他们画出来。我们需要几个参数:人物的方向,人物是走动、跑动还是静止。有了这些,我们可以把人物画出来。

/**人物移动时的绘制,包括是不是在奔跑*/
	public void draw(Graphics g,boolean isRun,Direction playerDirection) {
		direction = playerDirection;
		if(!isRun){
			if(direction==Direction.U)
				g.drawImage(walku[imgChange], x, y, null);
			if(direction==Direction.D)
				g.drawImage(walkd[imgChange], x, y, null);
			if(direction==Direction.L)
				g.drawImage(walkl[imgChange], x, y, null);
			if(direction==Direction.R)
				g.drawImage(walkr[imgChange], x, y, null);
			walkWait++;
			if(walkWait==3){
				walkWait = 0;
				imgChange++;
			}
		}
		else{
			if(direction==Direction.U)
				g.drawImage(runu[imgChange], x, y, null);
			if(direction==Direction.D)
				g.drawImage(rund[imgChange], x, y, null);
			if(direction==Direction.L)
				g.drawImage(runl[imgChange], x, y, null);
			if(direction==Direction.R)
				g.drawImage(runr[imgChange], x, y, null);
			runWait++;
			if(runWait==2){
				runWait = 0;
				imgChange++;	
			}
		}
		if(imgChange==4)
			imgChange = 0;
	}
	/**人物静止不动时的绘制*/
	public void draw(Graphics g, Direction direction) {
		if(direction==Direction.U)
			g.drawImage(walku[0], x, y, null);
		if(direction==Direction.D)
			g.drawImage(walkd[0], x, y, null);
		if(direction==Direction.L)
			g.drawImage(walkl[0], x, y, null);
		if(direction==Direction.R)
			g.drawImage(walkr[0], x, y, null);
	}
	
	public Direction getDirection(){
		return direction;
	}
	public void clearDirection(){
		direction = Direction.R;
	}



  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值