I want to make a player and 2 Circles.
When the player hit the first Circle, then the Circle will also move as like player. Continue with the second Circle, if the second circle get hit by the first circle (while the player is moving and pushing the first circle), the second circle will also move as like player's speed movement!
Can you solve the problems, please ... :)
Thank You!
Use the addChild() method.
var circle1Hit:Boolean = false;
var circle2Hit:Boolean = false;
function myHitTest(me:MouseEvent): void
{
if (player.hitTestObject(circle1) && circle1Hit == false){
circle1Hit = true;
var _x:Number = circle1.x - player.x;
var _y:Number = circle1.y - player.y;
player.addChild(circle1)
circle1.x = _x;
circle1.y = _y;
}
if (player.hitTestObject(circle2) && circle2Hit == false)
{
circle2Hit = true;
var _x:Number = circle2.x - player.x;
var _y:Number = circle2.y - player.y;
player.addChild(circle2)
circle2.x = _x;
circle2.y = _y;
}
}
For further reading check out this great tutorial that explains containers and OOP really well. Also check out the one on Arrays from the same author here. By using an array, you could add even more circles to the array and all of them would be able to stick like these two do without having to have a separate bit of code for each circle like we have here.
Related
I am trying to create a small RPG for class. I create one Bitmap image, cache it, and then every time I need that same Bitmap, I clone it, and finally add them to the stage. However, despite my efforts, my canvas is still extremely slow since I am drawing all of these bushes.
I would put them in a container, however, I need to know the X and Y position that way I know if the player is trying to step over their boundaries.
Here is my function:
parseRoom: function(mapObject, room, obj, image){
var letter = 'X';
//var object = obj;
var object = null;
var img = new createjs.Bitmap(image);
for(var m=0; m < mapObject.length; m++){
for(var j=0; j< mapObject[m].length; j++){
letter = mapObject[j][m];
switch (letter){
case 'X':
//do nothing
break;
case 'O':
//object = this.createObject();
//object.image = img.clone();
img.cache();
object = img.clone();
room.AddObstacle(object, m, j);
break;
}
}
}
}
and this is my function when I actually add them to the stage:
addObstacle: function(imgObj, x, y){
imgObj.x = x ||imgObj.x || 0;
imgObj.y = y ||imgObj.y || 0;
imgObj.setVisible = function(visible){
this.visible = visible;
};
imgObj.update = function(){
if(this.visible)this.visible= true;
else this.visible = false;
};
objects.push(imgObj);
stage.addChild(imgObj);
},
as you can see, I extend the Bitmap class and also add and update and a setVisible method to it. That way I can turn them all off or on depending on the screen. Any ideas that could help me and make my game smoother? Thank you!
I was constantly updating every object, including the bushes, and there was no need to update the bushes every tick. I simply removed logic from checking the bushes and now it runs really fast.
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).
I'm creating a simple music player which will play just one song. Stage timeline has got just one frame. There is main graphic for player which is movieClip_1 (it has 4 frames in it's own timeline) and that works ok. I've got button (button_2) which starts and pauses the song and the movieClip_1 (works ok). And i also have got a graphic (it's called tube - i have changed it to movie clip, it has got one frame inside it's timeline) as a seekbar component which I just want it to move correspondingly to channel.position of this song on the x axis which it does but gives me triple error of:
TypeError: Error #1009: Cannot access a property or method of a null object reference.
Debug points at this line:
tube.x = (chan.position/song.length) * 83;
I would really appreciate a tip regarding error and also what method to use in order for user to be able to navigate (with mouse) through song by moving tube on x axis and going to different part of song. I read about .startDrag and .stopDrag would that be good idea with my present code?
My code so far:
movieClip_1.stop();
var itsstoped:Boolean;
var youpausedit:Boolean;
var counter:Timer = new Timer(100);
var chan:SoundChannel;
var song:Sound = new Sound();
song.load(new URLRequest("wmc2.mp3"));
song.addEventListener(Event.COMPLETE, soundloaded);
function soundloaded(event:Event)
{
trace("Song has been loaded.");
}
counter.addEventListener(TimerEvent.TIMER,countcounter);
itsstoped = true;
youpausedit = false;
button_2.addEventListener(MouseEvent.CLICK, presser);
function presser(event:MouseEvent):void
{
if(itsstoped == true && youpausedit == true)
{
movieClip_1.gotoAndPlay(1);
chan = song.play(chan.position);
itsstoped = false;
}
else if(itsstoped == false)
{
movieClip_1.gotoAndStop(1);
chan.stop();
itsstoped = true;
youpausedit = true;
}
else if(itsstoped == true && youpausedit == false)
{
movieClip_1.gotoAndPlay(1);
chan = song.play();
counter.start();
itsstoped = false;
}
}
function countcounter(e:TimerEvent):void
{
trace(chan.position/song.length);
var percentage:uint = 100 * (chan.position / song.length);
trace(percentage);
if(percentage == 100)
{
movieClip_1.gotoAndStop(1);
itsstoped = true;
youpausedit = false;
counter.stop();
}
}
tube.buttonMode = true;
tube.useHandCursor = true;
addEventListener(Event.ENTER_FRAME, movewhenplay);
function movewhenplay(e:Event):void
{
tube.x = (chan.position/song.length) * 83;
}
Regarding the error, you're accessing an object that has yet to be instantiated, i.e. there is no data to fetch as it does not exist.
As for the searchbar, I'm guessing you're using some kind of mask for the search bar, as you're using its x position to display the song position. I would suggest you instead use its width parameter, and set the center point to the far left.
To be able to then search through the song, you can add a copy of this searchbar, place it on top of the first one. Set its alpha to 0, to make it invisible, but still clickable. Add mouseEvent listeners to that, and when the user clicks it, you can set the song to play from the position which you can calculate using mouseX relevant to the invisible search bar.
I.e. if you want the clicked position in percents
percent = (mouseX - invisiSearchBar.x) / invisiSearchbar.width
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.
Title is more or less self-explanatory, I’ve been working through many different tutorials and I’m not exactly too good with AS3 to be perfectly honest. (Image above shows what I'm aiming for)
Anyway, what I notice in most of the online tutorials I see, the drag and drop tutorials are either based on one object to one target or multiple objects to multiple targets, so I was wondering if someone is kind enough to help me and explaining how I can get multiple objects to connect to one target.
And, if possible making it switchable, as in for example, if object 1 is already in place on the target when I drag object 2 over, then object 1 returns to its original position and object two takes its place.
A easier way to explain this is to say that I'm trying to create a game where there are three statues and the user can pick one of the three to place in a set target zone.
I apologies if what I say doesn't make much sense, will clear up anything if that causes confusion. Here's the AS3 code I'm using at the moment.
var startX:int;
var startY:int;
circle1_mc.addEventListener(MouseEvent.MOUSE_DOWN, pickUp);
circle1_mc.addEventListener(MouseEvent.MOUSE_UP, dropIt);
circle2_mc.addEventListener(MouseEvent.MOUSE_DOWN, pickUp);
circle2_mc.addEventListener(MouseEvent.MOUSE_UP, dropIt);
circle3_mc.addEventListener(MouseEvent.MOUSE_DOWN, pickUp);
circle3_mc.addEventListener(MouseEvent.MOUSE_UP, dropIt);
function pickUp(event:MouseEvent):void {
startX = event.target.x;
startY = event.target.y;
event.target.startDrag(true);
event.target.parent.addChild(event.target);
}
function dropIt(event:MouseEvent):void {
event.target.stopDrag();
var theTargetName:String = "target" + event.target.name;
var theTarget:DisplayObject = getChildByName(theTargetName);
if (event.target.dropTarget != null && event.target.dropTarget.parent == theTarget){
event.target.buttonMode = false;
event.target.x = theTarget.x;
event.target.y = theTarget.y;
}
else{
event.target.x = startX;
event.target.y = startY;
circle1_mc.buttonMode = true;
circle2_mc.buttonMode = true;
circle3_mc.buttonMode = true;
Instead of checking the dropTarget, you can use hitTestObject to see if the dropped object is "touching" theTarget. Otherwise, any other item that has already been dropped onto theTarget may be reported as the dropTarget.
Also, since MovieClip is dynamic, you can store the startX and startY values in each instance.
The following modified code will use a single target_mc as a drop target. When one item is dropped on it, any other items will be moved back to their original spot:
// create an array as #David suggested to keep track of your draggable items
var circles:Array = [circle1_mc, circle2_mc, circle3_mc];
for each(var circleMC:MovieClip in circles)
{
circleMC.addEventListener(MouseEvent.MOUSE_DOWN, pickUp);
circleMC.addEventListener(MouseEvent.MOUSE_UP, dropIt);
circleMC.startX = circleMC.x;
circleMC.startY = circleMC.y;
}
function pickUp(event:MouseEvent):void
{
// no longer need to keep track of startX & startY here because that's already been done up above
event.target.startDrag(true);
event.target.parent.addChild(event.target);
}
function dropIt(event:MouseEvent):void
{
event.target.stopDrag();
// check to see if the event target is touching target_mc using hitTestObject
if(event.target.hitTestObject(target_mc)){
event.target.buttonMode = false;
event.target.x = target_mc.x;
event.target.y = target_mc.y;
// move all circles OTHER than the current target back to their original positions
for each(var circleMC:MovieClip in circles)
{
if(event.target != circleMC)
{
circleMC.x = circleMC.startX;
circleMC.y = circleMC.startY;
}
}
}
else
{
// only need to move the event target back if it was dropped outside of target_mc
event.target.x = event.target.startX;
event.target.y = event.target.startY;
event.target.buttonMode = true;
}
}