I have a scrollpane where I set the Y position and I want to disable the scrolling. This is my code:
// create root
VerticalGroup root = new VerticalGroup();
root.center();
root.bottom();
root.reverse();
root.pad(getPadding());
root.space(getPadding() * 2.5f);
// add some label's and button's to the root here
...
// create the scrollpane
ScrollPane scrollPane = new ScrollPane(root);
getStage().addActor(scrollPane);
scrollPane.setScrollingDisabled(true, false);
scrollPane.setClamp(true);
scrollPane.setOverscroll(false, false);
scrollPane.setFillParent(true);
Gdx.app.log("scroll max y", ""+scrollPane.getMaxY());
Gdx.app.log("scroll y", ""+scrollPane.getScrollY());
Gdx.app.log("scroll vis y", ""+scrollPane.getVisualScrollY());
scrollPane.layout();
scrollPane.setScrollPercentY(100);
scrollPane.updateVisualScroll();
Gdx.app.log("scroll max y", ""+scrollPane.getMaxY());
Gdx.app.log("scroll y", ""+scrollPane.getScrollY());
Gdx.app.log("scroll vis y", ""+scrollPane.getVisualScrollY());
I would assume that updateVisualScroll() does skip the scroll animation, but it doesn't. I tried everything and I have no clue why it still animates. This code is executed in the constructor of a screen. The Y-Axis is inverted, thats why I put the scroll percent to a 100 because I want to start at the top.
The logs are as expected:
scroll max y: 0.0
scroll y: 0.0
scroll vis y: 0.0
scroll max y: 592.0
scroll y: 592.0
scroll vis y: 592.0
Related
I was making a level table in libgdx using scroll pane. here there are different tables with specific level on a particular scroll pane. Is there any way to preset a particular table to be the first one I see, becuase it would be stupid if I have more than 50 level and I have to scroll through all of them to go to a particular level at end.
A brief details about my tables and scrollpane.
I have a arraylist of table called as column table, which is used as to store different level details in different columns. then this column table is added to another table which is called as levleTable.
The level table is added to scrollpane which is added to main table.
public void setScrollPane() {
scrollPane = new ScrollPane(levelTable, getScrollPaneStyle());
// scrollPane = new ScrollPane(levelTable, skin);
//scrollPane.setFlickScroll(true);
scrollPane.setFadeScrollBars(false);
scrollPane.setScrollingDisabled(false, true);
scrollPane.setScrollX(300);
scrollPane.updateVisualScroll();
//scrollPane.setSmoothScrolling(true);
mainTable.add(scrollPane).expand();
}
and in constructor`
mainTable = new Table();
mainTable.setFillParent(true);
levelTable = new Table();
setScrollPane();
columnTable = new ArrayList<Table>();
levelSelectionButton = new ArrayList<TextButton>();
makeLevelMenu();
//adding main table to stage
stage.addActor(mainTable);`
For the the better idea (when using mechanism like this) i to scroll the scrollPane automatically to the current object (which could be the table with your next level for example).
You can easily achieve it using:
scrollPane.setScrollY(y);
where the y should be
y = (total height of scroll Pane content) - ( (desired element Y position inside scrollPane) - (element height) )
I mean that if your scrollPane content has 100px height and there are 5 elements every with 20px height then scrolling to the third is:
y = 100 - (3 * 20px - 20px) = 100 - 40px = 60px
The same will work if your scrollPane is arranged horizontally - you just need to use scrollPane.setScrollX(x) and calculates all width instead of heights
UPDATE: before using setScrollX / setScrollY you have to call .layout() method on the scrollPane
The example:
#Override
public void show()
{
//creating stage and viewport
viewport = new FillViewport(1280, 800);
stage = new Stage(viewport);
Gdx.input.setInputProcessor(stage);
//creating levelTable
Table levelTable = new Table();
levelTable.setSize(2000, 500);
//filling levelTable with fake actors (it can be labels of your levels numbers)
for(int i = 0; i < 100; i++)
{
Actor a = new Actor();
a.setSize(80, 200);
//set debug to see the outline
a.debug();
levelTable.add(a).pad(150, 10, 150, 10);
}
//set debug to see the outline
levelTable.debug();
//defining scroll
ScrollPane scrollPane = new ScrollPane(levelTable, skin);
scrollPane.setSize(800, 600); //your custom size
scrollPane.setPosition(50, 50); //your custom position
scrollPane.setFadeScrollBars(false);
scrollPane.setScrollingDisabled(false, true);
//important!! you have to call it before setScrollX
scrollPane.layout(); //that's the thing!
//the number of column you want to go to
int numberOfColumn = 10;
//now move to column no numberOfColumn
scrollPane.setScrollX( levelTable.getWidth() - ( levelTable.getColumns() - numberOfColumn - 1 ) * 100 ); //100, because column width is 100 - actor = 80 + 2 * 10 pad
//set debug to see the outline
scrollPane.debug();
this.stage.addActor(scrollPane);
}
I am having difficulties with setting the correct width and height of my canvas element.
I have a ball, that I'd like to bounce back whenever it hits a screen boundary by changing it's vertical velocity. It works, but instead of moving back as soon as it hits the edge of the screen, it goes on for a couple of seconds and THEN moves back. I have these variables to determine the viewport's size:
var left = 0,
right = canvas.width,
top = 0,
bottom = canvas.height;
If my ball's x or y positions are outside these boundaries, the velocity should be changed to a negative one. However, during my animation I console.log it's x position and by the time it reaches the right edge of the screen the value is around 600, which is really strange, since I'm on a 1366x768px monitor.
Also, it doesnt't fully reach the left screen edge, but bounces off like 50px from it.
Any ideas are really appreciated, because I've been stuck on this for quite some time.
You can see a working example here: http://codepen.io/gbnikolov/pen/puiwk
Update your draw to the following.
Ball.prototype.draw = function(ctx) {
ctx.save();
// you've translated to the x and y position of the ball.
ctx.translate(this.x, this.y);
ctx.rotate(this.rotation);
ctx.scale(this.scaleX, this.scaleY);
ctx.lineWidth = this.lineWidth;
ctx.fillStyle = this.color;
ctx.strokeStyle = this.strokeColor;
ctx.beginPath();
// Draw at 0,0 since we are already translated to the x and y.
ctx.arc(0, 0, this.radius, 0, Math.PI * 2, true);
ctx.closePath();
ctx.fill();
ctx.stroke();
ctx.restore();
}
Live Demo
Your problem is in the draw method, you're translating the context and then making the arc at the x and y of the ball so if you translate to 20, 20 for example and then draw at 20,20 your ball is actually at 40,40.
When I compile my hero doesn't touch the floor but stops anyways a few pixels above. I figured if I traced both bodies and their respective sprites I'd know which ones aren't coincinding.
trace("Hero: ", hero.position.y, "/", heroSprite.y);
trace("Floor: ", floor.position.y, "/", floorSprite.y);
I get the following,
Hero: 470.2(...) / 470.2
Floor: 0 / 0
Also, how is the floor position 0 in its y property when:
createWall(stage.stageWidth/2, 500, 100, 30); //(y = 500)
I read that while the nape body 'registration point' is in the middle, the sprite one is in the upper-left corner so when giving the sprite the same x and y of the body it won't match. Below the sprite will be out of position.
public function createWall(x:Number, y:Number, width:Number, height:Number):void
{
wall.shapes.add(new Polygon(Polygon.rect(x, y, width, height)));
wall.space = space;
wallSprite.graphics.beginFill(0x000000);
wallSprite.graphics.drawRect(x, y, width, height);
wallSprite.graphics.endFill;
addChild(wallSprite);
wall.userData.sprite = (wallSprite);
addChild(wall.userData.sprite);
}
I tried wallSprite.graphics.drawRect(-width/2, -height/2, width, height); but didn't work. Althought I believe the problem is there, placing the sprite properly.
Drawing does not affect the position of an object. In your case the wall is at 0,0 and you draw at x:stage.stageWidth/2 , y: 500 but that's not going to become the wall coordinates, those are still 0,0 anyway.
I have a slider that controls a movie clip by dragging it through the frames to animate and this works great when dragging from left to right, But i want the slider to start in the middle and drag through the movie clip from a center point being able to go 350 to the right and 350 to the left.
Is this possible?
Heres my code so far and as you can see it drags 350 to the right through dialSpin_mc.
Is there a way to make the slider start at a certain frame and go backwards and forwards?
dialSpin_mc.stop();
slider_mc.knob_mc.buttonMode = true;
slider_mc.knob_mc.addEventListener(MouseEvent.MOUSE_DOWN, onDragKnob);
stage.addEventListener(MouseEvent.MOUSE_UP, onReleaseKnob)
slider_mc.knob_mc.buttonMode = true;
function onDragKnob(myEvent:Event):void
{
slider_mc.knob_mc.startDrag(false, new Rectangle(0,0,350,0));
slider_mc.knob_mc.addEventListener(Event.ENTER_FRAME, onScrubMovie);
}
function onReleaseKnob(myEvent:Event):void
{
slider_mc.knob_mc.stopDrag();
slider_mc.knob_mc.removeEventListener(Event.ENTER_FRAME, onScrubMovie);
}
function onScrubMovie(myEvent:Event):void {
var playHead:int=Math.round((slider_mc.knob_mc.x/350*8)+1);
dialSpin_mc.gotoAndStop(playHead);
}
As discussed in comments this is how you could code the slider functionality without using the startDrag() and stopDrag() functions.
The idea is that when you press the mouse button down over the slider, an ENTER_FRAME listener is created. Every frame the sliders X position will be updated to match the mouseX position, and to make sure it can only travel 175 pixels either way we also check the sliders new position.
After making sure the sliders position is valid, you can use the same code to set the dialSpin_mc frame.
Once the mouse button is released, the enter frame listener is removed.
The sliderOrigin declared at the top of the code will need to be changed to whatever is appropriate for your project (whatever the sliders xposition is when you move it to the middle of the slide area rather than the very left).
var sliderOrigin:int = 150; // The x position the slider is in when in the center of the slide bar
slider_mc.x = sliderOrigin;
slider_mc.addEventListener(MouseEvent.MOUSE_DOWN, mDown);
slider_mc.addEventListener(MouseEvent.MOUSE_UP, mUp);
function mDown(e:MouseEvent):void
{
addEventListener(Event.ENTER_FRAME, UpdateDrag);
}
function mUp(e:MouseEvent):void
{
removeEventListener(Event.ENTER_FRAME, UpdateDrag);
}
function UpdateDrag(e:Event):void
{
slider_mc.x = mouseX;
// Check if the slider is 'out of bounds' and change its position if it is
if(slider_mc.x < sliderOrigin - 175)
slider_mc.x = sliderOrigin - 175;
else if(slider_mc.x > sliderOrigin + 175)
slider_mc.x = sliderOrigin + 175
var playHead:int = Math.round((slider_mc.x/350*8)+1);
dialSpin_mc.gotoAndStop(playHead);
}
Depending on the start position of the slider the range of playHead will change (so if the slider starts at x pos 200 the range would be between 2 and 10, at x pos 400 the range is between 6 and 14 - simple fix by changing the offset from +1 to whatever is necassary).
i'm drawing a line with a gradient style, but for some reason the line's x position appears to be about 4 or 5 instead of 0 when added to the display list. tracing the line's x postion returns 0, but it's clearly visible that the line is not positioned at that coordinate.
if i remove the gradient box then it is positioned correctly, but that's not a solution since i would lose the gradient.
i'm targeting FlashPlayer 11 / AIR 3 using Flash Builder. any ideas?
//Constants
private static const LINE_COLOR:uint = 0xFFFFFF;
private static const LINE_WIDTH:uint = 10;
//Variables
private var volumeLineShape:Shape = new Shape();
private var volumeLineMatrix:Matrix = new Matrix();
// ~
volumeLineMatrix.createGradientBox(widthProperty, heightProperty);
volumeLineShape.graphics.clear();
volumeLineShape.graphics.lineStyle(LINE_WIDTH, 0, 1.0, false, LineScaleMode.NONE, CapsStyle.NONE);
volumeLineShape.graphics.lineGradientStyle(GradientType.LINEAR, [LINE_COLOR, LINE_COLOR, LINE_COLOR], [0.0, 1.0, 0.0], [0, 255 * toneProperty, 255], volumeLineMatrix);
volumeLineShape.graphics.moveTo(0, heightProperty - heightProperty * volumeProperty);
volumeLineShape.graphics.lineTo(widthProperty, heightProperty - heightProperty * volumeProperty);
Just gived some static values to width and position, and it drawed a line that left corner and line is transparent at corner. Check your values and change your background to see white transparent part of line.
volumeLineShape.graphics.clear();
volumeLineShape.graphics.lineStyle(LINE_WIDTH, 0, 1.0, false, LineScaleMode.NONE, CapsStyle.NONE);
volumeLineShape.graphics.lineGradientStyle(GradientType.LINEAR, [LINE_COLOR, LINE_COLOR, LINE_COLOR], [0.0, 1.0, 0.0], [0, 255 * toneProperty, 255], volumeLineMatrix);
volumeLineShape.graphics.moveTo(0, 0);
volumeLineShape.graphics.lineTo(100, 100);
it's a banding problem. setting zero position at alpha 0 and another zero position at alpha 1 causes issues.