Getting doubles with animated sprite in libgdx - libgdx

I am making a small simplistic game in libgdx to learn the basics and stuff. I tried my hand at having an animated character. One problem though, the first of the 4 frames shows fine but the second frame is shown and right next to it the third is rendered. The same for the third, it renders the last frame beside it. The first and last frame have no "Double" beside it though.
Character frames = C1 C2 C3 C4
1st frame - C1
2nd frame - C2 C3
3rd frame - C3 C4
4th frame(last) - C4
As for the code:
......
walk = new Animation(0.0015f, assets.leftframes);
.......
statetime += Gdx.graphics.getDeltaTime();
currentframe = walk.getKeyFrame(statetime, true);
batcher.draw(currentframe, character.x, character.y);
.......
I left out rest of the code to reduce clutter but I can show it if necessary.
Does anyone have any idea what the problem is?
Thanks in advance.
EDIT: Terrible paint skills but here is the picture of each frame as rendered:
Picture

It seems your second and third frames width are double of what they should be.
Check when you create your animation, all keyframes must have same width.
And your time between frames is too fast, try 0.2F.
EDIT (because your comment):
Thats what is wrong, every new frame gets a bigger width.
Replace this:
leftframes[x] = new TextureRegion(left, x * 32, 0, (x+1) * 32, 48);
With this:
leftframes[x] = new TextureRegion(left, x * 32, 0, 32, 48);

Related

Change page format after writeHTML

I generate page using writeHTML under TCPDF. My page is made of 3 blocs (top, middle, bottom). I rotate the top one by 180 and middle one by 90.
Final page must be A4 landscape.
It works fine (as you can see on the snap) except for a small detail: as the middle part turn of 90°, this mean BEFORE the rotation the height of this part is higher than the heigt of the A4 landscape.
The only way I've found to have a correct display even with a middle block of great height (before rotation), is to perform the rotation using an A3 Portrait page. As on the picture.
So 2 questions:
Any idea of another way of doing?
If there is no other option, is it possible to generate the PDF in A3 portrait (using WriteHTML) and AFTER, crop the page to save (output) only the top part of the page, so to have a A4 landscape? (using TCPDF, not "manually")
For those interested: As I've dynamic data, I need to search each time for the center of rotation and the translation I must apply to the bootom block for it goes up against the middle block after the rotation. For that, I add "tcpdf method" tag on my HTML template, perform a writeHTML which call functions GetX, GetY and save the coord. for rotaton and also relative position of middle and bottom block (for bottom block translation)
Then I "rollback", set the coord in the template and perform a second writeHTML.
Lemme guess. If it's longer, the page breaks and it only rotates the content that had fit on the page while also possibly throwing off values you were expecting for GetX and GetY?
Disable the automatic page break and it should work as you expect.
$pdf->SetAutoPageBreak(FALSE, 0);
This way, it'll just draw off-page where it needs to without a page break interfering.
Edit: However I was wrong, as noted in the comment, that GetY would return a coordinate outside of the page. It does not.
So, we'll need to do our height check on a larger page, and then redraw on a new (properly sized) page once we know what we need to for layout, and destroy the original.
You can do that with transactions or with AddPage and DeletePage.
I tested with AddPage and DeletePage.
//.....
$pdf = new TCPDF_HELPER('L', 'pt',
array(8*72,5*72), true, 'UTF-8', false);
// set auto page breaks
$pdf->SetAutoPageBreak(FALSE, 0);
// set image scale factor
$pdf->setImageScale(PDF_IMAGE_SCALE_RATIO);
$pdf->setFontSubsetting(true);
$fontname = TCPDF_FONTS::addTTFfont(dirname(__FILE__).'/playtime.ttf', 'TrueTypeUnicode', '', 96);
$pdf->setFont($fontname, '', 16);
//I'm using a points and a ridiculous 19 inch by 19 inch custom size.
//We'll use this one to get the proper offset with `GetY`
$pdf->AddPage('L', array(19*72, 19*72));
$pdf->SetXY(1, 45);
$pdf->setFillColor(255,255,230);
$column = <<<EOT
<p>WHITE APPLE COUNTRY HORSE STABLE BATTERY PIG SHEEP KANE CICI LOLIPOP</p>
<p>WHITE APPLE COUNTRY HORSE STABLE BATTERY PIG SHEEP KANE CICI LOLIPOP</p>
<p>WHITE APPLE COUNTRY HORSE STABLE BATTERY PIG SHEEP KANE CICI LOLIPOP ioj</p>
<p>WHITE APPLE COUNTRY HORSE STABLE BATTERY PIG SHEEP KANE CICI LOLIPOP ioj</p>
EOT;
//Get our multicell's final offset.
$pdf->WriteHTMLCell(80, '', '', 40, $column, 1, 2, 1, false, 'J', true);
$stopposition = $pdf->GetY();
//Now that we have our needed coordinates,
//Add a new page in our desired format.
$pdf->AddPage('L', array(8*72,5*72));
$pdf->StartTransform();
$pdf->Rotate(90, 40, 70);
$pdf->WriteHTMLCell(80, '', '', 40, $column, 1, 0, 1, true, 'J', true);
$pdf->StopTransform();
$pdf->SetX(20);
$pdf->SetY(-20);
$pdf->Write('', "End of column, pre-rotation: $stopposition pt");
//Delete our larger calculation page.
$pdf->DeletePage(1);
//.....
Even if EPB answer is a very interesting one and work in some cases, in my case the result was the same.
So i've found a different way of doing. It's NOT really a "pure answer" but a good trick.
I create my page in A3 Portrait and rotate the data in order to get all the data in the upper part.
Then, I use a tool named "pdfposter" which I call from PHP, in order to split the A3 portrait PDF in two A4 Landscape.
So, after the writeHTML() I do:
$path_a3 = __DIR__ . '/../tmp/a3.pdf';
$path_a4 = __DIR__ . '/../tmp/a4.pdf';
$pdf->Output($path_a3, 'F');
$pdfposter = "pdfposter -m a4 -p 2x1a4 ".$path_a3." ".$path_a4;
exec($pdfposter,$retArr, $retVal);
After that, I've a a4.pdf with two A4 pages.
Notice just one detail: the page made wih TCPDF with rotated data are NOT compatible with pdfposter 0.6! You have to install version 07.post1 (latest from Git).

