I would like to make a 2D Side-scroller game, where the game world/game stage is moving to the left, i.e. The background is transitioning to the left like Flappy Bird. Any ideas how I am able to automatically loop a background Actor object which has the same width and height as the Stage's Orthographic camera?
Well it is really simple. All you need to do is use the moveBy(x, y) method on the Actor instance.
float xMovingDelta = 10;
float yMovingDelta = 10;
actor.moveBy(xMovingDelta, yMovingDelta);
// Make sure you call the moveBy() method in a loop eg. the render() method.
Here is an example from my past game: It uses a Table instance but they both have the moveBy() method.
private void mMenuToDiffMenuAnimation() { // I call this method from the render() meth.
if(difficultyTable.getX() > (540 - 64)){
menuTable.moveBy(-30, 0);
difficultyTable.moveBy(-30, 0);
}else {
fromMMToDiffMenu = false;
/* When the table's xPos is greater than 540 -64 stop the animation.*/
}
}
Related
I want to move a sprite (which happens to be a Rectangle) from any position of the screen and make it stop at exactly the touched position of the screen. Now, I can stop my sprite already, but not at the exact touched position. I cannot find a good way of doing this without sacrificing either accuracy or risking the sprite to not stop at all.
Naturally - the problem arises because the current position is Float, so that Vector will never (or extremely rarely) have the exact same coordinates as the touch point (which is an int).
In the code below, I stop my sprite by simply checking the distance between the current position and the target position (i.e. the touched position Vector3), like so if (touch.dst(currentPsition.x, currentPosition.y, 0) < 4).
For example, if the sprite is at position (5,5) and I touch the screen at (100,100), it will stop at like (98.5352,96.8283).
My question is, how do I stop the sprite at exactly the touch position, without having to approximate?
void updateMotion() {
if (moveT) {
movement.set(velocity).scl(Gdx.graphics.getDeltaTime());
this.setPosition(currentPosition.add(movement));
if (touch.dst(currentPosition.x, currentPosition.y, 0) < 4)
moveT = false;
}
}
public void setMoveToTouchPosition(boolean moveT) {
this.moveT = moveT;
this.touch = new Vector3(Gdx.input.getX(), Gdx.input.getY(), 0);
GameScreen.getCamera().unproject(touch);
currentPosition = new Vector2(this.x, this.y);
direction.set(new Vector2(touch.x, touch.y)).sub(currentPosition).nor();
velocity = new Vector2(direction).scl(speed);
}
Of course sprite can't move smoothly to touch position and then stop in exactly the same position because of many reasons. Just change this
if (touch.dst(currentPosition.x, currentPosition.y, 0) < 4)
moveT = false;
to this
if (touch.dst(currentPosition.x, currentPosition.y, 0) < 2) {
currentPosition.x = touch.x;
currentPosition.y = touch.y;
moveT = false;
}
A quick yet acceptable solution to this could be the use of the Rectangle class. Considering you make a Rectangle surrounding the moving entity and constantly update it's bounds based on its current location, it's texture width, and it's texture height. You could stop it when it overlaps with the "target position". If you do this you guarantee yourself that it will stop exactly at that position. For example:
Texture entityTexture = new Texture("assets/image.png");
Rectangle entityBounds = new Rectangle();
entityBounds.set((currentPosition.x, currentPosition.y, entityTexture .getWidth(), entityTexture .getHeight()));
Rectangle targetBounds = new Rectangle();
targetBounds.set((targetPosition.x, targetPosition.y, 1, 1)); // make width and height 1 by 1 for max accuracy
public void update(){
// update bounds based on new position
entityBounds.set((currentPosition.x, currentPosition.y, entityTexture.getWidth(), entityTexture.getHeight()));
targetBounds.set((targetPosition.x, targetPosition.y, 1, 1));
if(entityBounds.overlaps(targetBounds)){
// do something
}
}
So I have 3 classes, MyGdxGame, Ball and DetectCollision. MyGdxGame initialises 4 instances of Ball (different colours and speed/direction, all bounce off the sides of the screen) and stores them as an arraylist.
This arraylist is passed through the constructor of DetectCollision:
public class DetectCollisions {
ArrayList<Ball> ball;
public DetectCollisions(ArrayList<Ball> ball) {
this.ball = ball;
start();
}
public void start() {
for(int i=0; i<ball.size();i++) {
...
}
}
Can anyone give me a hint as to where I should go with this? I just want to detect every time a ball collides with another (and eventually I'll have it print the number of collisions).
Any help highly appreciated :)
If you are going to add a lot of objects to the arraylist, use a 2D physics engine to do all the work for you. If you want to continue implementing your own functions, the very basic method to do is to implement a nested loop over the list to check every possible pair in the arraylist. The complexity is O(n^2)
for(int i=0; i<ball.size();i++) {
for(int j=i+1; j<ball.size();j++) {
check(ball.get(i), ball.get(j));
}
}
The method named check checks if given two circles collide or not. Checking two circles' collision is very easy. If the distance between the central points of the circles is smaller than the sum of the radiuses of the circles, then they collide. Check this page for further info about this.
This is very easy to accomplish if you let each Ball have bounds of type Circle.
You can make a circle as follows: Circle ballBounds = new Circle(float x, float y, float radius) This circle can act as the bounds of each ball ultimately allowing you to check if they collide using the Intersector class.
Having each Ball's boundary we can easily loop through the ArrayList<Ball> and check how many collide. For example:
ArrayList<Ball> ball = new ArrayList<Ball>(); // You need to add Balls to this ArrayList
Intersector intersector = new Intersector();
int counter = 0;
for(int i = 0; i < ball.size()-2; i++){
if(intersecor.overlaps(ball.get(i), ball.get(i+1)){
counter++;
}
i++;
}
I have an Enemy class that deals with my monster moving and attacking. Within that class, I have another class called enemyMagic, which is a blank movieclip that serves as a masterclass to different movieclips that I will make.
So in the enemyMagic class, I add a movieclip called attack1
public var attack1:Attack1 = new Attack1;
public function EnemyMagic() {
////////////CREATE THE TIMER//////////
masterEnemyAttackTimer.addEventListener(TimerEvent.TIMER, mastertimer);
////////////ATTACKS/////////
//TIER 1//
addChild(attack1);
}
And in the enemy class, I add the enemyMagic when the enemy is attacking a certain position.
for (var k:int = 0; k < Main.tileset.length; k++)
{
if (! Main.tileset[k].tileMiddle.hitTestObject(this.enemyVisionPoint))
{
if (Main.tileset[k].tileHP !== 0)
{
attackoptions.push(Main.tileset[k]);
}
if (Main.tileset[k].tileMiddle.hitTestObject(Main.player.visionPoint))
{
addChild(enemymagic);
Main.tileset[k].outline.gotoAndStop("attack");
this.enemymagic.x = (Main.tileset[k].x);
this.enemymagic.y = (Main.tileset[k].y);
trace(enemymagic.x, enemymagic.y, Main.tileset[k].x, Main.tileset[k].y);
For some reason, the enemymagic is tracing the exact same number as the tile's x and y, but it isn't adding it on the tile. It adds it way off the screen. I think it might be because it starts on the enemy's x and y and then calculates?
So my question is how can I get the enemymagic movie clip to get exactly on the position of the tile?
You can do two things. First, when you do a plain addChild() the base coordinate system of the child is the one of its parent, which is your Enemy instance, which is of course at somewhere nonzero. And then you assign it the coordinates of Main.tileset[k] which has a different parent (most likely instance of Main). This creates the distance you speak of. So, in order to locate your magic over the exact tile, either use this.globalToLocal(Main.tileset[k].localToGlobal(PZERO)) where PZERO is a new Point() constant (or write new Point() instead of PZERO, but this will create another empty Point object and will quickly escalate), or do an addChild() directly to the tile you are attacking with unaltered coordinates.
OK so i have a character that moves with the mouse. I need it to stay in the center of the screen(kind of like a platformer game). I can't figure out how to access the camera and move it. (Note: I have tried Vcam and moving all of the other objects but Vcam makes the file slow or something [or so i have heard] and moving the other objects in kind of like cheating [and for my needs is insufficient]) I don't have any code because i don't know where to start. Maybe someone can point me into the right direction.
Thanks,
Thor
One way is to store everyhting in one DisplayObject and then move that single object based on the camera movement. Instead of moving the camera, move the main container the opposite direction of the camera. I'm not sure why you seem to suggest a strategy like this is "cheating" as it is a perfectly suitable way to doing this.
This is my previous answer on a similar question found here.
What I do here is:
Create a Map class with a property camera which is another custom class MapCamera.
The MapCamera has five properties:
_x
_y
map - a reference to the instance of Map owning this MapCamera
offsetX
offsetY
The offset values represent the x and y spacing from the left and top edges of the screen, which should be set to half of the stage width and height so that the camera will centre on the stage correctly.
The _x and _y properties are private, and have getters and setters.
The getters are pretty basic:
public function get x():Number{ return _x; }
public function get y():Number{ return _y; }
The setters are where the viewport will be altered, like so:
public function set x(n:Number):void
{
_x = n;
map.x = -(_x + offsetX);
}
public function set y(n:Number):void
{
_y = n;
map.y = -(_y + offsetY);
}
From here, you add your children into the Map container and then can simply go:
map.camera.x = player.x;
map.camera.y = player.y;
Which will cause the player to always be in the centre of the screen.
Your camera is only a vector that modifies position of all renderable objects.
myMovieClip.x = movingClipPosition.x + camera.x
So if the camera.x is moved to the right, this will make the object move the left, giving the impression of a "camera".
I'm making a space navigation game. So it starts with the user on the spaceship and then when he press the up key the ship goes forward, the 'map' is always different, I have 5 variations of stars and 2 variations of planets, so they basically 'spawn' randomly while the user navigates. I can make the key detection, the movie clips generator code, but I don't know how do I make the navigation code, I mean how do I make the viewport move when the user press the key, ... I've saw a code that I didn't understand too well that the guy basically created a giant movie clip that moves according to the key that was pressed. That won't work in my case because I want it to generate everything randomly and when the user press the down arrow, I want it to go back, with the same 'map' that he was before. Please help me out guys I'm totally confused with all this viewport thing. And also, I want the game to run fast, I'm kind of new to the Action Script, and I don't know if it gets heavy if you are rendering objects that are not being displayed, if so will a simple 'obj.visible = false' works? Thanks in advance.
What I do here is:
Create a Map class with a property camera which is another custom class MapCamera.
The MapCamera has five properties:
_x
_y
map - a reference to the instance of Map owning this MapCamera
offsetX
offsetY
The offset values represent the x and y spacing from the left and top edges of the screen, which should be set to half of the stage width and height so that the camera will centre on the stage correctly.
The _x and _y properties are private, and have getters and setters.
The getters are pretty basic:
public function get x():Number{ return _x; }
public function get y():Number{ return _y; }
The setters are where the viewport will be altered, like so:
public function set x(n:Number):void
{
_x = n;
map.x = -(_x + offsetX);
}
public function set y(n:Number):void
{
_y = n;
map.y = -(_y + offsetY);
}
From here, you add your children into the Map container and then can simply go:
map.camera.x = player.x;
map.camera.y = player.y;
Which will cause the player to always be in the centre of the screen.