⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mappy.java

📁 一个JAVA的地图编辑器,适合快速开发移动终端游戏的好工具.
💻 JAVA
📖 第 1 页 / 共 5 页
字号:
//
//						______________________________
//						  --------------------------
//							* Mappy Java Version *
//						  __________________________
//						------------------------------
//
//							   (c) Slimer 2001
//

import java.awt.image.MemoryImageSource;
import java.awt.Rectangle;
import java.awt.Component;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Color;
import java.awt.Shape;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.IOException;
import java.io.File;

// These are required for the Log class.
import java.io.StringWriter;
import java.io.PrintWriter;
import java.util.Date;
import java.text.DateFormat;

//------------------------------------------------------------------------------
/**
 * Mappy Playback Library for Java Release 6<br>
 * <br>
 * Based on MappyJV Release1 14/07/99 (C)1999 <a href="mailto:rburrows@bigfoot.com">Robin
 * Burrows</a>. <br>
 * <br>
 * This class allows the playback of <a href="http://www.tilemap.co.uk">
 * Mappy</a> <code>.FMP</code> files. Current limitations are:
 * <ul>
 * 		<li>Pillars are not supported.
 * 		<li>Animation Blocks are not fully supported.
 * </ul>
 * After constructing a Mappy class, you must load a Map into it before it can
 * be used. If any of your image blocks are transparent then be sure to set the
 * transparent colour key via <code>setTransparentColour()</code> before you
 * call a <code>loadMap()</code> method. It is also important that you set
 * the screen area that the Map is to be drawn into (via <code>setScreenDimensions()
 * </code>) before any drawing functions are called.<br>
 * <br>
 * As a Map can have up to 8 layers, the Mappy class introduces the concept of
 * a current layer. This current layer is used implicity (i.e. without you
 * specifing)in most of the map operations (e.g. <code>drawForeground()</code>),
 * therefore you must set the current Map layer before calling any Map layer
 * methods. <br>
 * <br>
 * Despite the source for the Mappy Playback being quite large I have kept it
 * in a single source (<code>.java</code>) file to ease portability. For the
 * same reason, <code>Mappy</code> has been moved out of it's default package
 * of <code>com.alienfactory.gaming</code>.  Future releases may well begin to
 * spread accross several classes (over 2000 lines, I mean, come on!). <br>
 * <br>
 * See the readme.txt file for more info<br><br>
 * @version	1.23 (6 December 2002)
 * @author  <a href="mailto:slimer@alienfactory.co.uk">Slimer</a> of <a href="http://www.alienfactory.co.uk">Alien Factory</a>.
 * @see		#setTransparentColour(int)
 * @see		#loadMap(File, Component)
 * @see		#setScreenDimensions(Rectangle)
 * @see		Block
 **/
//------------------------------------------------------------------------------

public class Mappy {

	private static  Log         	log 						= new Log();
	private static	boolean			m_blnLogEnabled				= true;

	private static final int		MIN_NO_OF_LAYERS 			= 0;
	private static final int		MAX_NO_OF_LAYERS 			= 7;

	private 		int 			m_intMapWidth, m_intMapHeight;
	private			int				m_intBlockWidth, m_intBlockHeight;
	private 		int 			m_intBlockByteSize;
	private 		int 			m_intNoOfBlocks;
	private 		int 			m_intNoOfImages;
	private 		int 			m_intColourDepth;			// the no. of bits that represent a colour
	private			String			m_strMapDescription 		= "";		// this is whatever's found in the ATHR chunk

// FMP1.0 data:
	private			int				m_intMapType;				// type of map (always 0 for FMP0.5)
	private			int				m_intBlockGapX;				// gap between block starts horizontally
	private			int				m_intBlockGapY;				// gap between block starts vertically
	private			int				m_intBlockStaggerX;			// offset for odd rows horizontally
	private			int				m_intBlockStaggerY;			// offset for odd rows vertically
	private			int				m_intClickMask;				// index of image to detect solid areas
// end FMP1.0 data