Jumping back and forth inside a Movieclip with a button?

So, I'm very much a beginner in AS3. I've been reading and figuring out things as I go, though I can't wrap my head around this.
So, I have 4 frames. Each frame has a different movie clip, MC1,MC2,MC3,MC4
Inside those four movie clips, there is another movie clip with the same instance name for each: BC, and inside that movie clip there are two frames. Frame 1 has a dot, and frame 2 does not.
MC1>BC>(2 frames)
MC2>BC>(2 frames)
and so on....
What I'm trying to do: I wanted to see if there was any way to control the frame navigation of BC inside all four MC clips at the same time with one button.
I want to switch back and fourth between the two frames inside the BC movie clip.
I'm at a loss, I've tried quite a few things.
You should be able to do so by giving them all the same instance name (so long as there is only ever one of them on screen at once).
So lets say you have a button that spans all 4 frames with an instance name of navBtn and you gave each of the MC1-4 clips the same instance name of MC. You could do the following on frame 1:
navBtn.addEventListener(MouseEvent.CLICK, navBtnClick);
function navBtnClick(e:Event):void {
if(MC.BC.currentFrame == 2){
MC.BC.gotoAndStop(1);
}else{
MC.BC.gotoAndStop(2);
}
}
Reading your question again, perhaps what are looking for is to have each clip automatically go to the same frame for their BC child when they load? If that is the case, then follow the example in the comment on your question by #Organis. Here is one way you could accomplish this:
Create two variable on frame one of your main timeline:
var BC_NAV_CHANGE:String = "BC_NAV_CHANGE";
var BC_CurFrame:int = 1;
Then, when you need to change the frame of the BC objects, do the following:
//create a function that you call when you want to change the BC frame
function toggleBCFrame(e:Event = null){
MovieClip(root).BC_CurFrame = MovieClip(root).BC_CurFrame == 1 ? 2 : 1;
//the line above is a if/else shorthand, that is setting a new value to the `BC_CurFrame` var,
//if the current value is `1`, it will set it to `2`, otherwise it will set it to `1`
MovieClip(root).dispatchEvent(new Event(MovieClip(root).BC_NAV_CHANGE));
//this line (above) dispatches a event telling anything that's listening that the variable has changed
}
If the code above is on the main timeline, you can forgo all the MovieClip(root). parts of the code.
Now, on the timeline of your BC MovieClip(s), put the following code:
//create a function that goes to and stops at the frame stored in the global variable
function updateFrame(e:Event = null){
gotoAndStop(MovieClip(root).BC_CurFrame);
}
//next listen for the BC_NAV_CHANGE event, and call the above update function above any time that event happens
MovieClip(root).addEventListener(MovieClip(root).BC_NAV_CHANGE, updateFrame);
//lastly, call the update function right away so when the BC clips loads it immediately goes to the correct frame
updateFrame();

