0
\$\begingroup\$

Good afternoon. Help me please to add the code for the game. This game is puzzle. Everything works good, but I would like to have not just ordinary puzzles with numbers, but also the puzzle with a picture. Could you tell me how I can insert a picture ant divide it into parts? Thanks in advance for any help.

package com.frastan.puzzletestgame3.screens;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Screen;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.g2d.TextureAtlas;
import com.badlogic.gdx.math.Interpolation;
import com.badlogic.gdx.math.MathUtils;
import com.badlogic.gdx.scenes.scene2d.InputEvent;
import com.badlogic.gdx.scenes.scene2d.Stage;
import com.badlogic.gdx.scenes.scene2d.ui.Label;
import com.badlogic.gdx.scenes.scene2d.ui.Skin;
import com.badlogic.gdx.scenes.scene2d.ui.TextButton;
import com.badlogic.gdx.scenes.scene2d.utils.ClickListener;
import com.badlogic.gdx.utils.Align;
import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.viewport.StretchViewport;
import com.frastan.puzzletestgame3.Application;
import com.frastan.puzzletestgame3.actors.SlideButton;
import static com.badlogic.gdx.scenes.scene2d.actions.Actions.*;

public class PlayScreen implements Screen {
private final Application app;
private Stage stage;
private Skin skin;
private int boardSize = 4;
private int holeX, holeY;
private SlideButton[][] buttonGrid;
private TextButton buttonBack;
private Label labelInfo;
public PlayScreen(final Application app){
    this.app = app;
    this.stage = new Stage(new StretchViewport(Application.V_WIDTH,Application.V_HEIGHT,app.camera));
}

@Override
public void show() {
    System.out.println("PLAY");
    Gdx.input.setInputProcessor(stage);
    stage.clear();
    this.skin = new Skin();
    this.skin.addRegions(app.assets.get("ui/uiskin.atlas", TextureAtlas.class));
    this.skin.add("default-font", app.font24);
    this.skin.load(Gdx.files.internal("ui/uiskin.json"));
    initNavigationButtons();
    initInfoLabel();
    initGrid();

}
private void update(float delta){
    stage.act(delta);
}

@Override
public void render(float delta) {
    Gdx.gl.glClearColor(1f,1f,1f,1f);
    Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
    update(delta);
    stage.draw();
}

@Override
public void resize(int width, int height) {

}

@Override
public void pause() {

}

@Override
public void resume() {

}

@Override
public void hide() {

}

@Override
public void dispose() {
    stage.dispose();
}

private void initNavigationButtons(){
    buttonBack = new TextButton("Back", skin, "default");
    buttonBack.setPosition(20, app.camera.viewportHeight - 70);
    buttonBack.setSize(100, 50);
    buttonBack.addListener(new ClickListener(){
        @Override
        public void clicked(InputEvent event, float x, float y){
            app.setScreen(app.mainMenuScreen);
        }
    });
    stage.addActor(buttonBack);
}
private void initInfoLabel(){
    labelInfo = new Label("Welcome! Click any number tile to begin!", skin, "default");
    labelInfo.setPosition(20, 350);
    labelInfo.setAlignment(Align.center);
    labelInfo.addAction(sequence(alpha(0f), delay(.5f), fadeIn(.5f)));
    stage.addActor(labelInfo);
}
private void initGrid(){
    Array<Integer> nums = new Array<Integer>();
    for(int i = 1; i < boardSize * boardSize; i++){
        nums.add(i);
    }
    nums.shuffle();
    holeX = MathUtils.random(0, boardSize - 1);
    holeY = MathUtils.random(0, boardSize - 1);
    buttonGrid = new SlideButton[boardSize][boardSize];
    for(int i = 0; i <boardSize; i++){
        for(int j = 0; j <boardSize; j++){
            if(i != holeY || j != holeX) {
                int id = nums.removeIndex(0);
                buttonGrid[i][j] = new SlideButton(id + "", skin, "default", id);
                buttonGrid[i][j].setPosition((app.camera.viewportWidth / 7) * 2 + 51 * j,
                        (app.camera.viewportHeight / 5) * 3 - 51 * i);
                buttonGrid[i][j].setSize(50, 50);
                buttonGrid[i][j].addAction(sequence(alpha(0), delay((j + 1 + (i * boardSize)) / 15f),
                        parallel(fadeIn(.5f), moveBy(0, -10, .25f, Interpolation.pow5Out))));
                buttonGrid[i][j].addListener(new ClickListener(){
                    @Override
                    public void clicked(InputEvent event, float x, float y){
                        int buttonX = 0, buttonY = 0;
                        boolean buttonFound = false;
                        SlideButton selectedButton = (SlideButton) event.getListenerActor();
                        for(int i = 0; i < boardSize && !buttonFound; i++){
                            for(int j = 0; j < boardSize && !buttonFound; j++){
                                if(buttonGrid[i][j] != null && selectedButton == buttonGrid[i][j]){
                                    buttonX = j;
                                    buttonY = i;
                                    buttonFound = true;
                                }
                            }
                        }
                        if(holeX == buttonX || holeY == buttonY){
                            moveButtons(buttonX, buttonY);
                            if(solutionFound()){
                                labelInfo.clearActions();
                                labelInfo.setText("Solution Found!");
                                labelInfo.addAction(sequence(alpha(1f), delay(3f), fadeOut(2f, Interpolation.pow5Out)));
                            }
                        } else {
                            labelInfo.clearActions();
                            labelInfo.setText("Invalid Move!");
                            labelInfo.addAction(sequence(alpha(1f), delay(1f), fadeOut(1f, Interpolation.pow5Out)));
                        }
                    }
                });
                stage.addActor(buttonGrid[i][j]);
            }
        }
    }
}
private void moveButtons(int x, int y){
    SlideButton button;
    if(x < holeX){
        for(; holeX > x; holeX--){
            button = buttonGrid[holeY][holeX - 1];
            button.addAction(moveBy(51, 0, .5f, Interpolation.pow5Out));
            buttonGrid[holeY][holeX] = button;
            buttonGrid[holeY][holeX - 1] = null;
        }
    } else {
        for(; holeX < x; holeX++){
            button = buttonGrid[holeY][holeX + 1];
            button.addAction(moveBy(-51, 0, .5f, Interpolation.pow5Out));
            buttonGrid[holeY][holeX] = button;
            buttonGrid[holeY][holeX + 1] = null;
        }
    }
    if(y < holeY){
        for(; holeY > y; holeY--){
            button = buttonGrid[holeY - 1][holeX];
            button.addAction(moveBy(0, -51, .5f, Interpolation.pow5Out));
            buttonGrid[holeY][holeX] = button;
            buttonGrid[holeY - 1][holeX] = null;
        }
    } else {
        for(; holeY < y; holeY++){
            button = buttonGrid[holeY + 1][holeX];
            button.addAction(moveBy(0, 51, .5f, Interpolation.pow5Out));
            buttonGrid[holeY][holeX] = button;
            buttonGrid[holeY + 1][holeX] = null;
        }
    }
}
private boolean solutionFound(){
    int idCheck = 1;
    for(int i = 0; i < boardSize; i++){
        for(int j = 0; j < boardSize; j++){
            if(buttonGrid[i][j] != null){
                if(buttonGrid[i][j].getId() == idCheck++){
                    if(idCheck == 16){
                        return true;
                    }
                } else {
                    return false;
                }
            } else {
                return false;
            }
        }
    }
    return false;
}
}

