How Can I Make AS3 Var Loop move speed on the Y Axis on repeat my university project - actionscript-3

I'm tring to get the car image to move down the screen on the y Axis and make it a repeat and colide with another object
//creates the new Car
for (var c:int=0; c<8; c++){
var newcar = new car();
newcar.x = 55*c;
newcar.y = 100;
EntityArray.push(newcar);
stage.addChild(newcar);
trace("Car Created"+c)
}
How to make it colide with the following and remove it from screen
//creates the new Frog
for (var f:int=0; f<1; f++){
var newfrog = new frog();
newfrog.x = 210;
newfrog.y = 498;
EntityArray.push(newfrog);
stage.addChild(newfrog);
trace("Frog Created"+f)
}
[image][1][1]: https://i.stack.imgur.com/Ihsfx.png

Though I'm quite pleased to hear that today they still tell you about ActionScript at college, it's a bit hard
to give you advice here since I don't know what they've covered yet.
Generally speaking, you could realize this with a simple game loop, that runs periodically and in it's most simple
form:
checks user input (in your case most likely pressing left/right to move the frog)
update game state (move the cars & the frog ; check for collision)
draw everything to screen
For creating the periodical loop, Flash/ActionScript offers a powerful event called ENTER_FRAME. Once started, it
will fire with the framerate of the movie. So if you set your movie to 60fps, it will execute it's callback function
roughly every 17ms.
I assume your instances of Frog and Car extend Flash's Sprite or MovieClip class - so collision detection is also pretty
easy since you can use the inherited hitTestObject() method.
To make things a bit easier though I'd recommend that you don't put the reference to the frog instance inside the EntityArray.
Better use a global reference. (Also, you don't need a for-loop because there's just one frog)
As another sidenote, it's quite common that classnames start with a capital letter.
private var newfrog:frog; // defines a class variable we can access anywhere inside our class
//Later on instantiate new cars and the frog:
for (var c:int=0; c<8; c++){
var newcar = new car();
newcar.x = 55*c;
newcar.y = 100;
EntityArray.push(newcar);
stage.addChild(newcar);
}
newfrog = new frog();
newfrog.x = 210;
newfrog.y = 498;
stage.addChild(newfrog);
addEventListener(Event.ENTER_FRAME, loop); // register an ENTER_FRAME listener for the main game loop
private function loop(e:Event):void
{
var tempCar:car;
for(var a:int=0;a<EntityArray.length;a++)
{
tempCar=EntityArray[a]; // get a car from the EntityArray
tempCar.y++; // move it down on screen
if(tempCar.y>600) // if it's vertical position is greater than 600...
{
tempCar.y=0; // ...move it back to the top
}
if(newfrog.hitTestObject(tempCar)) // evaluates to true, if a car and the frog's bounding boxes overlap
{
trace("there's a collision!"); // do something
}
}
}

Related

AS3 tween object not working with .hitTestObject()

I am having a major problem in my new browser app.
Okay so I made game where different cubes (squares) spawn at the top of the screen and I use the Tween class to make them go down the screen and then disappear.
However I want to detect a collision when a cube hits the player (that is also a flying cube).
I tried everything, truly everything but it does not seem to work. The problematic thing is that when I remove the "Tween" function it does detect collision with the hitTestObject method but when I add the "Tween" line collision won't be detected anymore.
It looks like this:
function enemiesTimer (e:TimerEvent):void
{
newEnemy = new Enemy1();
layer2.addChild(newEnemy);
newEnemy.x = Math.random() * 700;
newEnemy.y = 10;
if (enemiesThere == 0)
{
enemiesThere = true;
player.addEventListener(Event.ENTER_FRAME, collisionDetection)
}
var Tween1:Tween = new Tween(newEnemy, "y", null, newEnemy.y, newEnemy.y+distance, movingTime, true);
}
And the collision detection part:
private function collisionDetection (e:Event):void
{
if (player.hitTestObject(newEnemy))
{
trace("aaa");
}
}
I am desperate for some information/help on the topic, it's been bugging me for days.
Thanks for your time, I would be very happy if someone could help me out^^
First, make sure the "newEnemy" instance and the "player" instance are within the same container. If they are not, their coordinate systems might not match up and could be the source of your problem.
Otherwise, you need to keep a reference to each enemy instance you create. It looks like you are only checking against a single "newEnemy" variable which is being overwritten every time you create a new enemy. This might be why you can successfully detect collision between the player and the most recent "enemy" instance.
So... you need a list of the enemies, you can use an Array for that.
private var enemyList:Array = [];
Every time you create an enemy, push it to the Array.
enemyList.push(newEnemy);
In your "collisionDetection" function, you need to loop through all of the enemies and check if the player is touching any of them.
for(var i:int = 0; i < enemyList.length; i++)
{
var enemy = enemies[i];
if (player.hitTestObject(enemy))
{
trace("Collision Detected!");
enemy.parent.removeChild(enemy); // remove the enemy from the stage
enemies.splice(i, 1); // remove the enemy from the list
}
}
I'd suggest that you move to TweenMax, it just might solve your problem, and in my experience it's much better in every possible way.
Scroll down the following page to see a few variations of this library, I myself use TweenNano, they're completely free of charge:
https://greensock.com/gsap-as
I think some plugins cost money, but I doubt you'll ever need them.

