Action Script 3. Animation loop forever after gotoAndStop() and have lag during animation when character have collisions - actionscript-3

I'm creating simple flash game. I have problem, animation loop forever after I user gotoAndStop() and I have lag when during animation if character have collision with ground or any stage (if character flying on the air don't have any lags)
Here is collision list:
var myCollisionList:CollisionList = new CollisionList(Hero);
myCollisionList.addItem(ground);
myCollisionList.addItem(ground3);
myCollisionList.addItem(ground5);
myCollisionList.addItem(ground4);
And here is my part of code where jumping with animation.
if(Hero.y_speed>0 && myCollisionList.checkCollisions().length > 0 )
{
Hero.y_speed=0;
Hero.x_speed=0;
if(space)
{
if (ground.hitTestPoint(Hero.x + 28, Hero.y+20, true))
{
Hero.gotoAndStop("attack");
stop();
Hero.y_speed = -20;
}
}
}
UPDATE:
Screenshot of the map:
UPDATE 2:
Here is part of code for move character to left (to right side the same) side, I know Its terrible, but I don't know how to make It better.
pakopos - name of CollisionList
fonas - background
var pakopos:CollisionList = new CollisionList(Hero);
pakopos.addItem(ground);
pakopos.addItem(ground3);
pakopos.addItem(ground5);
pakopos.addItem(ground4);
if(left){
Hero.x_speed = -walkspeed;
setDirection(1);
if(pakopos.checkCollisions().length > 0) {
if (ground5.hitTestPoint(Hero.x - 26, Hero.y-120, true)) {
trace("Touching left side - ground5");
ground5.x += 0;
ground4.x += 0;
ground3.x += 0;
fonas.x += 0;
Enemy.x += 0;
}
else if (Enemy.hitTestPoint(Hero.x - 26, Hero.y-120, true)) {
trace("Touching Enemy");
ground5.x += 0;
ground4.x += 0;
ground3.x += 0;
fonas.x += 0;
Enemy.x += 0;
}
else if (ground3.hitTestPoint(Hero.x - 26, Hero.y-120, true)) {
trace("Touching left side - ground3");
ground5.x += 0;
ground4.x += 0;
ground3.x += 0;
fonas.x += 0;
Enemy.x += 0;
}
else if (ground4.hitTestPoint(Hero.x - 26, Hero.y-120, true)) {
trace("Touching left side - ground4");
ground5.x += 0;
ground4.x += 0;
ground3.x += 0;
fonas.x += 0;
Enemy.x += 0;
}else
{
Hero.x_speed = 0;
ground5.x += 4;
ground4.x += 4;
ground3.x += 4;
fonas.x += 4;
Enemy.x += 4;
}}
else {
ground5.x += 4;
ground4.x += 4;
ground3.x += 4;
fonas.x += 4;
Enemy.x += 4;
}}

Your code is very cryptic so it's hard to say what's going on without actually debugging it but my guess is that you're checking collisions multiple times every time your posted code runs. You should check the documentation of the checkCollisions() function that you use since it seems to return an array of results. It likely gives you all collisions that it found among the objects in the collision list so you don't have to call hitTestPoint() directly afterwards.
Edit:
I'm not familiar with CDK that you use in your code but it returns an array of collision results where each result has the colliding objects, their angle and if they're overlapping. For what you're trying to do it seems like an overkill but as I said, I'm not familiar with it - it may be a lot faster then hitTestPoint().
I'd recommend using only one hit test method - either use CDK or use hitTestPoint() but not both. Both will give you pixel perfect detection results. If you use CDK, read the documentation on how checkCollisions() works. You'd have to do something like this:
...
var oResults:Array = pakopos.checkCollisions();
var nCount:int = oResults.length;
if (nCount > 0)
{
for ( var i:int = 0; i <nCount; i++ )
{
var oHit:Object = oResults[i];
// TODO check `oHit.object1` and `oHit.object2` to see which objects
// collided and do something based on that
// You may have multiple results since your hero may collide with
// 'ground' and 'ground4' at the same time.
}
}
Your collision group (pakopos) setup for CDK seems to be off - you won't have to determine if there's a collision between all the objects in your group - I assume you don't care if ground collides with ground4 but you added both to your collision list.
I think (not sure) that checkCollisions() tries to check all objects in the group against all other objects. What you need is check one object (Hero) against a list of objects (the various ground objects). That's a massive difference between the number of checks. This and your extra calls to hitTestPoint() can easily account for your lag.

Related

as3 move object back and forth on iPad or tablet

