I created a live wallpaper service using AndEngine library. On screen there are a number of bird Sprite objects that flying repeatedly from the left to right started in random y-coordinate (I'm using LoopEntityModifier and PathModifier for this, see my previous question if you're curious). The birds shouldn't start flying in same time, but there is a gap/interval about 3 seconds before another bird showed up from left most screen.
The question is what technique that I have to use to achieve that?
I had created array of Sprites to hold the bird sprites. The code is like this...
public class MyLiveWallpaperService extends BaseLiveWallpaperService {
private BirdSprite[] birdSprites; // BirdSprite is actually an extension class from AnimatedSprite
...
#Override
public Scene onLoadScene() {
...
birdSprites= new BirdSprite[4];
for (int i=0; i<4; ++i) {
birdSprites[i] = new BirdSprite(0, 0, birdTextureRegion);
scene.getChild(LAYER_FRONT).attachChild(birdSprites[i]);
}
}
}
The above code produces four birds that show-up on left screen in same time. I tried by adding Thread.sleep(3000) before calling attachChild, but it affects whole application. The live wallpapaper application become hanged for several seconds when started.
This is the solution I found by using TimerHandler:
scene.registerUpdateHandler(new TimerHandler(3, true, new ITimerCallback() {
#Override
public void onTimePassed(TimerHandler pTimerHandler) {
// your code here will be executed every 3 seconds (see 1st argument of TimerHandler)
...
scene.getChild(LAYER_FRONT).attachChild(birdSprites[i]);
}
}));
Please let me know if you have better solution.
Related
I'm working on a simple 2D text-base game. So, I have 2 Player class thats fighting in a Arena class. I want to use them at the same time and modify their (position, hp, etc...)
For example: when program is running, Player1 move to x,y position, Player2 move to x,y position and then they have new position in Arena at the same time.
What's the best way to do this?
Don't conflate game time with CPU time. Just because players move at the same game time doesn't mean you need to have CPU threads executing concurrently. You just need a logic loop that simulates simultaneous movement.
For example, loop over all the players and check that their actions don't conflict with each other. If two players want to move to the same location, show an error. Otherwise, loop over them a second time and move them all to their new locations. Then redraw the scene. Even though you're updating the players one at a time in the second loop, the screen won't show the movements until the entire scene is repainted.
For this you must use thread. Here is an example of this:
public static void main(String[] args) {
new Thread() {
public void run() {
method1();
}
}.start();
new Thread() {
public void run() {
method2();
}
}.start();
//etc
//or, as kingdamian42 pointed out, if you use java8, use this
new Thread(() -> method1()).start();
new Thread(() -> method2()).start();}
here method one and two will be you players move.
I have a problem regarding drawing multiple of the same objects. They end on top of each other, and their "Object values" even get added together e.g. if a zombie has "2" movement value and there is added 2 into the current level. Then when zombies are moved, they move "4" each. This does not happen if two different objects are moved e.g. Zombie and Dragon. I have created the following code based on my project - for a simpler overview. However, the behavior is the same.
It should be mentioned the objects of the same type have the same "HashCode". I have also made comments and println to help figure out the problem. Each of the 5 objects have different position (When set). However, they are rendered on top of each other and merged (Movement).
EnemyDatabase enemyDatabase;
ArrayList<Enemy> enemiesInlevel = new ArrayList<Enemy>();
void setup()
{
size(600, 600);
enemyDatabase = new EnemyDatabase();
enemyDatabase.enemies.add(new Enemy("Zombie", 3));
//If dragon is added - Then it can draw both - But only once
//enemyDatabase.enemies.add(new Enemy("Dragon", 10));
//Add 10 zombies to the level
for(int i=0; i< 5;i++)
{
//5 Zombies are created and succesfully added to the database
enemiesInlevel.add(enemyDatabase.enemies.get((int)random(0, enemyDatabase.enemies.size())));;
}
for(int i=0; i<enemiesInlevel.size();i++)
{
//Sets the position of all 5 - Gives random position
Enemy enemy = enemiesInlevel.get(i);
enemy.SetPosition();
}
}
void draw()
{
background(255, 200, 0);
//Draw 5 enemies - Of index 0 (Zombie)
for(int i=0; i<enemiesInlevel.size();i++)
{
Enemy tempEnemy = enemiesInlevel.get(i);
tempEnemy.draw();
//It runs 5 times - print returns 5 total objects in enemiesInlevel
}
}
class EnemyDatabase
{
ArrayList<Enemy> enemies = new ArrayList<Enemy>();
}
class Enemy
{
String enemyName;
int enemyHealth;
PVector enemyPosition;
public Enemy(String name, int hp)
{
enemyName = name;
enemyHealth = hp;
}
public void SetPosition()
{
enemyPosition = new PVector(random(0, width), random(0, height));
//Each of the objects has a random position
println(enemyPosition);
}
public void draw()
{
rect(enemyPosition.x, enemyPosition.y, 25, 25);
}
}
UPDATE
Here is an image of the problem
As the image shows from the output in the image line: The enemies have different positions when added to the array (5 different enemies) However, as the image shows, it still only displays one - And this happens because all of the sudden the positions is the same. I even tried to give a "Random position" in the "DrawImage" all of the enemies still end up having the same position
Hope you guys can figure it out. I certainly have a hard time - I usually don't work in processing Thank you
DrSatan's comment is correct. You're only ever adding a single Enemy to your EnemiesDatabase. So when you select 5 random enemies, you're really just selecting the same enemy 5 times.
It might look like they have different positions in your print statements, but that's because you're printing out the position every time you set it. You're setting it five times, but only the last position really counts for anything.
In other words, you're taking a single instance of Enemy, moving it around the screen 5 times, and printing out the position each time. But then when you draw it, only the last position you moved it to is what you see.
You need to refactor your code so you add more enemies to your EnemyDatabase, but please note that you're going to have similar problems no matter how many enemies are in your EnemyDatabsae, because you don't have any logic that makes sure you don't select the same instance twice. Even if you had 100 enemies in your database, nothing is stopping your random function from selecting the same enemy 5 times.
If I were you, I'd rethink my design. I don't really see the reason to have a separate EnemyDatabase class at all. Maybe just create a function that adds X random enemies to the level, where X is a parameter? That's up to you, but your fundamental problem here is that you only have a single instance of Enemy.
For the sake of learning I've been trying to build a little visualizer (like this one) that shows how different sorting algorithms work. I'm not overly experienced with Swing, and I'm reading that I should use a Timer, but I can't seem to wrap my head around how to actually use it properly.
import javax.swing.Timer;
// .....
public class sortPanel extends JPanel {
private ArrayList<Integer> list;
// .....
public void selectionSort(int msDelay) {
// code here that loops through and sorts the ArrayList.
// I know how to do this part but do not want to start it until I get Timer working.
Timer timer = new Timer(msDelay, new ActionListener() {
public void actionPerformed(ActionEvent ae) {
repaint();
}
});
timer.start();
}
// .....
}
This is what my GUI looks like:
Each of the four panels is an instance of sortPanel. The red circle is the current index of the array the algorithm is on. The start button (for now) calls the selectionSort method in for the first panel.
I was able to get the Timer to work properly when the command was to simply increase the index, but for a more complex task where I want a delay after every index change as well as array modification, I'm not sure how to make it work.
Any suggestions? I'd also appreciate some general criticism of my coding in terms of practices/conventions.
Full source is available here.
this is a problem that I've been really struggling with
I need to create a game for some University coursework. The game is basically a 4x4 grid. When i click a button, the player should move randomly within 1 square of it's location.
There's enemy spaceships that are generated randomly over the grid, and if the player lands on the spaceship, it destroys it. if there's two enemy ships on the same sqaure and the player lands on that square, the player is destroyed.
I've created a GIU using gridlayout and the button that I need to move the player, but I'm having problems trying to figure out how to actually use the grid. I've created an element class to create objects for the grid (ie, a list of enemy ships), but I don't know how to use this class with my gridlayout. I know I also have to redraw the grid after each move to reflect the changes, but I don't know if I would need to create a custom redraw method for this.
Any push in the correct direction so I can get my program actually doing something would be really helpful.
Some time ago I created a card game that also operated based on a GridLayout. Below is some of the code that was used to drive major events:
CardPanel extends JPanel {
public CardPanel() {
setLayout(gridLayout);
placeCards(N);
chatBoxText = new JTextArea(5, 30);
}
public void placeCards(int numCards) {
for (int i = 0; i < numCards; i++) {
Card card = deck.distributeCard();
String cardImageName = card.getImageName();
JLabel jLabel = makeImage(cardImageName);
cardSet.add(new GraphicCard(card, jLabel));
add(jLabel);
jLabel.addMouseListener(this);
}
if (GameLogic.noSetsOnBoard(cardSet)) {
gridLayout.setRows(gridLayout.getRows() + 1);
placeCards(3);
}
}
public void updateCard(Integer location) {
Card card = deck.distributeCard();
String cardImageName = card.getImageName();
JLabel jLabel = makeImage(cardImageName);
cardSet.set(location, new GraphicCard(card, jLabel));
jLabel.addMouseListener(this);
}
}
The CardPanel here is an object that represents the GridLayout (you see the constructor) as well as some of those helper methods.
Further on, on particular actions, I have the following code:
cardPanel.removeAll();
// Some other logic here
for (GraphicCard card: cardSet) {
cardPanel.add(card.getJLabel());
}
cardPanel.revalidate();
cardPanel.repaint();
In short, yes, it is custom, but it is not difficult. There are better ways to do it than the above such that you do not need to empty the entire panel in order to refresh it, the logic I have omitted above merited this particular solution.
The approach I used kept track of a CardPanel object which was an abstraction that contained not only the information that each box represented (in my case a card with some values), but also the graphic element to be rendered.
This was some time ago, so I don't recall the exact details but hopefully this is helpful.
I'm trying to use GridWorld (from the AP computer science curriculum) for making a game, and I'm having problems with using multiple grids. World's setGrid method doesn't seem to work. I was under the impression that you could have multiple grid objects co-existing, and that the current one pointed to by the World is the one that gets drawn in the GUI. But that's not what happens... when I call the World's setGrid and pass it a grid, the grid seems to only LOGICALLY be set, and System.out.printing it gives the correct results of its actors and their current positions, but the GUI doesn't update and you can't actually see the grid.
I wrote a simple ActorWorld to illustrate this:
public static void main(String[] args) throws Exception
{
ActorWorld x = new ActorWorld()
{
Grid<Actor> gr1 = new BoundedGrid<Actor>(10,10);
Grid<Actor> gr2 = new BoundedGrid<Actor>(10,10);
public void step()
{
new Actor().putSelfInGrid(gr1, new Location(1,1));
new Actor().putSelfInGrid(gr2, new Location(9,9));
if (getGrid() == gr2)
setGrid(gr1);
else
setGrid(gr2);
System.out.println(getGrid());
}
};
x.show();
}
Every step it's supposed to change to the other grid and display it, so basically what SHOULD be happening is one Actor in the grid changing location from (1,1) to (9,9). But in fact, it just displays an empty grid (because it's using the original grid it made in the default constructor, since I didn't provide one).
What's going on? How do I get it to paint the current grid?
Okay, I found the problem. Upon e-mailing gridworld's creator, he revealed that this is a bug.
I found the source code and added the line
display.setGrid(world.getGrid());
to the beginning of WorldFrame's repaint() method. The problem was that WorldFrame itself updates its current Grid, so logically it's on the right one, but the WorldFrame's GridPanel object, display, which is actually the JPanel that the grid is drawn in, does not get told to update its grid prior to the repaint. With this, the complete method is
public void repaint()
{
display.setGrid(world.getGrid());
String message = getWorld().getMessage();
if (message == null)
message = resources.getString("message.default");
messageArea.setText(message);
messageArea.repaint();
display.repaint(); // for applet
super.repaint();
}
and all is well. :)