Why doesnt my program draw the houses from the arrayList? - java

I want in my game to draw houses (huis = house) that fall continuesly at the sides of the screen. (On the grass as the 'world' moves downwards.'
But,having this code, and no trouble in the logcat i dont know why it doesnt draw the houses.
The 'main flow' of this code goes as follows: I created an arraylist that holds the house.png. Then through a for loop it adds a house when there is some space between it.
package com.mygdx.Papermadness;
import java.util.ArrayList;
import com.badlogic.gdx.ApplicationListener;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.InputAdapter;
import com.badlogic.gdx.audio.Music;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.Texture.TextureWrap;
import com.badlogic.gdx.graphics.g2d.Sprite;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.graphics.glutils.ShapeRenderer;
import com.badlogic.gdx.graphics.glutils.ShapeRenderer.ShapeType;
import com.badlogic.gdx.math.Rectangle;
import com.badlogic.gdx.math.Vector2;
public class Papermadness extends InputAdapter implements ApplicationListener {
private SpriteBatch huisBatch;
private Texture huisTexture;
private SpriteBatch batch;
private Sprite sprite;
private SpriteBatch spriteBatch;
private Sprite huisSprite;
private Texture spriteTexture;
private float scrollTimer = 0.0f;
private float huisVelocity = 200f;
private float huisLinksY = 2100;
private float huisLinksX = 0;
private float huisRechtsY = 2100;
private float huisRechtsX = 903;
private Sprite huis;
private ArrayList<Sprite> huisArray = new ArrayList<Sprite>();
Rectangle bounds;
Player player;
Paper paper;
ShapeRenderer sr;
#Override
public void create() {
player = new Player(new Vector2(50, 100), new Vector2(100, 100));
paper = new Paper(new Vector2(Gdx.input.getX(),Gdx.graphics.getHeight()-Gdx.input.getY()), new Vector2(50, 50));
sr = new ShapeRenderer();
spriteBatch = new SpriteBatch();
huisBatch = new SpriteBatch();
huisTexture = new Texture("huis.png");
huisSprite = new Sprite(huisTexture);
spriteTexture = new Texture("b2.png");
spriteTexture.setWrap(TextureWrap.Repeat, TextureWrap.Repeat);
sprite = new Sprite(spriteTexture);
sprite.setSize(Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
batch = new SpriteBatch();
}
#Override
public void render() {
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
float delta = Gdx.graphics.getDeltaTime();
scrollTimer += Gdx.graphics.getDeltaTime();
if (scrollTimer > 2f)
scrollTimer = 0.0f;
sprite.setV(scrollTimer + 2);
sprite.setV2(scrollTimer);
player.update();
paper.update();
spriteBatch.begin();
sprite.draw(spriteBatch);
for (int i = 0; i < huisArray.size(); i++) {
huisArray.get(i).setY(huisArray.get(i).getY() - huisVelocity * delta);
if (huisArray.get(i).getY() <= 200) {
huisArray.remove(i);
i--;
}
}
if (huisArray.size() > 0 && huisArray.get(0).getY() < 1200) {
addNewHuis();
}
huisBatch.begin();
for (int i = 0; i < huisArray.size(); i++) {
huisBatch.draw(huisArray.get(i), huisArray.get(i).getX(), huisArray.get(i).getY());
}
huisLinksY -= huisVelocity * delta;
huisRechtsY -= huisVelocity * delta;
batch.begin();
player.draw(batch);
paper.draw(batch);
batch.end();
sr.begin(ShapeType.Filled);
sr.setColor(Color.BLUE);
sr.setColor(Color.RED);
sr.setColor(Color.YELLOW);
sr.rect(Gdx.input.getX(), Gdx.graphics.getHeight() - Gdx.input.getY(), paper.getSize().x,
paper.getSize().y);
sr.end();
}
private void addNewHuis() {
huis = new Sprite();
huis.setY(1800);
huisArray.add(0, huis);
}
#Override
public void resize(int width, int height) {
// TODO Auto-generated method stub
}
#Override
public void pause() {
// TODO Auto-generated method stub
}
#Override
public void resume() {
// TODO Auto-generated method stub
}
#Override
public void dispose() {
// TODO Auto-generated method stub
}
}
Any help would be appreciated.

From my point of view, your house array is empty - so it does not have anything to draw. You create huisArray, but you do not add anything to it. So when you render() is called first, huisArray.size() == 0 is true.
for (int i = 0; i < huisArray.size(); i++) { //you do not step into this piece of code.
huisArray.get(i).setY(huisArray.get(i).getY() - huisVelocity * delta);
if (huisArray.get(i).getY() <= 200) {
huisArray.remove(i);
i--;
}
}
Then, you want to add a house if there are some houses there. But it's still empty so you do not add anything.
if (huisArray.size() > 0 && huisArray.get(0).getY() < 1200) {
addNewHuis();
}
And you attempt to draw still empty array:
huisBatch.begin();
for (int i = 0; i < huisArray.size(); i++) { //you do not step into this piece of code either
huisBatch.draw(huisArray.get(i), huisArray.get(i).getX(), huisArray.get(i).getY());
}
Solution: Add one-two huisSprite to huisArray in create().
Hope it helps :)

Related

Java - How to center a Render after a Scale Operation with the good mouse Position

In the code below, when I move the wheel of the mouse, the square is zooming in or out and I always detect the square position everywhere in the screen if my mouse go inside it, even if the map is scrolling.
That's really great :)
If I change the boolean "centerScreen" to true, I can zoom and the square is always in the center of the screen.
It is really very great ...
... but the mouse detection is not good :(
How can I modify my code to zoom in or out with the Render still in center of screen but with a perfect mouse detection with the square ?
Thanks for your help !
Here is my full "clean code" -- work with copy paste (in 3 class) --
Main Class
package main;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.RenderingHints;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class ZoomDemo extends JPanel
{
private static final long serialVersionUID = 1L;
private Rectangle2D square;
private Mouse mouse;
private ScrollMap scrollMap;
private static int screenWidth;
private static int screenHeight;
private static int centerScreenWidth;
private static int centerScreenHeight;
private static boolean centerScreen;
private List<Point> listStar = new ArrayList<Point>();
public static void main(String[] args)
{
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(800, 800);
frame.setLocationRelativeTo(null);
screenWidth = frame.getWidth();
screenHeight = frame.getHeight();
centerScreenWidth = screenWidth / 2;
centerScreenHeight = screenHeight / 2;
centerScreen = false;
ZoomDemo zoomDemo = new ZoomDemo();
frame.add(zoomDemo);
frame.setVisible(true);
}
public ZoomDemo()
{
mouse = new Mouse();
addMouseListener(mouse);
addMouseMotionListener(mouse);
addMouseWheelListener(mouse);
scrollMap = new ScrollMap(mouse, screenWidth, screenHeight);
int centerX = (int) getCenter(0, screenWidth, 50, true);
int centerY = (int) getCenter(0, screenHeight, 50, true);
square = new Rectangle2D.Double(centerX, centerY, 50, 50);
Random rand = new Random();
for (int i = 0; i < 50; i++)
{
int x = rand.nextInt(screenWidth);
int y = rand.nextInt(screenHeight);
listStar.add(new Point(x, y));
}
}
#Override
public void paint(Graphics g)
{
Graphics2D g2d = (Graphics2D) g.create();
/* Optimization */
g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_SPEED);
g2d.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_SPEED);
g2d.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_OFF);
g2d.setRenderingHint(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_DISABLE);
/* Background */
g2d.setColor(Color.GRAY);
g2d.fillRect(0, 0, this.getWidth(), this.getHeight());
/* Translatation center -- it is working, but mouse detection is not good */
if (centerScreen)
g2d.translate(centerScreenWidth, centerScreenHeight);
/* Listener Wheel Mouse for zooming and translation */
mouse.zoom(g2d);
/* Restore Translatation center */
if (centerScreen)
g2d.translate(-centerScreenWidth, -centerScreenHeight);
render(g2d);
g2d.dispose();
//#formatter:off
try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); }
//#formatter:on
repaint();
}
public void render(Graphics2D g2d)
{
/* Ask for scroll */
isScrolling(g2d);
/* Mouse Detection */
int xMouse = (int) (mouse.pMousePosition.x - scrollMap.getMapX());
int yMouse = (int) (mouse.pMousePosition.y - scrollMap.getMapY());
boolean detection = square.contains(xMouse, yMouse);
/* Graphic render */
g2d.setColor(Color.WHITE);
for (int i = 0; i < listStar.size(); i++)
g2d.fillRect(listStar.get(i).x, listStar.get(i).y, 4, 4);
g2d.setColor(detection ? Color.red : Color.black);
g2d.fill(square);
/* End of Scroll */
endScrolling(g2d);
}
private void isScrolling(Graphics2D g2d)
{
/* If Mouse on edge, so change value for scrolling */
scrollMap.scrolling();
/* Translation scrolling */
g2d.translate(scrollMap.getMapX(), scrollMap.getMapY());
}
private void endScrolling(Graphics2D g2d)
{
g2d.translate(-scrollMap.getMapX(), -scrollMap.getMapY());
}
public float getCenter(float startXZone, float longueurZone, float longueurElem, boolean round)
{
float s = startXZone + (longueurZone - longueurElem) / 2f;
return (round) ? Math.round(s) : s;
}
}
Mouse Class
package main;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.event.MouseWheelEvent;
import java.awt.event.MouseWheelListener;
import java.awt.geom.AffineTransform;
import java.awt.geom.NoninvertibleTransformException;
public class Mouse implements MouseMotionListener, MouseWheelListener, MouseListener
{
public Point pMousePosition = new Point();
public double scaleCoef;
public double inverseScaleCoef;
public boolean clic;
private AffineTransform affineScale;
private AffineTransform inverseScale;
public Mouse()
{
scaleCoef = 1;
inverseScaleCoef = 1;
transform();
}
private void transform()
{
affineScale = AffineTransform.getScaleInstance(scaleCoef, scaleCoef);
//#formatter:off
try { inverseScale = affineScale.createInverse(); } catch (NoninvertibleTransformException e) { }
//#formatter:on
}
public void zoom(Graphics2D g2)
{
transform();
g2.transform(affineScale);
}
#Override
public void mouseWheelMoved(MouseWheelEvent e)
{
if (e.getScrollType() == MouseWheelEvent.WHEEL_UNIT_SCROLL)
{
scaleCoef -= (0.1 * e.getWheelRotation());
scaleCoef = Math.max(0.1, scaleCoef);
inverseScaleCoef = 1d / scaleCoef;
}
}
#Override
public void mouseMoved(MouseEvent e)
{
pMousePosition = e.getPoint();
inverseScale.transform(pMousePosition, pMousePosition);
}
#Override
public void mousePressed(MouseEvent e)
{
clic = true;
}
#Override
public void mouseReleased(MouseEvent e)
{
clic = false;
}
#Override
public void mouseClicked(MouseEvent e)
{
}
#Override
public void mouseEntered(MouseEvent e)
{
}
#Override
public void mouseExited(MouseEvent e)
{
}
#Override
public void mouseDragged(MouseEvent e)
{
}
}
(Optional)
Scroll class
package main;
public class ScrollMap
{
private float mapX = 0;
private float mapY = 0;
private int speedScroll = 1;
private int edgeDetection = 70;
private int screenWidth;
private int screenHeight;
private Mouse mouse;
public ScrollMap(Mouse mouse, int screenWidth, int screenHeight)
{
this.mouse = mouse;
this.screenWidth = screenWidth;
this.screenHeight = screenHeight;
}
/**
* Scrolling ecran
*/
public void scrolling()
{
double scale = mouse.inverseScaleCoef;
/* Mouse to Right */
if ((mouse.pMousePosition.x > screenWidth * scale - edgeDetection))
{
for (int k = 0; k < speedScroll; k++)
moveMapToRight();
}
/* Mouse to Left */
else if ((mouse.pMousePosition.x < edgeDetection * scale))
{
for (int k = 0; k < speedScroll; k++)
moveMapToLeft();
}
/* Mouse to Down */
if ((mouse.pMousePosition.y < edgeDetection * scale))
{
for (int k = 0; k < speedScroll; k++)
moveMaptoDown();
}
/* Mouse to Up */
else if ((mouse.pMousePosition.y > screenHeight * scale - edgeDetection))
{
for (int k = 0; k < speedScroll; k++)
moveMapToUp();
}
}
public float moveMapToRight()
{
return mapX--;
}
public float moveMapToLeft()
{
return mapX++;
}
public float moveMapToUp()
{
return mapY--;
}
public float moveMaptoDown()
{
return mapY++;
}
public float getMapY()
{
return mapY;
}
public float getMapX()
{
return mapX;
}
}

