Graphics rendering in thread game loop. Changing data on arrays - java

I have two objects of 2D int arrays called:
originalMap and rendedMap which they contain numbers that correspond to the puzzle game map.
From the thread class i obtain the map array from the class call Puzzle.java and modifying the one.
int [][] rendedMap = Puzzle.getRendedMap().getMap();
int [][] originalMap = Puzzle.getMapObj().getMap();
This is my thread loop:
drawPuzzle(canvas, map); takes the canvas and the array and draws a map.
while(running){
if(!holder.getSurface().isValid())
continue;
canvas = holder.lockCanvas();
if(runSolution && movements.size()>0){
executeSolution();
drawPuzzle(canvas, rendedMap);
if(finished){//checks if the execution finished
runSolution=false;
}
if(message.equals("No more actions") ||
message.equals("Out of bounds, try again!")){
System.out.println(message);
drawPuzzle(canvas, originalMap);
}
}else{
drawPuzzle(canvas, originalMap);
}
drawMovements(canvas);
holder.unlockCanvasAndPost(canvas);
}
}
And this is the method that i modify the array:
public void executeSolution(){
numOfPlanets = 2;
for(int x=0;x<rendedMap.length-1; x++){
for(int y=0;y<rendedMap[x].length-1; y++){
//Checks where the robot is and saves its initial position
if(rendedMap[x][y]>=7 && rendedMap[x][y]<=9){
initX=x; initY=y; initial=true;
System.out.println("Initial X: "+initX +" Y: "+initY );
direction = rendedMap[x][rendedMap[x].length-1];
System.out.println("Direction: "+direction );
}
}//end inner for
}//end for
if(movements.size()>0){
for(int i=0; i<movements.size();i++){
if(movements.get(i).getColour().equals("none")){
if(movements.get(i).getMotion().equals("straight")){
if(direction==RIGHT){
if(rendedMap[initX][initY+1]==0){
finished=true;
message = "Out of bounds, try again!";
return;
}else{
rendedMap[initX][initY+1]= rendedMap[initX][initY+1]+6;
rendedMap[initX][initY]=rendedMap[initX][initY]-6;
}
}
}//action if
}//color if
}//movements for loop
if(numOfPlanets > 0 ){
finished = true;
message ="No more actions";
}
}//movements if statement
}
My problem is when i render the renderMap array for some reason originalMap changes as well and when i am trying to draw back the originalMap it doesn't change back.
I have even print them out and checked line by line and they are the same.
Any tips what might cause this?
I spend like days to figure it out.

if(direction==RIGHT) {
if(rendedMap[initX][initY+1]==0) {
finished=true;
message = "Out of bounds, try again!";
return;
} else {
rendedMap[initX][initY+1]= rendedMap[initX][initY+1]+6;
rendedMap[initX][initY]=rendedMap[initX][initY]-6;
}
}
check your rendedMap array is been initialized because this can often lead to contextual errors, especially within the android IDE.

if(!holder.getSurface().isValid())
continue;
canvas = holder.lockCanvas();
if(runSolution && movements.size()>0){
executeSolution();
drawPuzzle(canvas, rendedMap);
if(finished){//checks if the execution finished
runSolution=false;
}
if(message.equals("No more actions") ||
message.equals("Out of bounds, try again!")){
System.out.println(message);
drawPuzzle(canvas, originalMap);
}
}else{
drawPuzzle(canvas, originalMap);
}
drawMovements(canvas);
recall your drawPuzzle beforte surface view is locked down as the else causes it may not be executed in that contextual loop, as I said befor it is a problem that is comon with our organization apps
hope this helps! do hesistate to ask for more assistence
sorry for english I am indian

Related

GameOver Screen for a Memory game in Java

