I have an "art" application written in Processing that goes bezerk at about 1600 frames. The code is at https://github.com/jxxcarlson/Processing/tree/master/seurat . Try this to duplicate the error: (1) Start the app. (2) Hit the space bar to bring up the controls. (3) Wait until about 1600 frames. Suddenly the controls will disappaear to
be replaced by a large colored rectangle. Ugh! I've looked at the code from may angles, but must be missing something. If one disables the body of the if statement in displayControls(), in the "Seurat" tab, the error goes away -- but so do my controls. Yech!
Any suggestions would be greatly appreciated.
Your issue starts when the IF below equates to true.
//Frames.pde
if (frameCount > phase) {
for(int i = 0; i < particles.length; i++) {
particles[i].change(M); // M = maximum particle radius
particles[i].display();
}
}
Test this by changing frames[i].phase = 200*i; in Seurat.pde to frames[i].phase = 10*i;
I'll be honest, I haven't taken the time to read your code to know why, but now you can focus your efforts on that condition.
Related
I have a similar animation in Flash with a replay button at the bottom. Once the animation completes, it does not loop. Instead if you click replay, the animation starts again.
I want a textbox which will display the amount of times the button was pressed.
My existing code is currently replaying the animation. It's incrementing the count to 1 (from 0) in trace but not getting set within the textbox. Additionally, if I click the button again, trace displays 1 again -- no increment occurred (1 to 2, 2 to 3, etc).
If I comment out gotoAndPlay(1), the incrementing works just fine and is displayed in the textbox -- but the animation does not play again.
What am I doing wrong?
import flash.events.MouseEvent;
var hitcount:Number = 0;
textCounter.text = String(hitcount);
function incCounter(event:MouseEvent):void
{
hitcount++;
textCounter.text = String(hitcount);
trace(hitcount);
gotoAndPlay(1);
}
replay_btn.addEventListener(MouseEvent.CLICK, incCounter);
The problem in your code is that you are creating and initializing every time your counter, so sure you will get every replay the value 1.
So to avoid that, you can just verify if you have already created the hitcount var otherwise create it :
if(!hitcount){ // hitcount is null, so create it
var hitcount:Number = 0;
}
As a good practice, you can also remove the MouseEvent.CLICK on your button if you don't need it. So you get something like this :
if(!hitcount){
var hitcount:Number = 0;
}
count.text = hitcount.toString();
function incCounter(event:MouseEvent):void
{
event.target.removeEventListener(MouseEvent.CLICK, incCounter);
hitcount++;
count.text = hitcount.toString();
gotoAndPlay(1);
}
replay_btn.addEventListener(MouseEvent.CLICK, incCounter);
Hope that can help.
If your flash movie is longer than one frame then the layer which you are placing your actions on the stage needs to extend that amount of frames as well. Otherwise the code is no longer there after frame 1. Also when you come back to frame 1 you are attaching yet another mouse event each time. Start your code with yourButton.removeEventListener to ensure you are only ever attaching one event to it. And every time the movie ends and goes back to frame 1 your counter is reset to 1.
I'm having some trouble getting my playCount to work properly with my replay command.
The goal is to have a button pop up at the end, that gives the option to replay the animation. After the 3rd play, the button should no longer appear.
Currently it continues to show the button even after 3 plays.
The command to tell the replay button to appear is supposed to only trigger if the playCount is less than 3. The trace is coming back showing more that 3 plays, but the button still appears.
I'm not sure where the problem is.
Here's the problematic snippet of code (or where I think the problem is):
// replay button
if(playCount < 3)
{
trace(playCount);
tl.from(replayBtn, .5, {alpha:0})
replayBtn.addEventListener(MouseEvent.CLICK, replay);
}
function replay(event:MouseEvent):void{
tl.restart()
// add one to playCount
playCount++;
trace(playCount);
}
Here is a link to my files.
create a new function called removebutton then add an if condition
if(playCount >= 3)
{
trace(playCount);
replayBtn.enabled = false ;
replayBtn.removeEventListener(MouseEvent.CLICK, replay);
}
the reason is that your button is enabled and its still functioning , couldnt check your code though , but this might work ,
Managed to figure it out so I'll just leave this here
function replay(event:MouseEvent):void{
playCount++;
trace(playCount);
if(playCount < 2) {
//replay the function if there are less than 2 plays on the playcount
tl.restart();
} else {
//if there are not less than 2 plays, replay but the button invisible
tl.restart();
replayBtn.visible = false;
}
}
from what I originally had, I changed the function to an if-else clause. Instead of trying to make it not play the last step when the play count was about 2 (since it will replay 1 more time after it hits 2), I set it to restart if there are less than 2 counts and restart with the button invisible if there isn't less than 2 (the button is being hidden using alpha in the rest of the base animation)
I am new to flash and want to make it so when my character hits an object, they won't go through it, but still maintains control after they have hit it. I want it to be a solid object from all 4 points (top, left, right, bottom) of the object. Here is what I have been experimenting with...
function hitsTheObject(e:Event)
{
if (myCharacter.hitTestObject(Ball_mc))
{
gravity = 0
hitObject = true
}
if (dIsDown == true && hitObject == true)
myCharacter.x -=10
}
The first if statement works, though the second one turns off the dIsDown button I have coded. Any thoughts?
Edit: Basically I want the character to hit an object and for it to block the character, as if it was a wall.
Lewis, you're best bet is point collision. Here's some links to help you think it through and start off: http://www.wildbunny.co.uk/blog/2011/12/14/how-to-make-a-2d-platform-game-part-2-collision-detection/ and http://www.anotherearlymorning.com/2009/07/pixel-perfect-collision-detection-in-actionscript-3/
Check out my collision engine, it supports continuous/bullet collisions: https://github.com/Murplyx/AAE---Axis-Aligned-Engine
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.