Compositing the stage's last frame

I've created a series of classes that can be used to generate and render images. I want to store a copy of the last frame displayed so I can mix it with the current frame to create a video sustain effect. A brief overview of the classes involved in this example:
MasterContainer: a subclass of Sprite used as the main display object. Generative classes are placed in the MasterContainer, and redrawn when the container is told to render
CustomWave: a subclass of Shape used to contain, draw, and manipulate a GraphicsPath object. One of the aforementioned 'generative classes'
My current attempt involves the use of two MasterContainer objects - one for the current frame, and one for the last frame. If I'm not mistaken, the current appearance of one MasterContainer (and its children) can be copied to the other with a command like lastMaster.graphics.copyFrom(master.graphics);. Consider the following code:
var time:Number;
var master:MasterContainer = new MasterContainer(); //current frame
var lastMaster:MasterContainer = new MasterContainer(); // last frame
var wave:CustomWave = new CustomWave(new <Number>[0,0,0,0],0xffffff,5); //generator for current frame
master.RegisterComponent(wave); //adds CustomWave and registers with the rendering loop
addChild(lastMaster); //add last frame to stage
addChild(master); //add current frame to stage
addEventListener(Event.ENTER_FRAME, perFrame);
function perFrame(event:Event):void{
time = 0.001 * getTimer();
lastMaster.graphics.copyFrom(master.graphics); //copy previous frame's graphics
UpdatePoints(); //update the path of the CustomWave
UpdateColor(); //update the color of the CustomWave
master.fireRenderCannon(); //redraw objects registered to master
}
This seems to work in theory, but as far as I can tell lastMaster ends up with no visible graphics content even though master renders as expected. I've tried several times to test whether this is the case, and am pretty convinced that that it is, but am newish to AS3 and am concerned I am overlooking something - the code looks like it should work. Does anyone have suggestions on how to test this properly? Are there obvious defects within this code that would cause lastMaster to be visually blank? Is there an better way of accomplishing my goal?
I think I'm in over my head on this... I would love any input. Thanks!
After you copied graphics, what do you try to do with it?
Method copyFrom works as clocks, without any problems. Isn't here logic bug in your code?
function perFrame(event:Event):void{
time = 0.001 * getTimer();
lastMaster.graphics.copyFrom(master.graphics); //Here
//master.graphics.copyFrom(lastMaster.graphics);
UpdatePoints();
UpdateColor();
master.fireRenderCannon();
}
Example of copyFrom, it works fine with any complexity of graphics:
var complex: Shape = new Shape();
adobeExample(complex.graphics);
var test2: Shape = new Shape();
test2.graphics.copyFrom(complex.graphics);
addChild(test2);
private function adobeExample(graphics: Graphics):void{
// define the line style
graphics.lineStyle(2,0x000000);
// define the fill
graphics.beginFill(0x666699);//set the color
// establish a new Vector object for the commands parameter
var star_commands:Vector.<int> = new Vector.<int>();
// use the Vector array push() method to add moveTo() and lineTo() values
// 1 moveTo command followed by 3 lineTo commands
star_commands.push(1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2);
// establish a new Vector object for the data parameter
var star_coord:Vector.<Number> = new Vector.<Number>();
// use the Vector array push() method to add a set of coordinate pairs
star_coord.push(0,0, 75,50, 100,0, 125,50, 200,0, 150,75, 200,100, 150,125, 200,200, 125,150, 100,200, 75,150, 0,200, 50,125, 0,100, 50,75, 0,0);
graphics.drawPath(star_commands, star_coord);
}
After the comments made by Bennet and Nicolas, it became obvious that my requirements were (nearly) impossible without a fair amount of redesign. The changes made are as follows:
Generators are no longer DisplayObjects. They are only used to calculate vectors containing the IGraphicsData objects necessary to draw the generated graphic with the drawGraphicsData method.
MasterContainer is now a shape subclass that retrieves the Vector.<IGraphicsData> from each registered generator in order to draw the output.
A bitmap subclass is used to render the contents of the MasterContainer, combining it with a color-dampened version of the previous frame.
An abridged version of the bitmap subclass:
private var constantSustain:Number;
private var linearSustain:Number;
private var sustain:ColorTransform;
private var lastFrame:BitmapData;
public function BitmapManipulator(constantSustain:Number = 0.998, linearSustain:Number = 0.98) {
this.constantSustain = Math.min(Math.max(constantSustain, 0), 1);
this.linearSustain = Math.min(Math.max(linearSustain, 0), 1);
this.UpdateSustain();
this.addEventListener(Event.ADDED_TO_STAGE, OnAddedToStage)
}
private function UpdateSustain():void {
var constantRelease:Number = 255 * (this.constantSustain - 1);
this.sustain = new ColorTransform(this.linearSustain, this.linearSustain, this.linearSustain, 1,
constantRelease, constantRelease, constantRelease, 0);
}
private function OnAddedToStage(event:Event) {
this.lastFrame = new BitmapData(stage.stageWidth, stage.stageHeight, true, 0);
}
public function DrawFrame(container:MasterContainer):void {
this.lastFrame.draw(container);
this.bitmapData = lastFrame;
this.lastFrame = this.bitmapData
this.lastFrame.colorTransform(getBounds(this), this.sustain);
}
...and finally the results #60fps when using an indigo sine wave of shifting phase as the input for the CustomWave:

as3 animation with multiple images

I have only 3 images that I'm working with for animating a running animal:
1: animal standing
2: animal in stride/jumping
3: animal on its back dead
Currently, I'm embedding them into the main class as sprites and changing their .alpha properties whenever I want one and not the other 2. Is there a better way to do what I'm doing? One of the annoying things is updating the properties for each sprite individually. It would be ideal to have one object and being able to change the image on the object so I would only have to change one object's properties.
For this it would be best to handle your animation in its own Class!
Something like this, let's say your animal is a horse so that's what I'll call the class
package {
import flash.display.Sprite;
public class Horse extends Sprite{
private var holder:Sprite = new Sprite();
public function Horse() {
var img1:Image1 = new Image1();// ur images from library
var img2:Image2 = new Image2();
var img3:Image2 = new Image3();
holder.addChild(img1);
holder.addChild(img2);
holder.addChild(img3);
addChild(holder);
setImage(0);// set 1st image visible
}
public function setImage(nr:uint):void
{
for(var i:int = 0; i < holder.length;i++;)
holder[i].visible = false;
holder[nr].visible = true;
}
}
}
then you would use it like this for example!
var horse:Horse = new Horse();
addChild(horse);
horse.x = 25;
horse.y = 25; // move the whole object(all 3 images)
horse.setImage(2);// or to whatever frame you need
Use the visible attribute instead of the alpha value. If u just set alpha to 0 it will still be rendered and cost cpu. if you set visible to false it will not be rendered!
EDIT: As Amy pointed out, blitting is a possibilty here to, although the fastest aproach would be BitmapData Frame Assignment!
Here you keep all your Frames as BitmapData in a Vector, which you load from a SpriteSheet and just assign the new BitmapData to your Bitmap instead of using copyPixels. It's faster then blitting and you still have all your builtin methods availible!!

AS3 scale x and y using tween to give movieclip bounce effect