How to use a single script for multiple frames

I've build a topotrainer in Flash consisting of 50 states.
For every state I made a frame. The code of these 50 frames should be the same for all, while the graphics defer. If I put the code on the first of the 50 frames it is only working there. If I put the code at every frame I get a lot of errors, because all the functions are doublated.
Is there a way for all the 52 frames to run the same code?
Thanks for your time,
More info:
The red square is indicating the 50 states. That is pure graphicly.
I made a seperate layer for all the coding.
The blue circle indicates the (working) code for one single state-frame.
All the 50 graphical frames want to use this code.
#Atriace: is your explanation solving this particular problem?
Thanks,
Justin
Update
The important thing to be aware with frames is that things don't exist until after they're initialized. Assume that on Frame1 we have the blue square, and on Frame2 we have the red circle.
The play-head starts on the left and works its way to the right. As it arrives at each frame, it then creates whatever it finds there for it, be it a symbol or code. This means that if we try to hook up the red circle with an event listener on Frame1 it will fail; naturally because red circle hasn't been created yet.
stop();
function hello(e:Event):void {
var destination:int = (currentFrame == 1) ? 2 : 1;
trace("Hello " + e.currentTarget.name + ": " + currentFrame + " of " + totalFrames + " > " + destination)
gotoAndStop(destination)
}
BlueSquare.addEventListener("click", hello);
RedCircle.addEventListener("click", hello); // <<< this will fail
However, if we put that single line on the same frame as when the red circle is created, it will link to hello() correctly and run.

Actionscript 3- Random movement on stage? Also, Boundaries?

I'm trying to code something where there are creatures running back and forth, up and down across the stage, and I the player, have to try to go up to them, and pick them up. There are also boundaries on stage-
The map constraints- a big rectangle box is easy enough to accomplish. I've done this.
The boundaries within the map, which are also rectangles, but instead of bouncing the player back INSIDE the rectangle, I'm trying to do the opposite- keep the player out of it.
My code for it looks like this as of now:
//Conditions that check if player/monsters are hittesting the boxes (rocks
//and stuff), then if correct, bounce them away. Following code excludes
//the monsters for simplicity.
if((mcPlayer.x - aBounceBox[b].x) < 0 && mcPlayer.y <= (aBounceBox[b].y + aBounceBox[b].height/2) && mcPlayer.y >= (aBounceBox[b].y - aBounceBox[b].height/2))
{
mcPlayer.x = aBounceBox[b].x - aBounceBox[b].width/2 - mcPlayer.width/2;
}
//Duplicate above code for right side of box here
if((mcPlayer.y - (aBounceBox[b].y + aBounceBox[b].height/2)) < 0 && (mcPlayer.x + mcPlayer.width/2) > (aBounceBox[b].x - aBounceBox[b].width/2) && (mcPlayer.x - mcPlayer.width/2) < (aBounceBox[b].x + aBounceBox[b].width/2))
{
mcPlayer.y = aBounceBox[b].y + aBounceBox[b].height/2;
}
//Duplicate above code for Upper boundary of box here
The above doesn't work very well because the code to bounce for the left and right sides of the box conflicts with the upper and lower parts of the box I'm hit-testing for. Any ideas how to do that smoothly?
Also, another problem I am having is the pathing for the monsters in the game. I'm trying to get them to do the following:
Move around "organically", or a little randomly- move a little, stop. If they encounter a boundary, they'd stop and move, elsewhere. Not concerned where to, as long as they stop moving into rocks and trees, things like that.
Not overlap as much as possible as the move around on stage.
To push each other apart if they are overlapping, although I'd like to allow them to overlap very slightly.
I'm building that code slowly, but I thought I'd just ask if anyone has any ideas on how to do that.
To answer your first question, you may try to implement a new class/object which indicates the xy-offset between two display objects. In order to illustrate the idea more clearly, you can have a function similar to this:
public function getOffset(source:DisplayObject, target:DisplayObject):Object {
var dx:Number = target.x - source.x;
var dy:Number = target.y - source.y;
return { x:dx, y:dy };
}
Check if the hero character is colliding with another object first by hitTestObject(displayObj) of DisplayObject class. Proceed if the result is true.
Suppose you pass in your hero character as the source object, and another obstacle as the target object,
var offset:Object = getOffset(my_hero.mc, some_obstacle.mc);
After getting the resulting offset values, compare the magnitude (absolute value) of offset.x and offset.y. The outcome can be summarized as follows:
Let absDx be Math.abs(offset.x), absDy be Math.abs(offset.y),
absDx < absDy
offset.y < 0, target is above source
offset.y > 0, target is below source
absDx > absDy
offset.x < 0, target is to the left of source
offset.x > 0, target is to the right of source
absDx == absDy
refer to one of the above cases, doesn't really matter
Then you can update the position of your hero character according to different situations.
For your second question concerning implementing a very simple AI algorithm for your creatures, you can make use of the strategy above for your creatures to verify if they collide with any other stuff or not. If they do collide, assign them other directions of movement, or even simpler, just flip the signs(+/-) of their velocities and they will travel in opposite directions.
It is easier to implement simple algorithms first. Once it is working, you can apply whatever enhancements you like afterwards. For example, change directions when reaching junctions or per 3 seconds etc.

