Enemy manager class AS3 - windows

How can I make a enemy that moving across the line and throwing something to our player?
I want to do it with ActionScript 3, and I already have enemy_manager class
I already have this code for getting angle
var dx : Number = point1.x - point2.x;
var dy : Number = point1.y - point2.y;
var angleInRadians : Number = Math.atan2(dy, dx);
var andleInDegrees : Number = angleInRadians * (180 / Math.PI);

What I think that your asking is how to get decimal values to multiple by the projectiles speed to make the projectile go towards the player. This is the code to accomplish that.
var projectileSpeed:Number=30 (pixels a second)
var dx : Number = point2.x - point1.x;
var dy : Number = point2.y - point1.y;
var angleInRadians : Number = Math.atan2(dy, dx);
var angleInDegrees : Number = angleInRadians * (180 / Math.PI);
this.directionX = Math.cos(angleInRadians) * projectileSpeed; // Turns the angleInRadians into a decimal value
// For example ( 180 degrees would be 1 PI and the cos() and sin() would make directionX=-1 and directionY=0
this.directionY = Math.sin(angleInRadians) * projectileSpeed;
projectile.rotation = angleInDegrees; // makes it face where it is going ( if you event want this)
...
private function loop(e:Event):void { // loop to show the projectile move
// Updates the projectile's positions using directionX and directionY
projectile.x += directionX;
projectile.y += directionY;
}

Related

How can i split a list of points in all angle

I try to seperate a list of point into all basic angle
Here's my code
var increment =15/50;
var distance = 20;
var count = 0;
for( theta=0;theta <50; theta++) {
var newX = centerX +distance*Math.cos(theta*2*Math.PI*increment);
var newY = centerY +distance*Math.sin(theta*2*Math.PI*increment);
cxt.fillText("o",newX, newY);
count++;
if(count%5===0){
distance=distance+20;
}
}
Output:
I try to modify the increment many times but either they didn't make into straght lines or all the points turn into a mess
What is the exact increment number or function for this?
Problem 1
No need for count - it is being incremented in exactly the same fashion as theta:
var increment =15/50;
var distance = 20;
for( theta=0;theta <50; theta++) {
var newX = centerX +distance*Math.cos(theta*2*Math.PI*increment);
var newY = centerY +distance*Math.sin(theta*2*Math.PI*increment);
cxt.fillText("o",newX, newY);
if(theta%5===0){ // just use theta here
distance=distance+20;
}
}
Problem 2
The if statement increments distance once every 5 points, which means each "ring" only contains 5 points, whereas they should have as many points as basic angles. The logic should therefore be:
if (theta % 16 === 0) { // there are 16 "basic angles"
distance += 20;
}
Problem 3
1 is not an integer multiple of the fractional increment 15/50, so the second "ring" of points will not line up with the first - there will be an angular offset of 2*PI/5 between consecutive rings.
It is more efficient to separate the single loop into two nested loops, as suggested by Damien. The outer loop should increment the angle as the trigonometric functions are expensive.
var num_basic_angles = 16; // number of basic angles
var separation = 20; // distance between each point
var num_points; // number of points per angle
for (var angle = 0; angle < num_basic_angles; angle++) {
var theta = 2*Math.PI*angle/num_basic_angles;
var cos_t = Math.cos(theta);
var sin_t = Math.sin(theta);
for (var point = 0; point < num_points; point++) {
var x = centerX + distance * point * cos_t;
var y = centerY + distance * point * sin_t;
cxt.fillText("o",x,y);
}
}
If you really want to do things in a single loop, use theta = Math.floor(i / num_basic_angles), point = i % num_basic_angles, where i is the loop counter from 0 to num_basic_angles * num_points - 1.
Problem 4
The "basic angles" are not evenly distributed, so incrementing by a fixed value will not work.
No need to be too smart here, because these basic angles are arbitrarily defined anyway. Just store them in an array:
var basic_angles = [0,30,45,60,90,120,135,150,180,210,224,240,270,300,315,330];
var separation = 20; // distance between each point
var num_points; // number of points per angle
for (var angle = 0; angle < basic_angles.length; angle++) {
var theta = Math.PI/180.0*basic_angles[angle];
var cos_t = Math.cos(theta);
var sin_t = Math.sin(theta);
for (var point = 0; point < num_points; point++) {
var x = centerX + distance * point * cos_t;
var y = centerY + distance * point * sin_t;
cxt.fillText("o",x,y);
}
}

What's wrong with this nearest neighbor interpolation shader?

GPU.js converts a JS func into a shader. The following function knows this.thread.x as the current index being operated on, but it is ultimately working as a WebGL shader.
export default function(sprite, w, h, scale) {
var bufferWidth = w * 4;
var channel = this.thread.x % 4;
var thread = this.thread.x - channel;
var y = Math.round(this.thread.x / bufferWidth);
var x = (thread % bufferWidth) / 4;
var upscale = scale * 10;
var upscaleY = y * 10;
var upscaleX = x * 10;
var scaledY = Math.round(upscaleY / upscale);
var scaledX = Math.round(upscaleX / upscale);
var newIndex = scaledY * bufferWidth + scaledX * 4;
if (x <= w * scale && y <= h * scale) {
return sprite[newIndex + channel];
} else {
return 0;
}
}
This almost works, but rows become skipped completely, actually making the result shorter than it should, and lines where those missing rows travel up and down and left to right on the image as it's scaled over time.
You can see this effect here: https://enviziion.github.io/lost-worlds/
What's wrong with my algo? Ive tried tweaking rounding and all sorts of stuff but no luck.
Use Math.floor when computing y:
var y = Math.floor(thread / bufferWidth);
If you use Math.round then it will start rounding up to the next row halfway across the buffer, which will produce a weird discontinuity.
Mathematically, you should be able to get back thread.x from y * bufferWidth + x * 4, which works for floor but not round.

how to figure out cursive paths for an enemy to follow

The Problem
I am making a game where enemies appear at some point on the screen then follow a smooth curvy path and disappear at some point. I can make them follow a straight path but can't figure out the way to make them follow the paths depicted in the image.
Attempts
I started with parabolic curve and implemented them successfully. I just used the equation of parabola to calculate the coordinates gradually. I have no clue what is the equation for desired paths supposed to be.
What I want
I am not asking for the code.I just want someone to explain me the general technique.If you still want to show some code then I don't have special preference for programming language for this particular question you can use C,Java or even pseudo-code.
First you need to represent each curve with a set of points over time, For example:
-At T(0) the object should be at (X0, Y0).
-At T(1) the object should be at (X1, Y1).
And the more points you have, the more smooth curve you will get.
Then you will use those set of points to generate two formulas-one for X, and another one for Y-, using any Interpolation method, like The La-grange's Interpolation Formula:
Note that you should replace 'y' with the time T, and replace 'x' with your X for X formula, and Y for Y formula.
I know you hoped for a simple equation, but unfortunately this is will take from you a huge effort to simplify each equation, and my advise DON'T do it unless it's worth it.
If you are seeking for a more simple equation to perform well in each frame in your game you should read about SPline method, In this method is about splitting your curve into a smaller segments, and make a simple equation for every segment, for example:
Linear Spline:
Every segment contains 2 points, this will draw a line between every two points.
The result will be some thing like this:
Or you could use quadratic spline, or cubic spline for more smooth curves, but it will slow your game performance. You can read more about those methods here.
I think linear spline will be great for you with reasonable set of points for each curve.
Please change the question title to be more generic.
If you want to generate a spiral path you need.
Total time
How many full rotations
Largest radius
So, total time T_f = 5sec, rotations R_f = 2.5 * 2 * PI, the final distance from the start D_f = 200px
function SpiralEnemy(spawnX, spawnY, time) {
this.startX = spawnX;
this.startY = spawnY;
this.startTime = time;
// these will change and be used for rendering
this.x = this.startX;
this.y = this.startY;
this.done = false;
// constants we figured out above
var TFinal = 5.0;
var RFinal = -2.6 * 2 * Math.PI;
var RStart = -Math.PI / 2;
var DFinal = 100;
// the update function called every animation tick with the current time
this.update = function(t) {
var delta = t - this.startTime;
if(delta > TFinal) {
this.done = true;
return;
}
// find out how far along you are in the animation
var percent = delta / TFinal;
// what is your current angle of rotation (in radians)
var angle = RStart + RFinal * percent;
// how far from your start point should you be
var dist = DFinal * percent;
// update your coordinates
this.x = this.startX + Math.cos(angle) * dist;
this.y = this.startY + Math.sin(angle) * dist;
};
}
EDIT Here's a jsfiddle to mess with http://jsfiddle.net/pxb3824z/
EDIT 2 Here's a loop (instead of spiral) version http://jsfiddle.net/dpbLxuz7/
The loop code splits the animation into 2 parts the beginning half and the end half.
Beginning half : angle = Math.tan(T_percent) * 2 and dist = Speed + Speed * (1 - T_percent)
End half : angle = -Math.tan(1 - T_percent) * 2 and dist = **Speed + Speed * T_percent
T_percent is normalized to (0, 1.0) for both halfs.
function LoopEnemy(spawnX, spawnY, time) {
this.startX = spawnX;
this.startY = spawnY;
this.startTime = time;
// these will change and be used for rendering
this.x = this.startX;
this.y = this.startY;
this.last = time;
this.done = false;
// constants we figured out above
var TFinal = 5.0;
var RFinal = -2 * Math.PI;
var RStart = 0;
var Speed = 50; // px per second
// the update function called every animation tick with the current time
this.update = function(t) {
var delta = t - this.startTime;
if(delta > TFinal) {
this.done = true;
return;
}
// find out how far along you are in the animation
var percent = delta / TFinal;
var localDelta = t - this.last;
// what is your current angle of rotation (in radians)
var angle = RStart;
var dist = Speed * localDelta;
if(percent <= 0.5) {
percent = percent / 0.5;
angle -= Math.tan(percent) * 2;
dist += dist * (1 - percent);
} else {
percent = (percent - 0.5) / 0.5;
angle -= -Math.tan(1 - percent) * 2;
dist += dist * percent;
}
// update your coordinates
this.last = t;
this.x = this.x + Math.cos(angle) * dist;
this.y = this.y + Math.sin(angle) * dist;
};
}
Deriving the exact distance traveled and the height of the loop for this one is a bit more work. I arbitrarily chose a Speed of 50px / sec, which give a final x offset of ~+145 and a loop height of ~+114 the distance and height will scale from those values linearly (ex: Speed=25 will have final x at ~73 and loop height of ~57)
I don't understand how you give a curve. If you need a curve depicted on the picture, you can find a curve is given analytically and use it. If you have not any curves you can send me here: hedgehogues#bk.ru and I will help find you. I leave e-mail here because I don't get any messages about answers of users from stackoverflow. I don't know why.
If you have some curves in parametric view in [A, B], you can write a code like this:
struct
{
double x, y;
}SPoint;
coord = A;
step = 0.001
eps = 1e-6;
while (coord + step - eps < B)
{
SPoint p1, p2;
p1.x = x(coord);
p1.y = y(coord);
coord += step;
p2.x = x(coord);
p2.y = y(coord);
drawline(p1, p2);
}

Spawn bullet at barrel of gun