I am trying to give my "buttons" a bounce in effect using the tween class. I am also trying to make my code more efficent by using a function to handle this effect for all my buttons.
var MusicClip:MovieClip = new music_mc();
var MoviesClip:MovieClip = new movie_mc();
var GameClip:MovieClip = new game_mc();
MusicClip.y = 63;
MusicClip.x = 577;
MoviesClip.y = 87;
MoviesClip.x = 401;
GameClip.y = 75;
GameClip.x = 151;
addChild(MusicClip);
addChild(MoviesClip);
addChild(GameClip);
This is where I am having a hard time. I thought I had to tween both the
scaleX and scaleY for all three MovieClips, but the button just appears on the
stage and doesn't animate in. Also if I can put this code in a function so I
don't have to write it for every button (and future buttons) that would be great.
var scaleTween:Tween=new Tween(MusicClip,"scaleX",Elastic.easeOut,0,1,1,true);
var scale2Tween:Tween=new Tween(MusicClip,"scaleY",Elastic.easeOut,0,1,1,true);
I am not getting any error but there is no bouncing in effect.
You need to assign listeners to your MovieClips that will perform an action when you do something. You can use a single event handler for all of your MovieClips:
MusicClip.addEventListener(MouseEvent.MOUSE_OVER,bounceButton);
MusicClip.addEventListener(MouseEvent.MOUSE_OVER,bounceButton);
MoviesClip.addEventListener(MouseEvent.MOUSE_OVER,bounceButton);
function bounceButton(event:MouseEvent):void
{
var scaleTween:Tween=new Tween(event.target,"scaleX",Elastic.easeOut,0,1,1,true);
var scale2Tween:Tween=new Tween(event.target,"scaleY",Elastic.easeOut,0,1,1,true);
}
Note that rather than specifying any one MovieClip as the tween target, you are using event.target, which will refer to the MovieClip you have rolled over.
On an unrelated note, it is good practise to start instance names with a lower case letter. This helps to distinguish them from class names which by convention have uppercase letters to start each word:
var myVariable:MyClass;

Use bitmapData.hitTest on two bitmapData with centered registration point

I've spent all the day on this, it's time to ask for your help :)
I'm trying to do collision detection of two display objects, both have centered registration point.
On my stage I have fixed elements that when added to stage are pushed in an Array called "zoneUsed". All the displayObject in my project have the registration point in the center.
My goal is to click on the stage, and check if in the clicking coords I could create a circle. My plan was to create a Sprite for the new object, cycle on the zoneUsed array, and check if the new sprite have enough space to live.
Here my code so far:
private function checkSpaceForNewMarker (markerToCheck:Sprite):Boolean {
var isPossible:Boolean = true;
var bmdataToCheck:BitmapData = new BitmapData (markerToCheck.width, markerToCheck.height, true, 0);
var m:Matrix = new Matrix ();
m.tx = markerToCheck.width/2;
m.ty = markerToCheck.height/2;
bmdataToCheck.draw (markerToCheck, m);
for (var i:int = 0; i<zoneUsed.length; i++) {
trace ("*** CHECKING ****");
var bmddataOnTheTable:BitmapData = new BitmapData (zoneUsed[i].width, zoneUsed[i].height, true, 0);
var tableMatrix:Matrix = new Matrix ();
tableMatrix.tx = zoneUsed[i].width/2;
tableMatrix.ty = zoneUsed[i].height/2;
bmddataOnTheTable.draw(zoneUsed[i], tableMatrix);
if (bmdataToCheck.hitTest(new Point(markerToCheck.x, markerToCheck.y), 255, bmddataOnTheTable, new Point (zoneUsed[i].x, zoneUsed[i].y), 255)) {
trace ("COLLISION");
isPossible = false;
} else {
trace ("NO COLLISION");
isPossible = true;
}
}
return isPossible;
}
....But right now the results are weird. Depending on the zones, my traces work or not. What am I doing wrong?
The problem is , you are drawing 1/4 (quarter) part of every object.
BitmapData is not like a Shape, Sprite, MovieClip, and it crops all the pixels, when the drawing bounds is out of the bounds of (0,0,bitmapdata.width, bitmapdata.height) rectangle.
Just remove this lines:
m.tx = markerToCheck.width/2;
m.ty = markerToCheck.height/2;
and also
tableMatrix.tx = zoneUsed[i].width/2;
tableMatrix.ty = zoneUsed[i].height/2;
You don't need this translations.
Also your code may be cause for memory leak. You are creating bitmapdata, but do not dispose it. The garbage collector will not release the memory you have allocated.You must release memory explicitly. Call bitmapdata.dispose() every time you have no need of that bitmapdata.
I'm not sure that the origin of the bitmap has anything to do with the test itself. The very nature of the test would seem to imply that the hittest is based on the RGBA value of the two supplied bitmaps. Anyway rather than picking apart your own implementation I'll just refer you to a tutorial by Mike Chambers (adobe platform evangelist). http://www.mikechambers.com/blog/2009/06/24/using-bitmapdata-hittest-for-collision-detection/
Also for more flash tutorials check out www.gotoandlearn.com.