I wanted to make a shaking image in a imageView in Appcelerator TItanium
What I would like to do is to randomly change the top position and the left position of an imageView, to do like a shaking image.
OriginalImageLeft = image.left;
OriginalImageTop = image.top;
if (Math.random() > 0.5){
value = -1;
} else {
value = 1;
}
var viewAnimate = Ti.UI.createAnimation({
duration: 2000,
repeat:100,
left: OriginalImageLeft + (Math.random() * 20 * value),
top: OriginalImageTop + (Math.random() * 20 * value),
});
image.animate(viewAnimate)
But the code is not working, it calculates only one time the MathRandom() function so the shaking is not working.
Any idea ?
Create a function to calculate the position + doing the animation once. Then use the animation complete event to call that function again so it will calculate a new position + running the animation again. If you want to stop it just don't call the fuction again (e.g. add a counter/if-case around the function call).
A short info why your code won't work:
the OriginalImageLeft + (Math.random() * 20 * value) part is send to the native path once. So it will execute the Math.random() part in JS and send that number to the native App. The actual repeat part is executed with that calculated number.
Related
When using the draw_sprite code in game maker studio 2 gml the animation is set to a ridiculously fast speed. The draw event is as follows.
var cx = camera_get_view_x(view_camera[1]);
var cy = camera_get_view_y(view_camera[1]);
var cw = camera_get_view_width(view_camera[1]);
if (global.player_health >= 1)
{
draw_sprite(heartSmallSpr, -1, cx + (cw / 2) - 64, cy + 25)
}
if (global.player_health >= 2)
{
draw_sprite(heartSmallSpr, -1, cx + (cw / 2), cy + 25)
}
if (global.player_health >= 3)
{
draw_sprite(heartSmallSpr, -1, cx + (cw / 2) + 64, cy + 25)
}
The sprite has two frames set to 1 second but when the draw_sprite(); code is set to -1 or sprite_index it plays it is about 100 frames per second. I have tried setting the speed of the sprite but it does not do anything.
For now, I will just make a simple timer that subtracts 1 from a variable every frame and when it is equal to 0 I will make it change the sprite_index. This is probably the long way to do things but I am still open to any suggestions about the code above.
Just set the sprite index to 0, "sprite_index" is the image of which it needs to draw. i dont know why its running super fast if you set it to -1, but since there is no -1 image index, it should give you an error. Just set it to whatever you frame you want it to draw. If you are wanting it to play an animation, you cant use draw_sprite without setting up a variable to run through all the image index's.
If image_index shows you a heightened animation speed, it's either your room speed or you have somewhere in your game something manually changing either the image_speed or the image_index.
Maybe check if you have a left-over of some other code that you used to change those variables?
I am trying to rotate the camera around to X-axis of the scene.
At this point my code is like this:
rotation += 0.05;
camera.position.y = Math.sin(rotation) * 500;
camera.position.z = Math.cos(rotation) * 500;
This makes the camera move around but during the rotation something weird happens and either the camera flips, or it skips some part of the imaginary circle it's following.
You have only provided a snippet of code, so I have to make some assumptions about what you are doing.
This code:
rotation += 0.05;
camera.position.x = 0;
camera.position.y = Math.sin(rotation) * 500;
camera.position.z = Math.cos(rotation) * 500;
camera.lookAt( scene.position ); // the origin
will cause the "flipping" you refer to because the camera is trying to remain "right side up", and it will quickly change orientation as it passes over the "north pole."
If you offset the camera's x-coordinate like so,
camera.position.x = 200;
the camera behavior will appear more natural to you.
Three.js tries to keep the camera facing up. When you pass 0 along the z-axis, it'll "fix" the camera's rotation. You can just check and reset the camera's angle manually.
camera.lookAt( scene.position ); // the origin
if (camera.position.z < 0) {
camera.rotation.z = 0;
}
I'm sure this is not the best solution, but if anyone else runs across this question while playing with three.js (like I just did), it'll give one step further.
This works for me, I hope it helps.
Rotating around X-Axis:
var x_axis = new THREE.Vector3( 1, 0, 0 );
var quaternion = new THREE.Quaternion;
camera.position.applyQuaternion(quaternion.setFromAxisAngle(x_axis, rotation_speed));
camera.up.applyQuaternion(quaternion.setFromAxisAngle(x_axis, rotation_speed));
Rotating around Y-Axis:
var y_axis = new THREE.Vector3( 0, 1, 0 );
camera.position.applyQuaternion(quaternion.setFromAxisAngle(y_axis, angle));
Rotating around Z-Axis:
var z_axis = new THREE.Vector3( 0, 0, 1 );
camera.up.applyQuaternion(quaternion.setFromAxisAngle(z_axis, angle));
I wanted to move my camera to a new location while having the camera look at a particular object, and this is what I came up with [make sure to load tween.js]:
/**
* Helper to move camera
* #param loc Vec3 - where to move the camera; has x, y, z attrs
* #param lookAt Vec3 - where the camera should look; has x, y, z attrs
* #param duration int - duration of transition in ms
**/
function flyTo(loc, lookAt, duration) {
// Use initial camera quaternion as the slerp starting point
var startQuaternion = camera.quaternion.clone();
// Use dummy camera focused on target as the slerp ending point
var dummyCamera = camera.clone();
dummyCamera.position.set(loc.x, loc.y, loc.z);
// set the dummy camera quaternion
var rotObjectMatrix = new THREE.Matrix4();
rotObjectMatrix.makeRotationFromQuaternion(startQuaternion);
dummyCamera.quaternion.setFromRotationMatrix(rotObjectMatrix);
dummyCamera.up.set(camera)
console.log(camera.quaternion, dummyCamera.quaternion);
// create dummy controls to avoid mutating main controls
var dummyControls = new THREE.TrackballControls(dummyCamera);
dummyControls.target.set(loc.x, loc.y, loc.z);
dummyControls.update();
// Animate between the start and end quaternions
new TWEEN.Tween(camera.position)
.to(loc, duration)
.onUpdate(function(timestamp) {
// Slerp the camera quaternion for smooth transition.
// `timestamp` is the eased time value from the tween.
THREE.Quaternion.slerp(startQuaternion, dummyCamera.quaternion, camera.quaternion, timestamp);
camera.lookAt(lookAt);
})
.onComplete(function() {
controls.target = new THREE.Vector3(scene.children[1].position-0.001);
camera.lookAt(lookAt);
}).start();
}
Example usage:
var pos = {
x: -4.3,
y: 1.7,
z: 7.3,
};
var lookAt = scene.children[1].position;
flyTo(pos, lookAt, 60000);
Then in your update()/render() function, call TWEEN.update();
Full example
I am testing a background-loop animation where there will be to images both 1024x768 pixels in dimension, move leftwards, go offscreen, then jump back to the other side, and repeat.
I was able to do this by creating a constant speed for both background image to move (successful), and then I tried the following code to make it jump, but there was a problem:
if((background.center.x) < -511){
background.center = CGPointMake(1536, background.center.y);
}
if((background2.center.x) < -511){
background2.center = CGPointMake(1536, background2.center.y);
}
Somehow this is not working the way I expected. It leaves a few pixels of gap every time, and I am confused why. Does anyone know what's causing this to happen and how to fix it? Thanks!
It seems like you have forgotten to take into account the distance moved. The greater than expression might have been triggered because you moved to far. I guess your movement is larger than 1 pixel/frame.
I am not sure what kind of values that are feeding your movement but I think to take into account the movement you should do something like...
if ((background.center.x) < -511){
CGFloat dist = background.center.x + 512;
background.center = CGPointMake(1536+dist, background.center.y);
}
if ((background2.center.x) < -511){
CGFloat dist = background2.center.x + 512;
background2.center = CGPointMake(1536+dist, background2.center.y);
}
Rather than have the two images move (sort of) independently, I would keep track of a single backgroundPosition variable and then constantly update the position of both images relative to that one position. This should keep everything nice and tidy:
CGFloat const backgroundWidth = 1024;
CGFloat const backgroundSpeed = 2;
- (void)animateBackground {
backgroundPosition -= backgroundSpeed;
if (backgroundPosition < 0) {
backgroundPosition += backgroundWidth;
}
background1.center.x = backgroundPosition - backgroundWidth/2;
background2.center.x = backgroundPosition + backgroundWidth/2;
}
I'm new to actionscript. What I'm tryin to do is simulate traffic flow near a 2 lane intersection, following Wolfram's rule 184. To begin with, I'm trying to create a grid (8x8 of which the intersection is between the middle two rows and the middle two columns, like a plus sign) whose cells have the following attributes:
color = white;
car = false;
when clicked:
color = red;
car = true (a car is present);
So, after the user clicks cells to position the cars initially and presses the start button, the simulation will begin.
Here's my code so far (apologies for incorrect formatting):
class Main
{
private var parent:MovieClip;
public static function main(mc:MovieClip)
{
var app = new Main(mc);
}
public function Main(mc:MovieClip)
{
this.parent = mc;
//grid settings
var Cell:MovieClip = mc.createEmptyMovieClip("cell", mc.getNextHighestDepth());
var x:Number = 0;
var y:Number = 0;
var color:Number = 0xffffff;
var car:Boolean = false;
for (y = 0; y < 3 * Stage.height / 8; y += Stage.height / 8)
{
for (x = 3*Stage.width/8; x < 5*Stage.width/8; x+=Stage.width/8)
{
UI.drawRect(Cell, x, y, (Stage.width / 8) - 5, (Stage.height / 8) - 5, color, 100);
}
}
for (y = 3*Stage.height/8; y < 5 * Stage.height / 8; y += Stage.height / 8)
{
for (x = 0; x < Stage.width; x+=Stage.width/8)
{
UI.drawRect(Cell, x, y, (Stage.width / 8)-5, (Stage.height / 8)-5, color, 100);
}
}
for (y = 5*Stage.height/8; y < Stage.height; y += Stage.height / 8)
{
for (x = 3*Stage.width/8; x < 5*Stage.width/8; x+=Stage.width/8)
{
UI.drawRect(Cell, x, y, (Stage.width / 8)-5, (Stage.height / 8)-5, color, 100);
}
}
Cell.onMouseDown()
{
Cell.color = UI.RED;
Cell.car = true;
}
}
}
I know there's quite a few things gone wrong here. First of all, the cell color doesn't change on mouse down. Do i need to make movie clip for each cell in the for loops? I think it would be easier to make a grid of objects with given attributes, but i don't know how to do that. Would really appreciate if someone helps me out.
From what I can tell, issue with your current approach is that using drawRect() literally draws pixels on to the stage, which means you'll have no reference to those shapes in future frames. right now, you've got one MovieClip that has been drawn many times. What you need is a lot of MovieClips so you have a reference to each cell that you can update/edit every frame.
Your best bet is to do the following (I'll just provide pseudo because I'm a bit shaky on AS2 syntax):
A) Create an array to hold all of the Cells. Call it:
var Cells:Array = new Array();
B) During each step of the loops in your constructor, do 4 things.
1) Create a new MovieClip `var tempCell:MovieClip = new MovieClip();
2) Draw a rectangle on to each MovieClip: A tutorial for the graphics API in AS2 http://www.actionscript.org/resources/articles/727/1/Drawing-shapes-with-AS2/Page1.html
3) Add an event listenerto each MovieClip that points to a common event handler. This listener listens for mouse clicks on that MovieClip (or MOUSE_DOWN)
4) and use Cells.push(tempClip) to add that new MovieClip to your array so you now have one object that contains a reference to all of your cells.
C) Create an click event handler that redraws the cell that has been clicked. Try MouseEvent.target
You have another option to using the graphics API to draw rectangles, and that is to simply add and remove stock graphics from your Flash library. You'll have to draw these graphics in Flash and then 'Export for Actionscript' to call them up.
Hope this points you in the right direction!
J
I want to be able to make image move realistically with the accelerometer controlling it, like any labyrinth game. Below shows what I have so far but it seems very jittery and isnt realistic at all. The ball images seems to never be able to stop and does lots of jittery movements around everywhere.
- (void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration {
deviceTilt.x = 0.01 * deviceTilt.x + (1.0 - 0.01) * acceleration.x;
deviceTilt.y = 0.01 * deviceTilt.y + (1.0 - 0.01) * acceleration.y;
}
-(void)onTimer {
ballImage.center = CGPointMake(ballImage.center.x + (deviceTilt.x * 50), ballImage.center.y + (deviceTilt.y * 50));
if (ballImage.center.x > 279) {
ballImage.center = CGPointMake(279, ballImage.center.y);
}
if (ballImage.center.x < 42) {
ballImage.center = CGPointMake(42, ballImage.center.y);
}
if (ballImage.center.y > 419) {
ballImage.center = CGPointMake(ballImage.center.x, 419);
}
if (ballImage.center.y < 181) {
ballImage.center = CGPointMake(ballImage.center.x, 181);
}
Is there some reason why you can not use the smoothing filter provided in response to your previous question: How do you use a moving average to filter out accelerometer values in iPhone OS ?
You need to calculate the running average of the values. To do this you need to store the last n values in an array, and then push and pop values off the array when ever you read the accelerometer data. Here is some pseudocode:
const SIZE = 10;
float[] xVals = new float[SIZE];
float xAvg = 0;
function runAverage(float newX){
xAvg += newX/SIZE;
xVals.push(newX);
if(xVals.length > SIZE){
xAvg -= xVals.pop()/SIZE;
}
}
You need to do this for all three axis. Play around with the value of SIZE; the larger it is, the smoother the value, but the slower things will seem to respond. It really depends on how often you read the accelerometer value. If it is read 10 times per second, then SIZE = 10 might be too large.