Adding Offsets to My Java Game - java

So, as the title reads I am trying to add offsets to my java game. I was given a tip by a friend that I need to minus the offset from where I render the tiles onto my screen.
So I created a random world generator and did the offset thing, but I ran into a problem.
My Code:
public void generateMap(Graphics g) {
block = seed.nextInt(2);
//Render Dirt
if(block == 0) {
g.drawImage(Assets.dirt, x - GameState.xOffset, y - GameState.yOffset, null);
x += 32;
}
//Render Grass
if(block == 1) {
g.drawImage(Assets.grass, x - GameState.xOffset, y - GameState.yOffset, null);
x += 32;
}
//Check Where the X is
if(x > xFinish) {
if(y < yFinish) {
x = xStart;
y += 32;
}
}
}
looks simple enough right? after I do that I create code to add one to the offset every time I loop around:
public void tick() {
xOffset += 1;
}
So after that is done I run it but it does this:
is there any simple way I can fix this so that it appears that the screen "scrolls" to the left?

Is there any simple way I can fix this...
Probably not. Games are complicated. Don't let that dissuade you.
You are generating your game world and drawing in the same methods - you don't want to do this. Separation of responsibility is very important - you don't want a whole bunch of code in one spot doing the same thing. In this case, the functionality to generate the world and the drawing code need to be split.
For the world generation, generate the game world once, and persist it to storage using whatever format you like. Keep this away from the drawing code - it has no place there.
For representing blocks in your world, consider something like this:
class Block {
public BlockType getType() {
return type;
}
public int getxPosition() {
return xPosition;
}
public int getyPosition() {
return yPosition;
}
// hashCode(), equals(), etc omitted, they should be implemented
public static enum BlockType {
Dirt(Assets.dirt),
Grass(Assets.grass);
private final BufferedImage image;
BlockType(BufferedImage image) {
this.image = image;
}
public BufferedImage getImage() {
return image;
}
}
private final BlockType type;
private final int xPosition;
private final int yPosition;
private Block(BlockType type, int xPosition, int yPosition) {
this.type = type;
this.xPosition = xPosition;
this.yPosition = yPosition;
}
public static Block getInstance(BlockType type, int xPosition, int yPosition) {
return new Block(type, xPosition, yPosition);
}
}
You can then use Block.getInstance() to generate a map once, like this:
class GameState {
private final int WORLD_SIZE = 1024;
private Block[][] _world = new Block[WORLD_SIZE][WORLD_SIZE];
private static Random seed = new Random();
public void generateMap() {
int blockTypeLength = Block.BlockType.values().length;
for (int x = 0; x < WORLD_SIZE; x++) {
for (int y = 0; y < WORLD_SIZE; y++) {
int blockType = seed.nextInt(blockTypeLength);
_world[x][y] = Block.getInstance(Block.BlockType.values()[blockType], x, y);
}
}
}
public Block[][] getMap() {
return _world; // not thread safe, shares internal state, all the usual warnings
}
This obviously isn't the only way to generate a world - you would probably generate a world and save, then load from disk in later games (unless it was a short lived game - I don't know, that's your call).
Once you've got the world sorted out, you'd move on to a different module that would handle drawing. Assume GameState has two fields playerX and playerY that represent the player's coordinates in the game world (note: direct fields like this are bad practice, but used to simplify this example):
public void paintComponent(Graphics g) {
super.paintComponent(g);
Block[][] screen = new Block[16][16]; // declare a screen buffer to draw
// Assumes player is in the center of the screen
int screenRadiusX = GameFrame.Assets.SCREENBOUNDS_X / 2 / blockSize;
int screenRadiusY = GameFrame.Assets.SCREENBOUNDS_Y / 2 / blockSize;
for (int x = state.playerX - 8, xS = 0; x < state.playerX + 8; x++, xS++) {
for (int y = state.playerY - 8, yS = 0; y < state.playerY + 8; y++, yS++) {
screen[xS][yS] = world[x][y];
}
}
for (int x = 0; x < screen.length; x++) {
for (int y = 0; y < screen.length; y++) {
Block current = screen[x][y];
g.drawImage(current.getType().getImage(),
x * blockSize, // blockSize is the pixel dimension of
y * blockSize,
null
);
}
}
}
If this helps, then great! I'm glad I was able to help. If not, or if some ideas are still unclear, then I would consider perhaps running through a tutorial or book that walks you through making a game. Don't forget to learn the platform you're coding on during such a process.

Related

Rotating a String or char clockwise by 90 degrees

Folks, I'm having a really hard time with rotating a Shape clockwise by 90 degrees. I'm having troubles with completing it. If there is a shape:
.t.
ttt
The method rotateBy90() rotates the above shape by 90 degrees clockwise, so it'll be the following output:
t.
tt
t.
THe shapes are of a String type.
Here what I have and Im pretty sure Im completely doing it wrong. The method can be done by using either char[][], or char[], or String[], or String[][]. Another issue is that rotateBy90() is a void method. COuld smb please help me with this rotation algorithm? Thanks in advance!
import java.util.*;
public class CreateShape {
private int height;
private int width;
private char dc;
private Rotation initialPos;
private Rotation nextPos;
private char[][] shape = new char[height][width];
String[] shapeLayout = new String[height];
String[] rotatedArray;
public CreateShape(int height, int width, char dc)
{
this.height = height;
this.width = width;
this.dc = dc;
initialPos = Rotation.CW0;
}
public void rotateBy90()
{
nextPos = initialPos.next();
String newLayout = "";
int count = 0;
String[] newMatrixColumns= shape.split("\n");
while (count < shape.split("\n")[0].length()) {
for (int i = newMatrixColumns.length - 1; i > -1; i--) {
newLayout += newMatrixColumns[i].charAt(count);
}
newLayout = newLayout + "\n";
count++;
}
}
I don't quite get your approach and where your difficulties lie. I also don't get why you have so many unused fields. You may want to set your width and height fields final, as they shouldn't really change in this case.
Personally I think by far the easiest is to use a char[][]. All you have to do then is iterate your initial char[][] and place the element at the appropriate place in your new char[][]. So in your method you'd have something like
public void rotateBy90()
{
// bla bla
char[][] tempShape = new char[width][height];
for(int j = 0; j < width; j++) {
for(int i = 0; i < height; i++) {
tempShape[...][...] = myShape[i][j]; //I'll leave this as exercise
}
}
myShape = tempShape;
}
Word of caution: be careful with strings. Many string operations involve creating other strings (split, substring, concatenation etc). If you do them in a long loop, you may run out of memory fairly quickly.

Java 2D array - How to assign an array as a value?

Background
I am doing a game project for my java class and we are using a grid system for the playing area. 50 wide by 25 tall. The squares are dynamically sized based on your monitor size and it involves a bit of math. I removed that from my example below so it is easier to look at.
What I currently decided to do is store the grid squares in a nice and simple 2D array so we can access and update the playing area as needed. Here is that code:
// Updates when told to, saves new values
public static void GridList() {
// Record which grid squares are open (0) or blocked (1)
// X = Row and Y = Column
for (int x = 0; x < 50; x++ ) {
for ( int y = 0; y < 25; y++ ) {
gridList[x][y] = 0;
}
}
}
Our Problem
Now the trouble starts when I move on to saving order pairs (x,y) that represent the middle of these grid squares. For example, based on all the math we did to figure out your monitor size, we made a grid 50 wide by 25 tall and now need to save the (x,y) coordinates of the middle of those squares. This is so our AI knows where to move enemies; point by point as long as it is open.
This is what I have so far that saves X coordinates and Y coordinates in their own arrays:
public static void NodeList() {
for (int x = 0; x < 50; x++ ) {
for ( int y = 0; y < 25; y++ ) {
nodeListX[x][y] = *Removed all the math.*;
nodeListY[x][y] = *Removed all the math.*;
}
}
}
What We Are Aiming To Have
What I would really like to do is save an array for every grid square like this:
public static void NodeList() {
for (int x = 0; x < 50; x++ ) {
for ( int y = 0; y < 25; y++ ) {
nodeList[x][y] = *array{x,y}*;
}
}
}
Is this possible in Java? I can't figure this out. I saw things mentioned about lists but we have not covered that yet so I am at a loss.
Java doesn't really have a way to store a pair of numbers. But you could make a coordinate class like this:
`public class Coordinate
int x;
int y;
public Coordinate(x,y)
{
this.x=x;
this.y=y;
}
public int getX()
{
return x;
}
public int gety()
{
return y;
}
`
Then you can just create an array of coordinates.
Honestly, I don't see the problem with your or fdsa's solution. But if you're looking for another approach, you can always use a 3-dimensional array, with the third dimension containing 2 elements for X and Y:
public static void NodeList() {
for (int x = 0; x < 50; x++ ) {
for ( int y = 0; y < 25; y++ ) {
int xPos = *Removed all the math.*;
int yPos = *Removed all the math.*;
nodeList[x][y] = new int[] {xPos, yPos};
}
}
}
Just make sure to declare nodeList as int[][][].

Slow map in java

I'm making a game in java, is a rpg, however, only with the map the game is slow.
The map is made ​​in TiledMap Editor, therefore, an XML that is read and loaded into an ArrayList. My PC is a dual-core 3.0, 4GB RAM, 1GB Video.
The do the rendering is done as follows:
//method of tileset class
public void loadTileset(){
positions = new int[1 + tilesX * tilesY][2];
int yy = 0;
int xx = 0;
int index = 0;
// save the initial x and y point of each tile in an array named positions
// positions[tileNumber] [0] - X position
// positions[tileNumber] [1] - Y position
for(int i = 1 ; i < positions.length; i++){
if(index == tilesX ){
yy += tileHeight;
xx = 0;
index = 0;
}
positions[i][0] = xx;
positions[i][1] = yy;
xx += tileWidth;
index++;
}
}
//method of map class
public void draw(Graphics2D screen){
//x and y position of each tile on the screen
int x = 0; int y = 0;
for(int j = 0; j < 20 ; j++){
for(int i = initialTile ; i < initialTile + quantTiles ; i++){
int tile = map[j][i];
if(tile != 0){
screen.drawImage(tileSet.getTileImage().getSubimage(tileSet.getTileX(tile), tileSet.getTileY(tile),tileSet.getTileWidth(), tileSet.getTileHeight()),x,y,null);
}
x += tileSet.getTileWidth();
}
x = 0;
y += tileSet.getTileHeight();
}
}
Am I doing something wrong?
Note: I'm new to the forum and to make matters worse I do not understand very much English, so excuse any mistake.
First of all, you should not create the subimages for the tiles during each call. Strictly speaking, you should not call getSubimage at all for images that you want to paint: It will make the image "unmanaged", and this can degrade rendering performance by an order of magnitude. You should only call getSubimage for images that you do not want to render - for example, when you are initially creating individual images for the tiles.
You obviously already have a TileSet class. You could add a bit of functionality to this class so that you can directly access images for the tiles.
Your current code looks like this:
screen.drawImage(
tileSet.getTileImage().getSubimage(
tileSet.getTileX(tile),
tileSet.getTileY(tile),
tileSet.getTileWidth(),
tileSet.getTileHeight()),
x,y,null);
You could change it to look like this:
screen.drawImage(tileSet.getTileImage(tile), x,y,null);
The getTileImage(int tile) method suggested here could then obtain tiles that have been stored internally.
I'll sketch a few lines of code from the tip of my head, you'll probably be able to transfer this into your TileSet class:
class TileSet
{
private Map<Integer, BufferedImage> tileImages;
TileSet()
{
....
prepareTileImages();
}
private void prepareTileImages()
{
tileImages = new HashMap<Integer, BufferedImage>();
for (int tile : allPossibleTileValuesThatMayBeInTheMap)
{
// These are the tiles that you originally rendered
// in your "draw"-Method
BufferedImage image =
getTileImage().getSubimage(
getTileX(tile),
getTileY(tile),
getTileWidth(),
getTileHeight());
// Create a new, managed copy of the image,
// and store it in the map
BufferedImage managedImage = convertToARGB(image);
tileImages.put(tile, managedImage);
}
}
private static BufferedImage convertToARGB(BufferedImage image)
{
BufferedImage newImage = new BufferedImage(
image.getWidth(), image.getHeight(),
BufferedImage.TYPE_INT_ARGB);
Graphics2D g = newImage.createGraphics();
g.drawImage(image, 0, 0, null);
g.dispose();
return newImage;
}
// This is the new method: For a given "tile" value
// that you found at map[x][y], this returns the
// appropriate tile:
public BufferedImage getTileImage(int tile)
{
return tileImages.get(tile);
}
}

2d java minecraft game colliding with blocks

I'm making a 2D Minecraft-like platformer game which includes a player moving across blocks, but the player/block collision isn't working.
pretty much what im trying to do is collide with blocks that are 20 y 20 I have an array list of
blocks :
public blocks block[][] = new blocks[50][50]
how do I collide with each individual block.
Please see the Player class below. If you would like to see the Block class, please let me know in the comments.
public class Player
{
public int x = 200;
public int y = 10;
public static int dir = 1;
public static int fallingSpeed = 4;
public static boolean col = false;
public Image img, img1;
public void tick()
{
collide();
if(col == false)
{
y += fallingspeed;
Comp.sy += fallingspeed;
}
}
public void collide()
{
if (x >= 0 && y >= 0 && x >= Comp.level.block.length
&& y >= Comp.level.block[0].length - 21)
col = true;
else
col = false;
}
public void render(Graphics g)
{
if(dir == 1)
{
ImageIcon i2 = new ImageIcon("res/player2.png");
img = i2.getImage();
g.drawImage(img, x - Comp.sx, y - Comp.sy, null);
}
else if (dir == 2)
{
ImageIcon i2 = new ImageIcon("res/player1.png");
img = i2.getImage();
g.drawImage(img, x - Comp.sx, y - Comp.sy, null);
}
}
}
Yes, we kinda need the Block class to make an example.
The basic idea is that you use a for loop to iterate thought every block and check if the player collides with it. You can use the Rectangle2D and Area classes to help detect the actual collision, by casting a Rectange2D object to a Area Object and using area1.intersects(area2).

How to flip an image horizontally with an ImageJ-Plugin?

I want to develop a Java-Plugin for ImageJ that flips an image horizontally.
But my code flips only half of the picture. Maybe, there is something wrong with the construction or the output of the image copy?
public class flipHorizontal implements PlugInFilter {
public int setup (String arg, ImagePlus imp)
{
return DOES_ALL;
}
public void run (ImageProcessor ip)
{
int height=ip.getHeight();
int width=ip.getWidth();
ImageProcessor copy = ip;
for (int x=0; x<width; x++) {
for (int y=0; y<height; y++) {
int p=ip.getPixel(width-x-1,y);
copy.putPixel(x,y,p);
}
}
}
}
Your logic is wrong. What you get is normal: you're not processing half of your image but flipping horizontally once half of your image and twice the other half (if I'm not mistaken).
Anyway, if you want to flip horizontally by manipulating pixels yourself directly, as in your code sample, then instead of going to width, you need to go to half the width (width/2).
You then need to actually invert the two pixels from "left" and "right"
Here's an horizontal flip that works:
for (int x = 0; x < w / 2; x++) {
for (int y = 0; y < h; y++) {
final int l = tmp.getRGB( w - (x + 1), y);
final int r = tmp.getRGB( x, y);
tmp.setRGB( x, y, l );
tmp.setRGB( w - (x + 1), y, r );
}
}
There may be "off-by-one" errors in the code above but you should get the idea.
TacticalCoder is correct that you should only be iterating to half way across the image, and you need to save the value from the other side before overwriting it.
There are two additional points that might be worth making, however - one is the the ImageProcessor class already has a method called flipHorizontal, so you can simplify your code to:
public class flipHorizontal implements PlugInFilter {
public int setup (String arg, ImagePlus imp) {
return DOES_ALL;
}
public void run (ImageProcessor ip) {
ip.flipHorizontal();
}
}
The other point that would be worth making is that it seems that you misunderstand what this line means:
ImageProcessor copy = ip;
That's just creating another reference to the same object as ip, so:
copy.putPixel(x,y,p);
... and:
ip.putPixel(x,y,p);
... have exactly the same effect. If you want to create a new ImageProcessor representing the same pixel data, you could do:
ImageProcessor copy = ip.duplicate();
However, that's not necessary in this case.

Categories