Am i implementing this correctly? I'm having issues with the direction my character is in, yet the state manager is working correctly. I'm unsure whether this is the problem. I have my player facing right automatically when constructed yet he faces left.
I have two arrays for both right and left animation inside my assets manager, The original images are facing right, i declare that array and then flip the same image on the left array. Does the left array override the right?
int idleRIndex = 1;
TextureRegion[] idleRight = new TextureRegion[3];
for (int i = 0; i < idleRight.length; i++)
{
idleRight[i] = rubenSprite.findRegion("iframe" + idleRIndex);
idleRIndex++;
}
rubenIdleRight = new Animation(0.2f, idleRight);
int idleLIndex = 1;
TextureRegion[] idleLeft = new TextureRegion[3];
for (int i = 0; i < idleLeft.length; i++)
{
idleLeft[i] = rubenSprite.findRegion("iframe" + idleLIndex);
idleLeft[i].flip(true, false);
idleLIndex++;
}
rubenIdleLeft = new Animation(0.2f, idleLeft);
It seems so after a test. The findRegion("iframe" + idleLIndex) and for the right are returning the same object reference. So I think the flip for the left will also affect the right. Maybe you can create a new TextureRegion object from the atlas. It shouldn't be much overhead. Try:
idleLeft[i] = new TextureRegion(rubenSprite.findRegion("iframe" + idleLIndex));
Then the flip shouldn't affect the right anymore.
Related
If you want the TLDR without context: I need help figuring out how to properly define and fill a data structure from a 2D array for a pathfinding algorithm. Scroll to the bottom for my code.
I'm developing a game (early version available for viewing/playing on my github) For those curious about the map making program specifically, here is a link to that directory on my github.
If you just want to see how the game functions to get a better grasp, here is a video demo.
The game itself loads maps utilizing LUA, and I made a simple map maker to generate Lua using the Swing library in Java.
Basic Premise:
Navigate to the Goal of the map from the designated starting position.
Once a player starts moving, you can't stop or change directions until you hit a wall. Also you can't move diagonally.
Players can make their own maps and challenge their friends.
I want to restrict players to making only valid (winnable) maps to avoid frustration. - How do I best accomplish this in your opinion?
The A* algorithm I believe is my best starting point for a method like this. However, I need to wrap my head around defining a valid path.
My maps in Java are currently represented as a 2D Array of Image Icons. (For now)
The buttons can have 1 of 4 properties:
Empty - represents the floor, IE a normal navigatable part of the map.
Wall - represents a wall, Players will be stopped when coming into contact.
Start - represents where the player will start on the map.
Goal - represents the tile where the player will have completed the map.
Here is what I have (algorithm not included since its currently nothing different from a typical example on wiki)
class Tile {
JLabel payload = null; // wall, empty, goal, start
Tile up = null;
Tile down = null;
Tile left = null;
Tile right = null;
}
// Fill and return a list with the information for each tile on the map
public static ArrayList<Tile> checkMapStatus(JLabel[][] map){
ArrayList<Tile> mapList = new ArrayList<Tile>();
for(int i = 0; i < map.length; i++){
for(int j = 0; j < map.length; j++){
// create the surrounding tiles around the current tile (needs fixing)
Tile tile = new Tile();
Tile tileUp = new Tile();
Tile tileDown = new Tile();
Tile tileLeft = new Tile();
Tile tileRight = new Tile();
tile.payload = map[i][j];
if(map[j + 1] != null) // prevent accessing inexistant array position
tileUp.payload = map[i][j+1];
if(j > 0) // prevent accessing inexistant array position
tileDown.payload = map[i][j-1];
if(i > 0) // prevent accessing inexistant array position
tileLeft.payload = map[i-1][j];
if(map[i + 1] != null) // prevent accessing inexistant array position
tileRight.payload = map[i+1][j];
tile.up = tileUp;
tile.down = tileDown;
tile.left = tileLeft;
tile.right = tileRight;
mapList.add(tile);
}
}
return mapList;
}
Issues with the above code:
I'm creating tile objects that aren't technically connected to eachother right? That is, the up down left and right tiles aren't ever referenced again once created, so I'm creating 5 tiles when really I should only be creating 1 and refering the existing ones. How do I fix this in Java?
Possibility for efficiency? Would it be better for me to only define the wall, goal and starting tiles since the other ones are technically empty space?
What I would do is to start off with a Tile[][] temp variable to help with the objects referencing eachother, and flatten it as you go. It's slightly less efficient, but not enough to worry about if this is just to initialize things.
public static ArrayList<Tile> checkMapStatus(JLabel[][] map){
ArrayList<Tile> mapList = new ArrayList<Tile>();
Tile[][] temp = new Tile[map.length][];
for(int i = 0; i < map.length; i++){
temp[i] = new Tile[map[i].length];
for(int j = 0; j < map.length; j++){
// create the surrounding tiles around the current tile (needs fixing)
Tile tile = new Tile();
temp[i][j] = tile;
tile.payload = map[i][j];
//Just look up and to the left, populate the existing Tiles as you populate the current one
if(i > 0 && j < temp[i-1].length){
tile.up = temp[i-1][j];
temp[i-1][j].down = tile;
}
if(j > 0){
tile.left = temp[i][j-1];
temp[i][j-1].right = tile;
}
mapList.add(tile);
}
}
return mapList;
}
public class Game
{
private EnemyShip enemy1;
private EnemyShip enemy2;
private EnemyShip enemy3;
private PlayerShip player;
/**
* Initialises user's ship and guns
*/
public Game()
{
player = new PlayerShip();
enemy1 = new EnemyShip();
enemy2 = new EnemyShip();
enemy3 = new EnemyShip();
Can I make this enemy1,2,3 to be an array? I want to use enemy on a loop.
Or is there a way to make a loop for variable that is not an array? Like if I run the loop enemy1 will increment and become enemy2.
EnemyShip[] enemies = new EnemyShip[3];
for (int i=0; i<enemies.length; i++) { enemies[i] = new EnemyShip(); }
will give you an array of 3 EnemyShip objects. If the loop you're looking for is one that gives you a different instance variable each iteration then no you can't do that; you need to have them in a collection. However you can simplify the loop if you don't care about the index:
for (EnemyShip enemy : enemies) {
//do something with enemy object
}
As others have suggested, just do:
EnemyShip[] enemies = new EnemyShip[3];
for (int i = 0; i < enemies.length; i++) {
enemies[i] = new EnemyShip();
}
However, I think you should reconsider using an array. Using an array limits you to having, at maximum, as many enemies as will fit into the array.
Do you really know that you want at most 3 enemies at compile-time?
Why not make things more flexible and use a List instead? This will allow you to track as many enemies as you want to create at run-time. So for example, if the player is doing well you create more, if the player is doing poorly you create less.
List<Enemy> enemies = new ArrayList<Enemy>(3); // 3 is the expected capacity
for (int i = 0; i < 3; i++) {
createEnemy();
}
... elsewhere...
public void createEnemy() {
enemies.add(new EnemyShip());
}
Requirements change, particularly in game development. Try to avoid committing to things too early.
I'm writing an application where I show markers on a map using the library Unfolding Maps.
The application lets the user choose a year and depending on that value other markers are shown. This works perfect, but when the user selects another year I can't seem to get the other markers shown.
I've tried to completely renew the map but after that first time it doesn't redraw a map.
Besides that I've tried to add a MarkerManager to the map but then I get errors of OpenGL.
setup function:
public void setup() {
/*
* Provincies, set zoom to 10
*/
size(1000, 800, OPENGL);
this.map = new UnfoldingMap(this, new Microsoft.RoadProvider());
map.zoomAndPanTo(belgie, 8);
map.setPanningRestriction(belgie, 1);
map.setZoomRange(8, 8);
drawOtherMarker();
//map.getMarkerManager(markerRemarck.get(keyM)).enableDrawing();
MapUtils.createDefaultEventDispatcher(this, map);
}
function that creates the MarkerManager and adds it to the map
private void createMarkers(ArrayList<double[]> dataMarker) {
float size = 0;
int i = 0;
ListIterator<double[]> dataIt = dataMarker.listIterator();
ArrayList<SimplePointMarker> markList = new ArrayList<SimplePointMarker>();
while (dataIt.hasNext()) {
double[] element = dataIt.next();
SimplePointMarker point = new SimplePointMarker(new Location(
element[0], element[1]));
if (element[2] > 1000)
size = 120;
else if (element[2] > 100)
size = 60;
else if (element[2] > 10)
size = 30;
else
size = 20;
point.setRadius(size);
point.setColor(color(64,64,64,100));
point.setStrokeColor(color(178,34,34));
point.setStrokeWeight(30);
point.setStrokeWeight(0);
point.setId(Integer.toString(i++));
markList.add(point);
}
MarkerManager man = new MarkerManager(markList);
map.addMarkerManager(man);
}
When the map is drawn and another set of markers must be drawn the following function is called:
public void drawOtherMarker(){
if(!markerRemarck.containsKey(keyM)){
markerRemarck.put(keyM, totalMark++);
createMarkers(dataMarkerProvince);
}
if(dataMarkerTown != null){
markerRemarck.put(keyM + "city", totalMark++);
createMarkers(dataMarkerTown);
}
for(int i = 0; i < totalMark;++i)
map.getMarkerManager(i).disableDrawing();
map.getMarkerManager(markerRemarck.get(keyM)).enableDrawing();
}
another function brings in the data required to make the markers. I just don't seem to manage to add a MarkerManager after the first draw.
EDIT
This map is placed inside a JPanel. And the years are choosen with the help of a JComboBox. Once a year is chosen the "dataMarker" variable containing the information for creating markers is updated
thanks in advance for helping me out.
So I'm just messing around learning to create a Space invaders type game. I can get the bad guys to move, Great!!. Hero moves, Great!! Bullets move, Great!! However I try to remove my bullets once they leave the screen as to not eat up all resources and it force closes on me once it gets rid of the bullet. It goes off the screen. Hits the int of -2 and then we use the remove() and boom. Force Close.
Here is my code. I'm wondering if they access the size() at the same time and just cause a force close because of it.
//I removed everything that doesn't pertane to the bullets.
public class GameScreen{
Bullet bullet = world.bullet;
public GameScreen(Game game) {
super(game);
world = new World();
}
//Draws our bullets.
int bulletLength = bullet.bullets.size();
for(int i = 0; i < bulletLength; i++) {
Placement part = bullet.bullets.get(i);
x = part.x * 32 + 11;
y = part.y * 32;
g.drawPixmap(Assets.bullet, x, y);
}
Class that holds my bullets.
public class Bullet {
public List<Placement> bullets = new ArrayList<Placement>();
public Bullet() {
}
public void shoot(int x, int y){
bullets.add(new Placement(x,y));
}
public void advance(){
int len = bullets.size(); // gets all bullets.
for(int i = 0; i < len; i++) {
bullets.get(i).y --;
if (bullets.get(i).y <= -2){//removes them once they are off the screen.
bullets.remove(i);
}
}
}
This is what I use to keep track of placement.
package com.learning.planecomander;
public class Placement {
public int x, y;
public Placement(int x, int y) {
this.x = x;
this.y = y;
}
}
When going through your list to remove bullets, you can remove bullets from a list but that affects the list immediately instead of after your loop is done. Since you are traversing to the length of the list at the start, you are going off the end of the list since you've removed elements. An example is probably more helpful than that description.
Let's say you have a list with three bullets (which I'll call a, b, c to make the example easier). On a pass through the list, a and c are fine but b needs to be removed.
i = 0;
bullets[0] = a;
bullets[1] = b;
bullets[2] = c;
First loop goes fine, second loop starts like this
i = 1;
bullets[0] = a;
bullets[1] = b;
bullets[2] = c;
We remove b, but the loop keeps going
i = 2;
bullets[0] = a;
bullets[1] = c;
OH CRAP ARRAYINDEXOUTOFBOUNDS! PROGRAM CRASHES!
The way to solve this is to use a temp list to store the bullets that need to be removed, and then once your update loop is finished, make a call to bullets.removeAll(temp)
Doing two passes is a good answer. It makes the loops simpler and easy to understand. If you'd like to do it in one pass though, iterate through the list in reverse order, and when you remove a bullet you can go to the next one and not worry about blasting past the end of the ArrayList.
Alternatively, you can keep your bullets in a linked list, and run through the list with an Iterator, which you can also use to remove items from the list with. Removing from the beginning middle or end of an linked list is always a constant time operation. Whereas removing from the beginning of an ArrayList can be more expensive. If you need random access to the elements in the list, then they can be inefficient. Keep in mind though, if you're only dealing with a handful of objects, then it doesn't really matter.
For bonus points, you might want to put all of your objects in a list, and then have your central loop process them all and have your game objects respond polymorphically to calls like dead?, think, move, draw or whatever you think is appropriate.
Im learning Java and Im creating a memory type game where you have to find two equal cards.
I have created a Window etc etc but my problem is adding multiple JButtons to it. (my cards are JButtons with icons). I have commented my code where my problem is.
//Get the images.
private File bildmapp = new File("bildmapp");
private File[] bilder = bildmapp.listFiles();
//My own class extending JButton
Kort[] k = new Kort[bilder.length];
for(int i = 0; i < bilder.length; i++){
k[i] = new Kort(new ImageIcon(bilder[i].getPath()));
}
//Later in my code:
int sum = rows * columns;
Kort[] temp = new Kort[sum];
//My function to randomize.
Verktyg.slumpOrdning(k);
//***********************//
//Trying to fill a array from K (which contains all cards) so my temp contains SUM cards and SUM/2 pairs
for(int i = 0; i < sum/2; i++){
temp[i] = k[i];
temp[i+sum/2] = k[i];
}
//Problem is that i only get SUM/2 (half of the cards) cards, not the 16 (8 pairs) i would like to add in this case
//SYNLIGT = VISIBLE.
for(int i = 0; i < sum; i++){
temp[i].setStatus(Kort.Status.SYNLIGT);
j.add(temp[i]);
}
Your code ends up adding each Kort object to the container twice, since the array temp contains two references to each Kort. When you add a Kort a second time, it moves to the second location. A Component can only appear in one place at a time.
You may not add the same widget twice. You need two separate buttons (but you may use the same icon on both).
You have to create sum JButton objects not sum/2; otherwise 2 buttons are the same and therefore only displayed once.