	private 		byte 			m_bytColourMap[];			// Colour map 0xRRGGBB
	private 		Block			m_clsMapBlockStrPt[];		// Block structure object array
	private 		AnimStructure 	m_clsMapAniStrPt[];			// Anim structure object array

	private 		int 			m_intTransparentColour;		// Transparency: Index for 8bit, 0xRRGGBB for others
	private			Image			m_imgOpaqueBlocks[];		// The Images for opaque blocks
	private			Image			m_imgTransparentBlocks[];	// The Images for transparent blocks

	private 		short 			m_shtTheMap[][][];			// The Entire Map Matrix!

	private			boolean			m_blnMapLoaded;				// indicates wether or not a map has been loaded
	private			int				m_intScreenWidth			= 640;
	private			int				m_intScreenHeight			= 480;
	private			int				m_intScreenOffsetX			= 0;
	private			int				m_intScreenOffsetY			= 0;
	private			int				m_intX[], m_intY[];
	private			int				m_intMaxLayerNo				= 0;

	private			int				m_intCurrentMapLayer		= 0;



//______________________________________________________________________________
//------------------------------------------------------------------------------
// Constructors
//______________________________________________________________________________
//------------------------------------------------------------------------------

	/**
	 * Constructs a new Mappy Playback Library. <br>
	 **/
	public Mappy() {
		m_intX = new int[MAX_NO_OF_LAYERS + 1];
		m_intY = new int[MAX_NO_OF_LAYERS + 1];
		m_intTransparentColour 	= 0;
		m_blnMapLoaded			= false;
	}



//______________________________________________________________________________
//------------------------------------------------------------------------------
// Private Methods : General
//______________________________________________________________________________
//------------------------------------------------------------------------------

	/**
	 * Reads 4 bytes from the InputStream and converts them into a String. <br>
	 **/
	private String readID(InputStream stream) throws IOException {
		byte 	bytID[];
		String	strID;

		// default return value
		strID = "";

		// read the ID into a byte array
		bytID = new byte[4];
		readStream(stream, bytID, 0, 4);

		// convert byte array into a String
		strID = new String(bytID);

		// return ID
		return strID;
	}



	/**
	 * Reads 4 bytes from the InputStream and converts them into an int. <br>
	 **/
	private int readChunkLength(InputStream stream) throws IOException {
		int		intIndex;
		byte 	bytLength[];
		int		intChunkLength;

		// default return value
		intChunkLength = 0;

		// read the chunk length
		bytLength = new byte[4];
		readStream(stream, bytLength, 0, 4);

		// convert to int
		intChunkLength = convertToInt(bytLength, 0, 4);

		// return ID
		return intChunkLength;
	}



	/**
	 * Converts "intSize" bytes from the given array (at position "intOffset")
	 * into an int. <br>
	 **/
	private int convertToInt(byte bytArray[], int intOffset, int intSize) {
		int intIndex;
		int intValue;

		// default return value
		intValue = 0;

		// loop for all the required bytes
		for (intIndex = 0; intIndex < intSize; intIndex++) {

			// add the next few bits to the number
			intValue += ((int) bytArray[intOffset + intIndex]) & 0xFF;

			// if we're going around again, shift the value up
			if (intIndex < (intSize - 1)) {
				intValue <<= 8;
			}
		}

		// return int value
		return intValue;
	}



