To make things quick, I have an arrangement of tiles that a player and an enemy are on.
public static var floor1:Array = new Array(7);
floor1[0] = [0,1,1,1,1,1,0];
floor1[1] = [1,1,1,1,1,1,1];
floor1[2] = [1,1,1,0,1,1,1];
floor1[3] = [1,1,0,0,0,1,1];
floor1[4] = [1,1,1,0,1,1,1];
floor1[5] = [1,1,1,1,1,1,1];
floor1[6] = [0,1,1,1,1,1,0];
public function Main()
{
var tilew:int = 60;
var tileh:int = 60;
for (var i:int=0; i<floor1.length; i++)
{
for (var u:int=0; u<floor1[i].length; u++)
{
var cell:MovieClip = new Tile();
cell.gotoAndStop(floor1[i][u]);
cell.x = ((u-i)*tileh);
cell.y = ((u+i)*tilew/2);
addChild(cell);
cell.addEventListener(MouseEvent.ROLL_OVER, mouseover);
cell.addEventListener(MouseEvent.ROLL_OUT, mouseout);
cell.addEventListener(MouseEvent.CLICK, mouseclick);
cell.addEventListener(Event.ENTER_FRAME, beginfloor1);
}
}
var player:Player = new Player();
addChild(player);
player.mouseEnabled = false;
player.x = 5 * (tileh);
player.y = 5 * (tilew/2);
var enemy:Enemy = new Enemy();
addChild(enemy);
enemy.mouseEnabled = false;
enemy.x = 9 * (tileh);
enemy.y = 9 * (tileh/2);
My goal is to have the enemy move randomly on tiles in his range. What I did was create a square graphic called enemyVisionArea that checks which tile is hitting the enemy, which is basically surrounding tiles.
I have a timer function that tells the enemy to move every 5 seconds if the player isn't near him and if he's next to an available tile.
function timerenemy (event:TimerEvent){
if (enemy.enemyVisionArea.hitTestObject(enemyMover) && !player.visionPoint.hitTestObject(enemyMover.tileMiddle))
{
enemy.x = (enemyMover.x)+55;
enemy.y = (enemyMover.y)+20;
trace("moved");
}
}
enemyMover is a variable that I made equal to the tile objects.
function beginfloor1(event:Event)
{
enemyMover = event.currentTarget as Tile;
}
It just stays where it is. I'm just want to have the enemy move on its own on any tile that its enemyVisionArea is hitTesting a nearby tile. The beginfloor1 function doesn't seem to be working. Is there any way I can declare enemyMover = event.currentTarget as Tile and have the enemy move on a random tile that its enemyVisionArea is hitTesting?
If this is confusing, I can post the full code.
You are assigning 49 enterframe listeners which are called in sequence, and they ALL change one single variable to the cell they are attached to. Of course, the last tile is what's always assigned.
I expect that you want an enemy to check if there's a tile available for it to move to. You are essentially checking for one tile which is enemyMover - how do you determine what's that tile? You have to check all available tiles that are around the enemy, make a list of them and select one out of that list that's not the current tile, then move the enemy there.
So, first you need a complete tileset to be addressable from somewhere. The best way will be to declare a class-wide var tileset:Array and fill it where you make new tiles. Drop the Event.ENTER_FRAME listener from the code there, as it's useless. Then, in your timerevent that's for the enemy you do check all of the tileset if they are within your enemy's vision area (you use hitTestObject, I'd use clear distance grid-wise or coordinate-wise - it's a whole lot faster), if so, you add them to the TEMPORARY array you create within that function. Of course, if your enemy is at the currently processed cell, you ignore it - you have to move your enemy, not make him stand in place. Then, select (somehow, it's up to you) what cell your enemy should move to, and execute a move. Yes, if you want your enemy to move randomly, select a cell at random by its index via Math.floor(Math.random()*selectedcells.length).
Related
Im trying to make a simple game in AS3 where a player eats as many balls as possible. i dont know how to code very well and im having trouble trying to add a new ball to the stage every time one is eaten.
this is the code i have in main.as at the moment.
private var startX:Number = 512;
private var startY:Number = 384;
private var speed:Number = 8;
var player1;
var player2;
var player3;
var theBall;
player1 = new player(50,384, 1);
player2 = new player(944,384,2);
player3 = new player(488,84,3);
stage.addChild(player1);
stage.addChild(player2);
stage.addChild(player3);
if(theBall.hitTestObject(player1) || theBall.hitTestObject(player2) || theBall.hitTestObject(player3))
{
//removes the ball from the stage
trace("a player has eaten a ball");
stage.removeChild(theBall);
//adds new ball
//stage.addChild(theBall);
//reset x and y
startX = Math.random()*speed-speed/2;
startY = Math.random()*speed-speed/2;
}
In the ball.as ive specified how the ball should move randomly, start in the center of the stage and bounce off walls.
no errors appear, the code just doesnt work. how do you make a new ball re spawn in the center of the stage when one is eaten? do i declare this where i tried to in the main, or in the ball.as?
If you have a "ball" Object, in the way you have a "player" Object, then...
//removes the ball from the stage
trace("a player has eaten a ball");
stage.removeChild(theBall);
//reset x and y
startX = Math.random()*speed-speed/2;
startY = Math.random()*speed-speed/2;
//adds new ball
theBall = new ball();
theBall.x = stage.stageWidth/2;
theBall.y = stage.stageHeight/2;
stage.addChild( theBall );
You reuse the "theBall" variable, since you've removed the eaten instance from the stage. The old "theBall" instance is thrown out with stage.removeChild(theBall), and then you make a new one and add that new one to the stage.
Before your code, if the BALL isn't called and prepared for your stage. It might not work.
In your Library, check the movie_clip that contain the ball... And under the row "AS LINKAGE" next to the name of the Movie Clipe... You should call it for example "BALL_TEST"
In your AS3 code :
Add this before your code
var ball_bounce:BALL_TEST = new BALL_TEST();
Then your code
If i did correctly understand your question...
Kind regards
I am trying to get a cube movieclip to create another instance of itself and then add it to the stage at the coordinates right next to the previous one. However I can't get it to keep adding more children/ can't figure out how to access the childs coords. I attempted to add a new movieclip:mc every iteration of the for loop with the vertical and horizontal counting back by 50 every time and then,on a different thought process, i tried adding a new child every loop but I don't know how to access that childs properties. Any help would be appreciated. Thank you.
var countV:int=600;
var countH:int=600;
stage.addChild(havenAlpha);
var moveHOrV:Boolean=true;
var mc:MovieClip = new haven_Expand();
for(var i:int=0; i<=5; i++){
if(moveHOrV == false){
stage.addChild(mc);
countH=countH-50;
mc.x= countH;
moveHOrV=true;
}else if(moveHOrV == true){
stage.addChild(mc);
countV=countV-50;
mc.y=countV;
moveHOrV=false;
}
trace(countV,countH,moveHOrV,i);
stage.addChild(new haven_Expand())
stage.addChildAt(new haven_Expand(),countH);
}
In most Object oriented languages, variables are just pointers to the actual objects. So changing what is stored in a variable, doesn't actually make what was stored there previously go away.
To that end, you can just make one var to store each new object created every iteration. Like so:
stage.addChild(havenAlpha);
//this var will store the clip from the preivous iteration, but we'll start it off with the first item
var prevClip:MovieClip = new haven_Expand();
prevClip.x = 600;
prevClip.y = 600;
stage.addChild(prevClip);
var curClip:MovieClip; //used in the loop below to hold the current iterations item
for(var i:int=0; i<=5; i++){
curClip = new haven_Expand();//create new clip
stage.addChild(curClip); //add it to the stage
if(i % 2){ // % (modulous) gives you the remainder of the division, so this effectively will be false (0) every other time
curClip.x = prevClip.x - curClip.width; //place this new clip just to the left of the last iteration's clip
curClip.y = prevClip.y;
}else if(moveHOrV == true){
curClip.y = prevClip.y - curClip.height; //place this new clip just on top of the last iteration's clip
curClip.x = prevClip.x;
}
prevClip = curClip;
}
I'm not sure though if the x/y math is what you desire. This will make them distribute in a diagonal fashion. Are you actually wanting horizontal rows? I can update to show you that if desired.
I am stuck at a very basic problem which I am not quite able to figure out. I have 4 alienships and a crosshair which moves around with the mouse. I want to change the color of my crosshair to red when it is near one of the alienships. Both my alienships and crosshair are classes which extend movieclip. I use them in my main document class inside a main game loop which is triggered by the Enter_Frame event listener.
Here is my logic that checks for the same
private var objColor:ColorTransform = new ColorTransform();
private function overlayCursorMove() : void {
var initialColor:ColorTransform = new ColorTransform();
initialColor.color = 0xD3D3D3;
for(var i = 0; i < alienShipArray.length; i++){
var currentShip:AlienShip = alienShipArray[i];
if(currentShip.getDistance(overlayCursor.x - currentShip.x, overlayCursor.y - currentShip.y) <= 30 ){
overlayCursor.transform.colorTransform = objColor;
}
else if(currentShip.getDistance(overlayCursor.x - currentShip.x, overlayCursor.y - currentShip.y) > 30 ){
overlayCursor.transform.colorTransform = initialColor;
}
}
}
Below is the custom getDistance function inside the AlienShip class
public function getDistance(delta_x:Number, delta_y:Number):Number
{
return Math.sqrt((delta_x*delta_x)+(delta_y*delta_y));
}
overlayCursor is my crosshair which moves around with my mouseX and mouseY positions. I have 4 alienships on my stage and all of them are stored inside the alienShipArray.
I am just calculating the distance between my crosshair and the currentship position to check if its less than a certain amount to change the crosshair color else if distance is greater change it back to previous color.
Surprisingly the logic only works for the very last ship in the array that is when the loop reaches i = 3 ( alienShipArray[3] ). For the rest of the ship the color of the crosshair stays the same!
You need to break out of your loop when you encounter an intersection, otherwise your loop will continue to run and the other non-intersecting aliens will cause the else if part of your condition to test true, and your crosshair will be changed back to its initial color.
That would explain why your code only works with the last alien in the loop, as there are no further iterations in that instance to reset the color.
Something like the following should do it (untested):
private var objColor:ColorTransform = new ColorTransform();
private function overlayCursorMove() : void {
var initialColor:ColorTransform = new ColorTransform();
initialColor.color = 0xD3D3D3;
for(var i:uint = 0; i < alienShipArray.length; i++) {
var currentShip:AlienShip = alienShipArray[i];
// Reset cursor back to initial color
overlayCursor.transform.colorTransform = initialColor;
if(currentShip.getDistance(overlayCursor.x - currentShip.x, overlayCursor.y - currentShip.y) <= 30 ) {
// Intersection found, change the cursor color
overlayCursor.transform.colorTransform = objColor;
// And break out of the loop so further iterations don't reset it
break;
}
}
// No intersections found, cursor remains in its initial state
}
I am making an interactive game - and I have this code so far. Where drop1 is a coin and the user drops it into target1 (box) and once they have done they they are able to watch the video play in the next scene. AS you can see when drop1 (coin) is dropped onto the box the coin then disappears
//Array to hold the target instances, the drop instances,
//and the start positions of the drop instances.
var hitArray:Array = new Array(hitTarget1);
var dropArray:Array = new Array(drop1);
var positionsArray:Array = new Array();
//This adds the mouse down and up listener to the drop instances
//and add the starting x and y positions of the drop instances
//into the array.
for (var i:int = 0; i < dropArray.length; i++) {
dropArray[i].buttonMode = true;
dropArray[i].addEventListener(MouseEvent.MOUSE_DOWN, mdown);
dropArray[i].addEventListener(MouseEvent.MOUSE_UP, mUp);
positionsArray.push({xPos:dropArray[i].x, yPos:dropArray[i].y});
}
//This drags the object that has been selected and moves it
//to the top of the display list. This means you can't drag
//this object underneath anything.
function mdown(e:MouseEvent):void {
e.currentTarget.startDrag();
setChildIndex(MovieClip(e.currentTarget), numChildren - 1);
}
//This stops the dragging of the selected object when the mouse is
//released. If the object is dropped on the corresponding target
//then it get set to the x and y position of the target. Otherwise
//it returns to the original position.
function mUp(e:MouseEvent):void {
var dropIndex:int = dropArray.indexOf(e.currentTarget);
var target:MovieClip = e.currentTarget as MovieClip;
target.stopDrag();
if (target.hitTestObject(hitArray[dropIndex])) {
target.x = hitArray[dropIndex].x;
target.y = hitArray[dropIndex].y;
drop1.visible = false;
}else{
target.x = positionsArray[dropIndex].xPos;
target.y = positionsArray[dropIndex].yPos;
}
}
NOW... I want the code to know when the user has dropped the coin in the box and IF the user has they can then watch the video but can only watch the video if they drop the coin in box. How can i code this?
please help.
thank you
If you're still struggling you can always try reading the MANUAL..? I suspect this is why you've had no answer so far. Travelling between frames/scenes requires either gotoAndPlay or gotoAndStop. Check: http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/display/MovieClip.html#gotoAndPlay()
Look at example two for scene jumping code. Where it says "intro" (frame label) it's okay to just use a number but scenes must have names.. e.g:
mc1.gotoAndPlay("intro", "Scene 12");
or in your case something like below (assuming you have named it as scene_video)
if (target.hitTestObject(hitArray[dropIndex])) {
target.x = hitArray[dropIndex].x;
target.y = hitArray[dropIndex].y;
drop1.visible = false;
gotoAndStop(1, "scene_video"); }
Again I'm assuming your video player is on frame 1 of that scene so stopping there allows users a chance to watch the video player.
i am makin a puzzle game in as3 and I am allready done.
i splitted a bitmap into 8 parts, I converted them into mc's and I am able to move them around with the mouse.
I made a puzzleboard too where the puzzle pieces are droped.
now how can I make a puzzle solution, like when the puzzle pieces are in the right order then the whole bitmap should be displayed.
thak you for your attention
Why don't u store the mcs positions in an Array of Points?
This way , wherever the mcs are on the board , it would be easy to tween them back into position.
var positions:Array = [ new Point(mc1.x , mc1.y), .... , new Point(mcn.x , mc1.n), ];
//assuming that this code is run from
// the mcs container and that this container
// doesn't have any other children
for( var i:int ; i < this.numChildren ; ++i )
{
//provided that the MCs are on
//the right order in the Display List
var mc:MovieClip = this.getChildAt(i) as MovieClip;
//no tween here but you get the idea...
mc.x = positions[i].x;
mc.y = positions[i].y;
}
After you split the bitmaps and transfom them into MovieClips, I assume that at that stage you have the solution of the puzzle.
If yes, you then need to store the current positions of the pieces before they had a chance to be moved.
Practically that means not adding an event listener before you've actually stored the positions.
//instantiate the Array
var positions:Array = [];
for(var i:int ; i < this.numChildren; ++i )
{
// add the mcs positions
var positions[i] = new Point ( this.getChildAt(i).x , this.getChildAt(i).y );
//you could add your Mouse Event listener here...
}