So i am trying to create a game that is top down 2d and using a pixel tiled map style format. They way i would like to do it is have say 4 different tiles, different shades of green and brown for grass.
I would like to generate these 4 tiles randomly around the 1920*1080 pixel area to give a semi realistic effect.
So something like this:
But with randomly generated different tiles in there.
What would be the best way of doing this?
Just use a for loop and place a random tile at each location
for(int i = 0; i < numTilesY; i++)
{
for(int j = 0; j < numTilesX; j++)
{
placeRandomTile(i, j);
}
}
placeRandomTile would just use java's Random class to choose a random number, and depending on the number will place the corresponding tile. For example, if randomNumber == 2, place grass tile.
If you want the tiles to form a realistic looking world similiar to Minecraft, you should use some sort of a noise function like Perlin Noise. It will be random in that every time you generate a new world, the world will be different.
EDIT:
int[][] map= new int[32][32]; //create 32x32 tile map
public void placeRandomTile(int xIndex, int yIndex)
{
Random rand = new Random();
int value = rand.nextInt(5);//get value between 0 and 5
int tile = 0;
if(value == 0)
{
tile = 1; //1 corresponds to GRASS tile
}
if(value == 1)
{
tile = 2; //WATER tile
}
this.map[xIndex][yIndex] = tile;
}
Now that you have your map data stored in a 2D array, you just need to loop through the data and draw each tile accordingly at the proper locations.
In your drawing method, you would just draw each tile from the map like so:
public void draw(float x, float y, Graphics g)
{
for(int i = 0; i < map.length; i++)
{
for(int j = 0; j < map[i].length; j++)
{
int tileType = map[i][j]; //get tile type
if(tileType == Tile.grass.id)
{
Tile.grass.draw(x + (j * Tile.WIDTH), y + (i * Tile.HEIGHT));//draw grass
}
}
}
}
Since you are using libgdx, you will need to look into these classes: TiledMap, TiledMapTileLayer, Screen, Texture, and OrthogonalTiledMapRenderer. You basically create a TiledMap and draw Textures using a TiledMapRenderer.
You can view a sample game I have on Github from a while ago that does what you want. It's here. Look at Dungeon class and screens/GameScreen class
Related
I'm trying to make a grid of squares that change their fill (from black to white and vice-versa) when clicked. I'm able to turn the entire grid on or off currently, but I'm unable to figure out how to specify which particular square should be toggled when the mouse clicks within its borders. I've created buttons using mouseX and mouseY coordinates before, but they were for specific objects that I could adjust manually. I can't figure out how to do this using for loops and arrays.
I've been told to create a boolean array and pass the value of that array to the grid array, but again, I don't know how to specify which part of the array it needs to go to. For example, how do I change the fill value of square [6][3] upon mousePressed?
Here is my code so far:
int size = 100;
int cols = 8;
int rows = 5;
boolean light = false;
int a;
int b;
void setup() {
size (800, 600);
background (0);
}
void draw() {
}
void mousePressed() {
light = !light;
int[][] box = new int[cols][rows];
for (int i = 0; i < cols; i++) {
for (int j = 0; j < rows; j++) {
box[i][j] = i;
int a = i*100;
int b = j*100;
if (light == true) {
fill(255);
} else {
fill(0);
}
rect(a, b, 100, 100);
println(i, j);
}
}
}
First of all, you are currently recreating the entire board whenever the mouse is pressed. You must retain that info between mouse clicks, so make box a global array up there with the others. Further, it's sufficient to make it a boolean array if all you care about is the on/off state of each square:
boolean[][] isSquareLight = new boolean[cols][rows];
Instead of
if (light == true) {
you should then just check
if (isSquareLight[i][j] == true) {
(note that the == true is redundant).
Now, you've already written code that finds the coordinates for each box: You're passing it to rect!
rect(a, b, 100, 100);
All that is left to do is check whether the mouse is inside this rect, i.e. whether mouseX is between a and a+100 (and similar for mouseY) - if that's the case, then the user clicked in the box given by the current (i, j), so you can just negate isSquareLight[i][j] (before checking it like above) and it will work.
There are ways to calculate this without looping through the entire grid every time, but maybe the above helps you find the path yourself instead of just getting the code made for you.
PS: The int a; int b; at the top does nothing and can be removed. You are using the local variables a and b in your function, which is correct.
So, as part of my college coursework we are working in teams to develop simplistic games in Greenfoot, partly to develop on teamwork skills, and partly for actual programming.
Our game features a perlin/simplex generated map to render tessellated terrain tiles for our gameplay, however I need a way to reference the tiles individually, in order for a given tile to interact with it's neighbours.
Is there an easy way I can instantiate a worldTile object by passing a string such as their x/y coordinates (eg ter_12_142)? Or is there a simpler method to go about this?
Here's my code for placing tiles in the world;
private void tilePlacement() {
for (int y = 1; y < rows - 1; y++) {
for (int x = 2; x < cols - (cols / 4); x++) {
int w = (getColor(noise[x][y][0]));
int isAForest = (isForest(noise[x][y][1]));
addObject(new worldTile(w, isAForest), x * scl, y * scl);
}
}
}
The problem I'm having is with my render loop. My application is a series of 'Tile' objects each with an x and y coordinate and image. When the program starts it creates a 10x10 grid of these tiles on screen. However, not all the squares can be seen at the same time, so you can use the arrow keys to pan around them. When the key is pressed it uses a for loop to cycle through all the currently rendered tile (stored in an ArrayList) and shifts them all 16 in the appropriate direction. The problem is some of the tiles flicker. I can see when scrolling that one half of the screen doesn't move in time to be rendered in the right spot, making a black gap between that and the other half of the tiles. how do I ensure that all tiles are moved before rendering?
render function from my Core class
public static void render()
{
while(true)
{
Graphics g = buffer.getDrawGraphics();
try
{
g.setColor(Color.black);
g.fillRect(0, 0, 1280, 720);
if(renderQueue != null)
{
for(int i = 0; i<renderQueue.size(); i++)
{
Tile t = renderQueue.get(i);
g.drawImage(t.getImage(), t.getX(), t.getY(), null);
}
}
if(!buffer.contentsLost())
{
buffer.show();
}
}
finally
{
if(g != null)
{
g.dispose();
}
}
}
}
And here's the movement update function from the Input class
public void keyPressed(KeyEvent ke)
{
int e = ke.getKeyCode();
switch(e)
{
case 38://up
if(scrollY > 0)
{
scrollY -= 16;
for(int i = 0; i<Core.renderQueue.size(); i++)
{
Core.renderQueue.get(i).incrementY(16);
}
}
break;
case 40://down
if(scrollY < 560)
{
scrollY += 16;
for(int i = 0; i<Core.renderQueue.size(); i++)
{
Core.renderQueue.get(i).incrementY(-16);
}
}
break;
case 37://right
if(scrollX < 0)
{
scrollX += 16;
for(int i = 0; i<Core.renderQueue.size(); i++)
{
Core.renderQueue.get(i).incrementX(16);
}
}
break;
case 39://left
if(scrollX > 0)
{
scrollX -= 16;
for(int i = 0; i<Core.renderQueue.size(); i++)
{
Core.renderQueue.get(i).incrementX(-16);
}
}
break;
}
Thanks in advance!
It sounds like the tiles are being rendered while the coordinates for some of the tiles still have to be changed by Input.keyPressed. You could fix that by directly using scrollX and scrollY to draw the tile images in Core.render, instead of changing the coordinates for each of the tiles. If you copy the scroll values to two local variables at the begin of the while loop in render, the same values will be used for each tile.
Another option is to create a new list with tiles that have the modified coordinates (you could use the images from the current list). When the new list is complete, you could set a flag like newRenderQueue which will be picked up in render. When a new iteration of the while loop in render starts, you can replace the render queue with the new list and reset the flag.
P.S. Welcome to Stack Overflow! As Andrew Thompson already mentioned, it's very helpful to provide a complete example of your problem. This way people can quickly investigate the issue and provide (hopefully useful) advice... ;-)
Apologies if the question isn't clear but I couldn't think of another way to phrase it.
This is for a class assignment which I've been working at in BlueJ all weekend. I have to change a method (bounce) to let a user choose how many balls should be bouncing.
Other requirements are: the balls should be of different sizes and should be displayed in a row along the top of the screen BEFORE they bounce.
In order to do this I have to use a collection (ArrayList, HashMap, HashSet). So far I've used HashMap and have been able to have the user choose a number of "balls" of random sizes which place themselves in random positions in the top half of the screen.
When I try to have each ball bounce from its position at the top of the screen, ending at the right hand side I come up stuck. I can make the code draw one ball, bounce it then draw another ball, bounce it etc until the user selected number of balls has looped round.
There are two other classes, one to draw the canvas and one to draw the balls and move them. Both of which I'm not allowed to touch.
What I'm doing the wrong way is probably right in front of me but i've been staring at this code so long I thought I'd ask.
My current version of the code looks like this:
import java.awt.Color;
import java.util.HashMap;
import java.util.Random;
import java.util.Iterator;
public class BallDemo
{
private Canvas myCanvas;
private HashMap<Integer, BouncingBall> ballMap;
private int n;
private int j;
private BouncingBall ball;
/**
* Create a BallDemo object. Creates a fresh canvas and makes it visible.
*/
public BallDemo()
{
myCanvas = new Canvas("Ball Demo", 600, 500);
}
And the method I have to edit to bounce the balls:
public void bounce(int numBalls)
{
ballMap = new HashMap<Integer, BouncingBall>();
int ground = 400; // position of the ground line
Random randomD1 = new Random();
Random xpos = new Random();
myCanvas.setVisible(true);
// draw the ground
myCanvas.drawLine(50, ground, 550, ground);
// add balls to HashMap
for(n = 0; n < numBalls; n++) {
ballMap.put(numBalls, (ball = new BouncingBall(xpos.nextInt(300), 50, randomD1.nextInt(200), Color.BLUE, ground, myCanvas)));
//
for(j= 0; j < ballMap.size(); j++) {
ball.draw();
boolean finished = false;
while(!finished) {
myCanvas.wait(50); // small delay
ball.move(); // bounce the ball
// stop once ball has travelled a certain distance on x axis
if(ball.getXPosition() >= 550) {
finished = true;
}
}
}
}
}
}
Am I even on the right lines using a HashMap? The combination of keys, values seemed the best way to go. I think I need to somehow iterate through the items placed in the collection to make them bounce using the move() method. But first I need the balls to stay in a row at the top of the screen, no matter how many the user defines.
I'm new to programming and I'm just coming up stumped.
Thanks for any help!
#16dots is partly right, except ballMap.put(numBalls, ball); will over write the same value in the hash map each time, as numBalls does not change...
The key should be unique.
It should read...
for (int n; n < numBalls; n++) {
BouncingBall ball = new BouncingBall(xpos.nextInt(300), 50,
randomD1.
nextInt(200), Color.BLUE, ground, myCanvas);
ballMap.put(n, ball);
}
boolean finished = false;
while (!finished) {
finished = true;
for (int j = 0; j < ballMap.size(); j++) {
BouncingBall selectedBall = ballMap.get(j);
selectedBall.draw();
// Only move the ball if it hasn't finished...
if (selectedBall.getXPosition() < 550) {
selectedBall.move(); // bounce the ball
// stop once ball has travelled a certain distance on x axis
if (selectedBall.getXPosition() < 550) {
finished = false;
}
}
}
myCanvas.wait(50); // small delay
}
I have a game, and recently decided to switch from TilED (a tile map editor), to doing it manually. I've been searching all over google for some help, but to no avail. Here's my code that renders my background using sky tiles:
for (int x = 0; x < 16; x++) {
for (int y = 0; y < 16; y++) {
map[x][y] = AIR;
if(map[x][y] == AIR) {
air.draw(x * tilesize, y * tilesize);
}
}
}
This just creates a new 16 * 16 map and fills it with sky tiles. My question is, how do I specify levels for other tiles to go? So like grass tiles go on layer 10, dirt goes through 9 - 6, and stone fills the rest?
To do it on each level you would just do another for loop:
for(int x = 0; x < 16; x++) {
map[x][10] = GRASS;
}
And that is how you would make it work. Hope it helps!
you can look at the source of "AndEngine", an open source android game engine which reads TMX tiles created from Tiled:
there are lots of classes, but here is a start:
http://code.google.com/p/andengine/source/browse/src/org/anddev/andengine/entity/layer/tiled/tmx/TMXTiledMap.java
you can try to create a map with tiled then step though the tmx loader as is parses the map.