I want to create an infinite bouncing ball. For now I'm just trying to make the bouncing on Y (up & down).
This is my GameWorld class, you can see there is a method collides to detect the collision but How to make that "circle" go up?
public class GameWorld {
private Circle rond;
private Rectangle rect;
public GameWorld(int midPointY) {
rond = new Circle(100, midPointY - 5, 5);
rect = new Rectangle(0, 200, Gdx.graphics.getWidth(), 5);
}
public void update(float delta) {
if(collides(rond)){
}else
rond.y++;
}
public boolean collides(Circle rond) {
if (rect.y < rond.y + (rond.radius)*2) {
return (Intersector.overlaps(rond, rect));
}
return false;
}
public Circle getRond() {
return rond;
}
public Rectangle getRect() {
return rect;
}
}
Of course, I have another class GameRenderer that rendere these two objects
Typically with any kind of physics you want to store the speed of an object as well as its position. That way, each time though your update loop you just have to change the y position by the y speed. When the collision occurs, all you need to do is calculate the new yspeed and update rond.
public void update(float delta) {
if(collides(rond)){
rond.yspeed = -rond.yspeed;
}else{
rond.y+=rond.yspeed*delta;
}
}
Related
I'm struggling to set up monster on the map, but all I get is placing it on the camera coordinate. I tried to use Tiled and finally I set up monster where I wanted, but I don't know how to move this monster.
Link to game map, the dragon in right bottom corner is from Enemy class, and the goblin is from Bot class
Here same code from Enemy class
public Enemy() {
img = new Texture(Gdx.files.internal(path));
sprite = new Sprite(img);
batch = new SpriteBatch();
position = new Vector2();
}
public void update(float delta) {
batch.begin();
batch.draw(img, position.x, position.y);
batch.end();
}
And the Bot class, where I get monster from Tiled
public Bot(TextureMapObjectRenderer tiledMapRenderer, String name) {
this.tiledMapRenderer = tiledMapRenderer;
try {
monsterLayer = tiledMapRenderer.getMap().getLayers().get("monster");
monsterObjects = monsterLayer.getObjects();
monster = monsterObjects.get(name);
} catch (Exception ex) {
}
}
public void update(float delta) {
tiledMapRenderer.renderObject(monster);
}
I use TextureMapObject to get X and Y position of the enemy/monster. Also I create method to render MapObject.
public void renderMonster(MapObject object) {
if (object instanceof TextureMapObject) {
TextureMapObject textureMonster = (TextureMapObject) object;
textureMonsters.add(textureMonster);
batch.begin();
batch.draw(textureMonster.getTextureRegion(), textureMonster.getX(), textureMonster.getY());
batch.end();
// move the monster
textureMonster.setX(randomMove(-1, 1).x + textureMonster.getX());
textureMonster.setY(randomMove(-1, 1).y + textureMonster.getY());
}
}
I know that this method is not prefect, but it works.
So I'm trying to create a game and it's my first time. My game is a 2D side scroller and is about the player in space avoiding the incoming meteors. I have successfully managed to get the meteors spawning randomly on the x and y axis off screen and re position once it has gone pass the screen.
But the problem I face now is sometimes the spawn of the meteors will clump together which I don't want. How do I get the meteors to spawn at a certain distance from each other so they don't clump together. I couldn't find any good tutorials or if anyone can point me to the right direction. Below are my codes so far.
Meteor Class
public class Meteors {
private Texture bigMeteor;
private Vector2 posBigMeteor;
private Random yrand;
//Constructor
public Meteors(float x){
bigMeteor = new Texture("meteor.png");
yrand = new Random();
//Spawn location of meteor
posBigMeteor = new Vector2(x, yrand.nextInt(AstroDemo.HEIGHT/2 - bigMeteor.getHeight()));
}
public Texture getBigMeteor() {
return bigMeteor;
}
public Vector2 getPosBigMeteor() {
return posBigMeteor;
}
//Reposition the meteors
public void reposition(float x){
posBigMeteor.set(x, yrand.nextInt(AstroDemo.HEIGHT/2 - bigMeteor.getHeight()));
}
}
PlayState Class
public class PlayState extends State {
//Total meteor count on screen
private static final int METEOR_COUNT = 8;
private Naught naught;
private Texture bg;
private Random xrand;
private Array <Meteors> meteors;
public PlayState(GameStateManager gsm) {
super(gsm);
//Starting co-ordinates of main character (Naught)
naught = new Naught(50, 100);
//Setting viewport of the camera
cam.setToOrtho(false, AstroDemo.WIDTH/2, AstroDemo.HEIGHT/2);
bg = new Texture("bg.png");
xrand = new Random();
meteors = new Array <Meteors>();
//Spawn meteors randomly off screen
for (int i = 1; i <= METEOR_COUNT; i++){
meteors.add(new Meteors(AstroDemo.WIDTH/2 + (xrand.nextInt(300))));
}
}
#Override
protected void handleInput() {
//If screen/mouse is held
if(Gdx.input.isTouched()){
//Main Character jumps/flys
naught.jump();
}
}
#Override
public void update(float dt) {
handleInput();
naught.update(dt);
//If meteors are left side of the screen, re-position to the right side of the screen
for(Meteors meteor : meteors){
if (cam.position.x - (cam.viewportWidth/2) > meteor.getPosBigMeteor().x + meteor.getBigMeteor().getWidth()){
meteor.reposition(meteor.getPosBigMeteor().x + (AstroDemo.WIDTH/2 + 20 + (xrand.nextInt(300))));
}
}
cam.position.x = naught.getPosition().x + 80;
cam.update();
}
#Override
public void render(SpriteBatch sb) {
//Adjust the spritebatch for co-ordinate system in relation to camera
sb.setProjectionMatrix(cam.combined);
sb.begin();
//Draw background where the camera is
sb.draw(bg, cam.position.x - (cam.viewportWidth/2), 0);
sb.draw(naught.getTexture(), naught.getPosition().x, naught.getPosition().y);
for (Meteors meteor : meteors) {
sb.draw(meteor.getBigMeteor(), meteor.getPosBigMeteor().x, meteor.getPosBigMeteor().y);
}
sb.end();
}
#Override
public void dispose() {
}
}
create a array of predefined value for your y position and then get value randomly from that array.
or
Divide height into sub portion then get random value from that portion so that each random value not collide with other value.
In the picture below you can see that I have drawn a black circle into the screen and in the code I have tried to get the black circle to match the coordinates of the clear circle which is my physics body which is completely working.
My problem is when I move the clear circle around my map the black circle stays there in the corner. The black circle moves a little about a few pixels so it seems its mmoves around a bit but very scaled down and I don't know why. Thanks.
public void update(float dt){
handleInput(dt);
world.step(1 / 60f, 6, 2);
player.update(dt);
camX();
gameCam.update();
renderer.setView(gameCam);
}
#Override
public void render(float delta) {
update(delta);
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
game.batch.setProjectionMatrix(hud.stage.getCamera().combined);
hud.stage.draw();
renderer.render();
b2dr.render(world, gameCam.combined);
game.batch.begin();
game.batch.draw(ball,player.getX() , player.getY(), 70, 70);
game.batch.end();
}
public void camX(){
gameCam.position.x = gamePort.getWorldWidth() / 2;
if(player.b2Body.getPosition().x >= gamePort.getWorldWidth() / 2){
gameCam.position.x = player.b2Body.getPosition().x;
}
}
public class Character extends Sprite {
public World world;
public Body b2Body;
public float x;
public float y;
public Character(World world){
this.world = world;
defineMario();
}
public void update(float dt) {
setPosition(b2Body.getPosition().x,b2Body.getPosition().y );
}
You set the Batch's projection matrix to the UI's camera for UI drawing, but you never change it to the gameCamera's projection before drawing your game elements. Before the game.batch.begin(); line you need to add game.batch.setProjectionMatrix(gameCamera.combined);.
By the way, it doesn't make sense for Character to extend Sprite, since you don't use Character for drawing anything, only for tracking a position.
Please try this :
public class Character extends Sprite {
public World world;
public Body b2Body;
public float x;
public float y;
public Character(World world){
this.world = world;
defineMario();
}
public void update(float dt) {
//so the sprite and body will have the same center
setPosition(b2Body.getPosition().x-getWidth()/2, b2Body.getPosition().y- getHeight()/2 );
setCenterOrigin(); // to handle when body does a rotation
}
please, tell me if it works or not in comment
Good luck
Please excuse my bad english. I am having a problem while implementing a 2d camera. I made the camera to follow the player until it reaches near the edge of the game-level, where only the player moves and the camera stops. I made this easily but my problem is that the camera is not proper. The camera continues to move 1 extra pixel every time you reach at the edge of the game-level limit in all four directions (The code I posted only shows horizontal movement. This I did for simplicity). This means if you move 40 times to and fro near the left edge of the game, camera will move 40 extra pixels right! I have no idea how to solve this.
I posted a very simplified version from my original code below and made it as small as i could to show how the program works. Following just moves the player and camera horizontally across the screen.
This is 'theGamePanel' class (it is the main class) :-
public class TheGamePanel extends JPanel implements Runnable, KeyListener
{
private boolean left, right;
private float cameraX, cameraY;
private World world = new World();
private Player player = new Player();
public TheGamePanel()
{
//setting the size of panel
}
public static void main(String[] args)
{
//setting the window
}
public void paint(Graphics g)
{
super.paint(g);
// drawing the game-level and player
g.translate((int)cameraX, (int)cameraY);
world.paint(g);
player.paint(g);
g.translate(-(int)cameraX, -(int)cameraY);
}
public void upd()
{
player.update(left, right, this);
}
#Override
public void run()
{
// game-loop
}
#Override
public void keyPressed(KeyEvent e)
{
int code = e.getKeyCode();
if(code == KeyEvent.VK_LEFT)
{
left = true;
}
if(code == KeyEvent.VK_RIGHT)
{
right = true;
}
}
#Override
public void keyReleased(KeyEvent e)
{
if(e.getKeyCode() == KeyEvent.VK_LEFT)
{
left = false;
}
if(e.getKeyCode() == KeyEvent.VK_RIGHT)
{
right = false;
}
}
#Override
public void keyTyped(KeyEvent e)
{
}
//to set camera position
public void setCameraX(float cameraDx)
{
cameraX += cameraDx;
}
}
This is the 'Player' class. This class is where the player and camera movement takes place. The camera's x and values are then returned to 'TheGamePanel' :-
public class Player
{
private float x, y;
private float dx = 1;
private int width = 32, height = 32;
private float leftLimit, rightLimit;
public Player()
{
//player's initial x and y coordinates
x = 320;
y = 240;
//camera's limit (where the camera needs to stop following player)
leftLimit = x;
rightLimit = 960;
}
public void paint(Graphics g)
{
//for painting the player
g.setColor(Color.GREEN);
g.fillRect((int)x, (int)y, width, height);
}
//to move player and camera
public void update(boolean left, boolean right, TheGamePanel panel)
{
if(left == true)
{
x -= dx;
if(x > leftLimit && x < rightLimit)
{
panel.setCameraX(dx);
}
}
if(right == true)
{
x += dx;
if(x > leftLimit && x < rightLimit)
{
panel.setCameraX(-dx);
}
}
}
}
And lastly, the 'World' class. This class is used to simply paint a big map(level) in the background :-
public class World
{
private BufferedImage map;
private int tileWd = 32, tileHi = 32;
public World()
{
try
{
map = ImageIO.read(new File("map1.png"));
}
catch (IOException e)
{
e.printStackTrace();
}
}
public void paint(Graphics g)
{
//simply paints a game-level in the background
}
}
If anything not understandable please tell. I will add more details.
Consider the case where the player is standing near the right edge of the map. One quick tap on the "right" key moves him out of the camera-follow area so the camera doesn't move. One quick tap on the "left" key moves him back into the camera-follow area. The camera will be moved "dx" units to the left. This will have the effect of the player slowly creeping closer to the right edge of the playing field, if I'm correct.
(To find bugs like this, I generally litter the code with System.out.println messages. If there's a lot of messages, I write them to a file and do text searches on keywords)
you have a location for your camera (cameraX,cameraY) but nothing for the player?
just create a location for player (playerX,playerY)
change the paint like:
public void paint(Graphics g)
{
super.paint(g);
// drawing the game-level and player
g.translate((int)cameraX, (int)cameraY);
world.paint(g);
g.translate((int)playerX, (int)playerY);
player.paint(g);
g.translate(-(int)(playerX+cameraX), -(int)(playerY+cameraY));
}
and when player come near borders don't move camera and only player.
I believe the following change fixes the problem:
Player class:
//to move player and camera
public void update(boolean left, boolean right, TheGamePanel panel)
{
if(left == true)
{
x -= dx;
if(x > leftLimit && x < rightLimit)
{
panel.setCameraX(dx);
}
}
if(right == true)
{
if(x > leftLimit && x < rightLimit)
{
panel.setCameraX(-dx);
}
x += dx; // Only change: moved this line AFTER the if block
}
}
By testing x after changing it when moving left and before changing it when moving right you compensate for the error that was otherwise accumulating every time you reached one of the boundaries.
Anyway I suggest you to change your approach to the problem in order to make your code easier to maintain and more flexible. One way to do that is to calculate the camera position based on current player's position on every frame.
Note: The line g.translate(-(int)cameraX, -(int)cameraY); in the paint() method of TheGamePanel class is unnecessary once the method translate(int, int) is not incremental.
Regards
Trying to figure out why my Android game crashes whenever the player touches an animated coin. I have attached an image of the LogCat and my code is below (NOTE: all game objects in ![Renderer] are in an arraylist called toRender. the 2 coins in the game are currently held in the 3rd and 4th position in the list). Renderer and Coin classes respectively:
public class Renderer extends ApplicationAdapter {
private SpriteBatch batch;
private Texture background;
private ArrayList<GameObject> toRender;
private Timer timer;
private float delta;
private Game game;
public Renderer(ArrayList<GameObject> toRender) {
batch = new SpriteBatch();
background = new Texture(Gdx.files.internal("background2.png"));
this.toRender = toRender;
timer = Timer.getInstance();
}
public void collect() {
// for every object in toRender (an arraylist of objects)
for (GameObject o : toRender) {
// if player collides with/collects an object
if (Player.getInstance(null).hasCollected(o)) {
// if its the first coin that he collides with, dispose it
if (o.equals((Coin) toRender.get(3))) {
((Coin) toRender.get(3)).dispose();
}
// if its the second coin that he collides with, dispose it
if (o.equals((Coin) toRender.get(4))) {
((Coin) toRender.get(4)).dispose();
}
}
}
}
public void beginRendering() {
delta = Timer.getInstance().getTime();
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
batch.begin();
batch.draw(background, 0, 0, Gdx.graphics.getWidth(),
Gdx.graphics.getHeight());
timer.drawTime(batch);
for (GameObject object : toRender) {
object.update();
boolean objectIsntCoin = !(object.equals(toRender.get(3)) ||
object.equals(toRender.get(4))); //the 2 coins are in the 3rd and 4th position in the array list
// draw every object's sprite apart from coin, since coin should render the animation rather than the sprite
if (objectIsntCoin) {
object.draw(batch);
}
}
collect();
((Flag) toRender.get(toRender.size() - 1)).drawLevelComplete(batch);
// if the coin exists (i.e. hasn't been disposed), render the animation
if (((Coin) toRender.get(3)).checkExists()) {
((Coin) toRender.get(3)).render(delta);
}
// if the coin exists (i.e. hasn't been disposed), render the animation
if (((Coin) toRender.get(4)).checkExists()) {
((Coin) toRender.get(4)).render(delta);
}
batch.end();
}
}
public class Coin extends GameObject implements Screen {
private SpriteBatch batch;
private Animation animation;
private float time;
private float xPos;
private float yPos;
private Rectangle objectRect;
private boolean exists;
public Coin(Sprite spr, float xPos, float yPos, float radius) {
super(spr, xPos, yPos, radius);
this.xPos = xPos;
this.yPos = yPos;
batch = new SpriteBatch();
objectRect = new Rectangle(getxPos(), getyPos(), getSprite().getWidth(), getSprite().getHeight());
exists = true;
time = 0;
show();
}
public Rectangle getRect() {
return objectRect;
}
public void render(float delta) {
// TODO Auto-generated method stub
batch.begin();
batch.draw(animation.getKeyFrame(time += delta), xPos, yPos);
batch.end();
}
#Override
public void resize(int width, int height) {
}
#Override
public void show() {
animation = new Animation(1 / 8f,
new TextureRegion(new Texture(Gdx.files.internal("coin1.png"))),
new TextureRegion(new Texture(Gdx.files.internal("coin2.png"))),
new TextureRegion(new Texture(Gdx.files.internal("coin3.png"))),
new TextureRegion(new Texture(Gdx.files.internal("coin4.png"))),
new TextureRegion(new Texture(Gdx.files.internal("coin5.png"))),
new TextureRegion(new Texture(Gdx.files.internal("coin6.png"))),
new TextureRegion(new Texture(Gdx.files.internal("coin7.png"))),
new TextureRegion(new Texture(Gdx.files.internal("coin8.png"))));
animation.setPlayMode(Animation.PlayMode.LOOP);
}
#Override
public void hide() {
}
#Override
public void pause() {
}
#Override
public void resume() {
}
#Override
public void dispose() {
batch.dispose();
exists = false;
}
public boolean checkExists() {
return exists;
}
}
LogCat:1
So the errors that the LogCat point to:
1)dispose() method in Coin:
batch.dispose();
2)collect() method in Renderer:
if(o.equals((Coin) toRender.get(3))) {
3)beginRendering() method in Renderer:
for (GameObject object : toRender) {
Does anyone know why my program is crashing? I just want the animated coin to disappear when the Player touches it. Currently the coin DOES disappear, the application just shuts down immediately after though. Have been stuck on this for a while so any insight is highly appreciated.
Thank you in advance.
First, I want to mention that downcasting the objects in toRender like you are is both dangerous and indicates there is a flaw in your design. Additionally, you'll notice that equals(Object) accepts an Object as an argument; you don't need to cast it to Coin.
Anyway, the reason your program is crashing is explained in the IllegalArgumentException message,
buffer not allocated with newUnsafeByteBuffer or already disposed.
You're trying to dispose your Coin's batch when it has already been disposed.
In your collect() method, you loop through the objects, and you dispose of their batches, but the Coin objects themselves are never removed from your toRender list. So, the next time collect() is called, it will loop through those same Coin objects and try to dispose of them again, and an exception is thrown.
The solution is to remove the Coin objects from your toRender list when they no longer belong in your game's scene. However, you can't remove an element from a list while you're iterating over it, as this would disrupt the loop. Instead, remove them like so:
public void collect() {
// Holds the Coins we want to remove from toRender
final Collection<GameObject> toRemove = new LinkedList<>();
for (GameObject o : toRender) {
if (Player.getInstance(null).hasCollected(o)) {
if (o.equals(toRender.get(3))) {
final Coin coin = (Coin) toRender.get(3);
coin.dispose();
toRemove.add(coin);
}
if (o.equals(toRender.get(4))) {
final Coin coin = (Coin) toRender.get(4);
coin.dispose();
toRemove.add(coin);
}
}
}
// Remove the collected Coins
toRender.removeAll(toRemove);
}