I am programming a Memory game in java and I want to make a GameOver-Screen with an image from the sprites folder (I already have the image for it and it is an image with .jpg) after all cards are flipped. So when all cards are flipped, the game is actually over and this GameOver-Screen appears. I have no idea how I can do that. The only thing I know is that it should start with public void gameOver(){. Probably it is possible to make something with "if()" and between the brackets you could say that the condition is that all cards are flipped.
// Memory.java
import ch.aplu.jgamegrid.*; // Imports the Library of Gamegrid, on which this code is based
import ch.aplu.util.*;
public class Memory extends GameGrid implements GGMouseListener {
private boolean isReady = true;
private MemoryCard card1;
private MemoryCard card2;
public Memory() {
super(6, 6, 115, null, null, false);
MemoryCard[] cards = new MemoryCard[36];
for (int i = 0; i < 36; i++) {
if (i < 18)
cards[i] = new MemoryCard(i);
else
cards[i] = new MemoryCard(i - 18);
addActor(cards[i], getRandomEmptyLocation());
cards[i].show(1);
}
addMouseListener(this, GGMouse.lPress);
// Application thread used to flip back cards
doRun();
show();
while (true) {
// Wait until there is something to do
Monitor.putSleep();
delay(1000);
// Flip cards back
card1.show(1);
card2.show(1);
isReady = true;
// Rearm mouse events
setMouseEnabled(true);
}
}
// imports the GGMouse package
public boolean mouseEvent(GGMouse mouse) {
Location location = toLocation(mouse.getX(), mouse.getY());
MemoryCard card = (MemoryCard) getOneActorAt(location);
// Card already flipped->no action
if (card.getIdVisible() == 0)
return true;
// Show picture
card.show(0);
if (isReady) {
isReady = false;
card1 = card;
} else {
card2 = card;
// Pair found, let them visible
if (card1.getId() == card2.getId())
isReady = true;
else {
// Disable mouse events until application thread flipped back cards
setMouseEnabled(false);
Monitor.wakeUp();
}
}
return true;
}
public static void main(String[] args) {
new Memory();
}
}
Each time a card is flipped, check if all cards have been flipped. Use a loop - you already have one in your code. For each index in the for loop... ie each card... check if getIdVisible() is 0.
If the card at index i is still hidden, return null and continue running your program is normal. However, if you get all the way through the loop, that means all cards are visible, which means you can call the gameOver() method, which shows the game over screen.
Does that sound like it fits with your program?
Edit:
To check if all cards are flipped, one thing you can do is to make MemeryCard[] cards (up in the constructor) a global variable. Then you can just call this method every time you reveal two cards:
public boolean areAllCardsFlipped() {
// Start looking through each card
for (int i = 0; i < 36; i++) {
// We found a card that is NOT flipped. Stop here, because clearly all cards are not flipped.
if (cards[i].getIdVisible() != 0) {
return false;
}
}
// We have looked at all cards, and we know that each one is flipped. We can return true.
return true;
}
I'd say call this method in mouseEvent() before you return true for mouseEvent(), and if this returns true you can call the gameOver() method.
As for how to handle rendering the image... I don't know the api you're using for this game, so I can't tell you specifically how to do that. But at least with this code you should be able to trigger that gameOver.

Java - Loop gets executed, but header doesnt fit condition

This function should check if the explosion hit a box and should be canceled on the first box it hits.
For example bsp.getBomb().getStrength() is currently 2, when a box is hit i=3, but the loop is executed one more time even if the condition isn't met, why is that?
public void detectBomb(BombSpritePair bsp) {
for(int i = 0; i <= bsp.getBomb().getStrength(); i++) {
if(bd.detect(bsp.getBomb().getX(), bsp.getBomb().getY()+i)) {
Sprite sprite = new Sprite(new Texture("gras.png"));
sprite.setPosition(bsp.getBomb().getX()*16, (bsp.getBomb().getY()+i)*16);
// i = bsp.getBomb().getStrength()+1;
sprites.add(sprite);
System.out.println("RIP"+i);
System.out.println(bsp.getBomb().getStrength());
break;
}
}
}
Try adding break to the loop:
public void detectBomb(BombSpritePair bsp) {
for(int i = 0; i <= bsp.getBomb().getStrength(); i++) {
if(bd.detect(bsp.getBomb().getX(), bsp.getBomb().getY() + i)) {
Sprite sprite = new Sprite(new Texture("gras.png"));
sprite.setPosition(bsp.getBomb().getX()*16, (bsp.getBomb().getY()+i)*16);
sprites.add(sprite);
System.out.println("RIP"+i);
System.out.println(bsp.getBomb().getStrength());
break;
}
}
}
You may be seeing duplicate print statements if you are calling the detectBomb method multiple times. Putting a breakpoint or print statement at the beginning of this method will help determine what the problem is.
Another thing to keep in mind is that you are creating a new Texture for the Sprite every time the method get executed - it would be wise to only instantiate the Texture once and share it with all subsequent Sprite instances that require it.

Delete body box2d

Could anyone tell me why this is returning the error
'AL lib: (EE) alc_cleanup: 1 device not closed'
//mouseJoint collision callback
private QueryCallback queryCallback = new QueryCallback() {
#Override
public boolean reportFixture(Fixture fixture) {
if(fixture.getBody() == chest){
//add to remove list
bodiesToRemove.add(chest);
}
if (fixture.testPoint(tmp.x, tmp.y)){
reportFixture = fixture.getBody();
}
if (!fixture.testPoint(tmp.x, tmp.y))
return false;
//assigning bodyB to fixture
jointDef.bodyB = fixture.getBody();
jointDef.target.set(fixture.getBody().getWorldCenter());
//jointDef.target.set(tmp.x, tmp.y);// initial target point coincide with body anchor
joint = (MouseJoint) world.createJoint(jointDef);// creating the join the physics world
return false;
}
};
//main rendering loop
public void render(float delta) {
// TODO Auto-generated method stub
//code clears the screen with the given RGB colour (black)
Gdx.gl.glClearColor( 0f, 0f, 0f, 1f );
Gdx.gl.glClear( GL20.GL_COLOR_BUFFER_BIT );
stage.setCamera(camera);
stage.act(Gdx.graphics.getDeltaTime());
camera.position.x= chest.getPosition().x;
camera.update();
stage.draw();
world.step(1 / 60f, 8, 3);
renderer.render(world, camera.combined);
/////////////////////////////////////////////////////////////////
// this is the code that is causing the error when I try to delete a body
if(bodiesToRemove != null){
for(int i = 0; i <bodiesToRemove.size; i++){
Body b = bodiesToRemove.get(i);
if(b != null){
world.destroyBody(b);
b.setUserData(null);
b = null;
}
bodiesToRemove.clear();
}
}
////////////////////////////////////////////////////////////
}
////////////////////////////////////////////////////////////////////////////
I've changed this and it work's(pasted below), if anyone would like to explain the right way to do this or if this is the correct way that would be helpful.
I just added a boolean to prevent it from destroying the joint
// ////////////////// TOUCH EVENT ///////////////////////////////
//Called when a finger was lifted or a mouse button was released.
#Override
public boolean touchUp(int screenX, int screenY, int pointer, int button) {
//If no mouseJoint do nothing
System.out.println("touch" + (screenY*0.01f));
System.out.println("touch" + (screenX*0.01f));
if (joint == null)
return false;
//When user is not touching Screen destroy the
//mouseJoint/set to null
if(ran == false){
world.destroyJoint(joint);
joint = null;}
ran = false;
return true;
}
////////////////////////////////
/////////////////////////////////
if(!world.isLocked() && world.getBodyCount() > 0 ){
for(int i = 0; i <bodiesToRemove.size; i++){
Body b = bodiesToRemove.get(i);
if(b == null){
bodiesToRemove.removeIndex(i);
continue;
}
world.destroyBody(b);
ran = true;
bodiesToRemove.removeIndex(i);
}
}else{
bodiesToRemove.clear();
}
////////////////////////////////////////////////////////////
Box2D throws some odd errors, this is not one of them.
I assume you are using LibGDX, basically what is happening is a crash due to Box2D (I also assume it pops up saying "java or whatever has stopped responding"), this error you are seeing is thrown when the app exits while OpenAL is closing streams and cleaning up resources. Don't worry about that too much.
Ensure you are checking of the world is locked before destroying bodies, it usually throws an error and prints a clear message telling you this, depending on the way you are removing bodies.
if(!world.isLocked())
// do clean up code here
You don't need to clean up the variable inside local scope, or clear the userdata inside the body as the body as it will no longer exist in reference (unless you have it stored somewhere else).
So the proper code would be something like this:
if(!world.isLocked()){
for(int i = bodiesToRemove.size - 1; i--){
Body b = bodiesToRemove.get(i);
if(b == null){
bodiesToRemove.removeAt(i);
continue;
}
world.destroyBody(b);
bodiesToRemove.removeAt(i);
}
}
You are also clearing a list during iteration, not a good idea.
EDIT
The only other thing I can think of that is causing this problem is trying to delete a body that is not actually in the worlds body list.
Try the following:
// Ensure world is not locked AND that there is even bodies in the world
if(!world.isLocked() && world.getBodyCount() > 0){
for(int i = bodiesToRemove.size - 1; i--){
Body b = bodiesToRemove.get(i);
if(b == null){
bodiesToRemove.removeAt(i);
continue;
}
world.destroyBody(b);
bodiesToRemove.removeAt(i);
}
}else{
// There is no bodies in the world, so the bodies in our list are just
// random memory hogs, leave them for the GC by clearing the list
bodiesToRemove.clear();
}
EDIT
As stated by the OP, the problem lies with this block of code:
private QueryCallback queryCallback = new QueryCallback() {
#Override
public boolean reportFixture(Fixture fixture) {
if(fixture.getBody() == chest){
//add to remove list
bodiesToRemove.add(chest);
}
if (fixture.testPoint(tmp.x, tmp.y)){
reportFixture = fixture.getBody();
}
if (!fixture.testPoint(tmp.x, tmp.y))
return false;
//assigning bodyB to fixture
jointDef.bodyB = fixture.getBody();
jointDef.target.set(fixture.getBody().getWorldCenter());
//jointDef.target.set(tmp.x, tmp.y);
joint = (MouseJoint) world.createJoint(jointDef);
return false;
}
};
More specifically, this line:
joint = (MouseJoint) world.createJoint(jointDef);
The query callback is triggered during a world step. In Box2D, you can not create or destroy bodies, fixtures, and joints during the world step.
You have to create it outside this method, the simplest way to do it is via a flag. Set a flag to true and store the instance of the fixture somewhere and handle it outside in the game loop using said flag and fixture.

how do i stop this "IndexOutOfBoundsException" issue?

So I the app lets a user place down blocks on a grid, if the user lines up 3 or more blocks with the same suit, or color, then something happens. When player places a block I call this method:
blocks_.add(new Block(new Vector2(rect_mouse.x, rect_mouse.y), blocks_.get(0).blockID, blockCount));
When you place 3 or more together I call these methods:
blocks_.removeValue(blocks_.get(left_bravo_indexNum), true);
blocks_.removeValue(blocks_.get(center_charlie_indexNum), true);
blocks_.removeValue(blocks_.get(right_alpha_indexNum), true);
stack:
Exception in thread "LWJGL Application" java.lang.IndexOutOfBoundsException: 13
at com.badlogic.gdx.utils.Array.get(Array.java:125)
at com.jrp.mygearapp.GameScreen.touchUp(GameScreen.java:1443)
at com.badlogic.gdx.backends.lwjgl.LwjglInput.processEvents(LwjglInput.java:297)
at com.badlogic.gdx.backends.lwjgl.LwjglApplication.mainLoop(LwjglApplication.java:186)
at com.badlogic.gdx.backends.lwjgl.LwjglApplication$1.run(LwjglApplication.java:110)
This was intended to remove the blocks, but it resulted in this IndexOutOfBoundsException. Is there a way to prevent this error?
This could be occurring because the array auto sorts the number of elements and lowers the number to the correct number of elements in the array, and I still have elements that are labeled higher then the size of the array. I am still a novice, so my analysis could be incorrect. Please alert me if this is the case and help me find a fix.
Thanks.
edirted* TouchUp() function-------
#Override
public boolean touchUp(int x, int y, int pointer, int button) {
if (button == 0) {
display_blockCheck = false;
////set blockCount to the size of blockArray so blocks can properly be indexed
blockCount = blocks_.size;
if (!overlap) {
Gdx.app.log("Block Added", "x: " + x + " y: " + y);
updateQueueBlocks();
//add block
Vector2 rect_vector = new Vector2(rect_mouse.x, rect_mouse.y);
Block block = new Block(rect_vector,blocks_.get(0).blockID, blocks_.size);
blocks_.add(block);
if (center_charlie_suit == "Square") {
center_charlie_bool = true;
if (right_bravo_suit == "Square") {
right_bravo_bool = true;
if (right_alpha_suit == "Square") {
Gdx.app.log("3-pair", "Square:345:lr");
right_alpha_bool = true;
//call 3-pair event
blocks_.removeValue(blocks_.get(center_charlie_indexNum), true);
blocks_.removeValue(blocks_.get(right_alpha_indexNum), true);
blocks_.removeValue(blocks_.get(right_bravo_indexNum), true);
}
}
}
the rest is just really long and just checks for other blocks next to each other..
You're right, as you remove the blocks, the indexes change.
You don't show what type of Collection blocks_ is (Vector2?, did you write it?), however, rather than tracking the indices of the elements, simply track the elements themselves and call remove() to find and remove that element.

ActionEvent in Java moves multiple buttons

Okay so I am pretty much doing a crash course through creating a java application and am having an issue with executing an action. The program is the 15 puzzle, the game where you slide one piece at a time and try to get all numbers in order, so I allow for an 'Auto' mode option that will solve the board for the user once clicked. So my code reads the solution from a text file which is working fine just none of the 'squares' (JButtons) move when I click the auto button. So i am not sure if I just don't understand the action even process completely or not. heres my code, I can supply more of it if necessary.
if (e.getSource() == ctrButtons[0]) {
System.out.println("Auto Mode started\n");
Scanner s = null;
try {
s = new Scanner(new BufferedReader(new FileReader("move_list.txt")));
int count = 0;
while (s.hasNext()) {
//Cycle through to move in move_list
if (count != 18) {
s.next();
count+=1;
}
else {
int cur_move = Integer.parseInt(s.next());
count = 0;
/*Use cur_move to move blank space accordingly
*UP------------3
*LEFT----------2
*RIGHT---------1
*DOWN----------0
*/
int zero_index = -1;
for (int j=0; j<jbnButtons.length; j++) {
if (Integer.parseInt(jbnButtons[j].getText()) == 0) {
zero_index = j;
break;
}
}
Point zero = jbnButtons[zero_index].getLocation();
//Check if move is up
if (cur_move == 3) {
Point next = jbnButtons[zero_index-4].getLocation();
jbnButtons[zero_index].setLocation(next);
jbnButtons[zero_index-4].setLocation(zero);
}
//Check if move is left
else if (cur_move == 2) {
Point next = jbnButtons[zero_index-1].getLocation();
jbnButtons[zero_index].setLocation(next);
jbnButtons[zero_index-1].setLocation(zero);
}
//Check if move is right
else if (cur_move == 1) {
Point next = jbnButtons[zero_index+1].getLocation();
jbnButtons[zero_index].setLocation(next);
jbnButtons[zero_index+1].setLocation(zero);
}
//Check if move is down
else {
System.out.println("Current move = 0");
Point next = jbnButtons[zero_index+4].getLocation();
jbnButtons[zero_index].setLocation(next);
jbnButtons[zero_index+4].setLocation(zero);
}
}
}
}
So my code executes when I click the 'Auto' button and I was printing output to the screen to see if it was looping through the code which it was, just none of the buttons move each time through the loop. Any ideas??
You code is executing on the Event Dispatch Thread. The GUI can't repaint itself until the code finishes executing, so you won't see the intermediate steps only the final location of each component.
Read tje section from the Swing tutorial on Concurrency for a more complete explanation.
Maybe you should use a Swing Timer (the tutorial also has a section on this). Each time the Timer fire you do the next move.

Categories

Resources