I am trying to implement path drawing for a herding game.
Currently when I run the game on PC I use the mouse to draw a path for which the herder will move through, but I can not get it to draw a line.
package com.mygdx.herdergame.Sprites;
import com.badlogic.gdx.Input;
import com.badlogic.gdx.InputProcessor;
import com.badlogic.gdx.graphics.g2d.Animation;
import com.badlogic.gdx.graphics.g2d.Sprite;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.math.Vector3;
import com.badlogic.gdx.physics.box2d.Body;
import com.badlogic.gdx.physics.box2d.BodyDef;
import com.badlogic.gdx.physics.box2d.CircleShape;
import com.badlogic.gdx.physics.box2d.FixtureDef;
import com.badlogic.gdx.physics.box2d.World;
import com.badlogic.gdx.utils.Array;
import com.mygdx.herdergame.HerderGame;
import com.mygdx.herdergame.Screens.PlayScreen;
import java.util.ArrayList;
public class Herder extends Sprite implements InputProcessor {
HerderGame game;
public World world;
public Body b2body;
private PlayScreen screen;
//States
private enum State {
RUNNINGRIGHT, RUNNINGLEFT, RUNNINGUP, RUNNINGDOWN, STANDINGRIGHT, STANDINGLEFT, STANDINGUP, STANDINGDOWN
}
private State currentState;
private State previousState;
private float stateTimer;
//Textures
private Animation runningRight;
private Animation runningLeft;
private Animation runningUp;
private Animation runningDown;
private TextureRegion standRight;
private TextureRegion standLeft;
private TextureRegion standUp;
private TextureRegion standDown;
private float destinationX;
private float destinationY;
//Velocity
private static final float MAX_SPEED = 500;
private float speedLimit = 1000;
private Vector2 velocity = new Vector2(0, 0);
private static float ACCURACY = 50;
//Touch Screen
private Vector3 touchpoint = new Vector3();
private Vector2 targetPosition;
private ArrayList<Vector2> herderPath = new ArrayList<Vector2>();
boolean dragging;
boolean followingPath = false;
// death variables
private boolean isInTimedDeathZone;
private float deathTimer;
//this is the constructor.
public Herder(World world, PlayScreen screen) {
super(screen.getAtlas().findRegion("herderRight"));
this.screen = screen;
game = screen.getGame();
this.world = world;
defBody();
setTextures();
currentState = State.STANDINGRIGHT;
previousState = State.STANDINGRIGHT;
stateTimer = 0;
isInTimedDeathZone = false;
deathTimer = 0;
}
public void defBody() {
BodyDef bdef = new BodyDef();
bdef.position.set(500, 500);
bdef.type = BodyDef.BodyType.DynamicBody;
b2body = world.createBody(bdef);
FixtureDef fdef = new FixtureDef();
CircleShape shape = new CircleShape();
shape.setRadius(10);
fdef.shape = shape;
b2body.createFixture(fdef).setUserData(this);
}
public void setTextures() {
int herderUpStartX = game.rm.getChapter(game.getCurrentChapter()).getHerderUp().getStartX();
int herderUpStartY = game.rm.getChapter(game.getCurrentChapter()).getHerderUp().getStartY();
int herderDownStartX = game.rm.getChapter(game.getCurrentChapter()).getHerderDown().getStartX();
int herderDownStartY = game.rm.getChapter(game.getCurrentChapter()).getHerderDown().getStartY();
int herderLeftStartX = game.rm.getChapter(game.getCurrentChapter()).getHerderLeft().getStartX();
int herderLeftStartY = game.rm.getChapter(game.getCurrentChapter()).getHerderLeft().getStartY();
int herderRightStartX = game.rm.getChapter(game.getCurrentChapter()).getHerderRight().getStartX();
int herderRightStartY = game.rm.getChapter(game.getCurrentChapter()).getHerderRight().getStartY();
int numberOfFrame = game.rm.getChapter(game.getCurrentChapter()).getHerderRight().getNumberOfFrame();
int width = game.rm.getChapter(game.getCurrentChapter()).getHerderRight().getWidth();
int height = game.rm.getChapter(game.getCurrentChapter()).getHerderRight().getHeight();
//this enables the sprite to be drawn.
Array<TextureRegion> frames = new Array<TextureRegion>();
for (int i = 0; i < numberOfFrame; i++) {
frames.add(new TextureRegion(getTexture(), herderRightStartX + width * i, herderRightStartY, width, height));
}
runningRight = new Animation(0.1f, frames);
frames.clear();
for (int i = 0; i < numberOfFrame; i++) {
frames.add(new TextureRegion(getTexture(), herderLeftStartX + width * i, herderLeftStartY, width, height));
}
runningLeft = new Animation(0.1f, frames);
frames.clear();
for (int i = 0; i < numberOfFrame; i++) {
frames.add(new TextureRegion(getTexture(), herderDownStartX + width * i, herderDownStartY, width, height));
}
runningDown = new Animation(0.1f, frames);
frames.clear();
for (int i = 0; i < numberOfFrame; i++) {
frames.add(new TextureRegion(getTexture(), herderUpStartX + width * i, herderUpStartY, width, height));
}
runningUp = new Animation(0.1f, frames);
standRight = new TextureRegion(getTexture(), herderRightStartX, herderRightStartY, width, height);
setBounds(0, 0, 32, 32);
setRegion(standRight);
standLeft = new TextureRegion(getTexture(), herderLeftStartX, herderLeftStartY, width, height);
setBounds(0, 0, 32, 32);
setRegion(standLeft);
standUp = new TextureRegion(getTexture(), herderUpStartX, herderUpStartY, width, height);
setBounds(0, 0, 32, 32);
setRegion(standUp);
standDown = new TextureRegion(getTexture(), herderDownStartX, herderDownStartY, width, height);
setBounds(0, 0, 32, 32);
setRegion(standDown);
setSize(32, 32);
}
public TextureRegion getFrame(float dt) {
currentState = getState();
TextureRegion region;
switch (currentState) {
case RUNNINGRIGHT:
region = runningRight.getKeyFrame(stateTimer, true);
break;
case RUNNINGLEFT:
region = runningLeft.getKeyFrame(stateTimer, true);
break;
case RUNNINGUP:
region = runningUp.getKeyFrame(stateTimer, true);
break;
case RUNNINGDOWN:
region = runningDown.getKeyFrame(stateTimer, true);
break;
case STANDINGLEFT:
region = standLeft;
break;
case STANDINGUP:
region = standUp;
break;
case STANDINGDOWN:
region = standDown;
break;
case STANDINGRIGHT:
default:
region = standRight;
break;
}
stateTimer = currentState == previousState ? stateTimer + dt : 0;
previousState = currentState;
return region;
}
public State getState() {
Vector2 direction = b2body.getLinearVelocity();
if (direction.isZero()) {
switch (previousState) {
case RUNNINGUP:
return State.STANDINGUP;
case RUNNINGLEFT:
return State.STANDINGLEFT;
case RUNNINGDOWN:
return State.STANDINGDOWN;
case RUNNINGRIGHT:
return State.STANDINGRIGHT;
default:
return previousState;
}
} else if (direction.x >= 0 && direction.y >= 0) {
if (direction.x > direction.y) {
return State.RUNNINGRIGHT;
} else return State.RUNNINGUP;
} else if (direction.x >= 0 && direction.y <= 0) {
if (direction.x > -direction.y) {
return State.RUNNINGRIGHT;
} else return State.RUNNINGDOWN;
} else if (direction.x <= 0 && direction.y >= 0) {
if (-direction.x > direction.y) {
return State.RUNNINGLEFT;
} else return State.RUNNINGUP;
} else if (direction.x <= 0 && direction.y <= 0) {
if (-direction.x > -direction.y) {
return State.RUNNINGLEFT;
} else return State.RUNNINGDOWN;
} else return currentState = previousState;
}
public void update(float dt) {
if (isXStapable() || isYStapable()) {
stop();
}
if (followingPath) {
if (!herderPath.iterator().hasNext()) {
followingPath = false;
herderPath.clear();
stop();
} else if (targetPosition.dst(b2body.getPosition()) < 1.5) {
targetPosition = herderPath.get(0);
herderPath.remove(0);
velocity = calculateVelocity(b2body.getPosition(), targetPosition);
} else {
velocity = calculateVelocity(b2body.getPosition(), targetPosition);
}
}
b2body.setLinearVelocity(velocity);
setPosition(b2body.getPosition().x - getWidth() / 2, b2body.getPosition().y - getHeight() / 2);
setRegion(getFrame(dt));
if (isInTimedDeathZone) {
deathTimer += dt;
} else {
deathTimer = 0;
}
if (deathTimer > 2f) {
screen.gameOver();
}
}
public void setInTimedDeathZone(boolean b) {
this.isInTimedDeathZone = b;
}
#Override
public boolean keyDown(int keycode) {
switch (keycode) {
case Input.Keys.UP:
velocity.y = speedLimit;
break;
case Input.Keys.DOWN:
velocity.y = -speedLimit;
break;
case Input.Keys.LEFT:
velocity.x = -speedLimit;
break;
case Input.Keys.RIGHT:
velocity.x = speedLimit;
break;
default:
return true;
}
followingPath = false;
return true;
}
#Override
public boolean keyUp(int keycode) {
switch (keycode) {
case Input.Keys.UP:
case Input.Keys.DOWN:
velocity.y = 0;
break;
case Input.Keys.LEFT:
case Input.Keys.RIGHT:
velocity.x = 0;
break;
}
return true;
}
#Override
public boolean keyTyped(char character) {
return false;
}
#Override
public boolean touchDown(int screenX, int screenY, int pointer, int button) {
float diffX;
float diffY;
// ignore if its not left mouse button or first touch pointer
if (button != Input.Buttons.LEFT || pointer > 0) return false;
screen.getCamera().unproject(touchpoint.set(screenX, screenY, 0));
//ignore if the first point is not close to the herder
diffX = touchpoint.x - b2body.getPosition().x;
diffY = touchpoint.y - b2body.getPosition().y;
if (diffX > 25 || diffX < -25 || diffY > 25 || diffY < -25) return false;
dragging = true;
herderPath.clear();
targetPosition = b2body.getPosition();
herderPath.add(targetPosition);
return true;
}
#Override
public boolean touchDragged(int screenX, int screenY, int pointer) {
Vector2 vec2 = new Vector2();
if (!dragging) return false;
screen.getCamera().unproject(touchpoint.set(screenX, screenY, 0));
vec2.set(touchpoint.x, touchpoint.y);
herderPath.add(vec2);
followingPath = true;
return true;
}
#Override
public boolean touchUp(int screenX, int screenY, int pointer, int button) {
if (button != Input.Buttons.LEFT || pointer > 0) return false;
screen.getCamera().unproject(touchpoint.set(screenX, screenY, 0));
dragging = false;
return true;
}
private Vector2 calculateVelocity(Vector2 currentPosition, Vector2 targetPosition) {
Vector2 tempTP = new Vector2().set(targetPosition);
return tempTP.sub(currentPosition).nor().scl(speedLimit);
}
public boolean isXValid(int x) {
return b2body.getPosition().x <= x + ACCURACY && b2body.getPosition().x >= x - ACCURACY;
}
public boolean isYValid(int y) {
return b2body.getPosition().y <= y + ACCURACY && b2body.getPosition().y >= y - ACCURACY;
}
public boolean isXStapable() {
return isXValid((int) destinationX);
}
public boolean isYStapable() {
return isYValid((int) destinationY);
}
public void stop() {
velocity.set(0, 0);
}
#Override
public boolean mouseMoved(int screenX, int screenY) {
return false;
}
#Override
public boolean scrolled(int amount) {
return false;
}
public void setSpeedLimit(float multiplier) {
if (speedLimit > MAX_SPEED) {
this.speedLimit = MAX_SPEED;
} else {
this.speedLimit = multiplier;
}
}
}
Related
I try to make a game in android studio (for an univeristy project) and I have some problems.
The game in question is a maze game type. I create the maze and the player, it work but I would to insert an image for the player, but I don't know how.
This is the code of the entire GameView.
public class GameView extends View {
private enum Direction {
UP, DOWN, LEFT, RIGHT
}
private Cell[][] cells;
private Cell player, exit;
private static final int COLS = 7 , ROWS = 10;
private static final float WALL_THICKNESS = 7;
private float cellSize, hMargin, vMargin;
private Paint wallPaint, exitPaint,playerPaint;
private Random random;
public GameView(Context context, #Nullable AttributeSet attrs) {
super(context, attrs);
wallPaint = new Paint();
wallPaint.setColor(Color.BLACK);
wallPaint.setStrokeWidth(WALL_THICKNESS);
playerPaint = new Paint();
playerPaint.setColor(Color.RED);
exitPaint = new Paint();
exitPaint.setColor(Color.BLUE);
random = new Random();
createMaze();
}
private Cell getNeighbour(Cell cell){
ArrayList<Cell> neighbours = new ArrayList<>();
if(cell.col> 0){
if(!cells[cell.col-1][cell.row].visited){
neighbours.add(cells[cell.col-1][cell.row]);
}
}
if(cell.col < COLS-1){
if(!cells[cell.col+1][cell.row].visited){
neighbours.add(cells[cell.col+1][cell.row]);
}
}
if(cell.row > 0){
if(!cells[cell.col][cell.row-1].visited){
neighbours.add(cells[cell.col][cell.row-1]);
}
}
if(cell.row < ROWS-1){
if(!cells[cell.col][cell.row+1].visited){
neighbours.add(cells[cell.col][cell.row+1]);
}
}
if(neighbours.size() > 0){
int index = random.nextInt(neighbours.size());
return neighbours.get(index);
}
return null;
}
private void removeWall(Cell current, Cell next){
if(current.col == next.col && current.row == next.row+1){
current.topWall = false;
next.bottomWall = false;
}
if(current.col == next.col && current.row == next.row-1){
current.bottomWall = false;
next.topWall = false;
}
if(current.col == next.col+1 && current.row == next.row){
current.leftWall = false;
next.rightWall = false;
}
if(current.col == next.col-1 && current.row == next.row){
current.rightWall = false;
next.leftWall = false;
}
}
private void createMaze(){
Stack<Cell> stack = new Stack<>();
Cell current, next;
cells= new Cell[COLS][ROWS];
for(int x=0;x<COLS;x++){
for(int y=0;y<ROWS;y++){
cells[x][y] = new Cell(x, y);
}
}
player = cells[0][0];
exit = cells[COLS-1][ROWS-1];
current = cells[0][0];
current.visited = true;
do {
next = getNeighbour(current);
if (next != null) {
removeWall(current, next);
stack.push(current);
current = next;
current.visited = true;
} else {
current = stack.pop();
}
}while(!stack.empty());
}
#Override
protected void onDraw(Canvas canvas) {
//canvas.drawColor(Color.GREEN);
int width = getWidth();
int height = getHeight();
if (width / COLS > height / ROWS){
cellSize = height / (ROWS + 1);
}
else {
cellSize = width / (COLS + 1);
}
hMargin = (width - COLS*cellSize)/2;
vMargin = (height - ROWS*cellSize)/2;
for(int x=0;x<COLS;x++){
for(int y=0;y<ROWS;y++){
if(cells[x][y].topWall){
canvas.drawLine(
x*cellSize,
y*cellSize,
(x+1)*cellSize,
y*cellSize,
wallPaint);
}
if(cells[x][y].leftWall){
canvas.drawLine(
x*cellSize,
y*cellSize,
x*cellSize,
(y+1)*cellSize,
wallPaint);
}
if(cells[x][y].bottomWall){
canvas.drawLine(
x*cellSize,
(y+1)*cellSize,
(x+1)*cellSize,
(y+1)*cellSize,
wallPaint);
}
if(cells[x][y].rightWall){
canvas.drawLine(
(x+1)*cellSize,
y*cellSize,
(x+1)*cellSize,
(y+1)*cellSize,
wallPaint);
}
}
}
float margin = cellSize/20;
canvas.drawRect(
player.col*cellSize+margin,
player.row*cellSize+margin,
(player.col+1)*cellSize-margin,
(player.row+1)*cellSize-margin,
playerPaint
);
canvas.drawRect(
exit.col*cellSize+margin,
exit.row*cellSize+margin,
(exit.col+1)*cellSize-margin,
(exit.row+1)*cellSize-margin,
exitPaint
);
}
private void movePlayer(Direction direction){
switch (direction){
case UP :
if(!player.topWall)
player = cells[player.col][player.row-1];
break;
case DOWN :
if(!player.bottomWall)
player = cells[player.col][player.row+1];
break;
case LEFT :
if(!player.leftWall)
player = cells[player.col-1][player.row];
break;
case RIGHT :
if(!player.rightWall)
player = cells[player.col+1][player.row];
break;
}
invalidate();
}
#Override
public boolean onTouchEvent(MotionEvent event) {
if(event.getAction() == MotionEvent.ACTION_DOWN)
return true;
if(event.getAction() == MotionEvent.ACTION_MOVE){
float x = event.getX();
float y = event.getY();
float playerCenterX = hMargin + (player.col+0.5f)*cellSize;
float playerCenterY = vMargin + (player.col+0.5f)*cellSize;
float dx = x - playerCenterX;
float dy = y - playerCenterY;
float absDx = Math.abs(dx);
float absDy = Math.abs(dy);
if(absDx > cellSize || absDy > cellSize){
if(absDx > absDy){
if(dx>0){
movePlayer(Direction.RIGHT);
}else{
movePlayer(Direction.LEFT);
}
}
else{
if(dy>0){
movePlayer(Direction.DOWN);
}else{
movePlayer(Direction.UP);
}
}
}
return true;
}
return super.onTouchEvent(event);
}
private static class Cell{
boolean
topWall = true,
leftWall = true,
bottomWall = true,
rightWall = true,
visited = false;
int col, row;
public Cell(int col, int row) {
this.col = col;
this.row = row;
}
}
}
I try to do it with bitmap but when I start the app, it crash.
I'am working on Pacman clone with Java and libGDX
How to make Pacman move by pressing one button?
Here is my code for moving, but I think it's not the best option:
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.BitmapFont;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.graphics.g2d.TextureAtlas;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.math.Vector2;
public class Hero {
private int rightBorder;
private int leftBorder;
private int top;
private int bottom;
private GameController gc;
private float cellX;
private float cellY;
private TextureRegion texture;
private float speed;
private boolean isPressedD;
private boolean isPressedA;
private boolean isPressedW;
private boolean isPressedS;
private float offset;
private StringBuilder stringBuilder;
private int score;
public Hero(TextureAtlas atlas, GameController gc){
this.texture = atlas.findRegion("Pacman");
this.cellX = 1;
this.cellY = 1;
this.speed = 5f;
this.isPressedD = false;
this.isPressedA = false;
this.isPressedS = false;
this.isPressedW = false;
this.offset = 36;
this.stringBuilder = new StringBuilder();
this.score = 0;
this.gc = gc;
this.leftBorder = 0;
this.rightBorder = 15;
this.top = 8;
this.bottom = 0;
}
public void update(float dt){
movement(dt);
checkBounds();
}
private void checkBounds(){
if (cellX > rightBorder){
cellX = rightBorder;
}
if (cellX < leftBorder){
cellX = leftBorder;
}
if (cellY > top){
cellY = top;
}
if (cellY < bottom){
cellY = bottom;
}
// if (position.x > 1280 - offset){
// position.x = 1280 - offset;
// }
// if (position.x < 0 + offset){
// position.x = 0 + offset;
// }
// if (position.y > 720 - offset){
// position.y = 720 - offset;
// }
// if (position.y < 0 + offset){
// position.y = 0 + offset;
// }
}
public void movement(float dt){
if (Gdx.input.isKeyJustPressed(Input.Keys.D)){
isPressedD = true;
isPressedA = false;
isPressedS = false;
isPressedW = false;
}
if (Gdx.input.isKeyJustPressed(Input.Keys.A)){
isPressedD = false;
isPressedA = true;
isPressedS = false;
isPressedW = false;
}
if (Gdx.input.isKeyJustPressed(Input.Keys.S)){
isPressedD = false;
isPressedA = false;
isPressedS = true;
isPressedW = false;
}
if (Gdx.input.isKeyJustPressed(Input.Keys.W)){
isPressedD = false;
isPressedA = false;
isPressedS = false;
isPressedW = true;
}
if (isPressedA){
cellX -= speed * dt;
}
if (isPressedD){
cellX += speed * dt;
}
if (isPressedS){
cellY -= speed * dt;
}
if (isPressedW){
cellY += speed * dt;
}
}
public void renderGUI(SpriteBatch batch, BitmapFont font){
stringBuilder.setLength(0);
stringBuilder.append("Score: " + score);
font.draw(batch, stringBuilder, 10, 700);
}
public void render(SpriteBatch batch){
batch.draw(texture, cellX * GameMap.CELL_SIZE, cellY * GameMap.CELL_SIZE);
}
}
Here is moving method directly:
public void movement(float dt){
if (Gdx.input.isKeyJustPressed(Input.Keys.D)){
isPressedD = true;
isPressedA = false;
isPressedS = false;
isPressedW = false;
}
if (Gdx.input.isKeyJustPressed(Input.Keys.A)){
isPressedD = false;
isPressedA = true;
isPressedS = false;
isPressedW = false;
}
if (Gdx.input.isKeyJustPressed(Input.Keys.S)){
isPressedD = false;
isPressedA = false;
isPressedS = true;
isPressedW = false;
}
if (Gdx.input.isKeyJustPressed(Input.Keys.W)){
isPressedD = false;
isPressedA = false;
isPressedS = false;
isPressedW = true;
}
if (isPressedA){
cellX -= speed * dt;
}
if (isPressedD){
cellX += speed * dt;
}
if (isPressedS){
cellY -= speed * dt;
}
if (isPressedW){
cellY += speed * dt;
}
}
It's working but I can't ckeck collisions with walls.
How to change method for moving?
I need to press button and release immediately.
No need to create booleans and then do checks on them. Just check if the key is pressed and then put your code in that if statement.
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.BitmapFont;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.graphics.g2d.TextureAtlas;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.math.Vector2;
public class Hero {
private int rightBorder;
private int leftBorder;
private int top;
private int bottom;
private GameController gc;
private float cellX;
private float cellY;
private TextureRegion texture;
private float speed;
private float offset;
private StringBuilder stringBuilder;
private int score;
public Hero(TextureAtlas atlas, GameController gc){
this.texture = atlas.findRegion("Pacman");
this.cellX = 1;
this.cellY = 1;
this.speed = 5f;
this.offset = 36;
this.stringBuilder = new StringBuilder();
this.score = 0;
this.gc = gc;
this.leftBorder = 0;
this.rightBorder = 15;
this.top = 8;
this.bottom = 0;
}
public void update(float dt){
movement(dt);
checkBounds();
}
private void checkBounds(){
if (cellX > rightBorder){
cellX = rightBorder;
}
if (cellX < leftBorder){
cellX = leftBorder;
}
if (cellY > top){
cellY = top;
}
if (cellY < bottom){
cellY = bottom;
}
// if (position.x > 1280 - offset){
// position.x = 1280 - offset;
// }
// if (position.x < 0 + offset){
// position.x = 0 + offset;
// }
// if (position.y > 720 - offset){
// position.y = 720 - offset;
// }
// if (position.y < 0 + offset){
// position.y = 0 + offset;
// }
}
public void movement(float dt){
if (Gdx.input.isButtonPressed(Input.Keys.D)){
cellX += speed * dt;
}
else if (Gdx.input.isButtonPressed(Input.Keys.A)){
cellX -= speed * dt;
}
else if (Gdx.input.isButtonPressed(Input.Keys.S)){
cellY -= speed * dt;
}
else if (Gdx.input.isButtonPressed(Input.Keys.W)){
cellY += speed * dt;
}
}
public void renderGUI(SpriteBatch batch, BitmapFont font){
stringBuilder.setLength(0);
stringBuilder.append("Score: " + score);
font.draw(batch, stringBuilder, 10, 700);
}
public void render(SpriteBatch batch){
batch.draw(texture, cellX * GameMap.CELL_SIZE, cellY * GameMap.CELL_SIZE);
}
}
I'm creating a 2D java game and ran into a nullpointer exception. Whenever I call my render in the playstate class, it throws the exception. I had previously rendered the Font file and got it to work when commenting out the player object references. The player "linkformatted.png" file is able to load after trying and catching, but the nullpointer exception stays. Changing the values didn't work.
public class PlayState extends GameState {
private Font font;
private Player player;
public PlayState(GameStateManager gsm) {
super(gsm);
font = new Font("font/ZeldaFont.png", 16, 16);
player = new Player(new Sprite("entity/linkformatted.png"), new Vector2f(100, 100), 32);
}
public void update() {
player.update();
}
public void input(MouseHandler mouse, KeyHandler key) {
player.input(mouse, key);
}
public void render(Graphics2D g) {
Sprite.drawArray(g, font, "YOU", new Vector2f(100, 100), 32, 32, 16, 0);
player.render(g);
}
}
public class Sprite {
private BufferedImage SPRITESHEET = null;
private BufferedImage[][] spriteArray;
private final int TILE_SIZE = 32;
public int w;
public int h;
private int wSprite;
private int hSprite;
public Sprite(String file) {
w = TILE_SIZE;
h = TILE_SIZE;
System.out.println("Loading: " + file + "...");
SPRITESHEET = loadSprite(file);
wSprite = SPRITESHEET.getWidth() / w;
hSprite = SPRITESHEET.getHeight() / h;
loadSpriteArray();
}
public Sprite(String file, int w, int h) {
this.w = w;
this.h = h;
System.out.println("Loading: " + file + "...");
SPRITESHEET = loadSprite(file);
wSprite = SPRITESHEET.getWidth() / w;
hSprite = SPRITESHEET.getHeight() / h;
loadSpriteArray();
}
public void setSize(int width, int height) {
setWidth(width);
setHeight(height);
}
public void setWidth(int i) {
w = i;
wSprite = SPRITESHEET.getWidth() / w;
}
public void setHeight(int i) {
h = i;
hSprite = SPRITESHEET.getHeight() / h;
}
public int getWidth() {
return w;
}
public int getHeight() {
return h;
}
private BufferedImage loadSprite(String file) {
BufferedImage sprite = null;
try {
sprite = ImageIO.read(getClass().getClassLoader().getResourceAsStream(file));
} catch(Exception e) {
System.out.println("Error: could not load file: " + file);
}
return sprite;
}
public void loadSpriteArray() {
spriteArray = new BufferedImage[wSprite][hSprite];
for(int x = 0; x < wSprite; x++) {
for(int y = 0; y < hSprite; y++) {
spriteArray[x][y] = getSprite(x, y);
}
}
}
public BufferedImage getSpriteSheet() {
return SPRITESHEET;
}
public BufferedImage getSprite(int x, int y) {
return SPRITESHEET.getSubimage(x * w, y * h, w, h);
}
public BufferedImage[] getSpriteArray(int i) {
return spriteArray[i];
}
public BufferedImage[][] getSpriteArray2(int i) {
return spriteArray;
}
public static void drawArray(Graphics2D g, ArrayList<BufferedImage> img, Vector2f pos, int width, int height, int xOffset, int yOffset) {
float x = pos.x;
float y = pos.y;
for(int i = 0; i < img.size(); i++) {
if(img.get(i) != null) {
g.drawImage(img.get(i), (int) x, (int) y, width, height, null);
}
x += xOffset;
y += yOffset;
}
}
public static void drawArray(Graphics2D g, Font f, String word, Vector2f pos, int width, int height, int xOffset, int yOffset) {
float x = pos.x;
float y = pos.y;
for(int i = 0; i < word.length(); i++ ) {
if(word.charAt(i) != 32); // the space
g.drawImage(f.getFont(word.charAt(i)), (int) x, (int) y, width, height, null);
x += xOffset;
y += yOffset;
}
}
}
public class Animation {
private BufferedImage[] frames;
private int currentFrame;
private int numFrames;
private int count;
private int delay;
private int timesPlayed;
public Animation(BufferedImage[] frames) {
timesPlayed = 0;
setFrames(frames);
}
public Animation() {
timesPlayed = 0;
}
public void setFrames(BufferedImage[] frames) {
frames = frames;
currentFrame = 0;
timesPlayed = 0;
delay = 2;
numFrames = frames.length;
}
public void setDelay(int i) { delay = i;}
public void setFrame(int i) { currentFrame = i;}
public void setNumFrames(int i) { numFrames = i;}
public void update() {
if(delay == -1) return;
count++;
if(count == delay) {
currentFrame++;
count = 0;
}
if(currentFrame == numFrames) {
currentFrame = 0;
timesPlayed++;
}
}
public int getDelay() {
return delay;
}
public int getFrame() {
return currentFrame;
}
public int getCount() {
return count;
}
public BufferedImage getImage() {
return frames[currentFrame];
}
public boolean hasPlayedOnce() {
return timesPlayed > 0;
}
public boolean hasPlayed(int i) {
return timesPlayed == i;
}
}
public class Player extends Entity {
public Player(Sprite sprite, Vector2f origin, int size) {
super(sprite, origin, size);
}
public void move() {
if(up) {
dy -= acc;
if(dy < -maxSpeed) {
dy = -maxSpeed;
}
} else {
if(dy < 0) {
dy += deacc;
if(dy > 0) {
dy = 0;
}
}
}
if(down) {
dy += acc;
if(dy < maxSpeed) {
dy = maxSpeed;
}
} else {
if(dy > 0) {
dy -= deacc;
if(dy < 0) {
dy = 0;
}
}
}
if(left) {
dx -= acc;
if(dx < -maxSpeed) {
dy = -maxSpeed;
}
} else {
if(dx < 0) {
dx += deacc;
if(dx > 0) {
dx = 0;
}
}
}
if(right) {
dx += acc;
if(dx > maxSpeed) {
dy = maxSpeed;
}
} else {
if(dx > 0) {
dx -= deacc;
if(dx < 0) {
dx = 0;
}
}
}
}
public void update() {
super.update();
move();
pos.x = dx;
pos.y = dy;
}
#Override
public void render(Graphics2D g) {
g.drawImage(ani.getImage(), (int) (pos.x), (int) (pos.y), size, size, null);
}
public void input(MouseHandler mouse, KeyHandler key) {
if(key.up.down) {
up = true;
} else {
up = false;
}
if(key.down.down) {
down = true;
} else {
down = false;
}
if(key.left.down) {
left = true;
} else {
left = false;
}
if(key.right.down) {
right = true;
} else {
right = false;
}
if(key.attack.down) {
attack = true;
} else {
attack = false;
}
}
}
Here is what is printed:
Loading: entity/linkformatted.png...
Exception in thread "GameThread" java.lang.NullPointerException
at com.zwellis.game.graphics.Animation.getImage(Animation.java:62)
at com.zwellis.game.entity.Player.render(Player.java:82)
at com.zwellis.game.states.PlayState.render(PlayState.java:34)
at com.zwellis.game.states.GameStateManager.render(GameStateManager.java:71)
at com.zwellis.game.GamePanel.render(GamePanel.java:133)
at com.zwellis.game.GamePanel.run(GamePanel.java:90)
at java.base/java.lang.Thread.run(Thread.java:834)
Here is what happens when I made another file to display the image:
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.*;
public class ImageInFrame {
public static void main(String[] args) throws IOException {
String path = "entity/linkformatted.png";
File file = new File(path);
BufferedImage image = ImageIO.read(file);
JLabel label = new JLabel(new ImageIcon(image));
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.getContentPane().add(label);
f.pack();
f.setLocation(200,200);
f.setVisible(true);
}
}
Here is what happens:
Exception in thread "main" javax.imageio.IIOException: Can't read input file!
at java.desktop/javax.imageio.ImageIO.read(ImageIO.java:1308)
at ImageInFrame.main(ImageInFrame.java:11)
Here is also the github link
https://github.com/xfyktcl/ZwellisKnight.git
I'm trying to make a doodle jump game and currently I cant find a way to make the still image change to leg image once it lands on the ground and then change back to still. It kind of does that for one side but not not for both. I've tried using nested if, but then it wouldn't detect the button press. Here's the code:
GameObject game;
PImage doodle;
void setup() {
size(640, 800);
smooth(4);
frameRate(10);
doodle = loadImage("https://i.imgur.com/ytwebph.png");
game = new Doodle(new PVector(width/2, height-doodle.height*2), doodle);
game.setWidthAndHeight(new PVector(width, height));
}
void draw() {
background(200);
game.display();
game.move();
}
void keyPressed() {
game.setMove(keyCode, true);
}
void keyReleased() {
game.setMove(keyCode, false);
}
protected class Doodle extends GameObject {
protected float velocityY, gravity, time;
protected float groundPosition;
protected int facing = 0; //0 = right; 1 = left
protected Doodle(PVector position, PImage picture) {
super(position, picture);
gravity = 20;
time = 0.4;
velocityY = 35*gravity*time;
super.setSpeed(10);
groundPosition = position.y - picture.height;
}
public void move() {
if (isRight || position.y < groundPosition) {
this.picture = doodleImg[0];
facing = 0;
} else if (isLeft || position.y < groundPosition) {
this.picture = doodleImg[2];
facing = 1;
}
position.x = position.x + speed*(int(isRight) - int(isLeft));
//border control
if (position.x+picture.width/2 <= 0) {
position.x = this.getWidthAndHeight().x-picture.width/2;
} else if (position.x+picture.width/2 >= this.getWidthAndHeight().x) {
position.x = 0-picture.width/2;
}
//jump
velocityY -= gravity * time;
position.y -= velocityY * time;
if (position.y > groundPosition) {
if (facing == 0) {
this.picture = doodleImg[1];
} else if (facing == 1) {
this.picture = doodleImg[3];
}
position.y = groundPosition;
velocityY = 35;
}
}
}
public class GameObject {
public PVector position, widthAndHeight;
public int size, speed;
public PImage picture;
public boolean isLeft, isRight;
public PImage[] doodleImg = new PImage[6];
public GameObject(PVector position, PImage picture) {
this.position = position;
this.picture = picture;
widthAndHeight = new PVector(0, 0);
speed = 1;
//0,1 right; 2,3 left; 4,5 shoot;
doodleImg[0] = loadImage("https://i.imgur.com/ytwebph.png");
doodleImg[1] = loadImage("https://i.imgur.com/Y0cFSFK.png");
doodleImg[2] = loadImage("https://i.imgur.com/FL3IhU5.png");
doodleImg[3] = loadImage("https://i.imgur.com/YuqWihj.png");
}
public void move() {
position.x = 0;
}
public void display() {
image(picture, position.x, position.y);
}
public boolean setMove(int keycode, boolean isPressed) {
switch(keycode) {
case LEFT:
return isLeft = isPressed;
case RIGHT:
return isRight = isPressed;
default:
return isPressed;
}
}
protected PVector getWidthAndHeight() {
return widthAndHeight;
}
void setSpeed(int speed) {
this.speed = speed;
}
public void setWidthAndHeight(PVector newWidthAndHeight) {
widthAndHeight = newWidthAndHeight;
}
}
First set the facing state, dependent on the isRight and isLeft:
if (isRight) {
facing = 0;
} else if (isLeft) {
facing = 1;
}
The set the image dependent on the state of facing and the vertical position position.y:
if (position.y < groundPosition) {
this.picture = doodleImg[facing==0 ? 0 : 2];
} else {
this.picture = doodleImg[facing==0 ? 1 : 3];
}
public void move() {
if (isRight) {
facing = 0;
} else if (isLeft) {
facing = 1;
}
if (position.y < groundPosition) {
this.picture = doodleImg[facing==0 ? 0 : 2];
} else {
this.picture = doodleImg[facing==0 ? 1 : 3];
}
position.x = position.x + speed*(int(isRight) - int(isLeft));
//border control
if (position.x+picture.width/2 <= 0) {
position.x = this.getWidthAndHeight().x-picture.width/2;
} else if (position.x+picture.width/2 >= this.getWidthAndHeight().x) {
position.x = 0-picture.width/2;
}
//jump
velocityY -= gravity * time;
position.y -= velocityY * time;
if (position.y > groundPosition) {
position.y = groundPosition;
velocityY = 35;
}
}
I am making an app where balls fall from the top of the screen to the bottom of the screen, and the user has to touch a certain area to make the balls disappear. However, when the balls fall, they appear to stutter as the fall down the screen. Here is the entire code for the project:
public class GameActivity extends Activity implements View.OnTouchListener {
MyBringBack ourSurfaceView;
Paint p;
float x, y, secondX, secondY;
int firstRun;
Bitmap green, red, blue, purple, white;
int currentColor;
ArrayList<Ball> balls = new ArrayList<>();
Paint buttonPaint;
Boolean thingFirstRun;
int score;
Model model;
int cHeight, cWidth;
int nextBallSpeed;
int totalBalls;
int countBalls;
int buttonState = 0;
public final static int BUTTON_NONE = 0;
public final static int BUTTON_LEFT = 1;
public final static int BUTTON_RIGHT = 2;
public final static int BUTTON_BOTH = 3;
class Ball {
public Ball(int x, int y, int s, int color, Bitmap b) {
xCord = x;
yCord = y;
speed = s;
this.color = color;
passedLineYet = false;
bitmap = b;
}
public int xCord;
public int yCord;
public int speed;
public int color;
public boolean passedLineYet;
public Bitmap bitmap;
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
red = BitmapFactory.decodeResource(getResources(), R.drawable.redcircle);
blue = BitmapFactory.decodeResource(getResources(), R.drawable.bluecircle);
green = BitmapFactory.decodeResource(getResources(), R.drawable.greencircle);
purple = BitmapFactory.decodeResource(getResources(), R.drawable.purplecircle);
white = BitmapFactory.decodeResource(getResources(), R.drawable.white);
secondX = secondY = -1;
cHeight = 0;
cWidth = 0;
countBalls = 0;
nextBallSpeed = 60;
p = new Paint();
p.setColor(Color.WHITE);
p.setTextSize(200);
ourSurfaceView = new MyBringBack(this);
ourSurfaceView.setOnTouchListener(this);
setContentView(ourSurfaceView);
model = new Model();
score = 0;
(new Thread(model)).start();
thingFirstRun = false;
currentColor = Color.GREEN;
buttonPaint = new Paint();
buttonPaint.setColor(currentColor);
buttonPaint.setStrokeWidth(10);
buttonPaint.setStyle(Paint.Style.FILL);
firstRun = 0;
}
public boolean correctColor(Ball b) {
if (currentColor == b.color) {
return true;
}
return false;
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
return true;
}
#Override
protected void onPause() {
super.onPause();
ourSurfaceView.pause();
}
#Override
protected void onResume() {
super.onResume();
ourSurfaceView.resume();
}
#Override
public boolean onTouch(View v, MotionEvent event) {
try {
switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_POINTER_DOWN:
float xEvent = event.getX(event.getPointerId(event.getActionIndex()));
float yEvent = event.getY(event.getPointerId(event.getActionIndex()));
if (yEvent > cHeight / 4 * 3) {
if (xEvent < cWidth / 2) {
buttonState |= BUTTON_LEFT;
}
if (xEvent > cWidth / 2) {
buttonState |= BUTTON_RIGHT;
}
}
break;
case MotionEvent.ACTION_POINTER_UP:
case MotionEvent.ACTION_UP:
try {
xEvent = event.getX(event.getPointerId(event.getActionIndex()));
yEvent = event.getY(event.getPointerId(event.getActionIndex()));
} catch (Exception e) {
xEvent = event.getX();
yEvent = event.getY();
}
if (yEvent > cHeight / 4 * 3) {
if (xEvent < cWidth / 2) {
buttonState &= ~BUTTON_LEFT;
}
if (xEvent > cWidth / 2) {
buttonState &= ~BUTTON_RIGHT;
}
}
break;
}
switch (buttonState) {
case BUTTON_LEFT:
currentColor = Color.RED;
break;
case BUTTON_RIGHT:
currentColor = Color.BLUE;
break;
case BUTTON_BOTH:
currentColor = Color.MAGENTA;
break;
case BUTTON_NONE:
currentColor = Color.GREEN;
break;
}
buttonPaint.setColor(currentColor);
Log.v("BUTTON STATE", buttonState + "");
Log.v("BUTTON COLOR", currentColor + "");
return true;
} catch (Exception e) {
}
return true;
}
public class Model extends Thread implements Runnable {
#Override
public void run() {
while (true) {
try {
Thread.sleep(1000 / 240);
} catch (InterruptedException e) {
e.printStackTrace();
}
if (countBalls % nextBallSpeed == 0) {
int temp = (int) (Math.random() * 4);
if (temp == 0) {
balls.add(new Ball((int) (Math.random() * (cWidth - red.getWidth())), 0 - red.getHeight(), cHeight / 800, Color.RED, red));
} else if (temp == 1) {
balls.add(new Ball((int) (Math.random() * (cWidth - red.getWidth())), 0 - green.getHeight(), cHeight / 800, Color.GREEN, green));
} else if (temp == 2) {
balls.add(new Ball((int) (Math.random() * (cWidth - blue.getWidth())), 0 - blue.getHeight(), cHeight / 800, Color.BLUE, blue));
} else if (temp == 3) {
balls.add(new Ball((int) (Math.random() * (cWidth - purple.getWidth())), 0 - purple.getHeight(), cHeight / 800, Color.MAGENTA, purple));
}
totalBalls++;
}
if (totalBalls < 10) {
nextBallSpeed = 30;
} else if (totalBalls < 30) {
nextBallSpeed = 25;
} else if (totalBalls < 50) {
nextBallSpeed = 20;
} else if (totalBalls < 80) {
nextBallSpeed = 15;
} else if (totalBalls < 150) {
nextBallSpeed = 10;
} else {
nextBallSpeed = 5;
}
for (int i = 0; i < balls.size(); i++) {
int h = cHeight;
balls.get(i).yCord += balls.get(i).speed;
}
for (int i = 0; i < balls.size(); i++) {
try {
if (balls.get(i).yCord + green.getHeight() > ((double) cHeight * .75) && !balls.get(i).passedLineYet) {
balls.get(i).passedLineYet = true;
boolean b = correctColor(balls.get(i));
if (b) {
balls.remove(i);
score++;
}
if (!b) {
}
} else if (balls.get(i).yCord > cHeight) {
balls.remove(i);
score -= 5;
}
} catch (Exception ignored) {
}
}
countBalls++;
}
}
public boolean correctColor(Ball b) {
if (currentColor == b.color) {
return true;
}
return false;
}
}
public class MyBringBack extends SurfaceView implements Runnable {
SurfaceHolder ourHolder;
Thread ourThread = null;
boolean isRunning = false;
public MyBringBack(Context context) {
super(context);
ourHolder = getHolder();
}
public void pause() {
isRunning = false;
while (true) {
try {
ourThread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
break;
}
ourThread = null;
}
public void resume() {
isRunning = true;
ourThread = new Thread(this);
ourThread.start();
}
#Override
public void run() {
while (isRunning) {
try {
Thread.sleep(1000 / 240);
} catch (InterruptedException e) {
e.printStackTrace();
}
if (!ourHolder.getSurface().isValid()) {
continue;
}
//NE
Bitmap tempCanvasBitmap = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888);
Canvas tempCanvas = new Canvas();
tempCanvas.setBitmap(tempCanvasBitmap);
//NEND
//Canvas canvas = ourHolder.lockCanvas();
tempCanvas.drawColor(Color.BLACK);
if (firstRun == 0) {
cHeight = tempCanvas.getHeight();
cWidth = tempCanvas.getWidth();
red = getResizedBitmap(red, tempCanvas.getWidth() / 12, tempCanvas.getWidth() / 12);
green = getResizedBitmap(green, tempCanvas.getWidth() / 12, tempCanvas.getWidth() / 12);
blue = getResizedBitmap(blue, tempCanvas.getWidth() / 12, tempCanvas.getWidth() / 12);
purple = getResizedBitmap(purple, tempCanvas.getWidth() / 12, tempCanvas.getWidth() / 12);
white = getResizedBitmap(white, cHeight / 4 * 3, cWidth / 20);
firstRun = 1;
totalBalls = 0;
}
//canvas.drawBitmap(white, );
tempCanvas.drawRect(0, tempCanvas.getHeight() * 3 / 4, tempCanvas.getWidth(), tempCanvas.getHeight(), buttonPaint);
for (int i = 0; i < balls.size(); i++) {
try {
tempCanvas.drawBitmap(balls.get(i).bitmap, balls.get(i).xCord, balls.get(i).yCord, null);
} catch (Exception ignored) {
}
}
Rect r = new Rect();
p.getTextBounds(score + "", 0, (score + "").length(), r);
tempCanvas.drawText(score + "", cWidth - r.width() - 20, r.height() + 20, p);
Canvas canvas = ourHolder.lockCanvas();
canvas.drawBitmap(tempCanvasBitmap, 0, 0, p);
ourHolder.unlockCanvasAndPost(canvas);
}
}
}
public static Bitmap getResizedBitmap(Bitmap bm, int newHeight, int newWidth) {
int width = bm.getWidth();
int height = bm.getHeight();
float scaleWidth = ((float) newWidth) / width;
float scaleHeight = ((float) newHeight) / height;
// create a matrix for the manipulation
Matrix matrix = new Matrix();
// resize the bit map
matrix.postScale(scaleWidth, scaleHeight);
// recreate the new Bitmap
Bitmap resizedBitmap = Bitmap.createBitmap(bm, 0, 0, width, height, matrix, false);
return resizedBitmap;
}
}
I have created animations before, but without the use of a Runnable (all code in the onDraw() method). Perhaps the issue is with that.
Does anyone know why this stuttering might be occurring?
Use This:
Add the class member fields, replace your run(), and add primeCanvas() method.
boolean isPrimed = false;
Canvas canvas;
#Override
public void run() {
while(isRunning) {
if (!ourHolder.getSurface().isValid())
continue;
canvas = ourHolder.lockCanvas();
if(!isPrimed)
primeCanvas();
canvas.drawColor(Color.BLACK);
canvas.drawRect(0, canvas.getHeight() * 3 / 4, canvas.getWidth(), canvas.getHeight(), buttonPaint);
for(int i = 0; i < balls.size(); i ++)
canvas.drawBitmap(balls.get(i).bitmap, balls.get(i).xCord, balls.get(i).yCord, null);
Rect r = new Rect();
p.getTextBounds(score + "", 0, (score + "").length(), r);
canvas.drawText(score + "", cWidth - r.width() - 20, r.height() + 20, p);
ourHolder.unlockCanvasAndPost(canvas);
}
}
private void primeCanvas() {
cHeight = canvas.getHeight();
cWidth = canvas.getWidth();
red = getResizedBitmap(red, canvas.getWidth()/12, canvas.getWidth()/12);
green = getResizedBitmap(green, canvas.getWidth()/12, canvas.getWidth()/12);
blue = getResizedBitmap(blue, canvas.getWidth()/12, canvas.getWidth()/12);
purple = getResizedBitmap(purple, canvas.getWidth()/12, canvas.getWidth()/12);
white = getResizedBitmap(white, cHeight / 4 * 3, cWidth / 20);
firstRun = 1;
totalBalls = 0;
}