Yeahboi
Posts: 20
Joined: Wed Mar 18, 2020 5:17 am

Ray-cast 3D Game Engine

Wed Mar 18, 2020 8:28 am

Would Anyone Be willing to help me get this working? Its a simplistic Ray-cast engine, similar to the original DOOM game. But there is some issue with the textures that I haven't been able to fix for over a month now. Can anyone spot my mistake, or run it themselves to try and find it? I would greatly appreciate it.

Here, I've gone and pasted the code below. it has 4 separate .java files. images are attached, and need to go in a folder named "TEXTURES", with said folder being in the same location as the java files.

Code: Select all

import java.awt.Graphics;
import java.awt.image.BufferStrategy;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferInt;
import java.util.ArrayList;
import javax.swing.JFrame;

public class Game extends JFrame implements Runnable{

	private static final long serialVersionUID = 1L;
	public int mapWidth = 15;
	public int mapHeight = 15;
	public double delta = 0;
	private Thread thread;
	private boolean running;
	private BufferedImage image;
	public int[] pixels;
	public ArrayList<Texture> textures;
	public Camera camera;
	public Screen screen;
	public static int[][] map =
		{
			{1,1,1,1,1,1,1,1,2,2,2,2,2,2,2},
			{1,0,0,0,0,0,0,0,2,0,0,0,0,0,2},
			{1,0,3,3,3,3,3,0,0,0,0,0,0,0,2},
			{1,0,3,0,0,0,3,0,2,0,0,0,0,0,2},
			{1,0,3,0,0,0,3,0,2,2,2,0,2,2,2},
			{1,0,3,0,0,0,3,0,2,0,0,0,0,0,2},
			{1,0,3,3,0,3,3,0,2,0,0,0,0,0,2},
			{1,0,0,0,0,0,0,0,2,0,0,0,0,0,2},
			{1,1,1,1,1,1,1,1,4,4,4,0,4,4,4},
			{1,0,0,0,0,0,1,4,0,0,0,0,0,0,4},
			{1,0,0,0,0,0,1,4,0,0,0,0,0,0,4},
			{1,0,0,0,0,0,1,4,0,3,3,3,3,0,4},
			{1,0,0,0,0,0,1,4,0,3,3,3,3,0,4},
			{1,0,0,0,0,0,0,0,0,0,0,0,0,0,4},
			{1,1,1,1,1,1,1,4,4,4,4,4,4,4,4}
		};
	public Game() {
		thread = new Thread(this);
		image = new BufferedImage(1280, 720, BufferedImage.TYPE_INT_RGB);
		pixels = ((DataBufferInt)image.getRaster().getDataBuffer()).getData();
		textures = new ArrayList<Texture>();
		textures.add(Texture.beigebrick);
		textures.add(Texture.greybrick);
		textures.add(Texture.redbrick);
		textures.add(Texture.blackbrick);
		camera = new Camera(4.5, 4.5, 1, 0, 0, -.66);
		screen = new Screen(map, mapWidth, mapHeight, textures, 1280, 720);
		addKeyListener(camera);
		setSize(1280, 720);
		setResizable(false);
		setTitle("3D Engine");
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setBackground(Color.black);
		setLocationRelativeTo(null);
		setVisible(true);
		start();
	}
	private synchronized void start() {
		running = true;
		thread.start();
	}
	public synchronized void stop() {
		running = false;
		try {
			thread.join();
		} catch(InterruptedException e) {
			e.printStackTrace();
		}
	}
	public void render() {
		BufferStrategy bs = getBufferStrategy();
		if(bs == null) {
			createBufferStrategy(3);
			return;
		}
		Graphics g = bs.getDrawGraphics();
		g.drawImage(image, 0, 0, image.getWidth(), image.getHeight(), null);
		bs.show();
	}
	public void run() {
		long lastTime = System.nanoTime();
		final double ns = 1000000000.0 / 60.0;//60 times per second
		requestFocus();
		while(running) {
			long now = System.nanoTime();
			delta = delta + ((now-lastTime) / ns);
			lastTime = now;
			while (delta >= 1)//Make sure update is only happening 60 times a second
			{
				//handles all of the logic restricted time
				screen.update(camera, pixels);
				camera.update(map);
				delta--;
			}
			render();//displays to the screen unrestricted time
		}
	}
	public void coordinates(String [] args) {
		while (delta >= 1){
			System.out.println(camera.xPos + " " + camera.yPos);
		}

	}
	public static void main(String [] args){

		Game game = new Game();
}
}

