This commit is contained in:
Victor 2018-11-15 00:00:30 +02:00
parent d05ddef0cf
commit 57e16a639d
3 changed files with 251 additions and 55 deletions

201
src/Grid.java Normal file
View File

@ -0,0 +1,201 @@
import java.util.Random;
import java.util.Vector;
/**
* This class contains the data necessary to draw the maze.
*
* @author Carol Hamer
*/
public class Grid {
/**
* Random number generator to create a random maze.
*/
private Random myRandom = new Random();
/**
* data for which squares are filled and which are blank.
* 0 = black
* 1 = white
* values higher than 1 are used during the maze creation
* algorithm.
* 2 = the square could possibly be appended to the maze this round.
* 3 = the square's color is not yet decided, and the square is
* not close enough to be appended to the maze this round.
*/
int[][] mySquares;
int width, height;
//--------------------------------------------------------
// maze generation methods
/**
* Create a new maze.
*/
public Grid(int width, int height) {
this.width = width;
this.height = height;
}
public void newMaze() {
mySquares = new int[width][height];
// initialize all of the squares to white except a lattice
// framework of black squares.
for (int i = 1; i < width - 1; i++) {
for (int j = 1; j < height - 1; j++) {
if ((i % 2 == 1) || (j % 2 == 1)) {
mySquares[i][j] = 1;
}
}
}
// the entrance to the maze is at (0,1).
mySquares[0][1] = 0;
createMaze();
mySquares[mySquares.length-1][mySquares[0].length-2] = 5;
}
/**
* This method randomly generates the maze.
*/
private void createMaze() {
// create an initial framework of black squares.
for (int i = 1; i < mySquares.length - 1; i++) {
for (int j = 1; j < mySquares[i].length - 1; j++) {
if ((i + j) % 2 == 1) {
mySquares[i][j] = 0;
}
}
}
// initialize the squares that can be either black or white
// depending on the maze.
// first we set the value to 3 which means undecided.
for (int i = 1; i < mySquares.length - 1; i += 2) {
for (int j = 1; j < mySquares[i].length - 1; j += 2) {
mySquares[i][j] = 3;
}
}
// Then those squares that can be selected to be open
// (white) paths are given the value of 2.
// We randomly select the square where the tree of maze
// paths will begin. The maze is generated starting from
// this initial square and branches out from here in all
// directions to fill the maze grid.
Vector possibleSquares = new Vector(mySquares.length
* mySquares[0].length);
int[] startSquare = new int[2];
startSquare[0] = getRandomInt(mySquares.length / 2) * 2 + 1;
startSquare[1] = getRandomInt(mySquares[0].length / 2) * 2 + 1;
mySquares[startSquare[0]][startSquare[1]] = 2;
possibleSquares.addElement(startSquare);
// Here we loop to select squares one by one to append to
// the maze pathway tree.
while (possibleSquares.size() > 0) {
// the next square to be joined on is selected randomly.
int chosenIndex = getRandomInt(possibleSquares.size());
int[] chosenSquare = (int[]) possibleSquares.elementAt(chosenIndex);
// we set the chosen square to white and then
// remove it from the list of possibleSquares (i.e. squares
// that can possibly be added to the maze), and we link
// the new square to the maze.
mySquares[chosenSquare[0]][chosenSquare[1]] = 1;
possibleSquares.removeElementAt(chosenIndex);
link(chosenSquare, possibleSquares);
}
// now that the maze has been completely generated, we
// throw away the objects that were created during the
// maze creation algorithm and reclaim the memory.
possibleSquares = null;
System.gc();
}
/**
* internal to createMaze. Checks the four squares surrounding
* the chosen square. Of those that are already connected to
* the maze, one is randomly selected to be joined to the
* current square (to attach the current square to the
* growing maze). Those squares that were not previously in
* a position to be joined to the maze are added to the list
* of "possible" squares (that could be chosen to be attached
* to the maze in the next round).
*/
private void link(int[] chosenSquare, Vector possibleSquares) {
int linkCount = 0;
int i = chosenSquare[0];
int j = chosenSquare[1];
int[] links = new int[8];
if (i >= 3) {
if (mySquares[i - 2][j] == 1) {
links[2 * linkCount] = i - 1;
links[2 * linkCount + 1] = j;
linkCount++;
} else if (mySquares[i - 2][j] == 3) {
mySquares[i - 2][j] = 2;
int[] newSquare = new int[2];
newSquare[0] = i - 2;
newSquare[1] = j;
possibleSquares.addElement(newSquare);
}
}
if (j + 3 <= mySquares[i].length) {
if (mySquares[i][j + 2] == 3) {
mySquares[i][j + 2] = 2;
int[] newSquare = new int[2];
newSquare[0] = i;
newSquare[1] = j + 2;
possibleSquares.addElement(newSquare);
} else if (mySquares[i][j + 2] == 1) {
links[2 * linkCount] = i;
links[2 * linkCount + 1] = j + 1;
linkCount++;
}
}
if (j >= 3) {
if (mySquares[i][j - 2] == 3) {
mySquares[i][j - 2] = 2;
int[] newSquare = new int[2];
newSquare[0] = i;
newSquare[1] = j - 2;
possibleSquares.addElement(newSquare);
} else if (mySquares[i][j - 2] == 1) {
links[2 * linkCount] = i;
links[2 * linkCount + 1] = j - 1;
linkCount++;
}
}
if (i + 3 <= mySquares.length) {
if (mySquares[i + 2][j] == 3) {
mySquares[i + 2][j] = 2;
int[] newSquare = new int[2];
newSquare[0] = i + 2;
newSquare[1] = j;
possibleSquares.addElement(newSquare);
} else if (mySquares[i + 2][j] == 1) {
links[2 * linkCount] = i + 1;
links[2 * linkCount + 1] = j;
linkCount++;
}
}
if (linkCount > 0) {
int linkChoice = getRandomInt(linkCount);
int linkX = links[2 * linkChoice];
int linkY = links[2 * linkChoice + 1];
mySquares[linkX][linkY] = 1;
int[] removeSquare = new int[2];
removeSquare[0] = linkX;
removeSquare[1] = linkY;
possibleSquares.removeElement(removeSquare);
}
}
/**
* a randomization utility.
* @param upper the upper bound for the random int.
* @return a random non-negative int less than the bound upper.
*/
public int getRandomInt(int upper) {
int retVal = myRandom.nextInt() % upper;
if (retVal < 0) {
retVal += upper;
}
return (retVal);
}
}