enter image description here

\$\endgroup\$
  • \$\begingroup\$ You might want to look at TextureRegion.split(..) It splits a texture-region into multiple texture-regions! \$\endgroup\$ – ProRed Sep 27 '16 at 15:56
1
\$\begingroup\$

Libgdx provides Texture and TextureRegion classes that should do what you need.

A Texture is a handle to the entire image. One way to load it is

Texture dogTexture = new Texture(Gdx.files.internal("path/to/dog.png"));

and a Texture is drawn using a Batch

//x,y,width and height are where and how big the texture is drawn in your world
batch.draw(dogTexture,x,y,width,height);

A TextureRegion is just what it sounds, it is just a smaller part of a texture. It is created like this

//x,y,width, and height are coordinates on the texture where you want to cut-out the texture region
TextureRegion dogRegion = new TextureRegion(dogTexture,x,y,width,height);

and a TextureRegion can be drawn the same way as a whole texture

batch.draw(dogRegion,x,y,width,height);

So, you will want to create a TextureRegion for each SlideButton which corresponds to the part of the texture that the button should be displaying.

Then, you should draw the whole texture for the hint picture near the top of the game.

\$\endgroup\$
  • \$\begingroup\$ Could you write the code, please? Thank you for your assistance. \$\endgroup\$ – Frastan Jun 14 '16 at 21:39
  • \$\begingroup\$ package com.frastan.puzzletestgame3.actors; import com.badlogic.gdx.scenes.scene2d.ui.Skin; import com.badlogic.gdx.scenes.scene2d.ui.TextButton; public class SlideButton extends TextButton { private int id; public SlideButton(String text, Skin skin, String style, int id){ super(text, skin, style); this.id = id; } public int getId(){ return id; } } \$\endgroup\$ – Frastan Jun 14 '16 at 21:39
  • 4
    \$\begingroup\$ @Frastan this is not a code writing service \$\endgroup\$ – Bálint Jan 4 '17 at 8:49
0
\$\begingroup\$

For you if statement, the button manipulation code is a bit redundant, what I would recommend is to make another void class:

public void ModifyHole(SlideButton button, int yMod, int xMod){
    button = buttonGrid[holeY+yMod][holeX + xMod];
    button.addAction(moveBy(51*xMod*(-1), 51*yMod*(-1), .5f, Interpolation.pow5Out));
    buttonGrid[holeY][holeX] = button;
    buttonGrid[holeY + yMod][holeX + xMod] = null;
}

private void moveButtons(int x, int y){
    SlideButton button;
    if(x < holeX){
        for(; holeX > x; holeX--){
            ModifyHole(button, 0,-1);
        }
    } else {
        for(; holeX < x; holeX++){
            ModifyHole(button, 0,1);
        }
    }
    if(y < holeY){
        for(; holeY > y; holeY--){
            ModifyHole(button, -1,0);
        }
    } else {
        for(; holeY < y; holeY++){
            ModifyHole(button, 1,0);
        }
    }
}

This helps so that if you need to change the code for the manipulation, it'll affect all the if-statements.

Also you have a lot of magic numbers.

I'm not 100% sure what the 15 represents, though I think it is how far each block needs to move so something like:

private final int MOVE_DISTANCE = 15;

Same thing for when you check if the game is solved.

private final int SOLVED_TILES = 16;

Other places would be when you are initializing the board such as width, height, etc. Replace the magic numbers with final variables.

Another thing in the initialization is that you should move the button creation into a separate method so that it is easier to modify for a later date. Breaking code into chunks of code that all work together makes life easier and helps when going back to edit it.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.