	/**
	 * Updated for MappyJV R5 by RB
	 * Hopefully this will be faster, I have left the old code there commented out<br><br>
	 * R6: reads more than 1 byte at a time<br><br>
	 *
	 * This method is to replace the standard InputStream.read(byte[], int, int).
	 * Reason being, in Java1.1.x, it friggin don't work! Believe me, I've spent
	 * hours on it! You keep getting misc and spurlious data creeping in - VERY
	 * annoying, I can tell you! <br>
	 * <br>
	 * Yet another reason to jump to Java1.4! Yeah... <br>
	 **/
	private void readStream(InputStream stream, byte bytArray[], int intOffset, int intSize) throws IOException {

		int intIndex = 0;
		while  (intIndex < intSize) {
			intIndex += stream.read(bytArray, intIndex+intOffset, intSize-intIndex);
		}

/*
		byte bytTemp[]	= new byte[1];
		int	 intIndex;

		for (intIndex = 0; intIndex < intSize; intIndex++) {
			stream.read(bytTemp, 0, 1);
			bytArray[intOffset++] = bytTemp[0];
		}
*/
	}



//______________________________________________________________________________
//------------------------------------------------------------------------------
// Private Methods : Chunk Reading
//______________________________________________________________________________
//------------------------------------------------------------------------------

	/**
	 * Loads the ATHR chunk from the InputStream. <br>
	 * <br>
	 * ATHR: Up to 4 ASCII strings of author information. <br>
	 **/
	private void loadATHR(InputStream stream, int intChunkLength) throws IOException {
		byte 		bytATHR[];
		String		strDesc[];
		int			intStrStart, intStrEnd;
		int			intStrIndex;
		String		strFullDesc = "";

		log.info("Found Chunk - ATHR, reading...");

		bytATHR = new byte[intChunkLength];
		readStream(stream, bytATHR, 0, bytATHR.length);

		strDesc = new String[4];
		intStrStart = intStrEnd = 0;
		for (intStrIndex = 0; intStrIndex < strDesc.length; intStrIndex++) {
			// find the end of the line
			while (bytATHR[intStrEnd] != 0) intStrEnd++;

			// convert the byte array to a string
			strDesc[intStrIndex] = new String(bytATHR, intStrStart, intStrEnd - intStrStart);

			// concat all into the one string
			strFullDesc += strDesc[intStrIndex];
			if ((intStrIndex < (strDesc.length-1)) && (!strDesc[intStrIndex].equals(""))) {
				strFullDesc += "\n";
			}

			// start again
			intStrEnd++;
			intStrStart = intStrEnd;
		}

		log.info("  Author : " + strDesc[0]);
		log.info("  Desc   : " + strDesc[1]);
		log.info("         : " + strDesc[2]);
		log.info("         : " + strDesc[3]);

		// save for future use
		m_strMapDescription = strFullDesc;
	}