[mport java.awt.event.KeyListener;


public class Camera implements KeyListener{
	public double xPos, yPos, xDir, yDir, xPlane, yPlane;
	public boolean left, right, forward, back;
	public final double MOVE_SPEED = .04;
	public final double ROTATION_SPEED = .045;
	public Camera(double x, double y, double xd, double yd, double xp, double yp) {
		xPos = x;
		yPos = y;
		xDir = xd;
		yDir = yd;
		xPlane = xp;
		yPlane = yp;
	}
	public void keyPressed(KeyEvent key) {
		if((key.getKeyCode() == KeyEvent.VK_LEFT))
			left = true;
		if((key.getKeyCode() == KeyEvent.VK_RIGHT))
			right = true;
		if((key.getKeyCode() == KeyEvent.VK_UP))
			forward = true;
		if((key.getKeyCode() == KeyEvent.VK_DOWN))
			back = true;
		if((key.getKeyCode() == KeyEvent.VK_ESCAPE))
			gameCloser = true;
	}
	public void keyReleased(KeyEvent key) {
		if((key.getKeyCode() == KeyEvent.VK_LEFT))
			left = false;
		if((key.getKeyCode() == KeyEvent.VK_RIGHT))
			right = false;
		if((key.getKeyCode() == KeyEvent.VK_UP))
			forward = false;
		if((key.getKeyCode() == KeyEvent.VK_DOWN))
			back = false;
	}
	public void update(int[][] map) {
		if(forward) {
			if(map[(int)(xPos + xDir * MOVE_SPEED)][(int)yPos] == 0) {
				xPos+=xDir*MOVE_SPEED;
			}
			if(map[(int)xPos][(int)(yPos + yDir * MOVE_SPEED)] ==0)
				yPos+=yDir*MOVE_SPEED;
		}
		if(back) {
			if(map[(int)(xPos - xDir * MOVE_SPEED)][(int)yPos] == 0)
				xPos-=xDir*MOVE_SPEED;
			if(map[(int)xPos][(int)(yPos - yDir * MOVE_SPEED)]==0)
				yPos-=yDir*MOVE_SPEED;
		}
		if(right) {
			double oldxDir=xDir;
			xDir=xDir*Math.cos(-ROTATION_SPEED) - yDir*Math.sin(-ROTATION_SPEED);
			yDir=oldxDir*Math.sin(-ROTATION_SPEED) + yDir*Math.cos(-ROTATION_SPEED);
			double oldxPlane = xPlane;
			xPlane=xPlane*Math.cos(-ROTATION_SPEED) - yPlane*Math.sin(-ROTATION_SPEED);
			yPlane=oldxPlane*Math.sin(-ROTATION_SPEED) + yPlane*Math.cos(-ROTATION_SPEED);
		}
		if(left) {
			double oldxDir=xDir;
			xDir=xDir*Math.cos(ROTATION_SPEED) - yDir*Math.sin(ROTATION_SPEED);
			yDir=oldxDir*Math.sin(ROTATION_SPEED) + yDir*Math.cos(ROTATION_SPEED);
			double oldxPlane = xPlane;
			xPlane=xPlane*Math.cos(ROTATION_SPEED) - yPlane*Math.sin(ROTATION_SPEED);
			yPlane=oldxPlane*Math.sin(ROTATION_SPEED) + yPlane*Math.cos(ROTATION_SPEED);
		}
	}
	public void keyTyped(KeyEvent arg0) {
		// TODO Auto-generated method stub

	}
}

import java.awt.Color;

public class Screen {
	public int[][] map;
	public int mapWidth, mapHeight, width, height;
	public ArrayList<Texture> textures;

	public Screen(int[][] m, int mapW, int mapH, ArrayList<Texture> tex, int w, int h) {
		map = m;
		mapWidth = mapW;
		mapHeight = mapH;
		textures = tex;
		width = w;
		height = h;
	}
	public int[] update(Camera camera, int[] pixels) {
		for(int n=0; n<pixels.length/2; n++) {
			if(pixels[n] != Color.DARK_GRAY.getRGB()) pixels[n] = Color.DARK_GRAY.getRGB();
		}
		for(int i=pixels.length/2; i<pixels.length; i++){
			if(pixels[i] != Color.gray.getRGB()) pixels[i] = Color.gray.getRGB();
		}

	    for(int x=0; x<width; x=x+1) {
			double cameraX = 2 * x / (double)(width) -1;
		    double rayDirX = camera.xDir + camera.xPlane * cameraX;
		    double rayDirY = camera.yDir + camera.yPlane * cameraX;
		    //Map position
		    int mapX = (int)camera.xPos;
		    int mapY = (int)camera.yPos;
		    //length of ray from current position to next x or y-side
		    double sideDistX;
		    double sideDistY;
		    //Length of ray from one side to next in map
		    double deltaDistX = Math.sqrt(1 + (rayDirY*rayDirY) / (rayDirX*rayDirX));
		    double deltaDistY = Math.sqrt(1 + (rayDirX*rayDirX) / (rayDirY*rayDirY));
		    double perpWallDist;
		    //Direction to go in x and y
		    int stepX, stepY;
		    boolean hit = false;//was a wall hit
		    int side=0;//was the wall vertical or horizontal
		    //Figure out the step direction and initial distance to a side
		    if (rayDirX < 0)
		    {
		    	stepX = -1;
		    	sideDistX = (camera.xPos - mapX) * deltaDistX;
		    }
		    else
		    {
		    	stepX = 1;
		    	sideDistX = (mapX + 1.0 - camera.xPos) * deltaDistX;
		    }
		    if (rayDirY < 0)
		    {
		    	stepY = -1;
		        sideDistY = (camera.yPos - mapY) * deltaDistY;
		    }
		    else
		    {
		    	stepY = 1;
		        sideDistY = (mapY + 1.0 - camera.yPos) * deltaDistY;
		    }
		    //Loop to find where the ray hits a wall
		    while(!hit) {
		    	//Jump to next square
		    	if (sideDistX < sideDistY)
		        {
		    		sideDistX += deltaDistX;
		    		mapX += stepX;
		    		side = 0;
		        }
		        else
		        {
		        	sideDistY += deltaDistY;
		        	mapY += stepY;
		        	side = 1;
		        }
		    	//Check if ray has hit a wall
		    	//System.out.println(mapX + ", " + mapY + ", " + map[mapX][mapY]);
		    	if(map[mapX][mapY] > 0) {
		    		hit = true;
		    }
		    }
		    //Calculate distance to the point of impact
		    if(side==0)
		    	perpWallDist = Math.abs((mapX - camera.xPos + (1 - stepX) / 2) / rayDirX);
		    else
		    	perpWallDist = Math.abs((mapY - camera.yPos + (1 - stepY) / 2) / rayDirY);
		    //Now calculate the height of the wall based on the distance from the camera
		    int lineHeight;
		    if(perpWallDist > 0) lineHeight = Math.abs((int)(height / perpWallDist));
		    else lineHeight = height;
		    //calculate lowest and highest pixel to fill in current stripe
		    int drawStart = -lineHeight/2+ height/2;
		    if(drawStart < 0)
		    	drawStart = 0;
		    int drawEnd = lineHeight/2 + height/2;
		    if(drawEnd >= height)
		    	drawEnd = height - 1;
		    //add a texture
		    int texNum = map[mapX][mapY] - 1;
		    double wallX;//Exact position of where wall was hit
		    if(side==1) {//If its a y-axis wall
		    	wallX = (camera.xPos + ((mapY - camera.yPos + (1 - stepY) / 2) / rayDirY) * rayDirX);
		    } else {//X-axis wall
		    	wallX = (camera.yPos + ((mapX - camera.xPos + (1 - stepX) / 2) / rayDirX) * rayDirY);
		    }
		    wallX-=Math.floor(wallX);
		    //x coordinate on the texture
		    int texX = (int)(wallX * (textures.get(texNum).SIZE));
		    if(side == 0 && rayDirX > 0) texX = textures.get(texNum).SIZE - texX - 1;
		    if(side == 1 && rayDirY < 0) texX = textures.get(texNum).SIZE - texX - 1;
		    //calculate y coordinate on texture
		    for(int y=drawStart; y<drawEnd; y++) {
		    	int texY = (((y*2 - height + lineHeight) << 6) / lineHeight) / 2;
		    	int color;
		    	if(side==0) color = textures.get(texNum).pixels[texX + (texY * textures.get(texNum).SIZE)];
		    	else color = (textures.get(texNum).pixels[texX + (texY * textures.get(texNum).SIZE)]>>1) & 8355711;//Make y sides darker
		    	pixels[x + y*(width)] = color;
		    }
		}
		return pixels;
	}
}

import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;

public class Texture {
	public int[] pixels;
	private String loc;
	public final int SIZE;

	public Texture(String location, int size) {
		loc = location;
		SIZE = size;
		pixels = new int[SIZE * SIZE];
		load();
	}

	private void load() {
		try {
			BufferedImage image = ImageIO.read(new File(loc));
			int w = image.getWidth();
			int h = image.getHeight();
			image.getRGB(0, 0, 0, w, h,pixels, w);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	public static Texture beigebrick = new Texture("TEXTURES/Beige_Brick.png", 64);
	public static Texture greybrick = new Texture("TEXTURES/Grey_Brick.png", 64);
	public static Texture redbrick = new Texture("TEXTURES/Black_Brick.png", 64);
	public static Texture blackbrick = new Texture("TEXTURES/Black_Brick.png", 64);
}
Beige_Brick.png
Beige_Brick.png (2.33 KiB) Viewed 521 times
Black_Brick.png
Black_Brick.png (2.32 KiB) Viewed 521 times
Grey_Brick.png
Grey_Brick.png (2.32 KiB) Viewed 521 times
Remember; I'm kind of an idiot when it comes to this.

Yeahboi
Posts: 20
Joined: Wed Mar 18, 2020 5:17 am

Re: Ray-cast 3D Game Engine

Fri Mar 20, 2020 7:47 pm

I hadn't posted the code correctly. My mistake.

Ill post the four parts correctly in a series of replies, starting with this one

PART 1: Game.JAVA

Code: Select all

import java.awt.Color;
import java.awt.Graphics;
import java.awt.image.BufferStrategy;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferInt;
import java.util.ArrayList;
import javax.swing.JFrame;

public class Game extends JFrame implements Runnable{

	private static final long serialVersionUID = 1L;
	public int mapWidth = 15;
	public int mapHeight = 15;
	public double delta = 0;
	private Thread thread;
	private boolean running;
	private BufferedImage image;
	public int[] pixels;
	public ArrayList<Texture> textures;
	public Camera camera;
	public Screen screen;
	public static int[][] map =
		{
			{1,1,1,1,1,1,1,1,2,2,2,2,2,2,2},
			{1,0,0,0,0,0,0,0,2,0,0,0,0,0,2},
			{1,0,3,3,3,3,3,0,0,0,0,0,0,0,2},
			{1,0,3,0,0,0,3,0,2,0,0,0,0,0,2},
			{1,0,3,0,0,0,3,0,2,2,2,0,2,2,2},
			{1,0,3,0,0,0,3,0,2,0,0,0,0,0,2},
			{1,0,3,3,0,3,3,0,2,0,0,0,0,0,2},
			{1,0,0,0,0,0,0,0,2,0,0,0,0,0,2},
			{1,1,1,1,1,1,1,1,4,4,4,0,4,4,4},
			{1,0,0,0,0,0,1,4,0,0,0,0,0,0,4},
			{1,0,0,0,0,0,1,4,0,0,0,0,0,0,4},
			{1,0,0,0,0,0,1,4,0,3,3,3,3,0,4},
			{1,0,0,0,0,0,1,4,0,3,3,3,3,0,4},
			{1,0,0,0,0,0,0,0,0,0,0,0,0,0,4},
			{1,1,1,1,1,1,1,4,4,4,4,4,4,4,4}
		};
	public Game() {
		thread = new Thread(this);
		image = new BufferedImage(1280, 720, BufferedImage.TYPE_INT_RGB);
		pixels = ((DataBufferInt)image.getRaster().getDataBuffer()).getData();
		textures = new ArrayList<Texture>();
		textures.add(Texture.beigebrick);
		textures.add(Texture.greybrick);
		textures.add(Texture.redbrick);
		textures.add(Texture.blackbrick);
		camera = new Camera(4.5, 4.5, 1, 0, 0, -.66);
		screen = new Screen(map, mapWidth, mapHeight, textures, 1280, 720);
		addKeyListener(camera);
		setSize(1280, 720);
		setResizable(false);
		setTitle("3D Engine");
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setBackground(Color.black);
		setLocationRelativeTo(null);
		setVisible(true);
		start();
	}
	private synchronized void start() {
		running = true;
		thread.start();
	}
	public synchronized void stop() {
		running = false;
		try {
			thread.join();
		} catch(InterruptedException e) {
			e.printStackTrace();
		}
	}
	public void render() {
		BufferStrategy bs = getBufferStrategy();
		if(bs == null) {
			createBufferStrategy(3);
			return;
		}
		Graphics g = bs.getDrawGraphics();
		g.drawImage(image, 0, 0, image.getWidth(), image.getHeight(), null);
		bs.show();
	}
	public void run() {
		long lastTime = System.nanoTime();
		final double ns = 1000000000.0 / 60.0;//60 times per second
		requestFocus();
		while(running) {
			long now = System.nanoTime();
			delta = delta + ((now-lastTime) / ns);
			lastTime = now;
			while (delta >= 1)//Make sure update is only happening 60 times a second
			{
				//handles all of the logic restricted time
				screen.update(camera, pixels);
				camera.update(map);
				delta--;
			}
			render();//displays to the screen unrestricted time
		}
	}
	public void coordinates(String [] args) {
		while (delta >= 1){
			System.out.println(camera.xPos + " " + camera.yPos);
		}

	}
	public static void main(String [] args){

		Game game = new Game();
}
}
Remember; I'm kind of an idiot when it comes to this.

Yeahboi
Posts: 20
Joined: Wed Mar 18, 2020 5:17 am

Re: Ray-cast 3D Game Engine

Fri Mar 20, 2020 7:48 pm

PART 2: Screen.java

Code: Select all

import java.util.ArrayList;
import java.awt.Color;

public class Screen {
	public int[][] map;
	public int mapWidth, mapHeight, width, height;
	public ArrayList<Texture> textures;
	
	public Screen(int[][] m, int mapW, int mapH, ArrayList<Texture> tex, int w, int h) {
		map = m;
		mapWidth = mapW;
		mapHeight = mapH;
		textures = tex;
		width = w;
		height = h;
	}
	
	public int[] update(Camera camera, int[] pixels) {
		for(int n=0; n<pixels.length/2; n++) {
			if(pixels[n] != Color.DARK_GRAY.getRGB()) pixels[n] = Color.DARK_GRAY.getRGB();
		}
		for(int i=pixels.length/2; i<pixels.length; i++){
			if(pixels[i] != Color.gray.getRGB()) pixels[i] = Color.gray.getRGB();
		}
	    
	    for(int x=0; x<width; x=x+1) {
			double cameraX = 2 * x / (double)(width) -1;
		    double rayDirX = camera.xDir + camera.xPlane * cameraX;
		    double rayDirY = camera.yDir + camera.yPlane * cameraX;
		    //Map position
		    int mapX = (int)camera.xPos;
		    int mapY = (int)camera.yPos;
		    //length of ray from current position to next x or y-side
		    double sideDistX;
		    double sideDistY;
		    //Length of ray from one side to next in map
		    double deltaDistX = Math.sqrt(1 + (rayDirY*rayDirY) / (rayDirX*rayDirX));
		    double deltaDistY = Math.sqrt(1 + (rayDirX*rayDirX) / (rayDirY*rayDirY));
		    double perpWallDist;
		    //Direction to go in x and y
		    int stepX, stepY;
		    boolean hit = false;//was a wall hit
		    int side=0;//was the wall vertical or horizontal
		    //Figure out the step direction and initial distance to a side
		    if (rayDirX < 0)
		    {
		    	stepX = -1;
		    	sideDistX = (camera.xPos - mapX) * deltaDistX;
		    }
		    else
		    {
		    	stepX = 1;
		    	sideDistX = (mapX + 1.0 - camera.xPos) * deltaDistX;
		    }
		    if (rayDirY < 0)
		    {
		    	stepY = -1;
		        sideDistY = (camera.yPos - mapY) * deltaDistY;
		    }
		    else
		    {
		    	stepY = 1;
		        sideDistY = (mapY + 1.0 - camera.yPos) * deltaDistY;
		    }
		    //Loop to find where the ray hits a wall
		    while(!hit) {
		    	//Jump to next square
		    	if (sideDistX < sideDistY)
		        {
		    		sideDistX += deltaDistX;
		    		mapX += stepX;
		    		side = 0;
		        }
		        else
		        {
		        	sideDistY += deltaDistY;
		        	mapY += stepY;
		        	side = 1;
		        }
		    	//Check if ray has hit a wall
		    	//System.out.println(mapX + ", " + mapY + ", " + map[mapX][mapY]);
		    	if(map[mapX][mapY] > 0) hit = true;
		    }
		    //Calculate distance to the point of impact
		    if(side==0)
		    	perpWallDist = Math.abs((mapX - camera.xPos + (1 - stepX) / 2) / rayDirX);
		    else
		    	perpWallDist = Math.abs((mapY - camera.yPos + (1 - stepY) / 2) / rayDirY);	
		    //Now calculate the height of the wall based on the distance from the camera
		    int lineHeight;
		    if(perpWallDist > 0) lineHeight = Math.abs((int)(height / perpWallDist));
		    else lineHeight = height;
		    //calculate lowest and highest pixel to fill in current stripe
		    int drawStart = -lineHeight/2+ height/2;
		    if(drawStart < 0)
		    	drawStart = 0;
		    int drawEnd = lineHeight/2 + height/2;
		    if(drawEnd >= height) 
		    	drawEnd = height - 1;
		    //add a texture
		    int texNum = map[mapX][mapY] - 1;
		    double wallX;//Exact position of where wall was hit
		    if(side==1) {//If its a y-axis wall
		    	wallX = (camera.xPos + ((mapY - camera.yPos + (1 - stepY) / 2) / rayDirY) * rayDirX);
		    } else {//X-axis wall
		    	wallX = (camera.yPos + ((mapX - camera.xPos + (1 - stepX) / 2) / rayDirX) * rayDirY);
		    }
		    wallX-=Math.floor(wallX);
		    //x coordinate on the texture
		    int texX = (int)(wallX * (textures.get(texNum).SIZE));
		    if(side == 0 && rayDirX > 0) texX = textures.get(texNum).SIZE - texX - 1;
		    if(side == 1 && rayDirY < 0) texX = textures.get(texNum).SIZE - texX - 1;
		    //calculate y coordinate on texture
		    for(int y=drawStart; y<drawEnd; y++) {
		    	int texY = (((y*2 - height + lineHeight) << 6) / lineHeight) / 2;
		    	int color;
		    	if(side==0) color = textures.get(texNum).pixels[texX + (texY * textures.get(texNum).SIZE)];
		    	else color = (textures.get(texNum).pixels[texX + (texY * textures.get(texNum).SIZE)]>>1) & 8355711;//Make y sides darker
		    	pixels[x + y*(width)] = color;
		    }
		}
		return pixels;
	}
}
}
Last edited by Yeahboi on Mon Mar 23, 2020 4:28 am, edited 1 time in total.
Remember; I'm kind of an idiot when it comes to this.

Yeahboi
Posts: 20
Joined: Wed Mar 18, 2020 5:17 am

Re: Ray-cast 3D Game Engine

Fri Mar 20, 2020 7:52 pm

PART 3: Camera.java

Code: Select all

import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;


public class Camera implements KeyListener{
	public double xPos, yPos, xDir, yDir, xPlane, yPlane;
	public boolean left, right, forward, back;
	public final double MOVE_SPEED = .04;
	public final double ROTATION_SPEED = .045;
	public Camera(double x, double y, double xd, double yd, double xp, double yp) {
		xPos = x;
		yPos = y;
		xDir = xd;
		yDir = yd;
		xPlane = xp; 
		yPlane = yp;
	}
	public void keyPressed(KeyEvent key) {
		if((key.getKeyCode() == KeyEvent.VK_LEFT))
			left = true;
		if((key.getKeyCode() == KeyEvent.VK_RIGHT))
			right = true;
		if((key.getKeyCode() == KeyEvent.VK_UP))
			forward = true;
		if((key.getKeyCode() == KeyEvent.VK_DOWN))
			back = true;
		if((key.getKeyCode() == KeyEvent.VK_ESCAPE))
			gameCloser = true;
	}
	public void keyReleased(KeyEvent key) {
		if((key.getKeyCode() == KeyEvent.VK_LEFT))
			left = false;
		if((key.getKeyCode() == KeyEvent.VK_RIGHT))
			right = false;
		if((key.getKeyCode() == KeyEvent.VK_UP))
			forward = false;
		if((key.getKeyCode() == KeyEvent.VK_DOWN))
			back = false;
	}
	public void update(int[][] map) {
		if(forward) {
			if(map[(int)(xPos + xDir * MOVE_SPEED)][(int)yPos] == 0) {
				xPos+=xDir*MOVE_SPEED;
			}
			if(map[(int)xPos][(int)(yPos + yDir * MOVE_SPEED)] ==0)
				yPos+=yDir*MOVE_SPEED;
		}
		if(back) {
			if(map[(int)(xPos - xDir * MOVE_SPEED)][(int)yPos] == 0)
				xPos-=xDir*MOVE_SPEED;
			if(map[(int)xPos][(int)(yPos - yDir * MOVE_SPEED)]==0)
				yPos-=yDir*MOVE_SPEED;
		}
		if(right) {
			double oldxDir=xDir;
			xDir=xDir*Math.cos(-ROTATION_SPEED) - yDir*Math.sin(-ROTATION_SPEED);
			yDir=oldxDir*Math.sin(-ROTATION_SPEED) + yDir*Math.cos(-ROTATION_SPEED);
			double oldxPlane = xPlane;
			xPlane=xPlane*Math.cos(-ROTATION_SPEED) - yPlane*Math.sin(-ROTATION_SPEED);
			yPlane=oldxPlane*Math.sin(-ROTATION_SPEED) + yPlane*Math.cos(-ROTATION_SPEED);
		}
		if(left) {
			double oldxDir=xDir;
			xDir=xDir*Math.cos(ROTATION_SPEED) - yDir*Math.sin(ROTATION_SPEED);
			yDir=oldxDir*Math.sin(ROTATION_SPEED) + yDir*Math.cos(ROTATION_SPEED);
			double oldxPlane = xPlane;
			xPlane=xPlane*Math.cos(ROTATION_SPEED) - yPlane*Math.sin(ROTATION_SPEED);
			yPlane=oldxPlane*Math.sin(ROTATION_SPEED) + yPlane*Math.cos(ROTATION_SPEED);
		}
	}
	public void keyTyped(KeyEvent arg0) {
		// TODO Auto-generated method stub

	}
}
Remember; I'm kind of an idiot when it comes to this.

Yeahboi
Posts: 20
Joined: Wed Mar 18, 2020 5:17 am

Re: Ray-cast 3D Game Engine

Fri Mar 20, 2020 7:53 pm

PART 4: Texture.java

Code: Select all

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;

public class Texture {
	public int[] pixels;
	private String loc;
	public final int SIZE;

	public Texture(String location, int size) {
		loc = location;
		SIZE = size;
		pixels = new int[SIZE * SIZE];
		load();
	}

	private void load() {
		try {
			BufferedImage image = ImageIO.read(new File(loc));
			int w = image.getWidth();
			int h = image.getHeight();
			image.getRGB(0, 0, w, h, pixels, 0, w);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	public static Texture beigebrick = new Texture("TEXTURES/Beige_Brick.png", 64);
	public static Texture greybrick = new Texture("TEXTURES/Grey_Brick.png", 64);
	public static Texture redbrick = new Texture("TEXTURES/Red_Brick.png", 64);
	public static Texture blackbrick = new Texture("TEXTURES/Black_Brick.png", 64);
}
Remember; I'm kind of an idiot when it comes to this.

User avatar
mahjongg
Forum Moderator
Forum Moderator
Posts: 12653
Joined: Sun Mar 11, 2012 12:19 am
Location: South Holland, The Netherlands

Re: Ray-cast 3D Game Engine

Sat Mar 21, 2020 1:01 am

added code tags

jalih
Posts: 118
Joined: Mon Apr 15, 2019 3:54 pm

Re: Ray-cast 3D Game Engine

Sat Mar 21, 2020 3:46 pm

Seems like you are using old raycasting tutorial by Lode Vandevenne as a reference? This is not Doom like, but a lot simpler wolfenstein 3d style raycasting. Doom uses BSP-trees, this is a lot simpler...

I have not programmed in Java but can give you one advice: DON'T DRAW WALLS PIXEL BY PIXEL! It's slow as hell! Use some image drawing function that can draw rectangular area from the image scaled. So, just calculate start and end points for the wall slice and draw it using image drawing function with hardware acceleration enabled!

Do you know anyone grazy enough to write raycaster with forth style programming language? Well, now you do! :lol:

Yeahboi
Posts: 20
Joined: Wed Mar 18, 2020 5:17 am

Re: Ray-cast 3D Game Engine

Sun Mar 22, 2020 5:00 am

um... I have no idea what you said. I'm kind of an idiot.

How do I do that?

Thank you for the tip, as well.
Remember; I'm kind of an idiot when it comes to this.

Yeahboi
Posts: 20
Joined: Wed Mar 18, 2020 5:17 am

Re: Ray-cast 3D Game Engine

Sun Mar 22, 2020 5:01 am

mahjongg wrote:
Sat Mar 21, 2020 1:01 am
added code tags
Thanks!
Remember; I'm kind of an idiot when it comes to this.

User avatar
Gavinmc42
Posts: 4338
Joined: Wed Aug 28, 2013 3:31 am

Re: Ray-cast 3D Game Engine

Sun Mar 22, 2020 5:46 am

Wrong code for Screen.java.

Are you going to test this on OpenJDK too?
i'm trying to get upto speed with OpengL/GLES with Java.

This has some Python Raymarch code, that uses the hardware.
https://github.com/Blakkis/GLSL_Python.

I'm relearning Processing as the Pi4 is now fast enough.
But I don't think OpenJDK and OpenGL on 64bit Pi's is working?
I have not had much luck getting JOGL or LWJGL to install n Gentoo64

Is Java a good language to use for a 3D game engine?
It would be nice to use the OpenGLES 3.1 Compute Shaders for things like water.
I'm dancing on Rainbows.
Raspberries are not Apples or Oranges

Yeahboi
Posts: 20
Joined: Wed Mar 18, 2020 5:17 am

Re: Ray-cast 3D Game Engine

Sun Mar 22, 2020 5:49 am

Gavinmc42 wrote:
Sun Mar 22, 2020 5:46 am
Wrong code for Screen.java.
What do you mean?
Remember; I'm kind of an idiot when it comes to this.

Yeahboi
Posts: 20
Joined: Wed Mar 18, 2020 5:17 am

Re: Ray-cast 3D Game Engine

Sun Mar 22, 2020 5:52 am

Gavinmc42 wrote:
Sun Mar 22, 2020 5:46 am

Are you going to test this on OpenJDK too?
I mean, except for the textures, Its worked so far.
Remember; I'm kind of an idiot when it comes to this.

User avatar
Gavinmc42
Posts: 4338
Joined: Wed Aug 28, 2013 3:31 am

Re: Ray-cast 3D Game Engine

Mon Mar 23, 2020 12:27 am

Wrong code for Screen.java.

What do you mean?
Screen.java has the Texture class code in it.

I'm renewing my Java skills, was using it on PC's before Pi's came out, then moved to Python on Pi's.

Tried to install libGDX, it looks like a cool lib for java gaming, but dependencies killed the install.
I think someone has got it working on Raspbian.
I'm dancing on Rainbows.
Raspberries are not Apples or Oranges

Yeahboi
Posts: 20
Joined: Wed Mar 18, 2020 5:17 am

Re: Ray-cast 3D Game Engine

Mon Mar 23, 2020 4:29 am

Gavinmc42 wrote:
Mon Mar 23, 2020 12:27 am
Screen.java has the Texture class code in it.
Fixed
Remember; I'm kind of an idiot when it comes to this.

User avatar
Gavinmc42
Posts: 4338
Joined: Wed Aug 28, 2013 3:31 am

Re: Ray-cast 3D Game Engine

Mon Mar 23, 2020 10:45 am

Much better, less errors but, I don't know Java enough yet to get it to run.
Oh, and you missed the red_brick file.
Make a blue set and Wolfenstein is closer :D

I need to think about more about the left/right sideslips movements.

Still cannot find a nice simple Java game engine that works on Pi's.
Bit more time on this and you will have one.
I'm dancing on Rainbows.
Raspberries are not Apples or Oranges

Yeahboi
Posts: 20
Joined: Wed Mar 18, 2020 5:17 am

Re: Ray-cast 3D Game Engine

Tue Mar 24, 2020 3:38 am

Gavinmc42 wrote:
Mon Mar 23, 2020 10:45 am
Oh, and you missed the red_brick file.
This web-page will only let me upload three images.
Remember; I'm kind of an idiot when it comes to this.

Yeahboi
Posts: 20
Joined: Wed Mar 18, 2020 5:17 am

Re: Ray-cast 3D Game Engine

Tue Mar 24, 2020 3:41 am

And I've figured out why the game (Textures) doesn't work.

Exception in thread "main" java.lang.ExceptionInInitializerError
at Game.<init>(Game.java:44)
at Game.main(Game.java:102)
Caused by: java.lang.ArrayIndexOutOfBoundsException: Index 4096 out of bounds for length 4096
at java.desktop/java.awt.image.BufferedImage.getRGB(BufferedImage.java:986)
at Texture.load(Texture.java:23)
at Texture.<init>(Texture.java:15)
at Texture.<clinit>(Texture.java:29)
... 2 more

Except I have no idea what this means.
Remember; I'm kind of an idiot when it comes to this.

jalih
Posts: 118
Joined: Mon Apr 15, 2019 3:54 pm

Re: Ray-cast 3D Game Engine

Tue Mar 24, 2020 7:19 am

Yeahboi wrote:
Tue Mar 24, 2020 3:41 am
And I've figured out why the game (Textures) doesn't work.

Exception in thread "main" java.lang.ExceptionInInitializerError
at Game.<init>(Game.java:44)
at Game.main(Game.java:102)
Caused by: java.lang.ArrayIndexOutOfBoundsException: Index 4096 out of bounds for length 4096
at java.desktop/java.awt.image.BufferedImage.getRGB(BufferedImage.java:986)
at Texture.load(Texture.java:23)
at Texture.<init>(Texture.java:15)
at Texture.<clinit>(Texture.java:29)
... 2 more

Except I have no idea what this means.
Exception message is quite clear and should give you a hint!

I have not looked at your code but most probably you are iterating somewhere to array length but forget that array starts at index 0, so last array index is array length - 1.

Yeahboi
Posts: 20
Joined: Wed Mar 18, 2020 5:17 am

Re: Ray-cast 3D Game Engine

Fri Mar 27, 2020 10:22 pm

jalih wrote:
Tue Mar 24, 2020 7:19 am
I have not looked at your code but most probably you are iterating somewhere to array length but forget that array starts at index 0, so last array index is array length - 1.
I am quite the idiot, so would you be able to explain in detail what that means?
Remember; I'm kind of an idiot when it comes to this.

Return to “Java”