I am working on a 2d project for iPad where a ball moves back and forth. When it hits the border it has to rotate a bit and roll back in another direction and leaving a child behind that also starts to move and follows a random path. (I made the project in Scratch. See code.)
ball_mc.addEventListener(Event.ENTER_FRAME, moveBall);
function moveBall(e:Event):void {
ball_mc.rotation += 1;
if (ball_mc.x < (stage.stageWidth - 100)) {
//trace('move forward');
ball_mc.x += 2;
} else {
// while(ball_mc.x > 100)?
// trace('move backward');
// how does it roll back?
ball_mc.x += -2;
}
}
}
You need a variable that holds the value of the direction or velocity. This variable should be changed to 2 if the ball passes a left side boundary and changed to -2 if the ball passes a right side boundary. Like this:
var ballSpeed:Number = 0; // this should go where you declare global variables such as at the beginning of your main class before the constructor
ball_mc.addEventListener(Event.ENTER_FRAME, moveBall);
function moveBall(e:Event):void {
ball_mc.rotation += ballSpeed;
if (ball_mc.x < (stage.stageWidth - 100)) {
ballSpeed = 2;
} else if (ball_mc.x > stage.stageWidth){
ballSpeed = -2;
}

Moving objects on the stage

Let's say I have 5 objects in an array and I move all them along x-axis like this:
vx = 5;
for (i:int = 0; i < objects.length; i++)
{
objects[i].x += vx;
}
I would like to make this.
If any object from array 'objects' hit PointA, move all objects from that array to left side, for example set vx *= -1;
I can make only this:
for (i:int = 0; i < objects.length; i++)
{
// move right
objects[i].x += vx;
if (objects[i].hitTest(PointA))
{
// move left
vx *= -1;
}
}
This will change object's direction, but I need to wait all objets hit PointA.
How to change the direction of all objects in array, if any of them hit PointA?
I don't know action script but you should set a boolean outside the for loop, like bGoingRight
Check that this is true and move objects right, if its false move the objects left. When you pass the hitTest you should changed the boolean to false.
Rough Example
var bGoRight:Boolean = true;
for (i:int = 0; i < objects.length; i++)
{
if(bGoRight)
{
// move right
objects[i].x += vx;
}
else
{
// move left
vx *= -1;
}
if (objects[i].hitTest(PointA))
{
// if any object hit the point, set the flag to move left
bGoRight = false;
}
}
So you'll need to check the objects that have already hit PointA, store them, then check if the updated storage count is equivalent to your objects array. Then when that case is satisfied you can change the vx variable. This could look something like this:
//set a variable for storing collided object references
//note: if you are doing this in the IDE remove the 'private' attribute
private var _contactList:Array = [];
for (i:int = 0; i < objects.length; i++)
{
// move right
objects[i].x += vx;
if (objects[i].hitTest(PointA))
{
if( contactList.length == objects.length ) {
// move left
vx *= -1;
//clear our contact list
contactList.length = 0;
}
else if ( noContact( objects[i] ) ) {
contactList.push( objects[i] );
}
}
}
Then the function in the else if statement noContact(), again if you are doing this in the IDE you will need to remove the private attribute.
private function noContact( obj:* ):Boolean {
if ( contactList.indexOf( obj ) != -1 ) {
return false;
}
return true;
}
Another way you can do this is like this (a boolean way as stated in the other answer), but is reliant on your storage setup correct:
//set this variable for directionRight (boolean)
private var directionRight:Boolean = true;
for (i:int = 0; i < objects.length; i++)
{
// move right
objects[i].x += vx;
if (objects[i].hitTest(PointA))
{
//we are moving to the right, object[i] is the last object
if( i == objects.length-1 && directionRight ) {
// move left
directionRight = !directionRight;
vx *= -1;
}
else if ( i == 0 && !directionRight ) ) {
// move right
directionRight = !directionRight;
vx *= -1;
}
}
}

Flash (AS3) Movieclip Rotation

if (rotCW)
{
tramp1.rotation += 3;
if (tramp1.rotation = 90){
tramp1.rotation += 0;
}
}
I'm trying to make it so that if the movieclip's rotation is 90, its rotation speed is 0.
But every time I press the ' key (which triggers rotCW), the movieclip's rotation just goes to 90.
your problem is assignment within the 2nd condition. you need to use "=="
if (rotCW)
{
tramp1.rotation += 3;
if (tramp1.rotation == 90){
tramp1.rotation += 0;
}
}
edit: the +=3 line you have executes regardless of angle. if you are passing 90 and dont want to, you can test for the opposite condition and increment in that case. eg: if less than 90.
if (rotCW)
{
if (tramp1.rotation < 90){
tramp1.rotation += 3;
}
}

"snake" in html5 canvas. Math curve issue