Code for Sprite in Different Class

I want to make a game wherein when the main character sprite's X coordinate is less than the middle of the screen, he moves to the right and when it's more than the middle of the screen, he moves to the left. The sprite's animation changes when he is moving and when he is still (after reaching its destination). What I want to know is how can I do this when the sprite and its code for animation is in one class and the code for changing its X coordinate is in another class? Is it best to draw the same sprite in every class? How can I change the sprite when it is moving horizontally and when it is still? I plan to separate the code for what the sprite's actions will be in different classes because i want to call them randomly. Here is my code for the sprite's animation and i have no class for changing the x coordinate yet :
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Screen;
import com.badlogic.gdx.audio.Music;
import com.badlogic.gdx.audio.Sound;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.Animation;
import com.badlogic.gdx.graphics.g2d.Sprite;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.jpfalmazan.ninjaassault.NinjaAssault;
public class MainScreen implements Screen {
private static final int FRAME_COLS = 3;
private static final int FRAME_ROWS = 2;
Animation walkAnimation;
Texture walkSheet = new Texture ("ninjaWalk.png");
TextureRegion[] walkFrames;
TextureRegion currentFrame;
Texture holdStart;
float stateTime;
public Texture background;
private NinjaAssault game;
private Music BackgroundSFX;
public float screenWidth = Gdx.graphics.getWidth();
public float screenHeight = Gdx.graphics.getHeight();
float x = screenWidth/2;
float y = screenHeight/2;
public float walkSheetWidth = walkSheet.getWidth();
public float walkSheetHeight = walkSheet.getHeight();
public MainScreen (NinjaAssault game){
this.game = game;
}
#Override
public void show(){
background = new Texture("BGBlue.png");
holdStart = new Texture ("HoldStart.png");
BackgroundSFX = Gdx.audio.newMusic(Gdx.files.internal("data/RADWIMPS-iindesuka.mp3"));
TextureRegion[][] tmp = TextureRegion.split(walkSheet, (int )walkSheetWidth/FRAME_COLS, (int) walkSheetHeight/FRAME_ROWS);
walkFrames = new TextureRegion[FRAME_COLS*FRAME_ROWS];
int index = 0;
for (int i = 0; i < FRAME_ROWS; i++){
for (int j = 0; j < FRAME_COLS; j++) {
walkFrames[index++] = tmp[i][j];
}
}
walkAnimation = new Animation(0.0887f, walkFrames);
stateTime = 0f;
}
#Override
public void render(float delta) {
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
stateTime += Gdx.graphics.getDeltaTime();
currentFrame = walkAnimation.getKeyFrame(stateTime, true);
float hsWidth = holdStart.getWidth();
float hsHeight = holdStart.getHeight();
float currentFrameWidth = (float)(screenHeight*0.15);
float currentFrameHeight = (float)(screenHeight*0.15);
float holdStartWidth = (float)(screenWidth * 0.75);
game.batch.begin();
game.batch.draw(background,0,0, screenWidth,screenHeight);
BackgroundSFX.play();
game.batch.draw(currentFrame, x -currentFrameWidth/2, 0,currentFrameWidth,currentFrameHeight);
game.batch.draw(holdStart, (screenWidth / 2 - (holdStartWidth / 2)), (float) (screenHeight * 0.5), holdStartWidth, holdStartWidth * (hsHeight / hsWidth));
game.batch.end();
}
#Override
public void resize(int width, int height) {
}
#Override
public void pause() {
}
#Override
public void resume() {
}
#Override
public void hide() {
}
#Override
public void dispose() {
BackgroundSFX.dispose();
background.dispose();
walkSheet.dispose();
holdStart.dispose();
}
}
I tried to research on how to do this but the answers I get wasn't that helpful.
Simplest way is to create a Player class and put all the code for the animation and frames in there. Then give it a way to save its position. Like a vector or just a float for the x coordinate. Or even better, use a Rectangle. A rectangle will make moving and collision detection much easier.
Something like this:
public class Player{
private Animation walkAnimation;
private Texture walkSheet;
private TextureRegion[] walkFrames;
private TextureRegion currentFrame;
private float stateTime;
private Rectangle bound; //used for positioning and collision detection
public Player(float x, float y, float width, float height){
bound = new Rectangle();
bound.x = x;
bound.y = y;
bound.width = width;
bound.height = height;
walkSheet = new Texture ("ninjaWalk.png");
TextureRegion[][] tmp = TextureRegion.split(walkSheet,(int)walkSheetWidth/FRAME_COLS, (int) walkSheetHeight/FRAME_ROWS);
walkFrames = new TextureRegion[FRAME_COLS*FRAME_ROWS];
int index = 0;
for (int i = 0; i < FRAME_ROWS; i++){
for (int j = 0; j < FRAME_COLS; j++) {
walkFrames[index++] = tmp[i][j];
}
}
walkAnimation = new Animation(0.0887f, walkFrames);
stateTime = 0f;
}
public rectangle getBound(){
return bound;
}
public void update(float delta){
statetime += delta;
currentFrame = walkAnimation.getKeyFrame(stateTime, true);
}
public TextureRegion getCurrentFrame(){
return currentFrame;
}
}
This is just a quick untested example.
You say you want to move the player from another class. I don't know how you plan to do that, but all you need to do to move the player is to manipulate the x and y of the bound.
Just some other comments on you code:
#Override
public void render(float delta) {
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
player.update(delta); // to update the player
/***
* This does not have to be set every single frame. Move it to show()
*
float hsWidth = holdStart.getWidth();
float hsHeight = holdStart.getHeight();
float currentFrameWidth = (float)(screenHeight*0.15);
float currentFrameHeight = (float)(screenHeight*0.15);
float holdStartWidth = (float)(screenWidth * 0.75);
****************************************************/
BackgroundSFX.play(); // I am sure you don't need to start playing this every single frame? 60 times a second.
game.batch.begin();
game.batch.draw(background,0,0, screenWidth,screenHeight);
game.batch.draw(player.getCurrentFrame(), player.getBound().x, player.getbound().y, player.getBound().width, player.getBound().height)
game.batch.draw(holdStart, (screenWidth / 2 - (holdStartWidth / 2)), (float) (screenHeight * 0.5), holdStartWidth, holdStartWidth * (hsHeight / hsWidth));
game.batch.end();
}