	/**
	 * Loads the MPHD chunk from the InputStream. <br>
	 * <br>
	 * MPHD: Map header, see struct in mappy.c <br>
	 **/
	private boolean loadMPHD(InputStream stream, int intChunkLength) throws IOException {
		byte 		bytMPHD[];
		boolean		blnLSB;
		byte		bytTemp;
		int			intIndex;

		log.info("Found Chunk - MPHD, reading...");

		log.info("  loading map header.");

		// default LSB
		blnLSB = false;

		bytMPHD = new byte[intChunkLength];
		readStream(stream, bytMPHD, 0, bytMPHD.length);

		if (bytMPHD[0] > 1) {
			log.error("Map is not supported (version higher than 1.0)");
		}
		if (bytMPHD[2] == 1) {
			blnLSB = true;

			// looks like we're swapping around the lsb and msb
			for (intIndex = 4; intIndex < bytMPHD.length; intIndex += 2) {
				if (intIndex < 24 || intIndex >= 28) {
					bytTemp 			  = bytMPHD[intIndex];
					bytMPHD[intIndex] = bytMPHD[intIndex + 1];
					bytMPHD[intIndex + 1] = bytTemp;
				}
			}
		}

		m_intMapType = bytMPHD[3];
		if (m_intMapType > 3) {
			log.error("Map is not supported (unknown type)");
		}

		// load Map Header
		m_intMapWidth 			= (((int) bytMPHD[ 4])&0xFF)<<8 | ((int) bytMPHD[ 5])&0xFF;
		m_intMapHeight 			= (((int) bytMPHD[ 6])&0xFF)<<8 | ((int) bytMPHD[ 7])&0xFF;
		m_intBlockWidth 		= (((int) bytMPHD[12])&0xFF)<<8 | ((int) bytMPHD[13])&0xFF;
		m_intBlockHeight		= (((int) bytMPHD[14])&0xFF)<<8 | ((int) bytMPHD[15])&0xFF;
		m_intColourDepth 		= (((int) bytMPHD[16])&0xFF)<<8 | ((int) bytMPHD[17])&0xFF;
		m_intBlockByteSize		= (((int) bytMPHD[18])&0xFF)<<8 | ((int) bytMPHD[19])&0xFF;
		m_intNoOfBlocks 		= (((int) bytMPHD[20])&0xFF)<<8 | ((int) bytMPHD[21])&0xFF;
		m_intNoOfImages 		= (((int) bytMPHD[22])&0xFF)<<8 | ((int) bytMPHD[23])&0xFF;

		if (bytMPHD.length > 24) {
			if (m_intColourDepth == 8) m_intTransparentColour = ((int) bytMPHD[24])&0xFF;
			else m_intTransparentColour = (((int) bytMPHD[25])&0xFF)<<16 | (((int) bytMPHD[26])&0xFF)<<8 | ((int) bytMPHD[27])&0xFF;
		}

		if (bytMPHD.length > 28) {
			m_intBlockGapX      = (((int) bytMPHD[28])&0xFF)<<8 | ((int) bytMPHD[29])&0xFF;
			m_intBlockGapY      = (((int) bytMPHD[30])&0xFF)<<8 | ((int) bytMPHD[31])&0xFF;
			m_intBlockStaggerX  = (((int) bytMPHD[32])&0xFF)<<8 | ((int) bytMPHD[33])&0xFF;
			m_intBlockStaggerY  = (((int) bytMPHD[34])&0xFF)<<8 | ((int) bytMPHD[35])&0xFF;
		} else {
			m_intBlockGapX      = m_intBlockWidth;
			m_intBlockGapY      = m_intBlockHeight;
			m_intBlockStaggerX  = 0;
			m_intBlockStaggerY  = 0;
		}

		if (bytMPHD.length > 36) {
			m_intClickMask 		= (((int) bytMPHD[36])&0xFF)<<8 | ((int) bytMPHD[37])&0xFF;
		} else {
			m_intClickMask 		= 0;
		}
				
		log.info("  FMP version   : " + Integer.toString((int) bytMPHD[0]) + "." + Integer.toString((int) bytMPHD[1]));
		log.info("  MapWidth      : " + Integer.toString(m_intMapWidth));
		log.info("  MapHeight     : " + Integer.toString(m_intMapHeight));
		log.info("  BlockWidth    : " + Integer.toString(m_intBlockWidth));
		log.info("  BlockHeight   : " + Integer.toString(m_intBlockHeight));
		log.info("  ColourDepth   : " + Integer.toString(m_intColourDepth));
		log.info("  BlockByteSize : " + Integer.toString(m_intBlockByteSize));
		log.info("  NoOfBlocks    : " + Integer.toString(m_intNoOfBlocks));
		log.info("  NoOfImages    : " + Integer.toString(m_intNoOfImages));

		// return LSB
		return blnLSB;
	}



	/**
	 * Loads the CMAP chunk from the InputStream. <br>
	 * <br>
	 * CMAP: Colour palette for 8bit maps, for however many colours are needed. <br>
	 **/
	private void loadCMAP(InputStream stream, int intChunkLength) throws IOException {

		log.info("Found Chunk - CMAP, reading...");

		// read in the colour map
		log.info("  loading " + Integer.toString(intChunkLength / 3) + " entries.");
		m_bytColourMap = new byte[intChunkLength];
		readStream(stream, m_bytColourMap, 0, m_bytColourMap.length);
	}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -