Sorry if the title is ambiguous, I don't know how to really word what I'm trying to do.
So, anyway, I've created a basic zombie game where green squares follow you, you can die and kill the zombies.
The problem is, if there's a large crowd of the zombies, they all go into eachother and make one square, seeing as collision is too hard to do since they're moving along where they're pointing (pointing at the player), is there a way I can keep them spread out enough so they never go into eachother?
here's the code where I move the zombies:
for (var i2:int; i2 < ZombiesOnScreen.length; i2++ )
{
if (ZombiesOnScreen[i2].alive == true)
{
var dist_Y2:Number = player.y - ZombiesOnScreen[i2].y;
var dist_X2:Number = player.x - ZombiesOnScreen[i2].x;
var angle2:Number = Math.atan2(dist_Y2, dist_X2);
var degrees2:Number = angle2 * 180 / Math.PI;
ZombiesOnScreen[i2].rotation = degrees2;
var zomBAngle:Number = ZombiesOnScreen[i2].rotation * Math.PI / 180;
ZombiesOnScreen[i2].x = ZombiesOnScreen[i2].x + 1.6 * Math.cos(zomBAngle);
ZombiesOnScreen[i2].y = ZombiesOnScreen[i2].y + 1.6 * Math.sin(zomBAngle);
}
if (ZombiesOnScreen[i2].hitTestObject(player))
{
gameOver();
}
}
Also, sorry if this is literally just collision but just spaced out, I just want a way to stop them merging.
It may be beyond your current programming level but one common approach to this is on based the work of Craig Reynolds, outlined in his paper entitled "Flocks, herds and schools: A distributed behavioral model". He later released the C++ lib "openSteer." See his paper Steering Behaviors For Autonomous Characters for Java applet examples and a simplified explanation.
There have been many actionscript implementations of flocking behavior and ports of openSteer. Be careful though – you can't just copy and paste the code.
Related
I've been banging my head up against a wall for the past couple of days trying to figure out how to properly extend CitrusEngine's Box2DPhysicsObjects to generate my custom objects. My goal is to generate this behavior:
example of desired behavior.
This is designed to simulate my hero dashing at a direction determined by using input while swinging his sword to attack. The sword "sleeps" until the attack state is activated.
I think I have a fundamental misunderstanding of how to properly use Box2D (especially joints). If someone could point me in the right direction I would be eternally grateful. I can't really provide my current code because it's become beyond broken.
An implementation such as the one above would have very poor performance and would likely tunnel in almost every situation. Therefore a solution is to add a sensor with a funnel shape and add a joint between this sensor and my hero. The implementation:
override protected function createShape():void{
var radius:Number = 4;
var vertices:Vector.<b2Vec2> = new Vector.<b2Vec2>();
vertices.push(new b2Vec2(0,0));
for (var i:int = 0; i < 7; i++) {
var angle:Number = i / 6.0 * .5* Math.PI;
vertices.push(
new b2Vec2( radius * Math.cos(angle),
radius * Math.sin(angle) ));
}
var sword_shape:b2PolygonShape = new b2PolygonShape();
sword_shape.SetAsVector(vertices,8);
_shape = sword_shape;
}
So, I'm trying to get a few movieclips to follow it's precursor and have the last one follow the mouse. The problem is I'm creating them from code instead of using the interface and, since I'm not an expert, I can't get them to work.
All I have in the library is a MovieClip(linkage:"LETRA") which contains a textField inside(instance name:"myTextField").
Here's what I have:
import flashx.textLayout.operations.MoveChildrenOperation;
import flash.display.MovieClip;
import flash.events.Event;
//this are the letters that will be following the mouse
var phrase:Array = ["H","a","c","e","r"," ","u","n"," ","p","u","e","n","t","e"];
//variable to spread them instead of creating them one of top of each other
var posXLetter:Number = 0;
//looping through my array
for (var i:Number = 0; i < phrase.length; i++)
{
//create an instance of the LETRA movieclip which contains a text field inside
var newLetter:MovieClip = new LETRA();
//assing a letter to that text field matching the position of the phrase array
newLetter.myTextField.text = phrase[i];
//assign X position to the letter I'm going to add
newLetter.x = posXLetter;
//add properties for storing the letter position
var distx:Number = 0;
var disty:Number = 0;
//add the listener and the function which will move each letter
newLetter.addEventListener(Event.ENTER_FRAME, moveLetter);
function moveLetter(e:Event){
distx = newLetter.x - mouseX;
disty = newLetter.y - mouseY;
newLetter.x -= distx / 10;
newLetter.y -= disty / 10;
}
//add each letter to the stage
stage.addChild(newLetter);
//increment the next letter's x position
posXLetter += 9;
}
With that code, only one letter is following the mouse (the "E") and the rest are staying where I added them using addChild and the posXLetter variable.
Also, I'm trying to get it to behave more like a trail, so if I move up, the letters will lag beneath me; if I move to the left, the letters will lag to my right but I think that with my current approach they will either A) move all together to the same spot or B) always hang to the left of the cursor.
Thanks for any possible help.
This is a kind of motion called Inverse Kinematics and it is a quite popular way to make rag dolls in games. It uses a design pattern called the Composite Pattern where one object adds another object as a child of its and then when it's update() function if called, it calls all of its (usually one) child's update() functions. The most common example of this is of a snake. The snake's head follows your mouse, and the rest of the snake's body pieces move with the snake, and it looks immensely realistic. This exact example is explained and build here although it does not include joint restrictions at all.
This example is in the middle of a book, and so may be hard to start reading, but if your somewhat familiar with design patterns and/or have some intermediate experience with programming, then i'm sure you can understand it. I advise that you, after reading and understanding the example, scratch what you have now because it is not very elegant coding. You may feel that this example uses too many classes, but trust me, its worth it as it allows you to very easily edit your code, if you decide to change it in the future, with no drawbacks.
Also, i know that this snake is not what you want, but if you understand the concept then you can apply it to your own specific needs.
I hope this helps.
I think it is a scoping issue. You might need to modify your handler
function moveLetter(e:Event){
trace(e.target); //check if this is the right movie clip
distx = e.target.x - mouseX;
disty = e.target.y - mouseY;
e.target.x -= distx / 10;
e.target.y -= disty / 10;
}
I need to move many objects in a curve path across screen randomly. The objects start path and towards path also should take randomly. I had searched on google and finally i found one usefull tutorial to draw a curve. But i don't know how to move the objects using that curve path. But i am sure there would be some formula in as3 which has to use sin and cos theta. So please let me know if anybody have a solution for my problem. And also if i got any sample projects also would be very usefull for me.
And the link which i got to draw curve is as follows.
http://active.tutsplus.com/tutorials/actionscript/the-math-and-actionscript-of-curves-drawing-quadratic-and-cubic-curves/?search_index=4.
Thanks in advance.Immediate Help would be appreciated.
A quick'n'dirty would be using polar to cartesian coordinates(sin and cos) as you mentioned:
import flash.events.Event;
var a:Number = 0;//angle
var ra:Number = .01;//random angle increment
var rx:Number = 100;//random trajectory width
var ry:Number = 100;//random trajectory height
graphics.lineStyle(1);
addEventListener(Event.ENTER_FRAME,function (event:Event):void{
a += ra;//increment angle
rx += a;//fidle with radii otherwise it's gonna be a circle
ry += a;//feel free to play with these
graphics.lineTo(225 + (Math.cos(a) * rx),//offset(225,200)
200 + (Math.sin(a) * ry));//and use pol to car conversion
if(a > Math.PI) reset();//reset at 180 or any angle you like
});
function reset():void{
trace('reset');//more values to tweak here
a = Math.random();
ra = Math.random() * .0001;
rx = 20 + Math.random() * 200;
ry = 20 + Math.random() * 200;
}
Random numbers need tweaking to get mostly rounder ellipses (rather than flatter ones), but the principle is the same.
If you don't mind using libraries, why not try TweenLite's BezierPlugin or BezierThroughPlugin. Should be easy to randomize start/end points.
Also you can check out the first part of this older answer on quadratic,cubic and hermite interpolation
In my example I'm drawing a path, but of course, you could use those computed x,y coordinates to plug into a DisplayObject to move it on screen.
First of all sorry for some english mistakes. Portuguese is my first language(I am from Brazil)
Im trying to make a space game from scratch in AS3 and the way to move the ship is like in the game Air Traffic Chief.
I succeed at some point. But when the ship is very fast it start to shake and its not very smooth and clean as I want.
Here is what i have done: http://megaswf.com/s/2437744
As the code is very big so I pasted in pastebin: pastebin.com/1YVZ23WX
I also wrote some english documentation.
This is my first game and my first post here. I really hope you guys can help me.
Thanks in advance.
Edit:
As the code is very big i will try to clarify here.
When the user MouseDown and MouseMove the ship every coordinate is passed to an array.
When the user MouseUP this array is passed to a function that fix the array.
For example: If the distance between two coordinates is greater than 5px, the function creates a coordinate in the middle of the two coordinates.
if I take this function off the problem seen to be solved. But if the user move the mouse very slow it still happens. It also creates a problem that i was trying to solve with that function. as the distance of the two coordinates are very big when the ship arrive in one coordinate most of the line path disappear.
I uploaded a version without the function that fixes the array. http://megaswf.com/s/2437775
I think there is 2 ways for solving this problem
1- Try to fix the noise in the array of coordinates 2- Take off the function that create an coordinate between two points and try to fix the problem of the line path disappear.
Here is the 2 important functions:
this function moves the ship
private function mover():void
{
if (caminhoCoords[0]!=null) // caminhoCoords is the array that contain the path
{
var angulo:Number = Math.atan2(this.y - caminhoCoords[0][1], this.x - caminhoCoords[0][0]);
this.rotation = angulo / (Math.PI / 180);
this.x = this.x - velocidade * (Math.cos(angulo));
this.y = this.y - velocidade * (Math.sin(angulo));
var testex:Number = Math.abs(this.x - caminhoCoords[0][0]); //test to see the distance between the ship and the position in the array
var testey:Number = Math.abs(this.y - caminhoCoords[0][1]);
if (testey<=velocidade+2 && testex<=velocidade+2) // if is velocidade+2 close then go to the next coordnate
{
caminhoCoords.shift();
}
}
}
This function draw the line:
private function desenhaCaminho():void //draw the black Path
{
if(caminhoCoords.length>=1)
{
caminho.graphics.clear();
caminho.graphics.lineStyle(1, 0x000000, 1,true);
caminho.graphics.moveTo(caminhoCoords[0][0],caminhoCoords[0][1]);
for (var i:int = 1; i < caminhoCoords.length; i++)
{
caminho.graphics.lineTo(caminhoCoords[i][0], caminhoCoords[i][1]);
}
}else
{
caminho.graphics.clear();
}
}
Every time the ship arrive in one coordinate is take that coordinate off the array and redraw the array.
Is there a better way of doing that?
I believe if you set your registration point of the plane to the centre and use .snapto(path), it will improve the action.
Judging from just the look of the stuttering, I would guess you need to smooth out the "line" a fair bit. It's probably picking up a lot of noise in the line, which is then translated into the rotation of the plane. Either smooth out the rotation/position of the plane, or the line itself.
I'm trying to solve Kepler's Equation as a step towards finding the true anomaly of an orbiting body given time. It turns out though, that Kepler's equation is difficult to solve, and the wikipedia page describes the process using calculus. Well, I don't know calculus, but I understand that solving the equation involves an infinite number of sets which produce closer and closer approximations to the correct answer.
I can't see from looking at the math how to do this computationally, so I was hoping someone with a better maths background could help me out. How can I solve this beast computationally?
FWIW, I'm using F# -- and I can calculate the other elements necessary for this equation, it's just this part I'm having trouble with.
I'm also open to methods which approximate the true anomaly given time, periapsis distance, and eccentricity
This paper:
A Practical Method for Solving the Kepler Equation http://murison.alpheratz.net/dynamics/twobody/KeplerIterations_summary.pdf
shows how to solve Kepler's equation using an iterative computing method. It should be fairly straightforward to translate it to the language of your choice.
You might also find this interesting. It's an ocaml program, part of which claims to contain a Kepler Equation solver. Since F# is in the ML family of languages (as is ocaml), this might provide a good starting point.
wanted to drop a reply in here in case this page gets found by anyone else looking for similar materials.
The following was written as an "expression" in Adobe's After Effects software, so it's javascriptish, although I have a Python version for a different app (cinema 4d). The idea is the same: execute Newton's method iteratively until some arbitrary precision is reached.
Please note that I'm not posting this code as exemplary or meaningfully efficient in any way, just posting code we produced on a deadline to accomplish a specific task (namely, move a planet around a focus according to Kepler's laws, and do so accurately). We don't write code for a living, and so we're also not posting this for critique. Quick & dirty is what meets deadlines.
In After Effects, any "expression" code is executed once - for every single frame in the animation. This restricts what one can do when implementing many algorithms, due to the inability to address global data easily (other algorithms for Keplerian motion use interatively updated velocity vectors, an approach we couldn't use). The result the code leaves behind is the [x,y] position of the object at that instant in time (internally, this is the frame number), and the code is intended to be attached to the position element of an object layer on the timeline.
This code evolved out of material found at http://www.jgiesen.de/kepler/kepler.html, and is offered here for the next guy.
pi = Math.PI;
function EccAnom(ec,am,dp,_maxiter) {
// ec=eccentricity, am=mean anomaly,
// dp=number of decimal places
pi=Math.PI;
i=0;
delta=Math.pow(10,-dp);
var E, F;
// some attempt to optimize prediction
if (ec<0.8) {
E=am;
} else {
E= am + Math.sin(am);
}
F = E - ec*Math.sin(E) - am;
while ((Math.abs(F)>delta) && (i<_maxiter)) {
E = E - F/(1.0-(ec* Math.cos(E) ));
F = E - ec * Math.sin(E) - am;
i = i + 1;
}
return Math.round(E*Math.pow(10,dp))/Math.pow(10,dp);
}
function TrueAnom(ec,E,dp) {
S=Math.sin(E);
C=Math.cos(E);
fak=Math.sqrt(1.0-ec^2);
phi = 2.0 * Math.atan(Math.sqrt((1.0+ec)/(1.0-ec))*Math.tan(E/2.0));
return Math.round(phi*Math.pow(10,dp))/Math.pow(10,dp);
}
function MeanAnom(time,_period) {
curr_frame = timeToFrames(time);
if (curr_frame <= _period) {
frames_done = curr_frame;
if (frames_done < 1) frames_done = 1;
} else {
frames_done = curr_frame % _period;
}
_fractime = (frames_done * 1.0 ) / _period;
mean_temp = (2.0*Math.PI) * (-1.0 * _fractime);
return mean_temp;
}
//==============================
// a=semimajor axis, ec=eccentricity, E=eccentric anomaly
// delta = delta digits to exit, period = per., in frames
//----------------------------------------------------------
_eccen = 0.9;
_delta = 14;
_maxiter = 1000;
_period = 300;
_semi_a = 70.0;
_semi_b = _semi_a * Math.sqrt(1.0-_eccen^2);
_meananom = MeanAnom(time,_period);
_eccentricanomaly = EccAnom(_eccen,_meananom,_delta,_maxiter);
_trueanomaly = TrueAnom(_eccen,_eccentricanomaly,_delta);
r = _semi_a * (1.0 - _eccen^2) / (1.0 + (_eccen*Math.cos(_trueanomaly)));
x = r * Math.cos(_trueanomaly);
y = r * Math.sin(_trueanomaly);
_foc=_semi_a*_eccen;
[1460+x+_foc,540+y];
You could check this out, implemented in C# by Carl Johansen
Represents a body in elliptical orbit about a massive central body
Here is a comment from the code
True Anomaly in this context is the
angle between the body and the sun.
For elliptical orbits, it's a bit
tricky. The percentage of the period
completed is still a key input, but we
also need to apply Kepler's
equation (based on the eccentricity)
to ensure that we sweep out equal
areas in equal times. This
equation is transcendental (ie can't
be solved algebraically) so we
either have to use an approximating
equation or solve by a numeric method.
My implementation uses
Newton-Raphson iteration to get an
excellent approximate answer (usually
in 2 or 3 iterations).