How to make an object randomly spawn inside of the stage only - actionscript-3

My stage size is 640 x 1136
I want to spawn my objects randomly but only inside of the stage.
I used this
object.x = Math.random() * stage.stageHeight;
How can I make the x position spawn within the stage area?

You would want a "random in range" function like the one here
(included below).
However, if you are doing a game you may not be satisfied with the result of randomly spawning objects (e.g. objects piling up on each other, etc.) and want to exert more control. Lots of ways to be clever with that – like defining a set of regions or quadrants, picking one of those randomly and then generating random coordinates within that region, or having an array of defined "good" points and randomly selected from it. Actual randomness is often less interesting than the idea or appearance of randomness.
public function randRange(minNum:Number, maxNum:Number):Number {
return (Math.floor(Math.random() * (maxNum - minNum + 1)) + minNum);
}

TOMATO answer is the same as what you actually do so it's not really helpful. What you need to do is account for the object size. If you have an object that is at maximum 100 pixel wide then:
var size:Number = object.width;
object.x = size + Math.random() * (stage.stageWidth - size * 2);
This make sure the object spawn on the x axis inside the stage x axis. Same operation needs to be repeated for the y axis of course.

Related

LWJGL Picking - Select Certain Block When Hovering ( gluUnProject() )

This video will show my current situation, and I currently can't find any answers to it online.
https://www.youtube.com/watch?v=O8Mh-1Emoc8&feature=youtu.be
My Code:
public Vector3D pickBlock() {
glDisable(GL_TEXTURE);
IntBuffer viewport = BufferUtils.createIntBuffer(16);
FloatBuffer modelview = BufferUtils.createFloatBuffer(16);
FloatBuffer projection = BufferUtils.createFloatBuffer(16);
FloatBuffer winZ = BufferUtils.createFloatBuffer(1);
float winX, winY;
FloatBuffer position = BufferUtils.createFloatBuffer(3);
glGetFloat(GL_MODELVIEW_MATRIX, modelview);
glGetFloat(GL_PROJECTION_MATRIX, projection);
glGetInteger(GL_VIEWPORT, viewport);
winX = (float)Display.getWidth() / 2;
winY = (float)viewport.get(3) - (float)Display.getHeight() / 2;
glReadPixels(Display.getWidth() / 2, (int)winY, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, winZ);
gluUnProject(winX, winY, winZ.get(), modelview, projection, viewport, position);
glEnable(GL_TEXTURE);
return new Vector3D(position.get(0) / 2 + 0.5f, position.get(1) / 2 + 0.5f, position.get(2) / 2 + 0.5f);
}
It returns "/ 2 + 0.5f" because that is needed because of the offsets I have for the blocks (if I removed the 0.5f, the offset would be in the center instead of the corner)
I seams to me that the error, based on the video, comes from when you are facing in the positive z direction (or whatever your back direction is). My guess is that you aren't taking the facing direction into account as I see in your code that you are just adding a constant 0.5F to the position of your cursor.
Therfore, when you are facing backwards, it adds 0.5 which makes it be behind the wall (since back is negative Z). one simple check would be weather the Z component of your forward vector is positive or negative, and deciding the factor added to the cursor based on that, then doing the same for the X.
Depending on how you implemented your camera (IE: if you used Euler angles (rx, ry, rz) or if you used Quaternions / forward vectors), the way you would do that check would vary, feel free to ask me for examples based on your system if you need.
hope this helped!
PS: if you're using angles, you can either check for the range of the y-axis rotation value and determine which direction you are facing and thus weather to add or subtract, OR you can calculate the forward vector based on your angles, and then check the for sign of the component.

In Starling, how do you transform Filters to match the target Sprite's rotation & position?