Demo
I am trying to make a "snake" game in html 5 canvas. But i have a problem getting the snake to move the right direction. I would assume that the following code would make the snake move horizontal on 0 and 180 degrees, and vertical on 90 and 270 degrees, this is however not the case. What am i doing wrong here? (Use the left and right arrows to navigate).
function move(direction) {
if(direction == left) {
angel = (angel - 5) % 360;
if(angel < 0) angel += 360;
} else if (direction == right) {
angel = (angel + 5) % 360;
}
x = x + Math.floor(Math.cos(angel*0.0174532925)*5);
y = y + Math.floor(Math.sin(angel*0.0174532925)*5);
$("#infoBar").html("Direction: " + direction + " angel: " + angel);
drawPoint(x,y);
}
The multiplier is of course degrees to radiant. But somehow 270 degrees is not a straight vertical line, as i would assumed that it was. What am i doing wrong?
Javascript file.
Html file.
Because of floating point math.
cos(270 degrees) = 0
Buuuut:
Math.cos((Math.PI/180)*270) is not 0. It is: -1.836909530733566e-16
In other words it is -0.000000000000000183, etc. Very close to zero, but slightly less than zero!
But you're using Math.floor, and Math.floor that number (or Math.floor(-0.1) for that matter) = -1.
You don't want that.
Use Math.round instead of Math.floor.
Here's a live example of it fixed for you: http://jsfiddle.net/UtPJz/3/
I haven't compiled the code segment but you could do somehting like this:
function move(direction) {
switch(direction)
{
case RIGHT:
stepX = 1;
stepY = 0;
break;
case LEFT:
stepX = -1;
stepY = 0;
break;
case UP:
stepX = 0;
stepY = -1;
break;
case DOWN:
stepX = 0;
stepY = 1;
break;
}
x += stepX;
y += stepY;
drawPoint(x,y);
}

ActionScript 3 - Walls don't collide properly

For several weeks I'm been trying to make my topdown game. It went well for some time, but then at some point I wanted to create a scrolling map with walls everywhere. Now, to make it easy to create the map (and add more later) I made a class called "Wall" which I will hit test. This works, when it hits, the map must stop scrolling. It does, so good so far.
Now, when the player moves away from the object, I want the map to be able to scroll again, this works too, but now the player can't move to the side the player came from. I know this is because I need to define the sides, where the player enters, in order tell the game which movement must be set to zero at that point.
You can see the code here:
public function AddWalls(player:MovieClip)
{
WallObjects = new Array();
for (var i:int = 0; i < this.numChildren; i++)
{
var mc = this.getChildAt(i);
if (mc is Wall)
{
var wallobj:Object = new Object();
wallobj.mc = mc;
wallobj.leftside = mc.x;
wallobj.rightside = mc.x + mc.width;
wallobj.topside = mc.y;
wallobj.bottomside = mc.y + mc.height;
wallobj.width = mc.width;
wallobj.height = mc.height;
WallObjects.push(wallobj);
}
}
}
public function EnableCollisionWithWalls():void
{
for (var k:int = 0; k < WallObjects.length; k++)
{
//if (player.y > WallObjects[k].topside && player.y < WallObjects[k].bottomside && player.x > WallObjects[k].leftside && player.x < WallObjects[k].rightside)
if (player.hitTestObject(WallObjects[k].mc))
{
if (player.x > WallObjects[k].leftside && player.x < WallObjects[k].leftside+15)
{
Lefthit = true;
trace(DebugVar);
DebugVar++;
player.x = WallObjects[k].leftside;
Scroll_x = 0;
}
else
if ( player.x < WallObjects[k].leftside -1 || (player.y > WallObjects[k].leftside ))
{
Lefthit = false;
}
if (player.hitTestObject(derp))
{
Lefthit = false;
}
}
}
}
public function EnableMovement():void
{
map.x += Scroll_x;
map.y += Scroll_y;
for (var i:int = 0; i < this.numChildren; i++)
{
var mc = this.getChildAt(i);
if (mc is Wall)
{
mc.x += Scroll_x;
mc.y += Scroll_y;
}
}
}
public function MovementKeysDown(move:KeyboardEvent):void
{
var Speed:int = -5;
switch (move.keyCode)
{
case 37: // venstre knap
Scroll_x = -Speed;
break;
case 38: // op
Scroll_y = -Speed;
break;
case 39: // højre knap
Scroll_x = Speed;
if (Lefthit)
{
Scroll_x = 0;
}
break;
case 40: // ned
Scroll_y = Speed;
break;
default:
}
}
public function MovementKeysUp(move:KeyboardEvent):void
{
switch (move.keyCode)
{
case 37:
Scroll_x = 0;
break;
case 38:
Scroll_y = 0;
break;
case 39:
Scroll_x = 0;
break;
case 40:
Scroll_y = 0;
break;
default:
}
}
Might be some syntax errors (since I removed some code in this editor).
You can see the current version here.
In this version the scroll keeps on going. I did come up with a "fix" for it, by check if the player was 1 pixel away from the movieclip, inside the hit test (which for some reason works, which I guess it shouldn't since it doesn't hit anymore) and then setting the Lefthit to false. However this is not a good solution and if you continue up or down away from the movieclip, you are still not able to go right anymore...
I've been baffled by this for a long time, so I thought it was about time I asked for help. I couldn't find anything on how to control movement in a top-down game, with a scrolling map + wall :/
The simplest (but not most resource friendly) solution (if you anyway have a single storage for walls) is iterating through the walls and instead of using the Flash default hitTest (I don't like the way it works since ActionScript 2) - just check the coordinates and if you see that there's going to be a collision on the next simulation step - handle it according to the game logic.
The most useful optimization for this algorithm is creating a filter/data structure for getting only walls that are near to the player and so can be affected to the test for collisions.