I'm making a top-down shooter and the player's gun is offset from the coordinates of the object. I'm using GameMaker:Studio, so the x and y coords are the center of the object. The offset of the image is set here:
bullet_offset_x = 30;
bullet_offset_y = 28;
And here is the code for shooting the gun:
var xpos = x + (bullet_offset_x * cos(degtorad(direction))) - (bullet_offset_y * sin(degtorad(direction)));
var ypos = y + (bullet_offset_x * sin(degtorad(direction))) + (bullet_offset_y * cos(degtorad(direction)));
var flash = instance_create(xpos, ypos, obj_flash);
with (flash){
direction = other.direction;
image_angle = other.direction;
}
I'm using the following formula for placing the muzzle flash:
x' = xcos(angle) - ysin(angle)
y' = xsin(angle) + ycos(angle)
Therefore:
xpos = x + x' and ypos = x + y'
However, when I run the code, the muzzle flash is correctly positioned when the angle is 0/360, but is off otherwise. Am I calculating this wrong?
IMAGES:
Correct
Incorrect
You need to use lengthdir_x and lengthdir_y functions, like:
var xpos = x + lengthdir_x(offset_distance, offset_angle + image_angle); // or direction
var ypos = y + lengthdir_y(offset_distance, offset_angle + image_angle);
var flash = instance_create(xpos, ypos, obj_flash);
flash.direction = direction;
flash.image_angle = direction;
little example here
To calculate the values ​​to be substituted into the formula, you can use this program.
Originally it was made in Russian, but I have translated it into English. My English is terrible, but I hope you will be able to understand it.
upd: Example with offsets:
var delta_x = 60;
var delta_y = -70;
var angle = point_direction(0, 0, delta_x, delta_y);
var distance = point_distance(0, 0, delta_x, delta_y);
var xpos = x + lengthdir_x(distance, image_angle + angle);
var ypos = y + lengthdir_y(distance, image_angle + angle);
var obj = instance_create(xpos, ypos, obj_flash);
obj.image_angle = image_angle;
When your sprite has an angle of 0, your muzzle flash still at an angle of invtan(28/30) in relation to the sprite. Therefore, the angle that the flash must be placed at in relation to the rotation of the sprite can be given by
flashRotation = spriteRotationDegrees - invtan(28/30) \\you can change this to radians
Once that is found, the positions can be found by:
var x_pos = sprite_x_pos + Math.Sqrt(28^2 + 30^2)cos(flashRotation);
var y_pos = sprite_y_pos + Math.Sqrt(28^2 + 30^2)sin(flashRotation);
The actual angle of rotation of the flash (which way it points) will be the same angle as the sprite.
You may need to play with the flashRotaion equation depending upon which way is counted as a positive rotation.

Eliminating off-of-ball roll in Trackball controls (with code/fix)

Is the intent of the TrackballControl to have a "border" outside the trackball that induces roll? I personally dislike it. It is a bit discontinuous, and does't really have a lot of purpose (imho).
If not, the function getMouseProjectionOnBall can be changed similar to the following. This does two things (not necessarily "correctly"):
Normalize the radius to fill both axis
Map z values outside of the ball (ie where z was previously 0)
I find this a lot more natural, personally.
Thoughts?
this.getMouseProjectionOnBall = function(clientX, clientY) {
var xnormalized = (clientX - _this.screen.width * 0.5 - _this.screen.offsetLeft) / (_this.screen.width / 2.0);
var ynormalized = (_this.screen.height * 0.5 + _this.screen.offsetTop - clientY) / (_this.screen.height / 2.0);
var mouseOnBall = new THREE.Vector3(
xnormalized,
ynormalized,
0.0
);
var length = mouseOnBall.length();
var ballRadius = 1.0; // As a fraction of the screen
if (length > ballRadius * 0.70710678118654752440) {
var temp = ballRadius / 1.41421356237309504880;
mouseOnBall.z = temp * temp / length;
// Remove old method.
// This Left z = 0, which meant rotation axis
// becomes z, which is a roll
//mouseOnBall.normalize();
} else {
mouseOnBall.z = Math.sqrt(1.0 - length * length);
}
_eye.copy(_this.object.position).sub(_this.target);
var projection = _this.object.up.clone().setLength(mouseOnBall.y);
projection.add(_this.object.up.clone().cross(_eye).setLength(mouseOnBall.x));
projection.add(_eye.setLength(mouseOnBall.z));
return projection;
};

Resources