So in my game I spawn a grapple hook when I touch the screen, connecting player and ceiling. The problem is that the touchDown() of my inputAdapter only seems to activate the first time I touch, nothing happens after when I touch again (meaning: no other "grapple hooks" get created, just the one). touchUp() or every other input method still work.
Here are all the classes: Rope - GamePlay - InputManager and also just in case MainMenu
EDIT
So I was being a moron and in the overlapsOnX() method forgot to add and substract the width of the "cloud" so unless I got very lucky (or spawned in the right place) the rope wouldnt get created.
Here's how the method should look like
private boolean overlapsOnX(Body player, Body cloud){ //check if the player is currently in the same X position than a cloud
return player.getPosition().x >= cloud.getPosition().x - (20 / PPM) && player.getPosition().x <= cloud.getPosition().x + (20 / PPM);
}
TouchDown returns a boolean to indicate if the input has been processed or not. You are returning false, but you probably mean to return true. This would indicate the input has finished being handled.
Related
I wanted friends, do the following when my MC get a determanido internal quandro, it triggers a function to another MC. for example when the ball hit the wall, a person goes to search - la, I have tried using :
("root") {root.MC.play ()}
Translation from comments:
Friends, I have an MC_1 with 10 frames, when it reaches frame 5, I want another movieClip MC_2 to respond (eg: to move or fade etc)
creating a ENTER_FRAME listener for your MC_1 is the easiest way to achieve this
MC_1.addEventListener(Event.ENTER_FRAME,respond);
function respond(e:Event):void{
if(MC_1.currentFrame>=5)
MC_2.gotoAndPlay(2);
//or any other respose you want from MC_2
}
addFrameScript can be used in AS3 to specify a function to execute on reaching a MovieClip frame.
MovieClip.addFrameScript(index:int, func:Function);
A sample implementation of this:
// addFrameScript's index is zero Based, hence 4 means frame 5
MC_1.addFrameScript(4, funcToExecute);
function funcToExecute():void{
// this will get called when MC_1 reaches frame 5
// do stuff here, like manipulating MC_2, etc...
}
I want to make a timer that will show text at my panelText (dynamic text box) at specific time, actually I have a video that I want to have subtitles, and I want to use timer, my video is 3 minutes and 37 second long, and I have script that I want to show at some time, example at 1 minute 0 seconds it will show the text "hello, this is my video to learn about solar system" in my panelText, and at 2 minute I want to show text "There are 8 planets in our solar system", something like that. For information, I'm using flvPlayback to play the video and load the external video.
An example from my code:
var myTimer:Timer = new Timer(217000);
var time = 0;
myTimer.start()
myTimer.addEventListener(TimerEvent.TIMER,timerHandle);
function timerHandle(event:TimerEvent){
if(myTimer == 120000)
{
panelText.text="There's 8 planets in our solar system";
}
and i got error 1176: Comparison between a value with static type flash.utils:Timer and a possibly unrelated type int. can someone help me?, i'm sorry for my bad english
You should use FLVPlayback's addASCuePoint() function to make precise actions when your FLVPlayback fideo is playing. You use this function to set up whatever points you want to display custom subtitles, there can be as many of these as you want, then you listen for MetadataEvent.CUE_POINT event on your FLVPlayback instance, and process the cue point in order to display the associated subtitle. Note though, you will have to separately parse subtitle expiration, or assign a cue point to remove the displayed subtitle several seconds past the displaying cue point. Although it will be better if you will be able to add subtitles directly on the video, so that seeking through your video will not require handling of misaligned subtitles. Still, it's doable with pure AS3 code, if you would also listen to VideoEvent.FAST_FORWARD and VideoEvent.REWIND events to handle user interaction with playback and display corresponding subtitle by calling findNearestCuePoint() to find the closest earlier subtitle-enabled cue point.
An example of adding a cue point:
flv.addASCuePoint(0.1,"1",{text:"Subtitle one"});
flv.addASCuePoint(6.8,"2",{text:"Subtitle two"});
flv.addASCuePoint(11.8,"2 hide",{text:""}); // remove old subtitle
flv.addASCuePoint(120.0,"3",{text:"There are 8 planets in our solar system"});
Note that each call returns an Object, which is also returned whenever a MetadataEvent.CUE_POINT event is dispatched. This has a parameters sub-object that you have passed into addASCuePoint as third parameter, which you then parse and take actions depending on what's in there. Here, I've placed a single field "text" into each of the parameter objects, which should be the text to display as subtitles. So, then you listen to the cue point event and take actions, like this:
flv.addEventListener(MetadataEvent.CUE_POINT,cueHandler);
// do this only once, a listener does not need to be added per cue point
function cueHandler(e:MetadataEvent):void {
var cuepoint:Object=e.info;
if (cuepoint.parameters) {
panelText.text=cuepoint.parameters.text;
} else {
// DEBUG here
}
}
In case of seeking, you listen for FF and rewind events with a function that will call findNearestCuePoint(), retrieve its parameters.text and place that text into your text field.
You misunderstood the usage of the Timer class.
var myTimer:Timer = new Timer(n) means that the Timer will always "tick" at the specified interval n, in your case every 217000 milliseconds (217 seconds).
This might not be the best solution, but it'll show you how you can use the timer class for a scenario such as yours.
var myTimer:Timer = new Timer(1000); //a timer that will tick every second
myTimer.addEventListener(TimerEvent.TIMER, timerHandler);
myTimer.start(); //you should set up your listener before you start the timer
function timerHandler(event:TimerEvent):void{
//myTimer.currentCount will tell you how many times your Timer has ticked
//every tick, in this scenario, represents exactly one second, because we initialized the Timer with 1000 milliseconds
//so, if you want to show some text 86 seconds after the video has started, you could do:
if(myTimer.currentCount == 86){
panelText.text = "We're 86 seconds into the video";
}else if(myTimer.currentCount == 217){
//after reading your code it seems like you intended to let the timer only run 217 seconds, because that's the length of your video
//my proposed solution could also handle this, in this else if clause
myTimer.stop();
myTimer.removeEventListener(TimerEvent.TIMER, timerHandler);
myTimer = null;
}
}
The error is right.you are comparing a timer with a number!!.
fixed part of code:
if(myTimer.currentCount==120000){
panelText.text="There's 8 planets in our solar system";
}
and your timer constructor is wrong!the first argument is delay and next is repeat count.
the fixed code:
var myTimer:Timer = new Timer(100,2170);
var time = 0;
myTimer.start()
myTimer.addEventListener(TimerEvent.TIMER,timerHandle);
function timerHandle(event:TimerEvent){
if(myTimer.currentCount == 1200)
{
panelText.text="There's 8 planets in our solar system";
}
in this code, our timer ticked at every 0.1 second(100 miliseconds) and is ticked 2170 times. so, to set your text, you must put a zero after your desired second.
hope this helps :)
the collision not working i cant understand why, i put collision movieclips in the object and it doesnt seem to recognise one of the but does with the other, sorry for the confusing way of stating the problem if you play the game you will understand. im open to changing the way collision works too as long as it works ill be super happy
I'll try to explain. When You click "Down" or "Up" hero (box_MC) collide with both doors "Top_Door" and "Bottom_Door". Inside "bang" function at first checking collision with "Bottom_Door", so, hero always go down (.y += 100) and second condition (Top_Door) never will be true. How to fix this? Add variable var lastAction:String;. This variable will store last action: "up" or "down". Inside "down_MC_P" function initialize this variable by "down". Inside "up_MC_P" — "up". Next, replace the first condition to this if (box_MC.hitTestObject(cycle[i].Bottom_Door) && lastAction == "down") and second: if(box_MC.hitTestObject(cycle[i].Top_Door) && lastAction == "up"). That's all.
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.
This is the game loop in my code and the drawing code:
float frames_per_second = 60;
display_timer = al_create_timer(1/frames_per_second);
queue = al_create_event_queue();
al_register_event_source(queue, al_get_timer_event_source(display_timer));
al_start_timer(display_timer);
while(!end_game)
{
ALLEGRO_EVENT event;
al_wait_for_event(queue, &event);
if(event.type == ALLEGRO_EVENT_DISPLAY_CLOSE) break;
if(event.any.source == al_get_timer_event_source(display_timer))
{update_display();}
update_input();
}
void update_display()
{
al_clear_to_color(al_map_rgb(255, 255,255));
draw_objects(); //this is just an al_draw_bitmap() call
al_flip_display();
}
The animation created by moving objects on screen flickers, I'm surprised by this since I write to the back buffer of the screen thus I expect double buffering. What can I do to correct the flickering? Thanks.
Unrelated to the problem, you can check a timer by looking for the ALLEGRO_EVENT_TIMER event. You can use event.timer.source to check which timer it is, if you have more than one.
I think the main problem here is that you are drawing the graphics at 60fps but you are updating the input at an unlimited rate. This is actually backwards. You want to update the input at a fixed rate. You can draw the graphics as often as you like... although it makes no sense to update the graphics if nothing has changed.
So it should look something more like:
if(event.type == ALLEGRO_EVENT_TIMER)
{
update_input();
update_display();
}
However, this does not implement frame skipping if things get too slow. What you should do is set up the timer in a dedicated queue (that contains no other event sources). Then as long as there are events sitting in that dedicated timer queue, update the input.
Then update the display, assuming you've processed at least one tick. So you may, if things get too slow, do multiple input updates per drawn frame.