How do I HitTest two rotating objects properly? (A way to avoid bounding boxes)

I took an intro level flash course in college this semester and our final task was to make a mini-flash game.
I had to make a pipe-dream type game where there are a number of levels, and in each level you have to align the pipes so that the water flows and then you can pass to the next level.
I successfully made the first level, but upon making the second level,
where I placed a lot of curved pipes (by curved pipes I mean the attached image: ![Curved Pipe]: (http://imgur.com/mwpXAMn) )
I discovered that the method I use to decide when a level is complete is not working properly.
I was using HitTestObject, basically, I was testing whether 2 objects, Pipe_1, and Pipe_2, were intersecting. If all pipes intersected in the correct way, then procession to the next level is granted.
The problem with this I discovered is that flash has bounding boxes for movie clips you make, and that HitestObject uses bounding boxes to test for hits. Therefore, when you rotate a leftpipe so that it does not touch a straight pipe on screen, the bounding boxes still touch and it returns "collision" when in fact it is not actually touching on screen.
I looked up and found that you can use HitTestPoint but I can't figure out how to somehow make dynamic variables (that change upon rotation of object) that store one or two specific points on the leftpipe, say the two ends of it.
Once If I figure out how to get these values into a variable correctly, then I can figure out how to do HitTestpoint.
Also, I know of the LocaltoGlobal function but no matter what I try it keeps coming up with:
"Scene 1, Layer 'Layer 1', Frame 1, Line 30 1118: Implicit coercion of a value with static type Object to a possibly unrelated type flash.geom:Point."
meaning I don't know the correct code to store an x and a y coordinate as dynamic variables.
edit: ok since a person asked, I hunted this piece of code off the web and this is the one I was trying to play around with but to no avail:
How to use HitTest for 2 rectangles, r1 is rectangle 1 r2 is rectangle 2.
var r1width:Number = 135.0; //width of retangle 1 whith rotation 0
var r2width:Number = 93.0; //width of retangle 2 whith rotation 0
var p1:Object = {x:(r1width/2), y:(r1width/2)};
var p2:Object = {x:(-r1width/2), y:(r1width/2)};
var p3:Object = {x:(-r1width/2), y:(-r1width/2)};
var p4:Object = {x:(r1width/2), y:(-r1width/2)};
r1.localToGlobal(p1);
r1.localToGlobal(p2);
r1.localToGlobal(p3);
r1.localToGlobal(p4);
var p5:Object = {x:(r2width/2), y:(r2width/2)};
var p6:Object = {x:(-r2width/2), y:(r2width/2)};
var p7:Object = {x:(-r2width/2), y:(-r2width/2)};
var p8:Object = {x:(r2width/2), y:(-r2width/2)};
r2.localToGlobal(p5);
r2.localToGlobal(p6);
r2.localToGlobal(p7);
r2.localToGlobal(p8);
if((r2.hitTest(p1.x, p1.y, true))||(r2.hitTest(p2.x, p2.y, true))||(r2.hitTest(p3.x,
p3.y, true))||(r2.hitTest(p4.x, p4.y, true)))
{
trace('collision');
}
if((r1.hitTest(p5.x, p5.y, true))||(r1.hitTest(p6.x, p6.y, true))||(r1.hitTest(p7.x,
p7.y, true))||(r1.hitTest(p8.x, p8.y, true)))
{
trace('collision');
}
I did not write this code and it does not work. I'm not sure what "Object" is because I've never used it before, I'm assuming in this case it's sort of acting like a coordinate pair.
Also, this code is to hittest 2 rectangles, whereas I'm using an L-shaped pipe, so the x/y calculation would be quite different I imagine.
This code above gives the same error that I posted before:
Implicit coercion of a value with static type Object to a possibly unrelated type flash.geom:Point.
and it gives it first on line r1.localToGlobal(p1);
Instead of using Object, you need to use Point like so:
var p1:Point = new Point(r1width/2, r1width/2);