View File

@ -16,13 +16,9 @@ public class Keyboard {
} }
private int getKeyNum(int key) { private int getKeyNum(int key) {
if (key == Canvas.KEY_NUM0) Main.midlet.destroyApp(true);
else if(key == Canvas.KEY_STAR) Main.midlet.dsp.setCurrent(null);
else {
for (int i = 0; i < keys.length; i++) { for (int i = 0; i < keys.length; i++) {
if (key == keys[i]) return i; if (key == keys[i]) return i;
} }
}
return -1; return -1;
} }

View File

@ -5,37 +5,12 @@ import javax.microedition.lcdui.*;
public class RayCanvas extends Canvas {// implements Runnable { public class RayCanvas extends Canvas {// implements Runnable {
private Keyboard keyb; private Keyboard keyb;
private Grid grid;
//private final int mapWidth = 24; //private final int mapWidth = 24;
//private final int mapHeight = 24; //private final int mapHeight = 24;
private int gluk; private int gluk;
private Image pr; private Image pr;
private final int[][] worldMap =
{
{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,1},
{1,0,0,0,0,3,3,3,3,3,0,3,0,3,3,3,2,2,2,2,0,0,1,0,0,1,4,0,4,0,3,3,3,3,3,0,1},
{1,0,0,0,0,0,0,0,0,0,2,2,2,2,0,3,3,0,0,2,2,0,1,0,1,1,4,0,4,0,3,3,0,0,3,0,1},
{1,0,0,0,0,0,2,2,2,2,2,0,0,0,0,1,0,0,0,2,2,0,1,0,1,0,4,0,4,0,3,0,3,3,3,0,1},
{1,0,0,0,0,0,2,0,0,0,2,2,2,1,1,1,3,3,0,2,2,0,1,0,1,0,1,0,1,0,3,0,3,0,3,0,1},
{1,0,0,0,0,0,2,0,0,0,2,0,0,0,0,1,1,1,0,2,2,2,1,0,1,0,1,0,1,3,3,0,3,0,3,3,1},
{1,0,0,0,0,0,2,0,0,0,2,0,0,1,1,1,1,1,1,1,0,0,3,0,1,0,1,0,1,0,3,0,0,0,0,0,1},
{1,0,0,1,0,0,2,2,0,2,2,0,0,1,0,0,0,0,0,0,0,0,3,0,1,0,2,0,2,0,3,0,3,0,0,0,1},
{1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,0,3,0,2,0,2,0,2,0,2,0,0,0,1},
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,0,3,0,2,0,2,0,0,0,0,0,0,0,1},
{1,0,3,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,0,3,0,2,0,2,0,0,0,0,0,0,0,1},
{1,0,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,0,3,0,3,0,3,0,0,0,0,0,0,0,1},
{1,3,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,0,3,0,3,0,3,0,0,0,0,0,0,0,1},
{1,2,0,2,0,2,2,1,1,1,1,0,0,0,0,0,0,0,0,0,3,3,3,0,3,0,3,0,3,0,0,0,0,0,0,0,1},
{1,0,0,3,0,0,0,0,0,0,3,0,2,2,2,2,2,2,0,0,3,0,0,0,3,0,3,0,3,0,0,0,0,0,0,0,1},
{1,4,4,4,4,4,4,4,4,0,3,0,2,0,0,2,2,2,2,0,2,0,3,0,0,4,1,0,1,0,0,0,0,0,0,0,1},
{1,4,0,4,0,0,0,0,4,0,3,3,2,2,0,0,0,0,0,0,0,0,3,4,4,4,1,0,1,0,0,0,0,0,0,0,1},
{1,4,0,0,0,0,5,0,4,0,0,0,0,4,0,4,0,4,4,4,4,4,4,4,0,0,1,0,1,0,0,0,0,0,0,0,1},
{1,4,0,4,0,0,0,0,4,0,2,3,0,4,0,4,0,4,0,4,4,0,4,4,0,0,2,0,2,0,0,0,0,0,3,3,1},
{1,4,0,4,4,4,4,4,4,0,3,3,0,0,0,4,0,4,0,0,0,0,0,4,0,0,3,0,3,0,0,0,0,0,3,0,1},
{1,4,0,0,0,0,0,0,0,0,3,4,4,4,4,4,0,4,0,4,4,4,4,4,1,2,4,0,4,3,2,1,1,2,3,0,1},
{1,4,4,4,4,4,4,4,4,3,3,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,1},
{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}
};
private int[][] colors = new int[][] { private int[][] colors = new int[][] {
{0xcccc44, 0x444444, 0x333333, 0x222222, 0x111111},//gluk0 {0xcccc44, 0x444444, 0x333333, 0x222222, 0x111111},//gluk0
{0xcccc44, 0xaaaaaa, 0x888888, 0x555555, 0xcccccc},//gluk1 {0xcccc44, 0xaaaaaa, 0x888888, 0x555555, 0xcccccc},//gluk1
@ -47,18 +22,22 @@ public class RayCanvas extends Canvas {// implements Runnable {
private double planeX, planeY; //the 2d raycaster version of camera plane private double planeX, planeY; //the 2d raycaster version of camera plane
private int w,h; private int w,h;
private long lastTime; private long lastTime;
private int iFps, iActFps, iTimeToCountFps; private boolean showUI;
private final int size = 4;
public RayCanvas() { public RayCanvas() {
setFullScreenMode(true); setFullScreenMode(true);
w = getWidth(); w = getWidth();
h = getHeight(); h = getHeight();
grid = new Grid(24, 24);
grid.newMaze();
posX = 22; showUI = false;
posY = 27.5; posX = 7;
posY = 6.5;
dirX = -1; dirX = -1;
lastTime = 0;
dirY = planeX = 0; dirY = planeX = 0;
iFps = iActFps = iTimeToCountFps = 0;
planeY = 0.66; planeY = 0.66;
gluk = 1; gluk = 1;
@ -79,7 +58,10 @@ public class RayCanvas extends Canvas {// implements Runnable {
// } // }
protected void keyPressed(int key) { protected void keyPressed(int key) {
keyb.onPressed(key, getGameAction(key)); if(key == KEY_STAR) showUI = !showUI;
else if (key == -6) grid.newMaze();
else if (key == KEY_NUM0) Main.midlet.destroyApp(true);
else keyb.onPressed(key, getGameAction(key));
} }
protected void keyReleased(int key) { protected void keyReleased(int key) {
@ -91,13 +73,6 @@ public class RayCanvas extends Canvas {// implements Runnable {
int dTime = (int) (thisTime - lastTime);// âðåìÿ, ïðîøåäøåå ñ ïðîøëîãî êàäðà int dTime = (int) (thisTime - lastTime);// âðåìÿ, ïðîøåäøåå ñ ïðîøëîãî êàäðà
lastTime = thisTime; lastTime = thisTime;
iTimeToCountFps += dTime;
iFps++;
if (iTimeToCountFps >= 1000) {// åñëè íàáðàëîñü 1 ñåêóíäà - îáíîâëÿåì ñ÷åò÷èê
iActFps = iFps;
iTimeToCountFps = iFps = 0;
}
g.setColor(0); g.setColor(0);
g.fillRect(0, 0, w, h); g.fillRect(0, 0, w, h);
@ -155,9 +130,12 @@ public class RayCanvas extends Canvas {// implements Runnable {
side = 1; side = 1;
} }
//Check if ray has hit a wall //Check if ray has hit a wall
if (worldMap[mapX][mapY] > 0) try {
if (getCell(mapX, mapY) > 0) hit = 1;
} catch (Exception e) {
hit = 1; hit = 1;
} }
}
//Calculate distance projected on camera direction (oblique distance will give fisheye effect!) //Calculate distance projected on camera direction (oblique distance will give fisheye effect!)
if (side == 0) { if (side == 0) {
perpWallDist = Math.abs((mapX - rayPosX + (1 - stepX) / 2) / rayDirX); perpWallDist = Math.abs((mapX - rayPosX + (1 - stepX) / 2) / rayDirX);
@ -186,7 +164,7 @@ public class RayCanvas extends Canvas {// implements Runnable {
} }
int color = 0; int color = 0;
try { try {
color = colors[gluk][worldMap[mapX][mapY]]; color = colors[gluk][getCell(mapX, mapY)];
//give x and y sides different brightness //give x and y sides different brightness
if (side == 1) color -= 0x333333; if (side == 1) color -= 0x333333;
} catch (Exception e) { } catch (Exception e) {
@ -205,19 +183,19 @@ public class RayCanvas extends Canvas {// implements Runnable {
//move forward if no wall in front of you //move forward if no wall in front of you
if (keyb.getKeyState(UP)) { if (keyb.getKeyState(UP)) {
if (worldMap[(int) (posX + dirX * moveSpeed)][(int) posY] == 0) { if (getCell((int) (posX + dirX * moveSpeed), (int) posY) == 0) {
posX += dirX * moveSpeed; posX += dirX * moveSpeed;
} }
if (worldMap[(int) posX][(int) (posY + dirY * moveSpeed)] == 0) { if (getCell((int) posX, (int) (posY + dirY * moveSpeed)) == 0) {
posY += dirY * moveSpeed; posY += dirY * moveSpeed;
} }
} }
//move backwards if no wall behind you //move backwards if no wall behind you
if (keyb.getKeyState(DOWN)) { if (keyb.getKeyState(DOWN)) {
if (worldMap[(int) (posX - dirX * moveSpeed)][(int) posY] == 0) { if (getCell((int) (posX - dirX * moveSpeed), (int) posY) == 0) {
posX -= dirX * moveSpeed; posX -= dirX * moveSpeed;
} }
if (worldMap[(int) posX][(int) (posY - dirY * moveSpeed)] == 0) { if (getCell((int) posX, (int) (posY - dirY * moveSpeed)) == 0) {
posY -= dirY * moveSpeed; posY -= dirY * moveSpeed;
} }
} }
@ -242,9 +220,30 @@ public class RayCanvas extends Canvas {// implements Runnable {
planeY = oldPlaneX * Math.sin(rotSpeed) + planeY * Math.cos(rotSpeed); planeY = oldPlaneX * Math.sin(rotSpeed) + planeY * Math.cos(rotSpeed);
} }
// fps if(showUI) showLabirinth(g, (int)posX, (int)posY);
g.setColor(0xff);
g.drawString("" + iActFps, 1, 1, 20);
repaint(); repaint();
} }
private void showLabirinth(Graphics g, int x, int y) {
System.out.println("x= "+x+" y= "+y+" id= "+grid.mySquares[x][y]);
g.setColor(0xFFFFFF);
g.fillRect(0, 0, grid.width, grid.height);
g.setColor(0x00FF);
for(int i=0; i<grid.width; i++) {
for(int j=0; j<grid.height; j++) {
if(grid.mySquares[i][j]==1)
g.fillRect(i*size, j*size, size, size);
}
}
g.setColor(0xFF0000);
g.fillRect(x*size, y*size, size, size);
}
private int getCell(int x, int y) {
try {
return grid.mySquares[x][y];
}catch(Exception ex) {
return 1;
}
}
} }