Let's say your Starling display-list is as follows:
Stage
|___MainApp
|______Canvas (filter's target)
Then, you decide your MainApp should be rotated 90 degrees and offset a bit:
mainApp.rotation = Math.PI * 0.5;
mainApp.x = stage.stageWidth;
But all of a sudden, the filter keeps on applying itself to the target (canvas) in the angle it was originally (as if the MainApp was still at 0 degrees).
(notice in the GIF how the Blur's strong horizontal value continues to only apply horizontally although the parent object turned 90 degrees).
What would need to be changed to apply the filter to the target object before it gets it's parents transform? That way (I'm assuming) the filter's result would get transformed by the parent objects.
Any guess as to how this could be done?
https://github.com/bigp/StarlingShaderIssue
(PS: the filter I'm actually using is custom-made, but this BlurFilter example shows the same issue I'm having with the custom one. If there's any patching-up to do in the shader code, at least it wouldn't necessarily have to be done on the built-in BlurFilter specifically).
I solved this myself with numerous trial and error attempts over the course of several hours.
Since I only needed the shader to run in either at 0 or 90 degrees (not actually tweened like the gif demo shown in the question), I created a shader with two specialized sets of AGAL instructions.
Without going in too much details, the rotated version basically requires a few extra instructions to flip the x and y fields in the vertex and fragment shader (either by moving them with mov or directly calculating the mul or div result into the x or y field).
For example, compare the 0 deg vertex shader...
_vertexShader = [
"m44 op, va0, vc0", // 4x4 matrix transform to output space
"mov posOriginal, va1", // pass texture positions to fragment program
"mul posScaled, va1, viewportScale", // pass displacement positions (scaled)
].join("\n");
... with the 90 deg vertex shader:
_vertexShader = [
"m44 op, va0, vc0", // 4x4 matrix transform to output space
"mov posOriginal, va1", // pass texture positions to fragment program
//Calculate the rotated vertex "displacement" UVs
"mov temp1, va1",
"mov temp2, va1",
"mul temp2.y, temp1.x, viewportScale.y", //Flip X to Y, and scale with viewport Y
"mul temp2.x, temp1.y, viewportScale.x", //Flip Y to X, and scale with viewport X
"sub temp2.y, 1.0, temp2.y", //Invert the UV for the Y axis.
"mov posScaled, temp2",
].join("\n");
You can ignore the special aliases in the AGAL example, they're essentially posOriginal = v0, posScaled = v1 variants and viewportScale = vc4constants, then I do a string-replace to change them back to their respective registers & fields ).
Just a human-readable trick I use to avoid going insane. \☻/
The part that I struggled with the most was calculating the correct scale to adjust the UV's scale (with proper detection to Stage / Viewport resize and render-texture size shifts).
Eventually, this is what I came up with in the AS3 code:
var pt:Texture = _passTexture,
dt:RenderTexture = _displacement.texture,
notReady:Boolean = pt == null,
star:Starling = Starling.current;
var finalScaleX:Number, viewRatioX:Number = star.viewPort.width / star.stage.stageWidth;
var finalScaleY:Number, viewRatioY:Number = star.viewPort.height / star.stage.stageHeight;
if (notReady) {
finalScaleX = finalScaleY = 1.0;
} else if (isRotated) {
//NOTE: Notice how the native width is divided with height, instead of same side. Weird, but it works!
finalScaleY = pt.nativeWidth / dt.nativeHeight / _imageRatio / paramScaleX / viewRatioX; //Eureka!
finalScaleX = pt.nativeHeight / dt.nativeWidth / _imageRatio / paramScaleY / viewRatioY; //Eureka x2!
} else {
finalScaleX = pt.nativeWidth / dt.nativeWidth / _imageRatio / viewRatioX / paramScaleX;
finalScaleY = pt.nativeHeight / dt.nativeHeight / _imageRatio / viewRatioY / paramScaleY;
}
Hopefully these extracted pieces of code can be helpful to others with similar shader issues.
Good luck!

AS3 - How can multiple objects that appear randomly NEVER touch each other?

I have multiple objects that appear randomly on stage, but i want them to never touch each other when they appear.
object1.x = Math.random() * stage.stageWidth;
object1.y = Math.random() * stage.stageHeight;
object2.x = Math.random() * stage.stageWidth;
object2.y = Math.random() * stage.stageHeight;
object3.x = Math.random() * stage.stageWidth;
object3.y = Math.random() * stage.stageHeight;
etc...
And also how can i make them appear inside a box, instead of the stage.
I have multiple objects that appear randomly on stage, but i want them
to never touch each other when they appear
They obviously can't appear at random then.
A naive but quick to code solution is to use bounding box collision before actually placing the element using:
// http://stackoverflow.com/questions/2752349/fast-rectangle-to-rectangle-intersection
function rectIntersection(r1,r2) {
return !(r2.left > r1.right ||
r2.right < r1.left ||
r2.top > r1.bottom ||
r2.bottom < r1.top);
}
If there is indeed a collision you can re-run the random placement of that particular element until there is not any collision.
This method is naive because you need to run the collision detection for all elements on your screen each time you are attempting to do a random placement. If it fails (meaning there is a collision), then you need to run it again until there is not.
Keep in mind that you can also pre-calculate the placements instead of checking on animation runtime (if it's an animation).
For the second part of you question.
And also how can i make them appear inside a box, instead of the
stage.
Instead of using the stageWidth as a placement variable, you can use a function that returns a random integer within a range.
The ranges provided would be:
top-left/top-right for width
bottom-left/bottom-right for height
..of the box you want to constraint your elements in.
The function would return a random integer within those ranges and your boxes would always fall within that box.
Here's a code snippet to get you started:
function getRandomInt(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}

Gravity trajectory with already known destination

I have been spending several days trying to solve this problem and I am about to go mad. Your help would be very much appreciated.
I am using a 2D stage in libgdx. I want to move actors (or sprite) to this stage with a "gravity" display effect: for example for actor1, his initial coordinates are (0, 0), destination coordinates would be (100, 50), and I want to move this actor to this destination with a gravity trajectory effect. Then I want to use the same gravity for actor2 moving from (0, 0) to (25, 75), then actor3 from (0, 0) to (200, 75) etc.
I managed to apply a gravity trajectory to any actor based on this well known loop:
setX(getX() + velocity.x);
setY(getY() + velocity.y);
velocity.y += getGravity().y * delta;
So tweaking the gravity value would modify the trajectory. It works fine.
Now, as I said earlier I want to give every actors a unique trajectory given their predetermined destination.
So I have tried to find a formula to determine the x and y for each actor at every frame of their trajectory
I am using the following static parameters:
gravity.y : same for all actors
delay : the amount of frames during which each actor moves between his initial coordinates and his destination coordinates. Same value for all actors too
First I calculate the velocity with this SUPER UGLY formula that I am absolutely not proud of:
velocity = new Vector2 ( (destinationx - b.getX() )/time, initdisty/time + ( Math.sqrt(delta*1000)*time / ( 500/Math.abs(gravity) ) ));
where delta = Gdx.graphics.getDeltaTime();
Then I apply this velocity each frame to calculate the x and y of each actor:
public void act(float delta){
for (int i=0; i<delay; i++) {
setX(getX() + velocity.x);
setY(getY() + velocity.y);
velocity.y += gravity.y * delta;
}
}
It KIND OF work, but of course, this can not be a long term solid solution. Calculating the x and y for each frame for each actor (there can be 5-6 actors moving at the same time) doesn't look good at all.
The main problem is that the trajectories are good on computer with consistent 60FPS, they are okay on a tablet, but on a phone with limited memory and 30 < fps < 60, the trajectories become terribly wrong.
After reading several blog posts, it seems like I could avoid the multi device memory fps problems by removing the delta parameter from my formulas, but I haven't found how. And it still doesn't give me a strong long term solution to calculate the trajectory with predetermined destination coordinates.
Thanks for reading and for your time, please let me know if this is unclear I'll do my best to explain better.
Cause of the problem
Maintaining both position and velocity leads to discretization of the system resulting in quantization error. So you will experience inconsistent behavior by your current method when fps fluctuates.
Solution
All you need is to reduce your number of state variables to only two i.e. don't store current velocity. It is causing the errors in final position.
In stead use parametric form of the trajectory.
v = u + at
and
s = ut + ½at²
Implementation
Suppose you want to go from (sourceX, sourceY) to (targetX, targetY) in time 'totalTime'.
Calculate initial velocity.
Vector2 initialVelocity = new Vector2((targetX - sourceX) / totalTime,
(targetY - sourceY) / totalTime - gravity * totalTime / 2);
float currentTime = 0;
In each iteration, calculate position directly and keep track of currentTime.
public void act(float delta){
if (currentTime < totalTime) {
currentTime += delta;
setX((initialVelocity.x + gravity.x * currentTime / 2) * currentTime);
setY((initialVelocity.y + gravity.y * currentTime / 2) * currentTime);
} else {
setX(targetX);
setY(targetY);
}
}

Resize as a function of distance between mc's

I hope this hasn't been asked too much before. When I search I only get questions pertaining to rescaling to window size.
Now my question. I got one space ship firing a beam against another ship. I want the beam to show for some time and I want it to "bridge" the two ships. In other words, I want the beam to extend its width between the two ships.
I try to do this with a dot movie clip that is 1 pixel wide and high (and aligned left edge). I try to resize it with the following code: (target is the ship to be fire at and owner is the ship firing)
dist.vx = target.x - owner.x;
dist.vy = target.y - owner.y;
dist.dist = Math.sqrt(dist.vx*dist.vx + dist.vy*dist.vy);
width = dist.dist;
x = owner.x;
y = owner.y;
rotation = Math.atan2(target.y-y, target.x-x)*180/Math.PI;
This doesn't work as intended because 1) dot also gets alot bigger in the other dimension - how can I "turn off" this behavior? and 2) sometimes it seems to get way to wide - but only in certain angles...
Any suggestions on either solving the heigh/width scaling or on another way to achieve the same effect?
(I'm new to coding and flash.) Thanks!
By resizing a dot, you will have a rectangle...
You can dynamically create a sprite covering both ships and moveTo the hit point of one ship then lineTo the other ship... You do not need distance calculation at all. What you have to do is being careful on the placement of the sprite. So that you can calculate relative hitting points by simple math.
Suppose you have mc space contining mc ship1 and mc ship2, and hit point coords on ships are named hx, hy and you will use sprite s, calculation will be as follows.
// calculate hit points relative to mc space
var s1HX:int = ship1.x + ship1.hx,
s1HY:int = ship1.y + ship1.hy,
s2HX:int = ship2.x + ship2.hx,
s2HY:int = ship2.y + ship2.hy,
// sprite relative moveTo lineTo coords will be these.
mX: int, mY: int,
lX: int, lY: int;
// top left of sprite will be minimum of the hit coords.
s.x = (s1HX <= s2HX)? s1HX : s2HX;
s.y = (s1HY <= s2HY)? s1HY : s2HY;
// now we can get sprite relative moveTo lineTo coordinates:
mX = s1HX - s.x;
mY = s1HY - s.y;
lX = s2HX - s.x;
lY = s2HY - s.y;
The rest is implementation with using these with fancy line styles etc...
To create a new sprite:
var s:Sprite = new Sprite();
Adding / removing it to/from mc space:
space.addChild(s);
space.removeChild(s);
For graphics use the graphics object of sprite.
s.graphics
For setting line styles you can use:
s.graphics.lineStyle(...) ,
s.graphics.lineBitmapStyle(...),
s.graphics.lineGradientStyle(...)
Functions, please read the manual for usage.
After setting the line style to draw the line use:
s.graphics.moveTo(mX,mY);
s.graphics.lineTo(lX,lY);
For pulsating effects you have to do a little more complicated things such as using tween class which you can read about here: http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/fl/transitions/Tween.html
Note that:
Sprites are no complicated magic, they are like mc's but they do not have timelines etc.
Sprites try to scale when width or height change programmatically. So do not touch them, moveTo lineTo automatically sets the size of a sprite...