i am using AndEngine.
I have a scene that i would like to reuse for all of my levels.
The only thing that will change is the objects loaded on the scene through a method i created to load the level.
The problem i am facing is that at the end of the level the user gets the option to continue to the next level. I allow the user to load the next level with this method.
this.nextlevel = new Sprite(0,0,150,80,this.nextLevelRegion,this.getVertexBufferObjectManager()){
public boolean onAreaTouched(final TouchEvent pSceneTouchEvent,
final float pTouchAreaLocalX,
final float pTouchAreaLoca) {
GameScene.detachChildren();
loadLevel(level);
return true;
}
};
The loadLevel(int level_number) takes a int as a parameter. I increase this variable by level++; after the current level is loaded.
The problem is when the sprite is clicked it keeps adding +1 to the level integer and trying to load the wrong level..
Anyone know a better way of doing this?
this is what i did in my game:
i created a class that creates the game play scene, this class has a method that creates the scene and loads an XML level based on the number that it recieves when i call it.
when i want to go to next level i get the current level number (lets say its x) and call the method with x+1 as an attribute for it.
you should note that i depend in this method on recreating the scene all over again so you should reset every thing when you do that.
this is the call for the method:
Sprite Next=new Sprite(x-48/factor, y+30/factor, 96/factor, 60/factor,LoadAssets.WinMenuNextTextureRegion){
#Override
public boolean onAreaTouched(final TouchEvent pSceneTouchEvent, final float pTouchAreaLocalX, final float pTouchAreaLocalY) {
if(pSceneTouchEvent.isActionUp()){
pEngine.setScene(GamePlayScene.CreateTheGamePlayScene(context,pEngine,camera_width, camera_height,GamePlayScene.LevelNumber+1));
}
return true;
}};
and here is the link for my game if you want to see how that works:
https://market.android.com/details?id=com.ayham.blowangryshapes
i only have one game play scene in the game and the levels are loaded as needed.
Related
I have a mobile game which has a level select menu. The menu consists of 15 level buttons per page and of 4 pages. Page can be changed by swiping the screen. Swiping can be done over the buttons (it can start and end on a button) without triggering any of them. Buttons can be tapped which should activate their touchUp() method.
Currently the dragging works properly but the level select buttons are not handling the touchUp events.
I have done this by creating an actor that is the size of the whole screen. It is behaving as the dragHandler actor which detects touchDown, touchDragged and touchUp. It is working properly.
Under the dragHandler actor (on the stage) lies all the level button actors that move on the screen as the user drags it. Because the dragHandler is above the buttons, the buttons touchDown or touchUp methods are not called, the events are being handled in the dragHandler.
In my dragHandlers InputListeners touchUp method I have a piece of code that checks if the drag was long enough to be interpreted as a drag. If it wasn't, the event should be marked as unhandled. However, the InputListeners touchUp method prototype is returning a void so it cannot tell the lower levels that the event wasn't really handled (the touch seems to be marked as handled in the touchDown method already).
Here is my version of the InputListener in the dragHandler:
dragHandler.addListener(new MyInputListener() {
#Override
public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) {
// Mark dragging on, save drag start position
dragStartX = x;
isDragging = true;
return true;
}
#Override
public boolean touchUp(InputEvent event, float x, float y, int pointer, int button) {
// If the drag was long enough, mark the event as handled
if (Math.abs(dragXOffset) >= minDrag) {
// Do stuff
return true;
}
else
// Return false to tell that this event was not yet handled,
// and should be handled by another actor (in this case, a level select button)
return false;
}
public void touchDragged(InputEvent event, float x, float y, int pointer) {
dragXOffset = x - dragStartX;
updateLevelButtonPositionsToDraggedX();
}
}
I have made a new class called MyInputListener which is exactly the same class as the original InputListener.java but I have changed the touchUp method to return a boolean instead of void, and changed the switch-case to return its result (instead of a constant true). This however didn't affect in any way. I guess it is because the touchDown event is being already handled in the dragHandler, so the touchUp cannot be handled by a different EventListener anymore.
All the actors are on the same stage, and the applications input processor is set to be the stage. If I put the dragHandler below the button actors, the touchUp method of a button is called always when the touchUp event is fired on top of a button. I don't want the touchUp after a drag to trigger the touchUp event of any of the buttons.
Is there any way to achieve what I want with any approach similar to what I have done already?
Thank you for your time!
So, my issue is this: I'm attempting to define a custom set of nodes for a Javafx XYChart LineChart, where each node corresponds to a point that was plotted directly from the datasets. After looking around a little bit, Jewlesea actually had a solution at one point about how to add dynamic labels to nodes on a linechart graph that gave me enough of a push in the right direction to create black symbols (they are dots at the moment, but they can be many different things). Now I have a requirement that requires me to change ONE of the nodes on the XY chart into an 'X'. this could be either through loading an image in place of the 'node', or through physically manipulating the 'shape' parameter in .css.
The problem begins when I try to add this property dynamically, since which node has the 'x' will always be changing. Here are the things I've tried, and they all end up with no results whatsoever, regardless of the property used.
private XYChart.Data datum( Double x, Double y )
{
final XYChart.Data data = new XYChart.Data(x, y);
data.setNode(
new HoveredThresholdNode(x, y));
//data.getNode().setStyle("-fx-background-image: url(\"redX.png\");");
data.getNode().styleProperty().bind(
new SimpleStringProperty("-fx-background-color: #0181e2;")
.concat("-fx-font-size: 20px;")
.concat("-fx-background-radius: 0;")
.concat("-fx-background-insets: 0;")
.concat("-fx-shape: \"M2,0 L5,4 L8,0 L10,0 L10,2 L6,5 L10,8 L10,10 L8,10 L5,6 L2,10 L0,10 L0,8 L4,5 L0,2 L0,0 Z\";")
);
data.getNode().toFront();
return data;
}
So in the above, you can see that this is adding a property through the use of the 'bind' function after the dataNode has already been created. Also note above, I tried doing it through the 'setStyle' interface at this level to give it a background image, with no success. Also, no errors are being thrown, no 'invalid css' or anything of the sort, just simply no display on the graph at all when done this way.
now, in the HoveredThresholdNode (Again a big thanks to Jewelsea for being a master of Javafx and putting this bit of code online, it's where 90% of this class came from.) I tried essentially the same thing, at a different level. (actually being IN the node creation class, as opposed to a layer above it).
class HoveredThresholdNode extends StackPane {
/**
*
* #param x the x value of our node (this gets passed around a bunch)
* #param y the y value of our node (also gets passed around a bunch)
*/
HoveredThresholdNode(Double x, Double y) {
//The preferred size of each node of the graph
//getStylesheets().add(getClass().getResource("style/XYChart.css").toExternalForm());
//getStyleClass().add("xyChart-Node");
//setOpacity(.8);
styleProperty().bind(
new SimpleStringProperty("-fx-background-color: #0181e2;")
.concat("-fx-font-size: 20px;")
.concat("-fx-background-radius: 0;")
.concat("-fx-background-insets: 0;")
.concat("-fx-shape: \"M2,0 L5,4 L8,0 L10,0 L10,2 L6,5 L10,8 L10,10 L8,10 L5,6 L2,10 L0,10 L0,8 L4,5 L0,2 L0,0 Z\";")
);
//this label is the 'tooltip' label for the graph.
final Label label = createDataThresholdLabel(x, y);
final double Myx = x;
final double Myy = y;
setOnMouseEntered(new EventHandler<MouseEvent>() {
#Override public void handle(MouseEvent mouseEvent) {
if (Myx == 0) {
label.setTextFill(Color.DARKGRAY);
} else if (Myx > 0) {
label.setTextFill(Color.SPRINGGREEN);
} else {
label.setTextFill(Color.FIREBRICK);
}
label.setText("Current position: " + Myx + " , " + Myy);
//setCursor(Cursor.NONE);
toFront();
}
});
setOnMouseExited(new EventHandler<MouseEvent>() {
#Override public void handle(MouseEvent mouseEvent) {
//getChildren().clear();
//setCursor(Cursor.CROSSHAIR);
}
});
}
Now note, I also tried the setStyle(java.lang.String) method, with all of the same type of CSS, with no success. I have NO idea why this isn't styling dynamically. It's almost as if the custom nodes are simply ignoring all new .css that I define at runtime?
Any help would be greatly appreciated, please don't be shy if you need more details or explanation on any points.
So, I did finally find a good workaround to solve my problem, although not in the way I thought it would happen. The main problem I was having, was that I was extending from stackPane to create my node, which only had a very small number of graphical display options available to it, and by switching the 'prefSize()' property, I was simply changing the size of that stackPane, and then filling in the background area of that stack pane black, giving it a very deceptive shape-look to it.
So rather than use a stack pane, whenever I reached the node that I needed to place the red 'X' on, I simply called a different Datum method that returned a datum with an ImageView Attached, like so:
private XYChart.Data CoLDatum(Double x, Double y){
final XYChart.Data data = new XYChart.Data(x, y);
ImageView myImage = new ImageView(new Image(getClass().getResource("style/redX.png").toExternalForm()));
data.setNode(myImage);
data.getNode().setOnMouseEntered(new EventHandler<MouseEvent>() {
#Override public void handle(MouseEvent mouseEvent) {
main_label.setText("Some Text.");
}
});
data.getNode().setOnMouseExited(new EventHandler<MouseEvent>(){
#Override public void handle(MouseEvent mouseEvent) {
main_label.setText("");
}
});
return data;
}
and since ImageView is an implementing class of Node, this worked out just fine, and allowed me to load up an image for that one single node in the graph, while still maintaining a listener to give custom text to our information label when the red 'x' was hovered over with a mouse. Sometimes, it's the simple solutions that slip right past you.
I imagine that, had I employed stackPane properties properly with the setStyle(java.lang.String) method, they would have absolutely shown up, and I was just butchering the nature of a stack pane. Interesting.
Hopefully this helps somebody else stuck with similar problems!
I am making a button using MouseOverArea. After some trial and error, I realized I can override the methods in InputListener to do particular actions when an input event is notified.
For example, do things when mouse left button is pressed while cursor is over the component.
#Override
public void mousePressed(int button, int mx, int my) {
if (isMouseOver() && button == Input.MOUSE_LEFT_BUTTON) {
// Some magic happens
}
}
However, I will not able to do things like changing current game state because no Game object around. I know there are many ways to solve this problem, but I would like to know what is the Slick way to do this.
Are these methods suitable for such behavior ?
One way to modify game states is to use boolean states; Which are boolean variables that hold the state of the game or player. For example:
boolean isMovingUp, isMovingLeft, isMovingRight, isMovingDown;
You can then set these to true/false depending on what mouse or keyboard event takes place and your game class then read these variables, like so:
if (isMovingUp) {
// do something
isMovingUp = !isMovingUp;
}
Hope that helps!
I am using this method in AndEngine to determine the scene being touched by the user.
#Override
public boolean onSceneTouchEvent(Scene pScene, TouchEvent pSceneTouchEvent) {
if(pSceneTouchEvent.isActionDown()) {
Log.e("Arcade", "Scene Tapped");
//Simulate player jumping
}
return false;
}
What i want to do is when the scene is tapped, i want to allow the player to jump.
Now two things for this would it be better to use PathModifier, or MoveYModifier considering it is landscape mode?
If either please provide an example of such.
Thanks
EDIT:
ive managed to use Physics to simulate a jump using this..
#Override
public boolean onSceneTouchEvent(Scene pScene, TouchEvent pSceneTouchEvent) {
if(pSceneTouchEvent.isActionDown()) {
Log.e("Arcade", "Scene Tapped");
final Vector2 velocity = Vector2Pool.obtain(mPhysicsWorld.getGravity().x * -0.5f,mPhysicsWorld.getGravity().y * -0.5f);
body.setLinearVelocity(velocity);
Vector2Pool.recycle(velocity);
return true;
}
return false;
}
As you said in the answer by changing the gravity. The only issue is, when the user keeps touching the screen the sprites keep going up and up and up. How can i set it where the user can only click once and cant make him jump again until the sprite hits the ground, which is a rectangle?
Use the MoveYModifier. remember, you can register as many modifiers as you want. So if, for example, the game a platform game and the character always moves on the X axis, and he can jumpt if he wants (Like Gravity Guy or Yoo Ninja, although these games change the gravity which is something else).
You could do like:
Entity playerEntity = ..//It doesn't matter if the player is a sprite, animated sprite, or anything else. So I'll just use Entity here, but you can declare your player as you wish.
final float jumpDuration = 2;
final float startX = playerEntity.getX();
final float jumpHeight = 100;
final MoveYModifier moveUpModifier = new MoveYModifier(jumpDuration / 2, startX, startX + jumpHeight);
final MoveYModifier moveDownModifier = new MoveYModifier(jumpDuration / 2, startX + jumpHeight, startX);
final SequenceEntityModifier modifier = new SequenceEntityModifier(moveUpModifier, moveDownModifier);
playerEntity.registerEntityModifier(modifier);
EDIT:
For your second question:
Create a variable boolean mIsJumping in your scene; When the jump starts - set it to true. If the user taps the screen and mIsJumping == true, don't jump.
Now, register a ContactListener to your PhysicsWorld. Whenever there is contact between the player and the ground, set mIsJumping to false.
There are many samples of using ContactListeners in AndEngine forums, a quick search yields some. If you need an example, you can ask for one :)
EDIT 2: ContactListener sample:
Have 2 variables to hold IDs for the player and the ground: private static final String PLAYER_ID = "player", GROUND_ID = "ground";
When you create the ground body and the player body, set their IDs as the user data: playerBody.setUserData(PLAYER_ID); and groundBody.setUserData(GROUND_ID);
Create a ContactListener as a field in your scene:
private ContactListener mContactListener = new ContactListener() {
/**
* Called when two fixtures begin to touch.
*/
public void beginContact (Contact contact) {
final Body bodyA = contact.getFixtureA().getBody();
final Body bodyB = contact.getFixtureB().getBody();
if(bodyA.getUserData().equals(PLAYER_ID)) {
if(bodyB.getUserData().equals(GROUND_ID))
mIsJumping = false;
}
else if(bodyA.getUserData().equals(GROUND_ID)) {
if(bodyB.getUserData().equals(PLAYER_ID))
mIsJumping = false;
}
}
/**
* Called when two fixtures cease to touch.
*/
public void endContact (Contact contact) { }
/**
* This is called after a contact is updated.
*/
public void preSolve(Contact pContact) { }
/**
* This lets you inspect a contact after the solver is finished.
*/
public void postSolve(Contact pContact) { }
};
Lastly, register that contact listener: physicsWorld.setContactListener(mContactListener);
EDIT 3:
To move your sprite over the X axis, you can apply a force using Body.applyForce method, or apply an impulse using Body.applyLinearImpulse method. Play around with the arguments and find what works the next.
The vector should consist a X part only; Try Vector2 force = Vector2Pool.obtain(50, 0);. Then apply the force this way: body.applyForce(force, body.getWorldCenter());.
I'm using andengine for android for the first time. I'm creating a simple list of text that simply needs to be able to call the same method but send a different variable accroding to its position on the list. The list does not need to scroll and is short. I decided to use simple text and created a for loop to make them for me from a string array.
The loop works and creates the text properly but when touching they all perform the last touch assignment instead of the corresponding one.
Does the onAreaTouched code need to be referred to or is it saved some where once the touch area is registered.
here it is:
for(x =1; x<base.locale.length;x++){
textLoc[x-1]=new Text(10,(110+(x*30)),base.getmFont(),
base.locale[x],HorizontalAlign.CENTER){
#Override
public boolean onAreaTouched(final TouchEvent pSceneTouchEvent, final float pTouchAreaLocalX, final float pTouchAreaLocalY) {
base.moveListen(Integer.toString(x));
loadNewScene();
return true;
}
};
scene.getLastChild().attachChild(textLoc[x]);
scene.registerTouchArea(textLoc[x]);
}
Does that code compile? As in this line:
base.moveListen(Integer.toString(x));
you are refering to the non-final loop-variable x.