How to detect collision of player and ground in overlap2d and libgdx

I am following a video tutorial on Youtube called "Making Simple Sidescroller with Overlap2D and libGDX - Tutorial - 003".
I see on video he use raycast to detect collision. But when i try to follow, the player fall through the ground while in the video the player can stop on the ground.
Here is the link to download my libgdx project, and my overlap2d project for you to check.
Here is the code of Player.java
package com.test.superninja;
import com.badlogic.ashley.core.Entity;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input;
import com.uwsoft.editor.renderer.scripts.IScript;
import com.uwsoft.editor.renderer.components.TransformComponent;
import com.uwsoft.editor.renderer.components.DimensionsComponent;
import com.uwsoft.editor.renderer.utils.ComponentRetriever;
import com.uwsoft.editor.renderer.physics.PhysicsBodyLoader;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.physics.box2d.Fixture;
import com.badlogic.gdx.physics.box2d.RayCastCallback;
import com.badlogic.gdx.physics.box2d.World;
public class Player implements IScript {
private Entity player;
private TransformComponent transformComponent;
private DimensionsComponent dimensionsComponent;
private Vector2 speed;
private float gravity = -500f;
private float jumpSpeed = 170f;
private World world;
public Player(World world) {
this.world = world;
}
#Override
public void init(Entity entity) {
player = entity;
transformComponent = ComponentRetriever.get(entity, TransformComponent.class);
dimensionsComponent = ComponentRetriever.get(entity, DimensionsComponent.class);
speed = new Vector2(50, 0);
}
#Override
public void act(float delta) {
//transformComponent.scaleY = 0.5;
if (Gdx.input.isKeyPressed(Input.Keys.LEFT)) {
transformComponent.x -= speed.x * delta;
transformComponent.scaleX = -1f;
}
if (Gdx.input.isKeyPressed(Input.Keys.RIGHT)) {
transformComponent.x += speed.x * delta;
transformComponent.scaleX = 1f;
}
if (Gdx.input.isKeyJustPressed(Input.Keys.SPACE)) {
speed.y = jumpSpeed;
}
speed.y += gravity * delta;
transformComponent.y += speed.y * delta;
/*
if (transformComponent.y < 16f){
speed.y = 0;
transformComponent.y = 16f;
}
*/
}
private void rayCast() {
float rayGap = dimensionsComponent.height / 2;
// Ray size is the exact size of the deltaY change we plan for this frame
float raySize = -(speed.y) * Gdx.graphics.getDeltaTime();
//if(raySize < 5f) raySize = 5f;
// only check for collisions when moving down
if (speed.y > 0) return;
// Vectors of ray from middle middle
Vector2 rayFrom = new Vector2((transformComponent.x + dimensionsComponent.width / 2) * PhysicsBodyLoader.getScale(), (transformComponent.y + rayGap) * PhysicsBodyLoader.getScale());
Vector2 rayTo = new Vector2((transformComponent.x + dimensionsComponent.width / 2) * PhysicsBodyLoader.getScale(), (transformComponent.y - raySize) * PhysicsBodyLoader.getScale());
// Cast the ray
world.rayCast(new RayCastCallback() {
#Override
public float reportRayFixture(Fixture fixture, Vector2 point, Vector2 normal, float fraction) {
// Stop the player
speed.y = 0;
// reposition player slightly upper the collision point
transformComponent.y = point.y / PhysicsBodyLoader.getScale() + 0.1f;
return 0;
}
}, rayFrom, rayTo);
}
public float getX() {
return transformComponent.x;
}
public float getY() {
return transformComponent.y;
}
public float getWidth() {
return dimensionsComponent.width;
}
#Override
public void dispose() {
}
}
Here is SuperNinja.java
package com.test.superninja;
import com.badlogic.gdx.ApplicationAdapter;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.GL20;
import com.uwsoft.editor.renderer.SceneLoader;
import com.badlogic.gdx.utils.viewport.Viewport;
import com.badlogic.gdx.utils.viewport.FitViewport;
import com.uwsoft.editor.renderer.utils.ItemWrapper;
import com.uwsoft.editor.renderer.components.additional.ButtonComponent;
import com.badlogic.gdx.graphics.OrthographicCamera;
public class SuperNinja extends ApplicationAdapter {
private SceneLoader sceneLoader;
private Viewport viewport;
private ItemWrapper root;
private Player player;
private UIStage uiStage;
#Override
public void create () {
viewport = new FitViewport(266, 160);
sceneLoader = new SceneLoader();
sceneLoader.loadScene("MainScene", viewport);
root = new ItemWrapper(sceneLoader.getRoot());
player = new Player(sceneLoader.world);
root.getChild("player").addScript(player);
uiStage = new UIStage(sceneLoader.getRm());
}
#Override
public void render () {
Gdx.gl.glClearColor(0.5f, 0.5f, 0.5f, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
sceneLoader.getEngine().update(Gdx.graphics.getDeltaTime());
uiStage.act();
uiStage.draw();
((OrthographicCamera)viewport.getCamera()).position.x=player.getX()+player.getWidth()/2f;
}
}
Here is UIStage.java
package com.uwsoft.platformer;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.scenes.scene2d.Actor;
import com.badlogic.gdx.scenes.scene2d.InputEvent;
import com.badlogic.gdx.scenes.scene2d.Stage;
import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener;
import com.badlogic.gdx.scenes.scene2d.utils.ClickListener;
import com.uwsoft.editor.renderer.data.CompositeItemVO;
import com.uwsoft.editor.renderer.data.ProjectInfoVO;
import com.uwsoft.editor.renderer.resources.IResourceRetriever;
import com.uwsoft.editor.renderer.scene2d.CompositeActor;
/**
* Created by azakhary on 8/5/2015.
*/
public class UIStage extends Stage {
public UIStage(IResourceRetriever ir) {
Gdx.input.setInputProcessor(this);
ProjectInfoVO projectInfo = ir.getProjectVO();
CompositeItemVO menuButtonData = projectInfo.libraryItems.get("menuButton");
CompositeActor buttonActor = new CompositeActor(menuButtonData, ir);
addActor(buttonActor);
buttonActor.setX(getWidth() - buttonActor.getWidth());
buttonActor.setY(getHeight() - buttonActor.getHeight());
buttonActor.addListener(new ClickListener() {
#Override
public void clicked (InputEvent event, float x, float y) {
System.out.println("Hi");
}
});
}
}
With the help of Xeon, I solved my question. I just forgot to call rayCast() function.
I call raycast() function like this:
#Override
public void act(float delta) {
...
rayCast();
}
And it works. Thank you Xeon very much.

LibGDX - How to slow down update() method?

I'm trying to recreate Space Invaders in LibGDX to get grip on game-developing but when I try to set every enemy (for now they are just squares) to move in sequence the update() method makes them change their postitions way too fast. Is there some way to slow down this rendering on whole project or any other proper way to solve this? I also tried to handle movement in Timer class and scheulde it but it caused memory overload and threads weren't fired in the same time for every object.
package regularmikey.objects;
import java.util.Timer;
import java.util.TimerTask;
import com.badlogic.gdx.graphics.glutils.ShapeRenderer;
import com.badlogic.gdx.graphics.glutils.ShapeRenderer.ShapeType;
public class Aliens {
public float x;
public float y;
public float fx;
public float fy;
public int step_count = 0;
public Aliens(float x, float y) {
this.fx = this.x = x;
this.fy = this.y = y;
};
public void update(float dt){
if(step_count == 10) {
step_count = 0;
y = y - 1;
x = fx;
}
x = x + 3;
step_count++;
};
PlayState class
package regularmikey.gamestates;
import java.util.ArrayList;
import com.badlogic.gdx.graphics.glutils.ShapeRenderer;
import regularmikey.managers.GameStateManager;
import regularmikey.objects.Aliens;
import regularmikey.objects.Bullet;
import regularmikey.objects.Player;
public class PlayState extends GameState {
private Player player;
private ArrayList<Bullet> bullets;
private ArrayList<Aliens> aliens;
private ShapeRenderer sr;
public PlayState(GameStateManager gsm) {
super(gsm);
}
#Override
public void init() {
sr = new ShapeRenderer();
bullets = new ArrayList<Bullet>();
aliens = new ArrayList<Aliens>();
player = new Player(bullets);
spawnAliens();
}
#Override
public void update(float dt) {
player.update(dt);
for(int i = 0; i < aliens.size(); i++) {
aliens.get(i).update(dt);
}
}
public void spawnAliens() {
aliens.clear();
float i, j;
for(j = 100; j <= 510; j = j + 45) {
for(i = 250; i <= 445; i = i + 45) {
aliens.add(new Aliens(j, i));
}
}
}
#Override
public void draw() {
player.draw(sr);
for(int i = 0; i < aliens.size(); i++) {
aliens.get(i).draw(sr);
}
}
#Override
public void handleinput() {
// TODO Auto-generated method stub
}
#Override
public void dispose() {
// TODO Auto-generated method stub
}
}
public void draw(ShapeRenderer sr) {
sr.setColor(1, 1, 1, 1);
sr.begin(ShapeType.Line);
sr.rect(x, y, 30, 30);
sr.end();
};
}
The key here is the dt variable that is passed along with the update() method, which is short for Delta Time.
Delta time is a commonly used factor in game development that represents the time that has passed since the last frame.
I can't exactly make out the way you are making your aliens move about, but the usual way to make entities in your game move smoothly (regardless of the frame rate):
void update(float deltaTime){
this.position = currentPosition + (this.movementSpeed × deltaTime);
}
This doesn't take into consideration the direction in which the entity is moving, amongst others. But that is besides the point of this example.
So, in your case, you could so something like this:
package regularmikey.objects;
import java.util.Timer;
import java.util.TimerTask;
import com.badlogic.gdx.graphics.glutils.ShapeRenderer;
import com.badlogic.gdx.graphics.glutils.ShapeRenderer.ShapeType;
public class Aliens {
public float x;
public float y;
public float fx;
public float fy;
public int step_count = 0;
private float moveTimer;
private float moveTreshold;
public Aliens(float x, float y) {
this.fx = this.x = x;
this.fy = this.y = y;
moveTimer = 0; // This will act as a stopwatch
moveTreshold = 3000; // Alien will move once it passes this treshold
};
public void update(float dt){
// check whether we passed the treshold for moving or not
if(moveTimer += dt; > moveTreshold){
if(step_count == 10) {
step_count = 0;
y = y - 1;
x = fx;
}
x = x + 3;
step_count++;
moveTimer = 0; // reset the timer
}
};

Large Line Strip management in JOGL / OPENGL...?

Im trying to make a Java screensaver of a 3D rotating Lorenz Attractor
Im using java and jogl (OPENGL) to render the graphics...
i have 2 classes one is the main program setup OPENGL etc...
and another that just stores a LinkedList of Point3d's That are the vertex of the line..
Only one new point is added to the List every frame render.....
The problem i am having is render speed is very slow, my question is this...
1. Is there a Better / Easy way of buffering either the screen or the line strip so i only need to draw the last line....
2. Can VBO's be used for LINE_STRIP's and if i have to add one vertex to the buffer every step is this really going to speed things up...?
Its really quite annoying... glBegin()/ glEnd() works fine up to about 100 lines then crashes badly.
Help much needed to speed up render and would be greatly apreaciated.....
Ive added the working code below to get it to work you have to link to JOGL opengl lib's
CODE
LorenzSim.java
import javax.media.opengl.GL;
import javax.media.opengl.GL2;
import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.GLCapabilities;
import javax.media.opengl.GLEventListener;
import javax.media.opengl.GLProfile;
import javax.media.opengl.awt.GLCanvas;
import javax.media.opengl.fixedfunc.GLMatrixFunc;
import javax.media.opengl.glu.GLU;
import java.io.File;
import java.io.IOException;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.SourceDataLine;
import javax.vecmath.Point3d;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.image.*;
import com.jogamp.opengl.util.FPSAnimator;
import com.jogamp.opengl.util.gl2.GLUT;
import java.util.*;
import java.awt.event.*;
import sun.misc.*;
public class LorenzSim implements GLEventListener, KeyListener {
private static final int MIN_X = -20;
private static final int MAX_X = 20;
private static final int MIN_Y = -20;
private static final int MAX_Y = 20;
private static final double MIN_Z = 0;
private static final double MAX_Z = 40;
/**
* #param args
*/
// GLOBAL PARTS
boolean started = false;
int index = 0; // ANIMATOR COUNTER
String consoleLine = "";
// GENERAL OPEN GL
GLProfile glp = null;
GLCapabilities caps = null;
GLCanvas canvas = null;
GraphicsEnvironment ge = null;
GraphicsDevice gd = null;
Frame frame = null;
// GL _ CAM
double camX = 30;
double camY = 30;
double camZ = 50;
Lorenz myLorenz = null;
public LorenzSim ()
{
// GENERAL OPEN GL AND AWT SETUP
glp = GLProfile.getDefault();
caps = new GLCapabilities(glp);
canvas = new GLCanvas(caps);
ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
gd = ge.getDefaultScreenDevice();
frame = new Frame("QuadSim");
frame.setSize(600,600);
//frame.setUndecorated(true);
//gd.setFullScreenWindow(frame);
frame.setVisible(true);
canvas.setSize(frame.getWidth(),frame.getHeight());
frame.add(canvas);
// SETUP EVENT LISTENERS
canvas.addGLEventListener(this);
canvas.addKeyListener(this);
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
frame.dispose();
System.exit(0);
}
});
started = true;
FPSAnimator animator = new FPSAnimator(canvas, 60);
animator.add(canvas);
animator.start();
caps.setDoubleBuffered(true);
myLorenz = new Lorenz();
myLorenz.doSteps(0);
}
public static void main(String[] args) {
// TODO Auto-generated method stub
System.out.println("Welcome to Quad Simulator v0.1 - by Phil Poore");
LorenzSim mySim = new LorenzSim();
}
//############################################
// GL EVENT INTERFACE
//############################################
#Override
public void display(GLAutoDrawable drawable) {
// TODO Auto-generated method stub
if (started)
{
update();
render(drawable);
//System.out.println("Drisplay_index:"+index);
}
}
private void update() {
// TODO Auto-generated method stub
index++;
myLorenz.step();
}
private void render(GLAutoDrawable drawable) {
// TODO Auto-generated method stub
GL2 gl = drawable.getGL().getGL2();
GLU glu = new GLU();
drawable.swapBuffers();
gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
// START OF RENDER CYCLE
setCamera(gl,glu);
drawAxis(gl);
drawBox(gl);
drawLorenz(gl);
drawHUD(gl);
}
private void drawLorenz(GL2 gl) {
// TODO Auto-generated method stub
gl.glBegin(GL.GL_LINE_STRIP);
gl.glColor3f(1.0f, 0.0f, 0.0f);
gl.glLineWidth(0.1f);
for (int i = 0; i < myLorenz.myPoints.size() - 1; i++)
{
//float dx = (float) (myLorenz.myPoints.get(i).x - myLorenz.myPoints.get(i+1).x);
//float dy = (float) (myLorenz.myPoints.get(i).y - myLorenz.myPoints.get(i+1).y);
//float dz = (float) (myLorenz.myPoints.get(i).z - myLorenz.myPoints.get(i+1).z);
//float dc = (Math.abs(dx) + Math.abs(dy) + Math.abs(dz))/3.0f;
//gl.glColor3d(dc,dc,dc);
gl.glVertex3d(
myLorenz.myPoints.get(i).x,
myLorenz.myPoints.get(i).y,
myLorenz.myPoints.get(i).z);
}
gl.glEnd();
}
private void drawBox(GL2 gl) {
// TODO Auto-generated method stub
Point3d a = new Point3d(MIN_X,MIN_Y,MIN_Z);
Point3d b = new Point3d(MAX_X,MIN_Y,MIN_Z);
Point3d c = new Point3d(MAX_X,MAX_Y,MIN_Z);
Point3d d = new Point3d(MIN_X,MAX_Y,MIN_Z);
Point3d aa = new Point3d(MIN_X,MIN_Y,MAX_Z);
Point3d ab = new Point3d(MAX_X,MIN_Y,MAX_Z);
Point3d ac = new Point3d(MAX_X,MAX_Y,MAX_Z);
Point3d ad = new Point3d(MIN_X,MAX_Y,MAX_Z);
gl.glBegin(GL.GL_LINE_STRIP);
gl.glVertex3d(a.x, a.y, a.z);
gl.glVertex3d(b.x, b.y, b.z);
gl.glVertex3d(c.x, c.y, c.z);
gl.glVertex3d(d.x, d.y, d.z);
gl.glVertex3d(a.x, a.y, a.z);
gl.glEnd();
gl.glBegin(GL.GL_LINE_STRIP);
gl.glVertex3d(aa.x, aa.y, aa.z);
gl.glVertex3d(ab.x, ab.y, ab.z);
gl.glVertex3d(ac.x, ac.y, ac.z);
gl.glVertex3d(ad.x, ad.y, ad.z);
gl.glVertex3d(aa.x, aa.y, aa.z);
gl.glEnd();
gl.glBegin(GL.GL_LINES);
gl.glVertex3d(a.x, a.y, a.z);
gl.glVertex3d(aa.x, aa.y, aa.z);
gl.glVertex3d(b.x, b.y, b.z);
gl.glVertex3d(ab.x, ab.y, ab.z);
gl.glVertex3d(c.x, c.y, c.z);
gl.glVertex3d(ac.x, ac.y, ac.z);
gl.glVertex3d(d.x, d.y, d.z);
gl.glVertex3d(ad.x, ad.y, ad.z);
gl.glEnd();
}
private void drawHUD(GL2 gl) {
// TODO Auto-generated method stub
gl.glRasterPos2d(10,10);
gl.glWindowPos2d(10, 10);
gl.glColor3d(0.8, 0.8, 0.8);
GLUT glut = new GLUT();
//DecimalFormat df = new DecimalFormat("#.##");
glut.glutBitmapString(GLUT.BITMAP_8_BY_13,
":");
}
#Override
public void dispose(GLAutoDrawable arg0) {
// TODO Auto-generated method stub
}
#Override
public void init(GLAutoDrawable drawable) {
// TODO Auto-generated method stub
GL2 gl = drawable.getGL().getGL2();
//gl.glOrtho(0,100,-5,25,0,100);
gl.glEnable( GL.GL_LINE_SMOOTH );
gl.glHint( GL.GL_LINE_SMOOTH_HINT, GL.GL_NICEST );
}
#Override
public void reshape(GLAutoDrawable arg0, int arg1, int arg2, int arg3,
int arg4) {
// TODO Auto-generated method stub
}
private void drawAxis(GL2 gl) {
gl.glLineWidth((float) 1.0);
gl.glBegin(GL.GL_LINES);
// X
gl.glColor3f(1, 0, 0);
gl.glVertex3d(0,0,0);
gl.glVertex3d(1,0,0);
// Y
gl.glColor3f(0, 1, 0);
gl.glVertex3d(0,0,0);
gl.glVertex3d(0,1,0);
// Z
gl.glColor3f(0, 0, 1);
gl.glVertex3d(0,0,0);
gl.glVertex3d(0,0,1);
gl.glEnd();
}
private void setCamera(GL2 gl,GLU glu)
{
gl.glMatrixMode(GLMatrixFunc.GL_PROJECTION);
gl.glLoadIdentity();
glu.gluPerspective(120, 1.0, 5, 100);
gl.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
gl.glLoadIdentity();
glu.gluLookAt(camX, camY, camZ,
0.0,0.0 ,0.0 ,
0.0,0.0, 1.0);
gl.glRotated(0.0+index, 0, 0, 1);
// gl.glTranslated(MAX_X-MIN_X, MAX_Y-MIN_Y, MAX_Z-MIN_Z);
}
//############################################
// KEY LISTENER INTERFACE
//############################################
#Override
public void keyPressed(KeyEvent e) {
// TODO Auto-generated method stub
if (e.getKeyCode() == 27)
System.exit(0);
}
#Override
public void keyReleased(KeyEvent e) {
// TODO Auto-generated method stub
}
#Override
public void keyTyped(KeyEvent e) {
// TODO Auto-generated method stub
}
}
Lorenz.java
import javax.vecmath.*;
import java.awt.geom.;
import java.util.;
public class Lorenz {
public static final double rho = 28.0;
public static final double sigma = 10.0;
public static final double beta = 8.0/3.0;
private static final double step = 200.0;
public LinkedList<Point3d> myPoints = null;
public Lorenz ()
{
myPoints = new LinkedList<Point3d>();
Point3d first = new Point3d(0.1,0.1,0.1);
myPoints.add(first);
}
public void step()
{
System.out.println("stepping..."+myPoints.size());
Point3d last = myPoints.get(myPoints.size()-1);
double dx = (sigma * (last.y - last.x))/step;
double dy = ((last.x*(rho-last.z))-last.y)/step;
double dz = ((last.x*last.y - beta*last.z))/step;
Point3d next = new Point3d(last.x+dx,last.y+dy,last.z+dz);
myPoints.add(next);
}
public void doSteps(int count)
{
for (int i = 0; i < count; i++)
{
step();
}
}
public void dump()
{
System.out.println(myPoints.toString());
}
}
Phil
Try creating multiple VBOs for your set of lines. That way you only have to update a smaller number of vertices for each new line and the bulk of your geometry is already (probably) in video memory.
this may sound funny but try to remove the System.out.println() in the step() method. Printing to console is fairly slow/unpredictable in java so don't do this every frame.
to answer your question:
2) VBOs are fast for large(er) datasets and best used with rarely or partly updating data. They can represent any primitive you like, triangles, line strips etc. Adding one vertex every frame is not a good idea since they are allocated statically. You can still use them by predicting the maximum amount of vertices you would like to render and simply allocate this buffer a-priory.
if you decide to use VBOs you will have to make this changes:
- allocate a VBO which will determine the max amount of vertices of the graph
- upload only the new vertices per frame
- stop at max or think about a ringbuffer, but you will probably need an additional buffer used as indexbuffer to implement this
tipp: use JOGL's debug pipeline, it will try to throw an exception as soon as OpenGL sets an error code. This will may help to fix the crash issue you mentioned.
http://michael-bien.com/mbien/entry/jogl_2_composeable_pipline

Categories