Libgdx Game
For some reason, my SpriteBatch is not able to render both of the 2d int arrays I use to build my dungeon(in class Dungeon1).
I have created a random dungeon building algorithm which inputs into my 2d integer arrays. I'm trying to create a seperate Dungeon class with its own textures that implements the dungeon-building algorithm from the first class, but for some reason the map will not render.
In my main Game class I set my screen:
public class NanoRealms extends Game {
#Override
public void create() {
this.setScreen(new Dungeon1(this));
}
}
Then I use this class to build the dungeon:
public class Dungeon {
public static final int tileSIZE = 64;
private Random rand = new Random();
static int mapSize = 128;
static int[][] bg = new int[mapSize][mapSize];
static int[][] fg = new int[mapSize][mapSize];
private int roomCount = rand.nextInt(20) + 10;
private int minSize = 10;
private int maxSize = 20;
private ArrayList<Room> rooms = new ArrayList<Room>();
private Room[] room = new Room[roomCount];
public Dungeon() {
makeRooms();
squashRooms();
makeCorridors();
fillRoom();
Autotile at = new Autotile(mapSize, bg, fg);
}
...Dungeon Building Algorithm Goes HERE...
}
However, when I try to render the inputs I put into my 2 2d-Arrays, it just wont work.
You can see this in my render method of this class:
public class Dungeon1 implements Screen {
public Texture tiles;
public TextureRegion floor, wall, wallLeft, wallRight, tlCorn, trCorn, blCorn, brCorn, c1, c2, c3, c4;
float wh = Gdx.graphics.getWidth();
float ht = Gdx.graphics.getHeight();
private SpriteBatch batch;
private OrthographicCamera camera;
private int[][] fg = Dungeon.fg;
private int[][] bg = Dungeon.bg;
public Dungeon1(NanoRealms game) {
Dungeon d = new Dungeon();
tiles = new Texture(Gdx.files.internal("Map/tiles.png"));
floor = new TextureRegion(tiles, 2 * 64, 0, Dungeon.tileSIZE, Dungeon.tileSIZE);
wall = new TextureRegion(tiles, 64, 64, Dungeon.tileSIZE, Dungeon.tileSIZE);
wallLeft = new TextureRegion(tiles, 0, 2 * 64, Dungeon.tileSIZE, Dungeon.tileSIZE);
wallRight = new TextureRegion(tiles, 2 * 64, 2 * 64, Dungeon.tileSIZE, Dungeon.tileSIZE);
tlCorn = new TextureRegion(tiles, 0, 64, Dungeon.tileSIZE, Dungeon.tileSIZE);
trCorn = new TextureRegion(tiles, 2 * 64, 64, Dungeon.tileSIZE, Dungeon.tileSIZE);
blCorn = new TextureRegion(tiles, 0, 3 * 64, Dungeon.tileSIZE, Dungeon.tileSIZE);
brCorn = new TextureRegion(tiles, 2 * 64, 3 * 64, Dungeon.tileSIZE, Dungeon.tileSIZE);
c1 = new TextureRegion(tiles, 3 * 64, 64, Dungeon.tileSIZE, Dungeon.tileSIZE);
c2 = new TextureRegion(tiles, 4 * 64, 64, Dungeon.tileSIZE, Dungeon.tileSIZE);
c3 = new TextureRegion(tiles, 3 * 64, 2 * 64, Dungeon.tileSIZE, Dungeon.tileSIZE);
c4 = new TextureRegion(tiles, 4 * 64, 2 * 64, Dungeon.tileSIZE, Dungeon.tileSIZE);
batch = new SpriteBatch();
camera = new OrthographicCamera(30, 30 * (Gdx.graphics.getHeight()/Gdx.graphics.getWidth()));
camera.position.set(3000, 3000, 0);
camera.zoom = 300;
}
public void render(float delta) {
cameraInput();
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL30.GL_COLOR_BUFFER_BIT);
////
batch.begin();
batch.setProjectionMatrix(camera.combined);
batch.enableBlending();
for (int x = 0; x < bg.length; x++) {
float w = x * 64;
for (int y = 0; y < bg[x].length; y++) {
float h = y * 64;
if (bg[x][y] == 1) {
batch.draw(floor, w, h);
}
}
}
for (int x2 = 0; x2 < fg.length; x2++) {
float w2 = x2 * 64;
for (int y2 = 0; y2 < fg[x2].length; y2++) {
float h2 = y2 * 64;
if (fg[x2][y2] == 2) {
batch.draw(wall, w2, h2);
} else if (fg[x2][y2] == 3) {
batch.draw(wallLeft, w2, h2);
} else if (fg[x2][y2] == 4) {
batch.draw(wallRight, w2, h2);
} else if (fg[x2][y2] == 5) {
batch.draw(tlCorn, w2, h2);
} else if (fg[x2][y2] == 6) {
batch.draw(trCorn, w2, h2);
} else if (fg[x2][y2] == 7) {
batch.draw(blCorn, w2, h2);
} else if (fg[x2][y2] == 8) {
batch.draw(brCorn, w2, h2);
} else if (fg[x2][y2] == 9) {
batch.draw(c1, w2, h2);
} else if (fg[x2][y2] == 10) {
batch.draw(c2, w2, h2);
} else if (fg[x2][y2] == 11) {
batch.draw(c3, w2, h2);
} else if (fg[x2][y2] == 12) {
batch.draw(c4, w2, h2);
}
}
}
batch.end();
////
}
public void cameraInput() {
if (Gdx.input.isKeyPressed(Keys.Q))
camera.zoom += 0.5;
if (Gdx.input.isKeyPressed(Keys.E))
camera.zoom -= 0.5;
if (Gdx.input.isKeyPressed(Keys.A))
camera.translate(-10, 0, 0);
if (Gdx.input.isKeyPressed(Keys.D))
camera.translate(10, 0, 0);
if (Gdx.input.isKeyPressed(Keys.S))
camera.translate(0, -10, 0);
if (Gdx.input.isKeyPressed(Keys.W))
camera.translate(0, 10, 0);
}
}
When I put the render method and Textures from Dungeon1 into Dungeon, everything works fine. However, I want to create different styled dungeons with different textures without having to rewrite my dungeon algorithm every time.
You didn't say what actually went wrong, so I'm just guessing.
The problem that jumps out at me is that Dungeon1 extends Dungeon, but does not call the super constructor, so your methods makeRooms(), squashRooms(), etc are never called. You do create a Dungeon object and then do nothing with it, so it's thrown away.
So at the top of your Dungeon1 constructor, replace
Dungeon d = new Dungeon();
with
super();
As a side note, it seems odd that you have the static arrays bg and fg in Dungeon, and then your subclass hides them with arrays that have the same name, but then directs those non-static arrays to point at the static arrays from Dungeon. This is convoluted, and a bug waiting to happen. These do not look like something that should be static, so I think you can remove the static key word from both of them. And the subclass does not need to reference them at all. It's a subclass, so it can access them normally without "re-referencing" them.
Related
I have an issue where I'm unable to see Color Picker.
I'm trying to generate a lot of lines to make patterns to make me feel accomplished. It's a side project.
I'm not the best at coding so I need help. Also you have to minimize the window and open it back up to make it work when you are running it by the way.
*update I've figured out that the color picker is there but just behind all of my lines that I've drawn.
Here is my code.
import controlP5.ColorPicker;
import controlP5.ControlEvent;
import controlP5.ControlP5;
import processing.core.PApplet;
public class main extends PApplet {
ControlP5 cp5;
ColorPicker cp;
boolean guiState;
int col;
public static void main(String[] args) {
PApplet.main("main");
}
void drawLines() {
float lineLength = sqrt(height * height + width * width);
float nsHueStart = random((float) 10);
float nsSatStart = random((float) 10);
float nsRotStart = random((float) 10);
float nsHStart = random((float) 10);
float nsWStart = random((float) 10);
int lineWidthMax = 50;
for (int lineWidth = 1; lineWidth <= lineWidthMax; ++lineWidth) {
strokeWeight((5 * pow(lineWidth, 2)));
nsHueStart += 001;
float nsHue = nsHueStart;
float nsSat = nsSatStart;
float nsH = nsHStart;
float divH;
float divW;
for (float idxH = 0; idxH < height; idxH += divH) {
divH = map(noise(nsH), 0, 1, 80, 200);
float nsRot = nsRotStart;
float nsW = nsWStart;
for (float idxW = 0; idxW < width; idxW += divW) {
divW = map(noise(nsW), 0, 1, 0, 5); // do not use 2D noise
float brushHue = map(noise(nsHue), 0, 1, 0, 720) % 360; // various colors
float brushSat = map(noise(nsSat), 0, 1, 20, 70) / map(lineWidth, 1, lineWidthMax, 1, (float) 1.8);
float brushBri = map(noise(nsSat), 0, 1, 8, 15) / map(lineWidth, 1, lineWidthMax, 1, (float) (lineWidthMax * 2.8));
float brushAlp = 100;
float brushSiz = lineLength;
float brushRot = map(noise(nsRot), 0, 1, -60, 60);
pushMatrix();
translate(idxW, idxH);
canvasRotation(brushRot);
stroke(brushHue, brushSat, brushBri, brushAlp);
line(-brushSiz, 0, brushSiz, 0);
popMatrix();
nsHue += 002;
nsRot += 005;
nsW += 01 + noise(nsH) / 10; // not to be same shape
}
nsSat += 5;
nsH += 8;
}
}
}
public void settings() {
size(2560, 1395);
smooth(8);
}
public void setup() {
noStroke();
cp5 = new ControlP5(this);
cp = cp5.addColorPicker("picker")
.setPosition(60, 100)
.setColorValue(color(0, 128, 255, 128))
;
colorMode(HSB, 360, 100, 100, 100);
blendMode(SCREEN);
cp5.show();
frameRate(60);
}
public void draw() {
background(cp.getColorValue());
fill(0, 80);
rect(50, 90, 275, 80);
translate(0, 0);
drawLines();
}
public void controlEvent(ControlEvent c) {
if (c.isFrom(cp)) {
float r = (c.getArrayValue(0));
float g = (c.getArrayValue(1));
float b = (c.getArrayValue(2));
float a = (c.getArrayValue(3));
col = color(r, g, b, a);
println("event\talpha:"+a+"\tred:"+r+"\tgreen:"+g+"\tblue:"+b+"\tcol"+col);
}
}
void canvasRotation(float degrees) {
rotate(radians(degrees));
}
public void toggleGUI(boolean state) {
if (state) {
cp5.show();
} else {
cp5.hide();
background(200);
}
guiState = state;
}
public void keyPressed() {
if (keyCode == LEFT) toggleGUI(guiState);
switch (key) {
case ('1'):
cp.setArrayValue(new float[]{120, 0, 120, 255});
break;
case ('2'):
cp.setColorValue(color(255, 0, 0, 255));
break;
}
}
}
float x = 100;
float y = 100;
float p = 150;
float l = 10;
float a = 100;
float b = 100;
float n =20;
int value = 255;
int r = 150;
int t = 100;
int s = 100;
int w = 60;
int h = 60;
int z = 11;
int eyeSize = 10;
int pigNose = 30;
int pigBody = 30;
int pigEars = 35;
int pigTail = 20;
int otherpigTail = 200;
int speed = 1;
void setup () {
size (600, 600);
a = width/2.5;
b = height/2;
}
void draw() {
background(184, 233, 249);
//Draw legs
stroke(0);
fill(249, 137, 244);
rect(x+(2*w), y+h/3.5, z, 2*z);
rect(x+(w), y+h/3, z, 2*z);
rect(x+(1.5*w), y+h/3, z, 2*z);
rect(x+(2.5*w), y+h/3.5, z, 2*z);
////draw body
stroke(0);
fill(249, 137, 244);
ellipse(110+x,y-pigBody, p, p-20);
//draw tail
fill(0);
line(185+x, y-pigTail, x+otherpigTail, y-(2*pigTail));
// Draw payer's head
fill(249, 137, 244);
ellipse(x,y-pigNose,t,t);
// Draw player's eyes
fill(0);
ellipse(x-w/3+1,y-h/2,eyeSize,eyeSize);
ellipse(x+w/3-1,y-h/2,eyeSize,eyeSize);
//Draw nose
stroke(0);
fill(198, 105, 194);
ellipse(x, y, pigNose, pigNose);
//draw ears
stroke(0);
fill(198, 105, 194);
ellipse(x-(w/2),y-h, pigEars, pigEars);
ellipse(x+(w/2),y-h, pigEars, pigEars);
//draw obstacles
fill(value);
ellipse(a, b, s, s);
ellipse(300+a, 200+b, s, s);
ellipse(300-a, 400+b, s, s);
ellipse(300-a, 600+b, s, s);
ellipse(300-a, b, s, s);
ellipse(300+a, 800+b, s, s);
}
I need help turning this code into something similar to this:
/*
This is a very rudimentary virtual pet. It can sit,
lie down, and wag it's tail.
*/
class Pet {
int x, y;
int pose;
int WAG = 1, SLEEP = 2, SIT = 3;
float tailWag, wagSpeed;
Pet(int x, int y) {
this.x = x;
this.y = y;
pose = SIT;
}
// adjust pose and stop tail wagging
void sit() {
pose = SIT;
wagSpeed = 0;
tailWag = 0;
}
// adjust pose and start tail wagging
void wag() {
pose = WAG;
wagSpeed = .1;
}
// adjust pose and stop tail wagging
void sleep() {
pose = SLEEP;
wagSpeed = 0;
tailWag = 0;
}
// draw in selected pose
void draw() {
pushMatrix();
translate(x, y);
if (pose == SIT) {
drawSitting();
}
else if (pose == WAG) {
wagTail();
drawSitting();
}
else {
drawLaying();
}
popMatrix();
}
void drawLaying() {
// needs work :-)
ellipse(0, 0, 150, 60);
}
void wagTail() {
float maxTailWag = .5; // controls how much the tail wags back and forth
tailWag = tailWag + wagSpeed;
// reverse wag direction if the wag limit is reached
if (tailWag > maxTailWag || tailWag < -maxTailWag) {
wagSpeed = -wagSpeed;
}
}
// not pretty but gets the idea across
// origin is the center of the torso
void drawSitting() {
// torso
pushMatrix();
rotate(radians(-30));
ellipse(0, 0, 80, 120);
popMatrix();
ellipse(-20, -70, 60, 60); // head
// nose
pushMatrix();
translate(-55, -55);
rotate(radians(-15));
arc(0, 0, 40, 30, radians(20), radians(310), OPEN);
popMatrix();
// eyes
ellipse(-40, -85, 15, 15); // left eye
ellipse(-25, -80, 15, 15); // right eye
//ear
pushMatrix();
translate(15, -50);
rotate(radians(-20));
ellipse(0, 0, 20, 40);
popMatrix();
//tail
pushMatrix();
translate(40, 30);
rotate(radians(45)+tailWag);
arc(0, -35, 30, 60, radians(-220)-tailWag, radians(80), OPEN);
popMatrix();
// back leg
ellipse(0, 60, 50, 20);
// front leg
pushMatrix();
translate(-50, 30);
rotate(radians(15));
ellipse(0, 0, 30, 60);
popMatrix();
}
}
with classes and whatnot so that I can start working on adding in my own animations for the pet. I'm just not sure where to put everything/how to organize it like that using my drawing.
If I were you, I would start with something simpler. For example, here's a program that uses 4 variables to show a ball bouncing around:
float circleX = 50;
float circleY = 50;
float xSpeed = 1;
float ySpeed = 2;
void draw() {
background(200);
circleX += xSpeed;
if (circleX < 0 || circleX > width) {
xSpeed *= -1;
}
circleY += ySpeed;
if (circleY < 0 || circleY > height) {
ySpeed *= -1;
}
ellipse(circleX, circleY, 20, 20);
}
(source: happycoding.io)
From here, we can encapsulate those 4 variables into a class:
class Circle{
float x;
float y;
float xSpeed;
float ySpeed;
Circle(float x, float y, float xSpeed, float ySpeed){
this.x = x;
this.y = y;
this.xSpeed = xSpeed;
this.ySpeed = ySpeed;
}
}
Now that we have a class, we can use an instance of that class to control our ball.
Circle circle = new Circle(50, 50, 1, 2);
void draw() {
background(200);
circle.x += circle.xSpeed;
if (circle.x < 0 || circle.x > width) {
circle.xSpeed *= -1;
}
circle.y += circle.ySpeed;
if (circle.y < 0 || circle.y > height) {
circle.ySpeed *= -1;
}
ellipse(circle.x, circle.y, 20, 20);
}
class Circle{
float x;
float y;
float xSpeed;
float ySpeed;
Circle(float x, float y, float xSpeed, float ySpeed){
this.x = x;
this.y = y;
this.xSpeed = xSpeed;
this.ySpeed = ySpeed;
}
}
Your code would follow a similar pattern: create a class, encapsulate your data by moving your variables inside the class, and then create an instance of that class and call its methods to draw your figure. Start with something simpler, and just create a class that draws a single circle. Get that working first, and then add variables to that class to draw two circles (a head and a body), and keep working in small steps like that until you're drawing your whole figure.
I really suggest trying something out and posting an MCVE if you get stuck. Good luck.
Shameless self-promotion: I've written a tutorial on creating classes in Processing available here.
I have a simple animation play of a circle scale outwards and fade out whenever the applications detects that the hammer object has reached a certain angle. However, as it is currently implemented the animation will only play once. I have attempted using for loops to allow the animation to complete, but this causes the entire application to pause while the code is looped, and other attempts I have made have not worked, so any help at all would be appreciated.
import oscP5.*;
import netP5.*;
OscP5 oscP5;
NetAddress myRemoteLocation;
float bx;
float by;
int boxSizeX = 160;
int boxSizeY = 30;
boolean overBox = true;
boolean locked = false;
float xOffset = 0.0;
float yOffset = 0.0;
float angle = 4.70;
float cooldown;
int alphaVal = 255;
int colorchange = 0;
//for sound effect
float a = 0.0;
float s = 0.0;
BeatBall b1 = new BeatBall(210,425,60, 1);
BeatBall b2 = new BeatBall(570,395,60, 2);
Hammer h = new Hammer(135, -67, boxSizeY+25, boxSizeX-25, 1);
void setup()
{
ellipseMode(CENTER);
size(800, 600);
smooth();
frameRate(120);
bx = width/2.0;
by = height/2.0;
oscP5 = new OscP5(this,12001);
/* myRemoteLocation is a NetAddress. a NetAddress takes 2 parameters,
* an ip address and a port number. myRemoteLocation is used as parameter in
* oscP5.send() when sending osc packets to another computer, device,
* application. usage see below. for testing purposes the listening port
* and the port of the remote location address are the same, hence you will
* send messages back to this sketch.
*/
myRemoteLocation = new NetAddress("127.0.0.1",12000);
}
void draw()
{
background(0);
ellipseMode(CENTER);
float mx = constrain(angle, -2.6075916, -0.5207284);
///////////////////////////
//THIS IS THE ANIMATION //
//////////////////////////
if(locked)
{
a = a + 0.02;
s = cos(a)*10;
pushMatrix();
translate(210,425);
scale(s);
fill(colorchange, 30, 150, alphaVal);
ellipse(0, 0, 50, 50);
alphaVal = alphaVal - 3;
colorchange = colorchange + 3;
popMatrix();
}
pushMatrix();
translate(400, 425);
rotate(mx);
fill(222,223,255);
h.displayHammer();
rect(-25, -15, boxSizeX, boxSizeY);
popMatrix();
pushMatrix();
translate(595, 390);
rotate(radians(58));
fill(122,78,163);
rect(0, 0, 50, 50);
popMatrix();
b1.displayBall();
//b2.displaySquare();
cooldown = cooldown + 0.01;
println(cooldown);
if(mx == -2.6075916)
{
if(cooldown > 0.5)
{
locked = true;
soundEffect();
b1.collide();
cooldown = 0;
}
}
else if(mx == -0.5207284)
{
if(cooldown > 0.5)
{
b1.collide();
cooldown = 0;
}
}
}
void soundEffect()
{
}
void mousePressed()
{
xOffset = mouseX-bx;
yOffset = mouseY-by;
}
void mouseDragged()
{
angle = atan2(mouseY - 400, mouseX - 400);
println(angle);
}
I've been trying to make a 2D Tile-based game but didnt get very far before having some stuff go wrong. The game is fine except for that it is extremely slow and spaces keep appearing between the tiles. I tried putting all of the tile images into one image to load to make it smoother, but it didn't work. I need help with how to optimize my game for better fps.
Most of Display Class
Player p = new Player();
static Map m = new Map();
Hotbar h = new Hotbar();
static Zombie z = new Zombie();
public static void main(String args[]) {
Thread t1 = new Thread(new Display());
t1.start();
Thread t2 = new Thread(z);
t2.start();
Thread t3 = new Thread(m);
t3.start();
}
#SuppressWarnings("static-access")
public void run() {
while (true) {
try {
oldTime = currentTime;
currentTime = System.currentTimeMillis();
elapsedTime = currentTime - oldTime;
fps = (int) ((1000 / 40) - elapsedTime);
Thread.sleep(fps);
} catch (Exception e) {
e.printStackTrace();
}
if (started) {
p.playerMovement();
p.width = getWidth();
p.height = getHeight();
h.width = getWidth();
h.height = getHeight();
if (p.maptiles != null) {
z.maptiles = new Rectangle[p.maptiles.length];
z.maptiles = p.maptiles;
}
} else {
}
repaint();
}
}
Most of Map Class
BufferedImage backLayer;
BufferedImage backLayer2;
#SuppressWarnings("static-access")
public void createBack() {
backLayer = new BufferedImage(mapwidth * 32, mapheight * 32, BufferedImage.TYPE_INT_ARGB);
Graphics g = backLayer.getGraphics();
Graphics2D gd = (Graphics2D) g;
Color daycolor = new Color(0, 150, 255, 255);
Color nightcolor = new Color(0, 50, 100, Math.abs(time / daylength - 510 / 2));
Color backtilecolor = new Color(10, 10, 20, Math.abs(time / daylength - 510 / 4));
g.setColor(daycolor);
g.fillRect(0, 0, p.width, p.height);
g.setColor(nightcolor);
g.fillRect(0, 0, p.width, p.height);
time++;
if (time > 510 * daylength)
time = 0;
if (time < 100 * daylength || time > 410 * daylength) {
z.SpawnZombie();
} else {
}
g.setColor(backtilecolor);
int i = 0;
for (int x = 0; x < mapwidth; x++) {
for (int y = 0; y < mapheight; y++) {
if (mapdatasky[i] == 0) {
p.mapsky[i] = new Rectangle(x * 32 - p.playerX, y * 32 - p.playerY, 32, 32);
}
if (mapdatasky[i] >= 1) {
g.drawImage(tiles[mapdatasky[i]], x * 32 - p.playerX, y * 32 - p.playerY, 32, 32, null);
mapsky[i] = new Rectangle(x * 32 - p.playerX, y * 32 - p.playerY, 32, 32);
p.mapsky[i] = new Rectangle(x * 32 - p.playerX, y * 32 - p.playerY, 32, 32);
gd.fill(mapsky[i]);
}
i++;
}
}
backLayer2 = backLayer;
}
BufferedImage middleLayer;
BufferedImage middleLayer2;
#SuppressWarnings("static-access")
public void createMiddle() {
middleLayer = new BufferedImage(mapwidth * 32, mapheight * 32, BufferedImage.TYPE_INT_ARGB);
Graphics g = middleLayer.getGraphics();
Color fronttilecolor = new Color(20, 20, 40, Math.abs(time / daylength - 510 / 4));
int i = 0;
for (int x = 0; x < mapwidth; x++) {
for (int y = 0; y < mapheight; y++) {
if (mapdata[i] == -1) {
spawnX = x * 32 - p.width;
spawnY = y * 32 - p.height;
p.spawnX = spawnX;
p.spawnY = spawnY;
}
if (mapdata[i] == 0) {
p.mapsky[i] = new Rectangle(x * 32 - p.playerX, y * 32 - p.playerY, 32, 32);
}
if (mapdata[i] > 0) {
g.drawImage(tiles[mapdata[i]], x * 32 - p.playerX, y * 32 - p.playerY, 32, 32, null);
maptiles[i] = new Rectangle(x * 32 - p.playerX, y * 32 - p.playerY, 32, 32);
p.maptiles[i] = new Rectangle(x * 32 - p.playerX, y * 32 - p.playerY, 32, 32);
}
if (!p.breaking) {
tileid = -1;
}
if (tileid == i) {
g.setColor(new Color(100, 0, 0, 100));
g.fillRect(x * 32 - p.playerX + 16 - timer / (breaktime / 16), y * 32 - p.playerY + 16 - timer / (breaktime / 16), (timer / (breaktime / 16)) * 2, (timer / (breaktime / 16)) * 2);
}
i++;
}
}
g.setColor(fronttilecolor);
g.fillRect(0, 0, p.width, p.height);
middleLayer2 = middleLayer;
}
BufferedImage both;
BufferedImage both2;
public void mergeLayers() {
both = new BufferedImage(mapwidth * 32, mapheight * 32, BufferedImage.TYPE_INT_ARGB);
Graphics g = both.getGraphics();
g.drawImage(backLayer2, 0, 0, mapwidth * 32, mapheight * 32, null);
g.drawImage(middleLayer2, 0, 0, mapwidth * 32, mapheight * 32, null);
both2 = both;
}
public void renderMap(Graphics g) {
g.drawImage(both2, 0, 0, mapwidth * 32, mapheight * 32, null);
if (placetimer > 0)
placetimer--;
}
#Override
public void run() {
while (true) {
try {
oldTime = currentTime;
currentTime = System.currentTimeMillis();
elapsedTime = currentTime - oldTime;
fps = (int) ((1000 / 100) - elapsedTime);
Thread.sleep(fps);
if (!mapset) {
setMap();
mapset = true;
}
createBack();
createMiddle();
mergeLayers();
} catch(Exception e) {
e.printStackTrace();
}
}
}
Here is a picture of the rendering errors between tiles
Game Screenshot:
I agree that a review might be appropriate here.
But general hints: If you added this "merging" (createBack/createMiddle/mergeLayers) for performance reasons: Don't do it! There you are painting ALL tiles (and possibly also some that will not be visible anyhow, that could be clipped away when they are drawn directly with g.drawImage). Painting many small images into a large image, and then painting the large image on the screen, can hardly be faster than directly painting the small images on the screen in the first place....
If you added this "merging" to resolve the "stripes" that are appearing: Don't do it! The stripes come from the coordinates being changed from a different Thread than the one which is painting the images. You can avoid this by changing the way of how you compute the tiles and their coordinates. The code is slightly too ... "complex" to point it out, so I'll use some pseudocode here:
void paintTiles(Graphics g)
{
for (Tile tile : allTiles)
{
g.drawImage(tile, player.x, player.y, null);
}
}
The problem here is that while the painting thread is iterating over all tiles, the other thread may change the player coordinates. For example, some tiles may be painted with player.x=10 and player.y=20, then the other thread changes the player coordinates, and thus the remaining tiles are painted with player.x=15 and player.y=25 - and you'll notice this as a "stripe" appearing between the tiles.
In the best case, this can be resolved rather easily:
void paintTiles(Graphics g)
{
int currentPlayerX = player.x;
int currentPlayerY = player.y;
for (Tile tile : allTiles)
{
g.drawImage(tile, currentPlayerX, currentPlayerY, null);
}
}
This way, the "current" player coordinates will remain the same while iterating over the tiles.
I'm trying to make some shapes with Java. I created two rectangles with two different colors but I want to create a star shape and I can't find useful source to help me doing this.
Here is my code:
import java.awt.*;
import javax.swing.*;
public class shapes extends JPanel{
#Override
public void paintComponent(Graphics GPHCS){
super.paintComponent(GPHCS);
GPHCS.setColor(Color.BLUE);
GPHCS.fillRect(25,25,100,30);
GPHCS.setColor(Color.GRAY);
GPHCS.fillRect(25,65,100,30);
GPHCS.setColor(new Color(190,81,215));
GPHCS.drawString("This is my text", 25, 120);
}
}
You could try using a polygon and some basic math:
int midX = 500;
int midY = 340;
int radius[] = {118,40,90,40};
int nPoints = 16;
int[] X = new int[nPoints];
int[] Y = new int[nPoints];
for (double current=0.0; current<nPoints; current++)
{
int i = (int) current;
double x = Math.cos(current*((2*Math.PI)/max))*radius[i % 4];
double y = Math.sin(current*((2*Math.PI)/max))*radius[i % 4];
X[i] = (int) x+midX;
Y[i] = (int) y+midY;
}
g.setColor(Color.WHITE);
g.fillPolygon(X, Y, nPoints);
You can also use existing classes e.g. http://java-sl.com/shapes.html for regular polygons and stars.
The Polygon class can be considered as a legacy class that has been there since Java 1.0, but should hardly be used any more in new code. The odd way of specifying the x/y coordinates in separate arrays, and, more importantly, the fact that it only supports int[] arrays limits its application areas. Although it implements the Shape interface, there are more modern implementations of this interface that can be used to represent polygons. In most cases, describing the polygon as a Path2D is easier and more flexible. One can create a Path2D p = new Path2D.Double(); and then do a sequence of moveTo and lineTo calls to geneate the desired shape.
The following program shows how the Path2D class may be used to generate star shapes. The most important method is the createStar method. It is very generic. It receives
the center coordinates for the star
the inner and outer radius of the star
the number of rays that the star should have
the angle where the first ray should be (i.e. the rotation angle of the star)
If desired, a simpler method may be wrapped around this one - as with the createDefaultStar example in the code below.
The program shows different stars, painted as lines and filled with different colors and radial gradient paints, as examples:
The complete program as a MCVE:
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.RadialGradientPaint;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.geom.Path2D;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class DrawStarShape
{
public static void main(String[] args)
{
SwingUtilities.invokeLater(new Runnable()
{
#Override
public void run()
{
createAndShowGUI();
}
});
}
private static void createAndShowGUI()
{
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.getContentPane().add(new DrawStarShapePanel());
f.setSize(600, 600);
f.setLocationRelativeTo(null);
f.setVisible(true);
}
}
class DrawStarShapePanel extends JPanel
{
#Override
protected void paintComponent(Graphics gr)
{
super.paintComponent(gr);
Graphics2D g = (Graphics2D) gr;
g.setColor(Color.WHITE);
g.fillRect(0, 0, getWidth(), getHeight());
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g.setColor(Color.BLACK);
g.draw(createDefaultStar(50, 200, 200));
g.setPaint(Color.RED);
g.fill(createStar(400, 400, 40, 60, 10, 0));
g.setPaint(new RadialGradientPaint(
new Point(400, 200), 60, new float[] { 0, 1 },
new Color[] { Color.RED, Color.YELLOW }));
g.fill(createStar(400, 200, 20, 60, 8, 0));
g.setPaint(new RadialGradientPaint(
new Point(200, 400), 50, new float[] { 0, 0.3f, 1 },
new Color[] { Color.RED, Color.YELLOW, Color.ORANGE }));
g.fill(createStar(200, 400, 40, 50, 20, 0));
}
private static Shape createDefaultStar(double radius, double centerX,
double centerY)
{
return createStar(centerX, centerY, radius, radius * 2.63, 5,
Math.toRadians(-18));
}
private static Shape createStar(double centerX, double centerY,
double innerRadius, double outerRadius, int numRays,
double startAngleRad)
{
Path2D path = new Path2D.Double();
double deltaAngleRad = Math.PI / numRays;
for (int i = 0; i < numRays * 2; i++)
{
double angleRad = startAngleRad + i * deltaAngleRad;
double ca = Math.cos(angleRad);
double sa = Math.sin(angleRad);
double relX = ca;
double relY = sa;
if ((i & 1) == 0)
{
relX *= outerRadius;
relY *= outerRadius;
}
else
{
relX *= innerRadius;
relY *= innerRadius;
}
if (i == 0)
{
path.moveTo(centerX + relX, centerY + relY);
}
else
{
path.lineTo(centerX + relX, centerY + relY);
}
}
path.closePath();
return path;
}
}
I have 2 method.
1)
public static Bitmap drawStar(int W, int H, int color, boolean andRing)
{
Path path = new Path();
Bitmap output = Bitmap.createBitmap(W, H, Config.ARGB_8888);
Canvas canvas = new Canvas(output);
final Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setColor(color);
float midW ,min ,fat ,half ,radius;
if(andRing)
{
midW = W / 2;
min = Math.min(W, H);
half = min / 2;
midW = midW - half;
fat = min / 17;
radius = half - fat;
paint.setStrokeWidth(fat);
paint.setStyle(Paint.Style.STROKE);
canvas.drawCircle(midW + half, half, radius, paint);
path.reset();
paint.setStyle(Paint.Style.FILL);
path.moveTo( half * 0.5f, half * 0.84f);
path.lineTo( half * 1.5f, half * 0.84f);
path.lineTo( half * 0.68f, half * 1.45f);
path.lineTo( half * 1.0f, half * 0.5f);
path.lineTo( half * 1.32f, half * 1.45f);
path.lineTo( half * 0.5f, half * 0.84f);
}
else
{
min = Math.min(W, H);
half = min/2;
path.reset();
paint.setStyle(Paint.Style.FILL);
path.moveTo( half * 0.1f , half * 0.65f);
path.lineTo( half * 1.9f , half * 0.65f);
path.lineTo( half * 0.40f , half * 1.65f);
path.lineTo( half , 0 );
path.lineTo( half * 1.60f, half * 1.65f);
path.lineTo( half * 0.1f, half * 0.65f);
}
canvas.drawPath(path, paint);
return output;
}
2)
public static Bitmap drawStar(int W,int H,int spikes,int innerRadius,int outerRadius, int backColor,boolean border, int borderColor)
{
if(W < 10)
W = 10;
if(H < 10)
H = 10;
if(spikes < 5)
spikes = 5;
int smallL = W;
if(H < W)
smallL = H;
if(outerRadius > smallL/2)
outerRadius = smallL/2;
if(innerRadius < 5)
innerRadius = 5;
if(border)
{
outerRadius -=2;
innerRadius -=2;
}
Path path = new Path();
Bitmap output = Bitmap.createBitmap(W, H, Config.ARGB_8888);
Canvas canvas = new Canvas(output);
final Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setColor(backColor);
int cx = W/2;
int cy = H/2;
double rot = Math.PI / 2 * 3;
float x,y;
double step = Math.PI / spikes;
path.moveTo(cx, cy - outerRadius);
for (int i = 0; i < spikes; i++)
{
x = (float) (cx + Math.cos(rot) * outerRadius);
y = (float) (cy + Math.sin(rot) * outerRadius);
path.lineTo(x, y);
rot += step;
x = (float) (cx + Math.cos(rot) * innerRadius);
y = (float) (cy + Math.sin(rot) * innerRadius);
path.lineTo(x, y);
rot += step;
}
path.lineTo(cx, cy - outerRadius);
path.close();
canvas.drawPath(path, paint);
if(border)
{
paint.setStyle(Style.STROKE);
paint.setStrokeWidth(2);
paint.setColor(borderColor);
canvas.drawPath(path, paint);
}
return output;
}